From cace1c4618b6c6442b7dc973e935e7f3268e4aa7 Mon Sep 17 00:00:00 2001 From: Marc Fiuczynski Date: Tue, 9 Aug 2005 00:20:01 +0000 Subject: [PATCH] upgrade to fedora-2.6.12-1.1398.FC4 + vserver 2.0.rc7 --- CREDITS | 86 +- Documentation/BK-usage/00-INDEX | 51 - Documentation/BK-usage/bk-kernel-howto.txt | 283 - Documentation/BK-usage/bk-make-sum | 34 - Documentation/BK-usage/bksend | 36 - Documentation/BK-usage/bz64wrap | 41 - Documentation/BK-usage/cpcset | 36 - Documentation/BK-usage/cset-to-linus | 49 - Documentation/BK-usage/csets-to-patches | 44 - Documentation/BK-usage/gcapatch | 8 - Documentation/BK-usage/unbz64wrap | 25 - Documentation/DocBook/kernel-hacking.tmpl | 4 +- Documentation/DocBook/libata.tmpl | 160 +- Documentation/DocBook/tulip-user.tmpl | 325 - Documentation/DocBook/via-audio.tmpl | 595 - Documentation/DocBook/videobook.tmpl | 206 +- Documentation/README.moxa | 18 - Documentation/SubmittingDrivers | 7 +- Documentation/SubmittingPatches | 8 +- Documentation/cachetlb.txt | 17 +- Documentation/cciss.txt | 29 +- Documentation/cdrom/mcd | 4 - Documentation/devices.txt | 99 +- Documentation/filesystems/proc.txt | 40 +- Documentation/filesystems/umsdos.txt | 100 - Documentation/i2c/i2c-old-porting | 626 - Documentation/i2c/i2c-parport | 156 - Documentation/i2c/porting-clients | 6 +- Documentation/i386/zero-page.txt | 10 +- Documentation/ioctl-number.txt | 4 +- Documentation/kernel-parameters.txt | 142 +- Documentation/mkdev.cciss | 40 - Documentation/networking/ethertap.txt | 268 - Documentation/networking/pktgen.txt | 291 +- Documentation/pci.txt | 9 +- Documentation/power/pci.txt | 35 +- Documentation/power/swsusp.txt | 50 + Documentation/power/video.txt | 163 +- Documentation/scsi/ChangeLog | 2023 --- Documentation/scsi/qla2xxx.revision.notes | 457 - Documentation/scsi/scsi_mid_low_api.txt | 48 +- .../sound/alsa/ALSA-Configuration.txt | 411 +- .../alsa/DocBook/writing-an-alsa-driver.tmpl | 616 +- Documentation/sysctl/kernel.txt | 20 - Documentation/sysrq.txt | 35 +- Documentation/usb/error-codes.txt | 29 +- Documentation/usb/silverlink.txt | 78 - Documentation/vm/hugetlbpage.txt | 264 +- MAINTAINERS | 362 +- Makefile | 89 +- arch/alpha/Kconfig | 10 +- arch/alpha/defconfig | 1 - arch/alpha/kernel/core_marvel.c | 2 +- arch/alpha/kernel/entry.S | 21 +- arch/alpha/kernel/osf_sys.c | 44 +- arch/alpha/kernel/ptrace.c | 5 +- arch/alpha/kernel/setup.c | 18 +- arch/alpha/kernel/signal.c | 12 +- arch/alpha/kernel/smc37c669.c | 2 +- arch/alpha/kernel/smp.c | 54 - arch/alpha/kernel/sys_dp264.c | 2 +- arch/alpha/kernel/systbls.S | 7 +- arch/alpha/kernel/time.c | 2 +- arch/alpha/mm/init.c | 8 +- arch/alpha/mm/numa.c | 10 +- arch/arm/Kconfig | 402 +- arch/arm/Makefile | 6 +- arch/arm/boot/compressed/Makefile | 4 + arch/arm/boot/compressed/head-xscale.S | 26 +- arch/arm/boot/compressed/head.S | 105 +- arch/arm/common/Makefile | 2 + arch/arm/common/sa1111.c | 60 +- arch/arm/configs/a5k_defconfig | 522 - arch/arm/kernel/Makefile | 6 +- arch/arm/kernel/asm-offsets.c | 23 +- arch/arm/kernel/calls.S | 2 +- arch/arm/kernel/debug.S | 687 +- arch/arm/kernel/ecard.c | 218 +- arch/arm/kernel/entry-armv.S | 2307 +-- arch/arm/kernel/head.S | 377 +- arch/arm/kernel/irq.c | 140 +- arch/arm/kernel/process.c | 43 +- arch/arm/kernel/ptrace.c | 59 +- arch/arm/kernel/semaphore.c | 4 +- arch/arm/kernel/setup.c | 75 +- arch/arm/kernel/signal.c | 13 +- arch/arm/kernel/sys_arm.c | 31 +- arch/arm/kernel/time.c | 8 +- arch/arm/kernel/traps.c | 166 +- arch/arm/mach-clps7500/core.c | 11 +- arch/arm/mach-ebsa110/io.c | 87 +- arch/arm/mach-integrator/core.c | 8 +- arch/arm/mach-integrator/impd1.c | 15 +- arch/arm/mach-integrator/integrator_ap.c | 4 +- arch/arm/mach-integrator/integrator_cp.c | 27 +- arch/arm/mach-ixp4xx/prpmc1100-pci.c | 120 - arch/arm/mach-ixp4xx/prpmc1100-setup.c | 98 - arch/arm/mach-lh7a40x/arch-lpd7a40x.c | 2 - arch/arm/mach-omap/Makefile | 2 + arch/arm/mach-omap/board-generic.c | 1 - arch/arm/mach-omap/board-innovator.c | 103 +- arch/arm/mach-omap/board-osk.c | 72 +- arch/arm/mach-omap/board-perseus2.c | 84 +- arch/arm/mach-omap/dma.c | 55 +- arch/arm/mach-omap/gpio.c | 126 +- arch/arm/mach-pxa/Kconfig | 37 + arch/arm/mach-pxa/Makefile | 2 + arch/arm/mach-pxa/generic.c | 27 +- arch/arm/mach-pxa/idp.c | 160 +- arch/arm/mach-pxa/lubbock.c | 35 +- arch/arm/mach-pxa/pm.c | 72 +- arch/arm/mach-rpc/riscpc.c | 2 +- arch/arm/mach-s3c2410/Kconfig | 54 +- arch/arm/mach-s3c2410/Makefile | 4 + arch/arm/mach-s3c2410/mach-bast.c | 161 +- arch/arm/mach-s3c2410/mach-h1940.c | 16 +- arch/arm/mach-s3c2410/mach-vr1000.c | 127 +- arch/arm/mach-s3c2410/s3c2410.c | 30 +- arch/arm/mach-s3c2410/s3c2410.h | 23 +- arch/arm/mach-sa1100/Kconfig | 9 +- arch/arm/mach-sa1100/assabet.c | 8 +- arch/arm/mach-sa1100/badge4.c | 5 +- arch/arm/mach-sa1100/h3600.c | 2 +- arch/arm/mach-sa1100/shannon.c | 6 +- arch/arm/mach-shark/core.c | 2 - arch/arm/mach-versatile/core.c | 11 +- arch/arm/mm/Kconfig | 52 +- arch/arm/mm/consistent.c | 67 +- arch/arm/mm/copypage-v4mc.S | 80 - arch/arm/mm/copypage-xscale.S | 113 - arch/arm/mm/fault-armv.c | 4 +- arch/arm/mm/init.c | 42 +- arch/arm/mm/ioremap.c | 2 +- arch/arm/mm/minicache.c | 73 - arch/arm/mm/mm-armv.c | 101 +- arch/arm/mm/proc-sa1100.S | 44 +- arch/arm/mm/proc-xscale.S | 90 +- arch/arm/tools/mach-types | 100 +- arch/arm26/Kconfig | 9 +- arch/arm26/boot/compressed/ofw-shark.c | 258 - arch/arm26/kernel/calls.S | 5 + arch/arm26/kernel/init_task.c | 6 +- arch/arm26/kernel/irq.c | 2 +- arch/arm26/kernel/process.c | 106 +- arch/arm26/kernel/ptrace.c | 7 +- arch/arm26/kernel/setup.c | 7 +- arch/arm26/kernel/time-acorn.c | 69 - arch/arm26/lib/io-readsl-armv3.S | 78 - arch/arm26/lib/io-readsw-armv3.S | 107 - arch/arm26/lib/io-writesw-armv3.S | 127 - arch/arm26/machine/head.S | 111 - arch/arm26/machine/oldlatches.c | 72 - arch/arm26/machine/small_page.c | 191 - arch/arm26/mm/init.c | 10 +- arch/arm26/mm/mm-memc.c | 202 - arch/cris/Kconfig | 4 + arch/cris/arch-v10/drivers/Kconfig | 2 +- arch/cris/arch-v10/drivers/eeprom.c | 2 +- arch/cris/arch-v10/drivers/gpio.c | 2 +- arch/cris/arch-v10/kernel/fasttimer.c | 30 +- arch/cris/arch-v10/kernel/ptrace.c | 5 +- arch/cris/arch-v10/kernel/signal.c | 8 +- arch/cris/kernel/irq.c | 5 - arch/cris/kernel/setup.c | 2 - arch/h8300/Kconfig | 4 + arch/h8300/Makefile | 9 +- arch/h8300/kernel/process.c | 2 +- arch/h8300/kernel/ptrace.c | 5 +- arch/h8300/kernel/signal.c | 8 +- arch/h8300/kernel/syscalls.S | 15 + arch/i386/Kconfig | 139 +- arch/i386/Kconfig.debug | 17 +- arch/i386/Makefile | 21 +- arch/i386/boot/compressed/misc.c | 1 - arch/i386/boot/edd.S | 8 +- arch/i386/boot/setup.S | 8 +- arch/i386/boot/video.S | 18 +- arch/i386/defconfig | 2 - arch/i386/kernel/Makefile | 11 +- arch/i386/kernel/acpi/boot.c | 54 +- arch/i386/kernel/acpi/sleep.c | 12 +- arch/i386/kernel/acpi/wakeup.S | 4 +- arch/i386/kernel/apic.c | 34 +- arch/i386/kernel/apm.c | 37 +- arch/i386/kernel/asm-offsets.c | 7 +- arch/i386/kernel/cpu/common.c | 127 +- arch/i386/kernel/cpu/cpu.h | 1 - arch/i386/kernel/cpu/cpufreq/Makefile | 1 + arch/i386/kernel/cpu/cpufreq/gx-suspmod.c | 2 +- arch/i386/kernel/cpu/cpufreq/longhaul.c | 58 +- arch/i386/kernel/cpu/cpufreq/p4-clockmod.c | 2 +- arch/i386/kernel/cpu/cpufreq/powernow-k7.c | 34 +- arch/i386/kernel/cpu/cpufreq/powernow-k8.c | 138 +- arch/i386/kernel/cpu/cpufreq/powernow-k8.h | 24 +- .../kernel/cpu/cpufreq/speedstep-centrino.c | 160 +- arch/i386/kernel/cpu/cpufreq/speedstep-smi.c | 3 + arch/i386/kernel/cpu/intel.c | 66 +- arch/i386/kernel/cpu/mtrr/generic.c | 68 +- arch/i386/kernel/cpu/proc.c | 25 +- arch/i386/kernel/cpuid.c | 4 +- arch/i386/kernel/dmi_scan.c | 19 +- arch/i386/kernel/efi.c | 12 +- arch/i386/kernel/entry.S | 452 +- arch/i386/kernel/head.S | 12 +- arch/i386/kernel/i386_ksyms.c | 13 +- arch/i386/kernel/i387.c | 23 +- arch/i386/kernel/i8259.c | 23 +- arch/i386/kernel/io_apic.c | 27 +- arch/i386/kernel/irq.c | 5 +- arch/i386/kernel/mca.c | 21 +- arch/i386/kernel/microcode.c | 2 +- arch/i386/kernel/mpparse.c | 15 +- arch/i386/kernel/msr.c | 4 +- arch/i386/kernel/nmi.c | 25 +- arch/i386/kernel/numaq.c | 20 +- arch/i386/kernel/process.c | 90 +- arch/i386/kernel/ptrace.c | 183 +- arch/i386/kernel/reboot.c | 4 +- arch/i386/kernel/scx200.c | 62 +- arch/i386/kernel/setup.c | 167 +- arch/i386/kernel/signal.c | 65 +- arch/i386/kernel/smp.c | 6 +- arch/i386/kernel/smpboot.c | 87 +- arch/i386/kernel/srat.c | 94 +- arch/i386/kernel/syscall_table.S | 12 +- arch/i386/kernel/sysenter.c | 68 +- arch/i386/kernel/time_hpet.c | 59 +- arch/i386/kernel/timers/timer_tsc.c | 22 +- arch/i386/kernel/traps.c | 223 +- arch/i386/kernel/vm86.c | 41 +- arch/i386/kernel/vsyscall.lds.S | 3 +- arch/i386/lib/Makefile | 2 +- arch/i386/lib/delay.c | 2 +- arch/i386/lib/usercopy.c | 4 + arch/i386/mach-default/topology.c | 33 +- arch/i386/mach-visws/mpparse.c | 2 +- arch/i386/mach-voyager/voyager_basic.c | 2 - arch/i386/mach-voyager/voyager_smp.c | 61 +- arch/i386/mach-voyager/voyager_thread.c | 1 - arch/i386/math-emu/errors.c | 6 +- arch/i386/math-emu/fpu_aux.c | 2 +- arch/i386/math-emu/fpu_entry.c | 14 +- arch/i386/math-emu/fpu_proto.h | 2 - arch/i386/math-emu/fpu_system.h | 12 +- arch/i386/math-emu/get_address.c | 18 +- arch/i386/math-emu/load_store.c | 8 +- arch/i386/math-emu/reg_ld_str.c | 48 +- arch/i386/mm/discontig.c | 258 +- arch/i386/mm/fault.c | 17 +- arch/i386/mm/highmem.c | 8 +- arch/i386/mm/hugetlbpage.c | 35 +- arch/i386/mm/init.c | 82 +- arch/i386/mm/ioremap.c | 149 +- arch/i386/mm/mmap.c | 6 +- arch/i386/mm/pageattr.c | 57 +- arch/i386/mm/pgtable.c | 27 +- arch/i386/oprofile/op_model_p4.c | 9 +- arch/i386/pci/acpi.c | 17 +- arch/i386/pci/fixup.c | 26 +- arch/i386/pci/irq.c | 95 +- arch/i386/pci/mmconfig.c | 6 +- arch/i386/power/cpu.c | 3 +- arch/i386/power/swsusp.S | 36 +- arch/ia64/Kconfig | 93 +- arch/ia64/Makefile | 4 +- arch/ia64/configs/sn2_defconfig | 54 +- arch/ia64/defconfig | 51 +- arch/ia64/dig/Makefile | 5 - arch/ia64/dig/topology.c | 43 - arch/ia64/hp/common/sba_iommu.c | 136 +- arch/ia64/ia32/binfmt_elf32.c | 9 +- arch/ia64/ia32/ia32_entry.S | 10 +- arch/ia64/ia32/ia32_signal.c | 70 +- arch/ia64/ia32/ia32priv.h | 32 +- arch/ia64/ia32/sys_ia32.c | 115 +- arch/ia64/kernel/Makefile | 4 +- arch/ia64/kernel/acpi.c | 166 +- arch/ia64/kernel/asm-offsets.c | 28 +- arch/ia64/kernel/efi.c | 59 +- arch/ia64/kernel/entry.S | 238 +- arch/ia64/kernel/fsys.S | 11 +- arch/ia64/kernel/head.S | 299 +- arch/ia64/kernel/ia64_ksyms.c | 3 + arch/ia64/kernel/iosapic.c | 383 +- arch/ia64/kernel/irq.c | 1011 +- arch/ia64/kernel/irq_ia64.c | 50 +- arch/ia64/kernel/ivt.S | 30 +- arch/ia64/kernel/mca.c | 83 +- arch/ia64/kernel/module.c | 10 +- arch/ia64/kernel/perfmon.c | 295 +- arch/ia64/kernel/process.c | 86 +- arch/ia64/kernel/ptrace.c | 752 +- arch/ia64/kernel/sal.c | 2 +- arch/ia64/kernel/setup.c | 119 +- arch/ia64/kernel/signal.c | 118 +- arch/ia64/kernel/smp.c | 3 +- arch/ia64/kernel/smpboot.c | 319 +- arch/ia64/kernel/sys_ia64.c | 30 +- arch/ia64/kernel/time.c | 2 +- arch/ia64/kernel/traps.c | 105 +- arch/ia64/kernel/unwind.c | 34 +- arch/ia64/mm/contig.c | 10 +- arch/ia64/mm/discontig.c | 108 +- arch/ia64/mm/fault.c | 18 +- arch/ia64/mm/hugetlbpage.c | 96 +- arch/ia64/mm/init.c | 126 +- arch/ia64/mm/tlb.c | 3 +- arch/ia64/pci/pci.c | 350 +- .../sn/include/pci/pcibus_provider_defs.h | 43 - arch/ia64/sn/include/pci/pcidev.h | 54 - arch/ia64/sn/include/shub.h | 39 - arch/ia64/sn/include/shubio.h | 3476 ---- arch/ia64/sn/kernel/Makefile | 8 +- arch/ia64/sn/kernel/bte.c | 22 +- arch/ia64/sn/kernel/irq.c | 33 +- arch/ia64/sn/kernel/mca.c | 34 +- arch/ia64/sn/kernel/setup.c | 157 +- arch/ia64/sn/kernel/sn2/prominfo_proc.c | 14 +- arch/ia64/sn/kernel/sn2/ptc_deadlock.S | 22 +- arch/ia64/sn/kernel/sn2/sn2_smp.c | 91 +- arch/ia64/sn/kernel/sn2/timer.c | 5 +- arch/ia64/sn/kernel/sn2/timer_interrupt.c | 1 - arch/m68k/Kconfig | 8 +- arch/m68k/apollo/dn_debug.c | 22 - arch/m68k/atari/stdma.c | 10 +- arch/m68k/atari/stram.c | 5 +- arch/m68k/defconfig | 71 +- arch/m68k/kernel/ptrace.c | 5 +- arch/m68k/kernel/signal.c | 157 +- arch/m68k/sun3x/sun3x_ksyms.c | 13 - arch/m68knommu/Kconfig | 22 +- arch/m68knommu/kernel/process.c | 21 +- arch/m68knommu/kernel/ptrace.c | 5 +- .../platform/5206/ARNEWSH/crt0_ram.S | 213 - .../platform/5206e/MOTOROLA/crt0_ram.S | 178 - .../m68knommu/platform/5206e/eLITE/crt0_ram.S | 346 - .../platform/5249/MOTOROLA/crt0_ram.S | 230 - .../m68knommu/platform/5272/CANCam/crt0_ram.S | 154 - .../platform/5272/MOTOROLA/crt0_ram.S | 165 - .../m68knommu/platform/5272/NETtel/crt0_ram.S | 196 - .../m68knommu/platform/5272/SCALES/crt0_ram.S | 154 - .../m68knommu/platform/5272/senTec/crt0_ram.S | 159 - .../platform/527x/M5271EVB/crt0_ram.S | 166 - .../platform/527x/M5275EVB/crt0_ram.S | 166 - .../platform/528x/M5282EVB/crt0_ram.S | 171 - .../m68knommu/platform/528x/senTec/crt0_ram.S | 180 - .../platform/5307/ARNEWSH/crt0_ram.S | 167 - .../platform/5307/CLEOPATRA/crt0_ram.S | 183 - .../platform/5307/MOTOROLA/crt0_ram.S | 167 - arch/m68knommu/platform/5307/MP3/crt0_ram.S | 181 - .../m68knommu/platform/5307/NETtel/crt0_ram.S | 204 - .../platform/5407/CLEOPATRA/crt0_ram.S | 180 - .../platform/5407/MOTOROLA/crt0_ram.S | 160 - .../m68knommu/platform/68328/pilot/crt0_rom.S | 224 - .../platform/68360/uCquicc/crt0_ram.S | 408 - .../platform/68360/uCquicc/crt0_rom.S | 420 - .../platform/68EZ328/ucsimm/crt0_fixed.S | 109 - .../platform/68EZ328/ucsimm/crt0_himem.S | 1 - .../platform/68EZ328/ucsimm/crt0_ram.S | 167 - .../platform/68EZ328/ucsimm/crt0_rom.S | 1 - arch/m68knommu/platform/68VZ328/de2/Makefile | 12 - .../m68knommu/platform/68VZ328/de2/crt0_ram.S | 135 - .../platform/68VZ328/ucdimm/Makefile | 12 - .../platform/68VZ328/ucdimm/crt0_fixed.S | 109 - .../platform/68VZ328/ucdimm/crt0_himem.S | 1 - .../platform/68VZ328/ucdimm/crt0_ram.S | 171 - .../platform/68VZ328/ucdimm/crt0_rom.S | 1 - arch/mips/Kconfig | 97 +- arch/mips/Makefile | 30 +- arch/mips/au1000/common/power.c | 2 +- arch/mips/configs/atlas_defconfig | 593 +- arch/mips/configs/capcella_defconfig | 52 +- arch/mips/configs/cobalt_defconfig | 53 +- arch/mips/configs/db1000_defconfig | 40 +- arch/mips/configs/db1100_defconfig | 40 +- arch/mips/configs/db1500_defconfig | 45 +- arch/mips/configs/ddb5476_defconfig | 52 +- arch/mips/configs/ddb5477_defconfig | 51 +- arch/mips/configs/decstation_defconfig | 52 +- arch/mips/configs/e55_defconfig | 52 +- arch/mips/configs/ev64120_defconfig | 51 +- arch/mips/configs/ev96100_defconfig | 50 +- arch/mips/configs/ip22_defconfig | 62 +- arch/mips/configs/ip27_defconfig | 54 +- arch/mips/configs/ip32_defconfig | 58 +- arch/mips/configs/it8172_defconfig | 52 +- arch/mips/configs/ivr_defconfig | 51 +- arch/mips/configs/jaguar-atx_defconfig | 45 +- arch/mips/configs/jmr3927_defconfig | 52 +- arch/mips/configs/lasat200_defconfig | 52 +- arch/mips/configs/malta_defconfig | 608 +- arch/mips/configs/mpc30x_defconfig | 52 +- arch/mips/configs/ocelot_c_defconfig | 51 +- arch/mips/configs/ocelot_defconfig | 50 +- arch/mips/configs/osprey_defconfig | 50 +- arch/mips/configs/pb1100_defconfig | 43 +- arch/mips/configs/pb1500_defconfig | 43 +- arch/mips/configs/pb1550_defconfig | 41 +- arch/mips/configs/rm200_defconfig | 74 +- arch/mips/configs/sb1250-swarm_defconfig | 56 +- arch/mips/configs/sead_defconfig | 50 +- arch/mips/configs/tb0226_defconfig | 53 +- arch/mips/configs/tb0229_defconfig | 85 +- arch/mips/configs/workpad_defconfig | 52 +- arch/mips/configs/yosemite_defconfig | 49 +- arch/mips/ddb5xxx/ddb5074/irq.c | 1 - arch/mips/defconfig | 62 +- arch/mips/jmr3927/rbhma3100/irq.c | 55 +- arch/mips/kernel/Makefile | 8 +- arch/mips/kernel/irix5sys.h | 1029 -- arch/mips/kernel/irixelf.c | 60 +- arch/mips/kernel/irixsig.c | 100 +- arch/mips/kernel/irq.c | 2 +- arch/mips/kernel/linux32.c | 19 +- arch/mips/kernel/mips_ksyms.c | 7 +- arch/mips/kernel/process.c | 45 +- arch/mips/kernel/ptrace.c | 46 +- arch/mips/kernel/ptrace32.c | 7 +- arch/mips/kernel/reg.c | 69 - arch/mips/kernel/scall32-o32.S | 213 +- arch/mips/kernel/scall64-64.S | 12 +- arch/mips/kernel/scall64-n32.S | 4 +- arch/mips/kernel/scall64-o32.S | 75 +- arch/mips/kernel/semaphore.c | 3 +- arch/mips/kernel/setup.c | 27 +- arch/mips/kernel/signal.c | 152 +- arch/mips/kernel/signal32.c | 142 +- arch/mips/kernel/signal_n32.c | 51 +- arch/mips/kernel/smp.c | 24 +- arch/mips/kernel/syscall.c | 34 +- arch/mips/kernel/sysirix.c | 80 +- arch/mips/kernel/time.c | 3 +- arch/mips/kernel/traps.c | 38 +- arch/mips/mm/Makefile | 39 +- arch/mips/mm/init.c | 7 +- arch/mips/mm/pgtable.c | 1 + arch/mips/mm/sc-rm7k.c | 6 +- arch/mips/mm/tlb-sb1.c | 3 +- arch/mips/mm/tlb64-glue-r4k.S | 41 - arch/mips/mm/tlb64-glue-sb1.S | 66 - arch/mips/mm/tlbex32-mips32.S | 253 - arch/mips/mm/tlbex32-r3k.S | 194 - arch/mips/mm/tlbex32-r4k.S | 262 - arch/mips/momentum/ocelot_c/irq.c | 3 +- arch/mips/momentum/ocelot_g/gt-irq.c | 1 + arch/mips/pci/Makefile | 3 +- arch/mips/pci/fixup-au1000.c | 13 + arch/mips/pci/ops-msc.c | 8 +- arch/mips/pci/ops-titan.c | 46 +- arch/mips/pci/pci-vr41xx.c | 90 +- arch/mips/pci/pci-vr41xx.h | 69 +- arch/mips/pci/pci.c | 6 +- arch/mips/pmc-sierra/yosemite/irq-handler.S | 31 +- arch/mips/pmc-sierra/yosemite/irq.c | 26 +- arch/mips/pmc-sierra/yosemite/prom.c | 10 +- arch/mips/pmc-sierra/yosemite/setup.c | 108 +- arch/mips/pmc-sierra/yosemite/setup.h | 9 +- arch/mips/sgi-ip22/ip22-setup.c | 6 +- arch/mips/sgi-ip32/ip32-irq.c | 2 +- arch/mips/sibyte/sb1250/irq.c | 79 +- arch/mips/sibyte/sb1250/irq_handler.S | 2 +- arch/mips/tx4927/common/tx4927_irq.c | 4 +- .../toshiba_rbtx4927/toshiba_rbtx4927_irq.c | 4 +- arch/mips/vr4181/common/irq.c | 2 +- arch/mips/vr41xx/casio-e55/setup.c | 13 +- arch/mips/vr41xx/common/bcu.c | 26 +- arch/mips/vr41xx/common/cmu.c | 69 +- arch/mips/vr41xx/common/giu.c | 2 +- arch/mips/vr41xx/common/icu.c | 2 +- arch/mips/vr41xx/common/init.c | 44 +- arch/mips/vr41xx/common/ksyms.c | 33 - arch/mips/vr41xx/common/pmu.c | 56 +- arch/mips/vr41xx/common/rtc.c | 321 - arch/mips/vr41xx/common/serial.c | 178 - arch/mips/vr41xx/common/vrc4171.c | 106 - arch/mips/vr41xx/common/vrc4173.c | 2 +- arch/mips/vr41xx/ibm-workpad/setup.c | 13 +- arch/mips/vr41xx/tanbac-tb0226/setup.c | 17 +- arch/mips/vr41xx/tanbac-tb0229/Makefile | 2 - arch/mips/vr41xx/tanbac-tb0229/setup.c | 18 +- arch/mips/vr41xx/tanbac-tb0229/tb0219.c | 44 - arch/mips/vr41xx/victor-mpc30x/setup.c | 17 +- arch/mips/vr41xx/zao-capcella/setup.c | 18 +- arch/parisc/Kconfig | 38 +- arch/parisc/Makefile | 13 +- arch/parisc/configs/712_defconfig | 594 +- arch/parisc/configs/a500_defconfig | 203 +- arch/parisc/configs/b180_defconfig | 77 +- arch/parisc/configs/c3000_defconfig | 187 +- arch/parisc/configs/n4000_defconfig | 927 - arch/parisc/kernel/Makefile | 4 +- arch/parisc/kernel/cache.c | 39 +- arch/parisc/kernel/entry.S | 40 +- arch/parisc/kernel/firmware.c | 178 +- arch/parisc/kernel/hardware.c | 24 +- arch/parisc/kernel/head.S | 43 +- arch/parisc/kernel/init_task.c | 12 +- arch/parisc/kernel/irq.c | 800 +- arch/parisc/kernel/pacache.S | 1132 +- arch/parisc/kernel/pci-dma.c | 24 +- arch/parisc/kernel/perf.c | 57 +- arch/parisc/kernel/process.c | 10 +- arch/parisc/kernel/processor.c | 2 +- arch/parisc/kernel/ptrace.c | 52 +- arch/parisc/kernel/real2.S | 3 +- arch/parisc/kernel/setup.c | 22 +- arch/parisc/kernel/signal.c | 43 +- arch/parisc/kernel/smp.c | 13 +- arch/parisc/kernel/sys_parisc.c | 25 +- arch/parisc/kernel/sys_parisc32.c | 93 +- arch/parisc/kernel/syscall_table.S | 19 +- arch/parisc/kernel/traps.c | 41 +- arch/parisc/kernel/vmlinux.lds.S | 11 +- arch/parisc/mm/init.c | 14 +- arch/ppc/4xx_io/serial_sicc.c | 117 +- arch/ppc/8260_io/Kconfig | 11 +- arch/ppc/8260_io/fcc_enet.c | 969 +- arch/ppc/8xx_io/cs4218_tdm.c | 28 +- arch/ppc/8xx_io/enet.c | 2 +- arch/ppc/Kconfig | 186 +- arch/ppc/Makefile | 39 +- arch/ppc/boot/common/misc-common.c | 16 +- arch/ppc/boot/include/serial.h | 4 +- arch/ppc/boot/simple/Makefile | 34 +- arch/ppc/boot/simple/embed_config.c | 2 +- arch/ppc/boot/simple/gt64260_tty.c | 322 - arch/ppc/boot/simple/head.S | 7 +- arch/ppc/boot/simple/m8260_tty.c | 2 +- arch/ppc/boot/simple/misc-ev64260.S | 60 - arch/ppc/boot/simple/misc.c | 7 +- arch/ppc/boot/simple/mv64x60_tty.c | 360 + arch/ppc/configs/common_defconfig | 180 +- arch/ppc/configs/ev64260_defconfig | 444 +- arch/ppc/configs/ibmchrp_defconfig | 1 - arch/ppc/configs/pmac_defconfig | 364 +- arch/ppc/defconfig | 1330 -- arch/ppc/kernel/Makefile | 7 +- arch/ppc/kernel/align.c | 16 +- arch/ppc/kernel/asm-offsets.c | 5 + arch/ppc/kernel/cputable.c | 23 + arch/ppc/kernel/entry.S | 260 +- arch/ppc/kernel/head.S | 381 +- arch/ppc/kernel/head_44x.S | 229 +- arch/ppc/kernel/head_4xx.S | 184 +- arch/ppc/kernel/head_e500.S | 1019 -- arch/ppc/kernel/misc.S | 37 +- arch/ppc/kernel/ppc_ksyms.c | 6 +- arch/ppc/kernel/process.c | 11 - arch/ppc/kernel/ptrace.c | 45 +- arch/ppc/kernel/setup.c | 61 +- arch/ppc/kernel/signal.c | 120 +- arch/ppc/kernel/smp.c | 26 +- arch/ppc/kernel/syscalls.c | 10 +- arch/ppc/kernel/time.c | 24 +- arch/ppc/kernel/traps.c | 118 +- arch/ppc/kernel/vmlinux.lds.S | 8 + arch/ppc/lib/string.S | 13 +- arch/ppc/mm/hashtable.S | 2 +- arch/ppc/mm/init.c | 38 +- arch/ppc/mm/mmu_decl.h | 2 +- arch/ppc/mm/pgtable.c | 36 +- arch/ppc/oprofile/init.c | 23 - arch/ppc/platforms/4xx/Kconfig | 16 +- arch/ppc/platforms/4xx/Makefile | 2 + arch/ppc/platforms/4xx/ebony.c | 131 +- arch/ppc/platforms/4xx/ebony.h | 14 +- arch/ppc/platforms/4xx/ibm405gp.c | 9 + arch/ppc/platforms/4xx/ibm405gpr.c | 9 + arch/ppc/platforms/4xx/ibm440gp.c | 13 + arch/ppc/platforms/4xx/ibm440gx.c | 17 + arch/ppc/platforms/4xx/ibmnp405h.h | 4 +- arch/ppc/platforms/4xx/ibmstbx25.c | 9 + arch/ppc/platforms/4xx/ocotea.c | 15 +- arch/ppc/platforms/4xx/ocotea.h | 18 +- arch/ppc/platforms/4xx/redwood6.c | 50 +- arch/ppc/platforms/4xx/sycamore.c | 52 +- arch/ppc/platforms/85xx/mpc8540.c | 97 - arch/ppc/platforms/85xx/mpc8555.c | 95 - arch/ppc/platforms/85xx/mpc8560.c | 74 - arch/ppc/platforms/Makefile | 14 +- arch/ppc/platforms/ev64260.c | 651 + arch/ppc/platforms/ev64260.h | 101 +- arch/ppc/platforms/ev64260_setup.c | 476 - arch/ppc/platforms/pmac_cpufreq.c | 297 +- arch/ppc/platforms/pmac_feature.c | 596 +- arch/ppc/platforms/pmac_pic.c | 2 +- arch/ppc/platforms/pmac_setup.c | 60 +- arch/ppc/platforms/pmac_sleep.S | 47 +- arch/ppc/platforms/pplus.c | 8 +- arch/ppc/platforms/prep_setup.c | 10 +- arch/ppc/platforms/sandpoint.c | 13 +- arch/ppc/platforms/sbc82xx.c | 2 +- arch/ppc/syslib/Makefile | 38 +- arch/ppc/syslib/gt64260_common.c | 1664 -- arch/ppc/syslib/gt64260_pic.c | 261 +- arch/ppc/syslib/m8260_pci.c | 194 - arch/ppc/syslib/m8260_pci.h | 76 - arch/ppc/syslib/m8260_setup.c | 28 +- arch/ppc/syslib/m8xx_setup.c | 2 +- arch/ppc/syslib/mpc10x_common.c | 35 + arch/ppc/syslib/mv64360_pic.c | 426 + arch/ppc/syslib/mv64x60.c | 2392 +++ arch/ppc/syslib/open_pic.c | 55 +- arch/ppc/syslib/ppc4xx_pic.c | 669 +- arch/ppc/syslib/ppc4xx_serial.c | 171 - arch/ppc/syslib/prom_init.c | 159 +- arch/ppc64/Kconfig | 73 +- arch/ppc64/Makefile | 44 +- arch/ppc64/boot/Makefile | 29 +- arch/ppc64/boot/main.c | 9 +- arch/ppc64/boot/no_initrd.c | 2 - arch/ppc64/boot/start.c | 654 - arch/ppc64/configs/iSeries_defconfig | 189 +- arch/ppc64/kernel/HvLpEvent.c | 8 + arch/ppc64/kernel/LparData.c | 193 +- arch/ppc64/kernel/Makefile | 11 +- arch/ppc64/kernel/align.c | 4 +- arch/ppc64/kernel/asm-offsets.c | 48 +- arch/ppc64/kernel/cputable.c | 3 + arch/ppc64/kernel/dma.c | 102 +- arch/ppc64/kernel/eeh.c | 63 +- arch/ppc64/kernel/entry.S | 30 +- arch/ppc64/kernel/head.S | 309 +- arch/ppc64/kernel/iSeries_pci.c | 11 +- arch/ppc64/kernel/iSeries_proc.c | 3 +- arch/ppc64/kernel/iSeries_setup.c | 211 +- arch/ppc64/kernel/idle.c | 32 +- arch/ppc64/kernel/ioctl32.c | 1 - arch/ppc64/kernel/iommu.c | 29 +- arch/ppc64/kernel/irq.c | 51 +- arch/ppc64/kernel/lparcfg.c | 32 +- arch/ppc64/kernel/misc.S | 99 +- arch/ppc64/kernel/module.c | 3 +- arch/ppc64/kernel/pSeries_lpar.c | 13 +- arch/ppc64/kernel/pSeries_nvram.c | 7 +- arch/ppc64/kernel/pSeries_pci.c | 38 +- arch/ppc64/kernel/pacaData.c | 37 +- arch/ppc64/kernel/pci.c | 215 +- arch/ppc64/kernel/pci.h | 7 +- arch/ppc64/kernel/pci_dma_direct.c | 89 - arch/ppc64/kernel/pci_dn.c | 57 +- arch/ppc64/kernel/pmac_smp.c | 35 +- arch/ppc64/kernel/ppc_ksyms.c | 76 +- arch/ppc64/kernel/process.c | 81 +- arch/ppc64/kernel/prom.c | 618 +- arch/ppc64/kernel/ptrace.c | 25 +- arch/ppc64/kernel/ptrace32.c | 5 +- arch/ppc64/kernel/ras.c | 122 +- arch/ppc64/kernel/rtas-proc.c | 13 +- arch/ppc64/kernel/rtas.c | 63 +- arch/ppc64/kernel/rtas_flash.c | 28 +- arch/ppc64/kernel/rtasd.c | 73 +- arch/ppc64/kernel/rtc.c | 41 +- arch/ppc64/kernel/scanlog.c | 6 +- arch/ppc64/kernel/setup.c | 214 +- arch/ppc64/kernel/signal.c | 40 +- arch/ppc64/kernel/signal32.c | 79 +- arch/ppc64/kernel/smp.c | 156 +- arch/ppc64/kernel/sys_ppc32.c | 101 +- arch/ppc64/kernel/syscalls.c | 76 +- arch/ppc64/kernel/sysfs.c | 128 +- arch/ppc64/kernel/time.c | 243 +- arch/ppc64/kernel/traps.c | 234 +- arch/ppc64/kernel/udbg.c | 5 +- arch/ppc64/kernel/vio.c | 73 +- arch/ppc64/kernel/viopath.c | 55 +- arch/ppc64/kernel/xics.c | 81 +- arch/ppc64/lib/Makefile | 2 +- arch/ppc64/mm/fault.c | 32 +- arch/ppc64/mm/hash_utils.c | 76 +- arch/ppc64/mm/hugetlbpage.c | 144 +- arch/ppc64/mm/init.c | 256 +- arch/ppc64/mm/numa.c | 211 +- arch/ppc64/mm/tlb.c | 11 +- arch/ppc64/oprofile/common.c | 47 +- arch/ppc64/oprofile/op_model_power4.c | 9 +- arch/ppc64/xmon/ppc-opc.c | 119 +- arch/ppc64/xmon/setjmp.c | 77 - arch/ppc64/xmon/xmon.c | 123 +- arch/s390/Kconfig | 18 +- arch/s390/Makefile | 2 +- arch/s390/appldata/appldata_base.c | 76 +- arch/s390/appldata/appldata_os.c | 4 +- arch/s390/defconfig | 38 +- arch/s390/kernel/Makefile | 2 +- arch/s390/kernel/binfmt_elf32.c | 12 +- arch/s390/kernel/compat_exec.c | 97 - arch/s390/kernel/compat_linux.c | 233 +- arch/s390/kernel/compat_signal.c | 30 +- arch/s390/kernel/compat_wrapper.S | 51 +- arch/s390/kernel/debug.c | 8 +- arch/s390/kernel/entry.S | 135 +- arch/s390/kernel/entry64.S | 128 +- arch/s390/kernel/module.c | 3 +- arch/s390/kernel/process.c | 6 +- arch/s390/kernel/ptrace.c | 86 +- arch/s390/kernel/s390_ksyms.c | 2 - arch/s390/kernel/setup.c | 412 +- arch/s390/kernel/signal.c | 10 +- arch/s390/kernel/smp.c | 146 +- arch/s390/kernel/sys_s390.c | 29 +- arch/s390/kernel/syscalls.S | 10 +- arch/s390/kernel/time.c | 65 +- arch/s390/kernel/traps.c | 2 +- arch/s390/mm/cmm.c | 21 +- arch/s390/mm/fault.c | 13 +- arch/s390/mm/init.c | 40 +- arch/sh/Kconfig | 36 +- arch/sh/Makefile | 7 + arch/sh/defconfig | 372 - arch/sh/drivers/dma/dma-api.c | 2 +- arch/sh/drivers/pci/pci-sh7751.c | 10 +- arch/sh/drivers/pci/pci.c | 2 +- arch/sh/kernel/cpu/init.c | 2 +- arch/sh/kernel/cpu/sh4/sq.c | 4 +- arch/sh/kernel/irq.c | 631 +- arch/sh/kernel/process.c | 10 +- arch/sh/kernel/ptrace.c | 16 +- arch/sh/kernel/setup.c | 1 - arch/sh/kernel/sh_ksyms.c | 12 +- arch/sh/kernel/smp.c | 7 +- arch/sh/kernel/time.c | 35 +- arch/sh/lib/delay.c | 2 +- arch/sh/mm/cache-sh4.c | 40 +- arch/sh/mm/hugetlbpage.c | 11 +- arch/sh/mm/init.c | 2 - arch/sh/mm/pg-sh4.c | 8 +- arch/sh64/defconfig | 667 - arch/sh64/lib/old-checksum.c | 17 - arch/sh64/mm/hugetlbpage.c | 12 +- arch/sparc/Kconfig | 6 + arch/sparc/kernel/ioport.c | 4 +- arch/sparc/kernel/irq.c | 2 +- arch/sparc/kernel/muldiv.c | 11 +- arch/sparc/kernel/process.c | 32 +- arch/sparc/kernel/ptrace.c | 58 +- arch/sparc/kernel/signal.c | 25 +- arch/sparc/kernel/smp.c | 5 +- arch/sparc/kernel/sparc_ksyms.c | 27 +- arch/sparc/kernel/sun4c_irq.c | 17 +- arch/sparc/kernel/sun4d_irq.c | 2 +- arch/sparc/kernel/sun4m_smp.c | 4 +- arch/sparc/kernel/sys_sparc.c | 7 +- arch/sparc/kernel/sys_sunos.c | 6 +- arch/sparc/kernel/time.c | 4 +- arch/sparc/kernel/traps.c | 8 +- arch/sparc/kernel/unaligned.c | 23 +- arch/sparc/mm/fault.c | 20 +- arch/sparc/mm/init.c | 5 - arch/sparc/mm/io-unit.c | 18 +- arch/sparc/mm/iommu.c | 46 +- arch/sparc/mm/sun4c.c | 10 +- arch/sparc/prom/memory.c | 28 +- arch/sparc64/Kconfig | 69 +- arch/sparc64/Makefile | 4 +- arch/sparc64/defconfig | 88 +- arch/sparc64/kernel/auxio.c | 4 +- arch/sparc64/kernel/binfmt_aout32.c | 26 +- arch/sparc64/kernel/entry.S | 224 +- arch/sparc64/kernel/head.S | 83 +- arch/sparc64/kernel/ioctl32.c | 1 - arch/sparc64/kernel/irq.c | 10 +- arch/sparc64/kernel/module.c | 101 +- arch/sparc64/kernel/pci.c | 23 +- arch/sparc64/kernel/pci_psycho.c | 12 +- arch/sparc64/kernel/pci_schizo.c | 118 +- arch/sparc64/kernel/process.c | 23 +- arch/sparc64/kernel/ptrace.c | 110 +- arch/sparc64/kernel/sbus.c | 41 +- arch/sparc64/kernel/setup.c | 39 +- arch/sparc64/kernel/signal.c | 2 +- arch/sparc64/kernel/signal32.c | 61 +- arch/sparc64/kernel/smp.c | 183 +- arch/sparc64/kernel/sparc64_ksyms.c | 48 +- arch/sparc64/kernel/sys_sparc.c | 27 +- arch/sparc64/kernel/sys_sparc32.c | 856 +- arch/sparc64/kernel/sys_sunos32.c | 14 +- arch/sparc64/kernel/systbls.S | 22 +- arch/sparc64/kernel/time.c | 48 +- arch/sparc64/kernel/traps.c | 63 +- arch/sparc64/kernel/unaligned.c | 6 +- arch/sparc64/lib/Makefile | 4 +- arch/sparc64/lib/VIS.h | 128 - arch/sparc64/lib/VISbzero.S | 274 - arch/sparc64/lib/VIScsum.S | 546 - arch/sparc64/lib/VIScsumcopy.S | 897 - arch/sparc64/lib/VIScsumcopyusr.S | 916 - arch/sparc64/lib/VISmemset.S | 240 - arch/sparc64/lib/debuglocks.c | 78 +- arch/sparc64/lib/find_bit.c | 5 +- arch/sparc64/lib/rwsem.c | 239 - arch/sparc64/mm/fault.c | 10 +- arch/sparc64/mm/hugetlbpage.c | 80 +- arch/sparc64/mm/init.c | 176 +- arch/sparc64/prom/memory.c | 10 +- arch/um/Kconfig | 46 +- arch/um/Kconfig_block | 105 - arch/um/Kconfig_char | 37 +- arch/um/Makefile | 163 +- arch/um/Makefile-i386 | 12 +- arch/um/Makefile-skas | 15 +- arch/um/defconfig | 84 +- arch/um/drivers/Makefile | 25 +- arch/um/drivers/chan_kern.c | 57 +- arch/um/drivers/chan_user.c | 65 +- arch/um/drivers/cow.h | 5 +- arch/um/drivers/cow_user.c | 9 +- arch/um/drivers/fd.c | 8 +- arch/um/drivers/line.c | 598 +- arch/um/drivers/mcast_user.c | 47 +- arch/um/drivers/mconsole_kern.c | 13 +- arch/um/drivers/mmapper_kern.c | 27 +- arch/um/drivers/net_kern.c | 50 +- arch/um/drivers/net_user.c | 8 +- arch/um/drivers/null.c | 9 +- arch/um/drivers/port_kern.c | 45 +- arch/um/drivers/port_user.c | 11 +- arch/um/drivers/pty.c | 15 +- arch/um/drivers/slip_proto.h | 93 - arch/um/drivers/slip_user.c | 156 +- arch/um/drivers/slirp_user.c | 104 +- arch/um/drivers/ssl.c | 148 +- arch/um/drivers/stdio_console.c | 166 +- arch/um/drivers/tty.c | 7 +- arch/um/drivers/ubd_kern.c | 719 +- arch/um/drivers/ubd_user.c | 304 +- arch/um/drivers/xterm.c | 24 +- arch/um/drivers/xterm_kern.c | 20 +- arch/um/include/2_5compat.h | 24 - arch/um/include/frame.h | 53 - arch/um/include/frame_user.h | 23 - arch/um/include/init.h | 34 +- arch/um/include/kern_util.h | 7 +- arch/um/include/line.h | 52 +- arch/um/include/mconsole.h | 2 +- arch/um/include/os.h | 3 +- arch/um/include/skas_ptrace.h | 15 +- arch/um/include/sysdep-i386/checksum.h | 51 +- arch/um/include/sysdep-i386/frame.h | 29 - arch/um/include/sysdep-i386/frame_kern.h | 69 - arch/um/include/sysdep-i386/frame_user.h | 91 - arch/um/include/sysdep-i386/sigcontext.h | 21 +- arch/um/include/sysdep-i386/syscalls.h | 54 +- arch/um/include/ubd_user.h | 59 +- arch/um/include/um_uaccess.h | 15 +- arch/um/include/umn.h | 27 - arch/um/include/user_util.h | 4 - arch/um/kernel/Makefile | 48 +- arch/um/kernel/checksum.c | 45 - arch/um/kernel/exec_kern.c | 11 +- arch/um/kernel/frame.c | 343 - arch/um/kernel/frame_kern.c | 148 - arch/um/kernel/helper.c | 58 +- arch/um/kernel/initrd_kern.c | 59 - arch/um/kernel/initrd_user.c | 44 - arch/um/kernel/irq.c | 17 +- arch/um/kernel/irq_user.c | 17 +- arch/um/kernel/ksyms.c | 5 +- arch/um/kernel/mem.c | 100 +- arch/um/kernel/mem_user.c | 6 +- arch/um/kernel/physmem.c | 8 +- arch/um/kernel/process.c | 104 +- arch/um/kernel/process_kern.c | 95 +- arch/um/kernel/ptrace.c | 181 +- arch/um/kernel/sigio_kern.c | 2 +- arch/um/kernel/sigio_user.c | 30 +- arch/um/kernel/signal_kern.c | 88 +- arch/um/kernel/skas/Makefile | 9 +- arch/um/kernel/skas/include/ptrace-skas.h | 57 - arch/um/kernel/skas/include/skas.h | 15 +- arch/um/kernel/skas/mem_user.c | 11 +- arch/um/kernel/skas/process.c | 224 +- arch/um/kernel/skas/process_kern.c | 21 +- arch/um/kernel/skas/sys-i386/Makefile | 12 - arch/um/kernel/skas/sys-i386/sigcontext.c | 114 - arch/um/kernel/skas/syscall_user.c | 15 +- arch/um/kernel/skas/trap_user.c | 33 +- arch/um/kernel/skas/uaccess.c | 56 +- arch/um/kernel/skas/util/Makefile | 3 + arch/um/kernel/skas/util/mk_ptregs.c | 51 - arch/um/kernel/smp.c | 14 +- arch/um/kernel/sys_call_table.c | 325 - arch/um/kernel/syscall_kern.c | 155 +- arch/um/kernel/sysrq.c | 60 +- arch/um/kernel/time.c | 3 + arch/um/kernel/time_kern.c | 45 +- arch/um/kernel/trap_kern.c | 70 +- arch/um/kernel/trap_user.c | 37 +- arch/um/kernel/tt/Makefile | 20 +- arch/um/kernel/tt/exec_user.c | 7 +- arch/um/kernel/tt/include/ptrace-tt.h | 26 - arch/um/kernel/tt/mem.c | 10 +- arch/um/kernel/tt/process_kern.c | 123 +- arch/um/kernel/tt/ptproxy/Makefile | 5 +- arch/um/kernel/tt/ptproxy/proxy.c | 10 +- arch/um/kernel/tt/ptproxy/sysdep.c | 22 +- arch/um/kernel/tt/ptproxy/wait.c | 8 +- arch/um/kernel/tt/sys-i386/Makefile | 12 - arch/um/kernel/tt/sys-i386/sigcontext.c | 60 - arch/um/kernel/tt/syscall_kern.c | 95 +- arch/um/kernel/tt/syscall_user.c | 48 +- arch/um/kernel/tt/tlb.c | 176 +- arch/um/kernel/tt/tracer.c | 103 +- arch/um/kernel/tt/trap_user.c | 17 +- arch/um/kernel/tt/uaccess.c | 12 +- arch/um/kernel/um_arch.c | 61 +- arch/um/kernel/umid.c | 19 +- arch/um/kernel/user_util.c | 17 +- arch/um/kernel/vmlinux.lds.S | 6 + arch/um/os-Linux/Makefile | 10 +- arch/um/os-Linux/file.c | 2 +- arch/um/os-Linux/process.c | 14 +- arch/um/os-Linux/user_syms.c | 5 + arch/um/sys-i386/Makefile | 23 +- arch/um/sys-i386/ldt.c | 19 +- arch/um/sys-i386/ptrace_user.c | 27 +- arch/um/sys-i386/util/Makefile | 7 +- arch/um/sys-i386/util/mk_sc.c | 75 +- arch/um/sys-i386/util/mk_thread_kern.c | 22 - arch/um/sys-i386/util/mk_thread_user.c | 30 - arch/um/util/Makefile | 7 +- arch/um/util/mk_constants_kern.c | 28 - arch/um/util/mk_constants_user.c | 28 - arch/um/util/mk_task_kern.c | 17 - arch/um/util/mk_task_user.c | 30 - arch/v850/Kconfig | 3 + arch/v850/kernel/fpga85e2c.c | 1 - arch/v850/kernel/ptrace.c | 3 +- arch/v850/kernel/setup.c | 1 - arch/x86_64/Kconfig | 122 +- arch/x86_64/Makefile | 2 + arch/x86_64/boot/setup.S | 8 +- arch/x86_64/defconfig | 235 +- arch/x86_64/ia32/fpu32.c | 2 +- arch/x86_64/ia32/ia32_aout.c | 24 +- arch/x86_64/ia32/ia32_binfmt.c | 16 +- arch/x86_64/ia32/ia32_signal.c | 76 +- arch/x86_64/ia32/ia32entry.S | 30 +- arch/x86_64/ia32/ptrace32.c | 4 +- arch/x86_64/ia32/sys_ia32.c | 235 +- arch/x86_64/ia32/syscall32.c | 85 +- arch/x86_64/kernel/Makefile | 6 +- arch/x86_64/kernel/acpi/sleep.c | 17 +- arch/x86_64/kernel/apic.c | 16 +- arch/x86_64/kernel/e820.c | 101 +- arch/x86_64/kernel/head.S | 123 +- arch/x86_64/kernel/head64.c | 20 +- arch/x86_64/kernel/i387.c | 15 +- arch/x86_64/kernel/i8259.c | 16 +- arch/x86_64/kernel/init_task.c | 2 - arch/x86_64/kernel/io_apic.c | 109 +- arch/x86_64/kernel/mce.c | 74 +- arch/x86_64/kernel/module.c | 95 +- arch/x86_64/kernel/mpparse.c | 38 +- arch/x86_64/kernel/msr.c | 4 +- arch/x86_64/kernel/pci-gart.c | 26 +- arch/x86_64/kernel/process.c | 67 +- arch/x86_64/kernel/ptrace.c | 214 +- arch/x86_64/kernel/reboot.c | 60 +- arch/x86_64/kernel/setup.c | 373 +- arch/x86_64/kernel/setup64.c | 46 +- arch/x86_64/kernel/signal.c | 91 +- arch/x86_64/kernel/smp.c | 42 +- arch/x86_64/kernel/smpboot.c | 784 +- arch/x86_64/kernel/sys_x86_64.c | 97 +- arch/x86_64/kernel/time.c | 110 +- arch/x86_64/kernel/traps.c | 272 +- arch/x86_64/kernel/vmlinux.lds.S | 3 +- arch/x86_64/kernel/vsyscall.S | 169 - arch/x86_64/kernel/warmreboot.S | 83 - arch/x86_64/kernel/x8664_ksyms.c | 19 +- arch/x86_64/lib/csum-wrappers.c | 6 +- arch/x86_64/lib/io.c | 16 +- arch/x86_64/lib/old-checksum.c | 33 - arch/x86_64/mm/Makefile | 1 + arch/x86_64/mm/fault.c | 151 +- arch/x86_64/mm/init.c | 175 +- arch/x86_64/mm/ioremap.c | 129 +- arch/x86_64/mm/numa.c | 51 +- arch/x86_64/mm/pageattr.c | 102 +- arch/x86_64/pci/mmconfig.c | 8 +- configs/kernel-2.6.10-i586-smp.config | 2739 --- configs/kernel-2.6.10-i586.config | 2745 --- configs/kernel-2.6.10-i686-smp.config | 2743 --- configs/kernel-2.6.10-i686.config | 2747 --- crypto/Kconfig | 62 +- crypto/Makefile | 1 + crypto/cipher.c | 121 +- crypto/deflate.c | 2 + crypto/scatterwalk.h | 22 +- crypto/sha1.c | 84 +- crypto/tcrypt.c | 18 +- crypto/tcrypt.h | 233 +- drivers/Kconfig | 2 + drivers/Makefile | 7 +- drivers/acpi/Kconfig | 80 +- drivers/acpi/ac.c | 18 +- drivers/acpi/asus_acpi.c | 22 +- drivers/acpi/battery.c | 2 +- drivers/acpi/bus.c | 8 +- drivers/acpi/button.c | 4 +- drivers/acpi/debug.c | 14 +- drivers/acpi/dispatcher/dsopcode.c | 15 +- drivers/acpi/ec.c | 141 +- drivers/acpi/event.c | 2 +- drivers/acpi/events/evxface.c | 6 +- drivers/acpi/executer/exoparg2.c | 12 +- drivers/acpi/fan.c | 33 +- drivers/acpi/namespace/nsalloc.c | 2 +- drivers/acpi/namespace/nsdumpdv.c | 2 +- drivers/acpi/namespace/nsload.c | 2 +- drivers/acpi/namespace/nswalk.c | 2 +- drivers/acpi/osl.c | 21 +- drivers/acpi/pci_irq.c | 146 +- drivers/acpi/pci_link.c | 80 +- drivers/acpi/pci_root.c | 4 +- drivers/acpi/power.c | 10 +- drivers/acpi/processor.c | 2644 --- drivers/acpi/scan.c | 331 +- drivers/acpi/sleep/main.c | 2 +- drivers/acpi/tables/tbconvrt.c | 10 +- drivers/acpi/thermal.c | 31 +- drivers/acpi/toshiba_acpi.c | 6 +- drivers/acpi/utilities/utglobal.c | 20 +- drivers/atm/ambassador.c | 117 +- drivers/atm/firestream.c | 14 +- drivers/atm/fore200e.c | 185 +- drivers/atm/fore200e.h | 2 +- drivers/atm/he.c | 96 +- drivers/atm/horizon.c | 34 +- drivers/atm/idt77105.c | 4 +- drivers/atm/idt77252.c | 18 +- drivers/atm/iphase.c | 59 +- drivers/atm/lanai.c | 45 +- drivers/atm/nicstarmac.h | 14 - drivers/atm/suni.c | 2 +- drivers/base/Kconfig | 2 +- drivers/base/bus.c | 10 +- drivers/base/class.c | 104 +- drivers/base/class_simple.c | 23 +- drivers/base/core.c | 8 +- drivers/base/cpu.c | 16 +- drivers/base/dmapool.c | 2 +- drivers/base/driver.c | 13 +- drivers/base/firmware_class.c | 3 + drivers/base/init.c | 3 +- drivers/base/interface.c | 51 - drivers/base/map.c | 21 +- drivers/base/node.c | 22 +- drivers/base/platform.c | 61 +- drivers/base/power/power.h | 17 +- drivers/base/power/resume.c | 11 +- drivers/base/power/runtime.c | 4 +- drivers/base/power/shutdown.c | 23 +- drivers/base/power/suspend.c | 27 +- drivers/base/sys.c | 42 +- drivers/block/DAC960.c | 138 +- drivers/block/Kconfig | 135 +- drivers/block/Makefile | 1 + drivers/block/as-iosched.c | 32 +- drivers/block/cciss.c | 248 +- drivers/block/cciss_scsi.c | 54 +- drivers/block/cfq-iosched.c | 41 +- drivers/block/cpqarray.c | 17 +- drivers/block/deadline-iosched.c | 14 +- drivers/block/elevator.c | 70 +- drivers/block/floppy.c | 39 +- drivers/block/genhd.c | 105 +- drivers/block/ida_cmd.h | 2 +- drivers/block/ioctl.c | 19 + drivers/block/ll_rw_blk.c | 334 +- drivers/block/loop.c | 196 +- drivers/block/paride/paride.c | 2 +- drivers/block/paride/pcd.c | 38 +- drivers/block/paride/pd.c | 46 +- drivers/block/paride/pf.c | 43 +- drivers/block/paride/pg.c | 35 +- drivers/block/paride/pt.c | 36 +- drivers/block/paride/setup.h | 69 - drivers/block/ps2esdi.c | 10 +- drivers/block/rd.c | 6 +- drivers/block/scsi_ioctl.c | 7 +- drivers/block/swim3.c | 2 +- drivers/block/umem.c | 4 +- drivers/block/viodasd.c | 8 +- drivers/block/xd.c | 10 +- drivers/bluetooth/bcm203x.c | 8 +- drivers/bluetooth/bfusb.c | 18 +- drivers/bluetooth/bt3c_cs.c | 25 +- drivers/bluetooth/hci_bcsp.c | 74 +- drivers/bluetooth/hci_ldisc.c | 13 +- drivers/bluetooth/hci_usb.c | 54 +- drivers/bluetooth/hci_usb.h | 4 +- drivers/cdrom/aztcd.c | 9 +- drivers/cdrom/cdrom.c | 28 +- drivers/cdrom/cdu31a.c | 722 +- drivers/cdrom/isp16.c | 18 +- drivers/cdrom/mcd.c | 1565 -- drivers/cdrom/mcd.h | 106 - drivers/cdrom/mcdx.c | 46 +- drivers/cdrom/viocd.c | 17 +- drivers/char/Kconfig | 69 +- drivers/char/Makefile | 11 +- drivers/char/README.cycladesZ | 8 - drivers/char/agp/Kconfig | 28 +- drivers/char/agp/agp.h | 37 +- drivers/char/agp/ali-agp.c | 22 +- drivers/char/agp/alpha-agp.c | 7 +- drivers/char/agp/amd-k7-agp.c | 64 +- drivers/char/agp/amd64-agp.c | 73 +- drivers/char/agp/ati-agp.c | 18 +- drivers/char/agp/backend.c | 151 +- drivers/char/agp/efficeon-agp.c | 14 +- drivers/char/agp/generic.c | 512 +- drivers/char/agp/hp-agp.c | 22 +- drivers/char/agp/i460-agp.c | 25 +- drivers/char/agp/intel-agp.c | 84 +- drivers/char/agp/intel-mch-agp.c | 642 - drivers/char/agp/nvidia-agp.c | 7 +- drivers/char/agp/sis-agp.c | 20 +- drivers/char/agp/sworks-agp.c | 26 +- drivers/char/agp/uninorth-agp.c | 399 +- drivers/char/agp/via-agp.c | 38 +- drivers/char/applicom.c | 11 +- drivers/char/console_macros.h | 71 - drivers/char/consolemap.c | 121 +- drivers/char/cyclades.c | 23 +- drivers/char/digi_bios.h | 177 - drivers/char/digi_fep.h | 517 - drivers/char/drm/Kconfig | 5 +- drivers/char/drm/ati_pcigart.h | 206 - drivers/char/drm/drmP.h | 364 +- drivers/char/drm/drm_agpsupport.h | 468 - drivers/char/drm/drm_auth.h | 230 - drivers/char/drm/drm_bufs.h | 1269 -- drivers/char/drm/drm_context.h | 578 - drivers/char/drm/drm_dma.h | 181 - drivers/char/drm/drm_drawable.h | 56 - drivers/char/drm/drm_drv.h | 1060 -- drivers/char/drm/drm_fops.h | 156 - drivers/char/drm/drm_init.h | 128 - drivers/char/drm/drm_ioctl.h | 349 - drivers/char/drm/drm_irq.h | 368 - drivers/char/drm/drm_lock.h | 168 - drivers/char/drm/drm_memory_debug.h | 4 +- drivers/char/drm/drm_os_linux.h | 9 +- drivers/char/drm/drm_proc.h | 547 - drivers/char/drm/drm_scatter.h | 231 - drivers/char/drm/drm_stub.h | 236 - drivers/char/drm/drm_vm.h | 667 - drivers/char/drm/ffb.h | 12 - drivers/char/drm/ffb_drv.c | 99 +- drivers/char/drm/gamma.h | 77 - drivers/char/drm/gamma_dma.c | 12 +- drivers/char/drm/i810.h | 77 - drivers/char/drm/i810_dma.c | 231 +- drivers/char/drm/i830.h | 83 - drivers/char/drm/i830_dma.c | 214 +- drivers/char/drm/i830_drv.c | 99 +- drivers/char/drm/i830_irq.c | 10 +- drivers/char/drm/i915.h | 53 - drivers/char/drm/mga.h | 63 - drivers/char/drm/mga_dma.c | 95 +- drivers/char/drm/mga_drv.c | 93 +- drivers/char/drm/mga_drv.h | 28 +- drivers/char/drm/mga_irq.c | 3 +- drivers/char/drm/r128.h | 75 - drivers/char/drm/r128_cce.c | 21 +- drivers/char/drm/r128_drv.c | 88 +- drivers/char/drm/r128_drv.h | 39 +- drivers/char/drm/r128_irq.c | 3 +- drivers/char/drm/r128_state.c | 146 +- drivers/char/drm/radeon.h | 112 - drivers/char/drm/radeon_cp.c | 400 +- drivers/char/drm/radeon_drm.h | 40 +- drivers/char/drm/radeon_drv.c | 92 +- drivers/char/drm/radeon_drv.h | 174 +- drivers/char/drm/radeon_irq.c | 26 +- drivers/char/drm/radeon_mem.c | 21 +- drivers/char/drm/radeon_state.c | 645 +- drivers/char/drm/sis.h | 61 - drivers/char/drm/sis_ds.c | 101 +- drivers/char/drm/sis_mm.c | 40 +- drivers/char/drm/tdfx.h | 50 - drivers/char/drm/tdfx_drv.c | 72 +- drivers/char/dtlk.c | 6 +- drivers/char/esp.c | 270 +- drivers/char/fep.h | 168 - drivers/char/ftape/lowlevel/fdc-io.c | 70 +- drivers/char/ftape/lowlevel/ftape-init.c | 12 +- drivers/char/genrtc.c | 4 +- drivers/char/hangcheck-timer.c | 104 +- drivers/char/hp600_keyb.c | 340 - drivers/char/hvsi.c | 42 +- drivers/char/hw_random.c | 37 +- drivers/char/ip2/Makefile | 12 - drivers/char/ip2/ip2mkdev.c | 123 - drivers/char/ip2/ip2stat.c | 115 - drivers/char/ip2/ip2trace.c | 279 - drivers/char/ip2main.c | 5 +- drivers/char/ipmi/ipmi_bt_sm.c | 1 - drivers/char/ipmi/ipmi_devintf.c | 20 +- drivers/char/ipmi/ipmi_msghandler.c | 193 +- drivers/char/ipmi/ipmi_si_intf.c | 265 +- drivers/char/ipmi/ipmi_watchdog.c | 51 +- drivers/char/isicom.c | 12 +- drivers/char/istallion.c | 76 +- drivers/char/keyboard.c | 54 +- drivers/char/lcd.c | 86 +- drivers/char/lp.c | 30 +- drivers/char/mem.c | 271 +- drivers/char/misc.c | 14 +- drivers/char/moxa.c | 4 +- drivers/char/mwave/3780i.c | 2 +- drivers/char/mwave/mwavedd.c | 10 +- drivers/char/mxser.c | 62 +- drivers/char/n_hdlc.c | 18 +- drivers/char/n_tty.c | 14 +- drivers/char/pcmcia/synclink_cs.c | 64 +- drivers/char/pcxx.c | 2353 --- drivers/char/pcxx.h | 128 - drivers/char/pty.c | 8 +- drivers/char/random.c | 1760 +- drivers/char/raw.c | 2 +- drivers/char/rio/cdproto.h | 55 - drivers/char/riscom8.h | 2 +- drivers/char/rsf16fmi.h | 13 - drivers/char/rtc.c | 116 +- drivers/char/selection.c | 54 +- drivers/char/serial_tx3912.c | 981 -- drivers/char/serial_tx3912.h | 92 - drivers/char/sonypi.c | 447 +- drivers/char/sonypi.h | 431 - drivers/char/specialix_io8.h | 2 +- drivers/char/stallion.c | 33 +- drivers/char/synclink.c | 4 +- drivers/char/synclinkmp.c | 26 +- drivers/char/sysrq.c | 65 +- drivers/char/tipar.c | 53 +- drivers/char/tpqic02.c | 2812 ---- drivers/char/tty_io.c | 84 +- drivers/char/tty_ioctl.c | 6 +- drivers/char/vc_screen.c | 65 +- drivers/char/vt.c | 1930 ++- drivers/char/vt_ioctl.c | 173 +- drivers/char/watchdog/Kconfig | 9 +- drivers/char/watchdog/Makefile | 13 +- drivers/char/watchdog/i8xx_tco.c | 35 +- drivers/char/watchdog/machzwd.c | 31 +- drivers/char/watchdog/pcwd_pci.c | 6 +- drivers/char/watchdog/pcwd_usb.c | 14 +- drivers/char/watchdog/sa1100_wdt.c | 2 +- drivers/char/watchdog/sc1200wdt.c | 6 +- drivers/char/watchdog/scx200_wdt.c | 42 +- drivers/cpufreq/cpufreq.c | 128 +- drivers/cpufreq/cpufreq_userspace.c | 400 +- drivers/cpufreq/proc_intf.c | 0 drivers/firmware/Kconfig | 4 +- drivers/firmware/efivars.c | 46 +- drivers/i2c/algos/i2c-algo-bit.c | 4 +- drivers/i2c/busses/Kconfig | 110 +- drivers/i2c/busses/Makefile | 3 + drivers/i2c/busses/i2c-ali1535.c | 7 +- drivers/i2c/busses/i2c-ali1563.c | 61 +- drivers/i2c/busses/i2c-ali15x3.c | 7 +- drivers/i2c/busses/i2c-amd756.c | 15 +- drivers/i2c/busses/i2c-amd8111.c | 2 +- drivers/i2c/busses/i2c-elektor.c | 10 +- drivers/i2c/busses/i2c-i801.c | 65 +- drivers/i2c/busses/i2c-ibm_iic.c | 6 +- drivers/i2c/busses/i2c-keywest.c | 7 +- drivers/i2c/busses/i2c-nforce2.c | 17 +- drivers/i2c/busses/i2c-piix4.c | 54 +- drivers/i2c/busses/i2c-sis5595.c | 15 +- drivers/i2c/busses/i2c-sis96x.c | 12 +- drivers/i2c/busses/i2c-viapro.c | 122 +- drivers/i2c/chips/Kconfig | 83 +- drivers/i2c/chips/Makefile | 7 + drivers/i2c/chips/adm1021.c | 25 +- drivers/i2c/chips/asb100.c | 37 +- drivers/i2c/chips/eeprom.c | 74 +- drivers/i2c/chips/fscher.c | 54 +- drivers/i2c/chips/gl518sm.c | 37 +- drivers/i2c/chips/it87.c | 334 +- drivers/i2c/chips/lm75.c | 12 +- drivers/i2c/chips/lm78.c | 90 +- drivers/i2c/chips/lm80.c | 44 +- drivers/i2c/chips/lm83.c | 15 +- drivers/i2c/chips/lm85.c | 230 +- drivers/i2c/chips/lm90.c | 98 +- drivers/i2c/chips/via686a.c | 68 +- drivers/i2c/chips/w83627hf.c | 108 +- drivers/i2c/chips/w83781d.c | 177 +- drivers/i2c/chips/w83l785ts.c | 12 +- drivers/i2c/i2c-core.c | 110 +- drivers/i2c/i2c-dev.c | 20 +- drivers/ide/Kconfig | 10 +- drivers/ide/Makefile | 3 +- drivers/ide/arm/icside.c | 39 +- drivers/ide/ide-cd.c | 349 +- drivers/ide/ide-cd.h | 4 + drivers/ide/ide-default.c | 73 - drivers/ide/ide-disk.c | 670 +- drivers/ide/ide-dma.c | 51 +- drivers/ide/ide-floppy.c | 218 +- drivers/ide/ide-io.c | 600 +- drivers/ide/ide-iops.c | 137 +- drivers/ide/ide-lib.c | 135 +- drivers/ide/ide-pnp.c | 9 +- drivers/ide/ide-probe.c | 247 +- drivers/ide/ide-proc.c | 265 +- drivers/ide/ide-tape.c | 285 +- drivers/ide/ide-taskfile.c | 41 +- drivers/ide/ide.c | 1050 +- drivers/ide/legacy/hd.c | 4 +- drivers/ide/legacy/ide-cs.c | 50 +- drivers/ide/pci/Makefile | 2 - drivers/ide/pci/adma100.c | 30 - drivers/ide/pci/adma100.h | 28 - drivers/ide/pci/aec62xx.c | 115 +- drivers/ide/pci/aec62xx.h | 122 - drivers/ide/pci/alim15x3.c | 5 +- drivers/ide/pci/amd74xx.c | 12 +- drivers/ide/pci/atiixp.c | 23 +- drivers/ide/pci/cmd64x.c | 87 +- drivers/ide/pci/cmd64x.h | 95 - drivers/ide/pci/cs5520.c | 12 +- drivers/ide/pci/cs5530.c | 3 +- drivers/ide/pci/cy82c693.h | 83 - drivers/ide/pci/delkin_cb.c | 140 - drivers/ide/pci/generic.c | 131 +- drivers/ide/pci/generic.h | 127 - drivers/ide/pci/hpt366.c | 507 +- drivers/ide/pci/hpt366.h | 490 - drivers/ide/pci/it8172.c | 23 +- drivers/ide/pci/it8172.h | 34 - drivers/ide/pci/ns87415.c | 5 +- drivers/ide/pci/opti621.c | 26 +- drivers/ide/pci/opti621.h | 31 - drivers/ide/pci/pdc202xx_new.c | 133 +- drivers/ide/pci/pdc202xx_new.h | 118 - drivers/ide/pci/pdc202xx_old.c | 151 +- drivers/ide/pci/pdc202xx_old.h | 144 - drivers/ide/pci/piix.c | 79 +- drivers/ide/pci/piix.h | 64 - drivers/ide/pci/rz1000.c | 3 +- drivers/ide/pci/sc1200.c | 5 +- drivers/ide/pci/serverworks.c | 76 +- drivers/ide/pci/serverworks.h | 69 - drivers/ide/pci/sgiioc4.c | 59 +- drivers/ide/pci/siimage.c | 9 +- drivers/ide/pci/sis5513.c | 9 +- drivers/ide/pci/sl82c105.c | 5 +- drivers/ide/pci/slc90e66.c | 3 +- drivers/ide/pci/triflex.c | 4 +- drivers/ide/pci/trm290.c | 9 +- drivers/ide/pci/via82cxxx.c | 21 +- drivers/ide/ppc/pmac.c | 209 +- drivers/ide/setup-pci.c | 218 +- drivers/ieee1394/amdtp.c | 58 +- drivers/ieee1394/csr.c | 2 +- drivers/ieee1394/csr1212.c | 132 +- drivers/ieee1394/dv1394.c | 113 +- drivers/ieee1394/eth1394.c | 23 +- drivers/ieee1394/ieee1394_core.c | 82 +- drivers/ieee1394/ieee1394_core.h | 3 +- drivers/ieee1394/nodemgr.c | 188 +- drivers/ieee1394/nodemgr.h | 2 + drivers/ieee1394/ohci1394.c | 8 +- drivers/ieee1394/raw1394.c | 4012 ++--- drivers/ieee1394/sbp2.c | 93 +- drivers/ieee1394/video1394.c | 428 +- drivers/input/Kconfig | 27 +- drivers/input/evdev.c | 16 +- drivers/input/gameport/Kconfig | 32 +- drivers/input/gameport/ns558.c | 160 +- drivers/input/gameport/vortex.c | 82 +- drivers/input/input.c | 30 +- drivers/input/joydev.c | 37 +- drivers/input/joystick/adi.c | 122 +- drivers/input/joystick/analog.c | 102 +- drivers/input/joystick/gf2k.c | 92 +- drivers/input/joystick/grip.c | 103 +- drivers/input/joystick/grip_mp.c | 97 +- drivers/input/joystick/sidewinder.c | 157 +- drivers/input/keyboard/Kconfig | 115 +- drivers/input/keyboard/atkbd.c | 859 +- drivers/input/misc/Kconfig | 24 +- drivers/input/misc/pcspkr.c | 4 +- drivers/input/misc/uinput.c | 227 +- drivers/input/mouse/Kconfig | 38 +- drivers/input/mouse/Makefile | 3 +- drivers/input/mousedev.c | 58 +- drivers/input/serio/Kconfig | 65 +- drivers/input/serio/ambakmi.c | 4 +- drivers/input/serio/i8042-io.h | 51 +- drivers/input/serio/i8042.c | 631 +- drivers/input/serio/maceps2.c | 26 +- drivers/input/serio/sa1111ps2.c | 6 +- drivers/input/serio/serport.c | 107 +- drivers/input/tsdev.c | 11 +- drivers/isdn/act2000/act2000_isa.c | 7 +- drivers/isdn/act2000/module.c | 8 +- drivers/isdn/capi/capi.c | 14 +- drivers/isdn/capi/capidrv.c | 2 +- drivers/isdn/capi/kcapi.c | 4 +- drivers/isdn/capi/kcapi_proc.c | 10 +- drivers/isdn/hardware/avm/avm_cs.c | 30 +- drivers/isdn/hardware/eicon/capifunc.c | 10 +- drivers/isdn/hardware/eicon/dadapter.c | 6 +- drivers/isdn/hardware/eicon/di.c | 204 +- drivers/isdn/hardware/eicon/divamnt.c | 13 +- drivers/isdn/hardware/eicon/divasi.c | 5 +- drivers/isdn/hardware/eicon/divasmain.c | 8 +- drivers/isdn/hardware/eicon/divasproc.c | 3 +- drivers/isdn/hardware/eicon/message.c | 129 +- drivers/isdn/hardware/eicon/mntfunc.c | 6 +- drivers/isdn/hardware/eicon/os_4bri.c | 10 +- drivers/isdn/hisax/Kconfig | 6 + drivers/isdn/hisax/config.c | 18 +- drivers/isdn/hisax/elsa_cs.c | 29 +- drivers/isdn/hisax/hfc_usb.c | 2290 +-- drivers/isdn/hisax/isdnhdlc.c | 2 +- drivers/isdn/hisax/st5481_b.c | 2 +- drivers/isdn/hisax/st5481_d.c | 2 +- drivers/isdn/hisax/st5481_usb.c | 4 +- drivers/isdn/hisax/teles_cs.c | 29 +- drivers/isdn/i4l/isdn_common.c | 28 +- drivers/isdn/i4l/isdn_net.c | 1 + drivers/isdn/i4l/isdn_net.h | 7 +- drivers/isdn/i4l/isdn_ppp.c | 35 +- drivers/isdn/icn/icn.c | 15 +- drivers/isdn/isdnloop/isdnloop.c | 4 +- drivers/isdn/pcbit/drv.c | 14 +- drivers/isdn/pcbit/module.c | 5 +- drivers/isdn/tpam/Kconfig | 15 - drivers/isdn/tpam/Makefile | 11 - drivers/isdn/tpam/tpam.h | 229 - drivers/isdn/tpam/tpam_commands.c | 987 -- drivers/isdn/tpam/tpam_crcpc.c | 162 - drivers/isdn/tpam/tpam_hdlc.c | 923 - drivers/isdn/tpam/tpam_main.c | 297 - drivers/isdn/tpam/tpam_memory.c | 247 - drivers/isdn/tpam/tpam_nco.c | 651 - drivers/isdn/tpam/tpam_queues.c | 401 - drivers/macintosh/Kconfig | 8 + drivers/macintosh/adb.c | 14 +- drivers/macintosh/macserial.h | 10 +- drivers/macintosh/mediabay.c | 39 +- drivers/macintosh/therm_adt746x.c | 135 +- drivers/macintosh/therm_pm72.c | 488 +- drivers/macintosh/via-pmu.c | 190 +- drivers/md/Kconfig | 33 +- drivers/md/Makefile | 33 + drivers/md/dm-ioctl.c | 27 +- drivers/md/dm-table.c | 32 +- drivers/md/dm.c | 132 +- drivers/md/dm.h | 28 +- drivers/md/linear.c | 43 +- drivers/md/md.c | 114 +- drivers/md/multipath.c | 17 +- drivers/md/raid1.c | 59 +- drivers/md/raid10.c | 16 +- drivers/md/raid5.c | 153 +- drivers/md/raid6main.c | 140 +- drivers/media/common/ir-common.c | 165 +- drivers/media/common/saa7146_fops.c | 16 +- drivers/media/common/saa7146_vbi.c | 135 +- drivers/media/common/saa7146_video.c | 198 +- drivers/media/dvb/b2c2/b2c2-common.c | 214 - drivers/media/dvb/b2c2/b2c2-usb-core.c | 548 - drivers/media/dvb/b2c2/skystar2.c | 380 +- drivers/media/dvb/bt8xx/dst.h | 40 - drivers/media/dvb/bt8xx/dvb-bt8xx.c | 305 +- drivers/media/dvb/dibusb/dvb-dibusb.c | 1032 -- drivers/media/dvb/dvb-core/dmxdev.c | 258 +- drivers/media/dvb/dvb-core/dvb_ca_en50221.c | 1768 +- drivers/media/dvb/dvb-core/dvb_demux.c | 487 +- drivers/media/dvb/dvb-core/dvb_net.c | 299 +- drivers/media/dvb/dvb-core/dvb_ringbuffer.c | 18 +- drivers/media/dvb/dvb-core/dvb_ringbuffer.h | 18 +- drivers/media/dvb/dvb-core/dvbdev.c | 76 +- drivers/media/dvb/frontends/Kconfig | 39 +- drivers/media/dvb/frontends/stv0299.c | 302 +- drivers/media/dvb/frontends/tda1004x.c | 359 +- drivers/media/dvb/ttpci/av7110.c | 1872 ++- drivers/media/dvb/ttpci/av7110_av.c | 37 +- drivers/media/dvb/ttpci/av7110_ca.c | 24 +- drivers/media/dvb/ttpci/av7110_hw.c | 151 +- drivers/media/dvb/ttpci/av7110_ir.c | 117 +- .../media/dvb/ttusb-budget/dvb-ttusb-budget.c | 247 +- drivers/media/dvb/ttusb-dec/ttusb_dec.c | 350 +- drivers/media/radio/miropcm20-radio.c | 14 +- drivers/media/radio/radio-cadet.c | 8 +- drivers/media/radio/radio-gemtek.c | 6 +- drivers/media/radio/radio-typhoon.c | 12 +- drivers/media/radio/radio-zoltrix.c | 34 +- drivers/media/video/Kconfig | 22 +- drivers/media/video/Makefile | 2 + drivers/media/video/bttv-cards.c | 397 +- drivers/media/video/bttv-driver.c | 130 +- drivers/media/video/bttv-i2c.c | 58 +- drivers/media/video/bttv-risc.c | 10 +- drivers/media/video/bttv-vbi.c | 5 +- drivers/media/video/bttv.h | 11 +- drivers/media/video/bttvp.h | 30 +- drivers/media/video/bw-qcam.c | 16 +- drivers/media/video/c-qcam.c | 15 +- drivers/media/video/cpia.c | 2 +- drivers/media/video/cpia_usb.c | 8 +- drivers/media/video/cx88/cx88-cards.c | 393 +- drivers/media/video/cx88/cx88-i2c.c | 10 +- drivers/media/video/cx88/cx88-tvaudio.c | 457 +- drivers/media/video/cx88/cx88-vbi.c | 11 +- drivers/media/video/cx88/cx88-video.c | 52 +- drivers/media/video/cx88/cx88.h | 42 +- drivers/media/video/dpc7146.c | 9 +- drivers/media/video/hexium_gemini.c | 2 +- drivers/media/video/hexium_orion.c | 6 +- drivers/media/video/ir-kbd-gpio.c | 53 +- drivers/media/video/ir-kbd-i2c.c | 14 +- drivers/media/video/meye.c | 8 +- drivers/media/video/msp3400.c | 55 +- drivers/media/video/mxb.c | 6 +- drivers/media/video/planb.c | 24 +- drivers/media/video/pms.c | 8 +- drivers/media/video/saa5246a.c | 63 +- drivers/media/video/saa5246a.h | 2 +- drivers/media/video/saa5249.c | 68 +- drivers/media/video/saa7111.c | 5 +- drivers/media/video/saa7134/saa6752hs.c | 403 +- drivers/media/video/saa7134/saa7134-cards.c | 407 +- drivers/media/video/saa7134/saa7134-core.c | 121 +- drivers/media/video/saa7134/saa7134-i2c.c | 40 +- drivers/media/video/saa7134/saa7134-input.c | 61 +- drivers/media/video/saa7134/saa7134-oss.c | 6 +- drivers/media/video/saa7134/saa7134-ts.c | 7 +- drivers/media/video/saa7134/saa7134-tvaudio.c | 63 +- drivers/media/video/saa7134/saa7134-video.c | 77 +- drivers/media/video/saa7134/saa7134.h | 21 +- drivers/media/video/stradis.c | 18 +- drivers/media/video/tda7432.c | 13 +- drivers/media/video/tda9840.c | 13 +- drivers/media/video/tda9875.c | 5 +- drivers/media/video/tda9887.c | 53 +- drivers/media/video/tea6415c.c | 4 - drivers/media/video/tea6420.c | 4 - drivers/media/video/tuner.c | 1415 -- drivers/media/video/tvaudio.c | 64 +- drivers/media/video/tvmixer.c | 1 + drivers/media/video/video-buf.c | 15 +- drivers/media/video/videocodec.c | 2 +- drivers/media/video/videodev.c | 11 +- drivers/media/video/w9966.c | 12 +- drivers/media/video/zoran_driver.c | 130 +- drivers/media/video/zr36120.c | 52 +- drivers/message/fusion/mptbase.c | 7 +- drivers/message/fusion/mptbase.h | 12 +- drivers/message/fusion/mptctl.c | 626 +- drivers/message/fusion/mptlan.c | 6 +- drivers/message/fusion/mptscsih.c | 283 +- drivers/message/fusion/mptscsih.h | 8 - drivers/message/i2o/i2o_block.c | 92 +- drivers/message/i2o/i2o_config.c | 96 +- drivers/message/i2o/i2o_proc.c | 24 +- drivers/message/i2o/i2o_scsi.c | 119 +- drivers/message/i2o/pci.c | 49 +- drivers/misc/Kconfig | 2 +- drivers/misc/ibmasm/ibmasmfs.c | 1 + drivers/misc/ibmasm/module.c | 7 +- drivers/mmc/mmc.c | 2 +- drivers/mtd/Kconfig | 41 +- drivers/mtd/chips/Kconfig | 20 +- drivers/mtd/chips/amd_flash.c | 4 +- drivers/mtd/chips/cfi_cmdset_0001.c | 342 +- drivers/mtd/chips/cfi_cmdset_0002.c | 32 +- drivers/mtd/chips/cfi_cmdset_0020.c | 8 +- drivers/mtd/chips/cfi_probe.c | 108 +- drivers/mtd/chips/chipreg.c | 2 +- drivers/mtd/chips/jedec.c | 16 +- drivers/mtd/chips/jedec_probe.c | 102 +- drivers/mtd/chips/map_ram.c | 8 +- drivers/mtd/chips/map_rom.c | 4 +- drivers/mtd/cmdlinepart.c | 6 +- drivers/mtd/devices/Kconfig | 26 +- drivers/mtd/devices/Makefile | 3 +- drivers/mtd/devices/blkmtd.c | 9 +- drivers/mtd/devices/doc1000.c | 594 - drivers/mtd/devices/doc2000.c | 30 +- drivers/mtd/devices/doc2001.c | 26 +- drivers/mtd/devices/doc2001plus.c | 30 +- drivers/mtd/devices/docprobe.c | 20 +- drivers/mtd/devices/ms02-nv.c | 8 +- drivers/mtd/devices/pmc551.c | 21 +- drivers/mtd/ftl.c | 2 +- drivers/mtd/inftlmount.c | 7 +- drivers/mtd/maps/Kconfig | 24 +- drivers/mtd/maps/Makefile | 4 +- drivers/mtd/maps/amd76xrom.c | 2 +- drivers/mtd/maps/cstm_mips_ixx.c | 2 +- drivers/mtd/maps/dilnetpc.c | 4 +- drivers/mtd/maps/ebony.c | 6 +- drivers/mtd/maps/elan-104nc.c | 4 +- drivers/mtd/maps/ich2rom.c | 316 - drivers/mtd/maps/l440gx.c | 2 +- drivers/mtd/maps/netsc520.c | 2 +- drivers/mtd/maps/nettel.c | 20 +- drivers/mtd/maps/ocelot.c | 4 +- drivers/mtd/maps/octagon-5066.c | 2 +- drivers/mtd/maps/pci.c | 8 +- drivers/mtd/maps/pcmciamtd.c | 31 +- drivers/mtd/maps/physmap.c | 2 +- drivers/mtd/maps/sa1100-flash.c | 2 +- drivers/mtd/maps/sbc_gxx.c | 4 +- drivers/mtd/maps/sc520cdp.c | 2 +- drivers/mtd/maps/scb2_flash.c | 2 +- drivers/mtd/maps/scx200_docflash.c | 40 +- drivers/mtd/maps/sun_uflash.c | 6 +- drivers/mtd/maps/uclinux.c | 6 +- drivers/mtd/maps/vmax301.c | 2 +- drivers/mtd/mtdblock.c | 4 +- drivers/mtd/mtdchar.c | 26 +- drivers/mtd/mtdpart.c | 2 +- drivers/mtd/nand/Kconfig | 18 +- drivers/mtd/nand/Makefile | 4 +- drivers/mtd/nftlmount.c | 7 +- drivers/mtd/redboot.c | 32 +- drivers/net/3c501.c | 4 +- drivers/net/3c503.c | 73 +- drivers/net/3c505.c | 18 +- drivers/net/3c507.c | 154 +- drivers/net/3c509.c | 33 +- drivers/net/3c523.c | 4 +- drivers/net/3c527.c | 2 +- drivers/net/3c59x.c | 335 +- drivers/net/8139too.c | 117 +- drivers/net/82596.c | 8 +- drivers/net/8390.h | 1 + drivers/net/Kconfig | 216 +- drivers/net/Makefile | 9 +- drivers/net/Space.c | 13 +- drivers/net/ac3200.c | 66 +- drivers/net/appletalk/ltpc.c | 14 +- drivers/net/arcnet/arcnet.c | 292 +- drivers/net/arcnet/com90xx.c | 8 +- drivers/net/at1700.c | 6 +- drivers/net/b44.c | 38 +- drivers/net/b44.h | 17 +- drivers/net/bagetlance.c | 1368 -- drivers/net/bonding/bond_main.c | 76 +- drivers/net/cs89x0.c | 20 +- drivers/net/defxx.c | 2 +- drivers/net/dgrs.c | 22 +- drivers/net/e100.c | 192 +- drivers/net/e1000/e1000.h | 38 +- drivers/net/e1000/e1000_ethtool.c | 134 +- drivers/net/e1000/e1000_hw.c | 2308 ++- drivers/net/e1000/e1000_hw.h | 589 +- drivers/net/e1000/e1000_main.c | 1325 +- drivers/net/e1000/e1000_param.c | 9 +- drivers/net/e2100.c | 26 +- drivers/net/eepro.c | 144 +- drivers/net/eepro100.c | 352 +- drivers/net/eexpress.c | 6 +- drivers/net/epic100.c | 10 +- drivers/net/eql.c | 4 - drivers/net/es3210.c | 38 +- drivers/net/eth16i.c | 8 +- drivers/net/ethertap.c | 390 - drivers/net/ewrk3.c | 92 +- drivers/net/fc/Makefile | 8 - drivers/net/fc/iph5526.c | 4645 ------ drivers/net/fc/iph5526_ip.h | 24 - drivers/net/fc/iph5526_novram.c | 278 - drivers/net/fc/iph5526_scsi.h | 31 - drivers/net/fc/tach.h | 475 - drivers/net/fc/tach_structs.h | 428 - drivers/net/fealnx.c | 287 +- drivers/net/forcedeth.c | 406 +- drivers/net/gianfar.c | 147 +- drivers/net/gianfar.h | 7 +- drivers/net/gianfar_ethtool.c | 6 +- drivers/net/gt96100eth.c | 8 +- drivers/net/hamachi.c | 111 +- drivers/net/hamradio/Kconfig | 6 +- drivers/net/hamradio/baycom_epp.c | 187 +- drivers/net/hamradio/dmascc.c | 1899 ++- drivers/net/hamradio/hdlcdrv.c | 52 +- drivers/net/hp-plus.c | 4 +- drivers/net/hp.c | 4 +- drivers/net/hp100.c | 83 +- drivers/net/ibmlana.c | 103 +- drivers/net/ibmveth.c | 48 +- drivers/net/irda/Kconfig | 12 +- drivers/net/irda/act200l-sir.c | 5 +- drivers/net/irda/act200l.c | 9 +- drivers/net/irda/actisys.c | 5 +- drivers/net/irda/ali-ircc.c | 74 +- drivers/net/irda/donauboe.c | 26 +- drivers/net/irda/girbil.c | 9 +- drivers/net/irda/irda-usb.c | 88 +- drivers/net/irda/irport.c | 194 +- drivers/net/irda/irtty-sir.c | 68 +- drivers/net/irda/ma600-sir.c | 18 +- drivers/net/irda/ma600.c | 9 +- drivers/net/irda/mcp2120.c | 9 +- drivers/net/irda/nsc-ircc.c | 100 +- drivers/net/irda/sir_dev.c | 29 +- drivers/net/irda/sir_kthread.c | 9 +- drivers/net/irda/smsc-ircc2.c | 162 +- drivers/net/irda/stir4200.c | 20 +- drivers/net/irda/tekram-sir.c | 9 +- drivers/net/irda/tekram.c | 13 +- drivers/net/irda/via-ircc.c | 56 +- drivers/net/irda/vlsi_ir.c | 118 +- drivers/net/irda/w83977af_ir.c | 34 +- drivers/net/iseries_veth.c | 63 +- drivers/net/ixgb/ixgb.h | 30 +- drivers/net/ixgb/ixgb_ee.c | 202 +- drivers/net/ixgb/ixgb_ee.h | 3 +- drivers/net/ixgb/ixgb_ethtool.c | 525 +- drivers/net/ixgb/ixgb_hw.c | 233 +- drivers/net/ixgb/ixgb_hw.h | 52 +- drivers/net/ixgb/ixgb_ids.h | 23 +- drivers/net/ixgb/ixgb_main.c | 881 +- drivers/net/ixgb/ixgb_osdep.h | 15 +- drivers/net/ixgb/ixgb_param.c | 318 +- drivers/net/jazzsonic.c | 217 +- drivers/net/lance.c | 9 +- drivers/net/lne390.c | 66 +- drivers/net/loopback.c | 4 +- drivers/net/lp486e.c | 22 +- drivers/net/macsonic.c | 1 + drivers/net/natsemi.c | 24 +- drivers/net/ne.c | 6 +- drivers/net/ne2.c | 6 +- drivers/net/ne2k-pci.c | 10 +- drivers/net/ne3210.c | 35 +- drivers/net/net_init.c | 152 - drivers/net/netconsole.c | 121 +- drivers/net/netdump.c | 534 - drivers/net/netdump.h | 81 - drivers/net/ni52.c | 8 +- drivers/net/ns83820.c | 74 +- drivers/net/pci-skeleton.c | 6 +- drivers/net/pcmcia/3c574_cs.c | 74 +- drivers/net/pcmcia/3c589_cs.c | 52 +- drivers/net/pcmcia/axnet_cs.c | 49 +- drivers/net/pcmcia/com20020_cs.c | 32 +- drivers/net/pcmcia/fmvj18x_cs.c | 48 +- drivers/net/pcmcia/ibmtr_cs.c | 37 +- drivers/net/pcmcia/nmclan_cs.c | 45 +- drivers/net/pcmcia/pcnet_cs.c | 102 +- drivers/net/pcmcia/smc91c92_cs.c | 85 +- drivers/net/pcmcia/xirc2ps_cs.c | 104 +- drivers/net/pcnet32.c | 65 +- drivers/net/plip.c | 4 +- drivers/net/ppp_async.c | 4 +- drivers/net/ppp_generic.c | 18 +- drivers/net/ppp_synctty.c | 2 +- drivers/net/pppoe.c | 133 +- drivers/net/pppox.c | 2 +- drivers/net/r8169.c | 1154 +- drivers/net/rrunner.c | 2 +- drivers/net/s2io.c | 3579 ++-- drivers/net/s2io.h | 433 +- drivers/net/sb1000.c | 28 +- drivers/net/sb1250-mac.c | 109 +- drivers/net/sgiseeq.c | 70 +- drivers/net/shaper.c | 40 +- drivers/net/sis900.c | 310 +- drivers/net/sk98lin/h/skdrv1st.h | 1 + drivers/net/sk98lin/h/skdrv2nd.h | 5 +- drivers/net/sk98lin/skge.c | 286 +- drivers/net/sk_mca.c | 126 +- drivers/net/sk_mca.h | 19 +- drivers/net/skfp/h/targetos.h | 2 +- drivers/net/skfp/skfddi.c | 125 +- drivers/net/skfp/smt.c | 7 - drivers/net/smc-mca.c | 41 +- drivers/net/smc-ultra.c | 40 +- drivers/net/smc-ultra32.c | 30 +- drivers/net/smc9194.c | 6 +- drivers/net/starfire.c | 99 +- drivers/net/sundance.c | 274 +- drivers/net/sungem.c | 1016 +- drivers/net/sungem.h | 82 +- drivers/net/sunhme.c | 22 +- drivers/net/tg3.c | 2852 +++- drivers/net/tg3.h | 103 +- drivers/net/tlan.c | 94 +- drivers/net/tokenring/Kconfig | 2 +- drivers/net/tokenring/ibmtr.c | 164 +- drivers/net/tokenring/lanstreamer.c | 31 +- drivers/net/tokenring/olympic.c | 98 +- drivers/net/tokenring/smctr.c | 6 +- drivers/net/tulip/de2104x.c | 14 +- drivers/net/tulip/de4x5.c | 1 + drivers/net/tulip/dmfe.c | 21 +- drivers/net/tulip/interrupt.c | 2 +- drivers/net/tulip/media.c | 5 +- drivers/net/tulip/tulip.h | 2 +- drivers/net/tulip/tulip_core.c | 24 +- drivers/net/tulip/winbond-840.c | 19 +- drivers/net/tulip/xircom_tulip_cb.c | 31 +- drivers/net/tun.c | 315 +- drivers/net/typhoon.c | 269 +- drivers/net/via-rhine.c | 303 +- drivers/net/wan/Kconfig | 21 +- drivers/net/wan/c101.c | 3 - drivers/net/wan/cosa.c | 13 +- drivers/net/wan/cosa.h | 10 +- drivers/net/wan/dscc4.c | 121 +- drivers/net/wan/farsync.c | 11 +- drivers/net/wan/hd6457x.c | 2 +- drivers/net/wan/hostess_sv11.c | 6 +- drivers/net/wan/n2.c | 5 - drivers/net/wan/pc300_tty.c | 27 +- drivers/net/wan/sbni.c | 16 +- drivers/net/wan/sdla.c | 2 +- drivers/net/wan/sealevel.c | 10 +- drivers/net/wan/syncppp.c | 4 +- drivers/net/wan/wanxl.c | 38 +- drivers/net/wan/x25_asy.c | 22 +- drivers/net/wan/z85230.h | 2 +- drivers/net/wd.c | 44 +- drivers/net/wireless/Kconfig | 6 +- drivers/net/wireless/airo.c | 317 +- drivers/net/wireless/airo_cs.c | 34 +- drivers/net/wireless/arlan-proc.c | 15 +- drivers/net/wireless/atmel.c | 103 +- drivers/net/wireless/atmel_cs.c | 94 +- drivers/net/wireless/hermes.h | 64 +- drivers/net/wireless/orinoco.c | 3039 ++-- drivers/net/wireless/orinoco.h | 31 +- drivers/net/wireless/orinoco_pci.c | 126 +- drivers/net/wireless/orinoco_plx.c | 235 +- drivers/net/wireless/orinoco_tmd.c | 152 +- drivers/net/wireless/prism54/isl_38xx.c | 12 +- drivers/net/wireless/prism54/isl_ioctl.c | 58 +- drivers/net/wireless/prism54/isl_ioctl.h | 5 - drivers/net/wireless/prism54/islpci_dev.c | 7 +- drivers/net/wireless/prism54/islpci_dev.h | 2 - drivers/net/wireless/prism54/islpci_hotplug.c | 8 +- drivers/net/wireless/prism54/islpci_mgt.c | 2 + drivers/net/wireless/prism54/oid_mgt.c | 6 +- drivers/net/wireless/prism54/oid_mgt.h | 4 +- drivers/net/wireless/ray_cs.c | 45 +- drivers/net/wireless/strip.c | 22 +- drivers/net/yellowfin.c | 14 +- drivers/oprofile/buffer_sync.c | 71 +- drivers/oprofile/cpu_buffer.c | 158 +- drivers/oprofile/event_buffer.c | 7 +- drivers/oprofile/oprofile_files.c | 42 +- drivers/oprofile/oprofilefs.c | 3 +- drivers/parisc/ccio-dma.c | 74 +- drivers/parisc/superio.c | 109 +- drivers/parisc/wax.c | 68 +- drivers/parport/daisy.c | 2 +- drivers/parport/ieee1284.c | 2 +- drivers/parport/parport_pc.c | 141 +- drivers/parport/parport_serial.c | 92 +- drivers/parport/probe.c | 2 +- drivers/parport/procfs.c | 12 +- drivers/parport/share.c | 6 +- drivers/pci/Kconfig | 14 +- drivers/pci/Makefile | 6 + drivers/pci/hotplug.c | 126 +- drivers/pci/hotplug/cpci_hotplug.h | 2 +- drivers/pci/hotplug/cpci_hotplug_core.c | 429 +- drivers/pci/hotplug/cpci_hotplug_pci.c | 483 +- drivers/pci/hotplug/cpcihp_generic.c | 2 +- drivers/pci/hotplug/cpqphp_core.c | 4 +- drivers/pci/hotplug/cpqphp_pci.c | 30 +- drivers/pci/hotplug/ibmphp.h | 4 +- drivers/pci/hotplug/ibmphp_core.c | 804 +- drivers/pci/hotplug/ibmphp_hpc.c | 6 +- drivers/pci/hotplug/pci_hotplug_core.c | 5 + drivers/pci/hotplug/pciehp.h | 4 +- drivers/pci/hotplug/pciehp_core.c | 105 +- drivers/pci/hotplug/pciehp_ctrl.c | 3 +- drivers/pci/hotplug/pciehp_hpc.c | 179 +- drivers/pci/hotplug/pciehprm_acpi.c | 3 +- drivers/pci/hotplug/pcihp_skeleton.c | 2 +- drivers/pci/hotplug/rpadlpar_core.c | 10 +- drivers/pci/hotplug/rpaphp.h | 14 +- drivers/pci/hotplug/rpaphp_core.c | 49 +- drivers/pci/hotplug/rpaphp_pci.c | 129 +- drivers/pci/hotplug/rpaphp_slot.c | 15 +- drivers/pci/hotplug/rpaphp_vio.c | 4 +- drivers/pci/hotplug/shpchp.h | 2 +- drivers/pci/hotplug/shpchp_core.c | 3 +- drivers/pci/hotplug/shpchp_ctrl.c | 30 +- drivers/pci/hotplug/shpchprm_acpi.c | 7 +- drivers/pci/hotplug/shpchprm_legacy.c | 18 +- drivers/pci/msi.c | 74 +- drivers/pci/pci-driver.c | 43 +- drivers/pci/pci-sysfs.c | 262 +- drivers/pci/pci.c | 101 +- drivers/pci/pci.h | 35 +- drivers/pci/pci.ids | 1745 +- drivers/pci/probe.c | 165 +- drivers/pci/proc.c | 30 +- drivers/pci/quirks.c | 156 +- drivers/pci/search.c | 2 +- drivers/pcmcia/Kconfig | 44 +- drivers/pcmcia/Makefile | 18 +- drivers/pcmcia/bulkmem.c | 218 - drivers/pcmcia/cardbus.c | 45 +- drivers/pcmcia/cistpl.c | 50 +- drivers/pcmcia/cs.c | 607 +- drivers/pcmcia/cs_internal.h | 49 +- drivers/pcmcia/ds.c | 1377 +- drivers/pcmcia/i82092.c | 19 +- drivers/pcmcia/i82365.c | 57 +- drivers/pcmcia/rsrc_mgr.c | 1044 +- drivers/pcmcia/sa1100_generic.c | 2 +- drivers/pcmcia/sa1111_generic.c | 2 +- drivers/pcmcia/tcic.c | 39 +- drivers/pcmcia/yenta_socket.c | 17 +- drivers/pnp/isapnp/core.c | 55 +- drivers/pnp/pnpbios/Kconfig | 2 +- drivers/pnp/pnpbios/core.c | 21 +- drivers/s390/Kconfig | 2 +- drivers/s390/block/dasd.c | 106 +- drivers/s390/block/dasd_3990_erp.c | 42 +- drivers/s390/block/dasd_devmap.c | 86 +- drivers/s390/block/dasd_diag.c | 69 +- drivers/s390/block/dasd_eckd.c | 291 +- drivers/s390/block/dasd_erp.c | 10 +- drivers/s390/block/dasd_fba.c | 120 +- drivers/s390/block/dasd_genhd.c | 14 +- drivers/s390/block/dasd_int.h | 22 +- drivers/s390/char/Makefile | 2 +- drivers/s390/char/sclp.c | 1262 +- drivers/s390/char/tty3270.c | 6 +- drivers/s390/cio/chsc.c | 117 +- drivers/s390/cio/chsc.h | 16 +- drivers/s390/cio/cio.c | 44 +- drivers/s390/cio/cmf.c | 4 +- drivers/s390/cio/css.c | 16 +- drivers/s390/cio/device.c | 10 +- drivers/s390/cio/device_fsm.c | 66 +- drivers/s390/cio/device_id.c | 3 +- drivers/s390/cio/device_ops.c | 84 +- drivers/s390/cio/device_pgid.c | 10 +- drivers/s390/cio/qdio.c | 20 +- drivers/s390/cio/qdio.h | 6 +- drivers/s390/net/Makefile | 3 +- drivers/s390/net/ctcmain.c | 641 +- drivers/s390/net/ctctty.c | 12 +- drivers/s390/net/cu3088.c | 4 +- drivers/s390/net/iucv.c | 17 +- drivers/s390/net/lcs.c | 33 +- drivers/s390/net/qeth.h | 133 +- drivers/s390/net/qeth_main.c | 1297 +- drivers/s390/net/qeth_mpc.h | 5 +- drivers/s390/net/qeth_proc.c | 19 +- drivers/s390/net/qeth_sys.c | 201 +- drivers/s390/scsi/zfcp_aux.c | 42 +- drivers/s390/scsi/zfcp_def.h | 6 +- drivers/s390/scsi/zfcp_erp.c | 26 +- drivers/s390/scsi/zfcp_fsf.c | 73 +- drivers/s390/scsi/zfcp_sysfs_adapter.c | 6 + drivers/sbus/char/aurora.h | 2 +- drivers/sbus/char/bpp.c | 2 +- drivers/sbus/char/flash.c | 4 +- drivers/sbus/char/openprom.c | 10 +- drivers/sbus/char/riowatchdog.c | 2 +- drivers/sbus/char/rtc.c | 110 +- drivers/sbus/char/vfc_dev.c | 8 +- drivers/sbus/sbus.c | 16 + drivers/scsi/3w-xxxx.c | 366 +- drivers/scsi/3w-xxxx.h | 4 +- drivers/scsi/53c700.c | 139 +- drivers/scsi/53c700.h | 217 +- drivers/scsi/53c7xx.c | 23 +- drivers/scsi/BusLogic.c | 7 - drivers/scsi/Kconfig | 62 +- drivers/scsi/Makefile | 6 +- drivers/scsi/NCR53C9x.c | 20 +- drivers/scsi/NCR_D700.c | 52 +- drivers/scsi/NCR_Q720.c | 6 +- drivers/scsi/aacraid/README | 2 +- drivers/scsi/aacraid/aachba.c | 274 +- drivers/scsi/aacraid/aacraid.h | 217 +- drivers/scsi/aacraid/commctrl.c | 12 +- drivers/scsi/aacraid/comminit.c | 2 +- drivers/scsi/aacraid/commsup.c | 25 +- drivers/scsi/aacraid/linit.c | 117 +- drivers/scsi/aacraid/rkt.c | 21 +- drivers/scsi/aacraid/rx.c | 18 +- drivers/scsi/aacraid/sa.c | 28 +- drivers/scsi/advansys.c | 19 +- drivers/scsi/aha152x.c | 69 +- drivers/scsi/aha1542.c | 6 +- drivers/scsi/aic7xxx/aic7770_osm.c | 64 +- drivers/scsi/aic7xxx/aic79xx_osm.c | 60 +- drivers/scsi/aic7xxx/aic7xxx_osm.c | 3286 +--- drivers/scsi/aic7xxx/aic7xxx_osm.h | 217 +- drivers/scsi/aic7xxx/aic7xxx_osm_pci.c | 102 +- drivers/scsi/aic7xxx/aiclib.c | 1 - drivers/scsi/aic7xxx_old.c | 14 +- drivers/scsi/aic7xxx_old/aic7xxx_proc.c | 2 +- drivers/scsi/arm/acornscsi.c | 9 +- drivers/scsi/arm/arxescsi.c | 18 +- drivers/scsi/arm/cumana_2.c | 97 +- drivers/scsi/arm/eesox.c | 84 +- drivers/scsi/arm/fas216.c | 31 +- drivers/scsi/arm/powertec.c | 74 +- drivers/scsi/ata_piix.c | 37 +- drivers/scsi/atp870u.c | 345 +- drivers/scsi/constants.c | 946 +- drivers/scsi/cpqfcTSinit.c | 8 +- drivers/scsi/cpqfcTSworker.c | 16 +- drivers/scsi/dc395x.c | 91 +- drivers/scsi/dec_esp.c | 400 +- drivers/scsi/dpt/dpt_osdutil.h | 358 - drivers/scsi/dpt_i2o.c | 6 +- drivers/scsi/dpti.h | 1 - drivers/scsi/eata.c | 3169 ++-- drivers/scsi/esp.c | 13 +- drivers/scsi/fd_mcs.c | 58 +- drivers/scsi/fd_mcs.h | 37 - drivers/scsi/fdomain.c | 2 +- drivers/scsi/g_NCR5380.c | 14 +- drivers/scsi/gdth.c | 998 +- drivers/scsi/gdth.h | 41 - drivers/scsi/gdth_proc.c | 287 +- drivers/scsi/gdth_proc.h | 6 +- drivers/scsi/hosts.c | 90 +- drivers/scsi/ibmmca.c | 11 +- drivers/scsi/ibmvscsi/ibmvscsi.c | 145 +- drivers/scsi/ide-scsi.c | 229 +- drivers/scsi/imm.c | 2 +- drivers/scsi/in2000.c | 2 +- drivers/scsi/ips.c | 261 +- drivers/scsi/ips.h | 12 +- drivers/scsi/jazz_esp.c | 95 +- drivers/scsi/lasi700.c | 40 +- drivers/scsi/lasi700.h | 49 - drivers/scsi/libata-core.c | 830 +- drivers/scsi/libata-scsi.c | 65 +- drivers/scsi/libata.h | 3 +- drivers/scsi/lpfc/Makefile | 32 + drivers/scsi/lpfc/lpfc.h | 384 + drivers/scsi/lpfc/lpfc_compat.h | 97 + drivers/scsi/lpfc/lpfc_crtn.h | 216 + drivers/scsi/lpfc/lpfc_ct.c | 1237 ++ drivers/scsi/lpfc/lpfc_disc.h | 206 + drivers/scsi/lpfc/lpfc_els.c | 3258 ++++ drivers/scsi/lpfc/lpfc_hbadisc.c | 2537 +++ drivers/scsi/lpfc/lpfc_hw.h | 2687 +++ drivers/scsi/lpfc/lpfc_init.c | 1739 ++ drivers/scsi/lpfc/lpfc_logmsg.h | 41 + drivers/scsi/lpfc/lpfc_mbox.c | 646 + drivers/scsi/lpfc/lpfc_mem.c | 179 + drivers/scsi/lpfc/lpfc_nportdisc.c | 1842 ++ drivers/scsi/lpfc/lpfc_scsi.h | 157 + drivers/scsi/lpfc/lpfc_sli.c | 2885 ++++ drivers/scsi/lpfc/lpfc_sli.h | 216 + drivers/scsi/lpfc/lpfc_version.h | 32 + drivers/scsi/mac_scsi.c | 2 +- drivers/scsi/mca_53c9x.c | 4 +- drivers/scsi/megaraid/Kconfig.megaraid | 1 + drivers/scsi/ncr53c8xx.c | 522 +- drivers/scsi/nsp32.c | 16 +- drivers/scsi/nsp32.h | 1 + drivers/scsi/oktagon_esp.c | 2 - drivers/scsi/osst.c | 1025 +- drivers/scsi/pas16.c | 6 +- drivers/scsi/pci2000.c | 20 +- drivers/scsi/pcmcia/aha152x_stub.c | 33 +- drivers/scsi/pcmcia/fdomain_stub.c | 23 +- drivers/scsi/pcmcia/nsp_cs.c | 28 +- drivers/scsi/pcmcia/qlogic_stub.c | 26 +- drivers/scsi/pluto.c | 2 +- drivers/scsi/ppa.c | 2 +- drivers/scsi/psi240i.c | 8 +- drivers/scsi/qla1280.c | 168 +- drivers/scsi/qla2xxx/Makefile | 4 +- drivers/scsi/qla2xxx/ql2300.c | 2 +- drivers/scsi/qla2xxx/ql2300_fw.c | 13924 ++++++++-------- drivers/scsi/qla2xxx/ql2322_fw.c | 13219 +++++++-------- drivers/scsi/qla2xxx/ql6312.c | 14 +- drivers/scsi/qla2xxx/ql6312_fw.c | 13577 +++++++-------- drivers/scsi/qla2xxx/ql6322.c | 108 - drivers/scsi/qla2xxx/ql6322_fw.c | 7433 --------- drivers/scsi/qla2xxx/qla_dbg.c | 11 +- drivers/scsi/qla2xxx/qla_def.h | 176 +- drivers/scsi/qla2xxx/qla_gbl.h | 70 +- drivers/scsi/qla2xxx/qla_init.c | 1610 +- drivers/scsi/qla2xxx/qla_inline.h | 17 - drivers/scsi/qla2xxx/qla_iocb.c | 195 +- drivers/scsi/qla2xxx/qla_isr.c | 213 +- drivers/scsi/qla2xxx/qla_listops.h | 351 - drivers/scsi/qla2xxx/qla_mbx.c | 524 +- drivers/scsi/qla2xxx/qla_os.c | 2986 +--- drivers/scsi/qla2xxx/qla_rscn.c | 2 +- drivers/scsi/qla2xxx/qla_sup.c | 93 +- drivers/scsi/qla2xxx/qla_version.h | 6 +- drivers/scsi/qlogicfas.c | 4 +- drivers/scsi/qlogicfc.c | 80 +- drivers/scsi/qlogicfc.h | 80 - drivers/scsi/qlogicisp.c | 107 +- drivers/scsi/qlogicisp.h | 69 - drivers/scsi/qlogicpti.c | 2 +- drivers/scsi/sata_promise.c | 82 +- drivers/scsi/sata_sil.c | 55 +- drivers/scsi/sata_sis.c | 12 +- drivers/scsi/sata_svw.c | 18 +- drivers/scsi/sata_via.c | 215 +- drivers/scsi/sata_vsc.c | 20 +- drivers/scsi/scsi.c | 147 +- drivers/scsi/scsi.h | 58 - drivers/scsi/scsi_debug.c | 489 +- drivers/scsi/scsi_devinfo.c | 6 +- drivers/scsi/scsi_error.c | 193 +- drivers/scsi/scsi_ioctl.c | 44 +- drivers/scsi/scsi_lib.c | 317 +- drivers/scsi/scsi_obsolete.h | 106 - drivers/scsi/scsi_priv.h | 7 +- drivers/scsi/scsi_scan.c | 342 +- drivers/scsi/scsi_syms.c | 97 - drivers/scsi/scsi_sysfs.c | 393 +- drivers/scsi/scsi_transport_fc.c | 1624 +- drivers/scsi/scsi_transport_spi.c | 635 +- drivers/scsi/scsicam.c | 18 +- drivers/scsi/sd.c | 258 +- drivers/scsi/seagate.c | 5 +- drivers/scsi/sg.c | 320 +- drivers/scsi/sim710.c | 25 +- drivers/scsi/sr.c | 16 +- drivers/scsi/sr_ioctl.c | 6 + drivers/scsi/st.c | 436 +- drivers/scsi/st.h | 19 +- drivers/scsi/sym53c416.c | 6 +- drivers/scsi/sym53c8xx_2/sym_conf.h | 110 - drivers/scsi/sym53c8xx_2/sym_glue.c | 714 +- drivers/scsi/sym53c8xx_2/sym_misc.c | 111 - drivers/scsi/sym53c8xx_comm.h | 4 +- drivers/scsi/sym53c8xx_defs.h | 54 +- drivers/scsi/u14-34f.c | 2 +- drivers/scsi/ultrastor.c | 6 +- drivers/scsi/wd33c93.h | 2 + drivers/scsi/zalon.c | 44 +- drivers/serial/68328serial.h | 10 +- drivers/serial/68360serial.c | 8 +- drivers/serial/8250.c | 210 +- drivers/serial/8250_pci.c | 52 +- drivers/serial/8250_pnp.c | 6 +- drivers/serial/Kconfig | 72 +- drivers/serial/Makefile | 9 +- drivers/serial/amba-pl011.c | 16 +- drivers/serial/au1x00_uart.c | 67 +- drivers/serial/crisv10.h | 4 +- drivers/serial/icom.c | 89 +- drivers/serial/mcfserial.h | 4 +- drivers/serial/pmac_zilog.c | 4 +- drivers/serial/pxa.c | 18 +- drivers/serial/serial_core.c | 19 +- drivers/serial/sunsab.c | 123 +- drivers/serial/sunsu.c | 22 +- drivers/serial/sunzilog.c | 9 +- drivers/tc/zs.c | 643 +- drivers/tc/zs.h | 10 +- drivers/telephony/ixj.c | 131 +- drivers/telephony/ixj.h | 2 - drivers/usb/Kconfig | 28 + drivers/usb/Makefile | 9 +- drivers/usb/class/audio.c | 111 +- drivers/usb/class/bluetty.c | 10 +- drivers/usb/class/cdc-acm.c | 153 +- drivers/usb/class/usb-midi.c | 36 +- drivers/usb/class/usblp.c | 23 +- drivers/usb/core/buffer.c | 2 - drivers/usb/core/config.c | 12 +- drivers/usb/core/devices.c | 54 +- drivers/usb/core/devio.c | 373 +- drivers/usb/core/file.c | 66 +- drivers/usb/core/hcd-pci.c | 335 +- drivers/usb/core/hcd.c | 642 +- drivers/usb/core/hcd.h | 159 +- drivers/usb/core/hub.c | 739 +- drivers/usb/core/hub.h | 5 +- drivers/usb/core/inode.c | 4 +- drivers/usb/core/message.c | 124 +- drivers/usb/core/urb.c | 24 +- drivers/usb/core/usb.c | 144 +- drivers/usb/core/usb.h | 18 +- drivers/usb/gadget/Kconfig | 120 +- drivers/usb/gadget/dummy_hcd.c | 211 +- drivers/usb/gadget/epautoconf.c | 3 + drivers/usb/gadget/ether.c | 541 +- drivers/usb/gadget/file_storage.c | 72 +- drivers/usb/gadget/gadget_chips.h | 13 +- drivers/usb/gadget/inode.c | 32 +- drivers/usb/gadget/net2280.c | 27 +- drivers/usb/gadget/pxa2xx_udc.c | 280 +- drivers/usb/gadget/rndis.c | 195 +- drivers/usb/gadget/rndis.h | 165 +- drivers/usb/gadget/serial.c | 177 +- drivers/usb/gadget/zero.c | 59 +- drivers/usb/host/ehci-dbg.c | 32 +- drivers/usb/host/ehci-hcd.c | 281 +- drivers/usb/host/ehci-hub.c | 26 +- drivers/usb/host/ehci-mem.c | 42 +- drivers/usb/host/ehci-q.c | 105 +- drivers/usb/host/ehci-sched.c | 485 +- drivers/usb/host/ehci.h | 57 +- drivers/usb/host/ohci-dbg.c | 32 +- drivers/usb/host/ohci-hcd.c | 133 +- drivers/usb/host/ohci-hub.c | 34 +- drivers/usb/host/ohci-mem.c | 25 +- drivers/usb/host/ohci-omap.c | 309 +- drivers/usb/host/ohci-pci.c | 29 +- drivers/usb/host/ohci-q.c | 102 +- drivers/usb/host/ohci-sa1111.c | 142 +- drivers/usb/host/ohci.h | 82 +- drivers/usb/host/uhci-debug.c | 62 +- drivers/usb/host/uhci-hcd.c | 1762 +- drivers/usb/host/uhci-hcd.h | 83 +- drivers/usb/host/uhci-hub.c | 46 +- drivers/usb/image/hpusbscsi.c | 523 - drivers/usb/image/hpusbscsi.h | 73 - drivers/usb/image/mdc800.c | 93 +- drivers/usb/image/microtek.c | 14 +- drivers/usb/input/Kconfig | 23 +- drivers/usb/input/Makefile | 1 + drivers/usb/input/aiptek.c | 34 +- drivers/usb/input/ati_remote.c | 93 +- drivers/usb/input/hid-core.c | 407 +- drivers/usb/input/hiddev.c | 19 +- drivers/usb/input/kbtab.c | 6 +- drivers/usb/input/mtouchusb.c | 67 +- drivers/usb/input/powermate.c | 16 +- drivers/usb/input/wacom.c | 343 +- drivers/usb/media/Makefile | 2 +- drivers/usb/media/dabusb.c | 12 +- drivers/usb/media/ibmcam.c | 32 +- drivers/usb/media/konicawc.c | 20 +- drivers/usb/media/ov511.c | 40 +- drivers/usb/media/pwc/ChangeLog | 143 - drivers/usb/media/pwc/pwc-dec1.c | 42 - drivers/usb/media/pwc/pwc-dec1.h | 36 - drivers/usb/media/pwc/pwc-dec23.c | 623 - drivers/usb/media/pwc/pwc-dec23.h | 58 - drivers/usb/media/se401.c | 43 +- drivers/usb/media/stv680.c | 3 +- drivers/usb/media/ultracam.c | 20 +- drivers/usb/media/usbvideo.c | 12 +- drivers/usb/media/vicam.c | 10 +- drivers/usb/media/w9968cf.c | 14 +- drivers/usb/media/w9968cf.h | 2 +- drivers/usb/misc/Kconfig | 37 +- drivers/usb/misc/Makefile | 4 +- drivers/usb/misc/auerswald.c | 66 +- drivers/usb/misc/cytherm.c | 2 +- drivers/usb/misc/emi26.c | 10 +- drivers/usb/misc/emi62.c | 6 +- drivers/usb/misc/legousbtower.c | 17 +- drivers/usb/misc/tiglusb.c | 592 - drivers/usb/misc/tiglusb.h | 43 - drivers/usb/misc/usbtest.c | 41 +- drivers/usb/misc/uss720.c | 15 +- drivers/usb/net/kaweth.c | 26 +- drivers/usb/net/pegasus.c | 373 +- drivers/usb/net/pegasus.h | 5 +- drivers/usb/net/rtl8150.c | 4 +- drivers/usb/net/usbnet.c | 1289 +- drivers/usb/serial/Kconfig | 62 + drivers/usb/serial/Makefile | 6 + drivers/usb/serial/belkin_sa.c | 9 +- drivers/usb/serial/cyberjack.c | 7 +- drivers/usb/serial/digi_acceleport.c | 31 +- drivers/usb/serial/empeg.c | 6 +- drivers/usb/serial/ezusb.c | 2 +- drivers/usb/serial/ftdi_sio.c | 347 +- drivers/usb/serial/ftdi_sio.h | 94 +- drivers/usb/serial/io_edgeport.c | 79 +- drivers/usb/serial/io_ti.c | 16 +- drivers/usb/serial/ipaq.c | 2 +- drivers/usb/serial/ir-usb.c | 2 +- drivers/usb/serial/keyspan.c | 18 +- drivers/usb/serial/keyspan_pda.c | 20 +- drivers/usb/serial/kl5kusb105.c | 50 +- drivers/usb/serial/kobil_sct.c | 16 +- drivers/usb/serial/mct_u232.c | 181 +- drivers/usb/serial/omninet.c | 5 +- drivers/usb/serial/pl2303.c | 55 +- drivers/usb/serial/pl2303.h | 3 + drivers/usb/serial/usb-serial.c | 59 +- drivers/usb/serial/usb-serial.h | 4 - drivers/usb/serial/visor.c | 59 +- drivers/usb/serial/visor.h | 13 +- drivers/usb/serial/whiteheat.c | 5 +- drivers/usb/storage/Kconfig | 45 +- drivers/usb/storage/datafab.c | 2 +- drivers/usb/storage/isd200.c | 2 +- drivers/usb/storage/jumpshot.c | 2 +- drivers/usb/storage/scsiglue.c | 126 +- drivers/usb/storage/scsiglue.h | 6 - drivers/usb/storage/sddr09.c | 2 +- drivers/usb/storage/shuttle_usbat.c | 1265 +- drivers/usb/storage/shuttle_usbat.h | 78 +- drivers/usb/storage/transport.c | 60 +- drivers/usb/storage/unusual_devs.h | 288 +- drivers/usb/storage/usb.c | 242 +- drivers/usb/storage/usb.h | 61 +- drivers/video/Kconfig | 563 +- drivers/video/Makefile | 158 +- drivers/video/acornfb.c | 2 +- drivers/video/aty/atyfb_base.c | 84 +- drivers/video/aty/mach64_cursor.c | 2 +- drivers/video/aty/radeon_accel.c | 67 +- drivers/video/aty/radeon_base.c | 760 +- drivers/video/aty/radeon_i2c.c | 6 + drivers/video/aty/radeon_monitor.c | 181 +- drivers/video/aty/radeon_pm.c | 2930 +++- drivers/video/aty/radeonfb.h | 241 +- drivers/video/cirrusfb.c | 74 +- drivers/video/console/Kconfig | 51 +- drivers/video/console/Makefile | 12 +- drivers/video/console/dummycon.c | 2 +- drivers/video/console/fbcon.c | 321 +- drivers/video/console/fbcon.h | 10 +- drivers/video/console/mdacon.c | 28 +- drivers/video/console/newport_con.c | 86 +- drivers/video/console/promcon.c | 14 +- drivers/video/console/sticon.c | 12 +- drivers/video/console/sticore.c | 59 +- drivers/video/console/vgacon.c | 37 +- drivers/video/cyber2000fb.c | 23 +- drivers/video/fbmem.c | 194 +- drivers/video/hgafb.c | 18 +- drivers/video/i810/i810_gtf.c | 12 +- drivers/video/imsttfb.c | 21 +- drivers/video/intelfb/intelfbdrv.h | 69 - drivers/video/kyro/fbdev.c | 49 +- drivers/video/logo/logo.c | 7 +- drivers/video/matrox/matroxfb_DAC1064.c | 25 +- drivers/video/matrox/matroxfb_base.c | 90 +- drivers/video/matrox/matroxfb_base.h | 7 +- drivers/video/matrox/matroxfb_crtc2.c | 2 +- drivers/video/modedb.c | 52 +- drivers/video/neofb.c | 61 +- drivers/video/pm2fb.c | 238 +- drivers/video/radeonfb.c | 85 +- drivers/video/riva/fbdev.c | 39 +- drivers/video/sa1100fb.c | 39 +- drivers/video/savage/savagefb.c | 2276 --- drivers/video/sis/300vtbl.h | 185 +- drivers/video/sis/310vtbl.h | 213 +- drivers/video/sis/init.c | 647 +- drivers/video/sis/init.h | 536 +- drivers/video/sis/init301.c | 1339 +- drivers/video/sis/init301.h | 158 +- drivers/video/sis/initdef.h | 26 +- drivers/video/sis/oem300.h | 36 +- drivers/video/sis/oem310.h | 2 +- drivers/video/sis/osdef.h | 25 +- drivers/video/sis/sis.h | 168 +- drivers/video/sis/sis_main.c | 315 +- drivers/video/sis/sis_main.h | 75 +- drivers/video/sis/vgatypes.h | 63 +- drivers/video/sis/vstruct.h | 19 +- drivers/video/skeletonfb.c | 20 +- drivers/video/sstfb.c | 23 +- drivers/video/tdfxfb.c | 182 +- drivers/video/tgafb.c | 6 +- drivers/video/tridentfb.c | 78 +- drivers/video/vesafb.c | 19 +- drivers/video/vfb.c | 16 +- drivers/video/vga16fb.c | 28 +- fs/Kconfig | 161 +- fs/Makefile | 3 +- fs/affs/amigaffs.c | 15 +- fs/affs/bitmap.c | 10 +- fs/affs/inode.c | 24 +- fs/affs/super.c | 20 +- fs/affs/symlink.c | 9 +- fs/afs/cmservice.c | 4 +- fs/afs/vlocation.c | 2 +- fs/aio.c | 80 +- fs/attr.c | 24 +- fs/autofs4/autofs_i.h | 15 +- fs/autofs4/expire.c | 16 +- fs/autofs4/inode.c | 2 + fs/autofs4/root.c | 2 + fs/autofs4/waitq.c | 23 +- fs/bad_inode.c | 19 +- fs/befs/debug.c | 2 + fs/bfs/dir.c | 14 +- fs/binfmt_aout.c | 34 +- fs/binfmt_elf.c | 201 +- fs/binfmt_em86.c | 2 +- fs/binfmt_flat.c | 9 +- fs/binfmt_misc.c | 5 +- fs/binfmt_script.c | 2 +- fs/binfmt_som.c | 5 +- fs/bio.c | 222 +- fs/block_dev.c | 7 +- fs/buffer.c | 149 +- fs/char_dev.c | 30 +- fs/cifs/AUTHORS | 24 +- fs/cifs/CHANGES | 69 +- fs/cifs/README | 63 +- fs/cifs/TODO | 30 +- fs/cifs/asn1.c | 7 +- fs/cifs/cifs_debug.c | 58 +- fs/cifs/cifsfs.c | 128 +- fs/cifs/cifsfs.h | 18 +- fs/cifs/cifsglob.h | 21 +- fs/cifs/cifspdu.h | 152 +- fs/cifs/cifsproto.h | 149 +- fs/cifs/cifssmb.c | 1209 +- fs/cifs/connect.c | 896 +- fs/cifs/dir.c | 192 +- fs/cifs/fcntl.c | 6 +- fs/cifs/file.c | 1955 +-- fs/cifs/inode.c | 846 +- fs/cifs/link.c | 18 +- fs/cifs/misc.c | 175 +- fs/cifs/transport.c | 120 +- fs/coda/cnode.c | 2 +- fs/coda/inode.c | 4 +- fs/coda/psdev.c | 18 +- fs/coda/sysctl.c | 56 +- fs/coda/upcall.c | 8 +- fs/compat.c | 261 +- fs/compat_ioctl.c | 406 +- fs/dcache.c | 111 +- fs/devfs/base.c | 9 +- fs/devpts/inode.c | 61 +- fs/direct-io.c | 40 +- fs/dquot.c | 228 +- fs/eventpoll.c | 6 +- fs/exec.c | 162 +- fs/exportfs/expfs.c | 4 +- fs/ext2/acl.c | 4 +- fs/ext2/acl.h | 2 - fs/ext2/balloc.c | 39 +- fs/ext2/dir.c | 8 +- fs/ext2/ialloc.c | 11 +- fs/ext2/inode.c | 31 +- fs/ext2/ioctl.c | 4 +- fs/ext2/namei.c | 6 +- fs/ext2/super.c | 127 +- fs/ext2/xattr.c | 57 +- fs/ext2/xattr.h | 8 - fs/ext3/acl.c | 10 +- fs/ext3/balloc.c | 180 +- fs/ext3/dir.c | 2 +- fs/ext3/file.c | 16 +- fs/ext3/ialloc.c | 32 +- fs/ext3/inode.c | 304 +- fs/ext3/ioctl.c | 29 +- fs/ext3/namei.c | 23 +- fs/ext3/resize.c | 4 +- fs/ext3/super.c | 288 +- fs/ext3/xattr.c | 1260 +- fs/ext3/xattr.h | 5 +- fs/fat/dir.c | 750 +- fs/fat/fatfs_syms.c | 48 - fs/fat/file.c | 310 +- fs/fat/inode.c | 1170 +- fs/fcntl.c | 44 +- fs/file.c | 27 +- fs/file_table.c | 8 +- fs/fs-writeback.c | 24 +- fs/hfs/catalog.c | 10 +- fs/hfs/inode.c | 37 +- fs/hfs/super.c | 164 +- fs/hfsplus/bnode.c | 23 +- fs/hfsplus/brec.c | 10 +- fs/hfsplus/catalog.c | 47 +- fs/hfsplus/dir.c | 37 +- fs/hfsplus/inode.c | 16 +- fs/hfsplus/ioctl.c | 2 +- fs/hostfs/Makefile | 19 +- fs/hostfs/hostfs.h | 21 + fs/hostfs/hostfs_kern.c | 46 +- fs/hostfs/hostfs_user.c | 5 +- fs/hpfs/alloc.c | 4 +- fs/hpfs/hpfs.h | 12 +- fs/hpfs/hpfs_fn.h | 8 +- fs/hpfs/inode.c | 2 +- fs/hpfs/super.c | 6 +- fs/hppfs/Makefile | 10 - fs/hugetlbfs/inode.c | 15 +- fs/inode.c | 150 +- fs/ioctl.c | 109 +- fs/isofs/compress.c | 22 +- fs/isofs/dir.c | 13 +- fs/isofs/inode.c | 19 +- fs/isofs/namei.c | 13 +- fs/isofs/rock.c | 8 +- fs/jbd/commit.c | 179 +- fs/jbd/journal.c | 47 +- fs/jbd/transaction.c | 117 +- fs/jffs/inode-v23.c | 18 +- fs/jffs/intrep.c | 60 +- fs/jffs/jffs_fm.c | 12 +- fs/jffs2/Makefile | 3 +- fs/jffs2/background.c | 11 +- fs/jffs2/build.c | 53 +- fs/jffs2/compr.c | 12 +- fs/jffs2/compr_rtime.c | 12 +- fs/jffs2/compr_rubin.c | 18 +- fs/jffs2/compr_zlib.c | 16 +- fs/jffs2/erase.c | 15 +- fs/jffs2/file.c | 22 +- fs/jffs2/fs.c | 37 +- fs/jffs2/gc.c | 10 +- fs/jffs2/ioctl.c | 4 +- fs/jffs2/malloc.c | 4 +- fs/jffs2/nodelist.c | 42 +- fs/jffs2/nodelist.h | 40 +- fs/jffs2/nodemgmt.c | 80 +- fs/jffs2/os-linux.h | 29 +- fs/jffs2/read.c | 6 +- fs/jffs2/readinode.c | 10 +- fs/jffs2/scan.c | 15 +- fs/jffs2/super.c | 9 +- fs/jffs2/symlink.c | 4 +- fs/jffs2/wbuf.c | 165 +- fs/jffs2/write.c | 4 +- fs/jffs2/writev.c | 4 +- fs/jfs/acl.c | 3 +- fs/jfs/jfs_defragfs.h | 51 - fs/jfs/jfs_dmap.c | 12 +- fs/jfs/jfs_dtree.c | 10 +- fs/jfs/jfs_filsys.h | 1 + fs/jfs/jfs_imap.c | 80 +- fs/jfs/jfs_incore.h | 7 +- fs/jfs/jfs_inode.c | 2 + fs/jfs/jfs_logmgr.c | 159 +- fs/jfs/jfs_logmgr.h | 9 +- fs/jfs/jfs_metapage.c | 931 +- fs/jfs/jfs_metapage.h | 80 +- fs/jfs/jfs_mount.c | 5 - fs/jfs/jfs_txnmgr.c | 217 +- fs/jfs/jfs_umount.c | 16 +- fs/jfs/jfs_xtree.c | 63 +- fs/jfs/namei.c | 4 +- fs/jfs/super.c | 71 +- fs/jfs/xattr.c | 59 +- fs/libfs.c | 18 +- fs/lockd/clntproc.c | 31 +- fs/lockd/mon.c | 4 +- fs/lockd/svc.c | 49 +- fs/lockd/svclock.c | 1 - fs/locks.c | 88 +- fs/mbcache.c | 43 +- fs/mpage.c | 138 +- fs/namei.c | 362 +- fs/namespace.c | 136 +- fs/ncpfs/ncplib_kernel.c | 2 +- fs/nfs/dir.c | 442 +- fs/nfs/direct.c | 425 +- fs/nfs/file.c | 159 +- fs/nfs/idmap.c | 4 +- fs/nfs/inode.c | 158 +- fs/nfs/nfs4proc.c | 604 +- fs/nfs/nfs4state.c | 88 +- fs/nfs/nfs4xdr.c | 26 +- fs/nfs/nfsroot.c | 8 +- fs/nfs/proc.c | 72 +- fs/nfs/read.c | 21 +- fs/nfs/unlink.c | 12 +- fs/nfs/write.c | 47 +- fs/nfsd/auth.c | 8 +- fs/nfsd/export.c | 27 +- fs/nfsd/lockd.c | 2 +- fs/nfsd/nfs3xdr.c | 27 +- fs/nfsd/nfs4proc.c | 162 +- fs/nfsd/nfs4state.c | 1151 +- fs/nfsd/nfs4xdr.c | 346 +- fs/nfsd/nfsctl.c | 103 +- fs/nfsd/nfsfh.c | 11 +- fs/nfsd/nfsproc.c | 8 +- fs/nfsd/nfssvc.c | 96 +- fs/nfsd/nfsxdr.c | 6 +- fs/nfsd/vfs.c | 137 +- fs/ntfs/ChangeLog | 7 + fs/ntfs/aops.c | 2 +- fs/ntfs/compress.c | 2 +- fs/ntfs/debug.c | 10 +- fs/ntfs/mft.c | 3 +- fs/ntfs/super.c | 2 + fs/open.c | 37 +- fs/openpromfs/inode.c | 1 + fs/partitions/Kconfig | 6 +- fs/partitions/check.c | 8 +- fs/partitions/ibm.c | 3 +- fs/pipe.c | 231 +- fs/posix_acl.c | 6 +- fs/proc/Makefile | 4 +- fs/proc/array.c | 80 +- fs/proc/base.c | 403 +- fs/proc/generic.c | 7 +- fs/proc/inode.c | 50 +- fs/proc/kcore.c | 24 +- fs/proc/proc_misc.c | 131 +- fs/proc/proc_tty.c | 4 +- fs/proc/task_mmu.c | 141 +- fs/qnx4/inode.c | 10 +- fs/quota.c | 150 +- fs/quota_v2.c | 230 +- fs/ramfs/inode.c | 5 +- fs/read_write.c | 74 +- fs/readdir.c | 4 +- fs/reiserfs/bitmap.c | 21 +- fs/reiserfs/dir.c | 12 +- fs/reiserfs/do_balan.c | 6 +- fs/reiserfs/file.c | 33 +- fs/reiserfs/fix_node.c | 7 +- fs/reiserfs/ibalance.c | 4 +- fs/reiserfs/inode.c | 96 +- fs/reiserfs/ioctl.c | 8 +- fs/reiserfs/item_ops.c | 15 +- fs/reiserfs/journal.c | 44 +- fs/reiserfs/namei.c | 107 +- fs/reiserfs/objectid.c | 18 +- fs/reiserfs/prints.c | 75 +- fs/reiserfs/procfs.c | 4 +- fs/reiserfs/stree.c | 152 +- fs/reiserfs/super.c | 513 +- fs/reiserfs/xattr.c | 14 +- fs/select.c | 15 +- fs/smbfs/ChangeLog | 160 - fs/smbfs/file.c | 7 +- fs/smbfs/inode.c | 5 +- fs/smbfs/proc.c | 11 +- fs/smbfs/proto.h | 8 +- fs/smbfs/request.c | 6 +- fs/smbfs/smbiod.c | 2 +- fs/super.c | 20 +- fs/sysfs/bin.c | 27 +- fs/sysfs/dir.c | 2 +- fs/sysfs/file.c | 52 +- fs/sysfs/inode.c | 8 +- fs/sysfs/mount.c | 20 +- fs/sysfs/sysfs.h | 3 +- fs/sysv/itree.c | 6 +- fs/udf/namei.c | 12 +- fs/udf/super.c | 5 +- fs/umsdos/Makefile | 13 - fs/umsdos/README-WIP.txt | 114 - fs/umsdos/dir.c | 810 - fs/umsdos/emd.c | 660 - fs/umsdos/inode.c | 483 - fs/umsdos/ioctl.c | 446 - fs/umsdos/mangle.c | 522 - fs/umsdos/namei.c | 1124 -- fs/umsdos/rdir.c | 248 - fs/umsdos/specs | 289 - fs/xfs/Makefile | 3 +- fs/xfs/linux-2.6/xfs_ioctl.c | 243 +- fs/xfs/linux-2.6/xfs_iops.c | 37 +- fs/xfs/linux-2.6/xfs_linux.h | 1 + fs/xfs/linux-2.6/xfs_lrw.c | 14 +- fs/xfs/linux-2.6/xfs_super.c | 116 +- fs/xfs/linux-2.6/xfs_sysctl.c | 28 +- fs/xfs/linux-2.6/xfs_vnode.c | 13 +- fs/xfs/linux-2.6/xfs_vnode.h | 5 +- fs/xfs/quota/xfs_qm_syscalls.c | 6 +- fs/xfs/xfs_acl.c | 45 +- fs/xfs/xfs_arch.h | 159 +- fs/xfs/xfs_attr.c | 2 +- fs/xfs/xfs_bmap.c | 2 +- fs/xfs/xfs_bmap_btree.c | 4 +- fs/xfs/xfs_bmap_btree.h | 4 +- fs/xfs/xfs_clnt.h | 7 +- fs/xfs/xfs_da_btree.c | 42 +- fs/xfs/xfs_dinode.h | 162 +- fs/xfs/xfs_fs.h | 3 +- fs/xfs/xfs_fsops.c | 18 +- fs/xfs/xfs_inode.c | 117 +- fs/xfs/xfs_inode.h | 24 +- fs/xfs/xfs_iomap.c | 30 +- fs/xfs/xfs_itable.c | 278 +- fs/xfs/xfs_log.c | 68 +- fs/xfs/xfs_log_recover.c | 40 +- fs/xfs/xfs_mount.c | 28 +- fs/xfs/xfs_mount.h | 31 +- fs/xfs/xfs_vfsops.c | 109 +- fs/xfs/xfs_vnodeops.c | 73 +- include/acpi/acpi_drivers.h | 5 +- include/acpi/acpiosxf.h | 2 +- include/acpi/actbl2.h | 83 +- include/acpi/platform/aclinux.h | 4 +- include/asm-alpha/bitops.h | 14 +- include/asm-alpha/cacheflush.h | 2 +- include/asm-alpha/io.h | 11 + include/asm-alpha/page.h | 3 + include/asm-alpha/pgalloc.h | 4 +- include/asm-alpha/pgtable.h | 23 +- include/asm-alpha/resource.h | 46 +- include/asm-alpha/signal.h | 25 +- include/asm-alpha/spinlock.h | 94 +- include/asm-alpha/system.h | 2 + include/asm-alpha/uaccess.h | 11 +- include/asm-alpha/unistd.h | 7 +- include/asm-arm/arch-integrator/platform.h | 112 +- include/asm-arm/arch-lh7a40x/memory.h | 2 + include/asm-arm/arch-omap/clocks.h | 216 - include/asm-arm/arch-omap/dma.h | 4 + include/asm-arm/arch-omap/hardware.h | 110 +- include/asm-arm/arch-omap/memory.h | 4 +- include/asm-arm/arch-omap/mux.h | 32 +- include/asm-arm/arch-pxa/irqs.h | 32 + include/asm-arm/arch-pxa/memory.h | 2 - include/asm-arm/arch-pxa/pxa-regs.h | 103 +- include/asm-arm/arch-s3c2410/memory.h | 8 +- include/asm-arm/arch-s3c2410/regs-serial.h | 17 +- include/asm-arm/atomic.h | 1 + include/asm-arm/cacheflush.h | 20 +- include/asm-arm/dma-mapping.h | 22 + include/asm-arm/ecard.h | 15 +- include/asm-arm/hardware/sa1111.h | 8 +- include/asm-arm/mach/arch.h | 2 +- include/asm-arm/page.h | 18 +- include/asm-arm/pgtable.h | 52 +- include/asm-arm/processor.h | 11 +- include/asm-arm/resource.h | 47 +- include/asm-arm/spinlock.h | 8 + include/asm-arm/system.h | 5 + include/asm-arm/thread_info.h | 8 +- include/asm-arm/tlb.h | 42 +- include/asm-arm/uaccess.h | 3 +- include/asm-arm/unistd.h | 53 +- include/asm-arm26/atomic.h | 109 +- include/asm-arm26/cacheflush.h | 2 +- include/asm-arm26/calls.h | 262 - include/asm-arm26/ian_char.h | 79 - include/asm-arm26/pgtable.h | 19 +- include/asm-arm26/resource.h | 47 +- include/asm-arm26/tlb.h | 23 +- include/asm-arm26/uaccess.h | 40 +- include/asm-arm26/unistd.h | 321 +- include/asm-cris/cacheflush.h | 2 +- include/asm-cris/io.h | 11 + include/asm-cris/page.h | 7 +- include/asm-cris/pgtable.h | 8 +- include/asm-cris/resource.h | 47 +- include/asm-cris/uaccess.h | 3 +- include/asm-cris/unistd.h | 2 +- include/asm-generic/bug.h | 8 +- include/asm-generic/netdump.h | 61 - include/asm-generic/pgtable.h | 159 +- include/asm-generic/siginfo.h | 19 +- include/asm-generic/tlb.h | 13 +- include/asm-h8300/bitops.h | 2 +- include/asm-h8300/cacheflush.h | 2 +- include/asm-h8300/hardirq.h | 11 - include/asm-h8300/io.h | 11 + include/asm-h8300/page.h | 7 +- include/asm-h8300/pgtable.h | 9 + include/asm-h8300/processor.h | 5 - include/asm-h8300/resource.h | 47 +- include/asm-h8300/thread_info.h | 1 + include/asm-h8300/uaccess.h | 3 +- include/asm-h8300/unistd.h | 305 +- include/asm-i386/acpi.h | 7 - include/asm-i386/agp.h | 10 + include/asm-i386/apic.h | 1 - include/asm-i386/cacheflush.h | 2 +- include/asm-i386/checksum.h | 18 +- include/asm-i386/cpu.h | 18 +- include/asm-i386/cpufeature.h | 6 +- include/asm-i386/desc.h | 15 +- include/asm-i386/dma-mapping.h | 2 +- include/asm-i386/elf.h | 12 +- include/asm-i386/fixmap.h | 4 +- include/asm-i386/highmem.h | 23 +- include/asm-i386/hpet.h | 3 +- include/asm-i386/i387.h | 6 - include/asm-i386/mach-numaq/mach_apic.h | 11 +- include/asm-i386/mmzone.h | 7 - include/asm-i386/module.h | 2 + include/asm-i386/mpspec.h | 1 - include/asm-i386/msr.h | 15 + include/asm-i386/netdump.h | 100 - include/asm-i386/page.h | 15 +- include/asm-i386/param.h | 10 - include/asm-i386/pgalloc.h | 21 +- include/asm-i386/pgtable-2level.h | 36 +- include/asm-i386/pgtable-3level.h | 35 +- include/asm-i386/pgtable.h | 42 +- include/asm-i386/processor.h | 46 +- include/asm-i386/resource.h | 48 +- include/asm-i386/segment.h | 5 +- include/asm-i386/setup.h | 2 +- include/asm-i386/signal.h | 38 +- include/asm-i386/smp.h | 7 +- include/asm-i386/spinlock.h | 44 +- include/asm-i386/string.h | 124 +- include/asm-i386/suspend.h | 12 +- include/asm-i386/system.h | 9 +- include/asm-i386/thread_info.h | 8 +- include/asm-i386/timer.h | 1 + include/asm-i386/timex.h | 2 - include/asm-i386/uaccess.h | 68 +- include/asm-i386/unistd.h | 2 +- include/asm-ia64/acpi.h | 2 +- include/asm-ia64/cacheflush.h | 2 +- include/asm-ia64/gcc_intrin.h | 10 +- include/asm-ia64/ioctl32.h | 1 - include/asm-ia64/iosapic.h | 4 + include/asm-ia64/machvec.h | 41 +- include/asm-ia64/machvec_sn2.h | 10 +- include/asm-ia64/netdump.h | 6 - include/asm-ia64/page.h | 15 +- include/asm-ia64/pal.h | 88 +- include/asm-ia64/pci.h | 23 +- include/asm-ia64/pgalloc.h | 164 +- include/asm-ia64/pgtable.h | 76 +- include/asm-ia64/processor.h | 28 +- include/asm-ia64/resource.h | 54 +- include/asm-ia64/signal.h | 23 +- include/asm-ia64/smp.h | 50 +- include/asm-ia64/sn/addrs.h | 382 +- include/asm-ia64/sn/arch.h | 44 +- include/asm-ia64/sn/bte.h | 53 +- include/asm-ia64/sn/fetchop.h | 85 - include/asm-ia64/sn/geo.h | 45 +- include/asm-ia64/sn/klconfig.h | 2 +- include/asm-ia64/sn/leds.h | 1 + include/asm-ia64/sn/nodepda.h | 21 +- include/asm-ia64/sn/pda.h | 26 +- include/asm-ia64/sn/router.h | 618 - include/asm-ia64/sn/rw_mmr.h | 9 +- include/asm-ia64/sn/sn_cpuid.h | 36 +- include/asm-ia64/sn/sn_fru.h | 44 - include/asm-ia64/sn/sn_sal.h | 264 +- include/asm-ia64/sn/sndrv.h | 47 - include/asm-ia64/sn/types.h | 3 +- include/asm-ia64/spinlock.h | 11 +- include/asm-ia64/system.h | 4 + include/asm-ia64/thread_info.h | 19 +- include/asm-ia64/tlb.h | 11 +- include/asm-ia64/uaccess.h | 42 +- include/asm-ia64/unistd.h | 19 +- include/asm-m68k/adb_mouse.h | 23 - include/asm-m68k/atari_SCCserial.h | 67 - include/asm-m68k/cacheflush.h | 15 +- include/asm-m68k/checksum.h | 52 +- include/asm-m68k/io.h | 14 + include/asm-m68k/ipc.h | 32 +- include/asm-m68k/motorola_pgtable.h | 2 +- include/asm-m68k/pgtable.h | 12 +- include/asm-m68k/resource.h | 47 +- include/asm-m68k/setup.h | 8 +- include/asm-m68k/signal.h | 30 +- include/asm-m68k/thread_info.h | 7 + include/asm-m68k/uaccess.h | 5 +- include/asm-m68k/unistd.h | 2 +- include/asm-m68knommu/atomic.h | 74 +- include/asm-m68knommu/bitops.h | 263 +- include/asm-m68knommu/cacheflush.h | 2 +- include/asm-m68knommu/io_hw_swap.h | 113 - include/asm-m68knommu/keyboard.h | 1 - include/asm-m68knommu/nap.h | 96 - include/asm-m68knommu/page.h | 12 +- include/asm-m68knommu/pgtable.h | 9 + include/asm-m68knommu/semp3.h | 60 - include/asm-m68knommu/uaccess.h | 3 +- include/asm-m68knommu/unistd.h | 2 +- include/asm-mips/bootinfo.h | 1 + include/asm-mips/cacheflush.h | 5 +- include/asm-mips/checksum.h | 10 +- include/asm-mips/hazards.h | 85 +- include/asm-mips/it8172/it8172_lpc.h | 29 - include/asm-mips/mach-au1x00/au1000.h | 2 + include/asm-mips/mach-db1x00/db1x00.h | 3 + include/asm-mips/mach-generic/ide.h | 82 +- include/asm-mips/mipsregs.h | 103 +- include/asm-mips/mmu_context.h | 28 +- include/asm-mips/ng1.h | 55 - include/asm-mips/ng1hw.h | 219 - include/asm-mips/pci.h | 11 +- include/asm-mips/pgtable-32.h | 4 +- include/asm-mips/pgtable-64.h | 2 +- include/asm-mips/pgtable.h | 34 +- include/asm-mips/processor.h | 11 - include/asm-mips/resource.h | 57 +- include/asm-mips/spinlock.h | 11 +- include/asm-mips/stackframe.h | 20 +- include/asm-mips/system.h | 2 + include/asm-mips/thread_info.h | 1 + include/asm-mips/uaccess.h | 38 +- include/asm-mips/unistd.h | 12 +- include/asm-mips/vr41xx/vr41xx.h | 117 +- include/asm-mips/vr41xx/vrc4171.h | 43 - include/asm-mips/vr41xx/vrc4173.h | 2 + include/asm-parisc/bitops.h | 8 +- include/asm-parisc/bootdata.h | 16 - include/asm-parisc/cache.h | 1 + include/asm-parisc/cacheflush.h | 29 +- include/asm-parisc/checksum.h | 10 +- include/asm-parisc/dma-mapping.h | 2 +- include/asm-parisc/hardware.h | 6 +- include/asm-parisc/ide.h | 10 +- include/asm-parisc/module.h | 4 + include/asm-parisc/parport_gsc.h | 193 - include/asm-parisc/pdc.h | 15 +- include/asm-parisc/pgalloc.h | 9 +- include/asm-parisc/pgtable.h | 41 +- include/asm-parisc/processor.h | 3 - include/asm-parisc/resource.h | 48 +- include/asm-parisc/spinlock.h | 7 +- include/asm-parisc/system.h | 7 +- include/asm-parisc/uaccess.h | 30 +- include/asm-parisc/unistd.h | 7 +- include/asm-ppc/cacheflush.h | 2 +- include/asm-ppc/ibm44x.h | 158 +- include/asm-ppc/ibm4xx.h | 4 + include/asm-ppc/io.h | 54 +- include/asm-ppc/irq.h | 180 +- include/asm-ppc/machdep.h | 9 + include/asm-ppc/mmu.h | 54 +- include/asm-ppc/mpc10x.h | 8 +- include/asm-ppc/mpc8260.h | 4 +- include/asm-ppc/mv64x60.h | 345 + include/asm-ppc/mv64x60_defs.h | 973 ++ include/asm-ppc/ocp.h | 2 +- include/asm-ppc/page.h | 2 + include/asm-ppc/pci.h | 9 +- include/asm-ppc/pgtable.h | 195 +- include/asm-ppc/pmac_feature.h | 37 +- include/asm-ppc/ppcboot.h | 6 +- include/asm-ppc/processor.h | 8 +- include/asm-ppc/reg.h | 97 +- include/asm-ppc/reg_booke.h | 75 +- include/asm-ppc/resource.h | 44 +- include/asm-ppc/serial.h | 8 + include/asm-ppc/setup.h | 9 +- include/asm-ppc/smp.h | 1 - include/asm-ppc/spinlock.h | 49 +- include/asm-ppc/system.h | 7 +- include/asm-ppc/thread_info.h | 7 + include/asm-ppc/uaccess.h | 31 +- include/asm-ppc/uninorth.h | 56 +- include/asm-ppc/unistd.h | 23 +- include/asm-ppc64/cacheflush.h | 5 +- include/asm-ppc64/cputable.h | 62 +- include/asm-ppc64/eeh.h | 49 +- include/asm-ppc64/hardirq.h | 1 - include/asm-ppc64/iSeries/ItLpPaca.h | 134 - include/asm-ppc64/iSeries/iSeries_VpdInfo.h | 56 - include/asm-ppc64/iSeries/iSeries_fixup.h | 25 - include/asm-ppc64/io.h | 15 +- include/asm-ppc64/iommu.h | 19 +- include/asm-ppc64/ipc.h | 35 +- include/asm-ppc64/irq.h | 2 + include/asm-ppc64/machdep.h | 35 +- include/asm-ppc64/mmu.h | 212 +- include/asm-ppc64/mmu_context.h | 97 +- include/asm-ppc64/naca.h | 24 +- include/asm-ppc64/netdump.h | 6 - include/asm-ppc64/paca.h | 15 +- include/asm-ppc64/page.h | 68 +- include/asm-ppc64/pci-bridge.h | 31 +- include/asm-ppc64/pci.h | 137 +- include/asm-ppc64/pgalloc.h | 33 +- include/asm-ppc64/pgtable.h | 267 +- include/asm-ppc64/processor.h | 238 +- include/asm-ppc64/prom.h | 51 +- include/asm-ppc64/resource.h | 53 +- include/asm-ppc64/rtas.h | 5 +- include/asm-ppc64/signal.h | 33 +- include/asm-ppc64/smp.h | 11 +- include/asm-ppc64/spinlock.h | 28 +- include/asm-ppc64/system.h | 3 +- include/asm-ppc64/systemcfg.h | 30 +- include/asm-ppc64/thread_info.h | 15 +- include/asm-ppc64/time.h | 15 +- include/asm-ppc64/uaccess.h | 34 +- include/asm-ppc64/unistd.h | 6 +- include/asm-ppc64/vio.h | 27 +- include/asm-s390/atomic.h | 4 + include/asm-s390/cacheflush.h | 2 +- include/asm-s390/debug.h | 2 +- include/asm-s390/netdump.h | 6 - include/asm-s390/page.h | 5 + include/asm-s390/pgalloc.h | 7 +- include/asm-s390/pgtable.h | 51 +- include/asm-s390/processor.h | 4 +- include/asm-s390/resource.h | 47 +- include/asm-s390/smp.h | 25 + include/asm-s390/spinlock.h | 20 +- include/asm-s390/thread_info.h | 1 + include/asm-s390/uaccess.h | 12 +- include/asm-s390/unistd.h | 16 +- include/asm-sh/checksum.h | 14 +- include/asm-sh/cpu-sh2/cacheflush.h | 4 +- include/asm-sh/cpu-sh3/cacheflush.h | 6 +- include/asm-sh/cpu-sh4/cacheflush.h | 2 +- include/asm-sh/dma-mapping.h | 1 - include/asm-sh/irq.h | 3 +- include/asm-sh/mc146818rtc.h | 1 + include/asm-sh/pgalloc.h | 9 +- include/asm-sh/pgtable.h | 15 +- include/asm-sh/processor.h | 6 - include/asm-sh/resource.h | 47 +- include/asm-sh/spinlock.h | 13 +- include/asm-sh/uaccess.h | 3 +- include/asm-sh/unistd.h | 2 +- include/asm-sparc/bitops.h | 8 +- include/asm-sparc/bug.h | 3 + include/asm-sparc/cacheflush.h | 14 +- include/asm-sparc/checksum.h | 14 +- include/asm-sparc/hardirq.h | 9 - include/asm-sparc/ipc.h | 33 +- include/asm-sparc/pgtable.h | 23 +- include/asm-sparc/pgtsrmmu.h | 1 + include/asm-sparc/processor.h | 6 - include/asm-sparc/resource.h | 44 +- include/asm-sparc/sbus.h | 2 + include/asm-sparc/signal.h | 19 +- include/asm-sparc/spinlock.h | 25 +- include/asm-sparc/system.h | 10 +- include/asm-sparc/thread_info.h | 1 + include/asm-sparc/uaccess.h | 22 +- include/asm-sparc/unistd.h | 9 +- include/asm-sparc64/atomic.h | 62 +- include/asm-sparc64/bitops.h | 46 +- include/asm-sparc64/bug.h | 3 + include/asm-sparc64/cacheflush.h | 41 +- include/asm-sparc64/checksum.h | 51 +- include/asm-sparc64/compat.h | 106 +- include/asm-sparc64/hardirq.h | 9 - include/asm-sparc64/ide.h | 10 +- include/asm-sparc64/io.h | 15 +- include/asm-sparc64/iommu.h | 2 + include/asm-sparc64/page.h | 32 +- include/asm-sparc64/pci.h | 5 +- include/asm-sparc64/pgalloc.h | 101 +- include/asm-sparc64/pgtable.h | 104 +- include/asm-sparc64/resource.h | 46 +- include/asm-sparc64/siginfo.h | 35 +- include/asm-sparc64/signal.h | 24 +- include/asm-sparc64/spinlock.h | 55 +- include/asm-sparc64/thread_info.h | 1 + include/asm-sparc64/tlb.h | 13 +- include/asm-sparc64/uaccess.h | 16 +- include/asm-sparc64/unistd.h | 9 +- include/asm-um/arch-signal-i386.h | 24 - include/asm-um/archparam-i386.h | 141 - include/asm-um/common.lds.S | 9 +- include/asm-um/elf.h | 31 - include/asm-um/fixmap.h | 10 +- include/asm-um/page.h | 115 +- include/asm-um/pgalloc.h | 24 +- include/asm-um/pgtable.h | 241 +- include/asm-um/processor-generic.h | 17 +- include/asm-um/processor-i386.h | 21 +- include/asm-um/system-i386.h | 2 + include/asm-um/thread_info.h | 14 +- include/asm-um/timex.h | 2 - include/asm-um/uaccess.h | 4 +- include/asm-um/unistd.h | 106 +- include/asm-v850/cacheflush.h | 2 +- include/asm-v850/pgtable.h | 2 + include/asm-v850/resource.h | 47 +- include/asm-v850/uaccess.h | 3 +- include/asm-v850/unistd.h | 2 +- include/asm-x86_64/acpi.h | 5 +- include/asm-x86_64/agp.h | 10 + include/asm-x86_64/apicdef.h | 2 +- include/asm-x86_64/bitops.h | 8 +- include/asm-x86_64/bootsetup.h | 3 +- include/asm-x86_64/cacheflush.h | 3 +- include/asm-x86_64/checksum.h | 8 +- include/asm-x86_64/compat.h | 5 + include/asm-x86_64/floppy.h | 2 +- include/asm-x86_64/hw_irq.h | 2 - include/asm-x86_64/i387.h | 10 - include/asm-x86_64/ia32.h | 8 +- include/asm-x86_64/ia32_unistd.h | 6 +- include/asm-x86_64/io.h | 41 +- include/asm-x86_64/ioctl32.h | 1 - include/asm-x86_64/ipc.h | 6 - include/asm-x86_64/mmu_context.h | 14 +- include/asm-x86_64/mpspec.h | 3 +- include/asm-x86_64/msr.h | 24 +- include/asm-x86_64/netdump.h | 6 - include/asm-x86_64/page.h | 23 +- include/asm-x86_64/pgalloc.h | 52 +- include/asm-x86_64/pgtable.h | 171 +- include/asm-x86_64/processor.h | 25 +- include/asm-x86_64/ptrace.h | 5 + include/asm-x86_64/resource.h | 47 +- include/asm-x86_64/signal.h | 28 +- include/asm-x86_64/smp.h | 32 +- include/asm-x86_64/spinlock.h | 23 +- include/asm-x86_64/suspend.h | 1 - include/asm-x86_64/timex.h | 2 - include/asm-x86_64/topology.h | 13 +- include/asm-x86_64/uaccess.h | 37 +- include/asm-x86_64/unistd.h | 22 +- include/linux/acct.h | 4 + include/linux/acpi.h | 45 +- include/linux/affs_fs.h | 89 - include/linux/affs_fs_i.h | 59 - include/linux/affs_fs_sb.h | 57 - include/linux/ata.h | 2 + include/linux/atmdev.h | 32 +- include/linux/audit.h | 118 +- include/linux/auto_fs4.h | 2 +- include/linux/backing-dev.h | 41 +- include/linux/binfmts.h | 10 +- include/linux/bio.h | 11 +- include/linux/bitmap.h | 8 +- include/linux/blk.h | 2 - include/linux/blkdev.h | 45 +- include/linux/bootmem.h | 19 +- include/linux/buffer_head.h | 5 +- include/linux/capability.h | 8 +- include/linux/cdrom.h | 2 - include/linux/compat.h | 16 +- include/linux/compat_ioctl.h | 6 + include/linux/compiler-gcc+.h | 16 - include/linux/compiler-gcc3.h | 10 +- include/linux/compiler.h | 18 +- include/linux/console.h | 10 +- include/linux/cpu.h | 3 + include/linux/cpufreq.h | 71 +- include/linux/cpumask.h | 38 +- include/linux/crypto.h | 11 + include/linux/cyclades.h | 2 +- include/linux/dcache.h | 45 +- include/linux/delay.h | 1 + include/linux/device.h | 19 +- include/linux/devpts_fs.h | 3 +- include/linux/dp83840.h | 41 - include/linux/dtlk.h | 2 +- include/linux/dvb/osd.h | 9 +- include/linux/dvb/video.h | 65 +- include/linux/edd.h | 2 +- include/linux/efi.h | 23 +- include/linux/elevator.h | 3 + include/linux/elf.h | 7 +- include/linux/ext2_fs.h | 1 + include/linux/ext3_fs.h | 19 +- include/linux/ext3_fs_i.h | 46 +- include/linux/ext3_jbd.h | 25 +- include/linux/fb.h | 38 +- include/linux/file.h | 4 +- include/linux/fs.h | 241 +- include/linux/gameport.h | 151 +- include/linux/generic_serial.h | 2 +- include/linux/gfp.h | 49 +- include/linux/hayesesp.h | 4 +- include/linux/highmem.h | 17 +- include/linux/hugetlb.h | 10 +- include/linux/i2c-id.h | 33 +- include/linux/i2c.h | 84 +- include/linux/i2o.h | 30 +- include/linux/ide.h | 147 +- include/linux/if.h | 2 +- include/linux/if_pppox.h | 19 +- include/linux/if_shaper.h | 2 +- include/linux/inetdevice.h | 2 + include/linux/init.h | 4 +- include/linux/init_task.h | 22 +- include/linux/interrupt.h | 34 +- include/linux/ip.h | 53 +- include/linux/ipmi.h | 63 - include/linux/ipmi_smi.h | 11 +- include/linux/irq.h | 6 +- include/linux/iso_fs.h | 147 - include/linux/iso_fs_i.h | 27 - include/linux/iso_fs_sb.h | 34 - include/linux/ixjuser.h | 2 - include/linux/jbd.h | 29 +- include/linux/jffs2.h | 4 +- include/linux/jiffies.h | 8 + include/linux/kernel.h | 49 +- include/linux/kernel_stat.h | 20 +- include/linux/kobject.h | 5 + include/linux/libata.h | 129 +- include/linux/lockd/lockd.h | 2 - include/linux/major.h | 1 + include/linux/mbcache.h | 35 +- include/linux/mca.h | 14 +- include/linux/miscdevice.h | 5 +- include/linux/mm.h | 119 +- include/linux/mmzone.h | 50 +- include/linux/module.h | 38 +- include/linux/moduleparam.h | 22 +- include/linux/mount.h | 6 +- include/linux/msdos_fs.h | 302 +- include/linux/msdos_fs_i.h | 29 - include/linux/msdos_fs_sb.h | 60 - include/linux/mtd/cfi.h | 14 +- include/linux/mtd/doc2000.h | 6 +- include/linux/mtd/flashchip.h | 4 +- include/linux/mtd/gen_probe.h | 2 +- include/linux/mtd/map.h | 4 +- include/linux/mtd/nand.h | 8 +- include/linux/namei.h | 4 +- include/linux/net.h | 47 +- include/linux/netdevice.h | 34 +- include/linux/netfilter.h | 42 +- include/linux/netfilter_arp/arp_tables.h | 8 +- .../linux/netfilter_ipv4/compat_firewall.h | 45 - include/linux/netfilter_ipv4/ip_conntrack.h | 192 +- .../linux/netfilter_ipv4/ip_conntrack_tuple.h | 10 +- include/linux/netfilter_ipv4/ip_tables.h | 67 +- include/linux/netfilter_ipv4/ipchains_core.h | 189 - include/linux/netfilter_ipv4/ipfwadm_core.h | 256 - include/linux/netfilter_ipv6/ip6_tables.h | 8 +- include/linux/netlink.h | 10 +- include/linux/netpoll.h | 40 +- include/linux/nfs_fs.h | 82 +- include/linux/nfsd/nfsd.h | 17 +- include/linux/nfsd/state.h | 49 +- include/linux/nfsd/syscall.h | 19 + include/linux/nfsd/xdr4.h | 24 +- include/linux/notifier.h | 1 + include/linux/oprofile.h | 20 +- include/linux/page-flags.h | 52 +- include/linux/pagemap.h | 10 +- include/linux/parport.h | 12 +- include/linux/pci.h | 68 +- include/linux/pci_ids.h | 232 +- include/linux/percpu.h | 2 +- include/linux/personality.h | 7 +- include/linux/pkt_cls.h | 112 +- include/linux/pkt_sched.h | 9 +- include/linux/pm.h | 113 +- include/linux/poll.h | 10 +- include/linux/posix-timers.h | 93 +- include/linux/posix_acl.h | 6 +- include/linux/prctl.h | 1 + include/linux/proc_fs.h | 5 - include/linux/quota.h | 3 +- include/linux/quotaops.h | 2 +- include/linux/raid/linear.h | 7 +- include/linux/raid/raid5.h | 2 + include/linux/random.h | 15 +- include/linux/rcupdate.h | 37 +- include/linux/reiserfs_fs.h | 297 +- include/linux/reiserfs_fs_i.h | 5 +- include/linux/reiserfs_fs_sb.h | 5 +- include/linux/rtnetlink.h | 23 +- include/linux/sched.h | 251 +- include/linux/security.h | 120 +- include/linux/selection.h | 23 +- include/linux/serial.h | 6 +- include/linux/serialP.h | 8 +- include/linux/serial_core.h | 39 + include/linux/serio.h | 106 +- include/linux/signal.h | 20 +- include/linux/skbuff.h | 153 +- include/linux/slab.h | 33 +- include/linux/smp_lock.h | 14 +- include/linux/socket.h | 3 +- include/linux/sockios.h | 2 +- include/linux/spinlock.h | 82 +- include/linux/sunrpc/auth.h | 23 +- include/linux/sunrpc/cache.h | 24 +- include/linux/sunrpc/clnt.h | 2 +- include/linux/sunrpc/gss_api.h | 14 +- include/linux/sunrpc/gss_asn1.h | 2 - include/linux/sunrpc/svcauth.h | 16 +- include/linux/sunrpc/xprt.h | 6 +- include/linux/suspend.h | 44 +- include/linux/swap.h | 2 +- include/linux/syscalls.h | 5 +- include/linux/sysctl.h | 42 +- include/linux/sysfs.h | 13 + include/linux/sysrq.h | 14 +- include/linux/tcp.h | 98 +- include/linux/time.h | 3 + include/linux/timex.h | 2 - include/linux/tpqic02.h | 738 - include/linux/umsdos_fs.h | 182 - include/linux/umsdos_fs.p | 100 - include/linux/umsdos_fs_i.h | 58 - include/linux/usb.h | 125 +- include/linux/usbdevice_fs.h | 23 +- include/linux/videodev2.h | 147 +- include/linux/videotext.h | 85 +- include/linux/vmalloc.h | 5 +- include/linux/vs_context.h | 95 +- include/linux/vs_limit.h | 103 +- include/linux/vs_memory.h | 61 +- include/linux/vs_network.h | 122 +- include/linux/vs_sched.h | 23 + include/linux/vserver/context.h | 38 +- include/linux/vserver/context_cmd.h | 8 +- include/linux/vserver/cvirt.h | 7 + include/linux/vserver/cvirt_cmd.h | 29 +- include/linux/vserver/cvirt_def.h | 18 + include/linux/vserver/debug.h | 169 +- include/linux/vserver/dlimit.h | 36 +- include/linux/vserver/inode.h | 35 +- include/linux/vserver/legacy.h | 5 - include/linux/vserver/limit.h | 5 +- include/linux/vserver/namespace.h | 46 - include/linux/vserver/network.h | 37 +- include/linux/vserver/network_cmd.h | 22 +- include/linux/vserver/sched.h | 2 +- include/linux/vserver/sched_def.h | 2 + include/linux/vserver/signal.h | 19 - include/linux/vserver/switch.h | 4 +- include/linux/vserver/xid.h | 23 +- include/linux/vt_kern.h | 50 +- include/linux/wait.h | 66 +- include/linux/workqueue.h | 3 + include/linux/xfrm.h | 5 +- include/media/ir-common.h | 6 +- include/media/saa7146_vv.h | 28 +- include/net/addrconf.h | 9 +- include/net/bluetooth/bluetooth.h | 1 - include/net/bluetooth/hci.h | 10 +- include/net/bluetooth/hci_core.h | 40 +- include/net/bluetooth/l2cap.h | 30 +- include/net/bluetooth/rfcomm.h | 62 +- include/net/bluetooth/sco.h | 10 +- include/net/checksum.h | 6 +- include/net/dst.h | 33 +- include/net/ip.h | 44 +- include/net/ipv6.h | 32 +- include/net/irda/ircomm_tty.h | 4 +- include/net/irda/irda.h | 29 +- include/net/irda/irda_device.h | 4 - include/net/irda/irlmp.h | 3 - include/net/neighbour.h | 3 +- include/net/pkt_cls.h | 384 +- include/net/pkt_sched.h | 6 +- include/net/route.h | 11 +- include/net/scm.h | 4 +- include/net/sctp/sctp.h | 49 +- include/net/snmp.h | 14 +- include/net/sock.h | 244 +- include/net/tcp.h | 294 +- include/net/xfrm.h | 32 +- include/pcmcia/cs_types.h | 27 +- include/pcmcia/ss.h | 76 +- include/rxrpc/call.h | 5 - include/scsi/scsi.h | 17 +- include/scsi/scsi_device.h | 34 +- include/scsi/scsi_devinfo.h | 1 + include/scsi/scsi_eh.h | 6 + include/scsi/scsi_host.h | 100 +- include/scsi/scsi_transport.h | 33 +- include/scsi/scsi_transport_fc.h | 415 +- include/scsi/scsi_transport_spi.h | 8 + include/sound/ac97_codec.h | 28 +- include/sound/ad1848.h | 9 - include/sound/asound.h | 6 +- include/sound/control.h | 16 +- include/sound/core.h | 55 +- include/sound/cs4231.h | 5 - include/sound/cs46xx.h | 4 +- include/sound/emu10k1.h | 205 +- include/sound/pcm.h | 91 +- include/sound/soundmem.h | 8 - include/sound/trident.h | 14 +- include/sound/version.h | 4 +- include/sound/ymfpci.h | 25 +- include/sound/yss225.h | 23 - include/video/radeon.h | 476 +- init/Kconfig | 96 +- init/Makefile | 2 + init/calibrate.c | 8 +- init/initramfs.c | 19 +- init/main.c | 151 +- init/version.c | 6 +- ipc/compat_mq.c | 16 +- ipc/mqueue.c | 19 +- ipc/msg.c | 4 +- ipc/sem.c | 4 +- ipc/shm.c | 29 +- kernel/Makefile | 17 +- kernel/acct.c | 33 +- kernel/audit.c | 780 +- kernel/auditsc.c | 614 +- kernel/capability.c | 70 +- kernel/compat.c | 200 +- kernel/cpu.c | 7 +- kernel/cpuset.c | 1 + kernel/dma.c | 2 +- kernel/exit.c | 127 +- kernel/fork.c | 242 +- kernel/futex.c | 137 +- kernel/irq/handle.c | 16 +- kernel/irq/manage.c | 81 +- kernel/irq/spurious.c | 103 +- kernel/itimer.c | 228 +- kernel/kallsyms.c | 60 +- kernel/kthread.c | 27 +- kernel/module.c | 163 +- kernel/panic.c | 16 +- kernel/params.c | 235 +- kernel/pid.c | 2 +- kernel/posix-cpu-timers.c | 1 + kernel/posix-timers.c | 332 +- kernel/power/pm.c | 2 +- kernel/power/poweroff.c | 3 +- kernel/power/swsusp.c | 776 +- kernel/printk.c | 242 +- kernel/profile.c | 1 + kernel/ptrace.c | 63 +- kernel/rcupdate.c | 67 +- kernel/sched.c | 1290 +- kernel/signal.c | 374 +- kernel/softirq.c | 32 +- kernel/sys.c | 117 +- kernel/sys_ni.c | 140 +- kernel/sysctl.c | 200 +- kernel/time.c | 72 +- kernel/timer.c | 127 +- kernel/user.c | 5 +- kernel/vserver/Kconfig | 93 +- kernel/vserver/Makefile | 4 +- kernel/vserver/context.c | 269 +- kernel/vserver/cvirt.c | 165 +- kernel/vserver/cvirt_init.h | 11 + kernel/vserver/cvirt_proc.h | 2 + kernel/vserver/dlimit.c | 260 +- kernel/vserver/helper.c | 113 +- kernel/vserver/init.c | 2 +- kernel/vserver/inode.c | 83 +- kernel/vserver/legacy.c | 69 +- kernel/vserver/limit.c | 25 +- kernel/vserver/limit_proc.h | 10 + kernel/vserver/namespace.c | 120 +- kernel/vserver/network.c | 318 +- kernel/vserver/proc.c | 78 +- kernel/vserver/sched.c | 13 +- kernel/vserver/sched_init.h | 1 + kernel/vserver/sched_proc.h | 2 + kernel/vserver/signal.c | 45 +- kernel/vserver/switch.c | 90 +- kernel/vserver/sysctl.c | 2 +- kernel/workqueue.c | 35 +- lib/Makefile | 8 +- lib/bitmap.c | 103 + lib/kobject.c | 25 +- lib/kobject_uevent.c | 1 + lib/rwsem-spinlock.c | 48 +- lib/rwsem.c | 20 +- lib/string.c | 34 +- lib/vsprintf.c | 4 +- mm/Makefile | 8 +- mm/bootmem.c | 10 +- mm/filemap.c | 221 +- mm/fremap.c | 45 +- mm/highmem.c | 25 +- mm/hugetlb.c | 7 +- mm/madvise.c | 15 +- mm/memory.c | 1358 +- mm/mempool.c | 53 +- mm/mincore.c | 53 +- mm/mlock.c | 65 +- mm/mmap.c | 680 +- mm/mprotect.c | 140 +- mm/mremap.c | 78 +- mm/msync.c | 189 +- mm/nommu.c | 1052 +- mm/oom_kill.c | 219 +- mm/page-writeback.c | 85 +- mm/page_alloc.c | 786 +- mm/pdflush.c | 6 +- mm/readahead.c | 475 +- mm/rmap.c | 150 +- mm/shmem.c | 20 +- mm/slab.c | 304 +- mm/swap_state.c | 58 +- mm/swapfile.c | 205 +- mm/truncate.c | 108 +- mm/vmalloc.c | 319 +- mm/vmscan.c | 231 +- net/802/fc.c | 41 +- net/802/tr.c | 35 +- net/8021q/vlan.c | 9 +- net/8021q/vlan.h | 1 - net/Kconfig | 37 +- net/appletalk/ddp.c | 57 +- net/atm/addr.c | 93 +- net/atm/br2684.c | 6 +- net/atm/clip.c | 19 +- net/atm/common.c | 108 +- net/atm/ioctl.c | 9 +- net/atm/lec.c | 448 +- net/atm/signaling.c | 41 +- net/atm/svc.c | 83 +- net/ax25/af_ax25.c | 57 +- net/ax25/ax25_route.c | 4 +- net/bluetooth/af_bluetooth.c | 44 - net/bluetooth/hci_conn.c | 23 +- net/bluetooth/hci_core.c | 49 +- net/bluetooth/hci_event.c | 67 +- net/bluetooth/hci_sock.c | 51 +- net/bluetooth/hci_sysfs.c | 2 +- net/bluetooth/l2cap.c | 77 +- net/bluetooth/rfcomm/core.c | 200 +- net/bluetooth/rfcomm/sock.c | 117 +- net/bluetooth/sco.c | 64 +- net/bridge/br.c | 10 +- net/bridge/br_device.c | 21 +- net/bridge/br_fdb.c | 193 +- net/bridge/br_if.c | 25 +- net/bridge/br_ioctl.c | 2 +- net/bridge/br_netfilter.c | 2 +- net/bridge/br_notify.c | 9 + net/bridge/br_private.h | 19 +- net/bridge/br_stp_if.c | 3 + net/bridge/netfilter/ebtables.c | 27 +- net/core/datagram.c | 47 +- net/core/dev.c | 223 +- net/core/dst.c | 48 +- net/core/iovec.c | 25 +- net/core/neighbour.c | 123 +- net/core/net-sysfs.c | 20 +- net/core/netfilter.c | 128 +- net/core/netpoll.c | 242 +- net/core/pktgen.c | 3805 +++-- net/core/rtnetlink.c | 121 +- net/core/scm.c | 1 - net/core/skbuff.c | 222 +- net/core/sock.c | 316 +- net/decnet/af_decnet.c | 69 +- net/decnet/dn_dev.c | 31 +- net/decnet/dn_nsp_in.c | 2 +- net/decnet/dn_route.c | 11 +- net/econet/af_econet.c | 45 +- net/ethernet/eth.c | 4 +- net/ipv4/Kconfig | 47 +- net/ipv4/Makefile | 5 + net/ipv4/af_inet.c | 116 +- net/ipv4/ah4.c | 6 +- net/ipv4/arp.c | 13 +- net/ipv4/devinet.c | 125 +- net/ipv4/esp4.c | 11 +- net/ipv4/fib_frontend.c | 6 +- net/ipv4/fib_hash.c | 140 +- net/ipv4/fib_semantics.c | 97 +- net/ipv4/icmp.c | 54 +- net/ipv4/igmp.c | 32 +- net/ipv4/ip_fragment.c | 25 +- net/ipv4/ip_gre.c | 20 +- net/ipv4/ip_input.c | 9 +- net/ipv4/ip_output.c | 51 +- net/ipv4/ip_sockglue.c | 20 +- net/ipv4/ipcomp.c | 32 +- net/ipv4/ipconfig.c | 27 +- net/ipv4/ipip.c | 8 +- net/ipv4/ipmr.c | 6 +- net/ipv4/ipvs/ip_vs_core.c | 28 +- net/ipv4/ipvs/ip_vs_ctl.c | 31 +- net/ipv4/ipvs/ip_vs_proto_icmp.c | 182 - net/ipv4/ipvs/ip_vs_sync.c | 24 +- net/ipv4/ipvs/ip_vs_xmit.c | 12 +- net/ipv4/netfilter/Kconfig | 33 +- net/ipv4/netfilter/Makefile | 18 +- net/ipv4/netfilter/arp_tables.c | 29 +- net/ipv4/netfilter/ip_conntrack_amanda.c | 56 +- net/ipv4/netfilter/ip_conntrack_core.c | 733 +- net/ipv4/netfilter/ip_conntrack_ftp.c | 171 +- net/ipv4/netfilter/ip_conntrack_proto_icmp.c | 2 +- net/ipv4/netfilter/ip_conntrack_proto_sctp.c | 2 +- net/ipv4/netfilter/ip_conntrack_proto_tcp.c | 185 +- net/ipv4/netfilter/ip_conntrack_standalone.c | 227 +- net/ipv4/netfilter/ip_fw_compat.c | 303 - net/ipv4/netfilter/ip_fw_compat.h | 28 - net/ipv4/netfilter/ip_fw_compat_masq.c | 342 - net/ipv4/netfilter/ip_fw_compat_redir.c | 318 - net/ipv4/netfilter/ip_nat_core.c | 886 +- net/ipv4/netfilter/ip_nat_snmp_basic.c | 147 +- net/ipv4/netfilter/ip_nat_standalone.c | 165 +- net/ipv4/netfilter/ip_tables.c | 312 +- net/ipv4/netfilter/ipchains_core.c | 1854 -- net/ipv4/netfilter/ipfwadm_core.c | 1464 -- net/ipv4/netfilter/ipt_LOG.c | 20 +- net/ipv4/netfilter/ipt_MARK.c | 115 +- net/ipv4/netfilter/ipt_MASQUERADE.c | 20 +- net/ipv4/netfilter/ipt_REJECT.c | 163 +- net/ipv4/netfilter/ipt_ULOG.c | 4 +- net/ipv4/netfilter/ipt_helper.c | 16 +- net/ipv4/netfilter/iptable_mangle.c | 22 +- net/ipv4/netfilter/iptable_raw.c | 28 +- net/ipv4/protocol.c | 4 +- net/ipv4/raw.c | 75 +- net/ipv4/route.c | 848 +- net/ipv4/sysctl_net_ipv4.c | 17 + net/ipv4/tcp.c | 173 +- net/ipv4/tcp_diag.c | 7 + net/ipv4/tcp_input.c | 745 +- net/ipv4/tcp_ipv4.c | 256 +- net/ipv4/tcp_minisocks.c | 214 +- net/ipv4/tcp_output.c | 225 +- net/ipv4/tcp_timer.c | 38 +- net/ipv4/udp.c | 109 +- net/ipv4/xfrm4_policy.c | 129 +- net/ipv4/xfrm4_state.c | 4 +- net/ipv4/xfrm4_tunnel.c | 2 +- net/ipv6/README | 8 - net/ipv6/addrconf.c | 181 +- net/ipv6/af_inet6.c | 84 +- net/ipv6/ah6.c | 6 +- net/ipv6/anycast.c | 36 +- net/ipv6/datagram.c | 4 +- net/ipv6/esp6.c | 21 +- net/ipv6/exthdrs.c | 77 - net/ipv6/icmp.c | 56 +- net/ipv6/ip6_flowlabel.c | 25 +- net/ipv6/ip6_input.c | 34 +- net/ipv6/ip6_output.c | 50 +- net/ipv6/ip6_tunnel.c | 12 +- net/ipv6/ipcomp6.c | 20 +- net/ipv6/ipv6_sockglue.c | 10 +- net/ipv6/ipv6_syms.c | 3 - net/ipv6/mcast.c | 34 +- net/ipv6/ndisc.c | 246 +- net/ipv6/netfilter/ip6_tables.c | 41 +- net/ipv6/netfilter/ip6t_LOG.c | 10 +- net/ipv6/netfilter/ip6table_raw.c | 3 +- net/ipv6/proc.c | 34 +- net/ipv6/raw.c | 109 +- net/ipv6/reassembly.c | 2 +- net/ipv6/route.c | 117 +- net/ipv6/sit.c | 10 +- net/ipv6/tcp_ipv6.c | 218 +- net/ipv6/udp.c | 46 +- net/ipv6/xfrm6_policy.c | 135 +- net/ipv6/xfrm6_state.c | 6 +- net/ipx/af_ipx.c | 91 +- net/irda/af_irda.c | 152 +- net/irda/discovery.c | 45 +- net/irda/ircomm/ircomm_core.c | 52 +- net/irda/ircomm/ircomm_tty.c | 107 +- net/irda/irda_device.c | 117 +- net/irda/iriap.c | 160 +- net/irda/irlap_event.c | 101 +- net/irda/irlmp.c | 199 +- net/key/af_key.c | 84 +- net/lapb/lapb_iface.c | 2 +- net/llc/af_llc.c | 72 +- net/netlink/af_netlink.c | 261 +- net/netlink/netlink_dev.c | 278 - net/netrom/af_netrom.c | 100 +- net/netrom/nr_in.c | 8 +- net/packet/af_packet.c | 104 +- net/rose/af_rose.c | 104 +- net/rose/rose_route.c | 15 +- net/rxrpc/call.c | 15 +- net/rxrpc/connection.c | 4 +- net/rxrpc/rxrpc_syms.c | 1 - net/rxrpc/transport.c | 12 +- net/sched/Kconfig | 114 +- net/sched/Makefile | 17 +- net/sched/cls_api.c | 209 +- net/sched/cls_fw.c | 168 +- net/sched/cls_route.c | 344 +- net/sched/cls_rsvp.h | 102 +- net/sched/cls_tcindex.c | 373 +- net/sched/cls_u32.c | 162 +- net/sched/estimator.c | 2 +- net/sched/police.c | 186 +- net/sched/sch_api.c | 60 +- net/sched/sch_atm.c | 6 +- net/sched/sch_cbq.c | 84 +- net/sched/sch_generic.c | 11 +- net/sched/sch_gred.c | 15 +- net/sched/sch_hfsc.c | 48 +- net/sched/sch_htb.c | 64 +- net/sched/sch_ingress.c | 22 +- net/sched/sch_prio.c | 73 +- net/sched/sch_red.c | 2 +- net/sched/sch_tbf.c | 2 +- net/sctp/associola.c | 91 +- net/sctp/chunk.c | 10 +- net/sctp/endpointola.c | 61 +- net/sctp/inqueue.c | 39 +- net/sctp/ipv6.c | 106 +- net/sctp/output.c | 8 +- net/sctp/outqueue.c | 15 +- net/sctp/protocol.c | 82 +- net/sctp/sm_make_chunk.c | 180 +- net/sctp/sm_statefuns.c | 554 +- net/sctp/socket.c | 260 +- net/sctp/ulpevent.c | 17 +- net/sctp/ulpqueue.c | 24 +- net/socket.c | 61 +- net/sunrpc/auth.c | 205 +- net/sunrpc/auth_gss/auth_gss.c | 633 +- net/sunrpc/auth_gss/gss_generic_token.c | 35 - net/sunrpc/auth_gss/gss_krb5_crypto.c | 2 +- net/sunrpc/auth_gss/gss_krb5_mech.c | 108 +- net/sunrpc/auth_gss/gss_mech_switch.c | 20 +- net/sunrpc/auth_gss/gss_pseudoflavors.c | 237 - net/sunrpc/auth_gss/sunrpcgss_syms.c | 37 - net/sunrpc/auth_gss/svcauth_gss.c | 34 +- net/sunrpc/auth_unix.c | 87 +- net/sunrpc/cache.c | 49 +- net/sunrpc/clnt.c | 94 +- net/sunrpc/pmap_clnt.c | 11 +- net/sunrpc/rpc_pipe.c | 10 +- net/sunrpc/svcauth_des.c | 215 - net/sunrpc/svcauth_unix.c | 116 +- net/sunrpc/svcsock.c | 7 +- net/sunrpc/xprt.c | 28 +- net/tux/accept.c | 6 +- net/tux/cachemiss.c | 3 +- net/tux/directory.c | 2 +- net/tux/input.c | 6 +- net/tux/logger.c | 2 +- net/tux/main.c | 2 +- net/tux/output.c | 4 +- net/tux/proto_ftp.c | 6 +- net/tux/proto_http.c | 2 +- net/unix/af_unix.c | 93 +- net/wanrouter/af_wanpipe.c | 61 +- net/x25/af_x25.c | 156 +- net/xfrm/Makefile | 3 +- net/xfrm/xfrm_export.c | 63 - net/xfrm/xfrm_policy.c | 168 +- net/xfrm/xfrm_state.c | 127 +- net/xfrm/xfrm_user.c | 112 +- scripts/Makefile.modinst | 5 +- scripts/README.Menuconfig | 201 - scripts/kallsyms.c | 91 +- scripts/kconfig/.kxgettext.o.cmd | 48 - scripts/kconfig/Makefile | 24 +- scripts/kconfig/conf.c | 20 +- scripts/kconfig/confdata.c | 4 +- scripts/kconfig/kxgettext.o | Bin 2324 -> 0 bytes scripts/kconfig/mconf.c | 542 +- scripts/kernel-2.6-planetlab.spec | 4 +- scripts/kernel-doc | 127 +- scripts/makeman | 185 - scripts/reference_init.pl | 4 +- scripts/split-man | 112 - security/commoncap.c | 82 +- security/dummy.c | 86 +- security/security.c | 4 +- security/selinux/Kconfig | 32 +- security/selinux/avc.c | 306 +- security/selinux/hooks.c | 531 +- security/selinux/include/av_inherit.h | 73 +- security/selinux/include/av_perm_to_string.h | 462 +- security/selinux/include/av_permissions.h | 57 +- security/selinux/include/avc.h | 7 - security/selinux/include/class_to_string.h | 112 +- security/selinux/include/flask.h | 4 + security/selinux/include/objsec.h | 8 +- security/selinux/include/security.h | 13 +- security/selinux/netif.c | 2 +- security/selinux/selinuxfs.c | 164 +- security/selinux/ss/avtab.c | 61 +- security/selinux/ss/avtab.h | 6 - security/selinux/ss/conditional.c | 54 +- security/selinux/ss/ebitmap.c | 64 +- security/selinux/ss/mls.c | 729 +- security/selinux/ss/policydb.c | 862 +- security/selinux/ss/services.c | 286 +- security/selinux/ss/sidtab.c | 36 - sound/arm/sa11xx-uda1341.c | 10 +- sound/core/Kconfig | 24 +- sound/core/control.c | 366 +- sound/core/init.c | 178 +- sound/core/ioctl32/Makefile | 11 - sound/core/ioctl32/hwdep32.c | 73 - sound/core/ioctl32/ioctl32.c | 490 - sound/core/ioctl32/ioctl32.h | 102 - sound/core/ioctl32/pcm32.c | 461 - sound/core/ioctl32/rawmidi32.c | 91 - sound/core/ioctl32/seq32.c | 116 - sound/core/ioctl32/timer32.c | 105 - sound/core/memory.c | 16 +- sound/core/oss/pcm_oss.c | 72 +- sound/core/oss/pcm_plugin.c | 49 +- sound/core/oss/route.c | 91 +- sound/core/pcm_lib.c | 117 +- sound/core/pcm_memory.c | 4 +- sound/core/pcm_native.c | 120 +- sound/core/rawmidi.c | 256 +- sound/core/rtctimer.c | 2 + sound/core/seq/Makefile | 2 + sound/core/seq/oss/seq_oss.c | 21 +- sound/core/seq/oss/seq_oss_init.c | 85 +- sound/core/seq/oss/seq_oss_misc.c | 110 - sound/core/seq/seq_clientmgr.c | 38 +- sound/core/seq/seq_dummy.c | 1 + sound/core/seq/seq_midi.c | 104 +- sound/core/sound.c | 36 +- sound/core/timer.c | 109 +- sound/drivers/mpu401/mpu401.c | 252 +- sound/drivers/mtpav.c | 7 +- sound/drivers/opl3/opl3_lib.c | 6 +- sound/drivers/opl3/opl3_seq.c | 4 +- sound/drivers/serial-u16550.c | 23 +- sound/drivers/vx/vx_core.c | 127 +- sound/isa/Kconfig | 42 +- sound/isa/ad1848/ad1848_lib.c | 34 +- sound/isa/als100.c | 4 +- sound/isa/cs423x/cs4231_lib.c | 46 +- sound/isa/cs423x/cs4236.c | 2 + sound/isa/es18xx.c | 16 +- sound/isa/gus/gus_lfo.c | 429 - sound/isa/gus/interwave.c | 2 + sound/isa/opl3sa2.c | 18 +- sound/isa/opti9xx/opti92x-ad1848.c | 12 +- sound/isa/sb/emu8000_patch.c | 4 +- sound/isa/sscape.c | 26 +- sound/isa/wavefront/wavefront.c | 6 +- sound/isa/wavefront/wavefront_fx.c | 3 +- sound/isa/wavefront/wavefront_synth.c | 238 +- sound/oss/Kconfig | 42 +- sound/oss/Makefile | 3 + sound/oss/ac97.c | 13 +- sound/oss/ac97.h | 16 - sound/oss/ac97_codec.c | 174 +- sound/oss/aci.c | 6 +- sound/oss/ad1816.c | 23 +- sound/oss/ad1848.c | 30 +- sound/oss/ad1889.c | 18 +- sound/oss/awe_wave.c | 14 +- sound/oss/cmpci.c | 133 +- sound/oss/cs4232.h | 3 - sound/oss/dmasound/dac3550a.c | 4 - sound/oss/dmasound/dmasound_awacs.c | 9 +- sound/oss/gus_wave.c | 7 +- sound/oss/i810_audio.c | 149 +- sound/oss/maestro_tables.h | 333 - sound/oss/maui.c | 4 +- sound/oss/midibuf.c | 2 +- sound/oss/mpu401.c | 4 +- sound/oss/nm256_audio.c | 14 +- sound/oss/opl3.c | 2 +- sound/oss/opl3sa2.c | 31 +- sound/oss/pss.c | 36 +- sound/oss/sb_card.c | 6 +- sound/oss/sequencer.c | 4 +- sound/oss/soundcard.c | 14 +- sound/oss/sscape.c | 16 +- sound/oss/sys_timer.c | 2 +- sound/oss/trident.c | 54 +- sound/oss/via82cxxx_audio.c | 220 +- sound/oss/vwsnd.c | 6 +- sound/oss/waveartist.c | 2 +- sound/oss/wavfront.c | 158 +- sound/oss/wf_midi.c | 2 +- sound/parisc/harmony.c | 1598 +- sound/pci/Kconfig | 57 +- sound/pci/ac97/ac97_codec.c | 1096 +- sound/pci/ac97/ac97_local.h | 41 +- sound/pci/ac97/ac97_patch.c | 347 +- sound/pci/ac97/ac97_pcm.c | 18 +- sound/pci/ac97/ac97_proc.c | 12 +- sound/pci/ali5451/ali5451.c | 13 +- sound/pci/als4000.c | 111 +- sound/pci/atiixp.c | 78 +- sound/pci/au88x0/au88x0.c | 22 +- sound/pci/au88x0/au88x0.h | 8 +- sound/pci/au88x0/au88x0_core.c | 60 +- sound/pci/au88x0/au88x0_eq.c | 58 +- sound/pci/au88x0/au88x0_game.c | 54 +- sound/pci/au88x0/au88x0_pcm.c | 110 +- sound/pci/azt3328.c | 140 +- sound/pci/bt87x.c | 153 +- sound/pci/cmipci.c | 188 +- sound/pci/cs4281.c | 101 +- sound/pci/cs46xx/cs46xx_lib.c | 164 +- sound/pci/cs46xx/dsp_spos_scb_lib.c | 12 +- sound/pci/emu10k1/emu10k1.c | 64 +- sound/pci/emu10k1/emu10k1_main.c | 207 +- sound/pci/emu10k1/emufx.c | 429 +- sound/pci/emu10k1/emumixer.c | 408 +- sound/pci/ens1370.c | 146 +- sound/pci/es1938.c | 73 +- sound/pci/es1968.c | 103 +- sound/pci/fm801.c | 2 +- sound/pci/ice1712/Makefile | 2 +- sound/pci/ice1712/aureon.c | 510 +- sound/pci/ice1712/aureon.h | 10 +- sound/pci/ice1712/delta.c | 3 + sound/pci/ice1712/envy24ht.h | 2 +- sound/pci/ice1712/ice1712.c | 32 +- sound/pci/ice1712/ice1712.h | 13 +- sound/pci/ice1712/ice1724.c | 80 +- sound/pci/ice1712/revo.c | 24 + sound/pci/intel8x0.c | 116 +- sound/pci/intel8x0m.c | 94 +- sound/pci/korg1212/korg1212.c | 90 +- sound/pci/maestro3.c | 42 +- sound/pci/mixart/mixart.c | 26 +- sound/pci/nm256/nm256.c | 10 +- sound/pci/rme32.c | 11 +- sound/pci/rme96.c | 10 +- sound/pci/rme9652/hdsp.c | 606 +- sound/pci/rme9652/rme9652.c | 2 +- sound/pci/sonicvibes.c | 59 +- sound/pci/trident/trident.c | 2 +- sound/pci/trident/trident_main.c | 136 +- sound/pci/via82xx.c | 236 +- sound/pci/vx222/vx222.c | 7 +- sound/pci/ymfpci/ymfpci.c | 150 +- sound/pci/ymfpci/ymfpci_main.c | 30 +- sound/pcmcia/pdaudiocf/pdaudiocf.c | 42 +- sound/pcmcia/pdaudiocf/pdaudiocf.h | 6 +- sound/pcmcia/pdaudiocf/pdaudiocf_core.c | 10 +- sound/pcmcia/vx/vxpocket.c | 10 +- sound/ppc/keywest.c | 2 - sound/ppc/pmac.c | 247 +- sound/ppc/pmac.h | 10 +- sound/ppc/powermac.c | 7 + sound/ppc/tumbler.c | 433 +- sound/sparc/cs4231.c | 23 +- sound/usb/usbaudio.c | 130 +- sound/usb/usbaudio.h | 16 +- sound/usb/usbmixer.c | 72 +- sound/usb/usbquirks.h | 250 +- usr/initramfs_list | 5 - 3920 files changed, 224963 insertions(+), 274858 deletions(-) delete mode 100644 Documentation/BK-usage/00-INDEX delete mode 100644 Documentation/BK-usage/bk-kernel-howto.txt delete mode 100755 Documentation/BK-usage/bk-make-sum delete mode 100755 Documentation/BK-usage/bksend delete mode 100755 Documentation/BK-usage/bz64wrap delete mode 100755 Documentation/BK-usage/cpcset delete mode 100755 Documentation/BK-usage/cset-to-linus delete mode 100755 Documentation/BK-usage/csets-to-patches delete mode 100755 Documentation/BK-usage/gcapatch delete mode 100755 Documentation/BK-usage/unbz64wrap delete mode 100644 Documentation/DocBook/tulip-user.tmpl delete mode 100644 Documentation/DocBook/via-audio.tmpl delete mode 100644 Documentation/README.moxa delete mode 100644 Documentation/cdrom/mcd delete mode 100644 Documentation/filesystems/umsdos.txt delete mode 100644 Documentation/i2c/i2c-old-porting delete mode 100644 Documentation/i2c/i2c-parport delete mode 100644 Documentation/mkdev.cciss delete mode 100644 Documentation/networking/ethertap.txt delete mode 100644 Documentation/scsi/ChangeLog delete mode 100644 Documentation/scsi/qla2xxx.revision.notes delete mode 100644 Documentation/usb/silverlink.txt delete mode 100644 arch/arm/configs/a5k_defconfig delete mode 100644 arch/arm/mach-ixp4xx/prpmc1100-pci.c delete mode 100644 arch/arm/mach-ixp4xx/prpmc1100-setup.c delete mode 100644 arch/arm/mm/copypage-v4mc.S delete mode 100644 arch/arm/mm/copypage-xscale.S delete mode 100644 arch/arm/mm/minicache.c delete mode 100644 arch/arm26/boot/compressed/ofw-shark.c delete mode 100644 arch/arm26/kernel/time-acorn.c delete mode 100644 arch/arm26/lib/io-readsl-armv3.S delete mode 100644 arch/arm26/lib/io-readsw-armv3.S delete mode 100644 arch/arm26/lib/io-writesw-armv3.S delete mode 100644 arch/arm26/machine/head.S delete mode 100644 arch/arm26/machine/oldlatches.c delete mode 100644 arch/arm26/machine/small_page.c delete mode 100644 arch/arm26/mm/mm-memc.c delete mode 100644 arch/ia64/dig/topology.c delete mode 100644 arch/ia64/sn/include/pci/pcibus_provider_defs.h delete mode 100644 arch/ia64/sn/include/pci/pcidev.h delete mode 100644 arch/ia64/sn/include/shub.h delete mode 100644 arch/ia64/sn/include/shubio.h delete mode 100644 arch/m68k/apollo/dn_debug.c delete mode 100644 arch/m68k/sun3x/sun3x_ksyms.c delete mode 100644 arch/m68knommu/platform/5206/ARNEWSH/crt0_ram.S delete mode 100644 arch/m68knommu/platform/5206e/MOTOROLA/crt0_ram.S delete mode 100644 arch/m68knommu/platform/5206e/eLITE/crt0_ram.S delete mode 100644 arch/m68knommu/platform/5249/MOTOROLA/crt0_ram.S delete mode 100644 arch/m68knommu/platform/5272/CANCam/crt0_ram.S delete mode 100644 arch/m68knommu/platform/5272/MOTOROLA/crt0_ram.S delete mode 100644 arch/m68knommu/platform/5272/NETtel/crt0_ram.S delete mode 100644 arch/m68knommu/platform/5272/SCALES/crt0_ram.S delete mode 100644 arch/m68knommu/platform/5272/senTec/crt0_ram.S delete mode 100644 arch/m68knommu/platform/527x/M5271EVB/crt0_ram.S delete mode 100644 arch/m68knommu/platform/527x/M5275EVB/crt0_ram.S delete mode 100644 arch/m68knommu/platform/528x/M5282EVB/crt0_ram.S delete mode 100644 arch/m68knommu/platform/528x/senTec/crt0_ram.S delete mode 100644 arch/m68knommu/platform/5307/ARNEWSH/crt0_ram.S delete mode 100644 arch/m68knommu/platform/5307/CLEOPATRA/crt0_ram.S delete mode 100644 arch/m68knommu/platform/5307/MOTOROLA/crt0_ram.S delete mode 100644 arch/m68knommu/platform/5307/MP3/crt0_ram.S delete mode 100644 arch/m68knommu/platform/5307/NETtel/crt0_ram.S delete mode 100644 arch/m68knommu/platform/5407/CLEOPATRA/crt0_ram.S delete mode 100644 arch/m68knommu/platform/5407/MOTOROLA/crt0_ram.S delete mode 100644 arch/m68knommu/platform/68328/pilot/crt0_rom.S delete mode 100644 arch/m68knommu/platform/68360/uCquicc/crt0_ram.S delete mode 100644 arch/m68knommu/platform/68360/uCquicc/crt0_rom.S delete mode 100644 arch/m68knommu/platform/68EZ328/ucsimm/crt0_fixed.S delete mode 100644 arch/m68knommu/platform/68EZ328/ucsimm/crt0_himem.S delete mode 100644 arch/m68knommu/platform/68EZ328/ucsimm/crt0_ram.S delete mode 100644 arch/m68knommu/platform/68EZ328/ucsimm/crt0_rom.S delete mode 100644 arch/m68knommu/platform/68VZ328/de2/Makefile delete mode 100644 arch/m68knommu/platform/68VZ328/de2/crt0_ram.S delete mode 100644 arch/m68knommu/platform/68VZ328/ucdimm/Makefile delete mode 100644 arch/m68knommu/platform/68VZ328/ucdimm/crt0_fixed.S delete mode 100644 arch/m68knommu/platform/68VZ328/ucdimm/crt0_himem.S delete mode 100644 arch/m68knommu/platform/68VZ328/ucdimm/crt0_ram.S delete mode 100644 arch/m68knommu/platform/68VZ328/ucdimm/crt0_rom.S delete mode 100644 arch/mips/kernel/irix5sys.h delete mode 100644 arch/mips/kernel/reg.c delete mode 100644 arch/mips/mm/tlb64-glue-r4k.S delete mode 100644 arch/mips/mm/tlb64-glue-sb1.S delete mode 100644 arch/mips/mm/tlbex32-mips32.S delete mode 100644 arch/mips/mm/tlbex32-r3k.S delete mode 100644 arch/mips/mm/tlbex32-r4k.S delete mode 100644 arch/mips/vr41xx/common/ksyms.c delete mode 100644 arch/mips/vr41xx/common/rtc.c delete mode 100644 arch/mips/vr41xx/common/serial.c delete mode 100644 arch/mips/vr41xx/common/vrc4171.c delete mode 100644 arch/mips/vr41xx/tanbac-tb0229/tb0219.c delete mode 100644 arch/parisc/configs/n4000_defconfig delete mode 100644 arch/ppc/boot/simple/gt64260_tty.c delete mode 100644 arch/ppc/boot/simple/misc-ev64260.S create mode 100644 arch/ppc/boot/simple/mv64x60_tty.c delete mode 100644 arch/ppc/defconfig delete mode 100644 arch/ppc/kernel/head_e500.S delete mode 100644 arch/ppc/oprofile/init.c delete mode 100644 arch/ppc/platforms/85xx/mpc8540.c delete mode 100644 arch/ppc/platforms/85xx/mpc8555.c delete mode 100644 arch/ppc/platforms/85xx/mpc8560.c create mode 100644 arch/ppc/platforms/ev64260.c delete mode 100644 arch/ppc/platforms/ev64260_setup.c delete mode 100644 arch/ppc/syslib/gt64260_common.c delete mode 100644 arch/ppc/syslib/m8260_pci.c delete mode 100644 arch/ppc/syslib/m8260_pci.h create mode 100644 arch/ppc/syslib/mv64360_pic.c create mode 100644 arch/ppc/syslib/mv64x60.c delete mode 100644 arch/ppc/syslib/ppc4xx_serial.c delete mode 100644 arch/ppc64/boot/no_initrd.c delete mode 100644 arch/ppc64/boot/start.c delete mode 100644 arch/ppc64/kernel/pci_dma_direct.c delete mode 100644 arch/ppc64/xmon/setjmp.c delete mode 100644 arch/s390/kernel/compat_exec.c delete mode 100644 arch/sh/defconfig delete mode 100644 arch/sh64/defconfig delete mode 100644 arch/sh64/lib/old-checksum.c delete mode 100644 arch/sparc64/lib/VIS.h delete mode 100644 arch/sparc64/lib/VISbzero.S delete mode 100644 arch/sparc64/lib/VIScsum.S delete mode 100644 arch/sparc64/lib/VIScsumcopy.S delete mode 100644 arch/sparc64/lib/VIScsumcopyusr.S delete mode 100644 arch/sparc64/lib/VISmemset.S delete mode 100644 arch/sparc64/lib/rwsem.c delete mode 100644 arch/um/Kconfig_block delete mode 100644 arch/um/drivers/slip_proto.h delete mode 100644 arch/um/include/2_5compat.h delete mode 100644 arch/um/include/frame.h delete mode 100644 arch/um/include/frame_user.h delete mode 100644 arch/um/include/sysdep-i386/frame.h delete mode 100644 arch/um/include/sysdep-i386/frame_kern.h delete mode 100644 arch/um/include/sysdep-i386/frame_user.h delete mode 100644 arch/um/include/umn.h delete mode 100644 arch/um/kernel/checksum.c delete mode 100644 arch/um/kernel/frame.c delete mode 100644 arch/um/kernel/frame_kern.c delete mode 100644 arch/um/kernel/initrd_kern.c delete mode 100644 arch/um/kernel/initrd_user.c delete mode 100644 arch/um/kernel/skas/include/ptrace-skas.h delete mode 100644 arch/um/kernel/skas/sys-i386/Makefile delete mode 100644 arch/um/kernel/skas/sys-i386/sigcontext.c delete mode 100644 arch/um/kernel/skas/util/mk_ptregs.c delete mode 100644 arch/um/kernel/sys_call_table.c delete mode 100644 arch/um/kernel/tt/include/ptrace-tt.h delete mode 100644 arch/um/kernel/tt/sys-i386/Makefile delete mode 100644 arch/um/kernel/tt/sys-i386/sigcontext.c create mode 100644 arch/um/kernel/vmlinux.lds.S delete mode 100644 arch/um/sys-i386/util/mk_thread_kern.c delete mode 100644 arch/um/sys-i386/util/mk_thread_user.c delete mode 100644 arch/um/util/mk_constants_kern.c delete mode 100644 arch/um/util/mk_constants_user.c delete mode 100644 arch/um/util/mk_task_kern.c delete mode 100644 arch/um/util/mk_task_user.c delete mode 100644 arch/x86_64/kernel/vsyscall.S delete mode 100644 arch/x86_64/kernel/warmreboot.S delete mode 100644 arch/x86_64/lib/old-checksum.c delete mode 100644 configs/kernel-2.6.10-i586-smp.config delete mode 100644 configs/kernel-2.6.10-i586.config delete mode 100644 configs/kernel-2.6.10-i686-smp.config delete mode 100644 configs/kernel-2.6.10-i686.config delete mode 100644 drivers/acpi/processor.c delete mode 100644 drivers/atm/nicstarmac.h delete mode 100644 drivers/base/interface.c delete mode 100644 drivers/block/paride/setup.h delete mode 100644 drivers/cdrom/mcd.c delete mode 100644 drivers/cdrom/mcd.h delete mode 100644 drivers/char/README.cycladesZ delete mode 100644 drivers/char/agp/intel-mch-agp.c delete mode 100644 drivers/char/console_macros.h delete mode 100644 drivers/char/digi_bios.h delete mode 100644 drivers/char/digi_fep.h delete mode 100644 drivers/char/drm/ati_pcigart.h delete mode 100644 drivers/char/drm/drm_agpsupport.h delete mode 100644 drivers/char/drm/drm_auth.h delete mode 100644 drivers/char/drm/drm_bufs.h delete mode 100644 drivers/char/drm/drm_context.h delete mode 100644 drivers/char/drm/drm_dma.h delete mode 100644 drivers/char/drm/drm_drawable.h delete mode 100644 drivers/char/drm/drm_drv.h delete mode 100644 drivers/char/drm/drm_fops.h delete mode 100644 drivers/char/drm/drm_init.h delete mode 100644 drivers/char/drm/drm_ioctl.h delete mode 100644 drivers/char/drm/drm_irq.h delete mode 100644 drivers/char/drm/drm_lock.h delete mode 100644 drivers/char/drm/drm_proc.h delete mode 100644 drivers/char/drm/drm_scatter.h delete mode 100644 drivers/char/drm/drm_stub.h delete mode 100644 drivers/char/drm/drm_vm.h delete mode 100644 drivers/char/drm/ffb.h delete mode 100644 drivers/char/drm/gamma.h delete mode 100644 drivers/char/drm/i810.h delete mode 100644 drivers/char/drm/i830.h delete mode 100644 drivers/char/drm/i915.h delete mode 100644 drivers/char/drm/mga.h delete mode 100644 drivers/char/drm/r128.h delete mode 100644 drivers/char/drm/radeon.h delete mode 100644 drivers/char/drm/sis.h delete mode 100644 drivers/char/drm/tdfx.h delete mode 100644 drivers/char/fep.h delete mode 100644 drivers/char/hp600_keyb.c delete mode 100644 drivers/char/ip2/Makefile delete mode 100644 drivers/char/ip2/ip2mkdev.c delete mode 100644 drivers/char/ip2/ip2stat.c delete mode 100644 drivers/char/ip2/ip2trace.c delete mode 100644 drivers/char/pcxx.c delete mode 100644 drivers/char/pcxx.h delete mode 100644 drivers/char/rio/cdproto.h delete mode 100644 drivers/char/rsf16fmi.h delete mode 100644 drivers/char/serial_tx3912.c delete mode 100644 drivers/char/serial_tx3912.h delete mode 100644 drivers/char/sonypi.h delete mode 100644 drivers/char/tpqic02.c delete mode 100644 drivers/cpufreq/proc_intf.c delete mode 100644 drivers/ide/ide-default.c delete mode 100644 drivers/ide/pci/adma100.c delete mode 100644 drivers/ide/pci/adma100.h delete mode 100644 drivers/ide/pci/aec62xx.h delete mode 100644 drivers/ide/pci/cmd64x.h delete mode 100644 drivers/ide/pci/cy82c693.h delete mode 100644 drivers/ide/pci/delkin_cb.c delete mode 100644 drivers/ide/pci/generic.h delete mode 100644 drivers/ide/pci/hpt366.h delete mode 100644 drivers/ide/pci/it8172.h delete mode 100644 drivers/ide/pci/opti621.h delete mode 100644 drivers/ide/pci/pdc202xx_new.h delete mode 100644 drivers/ide/pci/pdc202xx_old.h delete mode 100644 drivers/ide/pci/piix.h delete mode 100644 drivers/ide/pci/serverworks.h delete mode 100644 drivers/isdn/tpam/Kconfig delete mode 100644 drivers/isdn/tpam/Makefile delete mode 100644 drivers/isdn/tpam/tpam.h delete mode 100644 drivers/isdn/tpam/tpam_commands.c delete mode 100644 drivers/isdn/tpam/tpam_crcpc.c delete mode 100644 drivers/isdn/tpam/tpam_hdlc.c delete mode 100644 drivers/isdn/tpam/tpam_main.c delete mode 100644 drivers/isdn/tpam/tpam_memory.c delete mode 100644 drivers/isdn/tpam/tpam_nco.c delete mode 100644 drivers/isdn/tpam/tpam_queues.c delete mode 100644 drivers/media/dvb/b2c2/b2c2-common.c delete mode 100644 drivers/media/dvb/b2c2/b2c2-usb-core.c delete mode 100644 drivers/media/dvb/bt8xx/dst.h delete mode 100644 drivers/media/dvb/dibusb/dvb-dibusb.c delete mode 100644 drivers/media/video/tuner.c delete mode 100644 drivers/mtd/devices/doc1000.c delete mode 100644 drivers/mtd/maps/ich2rom.c delete mode 100644 drivers/net/bagetlance.c delete mode 100644 drivers/net/ethertap.c delete mode 100644 drivers/net/fc/Makefile delete mode 100644 drivers/net/fc/iph5526.c delete mode 100644 drivers/net/fc/iph5526_ip.h delete mode 100644 drivers/net/fc/iph5526_novram.c delete mode 100644 drivers/net/fc/iph5526_scsi.h delete mode 100644 drivers/net/fc/tach.h delete mode 100644 drivers/net/fc/tach_structs.h delete mode 100644 drivers/net/net_init.c delete mode 100644 drivers/net/netdump.c delete mode 100644 drivers/net/netdump.h delete mode 100644 drivers/pcmcia/bulkmem.c delete mode 100644 drivers/scsi/dpt/dpt_osdutil.h delete mode 100644 drivers/scsi/fd_mcs.h delete mode 100644 drivers/scsi/lasi700.h create mode 100644 drivers/scsi/lpfc/Makefile create mode 100644 drivers/scsi/lpfc/lpfc.h create mode 100644 drivers/scsi/lpfc/lpfc_compat.h create mode 100644 drivers/scsi/lpfc/lpfc_crtn.h create mode 100644 drivers/scsi/lpfc/lpfc_ct.c create mode 100644 drivers/scsi/lpfc/lpfc_disc.h create mode 100644 drivers/scsi/lpfc/lpfc_els.c create mode 100644 drivers/scsi/lpfc/lpfc_hbadisc.c create mode 100644 drivers/scsi/lpfc/lpfc_hw.h create mode 100644 drivers/scsi/lpfc/lpfc_init.c create mode 100644 drivers/scsi/lpfc/lpfc_logmsg.h create mode 100644 drivers/scsi/lpfc/lpfc_mbox.c create mode 100644 drivers/scsi/lpfc/lpfc_mem.c create mode 100644 drivers/scsi/lpfc/lpfc_nportdisc.c create mode 100644 drivers/scsi/lpfc/lpfc_scsi.h create mode 100644 drivers/scsi/lpfc/lpfc_sli.c create mode 100644 drivers/scsi/lpfc/lpfc_sli.h create mode 100644 drivers/scsi/lpfc/lpfc_version.h delete mode 100644 drivers/scsi/qla2xxx/ql6322.c delete mode 100644 drivers/scsi/qla2xxx/ql6322_fw.c delete mode 100644 drivers/scsi/qla2xxx/qla_listops.h delete mode 100644 drivers/scsi/qlogicfc.h delete mode 100644 drivers/scsi/qlogicisp.h delete mode 100644 drivers/scsi/scsi_obsolete.h delete mode 100644 drivers/scsi/scsi_syms.c delete mode 100644 drivers/scsi/sym53c8xx_2/sym_conf.h delete mode 100644 drivers/scsi/sym53c8xx_2/sym_misc.c delete mode 100644 drivers/usb/image/hpusbscsi.c delete mode 100644 drivers/usb/image/hpusbscsi.h delete mode 100644 drivers/usb/media/pwc/ChangeLog delete mode 100644 drivers/usb/media/pwc/pwc-dec1.c delete mode 100644 drivers/usb/media/pwc/pwc-dec1.h delete mode 100644 drivers/usb/media/pwc/pwc-dec23.c delete mode 100644 drivers/usb/media/pwc/pwc-dec23.h delete mode 100644 drivers/usb/misc/tiglusb.c delete mode 100644 drivers/usb/misc/tiglusb.h delete mode 100644 drivers/video/intelfb/intelfbdrv.h delete mode 100644 drivers/video/savage/savagefb.c delete mode 100644 fs/fat/fatfs_syms.c delete mode 100644 fs/jfs/jfs_defragfs.h delete mode 100644 fs/smbfs/ChangeLog delete mode 100644 fs/umsdos/Makefile delete mode 100644 fs/umsdos/README-WIP.txt delete mode 100644 fs/umsdos/dir.c delete mode 100644 fs/umsdos/emd.c delete mode 100644 fs/umsdos/inode.c delete mode 100644 fs/umsdos/ioctl.c delete mode 100644 fs/umsdos/mangle.c delete mode 100644 fs/umsdos/namei.c delete mode 100644 fs/umsdos/rdir.c delete mode 100644 fs/umsdos/specs delete mode 100644 include/asm-arm/arch-omap/clocks.h delete mode 100644 include/asm-arm26/calls.h delete mode 100644 include/asm-arm26/ian_char.h delete mode 100644 include/asm-generic/netdump.h delete mode 100644 include/asm-i386/netdump.h delete mode 100644 include/asm-ia64/ioctl32.h delete mode 100644 include/asm-ia64/netdump.h delete mode 100644 include/asm-ia64/sn/fetchop.h delete mode 100644 include/asm-ia64/sn/router.h delete mode 100644 include/asm-ia64/sn/sn_fru.h delete mode 100644 include/asm-ia64/sn/sndrv.h delete mode 100644 include/asm-m68k/adb_mouse.h delete mode 100644 include/asm-m68k/atari_SCCserial.h delete mode 100644 include/asm-m68knommu/io_hw_swap.h delete mode 100644 include/asm-m68knommu/keyboard.h delete mode 100644 include/asm-m68knommu/nap.h delete mode 100644 include/asm-m68knommu/semp3.h delete mode 100644 include/asm-mips/it8172/it8172_lpc.h delete mode 100644 include/asm-mips/ng1.h delete mode 100644 include/asm-mips/ng1hw.h delete mode 100644 include/asm-mips/vr41xx/vrc4171.h delete mode 100644 include/asm-parisc/bootdata.h delete mode 100644 include/asm-parisc/parport_gsc.h create mode 100644 include/asm-ppc/mv64x60.h create mode 100644 include/asm-ppc/mv64x60_defs.h delete mode 100644 include/asm-ppc64/iSeries/ItLpPaca.h delete mode 100644 include/asm-ppc64/iSeries/iSeries_VpdInfo.h delete mode 100644 include/asm-ppc64/iSeries/iSeries_fixup.h delete mode 100644 include/asm-ppc64/netdump.h delete mode 100644 include/asm-s390/netdump.h delete mode 100644 include/asm-um/arch-signal-i386.h delete mode 100644 include/asm-um/elf.h delete mode 100644 include/asm-x86_64/ioctl32.h delete mode 100644 include/asm-x86_64/ipc.h delete mode 100644 include/asm-x86_64/netdump.h delete mode 100644 include/linux/affs_fs_i.h delete mode 100644 include/linux/affs_fs_sb.h delete mode 100644 include/linux/blk.h delete mode 100644 include/linux/compiler-gcc+.h delete mode 100644 include/linux/dp83840.h delete mode 100644 include/linux/iso_fs_i.h delete mode 100644 include/linux/iso_fs_sb.h delete mode 100644 include/linux/msdos_fs_i.h delete mode 100644 include/linux/msdos_fs_sb.h delete mode 100644 include/linux/netfilter_ipv4/compat_firewall.h delete mode 100644 include/linux/netfilter_ipv4/ipchains_core.h delete mode 100644 include/linux/netfilter_ipv4/ipfwadm_core.h delete mode 100644 include/linux/tpqic02.h delete mode 100644 include/linux/umsdos_fs.h delete mode 100644 include/linux/umsdos_fs.p delete mode 100644 include/linux/umsdos_fs_i.h delete mode 100644 include/linux/vserver/signal.h delete mode 100644 include/sound/soundmem.h delete mode 100644 include/sound/yss225.h delete mode 100644 net/ipv4/ipvs/ip_vs_proto_icmp.c delete mode 100644 net/ipv4/netfilter/ip_fw_compat.c delete mode 100644 net/ipv4/netfilter/ip_fw_compat.h delete mode 100644 net/ipv4/netfilter/ip_fw_compat_masq.c delete mode 100644 net/ipv4/netfilter/ip_fw_compat_redir.c delete mode 100644 net/ipv4/netfilter/ipchains_core.c delete mode 100644 net/ipv4/netfilter/ipfwadm_core.c delete mode 100644 net/ipv6/README delete mode 100644 net/netlink/netlink_dev.c delete mode 100644 net/sunrpc/auth_gss/gss_pseudoflavors.c delete mode 100644 net/sunrpc/auth_gss/sunrpcgss_syms.c delete mode 100644 net/sunrpc/svcauth_des.c delete mode 100644 net/xfrm/xfrm_export.c delete mode 100644 scripts/README.Menuconfig delete mode 100644 scripts/kconfig/.kxgettext.o.cmd delete mode 100644 scripts/kconfig/kxgettext.o delete mode 100755 scripts/makeman delete mode 100755 scripts/split-man delete mode 100644 sound/core/ioctl32/Makefile delete mode 100644 sound/core/ioctl32/hwdep32.c delete mode 100644 sound/core/ioctl32/ioctl32.c delete mode 100644 sound/core/ioctl32/ioctl32.h delete mode 100644 sound/core/ioctl32/pcm32.c delete mode 100644 sound/core/ioctl32/rawmidi32.c delete mode 100644 sound/core/ioctl32/seq32.c delete mode 100644 sound/core/ioctl32/timer32.c delete mode 100644 sound/core/seq/oss/seq_oss_misc.c delete mode 100644 sound/isa/gus/gus_lfo.c delete mode 100644 sound/oss/cs4232.h delete mode 100644 sound/oss/maestro_tables.h delete mode 100644 usr/initramfs_list diff --git a/CREDITS b/CREDITS index c0bdfc51a..d65ffe5a4 100644 --- a/CREDITS +++ b/CREDITS @@ -34,8 +34,9 @@ N: Dave Airlie E: airlied@linux.ie W: http://www.csn.ul.ie/~airlied D: NFS over TCP patches -S: University of Limerick -S: Ireland +D: in-kernel DRM Maintainer +S: Longford, Ireland +S: Sydney, Australia N: Tigran A. Aivazian E: tigran@veritas.com @@ -328,8 +329,6 @@ S: Brimson, MN 55602 S: USA N: Hennus Bergman -E: hennus@cybercomm.nl -W: http://www.cybercomm.nl/~hennus/ P: 1024/77D50909 76 99 FD 31 91 E1 96 1C 90 BB 22 80 62 F6 BD 63 D: Author and maintainer of the QIC-02 tape driver S: The Netherlands @@ -340,7 +339,7 @@ W: http://tomas.nocrew.org/ D: dsp56k device driver N: Ross Biro -E: bir7@leland.Stanford.Edu +E: ross.biro@gmail.com D: Original author of the Linux networking code N: Anton Blanchard @@ -805,6 +804,21 @@ S: One Dell Way S: Round Rock, TX 78682 S: USA +N: Ben Dooks +E: ben-linux@fluff.org +E: ben@simtec.co.uk +W: http://www.fluff.org/ben/ +W: http://www.simtec.co.uk/ +D: Samsung S3C2410/S3C2440 support, general ARM support +D: Maintaining Simtec Electronics development boards +S: Simtec Electronics +S: Avondale Drive +S: Tarleton +S: Preston +S: Lancs +S: PR4 6AX +S: United Kingdom + N: John G Dorsey E: john+@cs.cmu.edu D: ARM Linux ports to Assabet/Neponset, Spot @@ -826,6 +840,11 @@ E: cort@fsmlabs.com W: http://www.fsmlabs.com/linuxppcbk.html D: PowerPC +N: Daniel Drake +E: dsd@gentoo.org +D: USBAT02 CompactFlash support in usb-storage +S: UK + N: Oleg Drokin E: green@ccssu.crimea.ua W: http://www.ccssu.crimea.ua/~green @@ -863,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 @@ -1080,7 +1098,7 @@ S: Brazil N: Kumar Gala E: kumar.gala@freescale.com -D: Embedded PowerPC 6xx/7xx/74xx/82xx/85xx support +D: Embedded PowerPC 6xx/7xx/74xx/82xx/83xx/85xx support S: Austin, Texas 78729 S: USA @@ -1811,7 +1829,8 @@ D: CYPRESS CY82C693 chipset IDE, Digital's PC-Alpha 164SX boards N: Greg Kroah-Hartman E: greg@kroah.com -W: http://www.kroah.com/linux-usb/ +E: gregkh@suse.de +W: http://www.kroah.com/linux/ D: USB Serial Converter driver framework, USB Handspring Visor driver D: ConnectTech WHITEHeat USB driver, Generic USB Serial driver D: USB I/O Edgeport driver, USB Serial IrDA driver @@ -1819,6 +1838,7 @@ D: USB Bluetooth driver, USB Skeleton driver D: bits and pieces of USB core code. D: PCI Hotplug core, PCI Hotplug Compaq driver modifications D: portions of the Linux Security Module (LSM) framework +D: parts of the driver core, debugfs. N: Russell Kroll E: rkroll@exploits.org @@ -1937,7 +1957,8 @@ S: Germany N: Colin Leroy E: colin@colino.net W: http://www.geekounet.org/ -D: PowerMac adt7467 fan driver +D: PowerMac adt746x fan driver +D: Random fixing of various drivers (macintosh, usb, sound) S: Toulouse S: France @@ -2021,6 +2042,17 @@ N: H.J. Lu E: hjl@gnu.ai.mit.edu D: GCC + libraries hacker +N: Michal Ludvig +E: michal@logix.cz +E: michal.ludvig@asterisk.co.nz +W: http://www.logix.cz/michal +P: 1024D/C45B2218 1162 6471 D391 76E0 9F99 29DA 0C3A 2509 C45B 2218 +D: VIA PadLock driver +D: Netfilter pkttype module +S: Asterisk Ltd. +S: Auckland +S: New Zealand + N: Tuomas J. Lukka E: Tuomas.Lukka@Helsinki.FI D: Original dual-monitor patches @@ -2443,13 +2475,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 @@ -2927,10 +2955,10 @@ S: 03600 Karkkila S: Finland N: Deepak Saxena -E: deepak@csociety.purdue.edu +E: dsaxena@plexity.net D: I2O kernel layer (config, block, core, pci, net). I2O disk support for LILO -D: XScale(IOP310) porting -S: Tempe, Arizona +D: XScale(IOP, IXP) porting and other random ARM bits +S: Portland, OR N: Eric Schenk E: Eric.Schenk@dna.lth.se @@ -3156,6 +3184,14 @@ S: Department of Zoology, University of Washington S: Seattle, WA 98195-1800 S: USA +N: Eugene Surovegin +E: ebs@ebshome.net +W: http://kernel.ebshome.net/ +P: 1024D/AE5467F1 FF22 39F1 6728 89F6 6E6C 2365 7602 F33D AE54 67F1 +D: Embedded PowerPC 4xx: I2C, PIC and random hacks/fixes +S: Sunnyvale, California 94085 +S: USA + N: Corey Thomas E: corey@world.std.com W: http://world.std.com/~corey/index.html @@ -3258,6 +3294,7 @@ D: Author of the new e2fsck D: Author of job control and system call restart code D: Author of ramdisk device driver D: Author of loopback device driver +D: Author of /dev/random driver S: MIT Room E40-343 S: 1 Amherst Street S: Cambridge, Massachusetts 02139 @@ -3315,10 +3352,11 @@ S: Santa Clara, CA 95054 S: USA N: Matthias Urlichs -E: urlichs@noris.de -E: urlichs@smurf.sub.org +E: smurf@smurf.noris.de +E: smurf@debian.org +E: matthias@urlichs.de D: Consultant, developer, kernel hacker -D: Playing with Streams, ISDN, and BSD networking code for Linux +D: In a previous life, worked on Streams/ISDN/BSD networking code for Linux S: Schleiermacherstrasse 12 S: 90491 Nuernberg S: Germany @@ -3335,7 +3373,7 @@ D: Amiga Buddha and Catweasel chipset IDE D: Atari Falcon chipset IDE D: Amiga Gayle chipset IDE D: mipsel NEC DDB Vrc-5074 -S: Holsbeeksesteenweg 166 +S: Emiel Vlieberghlaan 2A/21 S: B-3010 Kessel-Lo S: Belgium @@ -3390,6 +3428,7 @@ N: Jeroen Vreeken E: pe1rxq@amsat.org W: http://www.chello.nl/~j.vreeken/ D: SE401 usb webcam driver +D: ZD1201 usb wireless lan driver S: Maastrichterweg 63 S: 5554 GG Valkenswaard S: The Netherlands @@ -3569,7 +3608,6 @@ S: The Netherlands N: David Woodhouse E: dwmw2@infradead.org -E: dwmw2@redhat.com D: ARCnet stuff, Applicom board driver, SO_BINDTODEVICE, D: some Alpha platform porting from 2.0, Memory Technology Devices, D: Acquire watchdog timer, PC speaker driver maintenance, diff --git a/Documentation/BK-usage/00-INDEX b/Documentation/BK-usage/00-INDEX deleted file mode 100644 index 82768784e..000000000 --- a/Documentation/BK-usage/00-INDEX +++ /dev/null @@ -1,51 +0,0 @@ -bk-kernel-howto.txt: Description of kernel workflow under BitKeeper - -bk-make-sum: Create summary of changesets in one repository and not -another, typically in preparation to be sent to an upstream maintainer. -Typical usage: - cd my-updated-repo - bk-make-sum ~/repo/original-repo - mv /tmp/linus.txt ../original-repo.txt - -bksend: Create readable text output containing summary of changes, GNU -patch of the changes, and BK metadata of changes (as needed for proper -importing into BitKeeper by an upstream maintainer). This output is -suitable for emailing BitKeeper changes. The recipient of this output -may pipe it directly to 'bk receive'. - -bz64wrap: helper script. Uncompressed input is piped to this script, -which compresses its input, and then outputs the uu-/base64-encoded -version of the compressed input. - -cpcset: Copy changeset between unrelated repositories. -Attempts to preserve changeset user, user address, description, in -addition to the changeset (the patch) itself. -Typical usage: - cd my-updated-repo - bk changes # looking for a changeset... - cpcset 1.1511 . ../another-repo - -csets-to-patches: Produces a delta of two BK repositories, in the form -of individual files, each containing a single cset as a GNU patch. -Output is several files, each with the filename "/tmp/rev-$REV.patch" -Typical usage: - cd my-updated-repo - bk changes -L ~/repo/original-repo 2>&1 | \ - perl csets-to-patches - -cset-to-linus: Produces a delta of two BK repositories, in the form of -changeset descriptions, with 'diffstat' output created for each -individual changset. -Typical usage: - cd my-updated-repo - bk changes -L ~/repo/original-repo 2>&1 | \ - perl cset-to-linus > summary.txt - -gcapatch: Generates patch containing changes in local repository. -Typical usage: - cd my-updated-repo - gcapatch > foo.patch - -unbz64wrap: Reverse an encoded, compressed data stream created by -bz64wrap into an uncompressed, typically text/plain output. - diff --git a/Documentation/BK-usage/bk-kernel-howto.txt b/Documentation/BK-usage/bk-kernel-howto.txt deleted file mode 100644 index b7b9075d2..000000000 --- a/Documentation/BK-usage/bk-kernel-howto.txt +++ /dev/null @@ -1,283 +0,0 @@ - - Doing the BK Thing, Penguin-Style - - - - -This set of notes is intended mainly for kernel developers, occasional -or full-time, but sysadmins and power users may find parts of it useful -as well. It assumes at least a basic familiarity with CVS, both at a -user level (use on the cmd line) and at a higher level (client-server model). -Due to the author's background, an operation may be described in terms -of CVS, or in terms of how that operation differs from CVS. - -This is -not- intended to be BitKeeper documentation. Always run -"bk help " or in X "bk helptool " for reference -documentation. - - -BitKeeper Concepts ------------------- - -In the true nature of the Internet itself, BitKeeper is a distributed -system. When applied to revision control, this means doing away with -client-server, and changing to a parent-child model... essentially -peer-to-peer. On the developer's end, this also represents a -fundamental disruption in the standard workflow of changes, commits, -and merges. You will need to take a few minutes to think about -how to best work under BitKeeper, and re-optimize things a bit. -In some sense it is a bit radical, because it might described as -tossing changes out into a maelstrom and having them magically -land at the right destination... but I'm getting ahead of myself. - -Let's start with this progression: -Each BitKeeper source tree on disk is a repository unto itself. -Each repository has a parent (except the root/original, of course). -Each repository contains a set of a changesets ("csets"). -Each cset is one or more changed files, bundled together. - -Each tree is a repository, so all changes are checked into the local -tree. When a change is checked in, all modified files are grouped -into a logical unit, the changeset. Internally, BK links these -changesets in a tree, representing various converging and diverging -lines of development. These changesets are the bread and butter of -the BK system. - -After the concept of changesets, the next thing you need to get used -to is having multiple copies of source trees lying around. This -really- -takes some getting used to, for some people. Separate source trees -are the means in BitKeeper by which you delineate parallel lines -of development, both minor and major. What would be branches in -CVS become separate source trees, or "clones" in BitKeeper [heh, -or Star Wars] terminology. - -Clones and changesets are the tools from which most of the power of -BitKeeper is derived. As mentioned earlier, each clone has a parent, -the tree used as the source when the new clone was created. In a -CVS-like setup, the parent would be a remote server on the Internet, -and the child is your local clone of that tree. - -Once you have established a common baseline between two source trees -- -a common parent -- then you can merge changesets between those two -trees with ease. Merging changes into a tree is called a "pull", and -is analagous to 'cvs update'. A pull downloads all the changesets in -the remote tree you do not have, and merges them. Sending changes in -one tree to another tree is called a "push". Push sends all changes -in the local tree the remote does not yet have, and merges them. - -From these concepts come some initial command examples: - -1) bk clone -q http://linux.bkbits.net/linux-2.5 linus-2.5 -Download a 2.5 stock kernel tree, naming it "linus-2.5" in the local dir. -The "-q" disables listing every single file as it is downloaded. - -2) bk clone -ql linus-2.5 alpha-2.5 -Create a separate source tree for the Alpha AXP architecture. -The "-l" uses hard links instead of copying data, since both trees are -on the local disk. You can also replace the above with "bk lclone -q ..." - -You only clone a tree -once-. After cloning the tree lives a long time -on disk, being updating by pushes and pulls. - -3) cd alpha-2.5 ; bk pull http://gkernel.bkbits.net/alpha-2.5 -Download changes in "alpha-2.5" repository which are not present -in the local repository, and merge them into the source tree. - -4) bk -r co -q -Because every tree is a repository, files must be checked out before -they will be in their standard places in the source tree. - -5) bk vi fs/inode.c # example change... - bk citool # checkin, using X tool - bk push bk://gkernel@bkbits.net/alpha-2.5 # upload change -Typical example of a BK sequence that would replace the analagous CVS -situation, - vi fs/inode.c - cvs commit - -As this is just supposed to be a quick BK intro, for more in-depth -tutorials, live working demos, and docs, see http://www.bitkeeper.com/ - - - -BK and Kernel Development Workflow ----------------------------------- -Currently the latest 2.5 tree is available via "bk clone $URL" -and "bk pull $URL" at http://linux.bkbits.net/linux-2.5 -This should change in a few weeks to a kernel.org URL. - - -A big part of using BitKeeper is organizing the various trees you have -on your local disk, and organizing the flow of changes among those -trees, and remote trees. If one were to graph the relationships between -a desired BK setup, you are likely to see a few-many-few graph, like -this: - - linux-2.5 - | - merge-to-linus-2.5 - / | | - / | | - vm-hacks bugfixes filesys personal-hacks - \ | | / - \ | | / - \ | | / - testing-and-validation - -Since a "bk push" sends all changes not in the target tree, and -since a "bk pull" receives all changes not in the source tree, you want -to make sure you are only pushing specific changes to the desired tree, -not all changes from "peer parent" trees. For example, pushing a change -from the testing-and-validation tree would probably be a bad idea, -because it will push all changes from vm-hacks, bugfixes, filesys, and -personal-hacks trees into the target tree. - -One would typically work on only one "theme" at a time, either -vm-hacks or bugfixes or filesys, keeping those changes isolated in -their own tree during development, and only merge the isolated with -other changes when going upstream (to Linus or other maintainers) or -downstream (to your "union" trees, like testing-and-validation above). - -It should be noted that some of this separation is not just recommended -practice, it's actually [for now] -enforced- by BitKeeper. BitKeeper -requires that changesets maintain a certain order, which is the reason -that "bk push" sends all local changesets the remote doesn't have. This -separation may look like a lot of wasted disk space at first, but it -helps when two unrelated changes may "pollute" the same area of code, or -don't follow the same pace of development, or any other of the standard -reasons why one creates a development branch. - -Small development branches (clones) will appear and disappear: - - -------- A --------- B --------- C --------- D ------- - \ / - -----short-term devel branch----- - -While long-term branches will parallel a tree (or trees), with period -merge points. In this first example, we pull from a tree (pulls, -"\") periodically, such as what occurs when tracking changes in a -vendor tree, never pushing changes back up the line: - - -------- A --------- B --------- C --------- D ------- - \ \ \ - ----long-term devel branch----------------- - -And then a more common case in Linux kernel development, a long term -branch with periodic merges back into the tree (pushes, "/"): - - -------- A --------- B --------- C --------- D ------- - \ \ / \ - ----long-term devel branch----------------- - - - - - -Submitting Changes to Linus ---------------------------- -There's a bit of an art, or style, of submitting changes to Linus. -Since Linus's tree is now (you might say) fully integrated into the -distributed BitKeeper system, there are several prerequisites to -properly submitting a BitKeeper change. All these prereq's are just -general cleanliness of BK usage, so as people become experts at BK, feel -free to optimize this process further (assuming Linus agrees, of -course). - - - -0) Make sure your tree was originally cloned from the linux-2.5 tree -created by Linus. If your tree does not have this as its ancestor, it -is impossible to reliably exchange changesets. - - - -1) Pay attention to your commit text. The commit message that -accompanies each changeset you submit will live on forever in history, -and is used by Linus to accurately summarize the changes in each -pre-patch. Remember that there is no context, so - "fix for new scheduler changes" -would be too vague, but - "fix mips64 arch for new scheduler switch_to(), TIF_xxx semantics" -would be much better. - -You can and should use the command "bk comment -C" to update the -commit text, and improve it after the fact. This is very useful for -development: poor, quick descriptions during development, which get -cleaned up using "bk comment" before issuing the "bk push" to submit the -changes. - - - -2) Include an Internet-available URL for Linus to pull from, such as - - Pull from: http://gkernel.bkbits.net/net-drivers-2.5 - - - -3) Include a summary and "diffstat -p1" of each changeset that will be -downloaded, when Linus issues a "bk pull". The author auto-generates -these summaries using "bk changes -L ", to obtain a listing -of all the pending-to-send changesets, and their commit messages. - -It is important to show Linus what he will be downloading when he issues -a "bk pull", to reduce the time required to sift the changes once they -are downloaded to Linus's local machine. - -IMPORTANT NOTE: One of the features of BK is that your repository does -not have to be up to date, in order for Linus to receive your changes. -It is considered a courtesy to keep your repository fairly recent, to -lessen any potential merge work Linus may need to do. - - -4) Split up your changes. Each maintainer<->Linus situation is likely -to be slightly different here, so take this just as general advice. The -author splits up changes according to "themes" when merging with Linus. -Simultaneous pushes from local development go to special trees which -exist solely to house changes "queued" for Linus. Example of the trees: - - net-drivers-2.5 -- on-going net driver maintenance - vm-2.5 -- VM-related changes - fs-2.5 -- filesystem-related changes - -Linus then has much more freedom for pulling changes. He could (for -example) issue a "bk pull" on vm-2.5 and fs-2.5 trees, to merge their -changes, but hold off net-drivers-2.5 because of a change that needs -more discussion. - -Other maintainers may find that a single linus-pull-from tree is -adequate for passing BK changesets to him. - - - -Frequently Answered Questions ------------------------------ -1) How do I change the e-mail address shown in the changelog? -A. When you run "bk citool" or "bk commit", set environment - variables BK_USER and BK_HOST to the desired username - and host/domain name. - - -2) How do I use tags / get a diff between two kernel versions? -A. Pass the tags Linus uses to 'bk export'. - -ChangeSets are in a forward-progressing order, so it's pretty easy -to get a snapshot starting and ending at any two points in time. -Linus puts tags on each release and pre-release, so you could use -these two examples: - - bk export -tpatch -hdu -rv2.5.4,v2.5.5 | less - # creates patch-2.5.5 essentially - bk export -tpatch -du -rv2.5.5-pre1,v2.5.5 | less - # changes from pre1 to final - -A tag is just an alias for a specific changeset... and since changesets -are ordered, a tag is thus a marker for a specific point in time (or -specific state of the tree). - - -3) Is there an easy way to generate One Big Patch versus mainline, - for my long-lived kernel branch? -A. Yes. This requires BK 3.x, though. - - bk export -tpatch -r`bk repogca bk://linux.bkbits.net/linux-2.5`,+ - diff --git a/Documentation/BK-usage/bk-make-sum b/Documentation/BK-usage/bk-make-sum deleted file mode 100755 index 58ca46a0f..000000000 --- a/Documentation/BK-usage/bk-make-sum +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh -e -# DIR=$HOME/BK/axp-2.5 -# cd $DIR - -LINUS_REPO=$1 -DIRBASE=`basename $PWD` - -{ -cat </dev/null - -cat < (:D: :I:)\n$each(:C:){ (:C:)\n}\n}' - - -} > /tmp/linus.txt - -cat < 13/02/2002 -# -# Add diffstat output after Changelog 21/02/2002 - -PROG=bksend - -usage() { - echo "usage: $PROG -r" - echo -e "\twhere is of the form '1.23', '1.23..', '1.23..1.27'," - echo -e "\tor '+' to indicate the most recent revision" - - exit 1 -} - -case $1 in --r) REV=$2; shift ;; --r*) REV=`echo $1 | sed 's/^-r//'` ;; -*) echo "$PROG: no revision given, you probably don't want that";; -esac - -[ -z "$REV" ] && usage - -echo "You can import this changeset into BK by piping this whole message to:" -echo "'| bk receive [path to repository]' or apply the patch as usual." - -SEP="\n===================================================================\n\n" -echo -e $SEP -bk changes -r$REV -echo -bk export -tpatch -du -h -r$REV | diffstat -echo; echo -bk export -tpatch -du -h -r$REV -echo -e $SEP -bk send -wgzip_uu -r$REV - diff --git a/Documentation/BK-usage/bz64wrap b/Documentation/BK-usage/bz64wrap deleted file mode 100755 index be7808768..000000000 --- a/Documentation/BK-usage/bz64wrap +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/sh - -# bz64wrap - the sending side of a bzip2 | base64 stream -# Andreas Dilger Jan 2002 - - -PATH=$PATH:/usr/bin:/usr/local/bin:/usr/freeware/bin - -# A program to generate base64 encoding on stdout -BASE64_ENCODE="uuencode -m /dev/stdout" -BASE64_BEGIN= -BASE64_END= - -BZIP=NO -BASE64=NO - -# Test if we have the bzip program installed -bzip2 -c /dev/null > /dev/null 2>&1 && BZIP=YES - -# Test if uuencode can handle the -m (MIME) encoding option -$BASE64_ENCODE < /dev/null > /dev/null 2>&1 && BASE64=YES - -if [ $BASE64 = NO ]; then - BASE64_ENCODE=mimencode - BASE64_BEGIN="begin-base64 644 -" - BASE64_END="====" - - $BASE64_ENCODE < /dev/null > /dev/null 2>&1 && BASE64=YES -fi - -if [ $BZIP = NO -o $BASE64 = NO ]; then - echo "$0: can't use bz64 encoding: bzip2=$BZIP, $BASE64_ENCODE=$BASE64" - exit 1 -fi - -# Sadly, mimencode does not appear to have good "begin" and "end" markers -# like uuencode does, and it is picky about getting the right start/end of -# the base64 stream, so we handle this internally. -echo "$BASE64_BEGIN" -bzip2 -9 | $BASE64_ENCODE -echo "$BASE64_END" diff --git a/Documentation/BK-usage/cpcset b/Documentation/BK-usage/cpcset deleted file mode 100755 index b8faca97d..000000000 --- a/Documentation/BK-usage/cpcset +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh -# -# Purpose: Copy changeset patch and description from one -# repository to another, unrelated one. -# -# usage: cpcset [revision] [from-repository] [to-repository] -# - -REV=$1 -FROM=$2 -TO=$3 -TMPF=/tmp/cpcset.$$ - -rm -f $TMPF* - -CWD_SAVE=`pwd` -cd $FROM -bk changes -r$REV | \ - grep -v '^ChangeSet' | \ - sed -e 's/^ //g' > $TMPF.log - -USERHOST=`bk changes -r$REV | grep '^ChangeSet' | awk '{print $4}'` -export BK_USER=`echo $USERHOST | awk '-F@' '{print $1}'` -export BK_HOST=`echo $USERHOST | awk '-F@' '{print $2}'` - -bk export -tpatch -hdu -r$REV > $TMPF.patch && \ -cd $CWD_SAVE && \ -cd $TO && \ -bk import -tpatch -CFR -y"`cat $TMPF.log`" $TMPF.patch . && \ -bk commit -y"`cat $TMPF.log`" - -rm -f $TMPF* - -echo changeset $REV copied. -echo "" - diff --git a/Documentation/BK-usage/cset-to-linus b/Documentation/BK-usage/cset-to-linus deleted file mode 100755 index d28a96f8c..000000000 --- a/Documentation/BK-usage/cset-to-linus +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/perl -w - -use strict; - -my ($lhs, $rev, $tmp, $rhs, $s); -my @cset_text = (); -my @pipe_text = (); -my $have_cset = 0; - -while (<>) { - next if /^---/; - - if (($lhs, $tmp, $rhs) = (/^(ChangeSet\@)([^,]+)(, .*)$/)) { - &cset_rev if ($have_cset); - - $rev = $tmp; - $have_cset = 1; - - push(@cset_text, $_); - } - - elsif ($have_cset) { - push(@cset_text, $_); - } -} -&cset_rev if ($have_cset); -exit(0); - - -sub cset_rev { - my $empty_cset = 0; - - open PIPE, "bk export -tpatch -hdu -r $rev | diffstat -p1 2>/dev/null |" or die; - while ($s = ) { - $empty_cset = 1 if ($s =~ /0 files changed/); - push(@pipe_text, $s); - } - close(PIPE); - - if (! $empty_cset) { - print @cset_text; - print @pipe_text; - print "\n\n"; - } - - @pipe_text = (); - @cset_text = (); -} - diff --git a/Documentation/BK-usage/csets-to-patches b/Documentation/BK-usage/csets-to-patches deleted file mode 100755 index e2b81c358..000000000 --- a/Documentation/BK-usage/csets-to-patches +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/perl -w - -use strict; - -my ($lhs, $rev, $tmp, $rhs, $s); -my @cset_text = (); -my @pipe_text = (); -my $have_cset = 0; - -while (<>) { - next if /^---/; - - if (($lhs, $tmp, $rhs) = (/^(ChangeSet\@)([^,]+)(, .*)$/)) { - &cset_rev if ($have_cset); - - $rev = $tmp; - $have_cset = 1; - - push(@cset_text, $_); - } - - elsif ($have_cset) { - push(@cset_text, $_); - } -} -&cset_rev if ($have_cset); -exit(0); - - -sub cset_rev { - my $empty_cset = 0; - - system("bk export -tpatch -du -r $rev > /tmp/rev-$rev.patch"); - - if (! $empty_cset) { - print @cset_text; - print @pipe_text; - print "\n\n"; - } - - @pipe_text = (); - @cset_text = (); -} - diff --git a/Documentation/BK-usage/gcapatch b/Documentation/BK-usage/gcapatch deleted file mode 100755 index aaeb17dc7..000000000 --- a/Documentation/BK-usage/gcapatch +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -# -# Purpose: Generate GNU diff of local changes versus canonical top-of-tree -# -# Usage: gcapatch > foo.patch -# - -bk export -tpatch -hdu -r`bk repogca bk://linux.bkbits.net/linux-2.5`,+ diff --git a/Documentation/BK-usage/unbz64wrap b/Documentation/BK-usage/unbz64wrap deleted file mode 100755 index 4fc3e73e9..000000000 --- a/Documentation/BK-usage/unbz64wrap +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh - -# unbz64wrap - the receiving side of a bzip2 | base64 stream -# Andreas Dilger Jan 2002 - -# Sadly, mimencode does not appear to have good "begin" and "end" markers -# like uuencode does, and it is picky about getting the right start/end of -# the base64 stream, so we handle this explicitly here. - -PATH=$PATH:/usr/bin:/usr/local/bin:/usr/freeware/bin - -if mimencode -u < /dev/null > /dev/null 2>&1 ; then - SHOW= - while read LINE; do - case $LINE in - begin-base64*) SHOW=YES ;; - ====) SHOW= ;; - *) [ "$SHOW" ] && echo "$LINE" ;; - esac - done | mimencode -u | bunzip2 - exit $? -else - cat - | uudecode -o /dev/stdout | bunzip2 - exit $? -fi diff --git a/Documentation/DocBook/kernel-hacking.tmpl b/Documentation/DocBook/kernel-hacking.tmpl index 1e8219d85..49a9ef82d 100644 --- a/Documentation/DocBook/kernel-hacking.tmpl +++ b/Documentation/DocBook/kernel-hacking.tmpl @@ -1,4 +1,6 @@ - + + diff --git a/Documentation/DocBook/libata.tmpl b/Documentation/DocBook/libata.tmpl index 92a405a0e..6df1dfd18 100644 --- a/Documentation/DocBook/libata.tmpl +++ b/Documentation/DocBook/libata.tmpl @@ -1,4 +1,6 @@ - + + @@ -12,7 +14,7 @@ - 2003 + 2003-2005 Jeff Garzik @@ -42,30 +44,38 @@ - - Thanks + + Introduction - 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<->ATA translation + for ATA devices according to the T10 SAT specification. - Thanks to Alan Cox for pointing out similarities - between SATA and SCSI, and in general for motivation to hack on - libata. - - - 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. libata Driver API + + 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. + + + 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. + struct ata_port_operations + Disable ATA port void (*port_disable) (struct ata_port *); @@ -76,6 +86,9 @@ void (*port_disable) (struct ata_port *); unplug). + + + Post-IDENTIFY device configuration void (*dev_config) (struct ata_port *, struct ata_device *); @@ -86,6 +99,9 @@ void (*dev_config) (struct ata_port *, struct ata_device *); issue of SET FEATURES - XFER MODE, and prior to operation. + + + Set PIO/DMA mode void (*set_piomode) (struct ata_port *, struct ata_device *); void (*set_dmamode) (struct ata_port *, struct ata_device *); @@ -106,6 +122,9 @@ void (*post_set_mode) (struct ata_port *ap); ->set_dma_mode() is only called if DMA is possible. + + + Taskfile read/write void (*tf_load) (struct ata_port *ap, struct ata_taskfile *tf); void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf); @@ -118,6 +137,9 @@ void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf); taskfile register values. + + + ATA command execute void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf); @@ -127,17 +149,37 @@ void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf); ->tf_load(), to be initiated in hardware. + + + Per-cmd ATAPI DMA capabilities filter + +int (*check_atapi_dma) (struct ata_queued_cmd *qc); + + + +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. + + + + + Read specific ATA shadow registers 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); - 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. + + + Select ATA device on bus void (*dev_select)(struct ata_port *ap, unsigned int device); @@ -145,9 +187,13 @@ void (*dev_select)(struct ata_port *ap, unsigned int device); 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. + + + Reset ATA bus void (*phy_reset) (struct ata_port *ap); @@ -160,17 +206,31 @@ void (*phy_reset) (struct ata_port *ap); functions ata_bus_reset() or sata_phy_reset() for this hook. + + + Control PCI IDE BMDMA engine 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); - 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. + +These hooks are typically either no-ops, or simply not implemented, in +FIS-based drivers. + + + + + High-level taskfile hooks void (*qc_prep) (struct ata_queued_cmd *qc); int (*qc_issue) (struct ata_queued_cmd *qc); @@ -188,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. + + + Timeout (error) handling void (*eng_timeout) (struct ata_port *ap); - 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(). + + + Hardware interrupt handling irqreturn_t (*irq_handler)(int, void *, struct pt_regs *); void (*irq_clear) (struct ata_port *); @@ -214,6 +280,9 @@ void (*irq_clear) (struct ata_port *); is quiet. + + + SATA phy read/write u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg); void (*scr_write) (struct ata_port *ap, unsigned int sc_reg, @@ -225,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. + + + Init and shutdown int (*port_start) (struct ata_port *ap); void (*port_stop) (struct ata_port *ap); @@ -238,15 +310,17 @@ void (*host_stop) (struct ata_host_set *host_set); tasks. - ->host_stop() is called when the rmmod or hot unplug process - begins. The hook must stop all hardware interrupts, DMA - engines, etc. - - ->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. + + ->host_stop() is called after all ->port_stop() calls +have completed. The hook must finalize hardware shutdown, release DMA +and other resources, etc. + + + @@ -277,4 +351,24 @@ void (*host_stop) (struct ata_host_set *host_set); !Idrivers/scsi/sata_sil.c + + Thanks + + 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. + + + Thanks to Alan Cox for pointing out similarities + between SATA and SCSI, and in general for motivation to hack on + libata. + + + 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). + + + diff --git a/Documentation/DocBook/tulip-user.tmpl b/Documentation/DocBook/tulip-user.tmpl deleted file mode 100644 index b74f8a363..000000000 --- a/Documentation/DocBook/tulip-user.tmpl +++ /dev/null @@ -1,325 +0,0 @@ - - - - - Tulip Driver User's Guide - - - - Jeff - Garzik - -
- jgarzik@pobox.com -
-
-
-
- - - 2001 - Jeff Garzik - - - - - 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. - - - - 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 - - - - For more details see the file COPYING in the source - distribution of Linux. - - -
- - - - - Introduction - -The Tulip Ethernet Card Driver -is maintained by Jeff Garzik (jgarzik@pobox.com). - - - -The Tulip driver was developed by Donald Becker and changed by -Jeff Garzik, Takashi Manabe and a cast of thousands. - - - -For 2.4.x and later kernels, the Linux Tulip driver is available at -http://sourceforge.net/projects/tulip/ - - - - This driver is for the Digital "Tulip" Ethernet adapter interface. - It should work with most DEC 21*4*-based chips/ethercards, as well as - with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and ASIX. - - - - The original author may be reached as becker@scyld.com, or C/O - Scyld Computing Corporation, - 410 Severn Ave., Suite 210, - Annapolis MD 21403 - - - - Additional information on Donald Becker's tulip.c - is available at http://www.scyld.com/network/tulip.html - - - - - - Driver Compatibility - - -This device driver is designed for the DECchip "Tulip", Digital's -single-chip ethernet controllers for PCI (now owned by Intel). -Supported members of the family -are the 21040, 21041, 21140, 21140A, 21142, and 21143. Similar work-alike -chips from Lite-On, Macronics, ASIX, Compex and other listed below are also -supported. - - - -These chips are used on at least 140 unique PCI board designs. The great -number of chips and board designs supported is the reason for the -driver size and complexity. Almost of the increasing complexity is in the -board configuration and media selection code. There is very little -increasing in the operational critical path length. - - - - - Board-specific Settings - - -PCI bus devices are configured by the system at boot time, so no jumpers -need to be set on the board. The system BIOS preferably should assign the -PCI INTA signal to an otherwise unused system IRQ line. - - - -Some boards have EEPROMs tables with default media entry. The factory default -is usually "autoselect". This should only be overridden when using -transceiver connections without link beat e.g. 10base2 or AUI, or (rarely!) -for forcing full-duplex when used with old link partners that do not do -autonegotiation. - - - - - Driver Operation - -Ring buffers - - -The Tulip can use either ring buffers or lists of Tx and Rx descriptors. -This driver uses statically allocated rings of Rx and Tx descriptors, set at -compile time by RX/TX_RING_SIZE. This version of the driver allocates skbuffs -for the Rx ring buffers at open() time and passes the skb->data field to the -Tulip as receive data buffers. When an incoming frame is less than -RX_COPYBREAK bytes long, a fresh skbuff is allocated and the frame is -copied to the new skbuff. When the incoming frame is larger, the skbuff is -passed directly up the protocol stack and replaced by a newly allocated -skbuff. - - - -The RX_COPYBREAK value is chosen to trade-off the memory wasted by -using a full-sized skbuff for small frames vs. the copying costs of larger -frames. For small frames the copying cost is negligible (esp. considering -that we are pre-loading the cache with immediately useful header -information). For large frames the copying cost is non-trivial, and the -larger copy might flush the cache of useful data. A subtle aspect of this -choice is that the Tulip only receives into longword aligned buffers, thus -the IP header at offset 14 isn't longword aligned for further processing. -Copied frames are put into the new skbuff at an offset of "+2", thus copying -has the beneficial effect of aligning the IP header and preloading the -cache. - - - - -Synchronization - -The driver runs as two independent, single-threaded flows of control. One -is the send-packet routine, which enforces single-threaded use by the -dev->tbusy flag. The other thread is the interrupt handler, which is single -threaded by the hardware and other software. - - - -The send packet thread has partial control over the Tx ring and 'dev->tbusy' -flag. It sets the tbusy flag whenever it's queuing a Tx packet. If the next -queue slot is empty, it clears the tbusy flag when finished otherwise it sets -the 'tp->tx_full' flag. - - - -The interrupt handler has exclusive control over the Rx ring and records stats -from the Tx ring. (The Tx-done interrupt can't be selectively turned off, so -we can't avoid the interrupt overhead by having the Tx routine reap the Tx -stats.) After reaping the stats, it marks the queue entry as empty by setting -the 'base' to zero. Iff the 'tp->tx_full' flag is set, it clears both the -tx_full and tbusy flags. - - - - - - - - Errata - - -The old DEC databooks were light on details. -The 21040 databook claims that CSR13, CSR14, and CSR15 should each be the last -register of the set CSR12-15 written. Hmmm, now how is that possible? - - - -The DEC SROM format is very badly designed not precisely defined, leading to -part of the media selection junkheap below. Some boards do not have EEPROM -media tables and need to be patched up. Worse, other boards use the DEC -design kit media table when it isn't correct for their board. - - - -We cannot use MII interrupts because there is no defined GPIO pin to attach -them. The MII transceiver status is polled using an kernel timer. - - - - - Driver Change History - - Version 0.9.14 (February 20, 2001) - - Fix PNIC problems (Manfred Spraul) - Add new PCI id for Accton comet - Support Davicom tulips - Fix oops in eeprom parsing - Enable workarounds for early PCI chipsets - IA64, hppa csr0 support - Support media types 5, 6 - Interpret a bit more of the 21142 SROM extended media type 3 - Add missing delay in eeprom reading - - - - Version 0.9.11 (November 3, 2000) - - Eliminate extra bus accesses when sharing interrupts (prumpf) - Barrier following ownership descriptor bit flip (prumpf) - Endianness fixes for >14 addresses in setup frames (prumpf) - Report link beat to kernel/userspace via netif_carrier_*. (kuznet) - Better spinlocking in set_rx_mode. - Fix I/O resource request failure error messages (DaveM catch) - Handle DMA allocation failure. - - - - Version 0.9.10 (September 6, 2000) - - Simple interrupt mitigation (via jamal) - More PCI ids - - - - Version 0.9.9 (August 11, 2000) - - More PCI ids - - - - Version 0.9.8 (July 13, 2000) - - Correct signed/unsigned comparison for dummy frame index - Remove outdated references to struct enet_statistics - - - - Version 0.9.7 (June 17, 2000) - - Timer cleanups (Andrew Morton) - Alpha compile fix (somebody?) - - - - Version 0.9.6 (May 31, 2000) - - Revert 21143-related support flag patch - Add HPPA/media-table debugging printk - - - - Version 0.9.5 (May 30, 2000) - - HPPA support (willy@puffingroup) - CSR6 bits and tulip.h cleanup (Chris Smith) - Improve debugging messages a bit - Add delay after CSR13 write in t21142_start_nway - Remove unused ETHER_STATS code - Convert 'extern inline' to 'static inline' in tulip.h (Chris Smith) - Update DS21143 support flags in tulip_chip_info[] - Use spin_lock_irq, not _irqsave/restore, in tulip_start_xmit() - Add locking to set_rx_mode() - Fix race with chip setting DescOwned bit (Hal Murray) - Request 100% of PIO and MMIO resource space assigned to card - Remove error message from pci_enable_device failure - - - - Version 0.9.4.3 (April 14, 2000) - - mod_timer fix (Hal Murray) - PNIC2 resuscitation (Chris Smith) - - - - Version 0.9.4.2 (March 21, 2000) - - Fix 21041 CSR7, CSR13/14/15 handling - Merge some PCI ids from tulip 0.91x - Merge some HAS_xxx flags and flag settings from tulip 0.91x - asm/io.h fix (submitted by many) and cleanup - s/HAS_NWAY143/HAS_NWAY/ - Cleanup 21041 mode reporting - Small code cleanups - - - - Version 0.9.4.1 (March 18, 2000) - - Finish PCI DMA conversion (davem) - Do not netif_start_queue() at end of tulip_tx_timeout() (kuznet) - PCI DMA fix (kuznet) - eeprom.c code cleanup - Remove Xircom Tulip crud - - - - -
diff --git a/Documentation/DocBook/via-audio.tmpl b/Documentation/DocBook/via-audio.tmpl deleted file mode 100644 index f91903c2a..000000000 --- a/Documentation/DocBook/via-audio.tmpl +++ /dev/null @@ -1,595 +0,0 @@ - - - - - Via 686 Audio Driver for Linux - - - - Jeff - Garzik - - - - - 1999-2001 - Jeff Garzik - - - - - 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. - - - - 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 - - - - For more details see the file COPYING in the source - distribution of Linux. - - - - - - - - Introduction - - The Via VT82C686A "super southbridge" chips contain - AC97-compatible audio logic which features dual 16-bit stereo - PCM sound channels (full duplex), plus a third PCM channel intended for use - in hardware-assisted FM synthesis. - - - The current Linux kernel audio driver for this family of chips - supports audio playback and recording, but hardware-assisted - FM features, and hardware buffer direct-access (mmap) - support are not yet available. - - - This driver supports any Linux kernel version after 2.4.10. - - - Please send bug reports to the mailing list linux-via@gtf.org. - To subscribe, e-mail majordomo@gtf.org with - - - subscribe linux-via - - - in the body of the message. - - - - - Driver Installation - - To use this audio driver, select the - CONFIG_SOUND_VIA82CXXX option in the section Sound during kernel configuration. - Follow the usual kernel procedures for rebuilding the kernel, - or building and installing driver modules. - - - To make this driver the default audio driver, you can add the - following to your /etc/conf.modules file: - - - alias sound via82cxxx_audio - - - Note that soundcore and ac97_codec support modules - are also required for working audio, in addition to - the via82cxxx_audio module itself. - - - - - Submitting a bug report - Description of problem - - Describe the application you were using to play/record sound, and how - to reproduce the problem. - - - Diagnostic output - - Obtain the via-audio-diag diagnostics program from - http://sf.net/projects/gkernel/ and provide a dump of the - audio chip's registers while the problem is occurring. Sample command line: - - - ./via-audio-diag -aps > diag-output.txt - - - Driver debug output - - Define VIA_DEBUG at the beginning of the driver, then capture and email - the kernel log output. This can be viewed in the system kernel log (if - enabled), or via the dmesg program. Sample command line: - - - dmesg > /tmp/dmesg-output.txt - - - Bigger kernel message buffer - - If you wish to increase the size of the buffer displayed by dmesg, then - change the LOG_BUF_LEN macro at the top of linux/kernel/printk.c, recompile - your kernel, and pass the LOG_BUF_LEN value to dmesg. Sample command line with - LOG_BUF_LEN == 32768: - - - dmesg -s 32768 > /tmp/dmesg-output.txt - - - - - - Known Bugs And Assumptions - - - Low volume - - - Volume too low on many systems. Workaround: use mixer program - such as xmixer to increase volume. - - - - - - - - - - Thanks - - Via for providing e-mail support, specs, and NDA'd source code. - - - MandrakeSoft for providing hacking time. - - - AC97 mixer interface fixes and debugging by Ron Cemer roncemer@gte.net. - - - Rui Sousa rui.sousa@conexant.com, for bugfixing - MMAP support, and several other notable fixes that resulted from - his hard work and testing. - - - Adrian Cox adrian@humboldt.co.uk, for bugfixing - MMAP support, and several other notable fixes that resulted from - his hard work and testing. - - - Thomas Sailer for further bugfixes. - - - - - Random Notes - - Two /proc pseudo-files provide diagnostic information. This is generally - not useful to most users. Power users can disable CONFIG_SOUND_VIA82CXXX_PROCFS, - and remove the /proc support code. Once - version 2.0.0 is released, the /proc support code will be disabled by - default. Available /proc pseudo-files: - - - /proc/driver/via/0/info - /proc/driver/via/0/ac97 - - - This driver by default supports all PCI audio devices which report - a vendor id of 0x1106, and a device id of 0x3058. Subsystem vendor - and device ids are not examined. - - - GNU indent formatting options: - --kr -i8 -ts8 -br -ce -bap -sob -l80 -pcs -cs -ss -bs -di1 -nbc -lp -psl - - - - Via has graciously donated e-mail support and source code to help further - the development of this driver. Their assistance has been invaluable - in the design and coding of the next major version of this driver. - - - The Via audio chip apparently provides a second PCM scatter-gather - DMA channel just for FM data, but does not have a full hardware MIDI - processor. I haven't put much thought towards a solution here, but it - might involve using SoftOSS midi wave table, or simply disabling MIDI - support altogether and using the FM PCM channel as a second (input? output?) - - - - - Driver ChangeLog - - -Version 1.9.1 - - - - - DSP read/write bugfixes from Thomas Sailer. - - - - - - Add new PCI id for single-channel use of Via 8233. - - - - - - Other bug fixes, tweaks, new ioctls. - - - - - - - -Version 1.1.15 - - - - - Support for variable fragment size and variable fragment number (Rui - Sousa) - - - - - - Fixes for the SPEED, STEREO, CHANNELS, FMT ioctls when in read & - write mode (Rui Sousa) - - - - - - Mmaped sound is now fully functional. (Rui Sousa) - - - - - - Make sure to enable PCI device before reading any of its PCI - config information. (fixes potential hotplug problems) - - - - - - Clean up code a bit and add more internal function documentation. - - - - - - AC97 codec access fixes (Adrian Cox) - - - - - - Big endian fixes (Adrian Cox) - - - - - - MIDI support (Adrian Cox) - - - - - - Detect and report locked-rate AC97 codecs. If your hardware only - supports 48Khz (locked rate), then your recording/playback software - must upsample or downsample accordingly. The hardware cannot do it. - - - - - - Use new pci_request_regions and pci_disable_device functions in - kernel 2.4.6. - - - - - - - -Version 1.1.14 - - - - - Use VM_RESERVE when available, to eliminate unnecessary page faults. - - - - - - -Version 1.1.12 - - - - - mmap bug fixes from Linus. - - - - - - -Version 1.1.11 - - - - - Many more bug fixes. mmap enabled by default, but may still be buggy. - - - - - - Uses new and spiffy method of mmap'ing the DMA buffer, based - on a suggestion from Linus. - - - - - - -Version 1.1.10 - - - - - Many bug fixes. mmap enabled by default, but may still be buggy. - - - - - - -Version 1.1.9 - - - - - Redesign and rewrite audio playback implementation. (faster and smaller, hopefully) - - - - - - Implement recording and full duplex (DSP_CAP_DUPLEX) support. - - - - - - Make procfs support optional. - - - - - - Quick interrupt status check, to lessen overhead in interrupt - sharing situations. - - - - - - Add mmap(2) support. Disabled for now, it is still buggy and experimental. - - - - - - Surround all syscalls with a semaphore for cheap and easy SMP protection. - - - - - - Fix bug in channel shutdown (hardware channel reset) code. - - - - - - Remove unnecessary spinlocks (better performance). - - - - - - Eliminate "unknown AFMT" message by using a different method - of selecting the best AFMT_xxx sound sample format for use. - - - - - - Support for realtime hardware pointer position reporting - (DSP_CAP_REALTIME, SNDCTL_DSP_GETxPTR ioctls) - - - - - - Support for capture/playback triggering - (DSP_CAP_TRIGGER, SNDCTL_DSP_SETTRIGGER ioctls) - - - - - - SNDCTL_DSP_SETDUPLEX and SNDCTL_DSP_POST ioctls now handled. - - - - - - Rewrite open(2) and close(2) logic to allow only one user at - a time. All other open(2) attempts will sleep until they succeed. - FIXME: open(O_RDONLY) and open(O_WRONLY) should be allowed to succeed. - - - - - - Reviewed code to ensure that SMP and multiple audio devices - are fully supported. - - - - - - - -Version 1.1.8 - - - - - Clean up interrupt handler output. Fixes the following kernel error message: - - - unhandled interrupt ... - - - - - - Convert documentation to DocBook, so that PDF, HTML and PostScript (.ps) output is readily - available. - - - - - - - -Version 1.1.7 - - - - - Fix module unload bug where mixer device left registered - after driver exit - - - - - - -Version 1.1.6 - - - - - Rewrite via_set_rate to mimic ALSA basic AC97 rate setting - - - - - Remove much dead code - - - - - Complete spin_lock_irqsave -> spin_lock_irq conversion in via_dsp_ioctl - - - - - Fix build problem in via_dsp_ioctl - - - - - Optimize included headers to eliminate headers found in linux/sound - - - - - - -Version 1.1.5 - - - - - Disable some overly-verbose debugging code - - - - - Remove unnecessary sound locks - - - - - Fix some ioctls for better time resolution - - - - - Begin spin_lock_irqsave -> spin_lock_irq conversion in via_dsp_ioctl - - - - - - -Version 1.1.4 - - - - - Completed rewrite of driver. Eliminated SoundBlaster compatibility - completely, and now uses the much-faster scatter-gather DMA engine. - - - - - - - - - Internal Functions -!Isound/oss/via82cxxx_audio.c - - - - - diff --git a/Documentation/DocBook/videobook.tmpl b/Documentation/DocBook/videobook.tmpl index 2c92b1836..3ec6c8755 100644 --- a/Documentation/DocBook/videobook.tmpl +++ b/Documentation/DocBook/videobook.tmpl @@ -1,4 +1,6 @@ - + + @@ -180,23 +182,23 @@ int __init myradio_init(struct video_init *v) - VFL_TYPE_RADIO/dev/radio{n} + VFL_TYPE_RADIO/dev/radio{n} Radio devices are assigned in this block. As with all of these selections the actual number assignment is done by the video layer accordijng to what is free. - VFL_TYPE_GRABBER/dev/video{n} + VFL_TYPE_GRABBER/dev/video{n} Video capture devices and also -- counter-intuitively for the name -- hardware video playback devices such as MPEG2 cards. - VFL_TYPE_VBI/dev/vbi{n} + VFL_TYPE_VBI/dev/vbi{n} The VBI devices capture the hidden lines on a television picture that carry further information like closed caption data, teletext (primarily in Europe) and now Intercast and the ATVEC internet television encodings. - VFL_TYPE_VTX/dev/vtx[n} + VFL_TYPE_VTX/dev/vtx[n} VTX is 'Videotext' also known as 'Teletext'. This is a system for sending numbered, 40x25, mostly textual page images over the hidden lines. Unlike the /dev/vbi interfaces, this is for 'smart' decoder @@ -301,25 +303,25 @@ static int radio_ioctl(struct video_device *dev, unsigned int cmd, void *arg) - nameThe device text name. This is intended for the user. + nameThe device text name. This is intended for the user. - channelsThe number of different channels you can tune on + channelsThe number of different channels you can tune on this card. It could even by zero for a card that has no tuning capability. For our simple FM radio it is 1. An AM/FM radio would report 2. - audiosThe number of audio inputs on this device. For our + audiosThe number of audio inputs on this device. For our radio there is only one audio input. - minwidth,minheightThe smallest size the card is capable of capturing + minwidth,minheightThe smallest size the card is capable of capturing images in. We set these to zero. Radios do not capture pictures - maxwidth,maxheightThe largest image size the card is capable of + maxwidth,maxheightThe largest image size the card is capable of capturing. For our radio we report 0. - typeThis reports the capabilities of the device, and + typeThis reports the capabilities of the device, and matches the field we filled in in the struct video_device when registering. @@ -375,26 +377,26 @@ static int radio_ioctl(struct video_device *dev, unsigned int cmd, void *arg) - int tunerThe number of the tuner in question + int tunerThe number of the tuner in question - char name[32]A text description of this tuner. "FM" will do fine. + char name[32]A text description of this tuner. "FM" will do fine. This is intended for the application. - u32 flags + u32 flags Tuner capability flags - u16 modeThe current reception mode + u16 modeThe current reception mode - u16 signalThe signal strength scaled between 0 and 65535. If + u16 signalThe signal strength scaled between 0 and 65535. If a device cannot tell the signal strength it should report 65535. Many simple cards contain only a signal/no signal bit. Such cards will report either 0 or 65535. - u32 rangelow, rangehigh + u32 rangelow, rangehigh The range of frequencies supported by the radio or TV. It is scaled according to the VIDEO_TUNER_LOW flag. @@ -408,20 +410,20 @@ static int radio_ioctl(struct video_device *dev, unsigned int cmd, void *arg) - VIDEO_TUNER_PALA PAL TV tuner + VIDEO_TUNER_PALA PAL TV tuner - VIDEO_TUNER_NTSCAn NTSC (US) TV tuner + VIDEO_TUNER_NTSCAn NTSC (US) TV tuner - VIDEO_TUNER_SECAMA SECAM (French) TV tuner + VIDEO_TUNER_SECAMA SECAM (French) TV tuner - VIDEO_TUNER_LOW + VIDEO_TUNER_LOW The tuner frequency is scaled in 1/16th of a KHz steps. If not it is in 1/16th of a MHz steps - VIDEO_TUNER_NORMThe tuner can set its format + VIDEO_TUNER_NORMThe tuner can set its format - VIDEO_TUNER_STEREO_ONThe tuner is currently receiving a stereo signal + VIDEO_TUNER_STEREO_ONThe tuner is currently receiving a stereo signal @@ -431,13 +433,13 @@ static int radio_ioctl(struct video_device *dev, unsigned int cmd, void *arg) - VIDEO_MODE_PALPAL Format + VIDEO_MODE_PALPAL Format - VIDEO_MODE_NTSCNTSC Format (USA) + VIDEO_MODE_NTSCNTSC Format (USA) - VIDEO_MODE_SECAMFrench Format + VIDEO_MODE_SECAMFrench Format - VIDEO_MODE_AUTOA device that does not need to do + VIDEO_MODE_AUTOA device that does not need to do TV format switching @@ -521,7 +523,7 @@ static unsigned long current_freq; if(copy_from_user(arg, &freq, sizeof(unsigned long))!=0) return -EFAULT; - if(hardware_set_freq(freq)<0) + if(hardware_set_freq(freq)<0) return -EINVAL; current_freq = freq; return 0; @@ -582,32 +584,32 @@ static int current_volume=0; - audioThe input the user wishes to query + audioThe input the user wishes to query - volumeThe volume setting on a scale of 0-65535 + volumeThe volume setting on a scale of 0-65535 - baseThe base level on a scale of 0-65535 + baseThe base level on a scale of 0-65535 - trebleThe treble level on a scale of 0-65535 + trebleThe treble level on a scale of 0-65535 - flagsThe features this audio device supports + flagsThe features this audio device supports - nameA text name to display to the user. We picked - "Radio" as it explains things quite nicely. + nameA text name to display to the user. We picked + "Radio" as it explains things quite nicely. - modeThe current reception mode for the audio + modeThe current reception mode for the audio We report MONO because our card is too stupid to know if it is in mono or stereo. - balanceThe stereo balance on a scale of 0-65535, 32768 is - middle. + balanceThe stereo balance on a scale of 0-65535, 32768 is + middle. - stepThe step by which the volume control jumps. This is + stepThe step by which the volume control jumps. This is used to help make it easy for applications to set - slider behaviour. + slider behaviour. @@ -617,15 +619,15 @@ static int current_volume=0; - VIDEO_AUDIO_MUTEThe audio is currently muted. We + VIDEO_AUDIO_MUTEThe audio is currently muted. We could fake this in our driver but we choose not to bother. - VIDEO_AUDIO_MUTABLEThe input has a mute option + VIDEO_AUDIO_MUTABLEThe input has a mute option - VIDEO_AUDIO_TREBLEThe input has a treble control + VIDEO_AUDIO_TREBLEThe input has a treble control - VIDEO_AUDIO_BASSThe input has a base control + VIDEO_AUDIO_BASSThe input has a base control @@ -635,13 +637,13 @@ static int current_volume=0; - VIDEO_SOUND_MONOMono sound + VIDEO_SOUND_MONOMono sound - VIDEO_SOUND_STEREOStereo sound + VIDEO_SOUND_STEREOStereo sound - VIDEO_SOUND_LANG1Alternative language 1 (TV specific) + VIDEO_SOUND_LANG1Alternative language 1 (TV specific) - VIDEO_SOUND_LANG2Alternative language 2 (TV specific) + VIDEO_SOUND_LANG2Alternative language 2 (TV specific) @@ -866,37 +868,37 @@ static struct video_device my_camera -VID_TYPE_CAPTUREWe support image capture +VID_TYPE_CAPTUREWe support image capture -VID_TYPE_TELETEXTA teletext capture device (vbi{n]) +VID_TYPE_TELETEXTA teletext capture device (vbi{n]) -VID_TYPE_OVERLAYThe image can be directly overlaid onto the - frame buffer +VID_TYPE_OVERLAYThe image can be directly overlaid onto the + frame buffer -VID_TYPE_CHROMAKEYChromakey can be used to select which parts - of the image to display +VID_TYPE_CHROMAKEYChromakey can be used to select which parts + of the image to display -VID_TYPE_CLIPPINGIt is possible to give the board a list of - rectangles to draw around. +VID_TYPE_CLIPPINGIt is possible to give the board a list of + rectangles to draw around. -VID_TYPE_FRAMERAMThe video capture goes into the video memory +VID_TYPE_FRAMERAMThe video capture goes into the video memory and actually changes it. Applications need to know this so they can clean up after the - card + card -VID_TYPE_SCALESThe image can be scaled to various sizes, - rather than being a single fixed size. +VID_TYPE_SCALESThe image can be scaled to various sizes, + rather than being a single fixed size. -VID_TYPE_MONOCHROMEThe capture will be monochrome. This isn't a +VID_TYPE_MONOCHROMEThe capture will be monochrome. This isn't a complete answer to the question since a mono camera on a colour capture card will still - produce mono output. + produce mono output. -VID_TYPE_SUBCAPTUREThe card allows only part of its field of +VID_TYPE_SUBCAPTUREThe card allows only part of its field of view to be captured. This enables applications to avoid copying all of a large image into memory when only some section is - relevant. + relevant. @@ -1207,18 +1209,18 @@ static int camera_ioctl(struct video_device *dev, unsigned int cmd, void *arg) - channelThe channel number we are selecting + channelThe channel number we are selecting - nameThe name for this channel. This is intended + nameThe name for this channel. This is intended to describe the port to the user. Appropriate names are therefore things like "Camera" "SCART input" - flagsChannel properties + flagsChannel properties - typeInput type + typeInput type - normThe current television encoding being used + normThe current television encoding being used if relevant for this channel. @@ -1229,9 +1231,9 @@ static int camera_ioctl(struct video_device *dev, unsigned int cmd, void *arg) - VIDEO_VC_TUNERChannel has a tuner. + VIDEO_VC_TUNERChannel has a tuner. - VIDEO_VC_AUDIOChannel has audio. + VIDEO_VC_AUDIOChannel has audio. @@ -1240,11 +1242,11 @@ static int camera_ioctl(struct video_device *dev, unsigned int cmd, void *arg) - VIDEO_TYPE_TVTelevision input. + VIDEO_TYPE_TVTelevision input. - VIDEO_TYPE_CAMERAFixed camera input. + VIDEO_TYPE_CAMERAFixed camera input. - 0Type is unknown. + 0Type is unknown. @@ -1253,13 +1255,13 @@ static int camera_ioctl(struct video_device *dev, unsigned int cmd, void *arg) - VIDEO_MODE_PALPAL encoded Television + VIDEO_MODE_PALPAL encoded Television - VIDEO_MODE_NTSCNTSC (US) encoded Television + VIDEO_MODE_NTSCNTSC (US) encoded Television - VIDEO_MODE_SECAMSECAM (French) Television + VIDEO_MODE_SECAMSECAM (French) Television - VIDEO_MODE_AUTOAutomatic switching, or format does not + VIDEO_MODE_AUTOAutomatic switching, or format does not matter @@ -1339,14 +1341,14 @@ static int camera_ioctl(struct video_device *dev, unsigned int cmd, void *arg) - GREYLinear greyscale. This is for simple cameras and the - like + GREYLinear greyscale. This is for simple cameras and the + like - RGB565The top 5 bits hold 32 red levels, the next six bits - hold green and the low 5 bits hold blue. + RGB565The top 5 bits hold 32 red levels, the next six bits + hold green and the low 5 bits hold blue. - RGB555The top bit is clear. The red green and blue levels - each occupy five bits. + RGB555The top bit is clear. The red green and blue levels + each occupy five bits. @@ -1477,32 +1479,32 @@ static struct video_buffer capture_fb; - widthThe width in pixels of the desired image. The card - may use a smaller size if this size is not available + widthThe width in pixels of the desired image. The card + may use a smaller size if this size is not available - heightThe height of the image. The card may use a smaller - size if this size is not available. + heightThe height of the image. The card may use a smaller + size if this size is not available. - x The X position of the top left of the window. This + x The X position of the top left of the window. This is in pixels relative to the left hand edge of the picture. Not all cards can display images aligned on any pixel boundary. If the position is unsuitable the card adjusts the image right and reduces the - width. + width. - y The Y position of the top left of the window. This + y The Y position of the top left of the window. This is counted in pixels relative to the top edge of the picture. As with the width if the card cannot display starting on this line it will adjust the - values. + values. - chromakeyThe colour (expressed in RGB32 format) for the - chromakey colour if chroma keying is being used. + chromakeyThe colour (expressed in RGB32 format) for the + chromakey colour if chroma keying is being used. - clipsAn array of rectangles that must not be drawn - over. + clipsAn array of rectangles that must not be drawn + over. - clipcountThe number of clips in this array. + clipcountThe number of clips in this array. @@ -1514,11 +1516,11 @@ static struct video_buffer capture_fb; - x, yCo-ordinates relative to the display + x, yCo-ordinates relative to the display - width, heightWidth and height in pixels + width, heightWidth and height in pixels - nextA spare field for the application to use + nextA spare field for the application to use @@ -1550,9 +1552,9 @@ static struct video_buffer capture_fb; struct video_window v; if(copy_from_user(&v, arg, sizeof(v))) return -EFAULT; - if(v.width > 640 || v.height > 480) + if(v.width > 640 || v.height > 480) return -EINVAL; - if(v.width < 16 || v.height < 16) + if(v.width < 16 || v.height < 16) return -EINVAL; hardware_set_key(v.chromakey); hardware_set_window(v); diff --git a/Documentation/README.moxa b/Documentation/README.moxa deleted file mode 100644 index 20600ad32..000000000 --- a/Documentation/README.moxa +++ /dev/null @@ -1,18 +0,0 @@ - =================================================================== - Release Note of Linux Driver for Moxa's C104/C168/CI-104J - =================================================================== - - ------------------------------------------------------------------- - Ver. 1.1 Sep. 1, 1999 - ------------------------------------------------------------------- - 1. Improved: - a. Static driver (kernel) and dynamic driver (loadable module) - modes are supported. - b. Multiple Smartio PCI series boards sharing the same IRQ - supported. - - ------------------------------------------------------------------- - Ver. 1.0 Feb 17, 1997 - ------------------------------------------------------------------- - 1. Newly release. - diff --git a/Documentation/SubmittingDrivers b/Documentation/SubmittingDrivers index 2630629d7..de3b252e7 100644 --- a/Documentation/SubmittingDrivers +++ b/Documentation/SubmittingDrivers @@ -118,13 +118,18 @@ Linux kernel mailing list: linux-kernel@vger.kernel.org [mail majordomo@vger.kernel.org to subscribe] +Linux Device Drivers, Third Edition (covers 2.6.10): + http://lwn.net/Kernel/LDD3/ (free version) + Kernel traffic: Weekly summary of kernel list activity (much easier to read) http://www.kerneltraffic.org/kernel-traffic/ LWN.net: Weekly summary of kernel development activity - http://lwn.net/ - 2.6 driver porting information: + 2.6 API changes: + http://lwn.net/Articles/2.6-kernel-api/ + Porting drivers from prior kernels to 2.6: http://lwn.net/Articles/driver-porting/ KernelTrap: diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches index 9838d32b2..4d35562b1 100644 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches @@ -271,7 +271,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,6 +291,12 @@ 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 diff --git a/Documentation/cachetlb.txt b/Documentation/cachetlb.txt index 9e2f988a8..e132fb116 100644 --- a/Documentation/cachetlb.txt +++ b/Documentation/cachetlb.txt @@ -142,6 +142,11 @@ changes occur: The ia64 sn2 platform is one example of a platform that uses this interface. +8) void lazy_mmu_prot_update(pte_t pte) + This interface is called whenever the protection on + any user PTEs change. This interface provides a notification + to architecture specific code to take appropiate action. + Next, we have the cache flushing interfaces. In general, when Linux is changing an existing virtual-->physical mapping to a new value, @@ -155,7 +160,7 @@ the sequence will be in one of the following forms: change_range_of_page_tables(mm, start, end); flush_tlb_range(vma, start, end); - 3) flush_cache_page(vma, addr); + 3) flush_cache_page(vma, addr, pfn); set_pte(pte_pointer, new_pte_val); flush_tlb_page(vma, addr); @@ -203,7 +208,7 @@ Here are the routines, one by one: call flush_cache_page (see below) for each entry which may be modified. -3) void flush_cache_page(struct vm_area_struct *vma, unsigned long addr) +3) void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn) This time we need to remove a PAGE_SIZE sized range from the cache. The 'vma' is the backing structure used by @@ -213,8 +218,14 @@ Here are the routines, one by one: executable (and thus could be in the 'instruction cache' in "Harvard" type cache layouts). + The 'pfn' indicates the physical page frame (shift this value + left by PAGE_SHIFT to get the physical address) that 'addr' + translates to. It is this mapping which should be removed from + the cache. + After running, there will be no entries in the cache for - 'vma->vm_mm' for virtual address 'addr'. + 'vma->vm_mm' for virtual address 'addr' which translates + to 'pfn'. This is used primarily during fault processing. diff --git a/Documentation/cciss.txt b/Documentation/cciss.txt index 5bbc54667..d599beb9d 100644 --- a/Documentation/cciss.txt +++ b/Documentation/cciss.txt @@ -15,26 +15,30 @@ This driver is known to work with the following cards: * SA 6400 U320 Expansion Module * SA 6i * SA P600 + * SA P800 + * SA E400 -If nodes are not already created in the /dev/cciss directory +If nodes are not already created in the /dev/cciss directory, run as root: -# mkdev.cciss [ctlrs] - -Where ctlrs is the number of controllers you have (defaults to 1 if not -specified). +# cd /dev +# ./MAKEDEV cciss Device Naming: -------------- -You need some entries in /dev for the cciss device. The mkdev.cciss script +You need some entries in /dev for the cciss device. The MAKEDEV script can make device nodes for you automatically. Currently the device setup is as follows: Major numbers: 104 cciss0 105 cciss1 - 106 cciss2 - etc... + 106 cciss2 + 105 cciss3 + 108 cciss4 + 109 cciss5 + 110 cciss6 + 111 cciss7 Minor numbers: b7 b6 b5 b4 b3 b2 b1 b0 @@ -44,7 +48,7 @@ Minor numbers: | +-------------------- Logical Volume number -The suggested device naming scheme is: +The device naming scheme is: /dev/cciss/c0d0 Controller 0, disk 0, whole device /dev/cciss/c0d0p1 Controller 0, disk 0, partition 1 /dev/cciss/c0d0p2 Controller 0, disk 0, partition 2 @@ -116,16 +120,13 @@ from the adapter, informing the SCSI mid layer may not be necessary. Note that the naming convention of the /proc filesystem entries contains a number in addition to the driver name. (E.g. "cciss0" -instead of just "cciss" which you might expect.) This is because -of changes to the 2.4 kernel PCI interface related to PCI hot plug -that imply the driver must register with the SCSI mid layer once per -adapter instance rather than once per driver. +instead of just "cciss" which you might expect.) Note: ONLY sequential access devices and medium changers are presented as SCSI devices to the SCSI mid layer by the cciss driver. Specifically, physical SCSI disk drives are NOT presented to the SCSI mid layer. The physical SCSI disk drives are controlled directly by the array controller -hardware and it is important to prevent the OS from attempting to directly +hardware and it is important to prevent the kernel from attempting to directly access these devices too, as if the array controller were merely a SCSI controller in the same way that we are allowing it to access SCSI tape drives. diff --git a/Documentation/cdrom/mcd b/Documentation/cdrom/mcd deleted file mode 100644 index 39537f9f0..000000000 --- a/Documentation/cdrom/mcd +++ /dev/null @@ -1,4 +0,0 @@ -This driver does not support XA or MultiSession CDs (PhotoCDs). Use the -experimental driver mcdx.c for that. - -You can use mcd for one interface, and mcdx for another. diff --git a/Documentation/devices.txt b/Documentation/devices.txt index 60ce4ae9d..a3efd3cc0 100644 --- a/Documentation/devices.txt +++ b/Documentation/devices.txt @@ -1,9 +1,9 @@ - LINUX ALLOCATED DEVICES + LINUX ALLOCATED DEVICES (2.6+ version) Maintained by Torben Mathiasen - Last revised: 04 August 2004 + Last revised: 25 January 2005 This list is the Linux Device List, the official registry of allocated device numbers and /dev directory nodes for the Linux operating @@ -24,7 +24,8 @@ platform only. Allocations marked (68k/Atari) apply to Linux/68k on the Atari platform only. The symbol {2.6} means the allocation is obsolete and scheduled for -removal once kernel version 2.6 (or equivalent) is released. +removal once kernel version 2.6 (or equivalent) is released. Some of these +allocations have already been removed. This document is in the public domain. The author requests, however, that semantically altered versions are not distributed without @@ -41,13 +42,6 @@ reply. **** DEVICE DRIVERS AUTHORS PLEASE READ THIS **** -THE DEVICE REGISTRY IS OFFICIALLY FROZEN FOR LINUS TORVALDS' KERNEL -TREE. At Linus' request, no more allocations will be made official -for Linus' kernel tree; the 3 June 2001 version of this list is the -official final version of this registry. At Alan Cox' request, -however, the registry will continue to be maintained for the -ac -series of kernels, and registrations will be accepted. - To have a major number allocated, or a minor number in situations where that applies (e.g. busmice), please contact me with the appropriate device information. Also, if you have additional @@ -437,6 +431,8 @@ Your cooperation is appreciated. 226 = /dev/systrace Systrace device 227 = /dev/mcelog X86_64 Machine Check Exception driver 228 = /dev/hpet HPET driver + 229 = /dev/fuse Fuse (virtual filesystem in user-space) + 230 = /dev/midishare MidiShare driver 240-254 Reserved for local use 255 Reserved for MISC_DYNAMIC_MINOR @@ -1177,7 +1173,7 @@ Your cooperation is appreciated. Requested by: andy@scramdisklinux.org - 65 char Sundance "plink" Transputer boards + 65 char Sundance "plink" Transputer boards (obsolete, unused) 0 = /dev/plink0 First plink device 1 = /dev/plink1 Second plink device 2 = /dev/plink2 Third plink device @@ -1527,12 +1523,12 @@ Your cooperation is appreciated. disks (see major number 3) except that the limit on partitions is 15. - 83 char Teletext/videotext interfaces {2.6} - 0 = /dev/vtx Teletext decoder - 16 = /dev/vttuner TV tuner on teletext interface - - Devices for the driver contained in the VideoteXt package. - More information on http://home.pages.de/~videotext/ + 83 char Matrox mga_vid video driver + 0 = /dev/mga_vid0 1st video card + 1 = /dev/mga_vid1 2nd video card + 2 = /dev/mga_vid2 3rd video card + ... + 15 = /dev/mga_vid15 16th video card 83 block I2O hard disk 0 = /dev/i2o/hdaw 49th I2O hard disk, whole disk @@ -1702,11 +1698,6 @@ Your cooperation is appreciated. 3 = /dev/ipauth Authentication control device/log file ... - 95 block IBM S/390 VM/ESA minidisk - 0 = /dev/msd0 First VM/ESA minidisk - 1 = /dev/msd1 Second VM/ESA minidisk - ... - 96 char Parallel port ATAPI tape devices 0 = /dev/pt0 First parallel port ATAPI tape 1 = /dev/pt1 Second parallel port ATAPI tape @@ -1743,10 +1734,14 @@ Your cooperation is appreciated. See http://stm.lbl.gov/comedi or http://www.llp.fu-berlin.de/. 98 block User-mode virtual block device - 0 = /dev/ubd0 First user-mode block device - 1 = /dev/ubd1 Second user-mode block device + 0 = /dev/ubda First user-mode block device + 16 = /dev/udbb Second user-mode block device ... + Partitions are handled in the same way as for IDE + disks (see major number 3) except that the limit on + partitions is 15. + This device is used by the user-mode virtual kernel port. 99 char Raw parallel ports @@ -2110,6 +2105,7 @@ Your cooperation is appreciated. disks (see major number 3) except that the limit on partitions is 15. +130 char (Misc devices) 130 block SCSI disk devices (160-175) 0 = /dev/sdfe 161st SCSI disk whole disk @@ -2547,7 +2543,12 @@ Your cooperation is appreciated. 0 = /dev/usb/lp0 First USB printer ... 15 = /dev/usb/lp15 16th USB printer - 32 = /dev/usb/mdc800 MDC800 USB camera + 16 = /dev/usb/mouse0 First USB mouse + ... + 31 = /dev/usb/mouse15 16th USB mouse + 32 = /dev/usb/ez0 First USB firmware loader + ... + 47 = /dev/usb/ez15 16th USB firmware loader 48 = /dev/usb/scanner0 First USB scanner ... 63 = /dev/usb/scanner15 16th USB scanner @@ -2555,22 +2556,11 @@ Your cooperation is appreciated. 65 = /dev/usb/usblcd USBLCD Interface (info@usblcd.de) 66 = /dev/usb/cpad0 Synaptics cPad (mouse/LCD) - 96 = /dev/usb/hiddev0 1st USB HID device - ... - 111 = /dev/usb/hiddev15 16th USB HID device - 112 = /dev/usb/auer0 1st auerswald ISDN device - ... - 127 = /dev/usb/auer15 16th auerswald ISDN device - 128 = /dev/usb/brlvgr0 First Braille Voyager device - ... - 131 = /dev/usb/brlvgr3 Fourth Braille Voyager device - 144 = /dev/usb/lcd USB LCD device - 160 = /dev/usb/legousbtower0 1st USB Legotower device - ... - 175 = /dev/usb/legousbtower15 16th USB Legotower device - 240 = /dev/usb/dabusb0 First daubusb device - ... - 243 = /dev/usb/dabusb3 Fourth dabusb device +180 block USB block devices + 0 = /dev/uba First USB block device + 8 = /dev/ubb Second USB block device + 16 = /dev/ubc Thrid USB block device + ... 181 char Conrad Electronic parallel port radio clocks 0 = /dev/pcfclock0 First Conrad radio clock @@ -2761,8 +2751,12 @@ Your cooperation is appreciated. 45 = /dev/ttyMM1 Marvell MPSC - port 1 46 = /dev/ttyCPM0 PPC CPM (SCC or SMC) - port 0 ... - 49 = /dev/ttyCPM5 PPC CPM (SCC or SMC) - port 5 - + 47 = /dev/ttyCPM5 PPC CPM (SCC or SMC) - port 5 + 50 = /dev/ttyIOC40 Altix serial card + ... + 81 = /dev/ttyIOC431 Altix serial card + 82 = /dev/ttyVR0 NEC VR4100 series SIU + 83 = /dev/ttyVR1 NEC VR4100 series DSIU 205 char Low-density serial ports (alternate device) 0 = /dev/culu0 Callout device for ttyLU0 @@ -2788,12 +2782,18 @@ Your cooperation is appreciated. ... 39 = /dev/cudb7 Callout device for ttyDB7 40 = /dev/cusg0 Callout device for ttySG0 - 41 = /dev/ttySMX0 Callout device for ttySMX0 - 42 = /dev/ttySMX1 Callout device for ttySMX1 - 43 = /dev/ttySMX2 Callout device for ttySMX2 + 41 = /dev/ttycusmx0 Callout device for ttySMX0 + 42 = /dev/ttycusmx1 Callout device for ttySMX1 + 43 = /dev/ttycusmx2 Callout device for ttySMX2 46 = /dev/cucpm0 Callout device for ttyCPM0 ... 49 = /dev/cucpm5 Callout device for ttyCPM5 + 50 = /dev/cuioc40 Callout device for ttyIOC40 + ... + 81 = /dev/cuioc431 Callout device for ttyIOC431 + 82 = /dev/cuvr0 Callout device for ttyVR0 + 83 = /dev/cuvr1 Callout device for ttyVR1 + 206 char OnStream SC-x0 tape devices 0 = /dev/osst0 First OnStream SCSI tape, mode 0 @@ -3007,7 +3007,12 @@ Your cooperation is appreciated. ioctl()'s can be used to rewind the tape regardless of the device used to access it. -231-239 UNASSIGNED +231 char InfiniBand MAD + 0 = /dev/infiniband/umad0 + 1 = /dev/infiniband/umad1 + ... + +232-239 UNASSIGNED 240-254 char LOCAL/EXPERIMENTAL USE 240-254 block LOCAL/EXPERIMENTAL USE diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index 2c3fc3a27..6c98f2bd4 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -909,16 +909,6 @@ nr_free_inodes Represents the number of free inodes. Ie. The number of inuse inodes is (nr_inodes - nr_free_inodes). -super-nr and super-max ----------------------- - -Again, super block structures are allocated by the kernel, but not freed. The -file super-max contains the maximum number of super block handlers, where -super-nr shows the number of currently allocated ones. - -Every mounted file system needs a super block, so if you plan to mount lots of -file systems, you may want to increase these numbers. - aio-nr and aio-max-nr --------------------- @@ -1709,12 +1699,13 @@ flush Writing to this file results in a flush of the routing cache. -gc_elasticity, gc_interval, gc_min_interval, gc_tresh, gc_timeout, -gc_thresh, gc_thresh1, gc_thresh2, gc_thresh3 --------------------------------------------------------------- +gc_elasticity, gc_interval, gc_min_interval_ms, gc_timeout, gc_thresh +--------------------------------------------------------------------- Values to control the frequency and behavior of the garbage collection -algorithm for the routing cache. +algorithm for the routing cache. gc_min_interval is deprecated and replaced +by gc_min_interval_ms. + max_size -------- @@ -1753,18 +1744,25 @@ settings contain additional options to set garbage collection parameters. In the interface directories you'll find the following entries: -base_reachable_time -------------------- +base_reachable_time, base_reachable_time_ms +------------------------------------------- A base value used for computing the random reachable time value as specified in RFC2461. -retrans_time ------------- +Expression of base_reachable_time, which is deprecated, is in seconds. +Expression of base_reachable_time_ms is in milliseconds. + +retrans_time, retrans_time_ms +----------------------------- + +The time between retransmitted Neighbor Solicitation messages. +Used for address resolution and to determine if a neighbor is +unreachable. -The time, expressed in jiffies (1/100 sec), between retransmitted Neighbor -Solicitation messages. Used for address resolution and to determine if a -neighbor is unreachable. +Expression of retrans_time, which is deprecated, is in 1/100 seconds (for +IPv4) or in jiffies (for IPv6). +Expression of retrans_time_ms is in milliseconds. unres_qlen ---------- diff --git a/Documentation/filesystems/umsdos.txt b/Documentation/filesystems/umsdos.txt deleted file mode 100644 index c253708f3..000000000 --- a/Documentation/filesystems/umsdos.txt +++ /dev/null @@ -1,100 +0,0 @@ -Firstly, let me say that UMSDOS is going through some major code changes, -and has some KNOWN BUGS (and quite a few unknown :-). Please read -fs/umsdos/README-WIP.txt for more information on current status. Thanks. - ----------------------------------------------------------------------------- -Very short explanation for the impatient! - -Umsdos is a file system driver that run on top the MSDOS fs driver. -It is written by Jacques Gelinas (jacques@solucorp.qc.ca) -and is currently maintained by Matija Nalis (mnalis@jagor.srce.hr) - -Umsdos is not a file system per se, but a twist to make a boring -one into a useful one. - -It gives you: - - long file names - Permissions and owners - Links - Special files (devices, pipes...) - All that is needed to be a linux root fs. - -There is plenty of documentation on it in the source. A formatted document -made from those comments is available from -sunsite.unc.edu:/pub/Linux/system/Filesystems/umsdos. - -You mount a DOS partition like this: - -mount -t umsdos /dev/hda3 /mnt - ^ ----------| - -All options are passed to the msdos drivers. Option like uid,gid etc are -given to msdos. - -The default behavior of Umsdos is to do the same thing as the msdos driver -mostly passing commands to it without much processing. Again, this is -the default. After doing the mount on a DOS partition, nothing special -happens. This is why all mount options are passed to the msdos fs driver. - -Umsdos uses a special DOS file --linux-.--- to store the information -which can't be handled by the normal MS-DOS filesystem. This is the trick. - ---linux-.--- is optional. There is one per directory. - -**** If --linux-.--- is missing, then Umsdos process the directory the - same way the msdos driver does. Short file names, no goodies, default - owner and permissions. So each directory may have or not this - --linux-.--- - -Now, how to get those --linux-.---. - -\begin joke_section - - Well send me a directory content - and I will send you one customised for you. - $5 per directory. Add any applicable taxes. -\end joke_section - -A utility umssync creates those. The kernel maintains them. It is available -from the same directory above (sunsite) in the file umsdos_progs-0.7.tar.gz. -A compiled version is available in umsdos_progs-0.7.bin.tar.gz. - -So in our example, after mounting mnt, we do - - umssync . - -This will promote this directory (a recursive option is available) to full -umsdos capabilities (long name, etc.). However, an "ls -l" before and after -won't show much difference. The files which were there are still there, but -now you can do all this: - - chmod 644 * - chown you.your_group * - ls >THIS_IS.A.VERY.LONG.NAME - ln -s toto tata - ls -l - -Once a directory is promoted, all subdirectories created will inherit that -promotion. - -What happens if you boot DOS and create files in those promoted directories ? -Umsdos won't notice new files, but will signal removed files (it won't crash). -Using umssync in /etc/rc will make sure the DOS directory is in sync with -the --linux-.---. - -It is a good idea to put the following command in your RC file just -after the "mount -a": - - mount -a - /sbin/umssync -i+ -c+ -r99 /umsdos_mount_point - - (You put one for each umsdos mount point in the fstab) - -This will ensure nice operation. A umsdos.fsck is in the making, -so you will be allowed to manage umsdos partitions in the same way -other filesystems are, using the generic fsck front end. - -Hope this helps! - diff --git a/Documentation/i2c/i2c-old-porting b/Documentation/i2c/i2c-old-porting deleted file mode 100644 index 158dfe550..000000000 --- a/Documentation/i2c/i2c-old-porting +++ /dev/null @@ -1,626 +0,0 @@ -I2C Conversion Guide for I2C-old to the current I2C API -July 2002 -For Linux Kernel v2.5.x -Frank Davis -------------------------------------------------------- - -There exists several kernel drivers that are using an old version of the I2C -API. These drivers need to be converted to the current (kernel 2.5.x) version. -The following document provides a guideline to make the appropriate changes to -the affected drivers. There maybe slight modifications to this guide that are -specific to the driver you are working on. If you see {driver_name}, replace -that with the respective name of the driver, such as saa7110.c , {driver_name} -= saa7110. - -------------------------------------------------------- - -Step 1: Include the right header file - -Perform the following change within the driver - -#include --> #include - -Step 2: Add and set the i2c modes - -Add the following code near the top of the driver - -static unsigned short normal_i2c[] = {34>>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 struct i2c_client_address_data addr_data = { - normal_i2c , normal_i2c_range, - probe , probe_range, - ignore , ignore_range, - force -}; - -static struct i2c_client client_template; - -Step 3: Modify the driver info struct - -Within the struct for the driver , such as struct {driver_name} , make the -following change , -struct i2c_bus *bus --> struct i2c_client *client - -Make changes where this change affects references within the file. - -Add a semaphore to the driver struct (as above) - -struct semaphore lock - -Step 5: Remove specific read and write functions - -Remove the driver specific write and read functions, usually in the form: -{driver_name}_write , {driver_name}_read , {driver_name}_write_block , etc. - -Step 6: Update the write and read functions for the current I2C API - -Replace all references of {driver_name}_write with i2c_smbus_write_byte_data -Replace all references of {driver_name}_read with i2c_smbus_read_byte_data or -i2c_smbus_read_byte , depending on args passed in. - -** Ensure that these functions pass in the i2c_client *client , NOT the -decoder/encoder that was passed in the driver specific write and read -functions. - -Step 7: Modify the driver's attach function - -Change the driver attach function prototype : -{driver_name}_attach(struct i2c_device *device) --> {driver_name}_attach(struct -i2c_adapter *adap, int addr , unsigned short flags, int kind) - -Create a i2c_client client... -Add the following (where "decoder" is a reference to a struct for the driver -info: - -struct i2c_client *client; -client = kmalloc(sizeof(*client), GFP_KERNEL); -if(client == NULL) - return -ENOMEM; -client_template.adapter = adap; -client_template.addr = addr; -memcpy(client, &client_template, sizeof(*client)); -strcpy(client->name , "{driver_name}"); -decoder->client = client; -client->data = decoder; -decoder->addr = addr; - -Towards the end of the function, add: - -init_MUTEX(&decoder->lock); -i2c_attach_client(client); - - -Step 8: Modify the driver's detach function - -Change the driver detach function prototype : -{driver_name}_detach(struct i2c_device *device) --> {driver_name}_detach(struct -i2c_client *client) - -In the beginning of the detach function, add: -i2c_detach_client(client); - -Towards the end of the detach function, add: -kfree(client->data); -kfree(client); - -Step 9: Modify the driver's command function - -Change the driver command function prototype : - -Step 10: Add the probe function after the driver's attach function. - -Add the following code: - -static int {driver_name}_probe(struct i2c_adapter *adap) -{ - return i2c_probe(adap, &addr_data, {driver_name}_attach); - -} - -Step 11: Modify the driver's i2c_driver - -Find the i2c_driver , such as -static struct i2c_driver i2c_driver_saa7110 -It is usually located towards the end of the driver -Replace the values from I2C_DRIVERID_{something} to {driver_name}_attach, and -add the following -I2C_DRIVERID_{driver_name} , // verify by looking in include/linux/i2c-id.h -I2C_DF_NOTIFY, -{driver_name}_probe, -.... - -Step 12: Adding the i2c_client - -Add the i2c_client to the driver. Add the following code: - -static struct i2c_client client_template = { - "{driver_name}_client", - -1, - 0, - 0, - NULL, - {i2c_driver reference} -}; - -Step 13: Registering and Unregistering - -Replace i2c_register_driver with i2c_add_driver -Replace i2c_unregister_driver with i2c_del_driver - -------------------------------------------------------- - -Example: - -The following patch provides the i2c coversion patch for the saa7110 driver -based on the above guide (for clarity). - - ---- drivers/media/video/saa7110.c.old Fri Jun 28 10:22:52 2002 -+++ drivers/media/video/saa7110.c Thu Jul 4 16:51:08 2002 -@@ -26,7 +26,7 @@ - #include - #include - --#include -+#include - #include - #include "linux/video_decoder.h" - -@@ -37,13 +37,31 @@ - - #define I2C_SAA7110 0x9C /* or 0x9E */ - -+#define IF_NAME "saa7110" - #define I2C_DELAY 10 /* 10 us or 100khz */ - -+static unsigned short normal_i2c[] = {34>>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 struct i2c_client_address_data addr_data = { -+ normal_i2c, normal_i2c_range, -+ probe, probe_range, -+ ignore, ignore_range, -+ force -+}; -+ -+static struct i2c_client client_template; -+ - struct saa7110 { -- struct i2c_bus *bus; -+ struct i2c_client *client; - int addr; - unsigned char reg[36]; -- -+ struct semaphore lock; - int norm; - int input; - int enable; -@@ -54,67 +72,10 @@ - }; - - /* ----------------------------------------------------------------------- */ --/* I2C support functions */ --/* ----------------------------------------------------------------------- */ --static --int saa7110_write(struct saa7110 *decoder, unsigned char subaddr, unsigned char data) --{ -- int ack; -- -- LOCK_I2C_BUS(decoder->bus); -- i2c_start(decoder->bus); -- i2c_sendbyte(decoder->bus, decoder->addr, I2C_DELAY); -- i2c_sendbyte(decoder->bus, subaddr, I2C_DELAY); -- ack = i2c_sendbyte(decoder->bus, data, I2C_DELAY); -- i2c_stop(decoder->bus); -- decoder->reg[subaddr] = data; -- UNLOCK_I2C_BUS(decoder->bus); -- return ack; --} -- --static --int saa7110_write_block(struct saa7110* decoder, unsigned const char *data, unsigned int len) --{ -- unsigned subaddr = *data; -- -- LOCK_I2C_BUS(decoder->bus); -- i2c_start(decoder->bus); -- i2c_sendbyte(decoder->bus,decoder->addr,I2C_DELAY); -- while (len-- > 0) { -- if (i2c_sendbyte(decoder->bus,*data,0)) { -- i2c_stop(decoder->bus); -- UNLOCK_I2C_BUS(decoder->bus); -- return -EAGAIN; -- } -- decoder->reg[subaddr++] = *data++; -- } -- i2c_stop(decoder->bus); -- UNLOCK_I2C_BUS(decoder->bus); -- -- return 0; --} -- --static --int saa7110_read(struct saa7110* decoder) --{ -- int data; -- -- LOCK_I2C_BUS(decoder->bus); -- i2c_start(decoder->bus); -- i2c_sendbyte(decoder->bus, decoder->addr, I2C_DELAY); -- i2c_start(decoder->bus); -- i2c_sendbyte(decoder->bus, decoder->addr | 1, I2C_DELAY); -- data = i2c_readbyte(decoder->bus, 1); -- i2c_stop(decoder->bus); -- UNLOCK_I2C_BUS(decoder->bus); -- return data; --} -- --/* ----------------------------------------------------------------------- */ - /* SAA7110 functions */ - /* ----------------------------------------------------------------------- */ - static --int saa7110_selmux(struct i2c_device *device, int chan) -+int saa7110_selmux(struct i2c_client *client, int chan) - { - static const unsigned char modes[9][8] = { - /* mode 0 */ { 0x00, 0xD9, 0x17, 0x40, 0x03, 0x44, 0x75, 0x16 }, -@@ -126,61 +87,59 @@ - /* mode 6 */ { 0x80, 0x59, 0x17, 0x42, 0xA3, 0x44, 0x75, 0x12 }, - /* mode 7 */ { 0x80, 0x9A, 0x17, 0xB1, 0x13, 0x60, 0xB5, 0x14 }, - /* mode 8 */ { 0x80, 0x3C, 0x27, 0xC1, 0x23, 0x44, 0x75, 0x21 } }; -- struct saa7110* decoder = device->data; - const unsigned char* ptr = modes[chan]; - -- saa7110_write(decoder,0x06,ptr[0]); /* Luminance control */ -- saa7110_write(decoder,0x20,ptr[1]); /* Analog Control #1 */ -- saa7110_write(decoder,0x21,ptr[2]); /* Analog Control #2 */ -- saa7110_write(decoder,0x22,ptr[3]); /* Mixer Control #1 */ -- saa7110_write(decoder,0x2C,ptr[4]); /* Mixer Control #2 */ -- saa7110_write(decoder,0x30,ptr[5]); /* ADCs gain control */ -- saa7110_write(decoder,0x31,ptr[6]); /* Mixer Control #3 */ -- saa7110_write(decoder,0x21,ptr[7]); /* Analog Control #2 */ -+ i2c_smbus_write_byte_data(client,0x06,ptr[0]); /* Luminance control */ -+ i2c_smbus_write_byte_data(client,0x20,ptr[1]); /* Analog Control #1 */ -+ i2c_smbus_write_byte_data(client,0x21,ptr[2]); /* Analog Control #2 */ -+ i2c_smbus_write_byte_data(client,0x22,ptr[3]); /* Mixer Control #1 */ -+ i2c_smbus_write_byte_data(client,0x2C,ptr[4]); /* Mixer Control #2 */ -+ i2c_smbus_write_byte_data(client,0x30,ptr[5]); /* ADCs gain control */ -+ i2c_smbus_write_byte_data(client,0x31,ptr[6]); /* Mixer Control #3 */ -+ i2c_smbus_write_byte_data(client,0x21,ptr[7]); /* Analog Control #2 */ - - return 0; - } - - static --int determine_norm(struct i2c_device* dev) -+int determine_norm(struct i2c_client* client) - { -- struct saa7110* decoder = dev->data; - int status; - - /* mode changed, start automatic detection */ -- status = saa7110_read(decoder); -+ status = i2c_smbus_read_byte(client); - if ((status & 3) == 0) { -- saa7110_write(decoder,0x06,0x80); -+ i2c_smbus_write_byte_data(client,0x06,0x80); - if (status & 0x20) { -- DEBUG(printk(KERN_INFO "%s: norm=bw60\n",dev->name)); -- saa7110_write(decoder,0x2E,0x81); -+ DEBUG(printk(KERN_INFO "%s: norm=bw60\n",adp->name)); -+ i2c_smbus_write_byte_data(client,0x2E,0x81); - return VIDEO_MODE_NTSC; - } -- DEBUG(printk(KERN_INFO "%s: norm=bw50\n",dev->name)); -- saa7110_write(decoder,0x2E,0x9A); -+ DEBUG(printk(KERN_INFO "%s: norm=bw50\n",adp->name)); -+ i2c_smbus_write_byte_data(client,0x2E,0x9A); - return VIDEO_MODE_PAL; - } - -- saa7110_write(decoder,0x06,0x00); -+ i2c_smbus_write_byte_data(client,0x06,0x00); - if (status & 0x20) { /* 60Hz */ -- DEBUG(printk(KERN_INFO "%s: norm=ntsc\n",dev->name)); -- saa7110_write(decoder,0x0D,0x06); -- saa7110_write(decoder,0x11,0x2C); -- saa7110_write(decoder,0x2E,0x81); -+ DEBUG(printk(KERN_INFO "%s: norm=ntsc\n",adp->name)); -+ i2c_smbus_write_byte_data(client,0x0D,0x06); -+ i2c_smbus_write_byte_data(client,0x11,0x2C); -+ i2c_smbus_write_byte_data(client,0x2E,0x81); - return VIDEO_MODE_NTSC; - } - - /* 50Hz -> PAL/SECAM */ -- saa7110_write(decoder,0x0D,0x06); -- saa7110_write(decoder,0x11,0x59); -- saa7110_write(decoder,0x2E,0x9A); -+ i2c_smbus_write_byte_data(client,0x0D,0x06); -+ i2c_smbus_write_byte_data(client,0x11,0x59); -+ i2c_smbus_write_byte_data(client,0x2E,0x9A); - - mdelay(150); /* pause 150 ms */ - -- status = saa7110_read(decoder); -+ status = i2c_smbus_read_byte(client); - if ((status & 0x03) == 0x01) { - DEBUG(printk(KERN_INFO "%s: norm=secam\n",dev->name)); -- saa7110_write(decoder,0x0D,0x07); -+ i2c_smbus_write_byte_data(client,0x0D,0x07); - return VIDEO_MODE_SECAM; - } - DEBUG(printk(KERN_INFO "%s: norm=pal\n",dev->name)); -@@ -188,7 +147,7 @@ - } - - static --int saa7110_attach(struct i2c_device *device) -+int saa7110_attach(struct i2c_adapter *adap, int addr, unsigned short flags, int kind) - { - static const unsigned char initseq[] = { - 0, 0x4C, 0x3C, 0x0D, 0xEF, 0xBD, 0xF0, 0x00, 0x00, -@@ -198,20 +157,28 @@ - 0xD9, 0x17, 0x40, 0x41, 0x80, 0x41, 0x80, 0x4F, - 0xFE, 0x01, 0xCF, 0x0F, 0x03, 0x01, 0x81, 0x03, - 0x40, 0x75, 0x01, 0x8C, 0x03}; -- struct saa7110* decoder; -+ struct saa7110 *decoder; -+ struct i2c_client *client; - int rv; -- -- device->data = decoder = kmalloc(sizeof(struct saa7110), GFP_KERNEL); -- if (device->data == 0) -+ client=kmalloc(sizeof(*client), GFP_KERNEL); -+ if(client == NULL) - return -ENOMEM; -- -+ client_template.adapter = adap; -+ client_template.addr = addr; -+ memcpy(client, &client_template, sizeof(*client)); -+ -+ decoder = kmalloc(sizeof(*decoder), GFP_KERNEL); -+ if (decoder == NULL) { -+ kfree(client); -+ return -ENOMEM; -+ } - - /* clear our private data */ -- memset(decoder, 0, sizeof(struct saa7110)); -- strcpy(device->name, "saa7110"); -- decoder->bus = device->bus; -- decoder->addr = device->addr; -+ memset(decoder, 0, sizeof(*decoder)); -+ strcpy(client->name, IF_NAME); -+ decoder->client = client; -+ client->data = decoder; -+ decoder->addr = addr; - decoder->norm = VIDEO_MODE_PAL; - decoder->input = 0; - decoder->enable = 1; -@@ -220,40 +187,52 @@ - decoder->hue = 32768; - decoder->sat = 32768; - -- rv = saa7110_write_block(decoder, initseq, sizeof(initseq)); -+ rv = i2c_master_send(client, initseq, sizeof(initseq)); - if (rv < 0) -- printk(KERN_ERR "%s_attach: init status %d\n", device->name, rv); -+ printk(KERN_ERR "%s_attach: init status %d\n", client->name, rv); - else { -- saa7110_write(decoder,0x21,0x16); -- saa7110_write(decoder,0x0D,0x04); -- DEBUG(printk(KERN_INFO "%s_attach: chip version %x\n", device->name, saa7110_read(decoder))); -- saa7110_write(decoder,0x0D,0x06); -+ i2c_smbus_write_byte_data(client,0x21,0x16); -+ i2c_smbus_write_byte_data(client,0x0D,0x04); -+ DEBUG(printk(KERN_INFO "%s_attach: chip version %x\n", client->name, i2c_smbus_read_byte(client))); -+ i2c_smbus_write_byte_data(client,0x0D,0x06); - } - -+ init_MUTEX(&decoder->lock); -+ i2c_attach_client(client); - /* setup and implicit mode 0 select has been performed */ - return 0; - } - -+static -+int saa7110_probe(struct i2c_adapter *adap) -+{ -+ return i2c_probe(adap, &addr_data, saa7110_attach); -+} -+ - static --int saa7110_detach(struct i2c_device *device) -+int saa7110_detach(struct i2c_client *client) - { -- struct saa7110* decoder = device->data; -+ struct saa7110* decoder = client->data; - -- DEBUG(printk(KERN_INFO "%s_detach\n",device->name)); -+ i2c_detach_client(client); -+ -+ DEBUG(printk(KERN_INFO "%s_detach\n",client->name)); - - /* stop further output */ -- saa7110_write(decoder,0x0E,0x00); -+ i2c_smbus_write_byte_data(client,0x0E,0x00); - -- kfree(device->data); -+ kfree(decoder); -+ kfree(client); - - return 0; - } - - static --int saa7110_command(struct i2c_device *device, unsigned int cmd, void *arg) -+int saa7110_command(struct i2c_client *client, unsigned int cmd, void *arg) - { -- struct saa7110* decoder = device->data; -+ struct saa7110* decoder = client->data; - int v; - - switch (cmd) { -@@ -272,11 +251,11 @@ - - case DECODER_GET_STATUS: - { -- struct saa7110* decoder = device->data; -+ struct saa7110* decoder = client->data; - int status; - int res = 0; - -- status = i2c_read(device->bus,device->addr|1); -+ status = i2c_smbus_read_byte(client); - if (status & 0x40) - res |= DECODER_STATUS_GOOD; - if (status & 0x03) -@@ -301,26 +280,26 @@ - v = *(int*)arg; - if (decoder->norm != v) { - decoder->norm = v; -- saa7110_write(decoder, 0x06, 0x00); -+ i2c_smbus_write_byte_data(client, 0x06, 0x00); - switch (v) { - case VIDEO_MODE_NTSC: -- saa7110_write(decoder, 0x0D, 0x06); -- saa7110_write(decoder, 0x11, 0x2C); -- saa7110_write(decoder, 0x30, 0x81); -- saa7110_write(decoder, 0x2A, 0xDF); -+ i2c_smbus_write_byte_data(client, 0x0D, 0x06); -+ i2c_smbus_write_byte_data(client, 0x11, 0x2C); -+ i2c_smbus_write_byte_data(client, 0x30, 0x81); -+ i2c_smbus_write_byte_data(client, 0x2A, 0xDF); - break; - case VIDEO_MODE_PAL: -- saa7110_write(decoder, 0x0D, 0x06); -- saa7110_write(decoder, 0x11, 0x59); -- saa7110_write(decoder, 0x2E, 0x9A); -+ i2c_smbus_write_byte_data(client, 0x0D, 0x06); -+ i2c_smbus_write_byte_data(client, 0x11, 0x59); -+ i2c_smbus_write_byte_data(client, 0x2E, 0x9A); - break; - case VIDEO_MODE_SECAM: -- saa7110_write(decoder, 0x0D, 0x07); -- saa7110_write(decoder, 0x11, 0x59); -- saa7110_write(decoder, 0x2E, 0x9A); -+ i2c_smbus_write_byte_data(client, 0x0D, 0x07); -+ i2c_smbus_write_byte_data(client, 0x11, 0x59); -+ i2c_smbus_write_byte_data(client, 0x2E, 0x9A); - break; - case VIDEO_MODE_AUTO: -- *(int*)arg = determine_norm(device); -+ *(int*)arg = determine_norm(client); - break; - default: - return -EPERM; -@@ -334,7 +313,7 @@ - return -EINVAL; - if (decoder->input != v) { - decoder->input = v; -- saa7110_selmux(device, v); -+ saa7110_selmux(client, v); - } - break; - -@@ -349,7 +328,7 @@ - v = *(int*)arg; - if (decoder->enable != v) { - decoder->enable = v; -- saa7110_write(decoder,0x0E, v ? 0x18 : 0x00); -+ i2c_smbus_write_byte_data(client,0x0E, v ? 0x18 : 0x00); - } - break; - -@@ -360,22 +339,22 @@ - if (decoder->bright != pic->brightness) { - /* We want 0 to 255 we get 0-65535 */ - decoder->bright = pic->brightness; -- saa7110_write(decoder, 0x19, decoder->bright >> 8); -+ i2c_smbus_write_byte_data(client, 0x19, decoder->bright >> 8); - } - if (decoder->contrast != pic->contrast) { - /* We want 0 to 127 we get 0-65535 */ - decoder->contrast = pic->contrast; -- saa7110_write(decoder, 0x13, decoder->contrast >> 9); -+ i2c_smbus_write_byte_data(client, 0x13, decoder->contrast >> 9); - } - if (decoder->sat != pic->colour) { - /* We want 0 to 127 we get 0-65535 */ - decoder->sat = pic->colour; -- saa7110_write(decoder, 0x12, decoder->sat >> 9); -+ i2c_smbus_write_byte_data(client, 0x12, decoder->sat >> 9); - } - if (decoder->hue != pic->hue) { - /* We want -128 to 127 we get 0-65535 */ - decoder->hue = pic->hue; -- saa7110_write(decoder, 0x07, (decoder->hue>>8)-128); -+ i2c_smbus_write_byte_data(client, 0x07, (decoder->hue>>8)-128); - } - } - break; -@@ -383,7 +362,7 @@ - case DECODER_DUMP: - for (v=0; v<34; v+=16) { - int j; -- DEBUG(printk(KERN_INFO "%s: %03x\n",device->name,v)); -+ DEBUG(printk(KERN_INFO "%s: %03x\n",client->name,v)); - for (j=0; j<16; j++) { - DEBUG(printk(KERN_INFO " %02x",decoder->reg[v+j])); - } -@@ -402,24 +381,30 @@ - - static struct i2c_driver i2c_driver_saa7110 = - { -- "saa7110", /* name */ -- -- I2C_DRIVERID_VIDEODECODER, /* in i2c.h */ -- I2C_SAA7110, I2C_SAA7110+1, /* Addr range */ -- -- saa7110_attach, -- saa7110_detach, -- saa7110_command -+ .owner = THIS_MODULE, -+ .name = IF_NAME, -+ .id = I2C_DRIVERID_SAA7110, -+ .flags = I2C_DF_NOTIFY, -+ .attach_adapter = saa7110_probe, -+ .detach_adapter = saa7110_detach, -+ .command = saa7110_command, - }; -+static struct i2c_client client_template = { -+ "saa7110_client", -+ -1, -+ 0, -+ 0, -+ NULL, -+ &i2c_driver_saa7110 -+}; - - static int saa7110_init(void) - { -- return i2c_register_driver(&i2c_driver_saa7110); -+ return i2c_add_driver(&i2c_driver_saa7110); - } - - static void saa7110_exit(void) - { -- i2c_unregister_driver(&i2c_driver_saa7110); -+ i2c_del_driver(&i2c_driver_saa7110); - } - - - - diff --git a/Documentation/i2c/i2c-parport b/Documentation/i2c/i2c-parport deleted file mode 100644 index d359461ce..000000000 --- a/Documentation/i2c/i2c-parport +++ /dev/null @@ -1,156 +0,0 @@ -================== -i2c-parport driver -================== - -2004-07-06, Jean Delvare - -This is a unified driver for several i2c-over-parallel-port adapters, -such as the ones made by Philips, Velleman or ELV. This driver is -meant as a replacement for the older, individual drivers: - * i2c-philips-par - * i2c-elv - * i2c-velleman - * video/i2c-parport (NOT the same as this one, dedicated to home brew - teletext adapters) - -It currently supports the following devices: - * Philips adapter - * home brew teletext adapter - * Velleman K8000 adapter - * ELV adapter - * Analog Devices evaluation boards (ADM1025, ADM1030, ADM1031, ADM1032) - -These devices use different pinout configurations, so you have to tell -the driver what you have, using the type module parameter. There is no -way to autodetect the devices. Support for different pinout configurations -can be easily added when needed. - - -Building your own adapter -------------------------- - -If you want to build you own i2c-over-parallel-port adapter, here is -a sample electronics schema (credits go to Sylvain Munaut): - -Device PC -Side ___________________Vdd (+) Side - | | | - --- --- --- - | | | | | | - |R| |R| |R| - | | | | | | - --- --- --- - | | | - | | /| | -SCL ----------x--------o |-----------x------------------- pin 2 - | \| | | - | | | - | |\ | | -SDA ----------x----x---| o---x--------------------------- pin 13 - | |/ | - | | - | /| | - ---------o |----------------x-------------- pin 3 - \| | | - | | - --- --- - | | | | - |R| |R| - | | | | - --- --- - | | - ### ### - GND GND - -Remarks: - - This is the exact pinout and electronics used on the Analog Devices - evaluation boards. - /| - - All inverters -o |- must be 74HC05, they must be open collector output. - \| - - All resitors are 10k. - - Pins 18-25 of the parallel port connected to GND. - - Pins 4-9 (D2-D7) could be used as VDD is the driver drives them high. - The ADM1032 evaluation board uses D4-D7. Beware that the amount of - current you can draw from the parallel port is limited. Also note that - all connected lines MUST BE driven at the same state, else you'll short - circuit the output buffers! So plugging the I2C adapter after loading - the i2c-parport module might be a good safety since data line state - prior to init may be unknown. - - This is 5V! - - Obviously you cannot read SCL (so it's not really standard-compliant). - Pretty easy to add, just copy the SDA part and use another input pin. - That would give (ELV compatible pinout): - - -Device PC -Side ______________________________Vdd (+) Side - | | | | - --- --- --- --- - | | | | | | | | - |R| |R| |R| |R| - | | | | | | | | - --- --- --- --- - | | | | - | | |\ | | -SCL ----------x--------x--| o---x------------------------ pin 15 - | | |/ | - | | | - | | /| | - | ---o |-------------x-------------- pin 2 - | \| | | - | | | - | | | - | |\ | | -SDA ---------------x---x--| o--------x------------------- pin 10 - | |/ | - | | - | /| | - ---o |------------------x--------- pin 3 - \| | | - | | - --- --- - | | | | - |R| |R| - | | | | - --- --- - | | - ### ### - GND GND - - -If possible, you should use the same pinout configuration as existing -adapters do, so you won't even have to change the code. - - -Similar (but different) drivers -------------------------------- - -This driver is NOT the same as the i2c-pport driver found in the i2c package. -The i2c-pport driver makes use of modern parallel port features so that -you don't need additional electronics. It has other restrictions however, and -was not ported to Linux 2.6 (yet). - -This driver is also NOT the same as the i2c-pcf-epp driver found in the -lm_sensors package. The i2c-pcf-epp driver doesn't use the parallel port -as an I2C bus directly. Instead, it uses it to control an external I2C bus -master. That driver was not ported to Linux 2.6 (yet) either. - - -Legacy documentation for Velleman adapter ------------------------------------------ - -Useful links: -Velleman http://www.velleman.be/ -Velleman K8000 Howto http://howto.htlw16.ac.at/k8000-howto.html - -The project has lead to new libs for the Velleman K8000 and K8005: - LIBK8000 v1.99.1 and LIBK8005 v0.21 -With these libs, you can control the K8000 interface card and the K8005 -stepper motor card with the simple commands which are in the original -Velleman software, like SetIOchannel, ReadADchannel, SendStepCCWFull and -many more, using /dev/velleman. - http://home.wanadoo.nl/hihihi/libk8000.htm - http://home.wanadoo.nl/hihihi/libk8005.htm - http://struyve.mine.nu:8080/index.php?block=k8000 - http://sourceforge.net/projects/libk8005/ diff --git a/Documentation/i2c/porting-clients b/Documentation/i2c/porting-clients index 18b9acef0..56404918e 100644 --- a/Documentation/i2c/porting-clients +++ b/Documentation/i2c/porting-clients @@ -49,9 +49,8 @@ Technical changes: static void lm75_update_client(struct i2c_client *client); * [Sysctl] All sysctl stuff is of course gone (defines, ctl_table - and functions). Instead, right after the static id definition - line, you have to define show and set functions for each sysfs - file. Only define set for writable values. Take a look at an + and functions). Instead, you have to define show and set functions for + each sysfs file. Only define set for writable values. Take a look at an existing 2.6 driver for details (lm78 for example). Don't forget to define the attributes for each file (this is that step that links callback functions). Use the file names specified in @@ -86,6 +85,7 @@ Technical changes: Replace the sysctl directory registration by calls to device_create_file. Move the driver initialization before any sysfs file creation. + Drop client->id. * [Init] Limits must not be set by the driver (can be done later in user-space). Chip should not be reset default (although a module diff --git a/Documentation/i386/zero-page.txt b/Documentation/i386/zero-page.txt index 30badb4e3..df28c7416 100644 --- a/Documentation/i386/zero-page.txt +++ b/Documentation/i386/zero-page.txt @@ -74,7 +74,11 @@ Offset Type Description 0x21c unsigned long INITRD_SIZE, size in bytes of ramdisk image 0x220 4 bytes (setup.S) 0x224 unsigned short setup.S heap end pointer +0x226 unsigned short zero_pad +0x228 unsigned long cmd_line_ptr +0x22c unsigned long ramdisk_max +0x230 16 bytes trampoline 0x290 - 0x2cf EDD_MBR_SIG_BUFFER (edd.S) -0x2d0 - 0x600 E820MAP -0x600 - 0x7ff EDDBUF (edd.S) for disk signature read sector -0x600 - 0x7eb EDDBUF (edd.S) for edd data +0x2d0 - 0xd00 E820MAP +0xd00 - 0xeff EDDBUF (edd.S) for disk signature read sector +0xd00 - 0xeeb EDDBUF (edd.S) for edd data diff --git a/Documentation/ioctl-number.txt b/Documentation/ioctl-number.txt index bd7a19777..769f925c8 100644 --- a/Documentation/ioctl-number.txt +++ b/Documentation/ioctl-number.txt @@ -72,6 +72,7 @@ Code Seq# Include File Comments 0x09 all linux/md.h 0x12 all linux/fs.h linux/blkpg.h +0x1b all InfiniBand Subsystem 0x20 all drivers/cdrom/cm206.h 0x22 all scsi/sg.h '#' 00-3F IEEE 1394 Subsystem Block for the entire subsystem @@ -145,7 +146,7 @@ Code Seq# Include File Comments 'p' 40-7F linux/nvram.h 'p' 80-9F user-space parport -'q' 00-1F linux/videotext.h conflict! +'q' 00-1F linux/serio.h 'q' 80-FF Internet PhoneJACK, Internet LineJACK 'r' 00-1F linux/msdos_fs.h @@ -163,6 +164,7 @@ Code Seq# Include File Comments 'z' 40-7F CAN bus card 0x80 00-1F linux/fb.h +0x81 00-1F linux/videotext.h 0x89 00-06 asm-i386/sockios.h 0x89 0B-DF linux/sockios.h 0x89 E0-EF linux/sockios.h SIOCPROTOPRIVATE range diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 3db6c5095..4924d387a 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -51,6 +51,7 @@ restrictions referred to are that the relevant option is valid if: MOUSE Appropriate mouse support is enabled. MTD MTD support is enabled. NET Appropriate network support is enabled. + NUMA NUMA support is enabled. NFS Appropriate NFS support is enabled. OSS OSS sound support is enabled. PARIDE The ParIDE subsystem is enabled. @@ -66,17 +67,22 @@ restrictions referred to are that the relevant option is valid if: SCSI Appropriate SCSI support is enabled. A lot of drivers has their options described inside of Documentation/scsi/. + SELINUX SELinux support is enabled. SERIAL Serial support is enabled. SMP The kernel is an SMP kernel. SPARC Sparc architecture is enabled. SWSUSP Software suspension is enabled. TS Appropriate touchscreen support is enabled. USB USB support is enabled. + USBHID USB Human Interface Device support is enabled. V4L Video For Linux support is enabled. VGA The VGA console has been enabled. VT Virtual terminal support is enabled. WDT Watchdog support is enabled. XT IBM PC/XT MFM hard disk support is enabled. + X86-64 X86-64 architecture is enabled. + More X86-64 boot options can be found in + Documentation/x86_64/boot-options.txt . In addition, the following text indicates that the option: @@ -151,6 +157,8 @@ running once the system is up. debugging. After system has booted up, it can be set via /proc/acpi/debug_level. + acpi_fake_ecdt [HW,ACPI] Workaround failure due to BIOS lacking ECDT + ad1816= [HW,OSS] Format: ,,, See also Documentation/sound/oss/AD1816. @@ -223,15 +231,19 @@ running once the system is up. atascsi= [HW,SCSI] Atari SCSI - atkbd.extra= [HW] Enable extra LEDs and keys on IBM RapidAccess, EzKey - and similar keyboards + atkbd.extra= [HW] Enable extra LEDs and keys on IBM RapidAccess, + EzKey and similar keyboards atkbd.reset= [HW] Reset keyboard during initialization atkbd.set= [HW] Select keyboard code set Format: (2 = AT (default) 3 = PS/2) - atkbd.scroll= [HW] Enable scroll wheel on MS Office and similar keyboards + atkbd.scroll= [HW] Enable scroll wheel on MS Office and similar + keyboards + + atkbd.softraw= [HW] Choose between synthetic and real raw mode + Format: (0 = real, 1 = synthetic (default)) atkbd.softrepeat= [HW] Use software keyboard repeat @@ -288,6 +300,14 @@ running once the system is up. See header of drivers/cdrom/cdu31a.c. chandev= [HW,NET] Generic channel device initialisation + + checkreqprot [SELINUX] Set initial checkreqprot flag value. + Format: { "0" | "1" } + See security/selinux/Kconfig help text. + 0 -- check protection applied by kernel (includes any implied execute protection). + 1 -- check protection requested by application. + Default value is set via a kernel config option. + Value can be changed at runtime via /selinux/checkreqprot. clock= [BUGS=IA-32, HW] gettimeofday timesource override. Forces specified timesource (if avaliable) to be used @@ -386,7 +406,7 @@ running once the system is up. dtc3181e= [HW,SCSI] - earlyprintk= [x86, x86_64] + earlyprintk= [IA-32, X86-64] earlyprintk=vga earlyprintk=serial[,ttySn[,baudrate]] @@ -409,7 +429,7 @@ running once the system is up. edb= [HW,PS2] - edd [EDD] + edd= [EDD] Format: {"of[f]" | "sk[ipmbr]"} See comment in arch/i386/boot/edd.S @@ -428,6 +448,14 @@ running once the system is up. See Documentation/block/as-iosched.txt and Documentation/block/deadline-iosched.txt for details. + enforcing [SELINUX] Set initial enforcing status. + Format: {"0" | "1"} + See security/selinux/Kconfig help text. + 0 -- permissive (log only, no denials). + 1 -- enforcing (deny and log). + Default value is 0. + Value can be changed at runtime via /selinux/enforce. + es1370= [HW,OSS] Format: [,] See also header of sound/oss/es1370.c. @@ -479,6 +507,10 @@ running once the system is up. gvp11= [HW,SCSI] + hashdist= [KNL,NUMA] Large hashes allocated during boot + are distributed across NUMA nodes. Defaults on + for IA-64, off otherwise. + hcl= [IA-64] SGI's Hardware Graph compatibility layer hd= [EIDE] (E)IDE hard drive subsystem geometry @@ -506,6 +538,11 @@ running once the system is up. i8042.noaux [HW] Don't check for auxiliary (== mouse) port i8042.nomux [HW] Don't check presence of an active multiplexing controller + i8042.nopnp [HW] Don't use ACPIPnP / PnPBIOS to discover KBD/AUX + controllers + i8042.panicblink= + [HW] Frequency with which keyboard LEDs should blink + when kernel panics (default is 0.5 sec) i8042.reset [HW] Reset the controller during init and cleanup i8042.unlock [HW] Unlock (ignore) the keylock @@ -574,26 +611,17 @@ running once the system is up. ips= [HW,SCSI] Adaptec / IBM ServeRAID controller See header of drivers/scsi/ips.c. - irqfixup [HW] - When an interrupt is not handled search all handlers - for it. Intended to get systems with badly broken - firmware running. - - irqpoll [HW] - When an interrupt is not handled search all handlers - for it. Also check all handlers each timer - interrupt. Intended to get systems with badly broken - firmware running. - isapnp= [ISAPNP] Format: , , , isolcpus= [KNL,SMP] Isolate CPUs from the general scheduler. - Format: , ..., + Format: ,..., This option can be used to specify one or more CPUs to isolate from the general SMP balancing and scheduling algorithms. The only way to move a process onto or off an "isolated" CPU is via the CPU affinity syscalls. + begins at 0 and the maximum value is + "number of CPUs in system - 1". This option is the preferred way to isolate CPUs. The alternative - manually setting the CPU mask of all tasks @@ -610,6 +638,9 @@ running once the system is up. keepinitrd [HW,ARM] + kstack=N [IA-32, X86-64] Print N words from the kernel stack + in oops dumps. + l2cr= [PPC] lapic [IA-32,APIC] Enable the local APIC even if BIOS disabled it. @@ -630,6 +661,20 @@ running once the system is up. logibm.irq= [HW,MOUSE] Logitech Bus Mouse Driver Format: + loglevel= All Kernel Messages with a loglevel smaller than the + console loglevel will be printed to the console. It can + also be changed with klogd or other programs. The + loglevels are defined as follows: + + 0 (KERN_EMERG) system is unusable + 1 (KERN_ALERT) action must be taken immediately + 2 (KERN_CRIT) critical conditions + 3 (KERN_ERR) error conditions + 4 (KERN_WARNING) warning conditions + 5 (KERN_NOTICE) normal but significant condition + 6 (KERN_INFO) informational + 7 (KERN_DEBUG) debug-level messages + log_buf_len=n Sets the size of the printk ring buffer, in bytes. Format is n, nk, nM. n must be a power of two. The default is set in kernel config. @@ -673,7 +718,11 @@ running once the system is up. mac53c9x= [HW,SCSI] Format: ,,,,,,, - + + machvec= [IA64] + Force the use of a particular machine-vector (machvec) in a generic + kernel. Example: machvec=hpzx1_swiotlb + mad16= [HW,OSS] Format: ,,,,,, @@ -768,6 +817,10 @@ running once the system is up. mtdparts= [MTD] See drivers/mtd/cmdline.c. + mtouchusb.raw_coordinates= + [HW] Make the MicroTouch USB driver use raw coordinates ('y', default) + or cooked coordinates ('n') + n2= [NET] SDL Inc. RISCom/N2 synchronous serial card NCR_D700= [HW,SCSI] @@ -817,7 +870,7 @@ running once the system is up. noexec [IA-64] - noexec [i386, x86_64] + noexec [IA-32, X86-64] noexec=on: enable non-executable mappings (default) noexec=off: disable nn-executable mappings @@ -829,6 +882,13 @@ running once the system is up. instruction doesn't work correctly and not to use it. + nohalt [IA-64] Tells the kernel not to use the power saving + function PAL_HALT_LIGHT when idle. This increases + power-consumption. On the positive side, it reduces + interrupt wake-up latency, which may improve performance + in certain environments such as networked servers or + real-time systems. + noirqdebug [IA-32] Disables the code which attempts to detect and disable unhandled interrupt sources. @@ -888,6 +948,13 @@ running once the system is up. panic= [KNL] Kernel behaviour on panic Format: + parkbd.port= [HW] Parallel port number the keyboard adapter is + connected to, default is 0. + Format: + parkbd.mode= [HW] Parallel port keyboard adapter mode of operation, + 0 for XT, 1 for AT (default is AT). + Format: + parport=0 [HW,PPT] Specify parallel ports. 0 disables. parport=auto Use 'auto' to force the driver to use parport=0xBBB[,IRQ[,DMA]] any IRQ/DMA settings detected (the @@ -1003,6 +1070,9 @@ running once the system is up. Format: { parport | timid | 0 } See also Documentation/parport.txt. + pnpacpi= [ACPI] + { off } + pnpbios= [ISAPNP] { on | off | curr | res | no-curr | no-res } @@ -1088,6 +1158,9 @@ running once the system is up. root= [KNL] Root filesystem + rootdelay= [KNL] Delay (in seconds) to pause before attempting to + mount the root filesystem + rootflags= [KNL] Set root filesystem mount option string rootfstype= [KNL] Set root filesystem type @@ -1125,10 +1198,16 @@ running once the system is up. scsi_logging= [SCSI] - serialnumber [BUGS=IA-32] + selinux [SELINUX] Disable or enable SELinux at boot time. + Format: { "0" | "1" } + See security/selinux/Kconfig help text. + 0 -- disable. + 1 -- enable. + Default value is set via kernel config option. + If enabled at boot time, /selinux/disable can be used + later to disable prior to initial policy load. - sf16fm= [HW] SF16FMI radio driver for Linux - Format: + serialnumber [BUGS=IA-32] sg_def_reserved_size= [SCSI] @@ -1324,9 +1403,6 @@ running once the system is up. sym53c416= [HW,SCSI] See header of drivers/scsi/sym53c416.c. - sym53c8xx= [HW,SCSI] - See Documentation/scsi/ncr53c8xx.txt. - t128= [HW,SCSI] See header of drivers/scsi/t128.c. @@ -1335,12 +1411,15 @@ running once the system is up. thash_entries= [KNL,NET] Set number of hash buckets for TCP connection - tipar= [HW] - See header of drivers/char/tipar.c. + time Show timing data prefixed to each printk message line + + tipar.timeout= [HW,PPT] + Set communications timeout in tenths of a second + (default 15). + + tipar.delay= [HW,PPT] + Set inter-bit delay in microseconds (default 10). - tiusb= [HW,USB] Texas Instruments' USB GraphLink (aka SilverLink) - Format: - tmc8xx= [HW,SCSI] See header of drivers/scsi/seagate.c. @@ -1371,6 +1450,9 @@ running once the system is up. Format: , usb-handoff [HW] Enable early USB BIOS -> OS handoff + + usbhid.mousepoll= + [USBHID] The interval which mice are to be polled at. video= [FB] Frame buffer configuration See Documentation/fb/modedb.txt. diff --git a/Documentation/mkdev.cciss b/Documentation/mkdev.cciss deleted file mode 100644 index fbbaf30a7..000000000 --- a/Documentation/mkdev.cciss +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/sh -# Script to create device nodes for SMART array controllers -# Usage: -# mkdev.cciss [num controllers] [num log volumes] [num partitions] -# -# With no arguments, the script assumes 1 controller, 16 logical volumes, -# and 16 partitions/volume, which is adequate for most configurations. -# -# If you had 5 controllers and were planning on no more than 4 logical volumes -# each, using a maximum of 8 partitions per volume, you could say: -# -# mkdev.cciss 5 4 8 -# -# Of course, this has no real benefit over "mkdev.cciss 5" except that it -# doesn't create so many device nodes in /dev/cciss. - -NR_CTLR=${1-1} -NR_VOL=${2-16} -NR_PART=${3-16} - -if [ ! -d /dev/cciss ]; then - mkdir -p /dev/cciss -fi - -C=0; while [ $C -lt $NR_CTLR ]; do - MAJ=`expr $C + 104` - D=0; while [ $D -lt $NR_VOL ]; do - P=0; while [ $P -lt $NR_PART ]; do - MIN=`expr $D \* 16 + $P` - if [ $P -eq 0 ]; then - mknod /dev/cciss/c${C}d${D} b $MAJ $MIN - else - mknod /dev/cciss/c${C}d${D}p${P} b $MAJ $MIN - fi - P=`expr $P + 1` - done - D=`expr $D + 1` - done - C=`expr $C + 1` -done diff --git a/Documentation/networking/ethertap.txt b/Documentation/networking/ethertap.txt deleted file mode 100644 index 337f650d7..000000000 --- a/Documentation/networking/ethertap.txt +++ /dev/null @@ -1,268 +0,0 @@ -NOTE: Ethertap is now an obsolete facility, and is scheduled - to be removed in the 2.5.x kernel series. Those writing - applications using ethertap should convert their code to - use the TUN/TAP driver instead, see 'tuntap.txt' in this - directory for more details. -DaveM - -Ethertap programming mini-HOWTO -------------------------------- - -The ethertap driver was written by Jay Schulist , -you should contact him for further information. This document was written by -bert hubert . Updates are welcome. - -What ethertap can do for you ----------------------------- - -Ethertap allows you to easily run your own network stack from userspace. -Tunnels can benefit greatly from this. You can also use it to do network -experiments. The alternative would be to use a raw socket to send data and -use libpcap to receive it. Using ethertap saves you this multiplicity and -also does ARP for you if you want. - -The more technical blurb: - -Ethertap provides packet reception and transmission for user space programs. -It can be viewed as a simple Ethernet device, which instead of receiving -packets from a network wire, it receives them from user space. - -Ethertap can be used for anything from AppleTalk to IPX to even building -bridging tunnels. It also has many other general purpose uses. - -Configuring your kernel ------------------------ - -Firstly, you need this in Networking Options: - - # - # Code maturity level options - # - CONFIG_EXPERIMENTAL=y - -Then you need Netlink support: - - CONFIG_NETLINK=y - -This allows the kernel to exchange data with userspace applications. There -are two ways of doing this, the new way works with netlink sockets and I -have no experience with that yet. ANK uses it in his excellent iproute2 -package, see for example rtmon.c. iproute2 can be found on -ftp://ftp.tux.org/pub/net/ip-routing/iproute2* - -The new way is described, partly in netlink(7), available on -http://www.europe.redhat.com/documentation/man-pages/man7/netlink.7.php3 - -There is also a Netlink-HOWTO, available on http://snafu.freedom.org/linux2.2/docs/netlink-HOWTO.html -Sadly I know of no code using ethertap with this new interface. - -The older way works by opening character special files with major node 36. -Enable this with: - - CONFIG_NETLINK_DEV=m - -Please be advised that this support is going to be dropped somewhere in the -future! - -Then finally in the Network Devices section, - - CONFIG_ETHERTAP=m - -You can include it directly in the kernel if you want, of course, no need -for modules. - -Setting it all up ------------------ - -First we need to create the /dev/tap0 device node: - - # mknod /dev/tap0 c 36 16 - # mknod /dev/tap1 c 36 17 - (etc) - -Include the relevant modules (ethertap.o, netlink_dev.o, perhaps netlink.o), -and bring up your tap0 device: - - # ifconfig tap0 10.0.0.123 up - -Now your device is up and running, you can ping it as well. This is what -confused me to no end, because nothing is connected to our ethertap as yet, -how is it that we can ping it? - -It turns out that the ethertap is just like a regular network interface - -even when it's down you can ping it. We need to route stuff to it: - - # route add -host 10.0.0.124 gw 10.0.0.123 - -Now we can read /dev/tap0 and when we ping 10.0.0.124 from our -localhost, output should appear on the screen. - - # cat /dev/tap0 - :ßVU:9````````````````````````þýþET@?' - - -Getting this to work from other hosts -------------------------------------- - -For this to work, you often need proxy ARP. - - # echo 1 > /proc/sys/net/ipv4/conf/eth0/proxy_arp - -eth0 here stands for the interface that connects to 'other hosts'. - -Chances are that you are trying this on a non-routing desktop computer, so -you need to enable ip forwarding: - - # echo 1 > /proc/sys/net/ipv4/ip_forward - -You should now be able to ping 10.0.0.124 from other hosts on your -10.0.0.0/8 subnet. If you are using public ip space, it should work from -everywhere. - -ARP ---- - -If we were to take things very literally, your tcp/ip pseudo stack would -also have to implement ARP and MAC addresses. This is often a bit silly as -the ethertap device is a figment of our imagination anyway. However, should -you want to go 'all the way', you can add the 'arp' flag to ifconfig: - - # ifconfig tap0 10.0.0.123 up arp - -This may also be useful when implementing a bridge, which needs to bridge -ARP packets as well. - -The sample program below will no longer work then, because it does not -implement ARP. - -Sample program --------------- - -A sample program is included somewhere in the bowels of the netfilter -source. I've extracted this program and list it here. It implements a very -tiny part of the IP stack and can respond to any pings it receives. It gets -confused if it receives ARP, as it tries to parse it by treating it as an IP -packet. - -/* Simple program to listen to /dev/tap0 and reply to pings. */ -#include -#include -#include -#if defined(__GLIBC__) && (__GLIBC__ == 2) -#include -#include -#else -#include -#include -#endif -#include -#include -#include -#include - -u_int16_t csum_partial(void *buffer, unsigned int len, u_int16_t prevsum) -{ - u_int32_t sum = 0; - u_int16_t *ptr = buffer; - - while (len > 1) { - sum += *ptr++; - len -= 2; - } - if (len) { - union { - u_int8_t byte; - u_int16_t wyde; - } odd; - odd.wyde = 0; - odd.byte = *((u_int8_t *)ptr); - sum += odd.wyde; - } - sum = (sum >> 16) + (sum & 0xFFFF); - sum += prevsum; - return (sum + (sum >> 16)); -} - -int main() -{ - int fd, len; - union { - struct { - char etherhdr[16]; - struct iphdr ip; - } fmt; - unsigned char raw[65536]; - } u; - - fd = open("/dev/tap0", O_RDWR); - if (fd < 0) { - perror("Opening `/dev/tap0'"); - return 1; - } - - /* u.fmt.ip.ihl in host order! Film at 11. */ - while ((len = read(fd, &u, sizeof(u))) > 0) { - u_int32_t tmp; - struct icmphdr *icmp - = (void *)((u_int32_t *)&u.fmt.ip + u.fmt.ip.ihl ); - struct tcphdr *tcp = (void *)icmp; - struct udphdr *udp = (void *)icmp; - - fprintf(stderr, "SRC = %u.%u.%u.%u DST = %u.%u.%u.%u\n", - (ntohl(u.fmt.ip.saddr) >> 24) & 0xFF, - (ntohl(u.fmt.ip.saddr) >> 16) & 0xFF, - (ntohl(u.fmt.ip.saddr) >> 8) & 0xFF, - (ntohl(u.fmt.ip.saddr) >> 0) & 0xFF, - (ntohl(u.fmt.ip.daddr) >> 24) & 0xFF, - (ntohl(u.fmt.ip.daddr) >> 16) & 0xFF, - (ntohl(u.fmt.ip.daddr) >> 8) & 0xFF, - (ntohl(u.fmt.ip.daddr) >> 0) & 0xFF); - - switch (u.fmt.ip.protocol) { - case IPPROTO_ICMP: - if (icmp->type == ICMP_ECHO) { - fprintf(stderr, "PONG! (iphdr = %u bytes)\n", - (unsigned int)((char *)icmp - - (char *)&u.fmt.ip)); - - /* Turn it around */ - tmp = u.fmt.ip.saddr; - u.fmt.ip.saddr = u.fmt.ip.daddr; - u.fmt.ip.daddr = tmp; - - icmp->type = ICMP_ECHOREPLY; - icmp->checksum = 0; - icmp->checksum - = ~csum_partial(icmp, - ntohs(u.fmt.ip.tot_len) - - u.fmt.ip.ihl*4, 0); - - { - unsigned int i; - for (i = 44; - i < ntohs(u.fmt.ip.tot_len); i++){ - printf("%u:0x%02X ", i, - ((unsigned char *) - &u.fmt.ip)[i]); - } - printf("\n"); - } - write(fd, &u, len); - } - break; - case IPPROTO_TCP: - fprintf(stderr, "TCP: %u -> %u\n", ntohs(tcp->source), - ntohs(tcp->dest)); - break; - - case IPPROTO_UDP: - fprintf(stderr, "UDP: %u -> %u\n", ntohs(udp->source), - ntohs(udp->dest)); - break; - } - } - if (len < 0) - perror("Reading from `/dev/tap0'"); - else fprintf(stderr, "Empty read from `/dev/tap0'"); - return len < 0 ? 1 : 0; -} - diff --git a/Documentation/networking/pktgen.txt b/Documentation/networking/pktgen.txt index 99c1485d7..cc4b4d041 100644 --- a/Documentation/networking/pktgen.txt +++ b/Documentation/networking/pktgen.txt @@ -1,77 +1,214 @@ -How to use the Linux packet generator module. - -1. Enable CONFIG_NET_PKTGEN to compile and build pktgen.o, install it - in the place where insmod may find it. -2. Cut script "ipg" (see below). -3. Edit script to set preferred device and destination IP address. -3a. Create more scripts for different interfaces. Up to thirty-two - pktgen processes can be configured and run at once by using the - 32 /proc/net/pktgen/pg* files. -4. Run in shell: ". ipg" -5. After this two commands are defined: - A. "pg" to start generator and to get results. - B. "pgset" to change generator parameters. F.e. - pgset "clone_skb 100" sets the number of copies of the same packet - will be sent before a new packet is allocated - pgset "clone_skb 0" use multiple SKBs for packet generation - pgset "pkt_size 9014" sets packet size to 9014 - pgset "frags 5" packet will consist of 5 fragments - pgset "count 200000" sets number of packets to send, set to zero - for continuous sends until explicitly - stopped. - pgset "ipg 5000" sets artificial gap inserted between packets - to 5000 nanoseconds - pgset "dst 10.0.0.1" sets IP destination address - (BEWARE! This generator is very aggressive!) - pgset "dst_min 10.0.0.1" Same as dst - pgset "dst_max 10.0.0.254" Set the maximum destination IP. - pgset "src_min 10.0.0.1" Set the minimum (or only) source IP. - pgset "src_max 10.0.0.254" Set the maximum source IP. - pgset "dstmac 00:00:00:00:00:00" sets MAC destination address - pgset "srcmac 00:00:00:00:00:00" sets MAC source address - pgset "src_mac_count 1" Sets the number of MACs we'll range through. The - 'minimum' MAC is what you set with srcmac. - pgset "dst_mac_count 1" Sets the number of MACs we'll range through. The - 'minimum' MAC is what you set with dstmac. - pgset "flag [name]" Set a flag to determine behaviour. Current flags - are: IPSRC_RND #IP Source is random (between min/max), - IPDST_RND, UDPSRC_RND, - UDPDST_RND, MACSRC_RND, MACDST_RND - pgset "udp_src_min 9" set UDP source port min, If < udp_src_max, then - cycle through the port range. - pgset "udp_src_max 9" set UDP source port max. - pgset "udp_dst_min 9" set UDP destination port min, If < udp_dst_max, then - cycle through the port range. - pgset "udp_dst_max 9" set UDP destination port max. - pgset stop aborts injection - - Also, ^C aborts generator. - ----- cut here - -#! /bin/sh - -modprobe pktgen - -PGDEV=/proc/net/pktgen/pg0 - -function pgset() { - local result - - echo $1 > $PGDEV - - result=`cat $PGDEV | fgrep "Result: OK:"` - if [ "$result" = "" ]; then - cat $PGDEV | fgrep Result: - fi -} - -function pg() { - echo inject > $PGDEV - cat $PGDEV -} - -pgset "odev eth0" -pgset "dst 0.0.0.0" - ----- cut here + + + HOWTO for the linux packet generator + ------------------------------------ + +Date: 041221 + +Enable CONFIG_NET_PKTGEN to compile and build pktgen.o either in kernel +or as module. Module is preferred. insmod pktgen if needed. Once running +pktgen creates a thread on each CPU where each thread has affinty it's CPU. +Monitoring and controlling is done via /proc. Easiest to select a suitable +a sample script and configure. + +On a dual CPU: + +ps aux | grep pkt +root 129 0.3 0.0 0 0 ? SW 2003 523:20 [pktgen/0] +root 130 0.3 0.0 0 0 ? SW 2003 509:50 [pktgen/1] + + +For montoring and control pktgen creates: + /proc/net/pktgen/pgctrl + /proc/net/pktgen/kpktgend_X + /proc/net/pktgen/ethX + + +Viewing threads +=============== +/proc/net/pktgen/kpktgend_0 +Name: kpktgend_0 max_before_softirq: 10000 +Running: +Stopped: eth1 +Result: OK: max_before_softirq=10000 + +Most important the devices assigend to thread. Note! A device can only belong +to one thread. + + +Viewing devices +=============== + +Parm section holds configured info. Current hold running stats. +Result is printed after run or after interruption. Example: + +/proc/net/pktgen/eth1 + +Params: count 10000000 min_pkt_size: 60 max_pkt_size: 60 + frags: 0 delay: 0 clone_skb: 1000000 ifname: eth1 + flows: 0 flowlen: 0 + dst_min: 10.10.11.2 dst_max: + src_min: src_max: + src_mac: 00:00:00:00:00:00 dst_mac: 00:04:23:AC:FD:82 + udp_src_min: 9 udp_src_max: 9 udp_dst_min: 9 udp_dst_max: 9 + src_mac_count: 0 dst_mac_count: 0 + Flags: +Current: + pkts-sofar: 10000000 errors: 39664 + started: 1103053986245187us stopped: 1103053999346329us idle: 880401us + seq_num: 10000011 cur_dst_mac_offset: 0 cur_src_mac_offset: 0 + cur_saddr: 0x10a0a0a cur_daddr: 0x20b0a0a + cur_udp_dst: 9 cur_udp_src: 9 + flows: 0 +Result: OK: 13101142(c12220741+d880401) usec, 10000000 (60byte,0frags) + 763292pps 390Mb/sec (390805504bps) errors: 39664 + +Confguring threads and devices +============================== +This is done via the /proc interface easiest done via pgset in the scripts + +Examples: + + pgset "clone_skb 1" sets the number of copies of the same packet + pgset "clone_skb 0" use single SKB for all transmits + pgset "pkt_size 9014" sets packet size to 9014 + pgset "frags 5" packet will consist of 5 fragments + pgset "count 200000" sets number of packets to send, set to zero + for continious sends untill explicitl stopped. + + pgset "delay 5000" adds delay to hard_start_xmit(). nanoseconds + + pgset "dst 10.0.0.1" sets IP destination address + (BEWARE! This generator is very aggressive!) + + pgset "dst_min 10.0.0.1" Same as dst + pgset "dst_max 10.0.0.254" Set the maximum destination IP. + pgset "src_min 10.0.0.1" Set the minimum (or only) source IP. + pgset "src_max 10.0.0.254" Set the maximum source IP. + pgset "dst6 fec0::1" IPV6 destination address + pgset "src6 fec0::2" IPV6 source address + pgset "dstmac 00:00:00:00:00:00" sets MAC destination address + pgset "srcmac 00:00:00:00:00:00" sets MAC source address + + pgset "src_mac_count 1" Sets the number of MACs we'll range through. + The 'minimum' MAC is what you set with srcmac. + + pgset "dst_mac_count 1" Sets the number of MACs we'll range through. + The 'minimum' MAC is what you set with dstmac. + + pgset "flag [name]" Set a flag to determine behaviour. Current flags + are: IPSRC_RND #IP Source is random (between min/max), + IPDST_RND, UDPSRC_RND, + UDPDST_RND, MACSRC_RND, MACDST_RND + + pgset "udp_src_min 9" set UDP source port min, If < udp_src_max, then + cycle through the port range. + + pgset "udp_src_max 9" set UDP source port max. + pgset "udp_dst_min 9" set UDP destination port min, If < udp_dst_max, then + cycle through the port range. + pgset "udp_dst_max 9" set UDP destination port max. + + pgset stop aborts injection. Also, ^C aborts generator. + + +Example scripts +=============== + +A collection of small tutorial scripts for pktgen is in expamples dir. + +pktgen.conf-1-1 # 1 CPU 1 dev +pktgen.conf-1-2 # 1 CPU 2 dev +pktgen.conf-2-1 # 2 CPU's 1 dev +pktgen.conf-2-2 # 2 CPU's 2 dev +pktgen.conf-1-1-rdos # 1 CPU 1 dev w. route DoS +pktgen.conf-1-1-ip6 # 1 CPU 1 dev ipv6 +pktgen.conf-1-1-ip6-rdos # 1 CPU 1 dev ipv6 w. route DoS +pktgen.conf-1-1-flows # 1 CPU 1 dev multiple flows. + +Run in shell: ./pktgen.conf-X-Y It does all the setup including sending. + + +Interrupt affinity +=================== +Note when adding devices to a specific CPU there good idea to also assign +/proc/irq/XX/smp_affinity so the TX-interrupts gets bound to the same CPU. +as this reduces cache bouncing when freeing skb's. + + +Current commands and configuration options +========================================== + +** Pgcontrol commands: + +start +stop + +** Thread commands: + +add_device +rem_device_all +max_before_softirq + + +** Device commands: + +count +clone_skb +debug + +frags +delay + +src_mac_count +dst_mac_count + +pkt_size +min_pkt_size +max_pkt_size + +udp_src_min +udp_src_max + +udp_dst_min +udp_dst_max + +flag + IPSRC_RND + TXSIZE_RND + IPDST_RND + UDPSRC_RND + UDPDST_RND + MACSRC_RND + MACDST_RND + +dst_min +dst_max + +src_min +src_max + +dst_mac +src_mac + +clear_counters + +dst6 +src6 + +flows +flowlen + +References: +ftp://robur.slu.se/pub/Linux/net-development/pktgen-testing/ +ftp://robur.slu.se/pub/Linux/net-development/pktgen-testing/examples/ + +Paper from Linux-Kongress in Erlangen 2004. +ftp://robur.slu.se/pub/Linux/net-development/pktgen-testing/pktgen_paper.pdf + +Thanks to: +Grant Grundler for testing on IA-64 and parisc, Harald Welte, Lennert Buytenhek +Stephen Hemminger, Andi Kleen, Dave Miller and many others. + + +Good luck with the linux net-development. \ No newline at end of file diff --git a/Documentation/pci.txt b/Documentation/pci.txt index b0676d114..62b1dc5d9 100644 --- a/Documentation/pci.txt +++ b/Documentation/pci.txt @@ -99,10 +99,10 @@ where all fields are passed in as hexadecimal values (no leading 0x). Users need pass only as many fields as necessary; vendor, device, subvendor, and subdevice fields default to PCI_ANY_ID (FFFFFFFF), class and classmask fields default to 0, and driver_data defaults to -0UL. Device drivers must call - pci_dynids_set_use_driver_data(pci_driver *, 1) -in order for the driver_data field to get passed to the driver. -Otherwise, only a 0 is passed in that field. +0UL. Device drivers must initialize use_driver_data in the dynids struct +in their pci_driver struct prior to calling pci_register_driver in order +for the driver_data field to get passed to the driver. Otherwise, only a +0 is passed in that field. When the driver exits, it just calls pci_unregister_driver() and the PCI layer automatically calls the remove hook for all devices handled by the driver. @@ -279,6 +279,7 @@ pci_for_each_dev_reverse() Superseded by pci_find_device_reverse() pci_for_each_bus() Superseded by pci_find_next_bus() pci_find_device() Superseded by pci_get_device() pci_find_subsys() Superseded by pci_get_subsys() +pci_find_slot() Superseded by pci_get_slot() pcibios_find_class() Superseded by pci_get_class() pci_find_class() Superseded by pci_get_class() pci_(read|write)_*_nodev() Superseded by pci_bus_(read|write)_*() diff --git a/Documentation/power/pci.txt b/Documentation/power/pci.txt index c85428e7a..35b1a7dae 100644 --- a/Documentation/power/pci.txt +++ b/Documentation/power/pci.txt @@ -165,40 +165,9 @@ Description: These functions are intended for use by individual drivers, and are defined in struct pci_driver: - int (*save_state) (struct pci_dev *dev, u32 state); - int (*suspend) (struct pci_dev *dev, u32 state); + int (*suspend) (struct pci_dev *dev, pm_message_t state); int (*resume) (struct pci_dev *dev); - int (*enable_wake) (struct pci_dev *dev, u32 state, int enable); - - -save_state ----------- - -Usage: - -if (dev->driver && dev->driver->save_state) - dev->driver->save_state(dev,state); - -The driver should use this callback to save device state. It should take into -account the current state of the device and the requested state in order to -avoid any unnecessary operations. - -For example, a video card that supports all 4 states (D0-D3), all controller -context is preserved when entering D1, but the screen is placed into a low power -state (blanked). - -The driver can also interpret this function as a notification that it may be -entering a sleep state in the near future. If it knows that the device cannot -enter the requested state, either because of lack of support for it, or because -the device is middle of some critical operation, then it should fail. - -This function should not be used to set any state in the device or the driver -because the device may not actually enter the sleep state (e.g. another driver -later causes causes a global state transition to fail). - -Note that in intermediate low power states, a device's I/O and memory spaces may -be disabled and may not be available in subsequent transitions to lower power -states. + int (*enable_wake) (struct pci_dev *dev, pci_power_t state, int enable); suspend diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt index 3b7172df0..c7c3459fd 100644 --- a/Documentation/power/swsusp.txt +++ b/Documentation/power/swsusp.txt @@ -15,6 +15,9 @@ From kernel/suspend.c: * If you change kernel command line between suspend and resume... * ...prepare for nasty fsck or worse. * + * If you change your hardware while system is suspended... + * ...well, it was not good idea. + * * (*) suspend/resume support is needed to make it safe. You need to append resume=/dev/your_swap_partition to kernel command @@ -183,3 +186,50 @@ firmware: tell bios to save state itself [needs BIOS-specific suspend "platform" is actually right thing to do, but "shutdown" is most reliable. + +Q: I do not understand why you have such strong objections to idea of +selective suspend. + +A: Do selective suspend during runtime power managment, that's okay. But +its useless for suspend-to-disk. (And I do not see how you could use +it for suspend-to-ram, I hope you do not want that). + +Lets see, so you suggest to + +* SUSPEND all but swap device and parents +* Snapshot +* Write image to disk +* SUSPEND swap device and parents +* Powerdown + +Oh no, that does not work, if swap device or its parents uses DMA, +you've corrupted data. You'd have to do + +* SUSPEND all but swap device and parents +* FREEZE swap device and parents +* Snapshot +* UNFREEZE swap device and parents +* Write +* SUSPEND swap device and parents + +Which means that you still need that FREEZE state, and you get more +complicated code. (And I have not yet introduce details like system +devices). + +Q: There don't seem to be any generally useful behavioral +distinctions between SUSPEND and FREEZE. + +A: Doing SUSPEND when you are asked to do FREEZE is always correct, +but it may be unneccessarily slow. If you want USB to stay simple, +slowness may not matter to you. It can always be fixed later. + +For devices like disk it does matter, you do not want to spindown for +FREEZE. + +Q: After resuming, system is paging heavilly, leading to very bad interactivity. + +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. diff --git a/Documentation/power/video.txt b/Documentation/power/video.txt index ed8788e93..68734355d 100644 --- a/Documentation/power/video.txt +++ b/Documentation/power/video.txt @@ -1,7 +1,7 @@ Video issues with S3 resume ~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 2003-2004, Pavel Machek + 2003-2005, Pavel Machek During S3 resume, hardware needs to be reinitialized. For most devices, this is easy, and kernel driver knows how to do @@ -11,33 +11,160 @@ boot video card. (Kernel usually does not even contain video card driver -- vesafb and vgacon are widely used). This is not problem for swsusp, because during swsusp resume, BIOS is -run normally so video card is normally initialized. +run normally so video card is normally initialized. S3 has absolutely +no chance of working with SMP/HT. Be sure it to turn it off before +testing (swsusp should work ok, OTOH). -There are three types of systems where video works after S3 resume: +There are a few types of systems where video works after S3 resume: -* systems where video state is preserved over S3. (Athlon HP Omnibook xe3s) +(1) systems where video state is preserved over S3. -* systems where it is possible to call video bios during S3 - resume. Unfortunately, it is not correct to call video BIOS at that - point, but it happens to work on some machines. Use - acpi_sleep=s3_bios (Athlon64 desktop system) +(2) systems where it is possible to call the video BIOS during S3 + resume. Unfortunately, it is not correct to call the video BIOS at + that point, but it happens to work on some machines. Use + acpi_sleep=s3_bios. -* systems that initialize video card into vga text mode and where BIOS - works well enough to be able to set video mode. Use - acpi_sleep=s3_mode on these. (Toshiba 4030cdt) +(3) systems that initialize video card into vga text mode and where + the BIOS works well enough to be able to set video mode. Use + acpi_sleep=s3_mode on these. -* on some systems s3_bios kicks video into text mode, and - acpi_sleep=s3_bios,s3_mode is needed (Toshiba Satellite P10-554) +(4) on some systems s3_bios kicks video into text mode, and + acpi_sleep=s3_bios,s3_mode is needed. -* radeon systems, where X can soft-boot your video card. You'll need - patched X, and plain text console (no vesafb or radeonfb), see - http://www.doesi.gmxhome.de/linux/tm800s3/s3.html. (Acer TM 800) +(5) radeon systems, where X can soft-boot your video card. You'll need + a new enough X, and a plain text console (no vesafb or radeonfb). See + http://www.doesi.gmxhome.de/linux/tm800s3/s3.html for more information. + Alternatively, you should use vbetool (6) instead. + +(6) other radeon systems, where vbetool is enough to bring system back + to life. It needs text console to be working. Do vbetool vbestate + save > /tmp/delme; echo 3 > /proc/acpi/sleep; vbetool post; vbetool + vbestate restore < /tmp/delme; setfont , and your video + should work. + +(7) on some systems, it is possible to boot most of kernel, and then + POSTing bios works. Ole Rohne has patch to do just that at + http://dev.gentoo.org/~marineam/patch-radeonfb-2.6.11-rc2-mm2. Now, if you pass acpi_sleep=something, and it does not work with your -bios, you'll get hard crash during resume. Be carefull. +bios, you'll get a hard crash during resume. Be careful. Also it is +safest to do your experiments with plain old VGA console. The vesafb +and radeonfb (etc) drivers have a tendency to crash the machine during +resume. -You may have system where none of above works. At that point you +You may have a system where none of above works. At that point you either invent another ugly hack that works, or write proper driver for your video card (good luck getting docs :-(). Maybe suspending from X (proper X, knowing your hardware, not XF68_FBcon) might have better chance of working. + +Table of known working systems: + +Model hack (or "how to do it") +------------------------------------------------------------------------------ +Acer Aspire 1406LC ole's late BIOS init (7), turn off DRI +Acer TM 242FX vbetool (6) +Acer TM C300 vga=normal (only suspend on console, not in X), vbetool (6) +Acer TM 4052LCi s3_bios (2) +Acer TM 636Lci s3_bios vga=normal (2) +Acer TM 650 (Radeon M7) vga=normal plus boot-radeon (5) gets text console back +Acer TM 660 ??? (*) +Acer TM 800 vga=normal, X patches, see webpage (5) or vbetool (6) +Acer TM 803 vga=normal, X patches, see webpage (5) or vbetool (6) +Acer TM 803LCi vga=normal, vbetool (6) +Arima W730a vbetool needed (6) +Asus L2400D s3_mode (3)(***) (S1 also works OK) +Asus L3350M (SiS 740) (6) +Asus L3800C (Radeon M7) s3_bios (2) (S1 also works OK) +Asus M6887Ne vga=normal, s3_bios (2), use radeon driver instead of fglrx in x.org +Athlon64 desktop prototype s3_bios (2) +Compal CL-50 ??? (*) +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 Inspiron 4000 ??? (*) +Dell Inspiron 500m ??? (*) +Dell Inspiron 600m ??? (*) +Dell Inspiron 8200 ??? (*) +Dell Inspiron 8500 ??? (*) +Dell Inspiron 8600 ??? (*) +eMachines athlon64 machines vbetool needed (6) (someone please get me model #s) +HP NC6000 s3_bios, may not use radeonfb (2); or vbetool (6) +HP NX7000 ??? (*) +HP Pavilion ZD7000 vbetool post needed, need open-source nv driver for X +HP Omnibook XE3 athlon version none (1) +HP Omnibook XE3GC none (1), video is S3 Savage/IX-MV +IBM TP T20, model 2647-44G none (1), video is S3 Inc. 86C270-294 Savage/IX-MV, vesafb gets "interesting" but X work. +IBM TP A31 / Type 2652-M5G s3_mode (3) [works ok with BIOS 1.04 2002-08-23, but not at all with BIOS 1.11 2004-11-05 :-(] +IBM TP R32 / Type 2658-MMG none (1) +IBM TP R40 2722B3G ??? (*) +IBM TP R50p / Type 1832-22U s3_bios (2) +IBM TP R51 none (1) +IBM TP T30 236681A ??? (*) +IBM TP T40 / Type 2373-MU4 none (1) +IBM TP T40p none (1) +IBM TP R40p s3_bios (2) +IBM TP T41p s3_bios (2), switch to X after resume +IBM TP T42 s3_bios (2) +IBM ThinkPad T42p (2373-GTG) s3_bios (2) +IBM TP X20 ??? (*) +IBM TP X30 s3_bios (2) +IBM TP X31 / Type 2672-XXH none (1), use radeontool (http://fdd.com/software/radeon/) to turn off backlight. +IBM Thinkpad X40 Type 2371-7JG s3_bios,s3_mode (4) +Medion MD4220 ??? (*) +Samsung P35 vbetool needed (6) +Sharp PC-AR10 (ATI rage) none (1) +Sony Vaio PCG-F403 ??? (*) +Sony Vaio PCG-N505SN ??? (*) +Sony Vaio vgn-s260 X or boot-radeon can init it (5) +Toshiba Libretto L5 none (1) +Toshiba Satellite 4030CDT s3_mode (3) +Toshiba Satellite 4080XCDT s3_mode (3) +Toshiba Satellite 4090XCDT ??? (*) +Toshiba Satellite P10-554 s3_bios,s3_mode (4)(****) +Uniwill 244IIO ??? (*) + + +(*) from http://www.ubuntulinux.org/wiki/HoaryPMResults, not sure + which options to use. If you know, please tell me. + +(***) To be tested with a newer kernel. + +(****) Not with SMP kernel, UP only. + +VBEtool details +~~~~~~~~~~~~~~~ +(with thanks to Carl-Daniel Hailfinger) + +First, boot into X and run the following script ONCE: +#!/bin/bash +statedir=/root/s3/state +mkdir -p $statedir +chvt 2 +sleep 1 +vbetool vbestate save >$statedir/vbe + + +To suspend and resume properly, call the following script as root: +#!/bin/bash +statedir=/root/s3/state +curcons=`fgconsole` +fuser /dev/tty$curcons 2>/dev/null|xargs ps -o comm= -p|grep -q X && chvt 2 +cat /dev/vcsa >$statedir/vcsa +sync +echo 3 >/proc/acpi/sleep +sync +vbetool post +vbetool vbestate restore <$statedir/vbe +cat $statedir/vcsa >/dev/vcsa +rckbd restart +chvt $[curcons%6+1] +chvt $curcons + + +Unless you change your graphics card or other hardware configuration, +the state once saved will be OK for every resume afterwards. +NOTE: The "rckbd restart" command may be different for your +distribution. Simply replace it with the command you would use to +set the fonts on screen. diff --git a/Documentation/scsi/ChangeLog b/Documentation/scsi/ChangeLog deleted file mode 100644 index dc88ee2ab..000000000 --- a/Documentation/scsi/ChangeLog +++ /dev/null @@ -1,2023 +0,0 @@ -Sat Jan 18 15:51:45 1997 Richard Henderson - - * Don't play with usage_count directly, instead hand around - the module header and use the module macros. - -Fri May 17 00:00:00 1996 Leonard N. Zubkoff - - * BusLogic Driver Version 2.0.3 Released. - -Tue Apr 16 21:00:00 1996 Leonard N. Zubkoff - - * BusLogic Driver Version 1.3.2 Released. - -Sun Dec 31 23:26:00 1995 Leonard N. Zubkoff - - * BusLogic Driver Version 1.3.1 Released. - -Fri Nov 10 15:29:49 1995 Leonard N. Zubkoff - - * Released new BusLogic driver. - -Wed Aug 9 22:37:04 1995 Andries Brouwer - - As a preparation for new device code, separated the various - functions the request->dev field had into the device proper, - request->rq_dev and a status field request->rq_status. - - The 2nd argument of bios_param is now a kdev_t. - -Wed Jul 19 10:43:15 1995 Michael Neuffer - - * scsi.c (scsi_proc_info): /proc/scsi/scsi now also lists all - attached devices. - - * scsi_proc.c (proc_print_scsidevice): Added. Used by scsi.c and - eata_dma_proc.c to produce some device info for /proc/scsi. - - * eata_dma.c (eata_queue)(eata_int_handler)(eata_scsi_done): - Changed handling of internal SCSI commands send to the HBA. - - -Wed Jul 19 10:09:17 1995 Michael Neuffer - - * Linux 1.3.11 released. - - * eata_dma.c (eata_queue)(eata_int_handler): Added code to do - command latency measurements if requested by root through - /proc/scsi interface. - Throughout Use HZ constant for time references. - - * eata_pio.c: Use HZ constant for time references. - - * aic7xxx.c, aic7xxx.h, aic7xxx_asm.c: Changed copyright from BSD - to GNU style. - - * scsi.h: Added READ_12 command opcode constant - -Wed Jul 19 09:25:30 1995 Michael Neuffer - - * Linux 1.3.10 released. - - * scsi_proc.c (dispatch_scsi_info): Removed unused variable. - -Wed Jul 19 09:25:30 1995 Michael Neuffer - - * Linux 1.3.9 released. - - * scsi.c Blacklist concept expanded to 'support' more device - deficiencies. blacklist[] renamed to device_list[] - (scan_scsis): Code cleanup. - - * scsi_debug.c (scsi_debug_proc_info): Added support to control - device lockup simulation via /proc/scsi interface. - - -Wed Jul 19 09:22:34 1995 Michael Neuffer - - * Linux 1.3.7 released. - - * scsi_proc.c: Fixed a number of bugs in directory handling - -Wed Jul 19 09:18:28 1995 Michael Neuffer - - * Linux 1.3.5 released. - - * Native wide, multichannel and /proc/scsi support now in official - kernel distribution. - - * scsi.c/h, hosts.c/h et al reindented to increase readability - (especially on 80 column wide terminals). - - * scsi.c, scsi_proc.c, ../../fs/proc/inode.c: Added - /proc/scsi/scsi which allows root to scan for hotplugged devices. - - * scsi.c (scsi_proc_info): Added, to support /proc/scsi/scsi. - (scan_scsis): Added some 'spaghetti' code to allow scanning for - single devices. - - -Thu Jun 20 15:20:27 1995 Michael Neuffer - - * proc.c: Renamed to scsi_proc.c - -Mon Jun 12 20:32:45 1995 Michael Neuffer - - * Linux 1.3.0 released. - -Mon May 15 19:33:14 1995 Michael Neuffer - - * scsi.c: Added native multichannel and wide scsi support. - - * proc.c (dispatch_scsi_info) (build_proc_dir_hba_entries): - Updated /proc/scsi interface. - -Thu May 4 17:58:48 1995 Michael Neuffer - - * sd.c (requeue_sd_request): Zero out the scatterlist only if - scsi_malloc returned memory for it. - - * eata_dma.c (register_HBA) (eata_queue): Add support for - large scatter/gather tables and set use_clustering accordingly - - * hosts.c: Make use_clustering changeable in the Scsi_Host structure. - -Wed Apr 12 15:25:52 1995 Eric Youngdale (eric@andante) - - * Linux 1.2.5 released. - - * buslogic.c: Update to version 1.15 (From Leonard N. Zubkoff). - Fixed interrupt routine to avoid races when handling multiple - complete commands per interrupt. Seems to come up with faster - cards. - - * eata_dma.c: Update to 2.3.5r. Modularize. Improved error handling - throughout and fixed bug interrupt routine which resulted in shifted - status bytes. Added blink LED state checks for ISA and EISA HBAs. - Memory management bug seems to have disappeared ==> increasing - C_P_L_CURRENT_MAX to 16 for now. Decreasing C_P_L_DIV to 3 for - performance reasons. - - * scsi.c: If we get a FMK, EOM, or ILI when attempting to scan - the bus, assume that it was just noise on the bus, and ignore - the device. - - * scsi.h: Update and add a bunch of missing commands which we - were never using. - - * sd.c: Use restore_flags in do_sd_request - this may result in - latency conditions, but it gets rid of races and crashes. - Do not save flags again when searching for a second command to - queue. - - * st.c: Use bytes, not STP->buffer->buffer_size when reading - from tape. - - -Tue Apr 4 09:42:08 1995 Eric Youngdale (eric@andante) - - * Linux 1.2.4 released. - - * st.c: Fix typo - restoring wrong flags. - -Wed Mar 29 06:55:12 1995 Eric Youngdale (eric@andante) - - * Linux 1.2.3 released. - - * st.c: Perform some waiting operations with interrupts off. - Is this correct??? - -Wed Mar 22 10:34:26 1995 Eric Youngdale (eric@andante) - - * Linux 1.2.2 released. - - * aha152x.c: Modularize. Add support for PCMCIA. - - * eata.c: Update to version 2.0. Fixed bug preventing media - detection. If scsi_register_host returns NULL, fail gracefully. - - * scsi.c: Detect as NEC (for photo-cd purposes) for the 84 - and 25 models as "NEC_OLDCDR". - - * scsi.h: Add define for NEC_OLDCDR - - * sr.c: Add handling for NEC_OLDCDR. Treat as unknown. - - * u14-34f.c: Update to version 2.0. Fixed same bug as in - eata.c. - - -Mon Mar 6 11:11:20 1995 Eric Youngdale (eric@andante) - - * Linux 1.2.0 released. Yeah!!! - - * Minor spelling/punctuation changes throughout. Nothing - substantive. - -Mon Feb 20 21:33:03 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.95 released. - - * qlogic.c: Update to version 0.41. - - * seagate.c: Change some message to be more descriptive about what - we detected. - - * sr.c: spelling/whitespace changes. - -Mon Feb 20 21:33:03 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.94 released. - -Mon Feb 20 08:57:17 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.93 released. - - * hosts.h: Change io_port to long int from short. - - * 53c7,8xx.c: crash on AEN fixed, SCSI reset is no longer a NOP, - NULL pointer panic on odd UDCs fixed, two bugs in diagnostic output - fixed, should initialize correctly if left running, now loadable, - new memory allocation, extraneous diagnostic output suppressed, - splx() replaced with save/restore flags. [ Drew ] - - * hosts.c, hosts.h, scsi_ioctl.c, sd.c, sd_ioctl.c, sg.c, sr.c, - sr_ioctl.c: Add special junk at end that Emacs will use for - formatting the file. - - * qlogic.c: Update to v0.40a. Improve parity handling. - - * scsi.c: Add Hitachi DK312C to blacklist. Change "};" to "}" in - many places. Use scsi_init_malloc to get command block - may - need this to be dma compatible for some host adapters. - Restore interrupts after unregistering a host. - - * sd.c: Use sti instead of restore flags - causes latency problems. - - * seagate.c: Use controller_type to determine string used when - registering irq. - - * sr.c: More photo-cd hacks to make sure we get the xa stuff right. - * sr.h, sr.c: Change is_xa to xa_flags field. - - * st.c: Disable retries for write operations. - -Wed Feb 15 10:52:56 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.92 released. - - * eata.c: Update to 1.17. - - * eata_dma.c: Update to 2.31a. Add more support for /proc/scsi. - Continuing modularization. Less crashes because of the bug in the - memory management ==> increase C_P_L_CURRENT_MAX to 10 - and decrease C_P_L_DIV to 4. - - * hosts.c: If we remove last host registered, reuse host number. - When freeing memory from host being deregistered, free extra_bytes - too. - - * scsi.c (scan_scsis): memset(SDpnt, 0) and set SCmd.device to SDpnt. - Change memory allocation to work around bugs in __get_dma_pages. - Do not free host if usage count is not zero (for modules). - - * sr_ioctl.c: Increase IOCTL_TIMEOUT to 3000. - - * st.c: Allow for ST_EXTRA_DEVS in st data structures. - - * u14-34f.c: Update to 1.17. - -Thu Feb 9 10:11:16 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.91 released. - - * eata.c: Update to 1.16. Use wish_block instead of host->block. - - * hosts.c: Initialize wish_block to 0. - - * hosts.h: Add wish_block. - - * scsi.c: Use wish_block as indicator that the host should be added - to block list. - - * sg.c: Add SG_EXTRA_DEVS to number of slots. - - * u14-34f.c: Use wish_block. - -Tue Feb 7 11:46:04 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.90 released. - - * eata.c: Change naming from eata_* to eata2x_*. Now at vers 1.15. - Update interrupt handler to take pt_regs as arg. Allow blocking - even if loaded as module. Initialize target_time_out array. - Do not put sti(); in timing loop. - - * hosts.c: Do not reuse host numbers. - Use scsi_make_blocked_list to generate blocking list. - - * script_asm.pl: Beats me. Don't know perl. Something to do with - phase index. - - * scsi.c (scsi_make_blocked_list): New function - code copied from - hosts.c. - - * scsi.c: Update code to disable photo CD for Toshiba cdroms. - Use just manufacturer name, not model number. - - * sr.c: Fix setting density for Toshiba drives. - - * u14-34f.c: Clear target_time_out array during reset. - -Wed Feb 1 09:20:45 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.89 released. - - * Makefile, u14-34f.c: Modularize. - - * Makefile, eata.c: Modularize. Now version 1.14 - - * NCR5380.c: Update interrupt handler with new arglist. Minor - cleanups. - - * eata_dma.c: Begin to modularize. Add hooks for /proc/scsi. - New version 2.3.0a. Add code in interrupt handler to allow - certain CDROM drivers to be detected which return a - CHECK_CONDITION during SCSI bus scan. Add opcode check to get - all DATA IN and DATA OUT phases right. Utilize HBA_interpret flag. - Improvements in HBA identification. Various other minor stuff. - - * hosts.c: Initialize ->dma_channel and ->io_port when registering - a new host. - - * qlogic.c: Modularize and add PCMCIA support. - - * scsi.c: Add Hitachi to blacklist. - - * scsi.c: Change default to no lun scan (too many problem devices). - - * scsi.h: Define QUEUE_FULL condition. - - * sd.c: Do not check for non-existent partition until after - new media check. - - * sg.c: Undo previous change which was wrong. - - * sr_ioctl.c: Increase IOCTL_TIMEOUT to 2000. - - * st.c: Patches from Kai - improve filemark handling. - -Tue Jan 31 17:32:12 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.88 released. - - * Throughout - spelling/grammar fixups. - - * scsi.c: Make sure that all buffers are 16 byte aligned - some - drivers (buslogic) need this. - - * scsi.c (scan_scsis): Remove message printed. - - * scsi.c (scsi_init): Move message here. - -Mon Jan 30 06:40:25 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.87 released. - - * sr.c: Photo-cd related changes. (Gerd Knorr??). - - * st.c: Changes from Kai related to EOM detection. - -Mon Jan 23 23:53:10 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.86 released. - - * 53c7,8xx.h: Change SG size to 127. - - * eata_dma: Update to version 2.10i. Remove bug in the registration - of multiple HBAs and channels. Minor other improvements and stylistic - changes. - - * scsi.c: Test for Toshiba XM-3401TA and exclude from detection - as toshiba drive - photo cd does not work with this drive. - - * sr.c: Update photocd code. - -Mon Jan 23 23:53:10 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.85 released. - - * st.c, st_ioctl.c, sg.c, sd_ioctl.c, scsi_ioctl.c, hosts.c: - include linux/mm.h - - * qlogic.c, buslogic.c, aha1542.c: Include linux/module.h. - -Sun Jan 22 22:08:46 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.84 released. - - * Makefile: Support for loadable QLOGIC boards. - - * aha152x.c: Update to version 1.8 from Juergen. - - * eata_dma.c: Update from Michael Neuffer. - Remove hard limit of 2 commands per lun and make it better - configurable. Improvements in HBA identification. - - * in2000.c: Fix biosparam to support large disks. - - * qlogic.c: Minor changes (change sti -> restore_flags). - -Wed Jan 18 23:33:09 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.83 released. - - * aha1542.c(aha1542_intr_handle): Use arguments handed down to find - which irq. - - * buslogic.c: Likewise. - - * eata_dma.c: Use min of 2 cmd_per_lun for OCS_enabled boards. - - * scsi.c: Make RECOVERED_ERROR a SUGGEST_IS_OK. - - * sd.c: Fail if we are opening a non-existent partition. - - * sr.c: Bump SR_TIMEOUT to 15000. - Do not probe for media size at boot time(hard on changers). - Flag device as needing sector size instead. - - * sr_ioctl.c: Remove CDROMMULTISESSION_SYS ioctl. - - * ultrastor.c: Fix bug in call to ultrastor_interrupt (wrong #args). - -Mon Jan 16 07:18:23 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.82 released. - - Throughout. - - Change all interrupt handlers to accept new calling convention. - In particular, we now receive the irq number as one of the arguments. - - * More minor spelling corrections in some of the new files. - - * aha1542.c, buslogic.c: Clean up interrupt handler a little now - that we receive the irq as an arg. - - * aha274x.c: s/snarf_region/request_region/ - - * eata.c: Update to version 1.12. Fix some comments and display a - message if we cannot reserve the port addresses. - - * u14-34f.c: Update to version 1.13. Fix some comments and display a - message if we cannot reserve the port addresses. - - * eata_dma.c: Define get_board_data function (send INQUIRY command). - Use to improve detection of variants of different DPT boards. Change - version subnumber to "0g". - - * fdomain.c: Update to version 5.26. Improve detection of some boards - repackaged by IBM. - - * scsi.c (scsi_register_host): Change "name" to const char *. - - * sr.c: Fix problem in set mode command for Toshiba drives. - - * sr.c: Fix typo from patch 81. - -Fri Jan 13 12:54:46 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.81 released. Codefreeze for 1.2 release announced. - - Big changes here. - - * eata_dma.*: New files from Michael Neuffer. - (neuffer@goofy.zdv.uni-mainz.de). Should support - all eata/dpt cards. - - * hosts.c, Makefile: Add eata_dma. - - * README.st: Document MTEOM. - - Patches from me (ERY) to finish support for low-level loadable scsi. - It now works, and is actually useful. - - * Throughout - add new argument to scsi_init_malloc that takes an - additional parameter. This is used as a priority to kmalloc, - and you can specify the GFP_DMA flag if you need DMA-able memory. - - * Makefile: For source files that are loadable, always add name - to SCSI_SRCS. Fill in modules: target. - - * hosts.c: Change next_host to next_scsi_host, and make global. - Print hosts after we have identified all of them. Use info() - function if present, otherwise use name field. - - * hosts.h: Change attach function to return int, not void. - Define number of device slots to allow for loadable devices. - Define tags to tell scsi module code what type of module we - are loading. - - * scsi.c: Fix scan_scsis so that it can be run by a user process. - Do not use waiting loops - use up and down mechanism as long - as current != task[0]. - - * scsi.c(scan_scsis): Do not use stack variables for I/O - this - could be > 16Mb if we are loading a module at runtime (i.e. use - scsi_init_malloc to get some memory we know will be safe). - - * scsi.c: Change dma freelist to be a set of pages. This allows - us to dynamically adjust the size of the list by adding more pages - to the pagelist. Fix scsi_malloc and scsi_free accordingly. - - * scsi_module.c: Fix include. - - * sd.c: Declare detach function. Increment/decrement module usage - count as required. Fix init functions to allow loaded devices. - Revalidate all new disks so we get the partition tables. Define - detach function. - - * sr.c: Likewise. - - * sg.c: Declare detach function. Allow attachment of devices on - loaded drivers. - - * st.c: Declare detach function. Increment/decrement module usage - count as required. - -Tue Jan 10 10:09:58 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.79 released. - - Patch from some undetermined individual who needs to get a life :-). - - * sr.c: Attacked by spelling bee... - - Patches from Gerd Knorr: - - * sr.c: make printk messages for photoCD a little more informative. - - * sr_ioctl.c: Fix CDROMMULTISESSION_SYS ioctl. - -Mon Jan 9 10:01:37 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.78 released. - - * Makefile: Add empty modules: target. - - * Wheee. Now change register_iomem to request_region. - - * in2000.c: Bugfix - apparently this is the fix that we have - all been waiting for. It fixes a problem whereby the driver - is not stable under heavy load. Race condition and all that. - Patch from Peter Lu. - -Wed Jan 4 21:17:40 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.77 released. - - * 53c7,8xx.c: Fix from Linus - emulate splx. - - Throughout: - - Change "snarf_region" with "register_iomem". - - * scsi_module.c: New file. Contains support for low-level loadable - scsi drivers. [ERY]. - - * sd.c: More s/int/long/ changes. - - * seagate.c: Explicitly include linux/config.h - - * sg.c: Increment/decrement module usage count on open/close. - - * sg.c: Be a bit more careful about the user not supplying enough - information for a valid command. Pass correct size down to - scsi_do_cmd. - - * sr.c: More changes for Photo-CD. This apparently breaks NEC drives. - - * sr_ioctl.c: Support CDROMMULTISESSION ioctl. - - -Sun Jan 1 19:55:21 1995 Eric Youngdale (eric@andante) - - * Linux 1.1.76 released. - - * constants.c: Add type cast in switch statement. - - * scsi.c (scsi_free): Change datatype of "offset" to long. - (scsi_malloc): Change a few more variables to long. Who - did this and why was it important? 64 bit machines? - - - Lots of changes to use save_state/restore_state instead of cli/sti. - Files changed include: - - * aha1542.c: - * aha1740.c: - * buslogic.c: - * in2000.c: - * scsi.c: - * scsi_debug.c: - * sd.c: - * sr.c: - * st.c: - -Wed Dec 28 16:38:29 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.75 released. - - * buslogic.c: Spelling fix. - - * scsi.c: Add HP C1790A and C2500A scanjet to blacklist. - - * scsi.c: Spelling fixup. - - * sd.c: Add support for sd_hardsizes (hard sector sizes). - - * ultrastor.c: Use save_flags/restore_flags instead of cli/sti. - -Fri Dec 23 13:36:25 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.74 released. - - * README.st: Update from Kai Makisara. - - * eata.c: New version from Dario - version 1.11. - use scsicam bios_param routine. Add support for 2011 - and 2021 boards. - - * hosts.c: Add support for blocking. Linked list automatically - generated when shpnt->block is set. - - * scsi.c: Add sankyo & HP scanjet to blacklist. Add support for - kicking things loose when we deadlock. - - * scsi.c: Recognize scanners and processors in scan_scsis. - - * scsi_ioctl.h: Increase timeout to 9 seconds. - - * st.c: New version from Kai - add better support for backspace. - - * u14-34f.c: New version from Dario. Supports blocking. - -Wed Dec 14 14:46:30 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.73 released. - - * buslogic.c: Update from Dave Gentzel. Version 1.14. - Add module related stuff. More fault tolerant if out of - DMA memory. - - * fdomain.c: New version from Rik Faith - version 5.22. Add support - for ISA-200S SCSI adapter. - - * hosts.c: Spelling. - - * qlogic.c: Update to version 0.38a. Add more support for PCMCIA. - - * scsi.c: Mask device type with 0x1f during scan_scsis. - Add support for deadlocking, err, make that getting out of - deadlock situations that are created when we allow the user - to limit requests to one host adapter at a time. - - * scsi.c: Bugfix - pass pid, not SCpnt as second arg to - scsi_times_out. - - * scsi.c: Restore interrupt state to previous value instead of using - cli/sti pairs. - - * scsi.c: Add a bunch of module stuff (all commented out for now). - - * scsi.c: Clean up scsi_dump_status. - -Tue Dec 6 12:34:20 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.72 released. - - * sg.c: Bugfix - always use sg_free, since we might have big buff. - -Fri Dec 2 11:24:53 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.71 released. - - * sg.c: Clear buff field when not in use. Only call scsi_free if - non-null. - - * scsi.h: Call wake_up(&wait_for_request) when done with a - command. - - * scsi.c (scsi_times_out): Pass pid down so that we can protect - against race conditions. - - * scsi.c (scsi_abort): Zero timeout field if we get the - NOT_RUNNING message back from low-level driver. - - - * scsi.c (scsi_done): Restore cmd_len, use_sg here. - - * scsi.c (request_sense): Not here. - - * hosts.h: Add new forbidden_addr, forbidden_size fields. Who - added these and why???? - - * hosts.c (scsi_mem_init): Mark pages as reserved if they fall in - the forbidden regions. I am not sure - I think this is so that - we can deal with boards that do incomplete decoding of their - address lines for the bios chips, but I am not entirely sure. - - * buslogic.c: Set forbidden_addr stuff if using a buggy board. - - * aha1740.c: Test for NULL pointer in SCtmp. This should not - occur, but a nice message is better than a kernel segfault. - - * 53c7,8xx.c: Add new PCI chip ID for 815. - -Fri Dec 2 11:24:53 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.70 released. - - * ChangeLog, st.c: Spelling. - -Tue Nov 29 18:48:42 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.69 released. - - * u14-34f.h: Non-functional change. [Dario]. - - * u14-34f.c: Use block field in Scsi_Host to prevent commands from - being queued to more than one host at the same time (used when - motherboard does not deal with multiple bus-masters very well). - Only when SINGLE_HOST_OPERATIONS is defined. - Use new cmd_per_lun field. [Dario] - - * eata.c: Likewise. - - * st.c: More changes from Kai. Add ready flag to indicate drive - status. - - * README.st: Document this. - - * sr.c: Bugfix (do not subtract CD_BLOCK_OFFSET) for photo-cd - code. - - * sg.c: Bugfix - fix problem where opcode is not correctly set up. - - * seagate.[c,h]: Use #defines to set driver name. - - * scsi_ioctl.c: Zero buffer before executing command. - - * scsi.c: Use new cmd_per_lun field in Scsi_Hosts as appropriate. - Add Sony CDU55S to blacklist. - - * hosts.h: Add new cmd_per_lun field to Scsi_Hosts. - - * hosts.c: Initialize cmd_per_lun in Scsi_Hosts from template. - - * buslogic.c: Use cmd_per_lun field - initialize to different - values depending upon bus type (i.e. use 1 if ISA, so we do not - hog memory). Use other patches which got lost from 1.1.68. - - * aha1542.c: Spelling. - -Tue Nov 29 15:43:50 1994 Eric Youngdale (eric@andante.aib.com) - - * Linux 1.1.68 released. - - Add support for 12 byte vendor specific commands in scsi-generics, - more (i.e. the last mandatory) low-level changes to support - loadable modules, plus a few other changes people have requested - lately. Changes by me (ERY) unless otherwise noted. Spelling - changes appear from some unknown corner of the universe. - - * Throughout: Change COMMAND_SIZE() to use SCpnt->cmd_len. - - * Throughout: Change info() low level function to take a Scsi_Host - pointer. This way the info function can return specific - information about the host in question, if desired. - - * All low-level drivers: Add NULL in initializer for the - usage_count field added to Scsi_Host_Template. - - * aha152x.[c,h]: Remove redundant info() function. - - * aha1542.[c,h]: Likewise. - - * aha1740.[c,h]: Likewise. - - * aha274x.[c,h]: Likewise. - - * eata.[c,h]: Likewise. - - * pas16.[c,h]: Likewise. - - * scsi_debug.[c,h]: Likewise. - - * t128.[c,h]: Likewise. - - * u14-34f.[c,h]: Likewise. - - * ultrastor.[c,h]: Likewise. - - * wd7000.[c,h]: Likewise. - - * aha1542.c: Add support for command line options with lilo to set - DMA parameters, I/O port. From Matt Aarnio. - - * buslogic.[c,h]: New version (1.13) from Dave Gentzel. - - * hosts.h: Add new field to Scsi_Hosts "block" to allow blocking - all I/O to certain other cards. Helps prevent problems with some - ISA motherboards. - - * hosts.h: Add usage_count to Scsi_Host_Template. - - * hosts.h: Add n_io_port to Scsi_Host (used when releasing module). - - * hosts.c: Initialize block field. - - * in2000.c: Remove "static" declarations from exported functions. - - * in2000.h: Likewise. - - * scsi.c: Correctly set cmd_len field as required. Save and - change setting when doing a request_sense, restore when done. - Move abort timeout message. Fix panic in request_queueable to - print correct function name. - - * scsi.c: When incrementing usage count, walk block linked list - for host, and or in SCSI_HOST_BLOCK bit. When decrementing usage - count to 0, clear this bit to allow usage to continue, wake up - processes waiting. - - - * scsi_ioctl.c: If we have an info() function, call it, otherwise - if we have a "name" field, use it, else do nothing. - - * sd.c, sr.c: Clear cmd_len field prior to each command we - generate. - - * sd.h: Add "has_part_table" bit to rscsi_disks. - - * sg.[c,h]: Add support for vendor specific 12 byte commands (i.e. - override command length in COMMAND_SIZE). - - * sr.c: Bugfix from Gerd in photocd code. - - * sr.c: Bugfix in get_sectorsize - always use scsi_malloc buffer - - we cannot guarantee that the stack is < 16Mb. - -Tue Nov 22 15:40:46 1994 Eric Youngdale (eric@andante.aib.com) - - * Linux 1.1.67 released. - - * sr.c: Change spelling of manufactor to manufacturer. - - * scsi.h: Likewise. - - * scsi.c: Likewise. - - * qlogic.c: Spelling corrections. - - * in2000.h: Spelling corrections. - - * in2000.c: Update from Bill Earnest, change from - jshiffle@netcom.com. Support new bios versions. - - * README.qlogic: Spelling correction. - -Tue Nov 22 15:40:46 1994 Eric Youngdale (eric@andante.aib.com) - - * Linux 1.1.66 released. - - * u14-34f.c: Spelling corrections. - - * sr.[h,c]: Add support for multi-session CDs from Gerd Knorr. - - * scsi.h: Add manufactor field for keeping track of device - manufacturer. - - * scsi.c: More spelling corrections. - - * qlogic.h, qlogic.c, README.qlogic: New driver from Tom Zerucha. - - * in2000.c, in2000.h: New driver from Brad McLean/Bill Earnest. - - * fdomain.c: Spelling correction. - - * eata.c: Spelling correction. - -Fri Nov 18 15:22:44 1994 Eric Youngdale (eric@andante.aib.com) - - * Linux 1.1.65 released. - - * eata.h: Update version string to 1.08.00. - - * eata.c: Set sg_tablesize correctly for DPT PM2012 boards. - - * aha274x.seq: Spell checking. - - * README.st: Likewise. - - * README.aha274x: Likewise. - - * ChangeLog: Likewise. - -Tue Nov 15 15:35:08 1994 Eric Youngdale (eric@andante.aib.com) - - * Linux 1.1.64 released. - - * u14-34f.h: Update version number to 1.10.01. - - * u14-34f.c: Use Scsi_Host can_queue variable instead of one from template. - - * eata.[c,h]: New driver for DPT boards from Dario Ballabio. - - * buslogic.c: Use can_queue field. - -Wed Nov 30 12:09:09 1994 Eric Youngdale (eric@andante.aib.com) - - * Linux 1.1.63 released. - - * sd.c: Give I/O error if we attempt 512 byte I/O to a disk with - 1024 byte sectors. - - * scsicam.c: Make sure we do read from whole disk (mask off - partition). - - * scsi.c: Use can_queue in Scsi_Host structure. - Fix panic message about invalid host. - - * hosts.c: Initialize can_queue from template. - - * hosts.h: Add can_queue to Scsi_Host structure. - - * aha1740.c: Print out warning about NULL ecbptr. - -Fri Nov 4 12:40:30 1994 Eric Youngdale (eric@andante.aib.com) - - * Linux 1.1.62 released. - - * fdomain.c: Update to version 5.20. (From Rik Faith). Support - BIOS version 3.5. - - * st.h: Add ST_EOD symbol. - - * st.c: Patches from Kai Makisara - support additional densities, - add support for MTFSS, MTBSS, MTWSM commands. - - * README.st: Update to document new commands. - - * scsi.c: Add Mediavision CDR-H93MV to blacklist. - -Sat Oct 29 20:57:36 1994 Eric Youngdale (eric@andante.aib.com) - - * Linux 1.1.60 released. - - * u14-34f.[c,h]: New driver from Dario Ballabio. - - * aic7770.c, aha274x_seq.h, aha274x.seq, aha274x.h, aha274x.c, - README.aha274x: New files, new driver from John Aycock. - - -Tue Oct 11 08:47:39 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.54 released. - - * Add third PCI chip id. [Drew] - - * buslogic.c: Set BUSLOGIC_CMDLUN back to 1 [Eric]. - - * ultrastor.c: Fix asm directives for new GCC. - - * sr.c, sd.c: Use new end_scsi_request function. - - * scsi.h(end_scsi_request): Return pointer to block if still - active, else return NULL if inactive. Fixes race condition. - -Sun Oct 9 20:23:14 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.53 released. - - * scsi.c: Do not allocate dma bounce buffers if we have exactly - 16Mb. - -Fri Sep 9 05:35:30 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.51 released. - - * aha152x.c: Add support for disabling the parity check. Update - to version 1.4. [Juergen]. - - * seagate.c: Tweak debugging message. - -Wed Aug 31 10:15:55 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.50 released. - - * aha152x.c: Add eb800 for Vtech Platinum SMP boards. [Juergen]. - - * scsi.c: Add Quantum PD1225S to blacklist. - -Fri Aug 26 09:38:45 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.49 released. - - * sd.c: Fix bug when we were deleting the wrong entry if we - get an unsupported sector size device. - - * sr.c: Another spelling patch. - -Thu Aug 25 09:15:27 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.48 released. - - * Throughout: Use new semantics for request_dma, as appropriate. - - * sr.c: Print correct device number. - -Sun Aug 21 17:49:23 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.47 released. - - * NCR5380.c: Add support for LIMIT_TRANSFERSIZE. - - * constants.h: Add prototype for print_Scsi_Cmnd. - - * pas16.c: Some more minor tweaks. Test for Mediavision board. - Allow for disks > 1Gb. [Drew??] - - * sr.c: Set SCpnt->transfersize. - -Tue Aug 16 17:29:35 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.46 released. - - * Throughout: More spelling fixups. - - * buslogic.c: Add a few more fixups from Dave. Disk translation - mainly. - - * pas16.c: Add a few patches (Drew?). - - -Thu Aug 11 20:45:15 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.44 released. - - * hosts.c: Add type casts for scsi_init_malloc. - - * scsicam.c: Add type cast. - -Wed Aug 10 19:23:01 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.43 released. - - * Throughout: Spelling cleanups. [??] - - * aha152x.c, NCR53*.c, fdomain.c, g_NCR5380.c, pas16.c, seagate.c, - t128.c: Use request_irq, not irqaction. [??] - - * aha1542.c: Move test for shost before we start to use shost. - - * aha1542.c, aha1740.c, ultrastor.c, wd7000.c: Use new - calling sequence for request_irq. - - * buslogic.c: Update from Dave Gentzel. - -Tue Aug 9 09:32:59 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.42 released. - - * NCR5380.c: Change NCR5380_print_status to static. - - * seagate.c: A few more bugfixes. Only Drew knows what they are - for. - - * ultrastor.c: Tweak some __asm__ directives so that it works - with newer compilers. [??] - -Sat Aug 6 21:29:36 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.40 released. - - * NCR5380.c: Return SCSI_RESET_WAKEUP from reset function. - - * aha1542.c: Reset mailbox status after a bus device reset. - - * constants.c: Fix typo (;;). - - * g_NCR5380.c: - * pas16.c: Correct usage of NCR5380_init. - - * scsi.c: Remove redundant (and unused variables). - - * sd.c: Use memset to clear all of rscsi_disks before we use it. - - * sg.c: Ditto, except for scsi_generics. - - * sr.c: Ditto, except for scsi_CDs. - - * st.c: Initialize STp->device. - - * seagate.c: Fix bug. [Drew] - -Thu Aug 4 08:47:27 1994 Eric Youngdale (eric@andante) - - * Linux 1.1.39 released. - - * Makefile: Fix typo in NCR53C7xx. - - * st.c: Print correct number for device. - -Tue Aug 2 11:29:14 1994 Eric Youngdale (eric@esp22) - - * Linux 1.1.38 released. - - Lots of changes in 1.1.38. All from Drew unless otherwise noted. - - * 53c7,8xx.c: New file from Drew. PCI driver. - - * 53c7,8xx.h: Likewise. - - * 53c7,8xx.scr: Likewise. - - * 53c8xx_d.h, 53c8xx_u.h, script_asm.pl: Likewise. - - * scsicam.c: New file from Drew. Read block 0 on the disk and - read the partition table. Attempt to deduce the geometry from - the partition table if possible. Only used by 53c[7,8]xx right - now, but could be used by any device for which we have no way - of identifying the geometry. - - * sd.c: Use device letters instead of sd%d in a lot of messages. - - * seagate.c: Fix bug that resulted in lockups with some devices. - - * sr.c (sr_open): Return -EROFS, not -EACCES if we attempt to open - device for write. - - * hosts.c, Makefile: Update for new driver. - - * NCR5380.c, NCR5380.h, g_NCR5380.h: Update from Drew to support - 53C400 chip. - - * constants.c: Define CONST_CMND and CONST_MSG. Other minor - cleanups along the way. Improve handling of CONST_MSG. - - * fdomain.c, fdomain.h: New version from Rik Faith. Update to - 5.18. Should now support TMC-3260 PCI card with 18C30 chip. - - * pas16.c: Update with new irq initialization. - - * t128.c: Update with minor cleanups. - - * scsi.c (scsi_pid): New variable - gives each command a unique - id. Add Quantum LPS5235S to blacklist. Change in_scan to - in_scan_scsis and make global. - - * scsi.h: Add some defines for extended message handling, - INITIATE/RELEASE_RECOVERY. Add a few new fields to support sync - transfers. - - * scsi_ioctl.h: Add ioctl to request synchronous transfers. - - -Tue Jul 26 21:36:58 1994 Eric Youngdale (eric@esp22) - - * Linux 1.1.37 released. - - * aha1542.c: Always call aha1542_mbenable, use new udelay - mechanism so we do not wait a long time if the board does not - implement this command. - - * g_NCR5380.c: Remove #include and #if - defined(CONFIG_SCSI_*). - - * seagate.c: Likewise. - - Next round of changes to support loadable modules. Getting closer - now, still not possible to do anything remotely usable. - - hosts.c: Create a linked list of detected high level devices. - (scsi_register_device): New function to insert into this list. - (scsi_init): Call scsi_register_device for each of the known high - level drivers. - - hosts.h: Add prototype for linked list header. Add structure - definition for device template structure which defines the linked - list. - - scsi.c: (scan_scsis): Use linked list instead of knowledge about - existing high level device drivers. - (scsi_dev_init): Use init functions for drivers on linked list - instead of explicit list to initialize and attach devices to high - level drivers. - - scsi.h: Add new field "attached" to scsi_device - count of number - of high level devices attached. - - sd.c, sr.c, sg.c, st.c: Adjust init/attach functions to use new - scheme. - -Sat Jul 23 13:03:17 1994 Eric Youngdale (eric@esp22) - - * Linux 1.1.35 released. - - * ultrastor.c: Change constraint on asm() operand so that it works - with gcc 2.6.0. - -Thu Jul 21 10:37:39 1994 Eric Youngdale (eric@esp22) - - * Linux 1.1.33 released. - - * sr.c(sr_open): Do not allow opens with write access. - -Mon Jul 18 09:51:22 1994 1994 Eric Youngdale (eric@esp22) - - * Linux 1.1.31 released. - - * sd.c: Increase SD_TIMEOUT from 300 to 600. - - * sr.c: Remove stray task_struct* variable that was no longer - used. - - * sr_ioctl.c: Fix typo in up() call. - -Sun Jul 17 16:25:29 1994 Eric Youngdale (eric@esp22) - - * Linux 1.1.30 released. - - * scsi.c (scan_scsis): Fix detection of some Toshiba CDROM drives - that report themselves as disk drives. - - * (Throughout): Use request.sem instead of request.waiting. - Should fix swap problem with fdomain. - -Thu Jul 14 10:51:42 1994 Eric Youngdale (eric@esp22) - - * Linux 1.1.29 released. - - * scsi.c (scan_scsis): Add new devices to end of linked list, not - to the beginning. - - * scsi.h (SCSI_SLEEP): Remove brain dead hack to try to save - the task state before sleeping. - -Sat Jul 9 15:01:03 1994 Eric Youngdale (eric@esp22) - - More changes to eventually support loadable modules. Mainly - we want to use linked lists instead of arrays because it is easier - to dynamically add and remove things this way. - - Quite a bit more work is needed before loadable modules are - possible (and usable) with scsi, but this is most of the grunge - work. - - * Linux 1.1.28 released. - - * scsi.c, scsi.h (allocate_device, request_queueable): Change - argument from index into scsi_devices to a pointer to the - Scsi_Device struct. - - * Throughout: Change all calls to allocate_device, - request_queueable to use new calling sequence. - - * Throughout: Use SCpnt->device instead of - scsi_devices[SCpnt->index]. Ugh - the pointer was there all along - - much cleaner this way. - - * scsi.c (scsi_init_malloc, scsi_free_malloc): New functions - - allow us to pretend that we have a working malloc when we - initialize. Use this instead of passing memory_start, memory_end - around all over the place. - - * scsi.h, st.c, sr.c, sd.c, sg.c: Change *_init1 functions to use - scsi_init_malloc, remove all arguments, no return value. - - * scsi.h: Remove index field from Scsi_Device and Scsi_Cmnd - structs. - - * scsi.c (scsi_dev_init): Set up for scsi_init_malloc. - (scan_scsis): Get SDpnt from scsi_init_malloc, and refresh - when we discover a device. Free pointer before returning. - Change scsi_devices into a linked list. - - * scsi.c (scan_scsis): Change to only scan one host. - (scsi_dev_init): Loop over all detected hosts, and scan them. - - * hosts.c (scsi_init_free): Change so that number of extra bytes - is stored in struct, and we do not have to pass it each time. - - * hosts.h: Change Scsi_Host_Template struct to include "next" and - "release" functions. Initialize to NULL in all low level - adapters. - - * hosts.c: Rename scsi_hosts to builtin_scsi_hosts, create linked - list scsi_hosts, linked together with the new "next" field. - -Wed Jul 6 05:45:02 1994 Eric Youngdale (eric@esp22) - - * Linux 1.1.25 released. - - * aha152x.c: Changes from Juergen - cleanups and updates. - - * sd.c, sr.c: Use new check_media_change and revalidate - file_operations fields. - - * st.c, st.h: Add changes from Kai Makisara, dated Jun 22. - - * hosts.h: Change SG_ALL back to 0xff. Apparently soft error - in /dev/brain resulted in having this bumped up. - Change first parameter in bios_param function to be Disk * instead - of index into rscsi_disks. - - * sd_ioctl.c: Pass pointer to rscsi_disks element instead of index - to array. - - * sd.h: Add struct name "scsi_disk" to typedef for Scsi_Disk. - - * scsi.c: Remove redundant Maxtor XT8760S from blacklist. - In scsi_reset, add printk when DEBUG defined. - - * All low level drivers: Modify definitions of bios_param in - appropriate way. - -Thu Jun 16 10:31:59 1994 Eric Youngdale (eric@esp22) - - * Linux 1.1.20 released. - - * scsi_ioctl.c: Only pass down the actual number of characters - required to scsi_do_cmd, not the one rounded up to a even number - of sectors. - - * ultrastor.c: Changes from Caleb Epstein for 24f cards. Support - larger SG lists. - - * ultrastor.c: Changes from me - use scsi_register to register - host. Add some consistency checking, - -Wed Jun 1 21:12:13 1994 Eric Youngdale (eric@esp22) - - * Linux 1.1.19 released. - - * scsi.h: Add new return code for reset() function: - SCSI_RESET_PUNT. - - * scsi.c: Make SCSI_RESET_PUNT the same as SCSI_RESET_WAKEUP for - now. - - * aha1542.c: If the command responsible for the reset is not - pending, return SCSI_RESET_PUNT. - - * aha1740.c, buslogic.c, wd7000.c, ultrastor.c: Return - SCSI_RESET_PUNT instead of SCSI_RESET_SNOOZE. - -Tue May 31 19:36:01 1994 Eric Youngdale (eric@esp22) - - * buslogic.c: Do not print out message about "must be Adaptec" - if we have detected a buslogic card. Print out a warning message - if we are configuring for >16Mb, since the 445S at board level - D or earlier does not work right. The "D" level board can be made - to work by flipping an undocumented switch, but this is too subtle. - - Changes based upon patches in Yggdrasil distribution. - - * sg.c, sg.h: Return sense data to user. - - * aha1542.c, aha1740.c, buslogic.c: Do not panic if - sense buffer is wrong size. - - * hosts.c: Test for ultrastor card before any of the others. - - * scsi.c: Allow boot-time option for max_scsi_luns=? so that - buggy firmware has an easy work-around. - -Sun May 15 20:24:34 1994 Eric Youngdale (eric@esp22) - - * Linux 1.1.15 released. - - Post-codefreeze thaw... - - * buslogic.[c,h]: New driver from David Gentzel. - - * hosts.h: Add use_clustering field to explicitly say whether - clustering should be used for devices attached to this host - adapter. The buslogic board apparently supports large SG lists, - but it is apparently faster if sd.c condenses this into a smaller - list. - - * sd.c: Use this field instead of heuristic. - - * All host adapter include files: Add appropriate initializer for - use_clustering field. - - * scsi.h: Add #defines for return codes for the abort and reset - functions. There are now a specific set of return codes to fully - specify all of the possible things that the low-level adapter - could do. - - * scsi.c: Act based upon return codes from abort/reset functions. - - * All host adapter abort/reset functions: Return new return code. - - * Add code in scsi.c to help debug timeouts. Use #define - DEBUG_TIMEOUT to enable this. - - * scsi.c: If the host->irq field is set, use - disable_irq/enable_irq before calling queuecommand if we - are not already in an interrupt. Reduce races, and we - can be sloppier about cli/sti in the interrupt routines now - (reduce interrupt latency). - - * constants.c: Fix some things to eliminate warnings. Add some - sense descriptions that were omitted before. - - * aha1542.c: Watch for SCRD from host adapter - if we see it, set - a flag. Currently we only print out the number of pending - commands that might need to be restarted. - - * aha1542.c (aha1542_abort): Look for lost interrupts, OGMB still - full, and attempt to recover. Otherwise give up. - - * aha1542.c (aha1542_reset): Try BUS DEVICE RESET, and then pass - DID_RESET back up to the upper level code for all commands running - on this target (even on different LUNs). - -Sat May 7 14:54:01 1994 - - * Linux 1.1.12 released. - - * st.c, st.h: New version from Kai. Supports boot time - specification of number of buffers. - - * wd7000.[c,h]: Updated driver from John Boyd. Now supports - more than one wd7000 board in machine at one time, among other things. - -Wed Apr 20 22:20:35 1994 - - * Linux 1.1.8 released. - - * sd.c: Add a few type casts where scsi_malloc is called. - -Wed Apr 13 12:53:29 1994 - - * Linux 1.1.4 released. - - * scsi.c: Clean up a few printks (use %p to print pointers). - -Wed Apr 13 11:33:02 1994 - - * Linux 1.1.3 released. - - * fdomain.c: Update to version 5.16 (Handle different FIFO sizes - better). - -Fri Apr 8 08:57:19 1994 - - * Linux 1.1.2 released. - - * Throughout: SCSI portion of cluster diffs added. - -Tue Apr 5 07:41:50 1994 - - * Linux 1.1 development tree initiated. - - * The linux 1.0 development tree is now effectively frozen except - for obvious bugfixes. - -****************************************************************** -****************************************************************** -****************************************************************** -****************************************************************** - -Sun Apr 17 00:17:39 1994 - - * Linux 1.0, patchlevel 9 released. - - * fdomain.c: Update to version 5.16 (Handle different FIFO sizes - better). - -Thu Apr 7 08:36:20 1994 - - * Linux 1.0, patchlevel8 released. - - * fdomain.c: Update to version 5.15 from 5.9. Handles 3.4 bios. - -Sun Apr 3 14:43:03 1994 - - * Linux 1.0, patchlevel6 released. - - * wd7000.c: Make stab at fixing race condition. - -Sat Mar 26 14:14:50 1994 - - * Linux 1.0, patchlevel5 released. - - * aha152x.c, Makefile: Fix a few bugs (too much data message). - Add a few more bios signatures. (Patches from Juergen). - - * aha1542.c: Fix race condition in aha1542_out. - -Mon Mar 21 16:36:20 1994 - - * Linux 1.0, patchlevel3 released. - - * sd.c, st.c, sr.c, sg.c: Return -ENXIO, not -ENODEV if we attempt - to open a non-existent device. - - * scsi.c: Add Chinon cdrom to blacklist. - - * sr_ioctl.c: Check return status of verify_area. - -Sat Mar 6 16:06:19 1994 - - * Linux 1.0 released (technically a pre-release). - - * scsi.c: Add IMS CDD521, Maxtor XT-8760S to blacklist. - -Tue Feb 15 10:58:20 1994 - - * pl15e released. - - * aha1542.c: For 1542C, allow dynamic device scan with >1Gb turned - off. - - * constants.c: Fix typo in definition of CONSTANTS. - - * pl15d released. - -Fri Feb 11 10:10:16 1994 - - * pl15c released. - - * scsi.c: Add Maxtor XT-3280 and Rodime RO3000S to blacklist. - - * scsi.c: Allow tagged queueing for scsi 3 devices as well. - Some really old devices report a version number of 0. Disallow - LUN != 0 for these. - -Thu Feb 10 09:48:57 1994 - - * pl15b released. - -Sun Feb 6 12:19:46 1994 - - * pl15a released. - -Fri Feb 4 09:02:17 1994 - - * scsi.c: Add Teac cdrom to blacklist. - -Thu Feb 3 14:16:43 1994 - - * pl15 released. - -Tue Feb 1 15:47:43 1994 - - * pl14w released. - - * wd7000.c (wd_bases): Fix typo in last change. - -Mon Jan 24 17:37:23 1994 - - * pl14u released. - - * aha1542.c: Support 1542CF/extended bios. Different from 1542C - - * wd7000.c: Allow bios at 0xd8000 as well. - - * ultrastor.c: Do not truncate cylinders to 1024. - - * fdomain.c: Update to version 5.9 (add new bios signature). - - * NCR5380.c: Update from Drew - should work a lot better now. - -Sat Jan 8 15:13:10 1994 - - * pl14o released. - - * sr_ioctl.c: Zero reserved field before trying to set audio volume. - -Wed Jan 5 13:21:10 1994 - - * pl14m released. - - * fdomain.c: Update to version 5.8. No functional difference??? - -Tue Jan 4 14:26:13 1994 - - * pl14l released. - - * ultrastor.c: Remove outl, inl functions (now provided elsewhere). - -Mon Jan 3 12:27:25 1994 - - * pl14k released. - - * aha152x.c: Remove insw and outsw functions. - - * fdomain.c: Ditto. - -Wed Dec 29 09:47:20 1993 - - * pl14i released. - - * scsi.c: Support RECOVERED_ERROR for tape drives. - - * st.c: Update of tape driver from Kai. - -Tue Dec 21 09:18:30 1993 - - * pl14g released. - - * aha1542.[c,h]: Support extended BIOS stuff. - - * scsi.c: Clean up messages about disks, so they are displayed as - sda, sdb, etc instead of sd0, sd1, etc. - - * sr.c: Force reread of capacity if disk was changed. - Clear buffer before asking for capacity/sectorsize (some drives - do not report this properly). Set needs_sector_size flag if - drive did not return sensible sector size. - -Mon Dec 13 12:13:47 1993 - - * aha152x.c: Update to version .101 from Juergen. - -Mon Nov 29 03:03:00 1993 - - * linux 0.99.14 released. - - * All scsi stuff moved from kernel/blk_drv/scsi to drivers/scsi. - - * Throughout: Grammatical corrections to various comments. - - * Makefile: fix so that we do not need to compile things we are - not going to use. - - * NCR5380.c, NCR5380.h, g_NCR5380.c, g_NCR5380.h, pas16.c, - pas16.h, t128.c, t128.h: New files from Drew. - - * aha152x.c, aha152x.h: New files from Juergen Fischer. - - * aha1542.c: Support for more than one 1542 in the machine - at the same time. Make functions static that do not need - visibility. - - * aha1740.c: Set NEEDS_JUMPSTART flag in reset function, so we - know to restart the command. Change prototype of aha1740_reset - to take a command pointer. - - * constants.c: Clean up a few things. - - * fdomain.c: Update to version 5.6. Move snarf_region. Allow - board to be set at different SCSI ids. Remove support for - reselection (did not work well). Set JUMPSTART flag in reset - code. - - * hosts.c: Support new low-level adapters. Allow for more than - one adapter of a given type. - - * hosts.h: Allow for more than one adapter of a given type. - - * scsi.c: Add scsi_device_types array, if NEEDS_JUMPSTART is set - after a low-level reset, start the command again. Sort blacklist, - and add Maxtor MXT-1240S, XT-4170S, NEC CDROM 84, Seagate ST157N. - - * scsi.h: Add constants for tagged queueing. - - * Throughout: Use constants from major.h instead of hardcoded - numbers for major numbers. - - * scsi_ioctl.c: Fix bug in buffer length in ioctl_command. Use - verify_area in GET_IDLUN ioctl. Add new ioctls for - TAGGED_QUEUE_ENABLE, DISABLE. Only allow IOCTL_SEND_COMMAND by - superuser. - - * sd.c: Only pay attention to UNIT_ATTENTION for removable disks. - Fix bug where sometimes portions of blocks would get lost - resulting in processes hanging. Add messages when we spin up a - disk, and fix a bug in the timing. Increase read-ahead for disks - that are on a scatter-gather capable host adapter. - - * seagate.c: Fix so that some parameters can be set from the lilo - prompt. Supply jumpstart flag if we are resetting and need the - command restarted. Fix so that we return 1 if we detect a card - so that multiple card detection works correctly. Add yet another - signature for FD cards (950). Add another signature for ST0x. - - * sg.c, sg.h: New files from Lawrence Foard for generic scsi - access. - - * sr.c: Add type casts for (void*) so that we can do pointer - arithmetic. Works with GCC without this, but it is not strictly - correct. Same bugfix as was in sd.c. Increase read-ahead a la - disk driver. - - * sr_ioctl.c: Use scsi_malloc buffer instead of buffer from stack - since we cannot guarantee that the stack is < 16Mb. - - ultrastor.c: Update to support 24f properly (JFC's driver). - - wd7000.c: Supply jumpstart flag for reset. Do not round up - number of cylinders in biosparam function. - -Sat Sep 4 20:49:56 1993 - - * 0.99pl13 released. - - * Throughout: Use check_region/snarf_region for all low-level - drivers. - - * aha1542.c: Do hard reset instead of soft (some ethercard probes - screw us up). - - * scsi.c: Add new flag ASKED_FOR_SENSE so that we can tell if we are - in a loop whereby the device returns null sense data. - - * sd.c: Add code to spin up a drive if it is not already spinning. - Do this one at a time to make it easier on power supplies. - - * sd_ioctl.c: Use sync_dev instead of fsync_dev in BLKFLSBUF ioctl. - - * seagate.c: Switch around DATA/CONTROL lines. - - * st.c: Change sense to unsigned. - -Thu Aug 5 11:59:18 1993 - - * 0.99pl12 released. - - * constants.c, constants.h: New files with ascii descriptions of - various conditions. - - * Makefile: Do not try to count the number of low-level drivers, - just generate the list of .o files. - - * aha1542.c: Replace 16 with sizeof(SCpnt->sense_buffer). Add tests - for addresses > 16Mb, panic if we find one. - - * aha1740.c: Ditto with sizeof(). - - * fdomain.c: Update to version 3.18. Add new signature, register IRQ - with irqaction. Use ID 7 for new board. Be more intelligent about - obtaining the h/s/c numbers for biosparam. - - * hosts.c: Do not depend upon Makefile generated count of the number - of low-level host adapters. - - * scsi.c: Use array for scsi_command_size instead of a function. Add - Texel cdrom and Maxtor XT-4380S to blacklist. Allow compile time - option for no-multi lun scan. Add semaphore for possible problems - with handshaking, assume device is faulty until we know it not to be - the case. Add DEBUG_INIT symbol to dump info as we scan for devices. - Zero sense buffer so we can tell if we need to request it. When - examining sense information, request sense if buffer is all zero. - If RESET, request sense information to see what to do next. - - * scsi_debug.c: Change some constants to use symbols like INT_MAX. - - * scsi_ioctl.c (kernel_scsi_ioctl): New function -for making ioctl - calls from kernel space. - - * sd.c: Increase timeout to 300. Use functions in constants.h to - display info. Use scsi_malloc buffer for READ_CAPACITY, since - we cannot guarantee that a stack based buffer is < 16Mb. - - * sd_ioctl.c: Add BLKFLSBUF ioctl. - - * seagate.c: Add new compile time options for ARBITRATE, - SLOW_HANDSHAKE, and SLOW_RATE. Update assembly loops for transferring - data. Use kernel_scsi_ioctl to request mode page with geometry. - - * sr.c: Use functions in constants.c to display messages. - - * st.c: Support for variable block size. - - * ultrastor.c: Do not use cache for tape drives. Set - unchecked_isa_dma flag, even though this may not be needed (gets set - later). - -Sat Jul 17 18:32:44 1993 - - * 0.99pl11 released. C++ compilable. - - * Throughout: Add type casts all over the place, and use "ip" instead - of "info" in the various biosparam functions. - - * Makefile: Compile seagate.c with C++ compiler. - - * aha1542.c: Always set ccb pointer as this gets trashed somehow on - some systems. Add a few type casts. Update biosparam function a little. - - * aha1740.c: Add a few type casts. - - * fdomain.c: Update to version 3.17 from 3.6. Now works with - TMC-18C50. - - * scsi.c: Minor changes here and there with datatypes. Save use_sg - when requesting sense information so that this can properly be - restored if we retry the command. Set aside dma buffers assuming each - block is 1 page, not 1Kb minix block. - - * scsi_ioctl.c: Add a few type casts. Other minor changes. - - * sd.c: Correctly free all scsi_malloc'd memory if we run out of - dma_pool. Store blocksize information for each partition. - - * seagate.c: Minor cleanups here and there. - - * sr.c: Set up blocksize array for all discs. Fix bug in freeing - buffers if we run out of dma pool. - -Thu Jun 2 17:58:11 1993 - - * 0.99pl10 released. - - * aha1542.c: Support for BT 445S (VL-bus board with no dma channel). - - * fdomain.c: Upgrade to version 3.6. Preliminary support for TNC-18C50. - - * scsi.c: First attempt to fix problem with old_use_sg. Change - NOT_READY to a SUGGEST_ABORT. Fix timeout race where time might - get decremented past zero. - - * sd.c: Add block_fsync function to dispatch table. - - * sr.c: Increase timeout to 500 from 250. Add entry for sync in - dispatch table (supply NULL). If we do not have a sectorsize, - try to get it in the sd_open function. Add new function just to - obtain sectorsize. - - * sr.h: Add needs_sector_size semaphore. - - * st.c: Add NULL for fsync in dispatch table. - - * wd7000.c: Allow another condition for power on that are normal - and do not require a panic. - -Thu Apr 22 23:10:11 1993 - - * 0.99pl9 released. - - * aha1542.c: Use (void) instead of () in setup_mailboxes. - - * scsi.c: Initialize transfersize and underflow fields in SCmd to 0. - Do not panic for unsupported message bytes. - - * scsi.h: Allocate 12 bytes instead of 10 for commands. Add - transfersize and underflow fields. - - * scsi_ioctl.c: Further bugfix to ioctl_probe. - - * sd.c: Use long instead of int for last parameter in sd_ioctl. - Initialize transfersize and underflow fields. - - * sd_ioctl.c: Ditto for sd_ioctl(,,,,); - - * seagate.c: New version from Drew. Includes new signatures for FD - cards. Support for 0ws jumper. Correctly initialize - scsi_hosts[hostnum].this_id. Improved handing of - disconnect/reconnect, and support command linking. Use - transfersize and underflow fields. Support scatter-gather. - - * sr.c, sr_ioctl.c: Use long instead of int for last parameter in sr_ioctl. - Use buffer and buflength in do_ioctl. Patches from Chris Newbold for - scsi-2 audio commands. - - * ultrastor.c: Comment out in_byte (compiler warning). - - * wd7000.c: Change () to (void) in wd7000_enable_dma. - -Wed Mar 31 16:36:25 1993 - - * 0.99pl8 released. - - * aha1542.c: Handle mailboxes better for 1542C. - Do not truncate number of cylinders at 1024 for biosparam call. - - * aha1740.c: Fix a few minor bugs for multiple devices. - Same as above for biosparam. - - * scsi.c: Add lockable semaphore for removable devices that can have - media removal prevented. Add another signature for flopticals. - (allocate_device): Fix race condition. Allow more space in dma pool - for blocksizes of up to 4Kb. - - * scsi.h: Define COMMAND_SIZE. Define a SCSI specific version of - INIT_REQUEST that can run with interrupts off. - - * scsi_ioctl.c: Make ioctl_probe function more idiot-proof. If - a removable device says ILLEGAL REQUEST to a door-locking command, - clear lockable flag. Add SCSI_IOCTL_GET_IDLUN ioctl. Do not attempt - to lock door for devices that do not have lockable semaphore set. - - * sd.c: Fix race condition for multiple disks. Use INIT_SCSI_REQUEST - instead of INIT_REQUEST. Allow sector sizes of 1024 and 256. For - removable disks that are not ready, mark them as having a media change - (some drives do not report this later). - - * seagate.c: Use volatile keyword for memory-mapped register pointers. - - * sr.c: Fix race condition, a la sd.c. Increase the number of retries - to 1. Use INIT_SCSI_REQUEST. Allow 512 byte sector sizes. Do a - read_capacity when we init the device so we know the size and - sectorsize. - - * st.c: If ioctl not found in st.c, try scsi_ioctl for others. - - * ultrastor.c: Do not truncate number of cylinders at 1024 for - biosparam call. - - * wd7000.c: Ditto. - Throughout: Use COMMAND_SIZE macro to determine length of scsi - command. - - - -Sat Mar 13 17:31:29 1993 - - * 0.99pl7 released. - - Throughout: Improve punctuation in some messages, and use new - verify_area syntax. - - * aha1542.c: Handle unexpected interrupts better. - - * scsi.c: Ditto. Handle reset conditions a bit better, asking for - sense information and retrying if required. - - * scsi_ioctl.c: Allow for 12 byte scsi commands. - - * ultrastor.c: Update to use scatter-gather. - -Sat Feb 20 17:57:15 1993 - - * 0.99pl6 released. - - * fdomain.c: Update to version 3.5. Handle spurious interrupts - better. - - * sd.c: Use register_blkdev function. - - * sr.c: Ditto. - - * st.c: Use register_chrdev function. - - * wd7000.c: Undo previous change. - -Sat Feb 6 11:20:43 1993 - - * 0.99pl5 released. - - * scsi.c: Fix bug in testing for UNIT_ATTENTION. - - * wd7000.c: Check at more addresses for bios. Fix bug in biosparam - (heads & sectors turned around). - -Wed Jan 20 18:13:59 1993 - - * 0.99pl4 released. - - * scsi.c: Ignore leading spaces when looking for blacklisted devices. - - * seagate.c: Add a few new signatures for FD cards. Another patch - with SCint to fix race condition. Use recursion_depth to keep track - of how many times we have been recursively called, and do not start - another command unless we are on the outer level. Fixes bug - with Syquest cartridge drives (used to crash kernel), because - they do not disconnect with large data transfers. - -Tue Jan 12 14:33:36 1993 - - * 0.99pl3 released. - - * fdomain.c: Update to version 3.3 (a few new signatures). - - * scsi.c: Add CDU-541, Denon DRD-25X to blacklist. - (allocate_request, request_queueable): Init request.waiting to NULL if - non-buffer type of request. - - * seagate.c: Allow controller to be overridden with CONTROLLER symbol. - Set SCint=NULL when we are done, to remove race condition. - - * st.c: Changes from Kai. - -Wed Dec 30 20:03:47 1992 - - * 0.99pl2 released. - - * scsi.c: Blacklist back in. Remove Newbury drive as other bugfix - eliminates need for it here. - - * sd.c: Return ENODEV instead of EACCES if no such device available. - (sd_init) Init blkdev_fops earlier so that sd_open is available sooner. - - * sr.c: Same as above for sd.c. - - * st.c: Return ENODEV instead of ENXIO if no device. Init chrdev_fops - sooner, so that it is always there even if no tapes. - - * seagate.c (controller_type): New variable to keep track of ST0x or - FD. Modify signatures list to indicate controller type, and init - controller_type once we find a match. - - * wd7000.c (wd7000_set_sync): Remove redundant function. - -Sun Dec 20 16:26:24 1992 - - * 0.99pl1 released. - - * scsi_ioctl.c: Bugfix - check dev->index, not dev->id against - NR_SCSI_DEVICES. - - * sr_ioctl.c: Verify that device exists before allowing an ioctl. - - * st.c: Patches from Kai - change timeout values, improve end of tape - handling. - -Sun Dec 13 18:15:23 1992 - - * 0.99 kernel released. Baseline for this ChangeLog. diff --git a/Documentation/scsi/qla2xxx.revision.notes b/Documentation/scsi/qla2xxx.revision.notes deleted file mode 100644 index 290cdaf84..000000000 --- a/Documentation/scsi/qla2xxx.revision.notes +++ /dev/null @@ -1,457 +0,0 @@ -/* - * QLogic ISP2200 and ISP2300 Linux Driver Revision List File. - * - ******************************************************************** - * - * Revision History - * - * Rev 8.00.00b8 December 5, 2003 AV - * - Instruct mid-layer to perform initial scan. - * - * Rev 8.00.00b7 December 5, 2003 AV - * - Resync with Linux Kernel 2.6.0-test11. - * - Add basic NVRAM parser (extras/qla_nvr). - * - * Rev 8.00.00b7-pre11 December 3, 2003 AV - * - Sanitize the scsi_qla_host structure: - * - Purge unused elements. - * - Reorganize high-priority members (cache coherency). - * - Add support for NVRAM access via a sysfs binary attribute: - * - Consolidate semaphore locking access. - * - Fix more PCI posting issues. - * - Add extras directory for dump/NVRAM tools. - * - Remove unused qla_vendor.c file. - * - * Rev 8.00.00b7-pre11 November 26, 2003 DG/AV - * - Merge several patches from Christoph Hellwig [hch@lst.de]: - * - in Linux 2.6 both pci and the scsi layer use the generic - * dma direction bits, use them directly instead of the scsi - * and pci variants and the (noop) conversion routines. - * - Fix _IOXX_BAD() usage for external IOCTL interface. - * - Use atomic construct for HA loop_state member. - * - Add generic model description text for HBA types. - * - * Rev 8.00.00b7-pre5 November 17, 2003 AV - * - Merge several patches from Christoph Hellwig [hch@lst.de]: - * - patch to split the driver into a common qla2xxx.ko and a - * qla2?00.ko for each HBA type - the latter modules are - * only very small wrappers, mostly for the firmware - * images, all the meat is in the common qla2xxx.ko. - * - make the failover code optional. - * - kill useless lock_kernel in dpc thread startup. - * - no need for modversions hacks in 2.6 (or 2.4). - * - kill qla2x00_register_with_Linux. - * - simplify EH code, cmd or it's hostdata can't be NULL, no - * need to search whether the host it's ours, the midlayer - * makes sure it won't call into a driver for some else - * host. - * - Merge several patches from Jes Sorensen - * [jes@wildopensource.com]: - * - Call qla2x00_config_dma_addressing() before performing - * any consistent allocations. This is required since the - * dma mask settings will affect the memory - * pci_alloc_consistent() will return. - * - Call pci_set_consistent_dma_mask() to allow for 64 bit - * consistent allocations, required on some platforms such - * as the SN2. - * - Wait 20 usecs (not sure how long is really necessary, - * but this seems safe) after setting CSR_ISP_SOFT_RESET in - * the ctrl_status register as the card doesn't respond to - * PCI reads while in reset state. This causes a machine - * check on some architectures. - * - Flush PCI writes before calling udelay() to ensure the - * write is not sitting idle in-flight for a while before - * hitting the hardware. - * - Include linux/vmalloc.h in qla_os.c since it uses - * vmalloc(). - * - Use auto-negotiate link speed when using default - * parameters rather than NVRAM settings. Disable NVRAM - * reading on SN2 since it's not possible to execute the - * HBA's BIOS on an SN2. I suggest doing something similar - * for all architectures that do not provide x86 BIOS - * emulation. - * - Clean-up slab-cache allocations: - * - locking. - * - mempool allocations in case of low-memory situations. - * - Fallback to GA_NXT scan if GID_PT call returns more than - * MAX_FIBRE_DEVICES. - * - Preserve iterating port ID across GA_NXT calls in - * qla2x00_find_all_fabric_devs(). - * - Pre-calculate ASCII firmware dump length as to not incur the - * cost-to-calculate at each invocation of a read(). - * - * Rev 8.00.00b6 November 4, 2003 AV - * - Add new 2300 TPX firmware (3.02.18). - * - * Rev 8.00.00b6-pre25 October 20, 2003 RA/AV - * - Resync with Linux Kernel 2.6.0-test9. - * - Rework firmware dump process: - * - Use binary attribute within sysfs tree. - * - Add user-space tool (gdump.sh) to retrieve formatted - * buffer. - * - Add ISP2100 support. - * - Use a slab cache for SRB allocations to reduce memory - * pressure. - * - Initial conversion of driver logging methods to a new - * qla_printk() function which uses dev_printk (Daniel - * Stekloff, IBM). - * - Further reduce stack usage in qla2x00_configure_local_loop() - * and qla2x00_find_all_fabric_devs(). - * - Separate port state used for routing of I/O's from port - * mgmt-login retry etc. - * - * Rev 8.00.00b6-pre19 October 13, 2003 AV - * - Resync with Linux Kernel 2.6.0-test7-bk5. - * - Add intelligent RSCN event handling: - * - reduce scan time during 'port' RSCN events by only - * querying specified port ids. - * - Available on ISP23xx cards only. - * - Increase maximum number of recognizable targets from 256 - * to 512. - * - Backend changes were previously added to support TPX - * (2K logins) firmware. Mid-layer can now scan for targets - * (H, B, T, L) where 512 < T >= 0. - * - Remove IP support from driver. - * - Switch firmware types from IP->TP for ISP22xx and - * IPX->TPX for ISP23xx cards. - * - Remove files qla_ip.[ch]. - * - Remove type designations from firmware filenames. - * - * Rev 8.00.00b6-pre11 September 15, 2003 DG/AV - * - Resync with 6.06.00. - * - Resync with Linux Kernel 2.6.0-test5-bk3. - * - Add new 2300 IPX firmware (3.02.15). - * - * Rev 8.00.00b5 July 31, 2003 AV - * - Always create an fc_lun_t entry for lun 0 - as the mid- - * layer requires access to this lun for discovery to occur. - * - General sanitizing: - * - Add generic firmware option definitions. - * - Generalize retrieval/update of firmware options. - * - Fix compile errors which occur with extended debug. - * - Handle failure cases for scsi_add_host() and - * down_interruptible(). - * - Host template updates: - * - Use standard bios_param callback function. - * - Disable clustering. - * - Remove unchecked_is_dma entry. - * - * Rev 8.00.00b5-pre5 July 29, 2003 DG/AV - * - Resync with 6.06.00b13. - * - Resync with Linux Kernel 2.6.0-test2. - * - Pass the complete loop_id, not the masked (0xff) value - * while issuing mailbox commands (qla_mbx.c/qla_fo.c/ - * qla_iocb.c/qla_init.c). - * - Properly handle zero-length return status for an RLC CDB. - * - Create an fclun_t structure for 'disconnected' luns, - * peripheral-qualifier of 001b. - * - Remove unused LIP-sequence register access during AE 8010. - * - Generalize qla2x00_mark_device_lost() to handle forced - * login request -- modify all direct/indirect invocations - * with proper flag. - * - Save RSCN notification (AE 8015h) data in a proper and - * consistent format (domain, area, al_pa). - * - General sanitizing: - * - scsi_qla_host structure member reordering for cache-line - * coherency. - * - Remove unused SCSI opcodes, endian-swap definitions. - * - Remove CMD_* pre-processor defines. - * - Remove unused SCSIFCHOTSWAP/GAMAP/MULTIHOST codes. - * - Backout patch which added a per-scsi_qla_host scsi host - * spinlock, since mid-layer already defines one. - * - Add new 2300 IPX firmware (3.02.15). - * - * Rev 8.00.00b4 July 14, 2003 RA/DG/AV - * - Resync with 6.06.00b12. - * - Resync with Linux Kernel 2.6.0-test1. - * - Remove IOCB throttling code -- originally #if'd. - * - Remove apidev_*() routines since proc_mknod() has been - * removed -- need alternate IOCTL interface. - * - Merge several performance/fix patches from Arjan van de - * Ven: - * - Undefined operation >> 32. - * - No need to acquire mid-layer lock during command - * callback. - * - Use a per-HBA mid-layer lock. - * - Use a non-locked cycle for setting the count of the - * newly allocated sp (qla2x00_get_new_sp()). - * - Modify semantic behavior of qla2x00_queuecommand(): - * - Reduce cacheline bouncing by having I/Os submitted - * by the IRQ handler. - * - Remove extraneous calls to qla2x00_next() during I/O - * queuing. - * - Use list_splice_init() during qla2x00_done() handling - * of commands to reduce list_lock contention. - * - RIO mode support for ISP2200: - * - Implementation differs slightly from original patch. - * - Do not use bottom-half handler (tasklet/work queue) - * for qla2x00_done() processing. - * - * Rev 8.00.00b4-pre22 July 12, 2003 AV - * - Check for 'Process Response Queue' requests early during - * the Host Status check. - * - General sanitizing: - * - srb_t structure rewrite, removal of unused members. - * - Remove unused fcdev array, fabricid, and PORT_* - * definitions. - * - Remove unused config_reg_t PCI definitions. - * - Add new 2200 IP firmware (2.02.06). - * - Add new 2300 IPX firmware (3.02.14). - * - * Rev 8.00.00b4-pre19 June 30, 2003 AV - * - Resync with Linux Kernel 2.5.73-bk8. - * - Rework IOCB command queuing methods: - * - Upper-layer driver *MUST* properly set the direction - * bit of SCSI commands. - * - Generalize 32bit/64bit queuing path functions. - * - Remove costly page-boundary cross check when using - * 64bit address capable IOCBs. - * - * Rev 8.00.00b4-pre15 June 19, 2003 AV - * - Resync with 6.06.00b11. - * - Continue fcport list consolidation work: - * - Updated IOCTL implementations to use new fcports - * list. - * - Modified product ID check to not verify ISP chip - * revision -- ISP2312 v3 (qla2x00_chip_diag()). - * - Add new 2300 IPX firmware (3.02.13): - * - * Rev 8.00.00b4-pre13 June 19, 2003 AV - * - Fix build process for qla2100 driver -- no support - * for IP. - * - SCSI host template modifications: - * - Set sg_tablesize based on the derived DMA mask. - * - Increase max_sectors since only limit within RISC - * is transfer of (((2^32) - 1) >> 9) sectors. - * - * Rev 8.00.00b4-pre12 June 18, 2003 RA, DG, RL, AV - * - Resync with 6.06.00b10. - * - Resync with Linux Kernel 2.5.72. - * - Initial fcport list consolidation work: - * - fcports/fcinitiators/fcdev/fc_ip --> ha->fcports - * list. - * - * Rev 8.00.00b4-pre7 June 05, 2003 AV - * - Properly release PCI resouces in init-failure case. - * - Reconcile disparite function return code definitions. - * - * Rev 8.00.00b4-pre4 June 03, 2003 AV - * - Resync with Linux Kernel 2.5.70-bk8: - * - SHT proc_info() changes. - * - Restructure SNS Generic Services routines: - * - Add qla_gs.c file to driver distribution. - * - Configure PCI latency timer for ISP23xx. - * - * Rev 8.00.00b4-pre3 June 02, 2003 RA, DG, RL, AV - * - Resync with 6.06.00b5. - * - Rework (again) PCI I/O space configuration - * (Anton Blanchard): - * - Use pci_set_mwi() routine; - * - Remove uneeded qla2x00_set_cache_line() function. - * - Remove extraneous modification of PCI_COMMAND word. - * - * Rev 8.00.00b3 May 29, 2003 AV - * - Resync with Linux Kernel 2.5.70. - * - Move RISC paused check from ISR fast-path. - * - * Rev 8.00.00b3-pre8 May 26, 2003 AV - * - Add new 2300 IPX firmware (3.02.12): - * - Rework PCI I/O space configuration. - * - * Rev 8.00.00b3-pre6 May 22, 2003 RA, DG, RL, AV - * - Resync with 6.06.00b3. - * - * Rev 8.00.00b3-pre4 May 21 2003 AV - * - Add new 2300 IPX firmware (3.02.11): - * - Remove 2300 TPX firmware from distribution. - * - * Rev 8.00.00b3-pre3 May 21 2003 AV - * - Properly setup PCI configuation space during - * initialization: - * - Properly configure Memory-Mapped I/O during early - * configuration stage. - * - Rework IP functionality to support 2k logins. - * - Add new 2300 IPX firmware (3.02.11): - * - Remove 2300 TPX firmware from distribution. - * - * Rev 8.00.00b3-pre2 May ??, 2003 RA, DG, RL, AV - * - Resync with 6.06.00b1. - * - * Rev 8.00.00b3-pre1 May ??, 2003 RA, DG, RL, AV - * - Resync with 6.05.00. - * - * Rev 8.00.00b2 May 19, 2003 AV - * - Simplify dma_addr_t handling during command queuing given - * new block-layer defined restrictions: - * - Physical addresses not spanning 4GB boundaries. - * - Firmware versions: 2100 TP (1.19.24), 2200 IP (2.02.05), - * 2300 TPX (3.02.10). - * - * Rev 8.00.00b2-pre1 May 13, 2003 AV - * - Add support for new 'Hotplug initialization' model. - * - Simplify host template by removing unused callbacks. - * - Use scsicam facilities to determine geometry. - * - Fix compilation issues for non-ISP23xx builds: - * - Correct register references in qla_dbg.c. - * - Correct Makefile build process. - * - * Rev 8.00.00b1 May 05, 2003 AV - * - Resync with Linux Kernel 2.5.69. - * - Firmware versions: 2100 TP (1.19.24), 2200 TP (2.02.05), - * 2300 TPX (3.02.10). - * - * Rev 8.00.00b1-pre45 April ??, 2003 AV - * - Resync with Linux Kernel 2.5.68-bk11: - * - Fix improper return-code assignment during fabric - * discovery. - * - Remove additional extraneous #defines from - * qla_settings.h. - * - USE_PORTNAME -- FO will always use portname. - * - Default queue depth size set to 64. - * - * Rev 8.00.00b1-pre42 April ??, 2003 AV - * - Convert bottom-half tasklet to a work_queue. - * - Initial basic coding of dynamic queue depth handling - * during QUEUE FULL statuses. - * - Fix mailbox interface problem with - * qla2x00_get_retry_cnt(). - * - * Rev 8.00.00b1-pre41 April ??, 2003 AV - * - Convert build defines qla2[1|2|3]00 macros to - * qla2[1|2|3]xx due to module name stringification clashes. - * - Add additional ISP2322 checks during board configuration. - * - * Rev 8.00.00b1-pre40 April ??, 2003 AV - * - Resync with Linux Kernel 2.5.68-bk8: - * - Updated IRQ handler interface. - * - Add ISP dump code (stub) in case of SYSTEM_ERROR on - * ISP2100. - * - Add new 2200 IP firmware (2.02.05). - * - * Rev 8.00.00b1-pre39 April ??, 2003 AV - * - Resync with Linux Kernel 2.5.68. - * - Add simple build.sh script to aid in external compilation. - * - Clean-break with Kernel 2.4 compatibility. - * - Rework DPC routine -- completion routines for signaling. - * - Re-add HBAAPI character device node for IOCTL support. - * - Remove residual QLA2X_PERFORMANCE defines. - * - Allocate SP pool via __get_free_pages() rather than - * individual kmalloc()'s. - * - Inform SCSI mid-layer of 16-byte CDB support - * (host->max_cmd_len): - * - Remove unecessary 'more_cdb' handling code from - * qla_iocb.c and qla_xioct.c. - * - Reduce duplicate code in fabric scanning logic (MS IOCB - * preparation). - * - Add ISP dump code in case of SYSTEM_ERROR. - * - Remove 2300 VIX firmware from distribution: - * - Add initial code for IPX support. - * - Add new 2300 TPX firmware (3.02.10). - * - * Rev 8.00.00b1-pre34 April ??, 2003 AV - * - Resync with Linux Kernel 2.5.67. - * - Use domain/area/al_pa fields when displaying PortID - * values -- addresses endianess issues. - * - Rework large case statement to check 'common' CDB commands - * early in qla2x00_get_cmd_direction(). - * - * Rev 8.00.00b1-pre31 April ??, 2003 AV - * - Update makefile to support PPC64 build. - * - Retool NVRAM configuration routine and structures: - * - Consoldate ISP21xx/ISP22xx/ISP23xx configuration - * (struct nvram_t). - * - Remove big/little endian support structures in favor of - * simplified bit-operations within byte fields. - * - Fix long-standing 'static' buffer sharing problem in - * qla2x00_configure_fabric(). - * - * Rev 8.00.00b1-pre30 April ??, 2003 AV - * - Complete implementation of GID_PT scan. - * - Use consistent MS IOCB invocation method to query SNS: - * - Add RNN_ID and RSNN_NN registrations in a fabric. - * - Remove unused Mailbox Command 6Eh (Send SNS) support - * structures. - * - Use 64bit safe IOCBs while issuing INQUIRY and RLC during - * topology scan. - * - Until reimplementation of fcdev_t/fcport list - * consolidation, valid loop_id ranges are still limited from - * 0x00 through 0xFF -- enforce this within the code. - * - * Rev 8.00.00b1-pre27 March ??, 2003 AV - * - Resync with 6.05.00b9. - * - Retool HBA PCI configuration -- qla2x00_pci_config(). - * - Remove inconsistent use of delay routines (UDELAY/SYS*). - * - Continue to teardown/clean/add comments and debug - * routines. - * - Properly swap bytes of the device's nodename in - * qla2x00_configure_local_loop(). - * - * Rev 8.00.00b1-pre25 March ??, 2003 AV - * - Resync with 6.05.00b8. - * - * Rev 8.00.00b1-pre23 March ??, 2003 AV - * - Remove (#define) IOCB usage throttling. - * - Abstract interrupt polling with qla2x00_poll(). - * - Modify lun scanning logic: - * - If the device does not support the SCSI Report Luns - * command, the driver will now only scan from 0 to the - * max#-luns as defined in the NVRAM (BIOS), rather than - * blindly scanning from 0 to 255 -- which could result in - * an increase in startup time when running against slow - * (JBOD) devices. - * - Rework reset logic in qla2x00_reset_chip() (spec). - * - * Rev 8.00.00b1-pre22 March ??, 2003 AV - * - Resync with 6.05.00b7. - * - Cleanup (rewrite) ISR handler. - * - Rename kmem_zalloc --> qla2x00_kmem_zalloc(): - * - This function will eventually be removed. - * - Add new 2300 VIX firmware (3.02.09): - * - Support for Tape, Fabric, 2K logins, IP, and VI. - * - * Rev 8.00.00b1-pre18 March ??, 2003 AV - * - Support 232x type ISPs. - * - Support single firmware for each ISP type: - * - Restructure brd_info/fw_info methods. - * - Streamline firmware load process. - * - Properly query firmware for version information. - * - Remove extraneous scsi_qla_host members: - * - device_id ==> pdev->device - * - Fix fc4 features (RFF_ID) registration. - * - Convert kmem_zalloc --> qla2x00_kmem_zalloc(). - * - Remove unused/extraneous #defines (USE_PORTNAME). - * - * Rev 8.00.00b1-pre14 March ??, 2003 AV - * - Resync with 6.05.00b6. - * - Initial source-code restructuring effort. - * - Build procedure. - * - Source file layout -- intuitive component layout. - * - Remove unused #defines (*PERFORMANCE, WORD_FW_LOAD, etc). - * - Add support for 2K logins (TPX -- firmware). - * - Add module parameter ql2xsuspendcount. - * - Add new 2200 IP/TP firmware (2.02.04). - * - * Rev 8.00.00b1-pre9 March ??, 2003 RL/DG/RA/AV - * - Use kernel struct list_head for fcport and fclun lists. - * - Remove extraneous (L|M)S_64BITS() and QL21_64*() defines. - * - * Rev 8.00.00b1-pre8 February 28, 2003 RL/DG/RA/AV - * - Resync with 6.05.00b3. - * - * Rev 8.00.00b1-pre7 February 23, 2003 RL/DG/RA/AV - * - Add alternate fabric scanning logic (GID_PT/GNN_ID/GPN_ID). - * - Remove use of deprecated function check_region(). - * - Add new 2300 IP/TP firmware (3.02.08). - * - * Rev 8.00.00b1-pre5 January 28, 2003 RL/DG/RA/AV - * - Resync with 6.05.00b3. - * - Consolidate device_reg structure definitions for ISP types. - * - Add support for new queue-depth selection. - * - Add new 2300 IP/TP firmware (3.02.07). - * - * Rev 8.00.00b1-pre1 January 17, 2003 AV - * - Initial branch from 6.04.00b8 driver. - * - Remove VMWARE specific code. - * - Add support for pci_driver interface. - * - ********************************************************************/ diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt index e764129e7..e41703d7d 100644 --- a/Documentation/scsi/scsi_mid_low_api.txt +++ b/Documentation/scsi/scsi_mid_low_api.txt @@ -363,8 +363,8 @@ and Adaptec have their own coding conventions. Mid level supplied functions ============================ These functions are supplied by the SCSI mid level for use by LLDs. -The names (i.e. entry points) of these functions are exported (mainly in -scsi_syms.c) so an LLD that is a module can access them. The kernel will +The names (i.e. entry points) of these functions are exported +so an LLD that is a module can access them. The kernel will arrange for the SCSI mid level to be loaded and initialized before any LLD is initialized. The functions below are listed alphabetically and their names all start with "scsi_". @@ -389,8 +389,6 @@ Summary: scsi_remove_host - detach and remove all SCSI devices owned by host scsi_report_bus_reset - report scsi _bus_ reset observed scsi_set_device - place device reference in host structure - scsi_to_pci_dma_dir - convert SCSI subsystem direction flag to PCI - scsi_to_sbus_dma_dir - convert SCSI subsystem direction flag to SBUS scsi_track_queue_full - track successive QUEUE_FULL events scsi_unblock_requests - allow further commands to be queued to given host scsi_unregister - [calls scsi_host_put()] @@ -756,48 +754,6 @@ void scsi_report_bus_reset(struct Scsi_Host * shost, int channel) void scsi_set_device(struct Scsi_Host * shost, struct device * dev) -/** - * scsi_to_pci_dma_dir - convert SCSI subsystem direction flag to PCI - * @scsi_data_direction: SCSI subsystem direction flag - * - * Returns DMA_TO_DEVICE given SCSI_DATA_WRITE, - * DMA_FROM_DEVICE given SCSI_DATA_READ - * DMA_BIDIRECTIONAL given SCSI_DATA_UNKNOWN - * else returns DMA_NONE - * - * Might block: no - * - * Notes: The SCSI subsystem now uses the same values for these - * constants as the PCI subsystem so this function is a nop. - * The recommendation is not to use this conversion function anymore - * (in the 2.6 kernel series) as it is not needed. - * - * Defined in: drivers/scsi/scsi.h . - **/ -int scsi_to_pci_dma_dir(unsigned char scsi_data_direction) - - -/** - * scsi_to_sbus_dma_dir - convert SCSI subsystem direction flag to SBUS - * @scsi_data_direction: SCSI subsystem direction flag - * - * Returns DMA_TO_DEVICE given SCSI_DATA_WRITE, - * FROM_DEVICE given SCSI_DATA_READ - * DMA_BIDIRECTIONAL given SCSI_DATA_UNKNOWN - * else returns DMA_NONE - * - * Notes: The SCSI subsystem now uses the same values for these - * constants as the SBUS subsystem so this function is a nop. - * The recommendation is not to use this conversion function anymore - * (in the 2.6 kernel series) as it is not needed. - * - * Might block: no - * - * Defined in: drivers/scsi/scsi.h . - **/ -int scsi_to_sbus_dma_dir(unsigned char scsi_data_direction) - - /** * scsi_track_queue_full - track successive QUEUE_FULL events on given * device to determine if and when there is a need diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 35b433121..71ef0498d 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -7,75 +7,75 @@ Kernel Configuration ==================== -To enable the ALSA support, at least you need to build the kernel with -the primary sound card support (CONFIG_SOUND). Since ALSA can emulate -the OSS, you don't have to choose any of the OSS/Free modules. Please -enable "OSS API emulation" (CONFIG_SND_OSSEMUL) and both OSS mixer and -PCM supports if you want to run the OSS application with the ALSA. - -When you want to support the WaveTable functionality on some cards -such like SB Live!, you need to enable "Sequencer support" +To enable ALSA support you need at least to build the kernel with +primary sound card support (CONFIG_SOUND). Since ALSA can emulate OSS, +you don't have to choose any of the OSS modules. + +Enable "OSS API emulation" (CONFIG_SND_OSSEMUL) and both OSS mixer and +PCM supports if you want to run OSS applications with ALSA. + +If you want to support the WaveTable functionality on cards such as +SB Live! then you need to enable "Sequencer support" (CONFIG_SND_SEQUENCER). -For getting more verbose debug messages, turn on "Verbose printk" and -"Debug" options. For checking the memory leaks, you can turn on -"Debug memory" option, too. "Debug detection" will put more -additional checks for the detection of cards. +To make ALSA debug messages more verbose, enable the "Verbose printk" +and "Debug" options. To check for memory leaks, turn on "Debug memory" +too. "Debug detection" will add checks for the detection of cards. -Please note that all the ALSA ISA drivers support Linux isapnp API (if -the card supports). You don't need to configure the PnP via -isapnptools. +Please note that all the ALSA ISA drivers support the Linux isapnp API +(if the card supports ISA PnP). You don't need to configure the cards +using isapnptools. Creating ALSA devices ===================== -Use the /dev/MAKEDEV script to create the nessecary device nodes. +This depends on your distribution, but normally you use the /dev/MAKEDEV +script to create the necessary device nodes. On some systems you use a +script named 'snddevices'. Module parameters ================= - A user can modify or set parameters at the load time of the module. If - the module supports more cards and you have got more than one card - of the same type, you may simply specify more values for the parameter, - delimited by commas. - - Note that module option names were changed in 0.9.0rc4. The 'snd_' - prefix was removed. +The user can load modules with options. If the module supports more than +one card and you have more than one card of the same type then you can +specify multiple values for the option separated by commas. + +Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. Module snd ---------- - The module snd is the ALSA core module, which is used by all ALSA - card drivers. This takes the global options for creating devices, - etc. + The core ALSA module. It is used by all ALSA card drivers. + It takes the following options which have global effects. - major - major # for sound driver - - default is 116 + major - major number for sound driver + - Default: 116 cards_limit - - specifies card limit # for auto-loading (1-8) - - default is 1 - - for auto-loading more than 1 card, specify this option - together with snd-card-X aliases. + - limiting card index for auto-loading (1-8) + - Default: 1 + - For auto-loading more than one card, specify this + option together with snd-card-X aliases. device_mode - - specifies permission mask for dynamic sound device filesystem - (available only when DEVFS is enabled) - - default value = 0666 - - for example 'device_mode=0660' + - permission mask for dynamic sound device filesystem + - This is available only when DEVFS is enabled + - Default: 0666 + - E.g.: device_mode=0660 Module snd-pcm-oss ------------------ The PCM OSS emulation module. - This module takes the options to change the mapping of devices. + This module takes options which change the mapping of devices. dsp_map - PCM device number maps assigned to the 1st OSS device. - (default: 0) + - Default: 0 adsp_map - PCM device number maps assigned to the 2st OSS device. - (default: 1) - nonblock_open - Don't block opening busy PCM devices. + - Default: 1 + nonblock_open + - Don't block opening busy PCM devices. For example, when dsp_map=2, /dev/dsp will be mapped to PCM #2 of the card #0. Similarly, when adsp_map=0, /dev/adsp will be mapped @@ -91,33 +91,39 @@ Module parameters Module snd-rawmidi ------------------ - This module takes the options to change the mapping of OSS - devices like snd-pcm-oss module. + This module takes options which change the mapping of devices. + similar to those of the snd-pcm-oss module. midi_map - MIDI device number maps assigned to the 1st OSS device. - (default: 0) + - Default: 0 amidi_map - MIDI device number maps assigned to the 2st OSS device. - (default: 1) - - Common parameters for top soundcard modules - ------------------------------------------- - - Each of top-level soundcard module takes some general options, - - index - 0-7 - index (slot #) for soundcard - - if not set or -1, first free index (slot #) is assigned - id - user identification for card (up to 15 chars) - - default expression is 'card' (for example card1) - - value is used for /proc/asound filesystem - - this value can be used by applications for identification - of card if user does not want identify card with index number - enable - enable card. (all cards enabled for PCI and ISA PnP cards - as default.) + - Default: 1 + + Common parameters for top sound card modules + -------------------------------------------- + + Each of top level sound card module takes the following options. + + index - index (slot #) of sound card + - Values: 0 through 7 or negative + - If nonnegative, assign that index number + - if negative, interpret as a bitmask of permissible + indices; the first free permitted index is assigned + - Default: -1 + id - card ID (identifier or name) + - Can be up to 15 characters long + - Default: the card type + - A directory by this name is created under /proc/asound/ + containing information about the card + - This ID can be used instead of the index number in + identifying the card + enable - enable card + - Default: enabled, for PCI and ISA PnP cards Module snd-ad1816a ------------------ - Module for soundcards based on Analog Devices AD1816A/AD1815 ISA chips. + Module for sound cards based on Analog Devices AD1816A/AD1815 ISA chips. port - port # for AD1816A chip (PnP setup) mpu_port - port # for MPU-401 UART (PnP setup) @@ -132,7 +138,7 @@ Module parameters Module snd-ad1848 ----------------- - Module for soundcards based on AD1848/AD1847/CS4248 ISA chips. + Module for sound cards based on AD1848/AD1847/CS4248 ISA chips. port - port # for AD1848 chip irq - IRQ # for AD1848 chip @@ -147,7 +153,8 @@ Module parameters Module for ALi M5451 PCI chip. pcm_channels - Number of hardware channels assigned for PCM - spdif - Support SPDIF I/O (disabled by default) + spdif - Support SPDIF I/O + - Default: disabled Module supports autoprobe and multiple chips (max 8). @@ -156,7 +163,7 @@ Module parameters Module snd-als100 ----------------- - Module for soundcards based on Avance Logic ALS100/ALS120 ISA chips. + Module for sound cards based on Avance Logic ALS100/ALS120 ISA chips. port - port # for ALS100 (SB16) chip (PnP setup) irq - IRQ # for ALS100 (SB16) chip (PnP setup) @@ -171,7 +178,7 @@ Module parameters Module snd-als4000 ------------------ - Module for soundcards based on Avance Logic ALS4000 PCI chip. + Module for sound cards based on Avance Logic ALS4000 PCI chip. joystick_port - port # for legacy joystick support. 0 = disabled (default), 1 = auto-detect @@ -184,6 +191,8 @@ Module parameters Module for ATI IXP 150/200/250 AC97 controllers. ac97_clock - AC'97 clock (defalut = 48000) + ac97_quirk - AC'97 workaround for strange hardware + See the description of intel8x0 module for details. spdif_aclink - S/PDIF transfer over AC-link (default = 1) This module supports up to 8 cards and autoprobe. @@ -195,6 +204,9 @@ Module parameters Module supports up to 8 cards. + Note: The default index value of this module is -2, i.e. the first + slot is excluded. + Module snd-au8810, snd-au8820, snd-au8830 ----------------------------------------- @@ -224,7 +236,7 @@ Module parameters Module snd-azt2320 ------------------ - Module for soundcards based on Aztech System AZT2320 ISA chip (PnP only). + Module for sound cards based on Aztech System AZT2320 ISA chip (PnP only). port - port # for AZT2320 chip (PnP setup) wss_port - port # for WSS (PnP setup) @@ -240,7 +252,7 @@ Module parameters Module snd-azt3328 ------------------ - Module for soundcards based on Aztech AZF3328 PCI chip. + Module for sound cards based on Aztech AZF3328 PCI chip. joystick - Enable joystick (default off) @@ -252,13 +264,25 @@ Module parameters Module for video cards based on Bt87x chips. digital_rate - Override the default digital rate (Hz) + load_all - Load the driver even if the card model isn't known + + Module supports up to 8 cards. + + Note: The default index value of this module is -2, i.e. the first + slot is excluded. + + Module snd-ca0106 + ----------------- + + Module for Creative Audigy LS and SB Live 24bit Module supports up to 8 cards. + Module snd-cmi8330 ------------------ - Module for soundcards based on C-Media CMI8330 ISA chips. + Module for sound cards based on C-Media CMI8330 ISA chips. wssport - port # for CMI8330 chip (WSS) wssirq - IRQ # for CMI8330 chip (WSS) @@ -273,7 +297,7 @@ Module parameters Module snd-cmipci ----------------- - Module for C-Media CMI8338 and 8738 PCI soundcards. + Module for C-Media CMI8338 and 8738 PCI sound cards. mpu_port - 0x300,0x310,0x320,0x330, 0 = disable (default) fm_port - 0x388 (default), 0 = disable (default) @@ -286,7 +310,7 @@ Module parameters Module snd-cs4231 ----------------- - Module for soundcards based on CS4231 ISA chips. + Module for sound cards based on CS4231 ISA chips. port - port # for CS4231 chip mpu_port - port # for MPU-401 UART (optional), -1 = disable @@ -303,7 +327,7 @@ Module parameters Module snd-cs4232 ----------------- - Module for soundcards based on CS4232/CS4232A ISA chips. + Module for sound cards based on CS4232/CS4232A ISA chips. port - port # for CS4232 chip (PnP setup - 0x534) cport - control port # for CS4232 chip (PnP setup - 0x120,0x210,0xf00) @@ -323,7 +347,7 @@ Module parameters Module snd-cs4236 ----------------- - Module for soundcards based on CS4235/CS4236/CS4236B/CS4237B/ + Module for sound cards based on CS4235/CS4236/CS4236B/CS4237B/ CS4238B/CS4239 ISA chips. port - port # for CS4236 chip (PnP setup - 0x534) @@ -356,7 +380,7 @@ Module parameters Module snd-cs46xx ----------------- - Module for PCI soundcards based on CS4610/CS4612/CS4614/CS4615/CS4622/ + Module for PCI sound cards based on CS4610/CS4612/CS4614/CS4615/CS4622/ CS4624/CS4630/CS4280 PCI chips. external_amp - Force to enable external amplifer. @@ -389,14 +413,14 @@ Module parameters Module snd-dummy ---------------- - Module for the dummy soundcard. This soundcard doesn't do any output + Module for the dummy sound card. This "card" doesn't do any output or input, but you may use this module for any application which - requires a soundcard (like RealPlayer). + requires a sound card (like RealPlayer). Module snd-emu10k1 ------------------ - Module for EMU10K1/EMU10k2 based PCI soundcards. + Module for EMU10K1/EMU10k2 based PCI sound cards. * Sound Blaster Live! * Sound Blaster PCI 512 * Emu APS (partially supported) @@ -426,10 +450,17 @@ Module parameters * Creative Card 5.1 (c) 2003 [0x3fc3/0x7cff] * Creative Card all ins and outs [0x3fff/0x7fff] + Module snd-emu10k1x + ------------------- + + Module for Creative Emu10k1X (SB Live Dell OEM version) + + Module supports up to 8 cards. + Module snd-ens1370 ------------------ - Module for Ensoniq AudioPCI ES1370 PCI soundcards. + Module for Ensoniq AudioPCI ES1370 PCI sound cards. * SoundBlaster PCI 64 * SoundBlaster PCI 128 @@ -440,7 +471,7 @@ Module parameters Module snd-ens1371 ------------------ - Module for Ensoniq AudioPCI ES1371 PCI soundcards. + Module for Ensoniq AudioPCI ES1371 PCI sound cards. * SoundBlaster PCI 64 * SoundBlaster PCI 128 * SoundBlaster Vibra PCI @@ -453,7 +484,7 @@ Module parameters Module snd-es968 ---------------- - Module for soundcards based on ESS ES968 chip (PnP only). + Module for sound cards based on ESS ES968 chip (PnP only). port - port # for ES968 (SB8) chip (PnP setup) irq - IRQ # for ES968 (SB8) chip (PnP setup) @@ -464,7 +495,7 @@ Module parameters Module snd-es1688 ----------------- - Module for ESS AudioDrive ES-1688 and ES-688 soundcards. + Module for ESS AudioDrive ES-1688 and ES-688 sound cards. port - port # for ES-1688 chip (0x220,0x240,0x260) mpu_port - port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable (default) @@ -477,7 +508,7 @@ Module parameters Module snd-es18xx ----------------- - Module for ESS AudioDrive ES-18xx soundcards. + Module for ESS AudioDrive ES-18xx sound cards. port - port # for ES-18xx chip (0x220,0x240,0x260) mpu_port - port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable (default) @@ -496,14 +527,14 @@ Module parameters Module snd-es1938 ----------------- - Module for soundcards based on ESS Solo-1 (ES1938,ES1946) chips. + Module for sound cards based on ESS Solo-1 (ES1938,ES1946) chips. Module supports up to 8 cards and autoprobe. Module snd-es1968 ----------------- - Module for soundcards based on ESS Maestro-1/2/2E (ES1968/ES1978) chips. + Module for sound cards based on ESS Maestro-1/2/2E (ES1968/ES1978) chips. total_bufsize - total buffer size in kB (1-4096kB) pcm_substreams_p - playback channels (1-8, default=2) @@ -521,7 +552,7 @@ Module parameters Module snd-fm801 ---------------- - Module for ForteMedia FM801 based PCI soundcards. + Module for ForteMedia FM801 based PCI sound cards. tea575x_tuner - Enable TEA575x tuner - 1 = MediaForte 256-PCS @@ -535,7 +566,7 @@ Module parameters Module snd-gusclassic --------------------- - Module for Gravis UltraSound Classic soundcard. + Module for Gravis UltraSound Classic sound card. port - port # for GF1 chip (0x220,0x230,0x240,0x250,0x260) irq - IRQ # for GF1 chip (3,5,9,11,12,15) @@ -550,7 +581,7 @@ Module parameters Module snd-gusextreme --------------------- - Module for Gravis UltraSound Extreme (Synergy ViperMax) soundcard. + Module for Gravis UltraSound Extreme (Synergy ViperMax) sound card. port - port # for ES-1688 chip (0x220,0x230,0x240,0x250,0x260) gf1_port - port # for GF1 chip (0x210,0x220,0x230,0x240,0x250,0x260,0x270) @@ -569,7 +600,7 @@ Module parameters Module snd-gusmax ----------------- - Module for Gravis UltraSound MAX soundcard. + Module for Gravis UltraSound MAX sound card. port - port # for GF1 chip (0x220,0x230,0x240,0x250,0x260) irq - IRQ # for GF1 chip (3,5,9,11,12,15) @@ -581,22 +612,49 @@ Module parameters Module supports up to 8 cards and autoprobe. + Module snd-hda-intel + -------------------- + + Module for Intel HD Audio (ICH6, ICH6M, ICH7) + + model - force the model name + + Module supports up to 8 cards. + + Each codec may have a model table for different configurations. + If your machine isn't listed there, the default (usually minimal) + configuration is set up. You can pass "model=" option to + specify a certain model in such a case. There are different + models depending on the codec chip. + + Model name Description + ---------- ----------- + ALC880 + 3stack 3-jack in back and a headphone out + 3stack-digout 3-jack in back, a HP out and a SPDIF out + 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 + + CMI9880 + minimal 3-jack in back + min_fp 3-jack in back, 2-jack in front + 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 + Module snd-hdsp --------------- Module for RME Hammerfall DSP audio interface(s) - precise_ptr - Enable precise pointer (doesn't work reliably). - (default = 0) - line_outs_monitor - Send all input and playback streams to line outs - by default. (default = 0) - force_firmware - Force a reload of the I/O box firmware - (default = 0) - Module supports up to 8 cards. - Note: you need to load the firmware via hdsploader utility included - in alsa-tools and alsa-firmware packages. + Note: The firmware data can be automatically loaded via hotplug + when CONFIG_FW_LOADER is set. Otherwise, you need to load + the firmware via hdsploader utility included in alsa-tools + package. + The firmware data is found in alsa-firmware package. Note: snd-page-alloc module does the job which snd-hammerfall-mem module did formerly. It will allocate the buffers in advance @@ -607,7 +665,7 @@ Module parameters Module snd-ice1712 ------------------ - Module for Envy24 (ICE1712) based PCI soundcards. + Module for Envy24 (ICE1712) based PCI sound cards. * MidiMan M Audio Delta 1010 * MidiMan M Audio Delta 1010LT * MidiMan M Audio Delta DiO 2496 @@ -639,7 +697,7 @@ Module parameters Module snd-ice1724 ------------------ - Module for Envy24HT (VT/ICE1724) based PCI soundcards. + Module for Envy24HT (VT/ICE1724) based PCI sound cards. * MidiMan M Audio Revolution 7.1 * AMP Ltd AUDIO2000 * TerraTec Aureon Sky-5.1, Space-7.1 @@ -661,16 +719,21 @@ Module parameters * ALi m5455 ac97_clock - AC'97 codec clock base (0 = auto-detect) - ac97_quirk - AC'97 workaround for strange hardware (-1 = default) - -1 = default, don't override - 0 = disable - 1 = use headphone control as master - 2 = swap headphone and master controls - 3 = for AD1985, turn on OMS bit and use headphone - 4 = for ALC65x, turn on the jack sense mode - 5 = inverted EAPD implementation - buggy_irq - Enable workaround for buggy interrupts on some - motherboards (default off) + ac97_quirk - AC'97 workaround for strange hardware + The following strings are accepted: + default = don't override the default setting + disable = disable the quirk + hp_only = use headphone control as master + swap_hp = swap headphone and master controls + swap_surround = swap master and surround controls + ad_sharing = for AD1985, turn on OMS bit and use headphone + alc_jack = for ALC65x, turn on the jack sense mode + inv_eapd = inverted EAPD implementation + mute_led = bind EAPD bit for turning on/off mute LED + For backward compatibility, the corresponding integer + value -1, 0, ... are accepted, too. + buggy_irq - Enable workaround for buggy interrupts on some + motherboards (default off) Module supports autoprobe and multiple bus-master chips (max 8). @@ -700,11 +763,14 @@ Module parameters This module supports up to 8 cards and autoprobe. + Note: The default index value of this module is -2, i.e. the first + slot is excluded. + Module snd-interwave -------------------- Module for Gravis UltraSound PnP, Dynasonic 3-D/Pro, STB Sound Rage 32 - and other soundcards based on AMD InterWave (tm) chip. + and other sound cards based on AMD InterWave (tm) chip. port - port # for InterWave chip (0x210,0x220,0x230,0x240,0x250,0x260) irq - IRQ # for InterWave chip (3,5,9,11,12,15) @@ -721,8 +787,8 @@ Module parameters Module snd-interwave-stb ------------------------ - Module for UltraSound 32-Pro (soundcard from STB used by Compaq) - and other soundcards based on AMD InterWave (tm) chip with TEA6330T + Module for UltraSound 32-Pro (sound card from STB used by Compaq) + and other sound cards based on AMD InterWave (tm) chip with TEA6330T circuit for extended control of bass, treble and master volume. port - port # for InterWave chip (0x210,0x220,0x230,0x240,0x250,0x260) @@ -768,12 +834,18 @@ Module parameters Module snd-mixart ----------------- - Module for Digigram miXart8 soundcards. + Module for Digigram miXart8 sound cards. Module supports multiple cards. Note: One miXart8 board will be represented as 4 alsa cards. See MIXART.txt for details. + When the driver is compiled as a module and the hotplug firmware + is supported, the firmware data is loaded via hotplug automatically. + Install the necessary firmware files in alsa-firmware package. + When no hotplug fw loader is available, you need to load the + firmware via mixartloader utility in alsa-tools package. + Module snd-mpu401 ----------------- @@ -781,10 +853,9 @@ Module parameters port - port number or -1 (disable) irq - IRQ number or -1 (disable) - acpipnp - ACPI PnP detection - 0 = disable, 1 = enable (default) + pnp - PnP detection - 0 = disable, 1 = enable (default) - Module supports multiple devices (max 8) and ACPI PnP. If PnP is not - used (or ACPI not enabled), port and irq must be specified. + Module supports multiple devices (max 8) and PnP. Module snd-mtpav ---------------- @@ -851,7 +922,7 @@ Module parameters Module snd-opl3sa2 ------------------ - Module for Yamaha OPL3-SA2/SA3 soundcards. + Module for Yamaha OPL3-SA2/SA3 sound cards. port - control port # for OPL3-SA chip (0x370) sb_port - SB port # for OPL3-SA chip (0x220,0x240) @@ -871,7 +942,7 @@ Module parameters Module snd-opti92x-ad1848 ------------------------- - Module for soundcards based on OPTi 82c92x and Analog Devices AD1848 chips. + Module for sound cards based on OPTi 82c92x and Analog Devices AD1848 chips. Module works with OAK Mozart cards as well. port - port # for WSS chip (0x530,0xe80,0xf40,0x604) @@ -886,7 +957,7 @@ Module parameters Module snd-opti92x-cs4231 ------------------------- - Module for soundcards based on OPTi 82c92x and Crystal CS4231 chips. + Module for sound cards based on OPTi 82c92x and Crystal CS4231 chips. port - port # for WSS chip (0x530,0xe80,0xf40,0x604) mpu_port - port # for MPU-401 UART (0x300,0x310,0x320,0x330) @@ -901,7 +972,7 @@ Module parameters Module snd-opti93x ------------------ - Module for soundcards based on OPTi 82c93x chips. + Module for sound cards based on OPTi 82c93x chips. port - port # for WSS chip (0x530,0xe80,0xf40,0x604) mpu_port - port # for MPU-401 UART (0x300,0x310,0x320,0x330) @@ -930,21 +1001,21 @@ Module parameters ---------------- Module for RME Digi32, Digi32 Pro and Digi32/8 (Sek'd Prodif32, - Prodif96 and Prodif Gold) soundcards. + Prodif96 and Prodif Gold) sound cards. Module supports up to 8 cards. Module snd-rme96 ---------------- - Module for RME Digi96, Digi96/8 and Digi96/8 PRO/PAD/PST soundcards. + Module for RME Digi96, Digi96/8 and Digi96/8 PRO/PAD/PST sound cards. Module supports up to 8 cards. Module snd-rme9652 ------------------ - Module for RME Digi9652 (Hammerfall, Hammerfall-Light) soundcards. + Module for RME Digi9652 (Hammerfall, Hammerfall-Light) sound cards. precise_ptr - Enable precise pointer (doesn't work reliably). (default = 0) @@ -960,7 +1031,7 @@ Module parameters Module snd-sa11xx-uda1341 (on arm only) --------------------------------------- - Module for Philips UDA1341TS on Compaq iPAQ H3600 soundcard. + Module for Philips UDA1341TS on Compaq iPAQ H3600 sound card. Module supports only one card. Module has no enable and index options. @@ -1007,7 +1078,7 @@ Module parameters Module snd-sgalaxy ------------------ - Module for Aztech Sound Galaxy soundcard. + Module for Aztech Sound Galaxy sound card. sbport - Port # for SB16 interface (0x220,0x240) wssport - Port # for WSS interface (0x530,0xe80,0xf40,0x604) @@ -1047,7 +1118,7 @@ Module parameters Module snd-wavefront -------------------- - Module for Turtle Beach Maui, Tropez and Tropez+ soundcards. + Module for Turtle Beach Maui, Tropez and Tropez+ sound cards. cs4232_pcm_port - Port # for CS4232 PCM interface. cs4232_pcm_irq - IRQ # for CS4232 PCM interface (5,7,9,11,12,15). @@ -1067,7 +1138,7 @@ Module parameters Module snd-sonicvibes --------------------- - Module for S3 SonicVibes PCI soundcards. + Module for S3 SonicVibes PCI sound cards. * PINE Schubert 32 PCI reverb - Reverb Enable - 1 = enable, 0 = disable (default) @@ -1099,7 +1170,7 @@ Module parameters Module snd-trident ------------------ - Module for Trident 4DWave DX/NX soundcards. + Module for Trident 4DWave DX/NX sound cards. * Best Union Miss Melody 4DWave PCI * HIS 4DWave PCI * Warpspeed ONSpeed 4DWave PCI @@ -1182,6 +1253,18 @@ Module parameters Note: for the MPU401 on VIA823x, use snd-mpu401 driver additonally. The mpu_port option is for VIA686 chips only. + Module snd-via82xx-modem + ------------------------ + + Module for VIA82xx AC97 modem + + ac97_clock - AC'97 codec clock base (default 48000Hz) + + Module supports up to 8 cards. + + Note: The default index value of this module is -2, i.e. the first + slot is excluded. + Module snd-virmidi ------------------ @@ -1203,9 +1286,12 @@ Module parameters Module supports up to 8 cards. - For loading the firmware, use vxloader utility in alsa-tools - and alsa-firmware packages. You can load the firmware automatically - by adding the following to /etc/modprobe.conf + When the driver is compiled as a module and the hotplug firmware + is supported, the firmware data is loaded via hotplug automatically. + Install the necessary firmware files in alsa-firmware package. + When no hotplug fw loader is available, you need to load the + firmware via vxloader utility in alsa-tools package. To invoke + vxloader automatically, add the following to /etc/modprobe.conf install snd-vx222 /sbin/modprobe --first-time -i snd-vx222 && /usr/bin/vxloader @@ -1222,10 +1308,6 @@ Module parameters Module for Digigram VX-Pocket VX2 PCMCIA card. - irq_mask - IRQ bitmask, specifies the available IRQs as bits - (default = 0xffff, all available) - irq_list - List of available interrupts (default = -1, not specified) - 4 numbers must be given (if specified). ibl - Capture IBL size. (default = 0, minimum size) Module supports up to 8 cards. The module is compiled only when @@ -1234,11 +1316,11 @@ Module parameters To activate the driver via the card manager, you'll need to set up /etc/pcmcia/vxpocket.conf. See the sound/pcmcia/vx/vxpocket.c. - For loading the firmware, use vxloader utility in alsa-tools - and alsa-firmware packages. - - The irq_mask and irq_list are provided to avoid allocation of - specific IRQs. Usually you don't need to specify them. + When the driver is compiled as a module and the hotplug firmware + is supported, the firmware data is loaded via hotplug automatically. + Install the necessary firmware files in alsa-firmware package. + When no hotplug fw loader is available, you need to load the + firmware via vxloader utility in alsa-tools package. About capture IBL, see the description of snd-vx222 module. @@ -1249,9 +1331,6 @@ Module parameters Module for Digigram VX-Pocket 440 PCMCIA card. - irq_mask - IRQ bitmask, specifies the available IRQs as bits - irq_list - List of available interrupts (default = -1, not specified) - 4 numbers must be given (if specified). ibl - Capture IBL size. (default = 0, minimum size) Module supports up to 8 cards. The module is compiled only when @@ -1260,11 +1339,11 @@ Module parameters To activate the driver via the card manager, you'll need to set up /etc/pcmcia/vxp440.conf. See the sound/pcmcia/vx/vxp440.c. - For loading the firmware, use vxloader utility in alsa-tools - and alsa-firmware packages. - - The irq_mask and irq_list are provided to avoid allocation of - specific IRQs. Usually you don't need to specify them. + When the driver is compiled as a module and the hotplug firmware + is supported, the firmware data is loaded via hotplug automatically. + Install the necessary firmware files in alsa-firmware package. + When no hotplug fw loader is available, you need to load the + firmware via vxloader utility in alsa-tools package. About capture IBL, see the description of snd-vx222 module. @@ -1290,10 +1369,7 @@ Module parameters Module snd-pdaudiocf -------------------- - Module for Sound Core PDAudioCF soundcard. - - irq_mask - IRQ mask (PCMCIA type) - irq_list - List of available interrupts for this soundcard + Module for Sound Core PDAudioCF sound card. Note: the driver is build only when CONFIG_ISA is set. @@ -1316,7 +1392,7 @@ Module Autoloading Support The ALSA drivers can be loaded automatically on demand by defining module aliases. The string 'snd-card-%1' is requested for ALSA native -devices where %i is soundcard number from zero to seven. +devices where %i is sound card number from zero to seven. To auto-load an ALSA driver for OSS services, define the string 'sound-slot-%i' where %i means the slot number for OSS, which @@ -1329,16 +1405,16 @@ alias snd-card-0 snd-emu10k1 alias sound-slot-0 snd-emu10k1 ----- /etc/modprobe.conf -The available number of auto-loaded soundcards depends on the module +The available number of auto-loaded sound cards depends on the module option "cards_limit" of snd module. As default it's set to 1. To enable the auto-loading of multiple cards, specify the number of -soundcards in that option. +sound cards in that option. When multiple cards are available, it'd better to specify the index number for each card via module option, too, so that the order of cards is kept consistent. -An example configuration for two soundcards is like below: +An example configuration for two sound cards is like below: ----- /etc/modprobe.conf # ALSA portion @@ -1359,18 +1435,21 @@ In this example, the interwave card is always loaded as the first card ALSA PCM devices to OSS devices mapping ======================================= -/dev/snd/pcmC0D0 -> /dev/audio0 (/dev/audio) -> minor 4 -/dev/snd/pcmC0D0 -> /dev/dsp0 (/dev/dsp) -> minor 3 -/dev/snd/pcmC0D1 -> /dev/adsp0 (/dev/adsp) -> minor 12 -/dev/snd/pcmC1D0 -> /dev/audio1 -> minor 4+16 = 20 -/dev/snd/pcmC1D0 -> /dev/dsp1 -> minor 3+16 = 19 -/dev/snd/pcmC1D1 -> /dev/adsp1 -> minor 12+16 = 28 -/dev/snd/pcmC2D0 -> /dev/audio2 -> minor 4+32 = 36 -/dev/snd/pcmC2D0 -> /dev/dsp2 -> minor 3+32 = 39 -/dev/snd/pcmC2D1 -> /dev/adsp2 -> minor 12+32 = 44 - -The first number from /dev/snd/pcmC{X}D{Y} expression means soundcard number -and second means device number. +/dev/snd/pcmC0D0[c|p] -> /dev/audio0 (/dev/audio) -> minor 4 +/dev/snd/pcmC0D0[c|p] -> /dev/dsp0 (/dev/dsp) -> minor 3 +/dev/snd/pcmC0D1[c|p] -> /dev/adsp0 (/dev/adsp) -> minor 12 +/dev/snd/pcmC1D0[c|p] -> /dev/audio1 -> minor 4+16 = 20 +/dev/snd/pcmC1D0[c|p] -> /dev/dsp1 -> minor 3+16 = 19 +/dev/snd/pcmC1D1[c|p] -> /dev/adsp1 -> minor 12+16 = 28 +/dev/snd/pcmC2D0[c|p] -> /dev/audio2 -> minor 4+32 = 36 +/dev/snd/pcmC2D0[c|p] -> /dev/dsp2 -> minor 3+32 = 39 +/dev/snd/pcmC2D1[c|p] -> /dev/adsp2 -> minor 12+32 = 44 + +The first number from /dev/snd/pcmC{X}D{Y}[c|p] expression means +sound card number and second means device number. The ALSA devices +have either 'c' or 'p' suffix indicating the direction, capture and +playback, respectively. + Please note that the device mapping above may be varied via the module options of snd-pcm-oss module. diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index d08c20d86..e78947530 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl @@ -18,8 +18,8 @@ - July 11, 2004 - 0.3.3 + March 6, 2005 + 0.3.4 @@ -110,9 +110,9 @@ - One is the the trees provided as a tarball or via cvs from the + One is the trees provided as a tarball or via cvs from the ALSA's ftp site, and another is the 2.6 (or later) Linux kernel - tree. To synchronize both, the ALSA driver tree is split to + tree. To synchronize both, the ALSA driver tree is split into two different trees: alsa-kernel and alsa-driver. The former contains purely the source codes for the Linux 2.6 (or later) tree. This tree is designed only for compilation on 2.6 or @@ -397,12 +397,12 @@ #include #include - // module parameters (see "Module Parameters") + /* module parameters (see "Module Parameters") */ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; - // definition of the chip-specific record + /* definition of the chip-specific record */ typedef struct snd_mychip mychip_t; struct snd_mychip { snd_card_t *card; @@ -410,23 +410,26 @@ // "PCI Resource Managements" }; - // chip-specific destructor - // (see "PCI Resource Managements") + /* chip-specific destructor + * (see "PCI Resource Managements") + */ static int snd_mychip_free(mychip_t *chip) { - // will be implemented later... + .... // will be implemented later... } - // component-destructor - // (see "Management of Cards and Components") + /* component-destructor + * (see "Management of Cards and Components") + */ static int snd_mychip_dev_free(snd_device_t *device) { mychip_t *chip = device->device_data; return snd_mychip_free(chip); } - // chip-specific constructor - // (see "Management of Cards and Components") + /* chip-specific constructor + * (see "Management of Cards and Components") + */ static int __devinit snd_mychip_create(snd_card_t *card, struct pci_dev *pci, mychip_t **rchip) @@ -441,8 +444,9 @@ // check PCI availability here // (see "PCI Resource Managements") + .... - // allocate a chip-specific data with zero filled + /* allocate a chip-specific data with zero filled */ chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); if (chip == NULL) return -ENOMEM; @@ -451,17 +455,21 @@ // rest of initialization here; will be implemented // later, see "PCI Resource Managements" + .... if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { snd_mychip_free(chip); return err; } + + snd_card_set_dev(card, &pci->dev); + *rchip = chip; return 0; } - // constructor -- see "Constructor" sub-section + /* constructor -- see "Constructor" sub-section */ static int __devinit snd_mychip_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { @@ -470,7 +478,7 @@ mychip_t *chip; int err; - // (1) + /* (1) */ if (dev >= SNDRV_CARDS) return -ENODEV; if (!enable[dev]) { @@ -478,39 +486,39 @@ return -ENOENT; } - // (2) + /* (2) */ card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); if (card == NULL) return -ENOMEM; - // (3) + /* (3) */ if ((err = snd_mychip_create(card, pci, &chip)) < 0) { snd_card_free(card); return err; } - // (4) + /* (4) */ strcpy(card->driver, "My Chip"); strcpy(card->shortname, "My Own Chip 123"); sprintf(card->longname, "%s at 0x%lx irq %i", card->shortname, chip->ioport, chip->irq); - // (5) - // implemented later + /* (5) */ + .... // implemented later - // (6) + /* (6) */ if ((err = snd_card_register(card)) < 0) { snd_card_free(card); return err; } - // (7) + /* (7) */ pci_set_drvdata(pci, card); dev++; return 0; } - // destructor -- see "Destructor" sub-section + /* destructor -- see "Destructor" sub-section */ static void __devexit snd_mychip_remove(struct pci_dev *pci) { snd_card_free(pci_get_drvdata(pci)); @@ -743,7 +751,7 @@ - where the last twos are necessary only when module options are + where the last one is necessary only when module options are defined in the source file. If the codes are split to several files, the file without module options don't need them. @@ -758,7 +766,7 @@ - The ALSA interfaces like PCM or control API are define in other + The ALSA interfaces like PCM or control API are defined in other header files as <sound/xxx.h>. They have to be included after <sound/core.h>. @@ -1089,20 +1097,22 @@ static int snd_mychip_free(mychip_t *chip) { - // disable hardware here if any - // (not implemented in this document) + /* disable hardware here if any */ + .... // (not implemented in this document) - // release the irq + /* release the irq */ if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); - // release the i/o ports + /* release the i/o ports & memory */ pci_release_regions(chip->pci); - // release the data + /* disable the PCI entry */ + pci_disable_device(chip->pci); + /* release the data */ kfree(chip); return 0; } - // chip-specific constructor + /* chip-specific constructor */ static int __devinit snd_mychip_create(snd_card_t *card, struct pci_dev *pci, mychip_t **rchip) @@ -1115,27 +1125,32 @@ *rchip = NULL; - // check PCI availability (28bit DMA) + /* initialize the PCI entry */ if ((err = pci_enable_device(pci)) < 0) return err; + /* check PCI availability (28bit DMA) */ if (pci_set_dma_mask(pci, 0x0fffffff) < 0 || pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) { printk(KERN_ERR "error to set 28bit mask DMA\n"); + pci_disable_device(pci); return -ENXIO; } chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); - if (chip == NULL) + if (chip == NULL) { + pci_disable_device(pci); return -ENOMEM; + } - // initialize the stuff + /* initialize the stuff */ chip->card = card; chip->pci = pci; chip->irq = -1; - // (1) PCI resource allocation + /* (1) PCI resource allocation */ if ((err = pci_request_regions(pci, "My Chip")) < 0) { kfree(chip); + pci_disable_device(pci); return err; } chip->port = pci_resource_start(pci, 0); @@ -1148,19 +1163,22 @@ } chip->irq = pci->irq; - // (2) initialization of the chip hardware - // (not implemented in this document) + /* (2) initialization of the chip hardware */ + .... // (not implemented in this document) if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { snd_mychip_free(chip); return err; } + + snd_card_set_dev(card, &pci->dev); + *rchip = chip; return 0; } - // PCI IDs + /* PCI IDs */ static struct pci_device_id snd_mychip_ids[] = { { PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, @@ -1169,7 +1187,7 @@ }; MODULE_DEVICE_TABLE(pci, snd_mychip_ids); - // pci_driver definition + /* pci_driver definition */ static struct pci_driver driver = { .name = "My Own Chip", .id_table = snd_mychip_ids, @@ -1177,13 +1195,13 @@ .remove = __devexit_p(snd_mychip_remove), }; - // initialization of the module + /* initialization of the module */ static int __init alsa_card_mychip_init(void) { return pci_module_init(&driver); } - // clean up the module + /* clean up the module */ static void __exit alsa_card_mychip_exit(void) { pci_unregister_driver(&driver); @@ -1228,6 +1246,7 @@ if (pci_set_dma_mask(pci, 0x0fffffff) < 0 || pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) { printk(KERN_ERR "error to set 28bit mask DMA\n"); + pci_disable_device(pci); return -ENXIO; } @@ -1285,6 +1304,7 @@ port = pci_resource_start(pci, 0); @@ -1294,6 +1314,7 @@ + It will reserve the i/o port region of 8 bytes of the given PCI device. The returned value, chip->res_port, is allocated via kmalloc() by @@ -1433,6 +1454,11 @@ the native kfree() without wrapper. + + Don't forget to call pci_disable_device() + before all finished. + + And finally, release the chip-specific record. @@ -1462,7 +1488,7 @@ When the chip-data is assigned to the card using snd_device_new() with SNDRV_DEV_LOWLELVEL , its destructor is - called at the last. that is, it is assured that all other + called at the last. That is, it is assured that all other components like PCMs and controls have been already released. You don't have to call stopping PCMs, etc. explicitly, but just stop the hardware in the low-level. @@ -1485,7 +1511,7 @@ - and the allocation would be (assuming its size is 512 bytes): + and the allocation would be like below: @@ -1522,6 +1548,30 @@ +
+ Registration of Device Struct + + At some point, typically after calling snd_device_new(), + you need to register the struct device of the chip + you're handling for udev and co. ALSA provides a macro for compatibility with + older kernels. Simply call like the following: + + +dev); +]]> + + + so that it stores the PCI's device pointer to the card. This will be + referred by ALSA core functions later when the devices are registered. + + + In the case of non-PCI, pass the proper device struct pointer of the BUS + instead. (In the case of legacy ISA without PnP, you don't have to do + anything.) + +
+
PCI Entries @@ -1801,8 +1851,9 @@ mychip_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; - // set up the hardware with the current configuration - // for example... + /* set up the hardware with the current configuration + * for example... + */ mychip_set_sample_format(chip, runtime->format); mychip_set_sample_rate(chip, runtime->rate); mychip_set_channels(chip, runtime->channels); @@ -1835,7 +1886,7 @@ mychip_t *chip = snd_pcm_substream_chip(substream); unsigned int current_ptr; - // get the current hardware pointer + /* get the current hardware pointer */ current_ptr = mychip_get_hw_pointer(chip); return current_ptr; } @@ -1886,6 +1937,7 @@ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mychip_capture_ops); /* pre-allocation of buffers */ + /* NOTE: this may fail */ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), 64*1024, 64*1024); @@ -1900,7 +1952,7 @@
Constructor - A pcm instance is allocated snd_pcm_new() + A pcm instance is allocated by snd_pcm_new() function. It would be better to create a constructor for pcm, namely, @@ -2068,18 +2120,19 @@ static void mychip_pcm_free(snd_pcm_t *pcm) { mychip_t *chip = snd_pcm_chip(pcm); - // free your own data + /* free your own data */ kfree(chip->my_private_pcm_data); - // do what you like else... + // do what you like else + .... } static int __devinit snd_mychip_new_pcm(mychip_t *chip) { snd_pcm_t *pcm; .... - // allocate your own data + /* allocate your own data */ chip->my_private_pcm_data = kmalloc(...); - // set the destructor + /* set the destructor */ pcm->private_data = chip; pcm->private_free = mychip_pcm_free; .... @@ -2184,7 +2237,8 @@ struct _snd_pcm_runtime { unsigned char *dma_area; /* DMA area */ dma_addr_t dma_addr; /* physical bus address (not accessible from main CPU) */ size_t dma_bytes; /* size of DMA area */ - void *dma_private; /* private DMA data for the memory allocator */ + + struct snd_dma_buffer *dma_buffer_p; /* allocated buffer */ #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) /* -- OSS things -- */ @@ -2199,7 +2253,7 @@ struct _snd_pcm_runtime { For the operators (callbacks) of each sound driver, most of these records are supposed to be read-only. Only the PCM - middle-layer changes / updates these info. The excpetions are + middle-layer changes / updates these info. The exceptions are the hardware description (hw), interrupt callbacks (transfer_ack_xxx), DMA buffer information, and the private data. Besides, if you use the standard buffer allocation @@ -2231,7 +2285,7 @@ struct _snd_pcm_runtime { runtime; ... - runtime->hw = snd_mychip_playback_hw; // common definition + runtime->hw = snd_mychip_playback_hw; /* common definition */ if (chip->model == VERY_OLD_ONE) runtime->hw.channels_max = 1; ]]> @@ -2957,6 +3011,9 @@ struct _snd_pcm_runtime { current appl_ptr for the internal buffer, and this callback is useful only for such a purpose. + + This callback is atomic. +
@@ -3030,7 +3087,7 @@ struct _snd_pcm_runtime { spin_lock(&chip->lock); .... if (pcm_irq_invoked(chip)) { - // call updater, unlock before it + /* call updater, unlock before it */ spin_unlock(&chip->lock); snd_pcm_period_elapsed(chip->substream); spin_lock(&chip->lock); @@ -3075,24 +3132,25 @@ struct _snd_pcm_runtime { .... if (pcm_irq_invoked(chip)) { unsigned int last_ptr, size; - // get the current hardware pointer (in frames) + /* get the current hardware pointer (in frames) */ last_ptr = get_hw_ptr(chip); - // calculate the processed frames since the - // last update + /* calculate the processed frames since the + * last update + */ if (last_ptr < chip->last_ptr) size = runtime->buffer_size + last_ptr - chip->last_ptr; else size = last_ptr - chip->last_ptr; - // remember the last updated point + /* remember the last updated point */ chip->last_ptr = last_ptr; - // accumulate the size + /* accumulate the size */ chip->size += size; - // over the period boundary? + /* over the period boundary? */ if (chip->size >= runtime->period_size) { - // reset the accumulator + /* reset the accumulator */ chip->size %= runtime->period_size; - // call updater + /* call updater */ spin_unlock(&chip->lock); snd_pcm_period_elapsed(substream); spin_lock(&chip->lock); @@ -3153,6 +3211,11 @@ struct _snd_pcm_runtime { udelay() or mdelay(). + + All three atomic callbacks (trigger, pointer, and ack) are + called with local interrupts disabled. + +
Constraints @@ -3198,7 +3261,7 @@ struct _snd_pcm_runtime { There are many different constraints. - Look in sound/asound.h for a complete list. + Look in sound/pcm.h for a complete list. You can even define your own constraint rules. For example, let's suppose my_chip can manage a substream of 1 channel if and only if the format is S16_LE, otherwise it supports any format @@ -3216,7 +3279,7 @@ struct _snd_pcm_runtime { snd_mask_t *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); snd_mask_t fmt; - snd_mask_any(&fmt); // Init the struct + snd_mask_any(&fmt); /* Init the struct */ if (c->min < 2) { fmt.bits[0] &= SNDRV_PCM_FMTBIT_S16_LE; return snd_mask_refine(f, &fmt); @@ -4014,7 +4077,7 @@ struct _snd_pcm_runtime { Both snd_ac97_write() and snd_ac97_update() functions are used to set a value to the given register - (AC97_XXX). The different between them is + (AC97_XXX). The difference between them is that snd_ac97_update() doesn't write a value if the given value has been already set, while snd_ac97_write() always rewrites the @@ -4100,8 +4163,8 @@ struct _snd_pcm_runtime { Proc Files The ALSA AC97 interface will create a proc file such as - /proc/asound/card0/ac97#0 and - ac97#0regs. You can refer to these files to + /proc/asound/card0/codec97#0/ac97#0-0 and + ac97#0-0+regs. You can refer to these files to see the current status and registers of the codec.
@@ -4148,18 +4211,6 @@ struct _snd_pcm_runtime { implementation of mpu401 stuff. For example, emu10k1 has its own mpu401 routines.
- - - In this document, I won't explain the rawmidi interface API, - which is the basis of MPU401-UART implementation. - - - - For details, please check the source, - core/rawmidi.c, and examples such as - drivers/mpu401/mpu401_uart.c or - usb/usbmidi.c. -
@@ -4282,6 +4333,354 @@ struct _snd_pcm_runtime { + + + + + RawMIDI Interface + +
+ Overview + + + The raw MIDI interface is used for hardware MIDI ports that can + be accessed as a byte stream. It is not used for synthesizer + chips that do not directly understand MIDI. + + + + ALSA handles file and buffer management. All you have to do is + to write some code to move data between the buffer and the + hardware. + + + + The rawmidi API is defined in + <sound/rawmidi.h>. + +
+ +
+ Constructor + + + To create a rawmidi device, call the + snd_rawmidi_new function: + + +card, "MyMIDI", 0, outs, ins, &rmidi); + if (err < 0) + return err; + rmidi->private_data = chip; + strcpy(rmidi->name, "My MIDI"); + rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | + SNDRV_RAWMIDI_INFO_INPUT | + SNDRV_RAWMIDI_INFO_DUPLEX; +]]> + + + + + + The first argument is the card pointer, the second argument is + the ID string. + + + + The third argument is the index of this component. You can + create up to 8 rawmidi devices. + + + + The fourth and fifth arguments are the number of output and + input substreams, respectively, of this device. (A substream is + the equivalent of a MIDI port.) + + + + Set the info_flags field to specify + the capabilities of the device. + Set SNDRV_RAWMIDI_INFO_OUTPUT if there is + at least one output port, + SNDRV_RAWMIDI_INFO_INPUT if there is at + least one input port, + and SNDRV_RAWMIDI_INFO_DUPLEX if the device + can handle output and input at the same time. + + + + After the rawmidi device is created, you need to set the + operators (callbacks) for each substream. There are helper + functions to set the operators for all substream of a device: + + + + + + + + + The operators are usually defined like this: + + + + + + These callbacks are explained in the Callbacks + section. + + + + If there is more than one substream, you should give each one a + unique name: + + +streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) { + substream = list_entry(list, snd_rawmidi_substream_t, list); + sprintf(substream->name, "My MIDI Port %d", substream->number + 1); + } + /* same for SNDRV_RAWMIDI_STREAM_INPUT */ +]]> + + + +
+ +
+ Callbacks + + + In all callbacks, the private data that you've set for the + rawmidi device can be accessed as + substream->rmidi->private_data. + + + + + If there is more than one port, your callbacks can determine the + port index from the snd_rawmidi_substream_t data passed to each + callback: + + +number; +]]> + + + + +
+ <function>open</function> callback + + + + + + + + + This is called when a substream is opened. + You can initialize the hardware here, but you should not yet + start transmitting/receiving data. + +
+ +
+ <function>close</function> callback + + + + + + + + + Guess what. + + + + The open and close + callbacks of a rawmidi device are serialized with a mutex, + and can sleep. + +
+ +
+ <function>trigger</function> callback for output + substreams + + + + + + + + + This is called with a nonzero up + parameter when there is some data in the substream buffer that + must be transmitted. + + + + To read data from the buffer, call + snd_rawmidi_transmit_peek. It will + return the number of bytes that have been read; this will be + less than the number of bytes requested when there is no more + data in the buffer. + After the data has been transmitted successfully, call + snd_rawmidi_transmit_ack to remove the + data from the substream buffer: + + + + + + + + + If you know beforehand that the hardware will accept data, you + can use the snd_rawmidi_transmit function + which reads some data and removes it from the buffer at once: + + + + + + + + + If you know beforehand how many bytes you can accept, you can + use a buffer size greater than one with the + snd_rawmidi_transmit* functions. + + + + The trigger callback must not sleep. If + the hardware FIFO is full before the substream buffer has been + emptied, you have to continue transmitting data later, either + in an interrupt handler, or with a timer if the hardware + doesn't have a MIDI transmit interrupt. + + + + The trigger callback is called with a + zero up parameter when the transmission + of data should be aborted. + +
+ +
+ <function>trigger</function> callback for input + substreams + + + + + + + + + This is called with a nonzero up + parameter to enable receiving data, or with a zero + up parameter do disable receiving data. + + + + The trigger callback must not sleep; the + actual reading of data from the device is usually done in an + interrupt handler. + + + + When data reception is enabled, your interrupt handler should + call snd_rawmidi_receive for all received + data: + + + + + + +
+ +
+ <function>drain</function> callback + + + + + + + + + This is only used with output substreams. This function should wait + until all data read from the substream buffer has been transmitted. + This ensures that the device can be closed and the driver unloaded + without losing data. + + + + This callback is optional. If you do not set + drain in the snd_rawmidi_ops_t + structure, ALSA will simply wait for 50 milliseconds + instead. + +
+
+ +
+ + @@ -4581,7 +4980,7 @@ struct _snd_pcm_runtime { where size is the byte size to be pre-allocated and the max is the maximal size to be changed via prealloc proc file. - The allocator will try to get as the large area as possible + The allocator will try to get as large area as possible within the given size. @@ -4803,7 +5202,7 @@ struct _snd_pcm_runtime { If your hardware supports the page table like emu10k1 or the buffer descriptors like via82xx, you can use the scatter-gather (SG) DMA. ALSA provides an interface for handling SG-buffers. - The API is provided in <sound/pcm_sgbuf.h>. + The API is provided in <sound/pcm.h>. @@ -5107,12 +5506,12 @@ struct _snd_pcm_runtime { Call snd_pcm_suspend_all() to suspend the running PCM streams. Save the register values if necessary. Stop the hardware if necessary. - Set the power-state as D3hot by calling snd_power_change_state(). + Disable the PCI device by calling pci_disable_device(). @@ -5141,18 +5540,18 @@ struct _snd_pcm_runtime { pm_private_data; - // (2) + /* (2) */ snd_pcm_suspend_all(chip->pcm); - // (3) + /* (3) */ snd_mychip_save_registers(chip); - // (4) + /* (4) */ snd_mychip_stop_hardware(chip); - // (5) - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); + /* (5) */ + pci_disable_device(chip->pci); return 0; } ]]> @@ -5172,8 +5571,6 @@ struct _snd_pcm_runtime { Resume the mixer, e.g. calling snd_ac97_resume(). Restart the hardware (if any). - Set the power-state as D0 by calling - snd_power_change_state(). @@ -5185,20 +5582,18 @@ struct _snd_pcm_runtime { pm_private_data; - // (2) + /* (2) */ pci_enable_device(chip->pci); - // (3) + /* (3) */ snd_mychip_reinit_chip(chip); - // (4) + /* (4) */ snd_mychip_restore_registers(chip); - // (5) + /* (5) */ snd_ac97_resume(chip->ac97); - // (6) + /* (6) */ snd_mychip_restart_chip(chip); - // (7) - snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; } ]]> @@ -5314,19 +5709,15 @@ struct _snd_pcm_runtime { - - Here boot_devs is passed but simply ignored since we don't care - the number of parsed parameters. @@ -5423,7 +5814,10 @@ struct _snd_pcm_runtime { depends on SND select SND_PCM help - Say 'Y' or 'M' to include support for Foobar XYZ soundcard. + Say Y here to include support for Foobar XYZ soundcard. + + To compile this driver as a module, choose M here: the module + will be called snd-xyz. ]]> diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt index 65285a4c1..351591769 100644 --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt @@ -49,7 +49,6 @@ show up in /proc/sys/kernel: - shmmax [ sysv ipc ] - shmmni - stop-a [ SPARC only ] -- suid_dumpable - sysrq ==> Documentation/sysrq.txt - tainted - threads-max @@ -301,25 +300,6 @@ 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. -2 - (suidsafe) - any binary which normally 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 e2ffee309..92a55ec0a 100644 --- a/Documentation/sysrq.txt +++ b/Documentation/sysrq.txt @@ -10,13 +10,32 @@ regardless of whatever else it is doing, unless it is completely locked up. * How do I enable the magic SysRq key? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ You need to say "yes" to 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' when -configuring the kernel. When running on a kernel with SysRq compiled in, it -may be DISABLED at run-time using following command: - - echo "0" > /proc/sys/kernel/sysrq - -Note that previous versions disabled sysrq by default, and you were required -to specifically enable it at run-time. That is not the case any longer. +configuring the kernel. When running a kernel with SysRq compiled in, +/proc/sys/kernel/sysrq controls the functions allowed to be invoked via +the SysRq key. By default the file contains 1 which means that every +possible SysRq request is allowed (in older versions SysRq was disabled +by default, and you were required to specifically enable it at run-time +but this is not the case any more). Here is the list of possible values +in /proc/sys/kernel/sysrq: + 0 - disable sysrq completely + 1 - enable all functions of sysrq + >1 - bitmask of allowed sysrq functions (see below for detailed function + description): + 2 - enable control of console logging level + 4 - enable control of keyboard (SAK, unraw) + 8 - enable debugging dumps of processes etc. + 16 - enable sync command + 32 - enable remount read-only + 64 - enable signalling of processes (term, kill, oom-kill) + 128 - allow reboot/poweroff + 256 - allow nicing of all RT tasks + +You can set the value in the file by the following command: + echo "number" >/proc/sys/kernel/sysrq + +Note that the value of /proc/sys/kernel/sysrq influences only the invocation +via a keyboard. Invocation of any operation via /proc/sysrq-trigger is always +allowed. * How do I use the magic SysRq key? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -77,6 +96,8 @@ On all - write a character to /proc/sysrq-trigger. eg: it so that only emergency messages like PANICs or OOPSes would make it to your console.) +'f' - Will call oom_kill to kill a memory hog process + 'e' - Send a SIGTERM to all processes, except for init. 'i' - Send a SIGKILL to all processes, except for init. diff --git a/Documentation/usb/error-codes.txt b/Documentation/usb/error-codes.txt index 09754b7d2..1e36f1661 100644 --- a/Documentation/usb/error-codes.txt +++ b/Documentation/usb/error-codes.txt @@ -23,6 +23,9 @@ USB-specific: -ENODEV specified USB-device or bus doesn't exist +-ENOENT specified interface or endpoint does not exist or + is not enabled + -ENXIO host controller driver does not support queuing of this type of urb. (treat as a host controller bug.) @@ -83,7 +86,24 @@ one or more packets could finish before an error stops further endpoint I/O. prescribed bus turn-around time c) unknown USB error --EILSEQ (*, **) CRC mismatch +-EILSEQ (*, **) a) CRC mismatch + b) no response packet received within the + prescribed bus turn-around time + c) unknown USB error + + Note that often the controller hardware does not + distinguish among cases a), b), and c), so a + driver cannot tell whether there was a protocol + error, a failure to respond (often caused by + device disconnect), or some other fault. + +-ETIMEDOUT (**) No response packet received within the prescribed + bus turn-around time. This error may instead be + reported as -EPROTO or -EILSEQ. + + Note that the synchronous USB message functions + also use this code to indicate timeout expired + before the transfer completed. -EPIPE (**) Endpoint stalled. For non-control endpoints, reset this status with usb_clear_halt(). @@ -104,8 +124,6 @@ one or more packets could finish before an error stops further endpoint I/O. specified buffer, and URB_SHORT_NOT_OK was set in urb->transfer_flags. --ETIMEDOUT (**) transfer timed out, NAK - -ENODEV Device was removed. Often preceded by a burst of other errors, since the hub driver does't detect device removal events immediately. @@ -143,4 +161,7 @@ usb_register(): usb_get_*/usb_set_*(): usb_control_msg(): usb_bulk_msg(): - All USB errors (submit/status) can occur +-ETIMEDOUT Timeout expired before the transfer completed. + In the future this code may change to -ETIME, + whose definition is a closer match to this sort + of error. diff --git a/Documentation/usb/silverlink.txt b/Documentation/usb/silverlink.txt deleted file mode 100644 index 81cbb52dc..000000000 --- a/Documentation/usb/silverlink.txt +++ /dev/null @@ -1,78 +0,0 @@ -------------------------------------------------------------------------- -Readme for Linux device driver for the Texas Instruments SilverLink cable -and direct USB cable provided by some TI's handhelds. -------------------------------------------------------------------------- - -Author: Romain Liévin & Julien Blache -Homepage: http://lpg.ticalc.org/prj_usb - -INTRODUCTION: - -This is a driver for the TI-GRAPH LINK USB (aka SilverLink) cable, a cable -designed by TI for connecting their TI8x/9x calculators to a computer -(PC or Mac usually). It has been extended to support the USB port offered by -some latest TI handhelds (TI84+ and TI89 Titanium). - -If you need more information, please visit the 'SilverLink drivers' homepage -at the above URL. - -WHAT YOU NEED: - -A TI calculator of course and a program capable to communicate with your -calculator. -TiLP will work for sure (since I am his developer !). yal92 may be able to use -it by changing tidev for tiglusb (may require some hacking...). - -HOW TO USE IT: - -You must have first compiled USB support, support for your specific USB host -controller (UHCI or OHCI). - -Next, (as root) from your appropriate modules directory (lib/modules/2.5.XX): - - insmod usb/usbcore.o - insmod usb/usb-uhci.o insmod usb/ohci-hcd.o - insmod tiglusb.o - -If it is not already there (it usually is), create the device: - - mknod /dev/tiglusb0 c 115 16 - -You will have to set permissions on this device to allow you to read/write -from it: - - chmod 666 /dev/tiglusb0 - -Now you are ready to run a linking program such as TiLP. Be sure to configure -it properly (RTFM). - -MODULE PARAMETERS: - - You can set these with: insmod tiglusb NAME=VALUE - There is currently no way to set these on a per-cable basis. - - NAME: timeout - TYPE: integer - DEFAULT: 15 - DESC: Timeout value in tenth of seconds. If no data is available once this - time has expired then the driver will return with a timeout error. - -QUIRKS: - -The following problem seems to be specific to the link cable since it appears -on all platforms (Linux, Windows, Mac OS-X). - -In some very particular cases, the driver returns with success but -without any data. The application should retry a read operation at least once. - -HOW TO CONTACT US: - -You can email me at roms@lpg.ticalc.org. Please prefix the subject line -with "TIGLUSB: " so that I am certain to notice your message. -You can also mail JB at jb@jblache.org: he has written the first release of -this driver but he better knows the Mac OS-X driver. - -CREDITS: - -The code is based on dabusb.c, printer.c and scanner.c ! -The driver has been developed independently of Texas Instruments Inc. diff --git a/Documentation/vm/hugetlbpage.txt b/Documentation/vm/hugetlbpage.txt index 47a7121b4..1b9bcd1fe 100644 --- a/Documentation/vm/hugetlbpage.txt +++ b/Documentation/vm/hugetlbpage.txt @@ -1,14 +1,14 @@ The intent of this file is to give a brief summary of hugetlbpage support in the Linux kernel. This support is built on top of multiple page size support -that is provided by most of modern architectures. For example, IA-32 -architecture supports 4K and 4M (2M in PAE mode) page sizes, IA-64 +that is provided by most modern architectures. For example, i386 +architecture supports 4K and 4M (2M in PAE mode) page sizes, ia64 architecture supports multiple page sizes 4K, 8K, 64K, 256K, 1M, 4M, 16M, -256M. A TLB is a cache of virtual-to-physical translations. Typically this -is a very scarce resource on processor. Operating systems try to make best -use of limited number of TLB resources. This optimization is more critical -now as bigger and bigger physical memories (several GBs) are more readily -available. +256M and ppc64 supports 4K and 16M. A TLB is a cache of virtual-to-physical +translations. Typically this is a very scarce resource on processor. +Operating systems try to make best use of limited number of TLB resources. +This optimization is more critical now as bigger and bigger physical memories +(several GBs) are more readily available. Users can use the huge page support in Linux kernel by either using the mmap system call or standard SYSv shared memory system calls (shmget, shmat). @@ -98,125 +98,187 @@ a supplementary group and system admin needs to configure that gid into applications to use any combination of mmaps and shm* calls. Though the mount of filesystem will be required for using mmaps. -/* Example of using hugepage in user application using Sys V shared memory - * system calls. In this example, app is requesting memory of size 256MB that - * is backed by huge pages. Application uses the flag SHM_HUGETLB in shmget - * system call to informt the kernel that it is requesting hugepages. For - * IA-64 architecture, Linux kernel reserves Region number 4 for hugepages. - * That means the addresses starting with 0x800000....will need to be - * specified. +******************************************************************* + +/* + * Example of using hugepage memory in a user application using Sys V shared + * memory system calls. In this example the app is requesting 256MB of + * memory that is backed by huge pages. The application uses the flag + * SHM_HUGETLB in the shmget system call to inform the kernel that it is + * requesting hugepages. + * + * For the ia64 architecture, the Linux kernel reserves Region number 4 for + * hugepages. That means the addresses starting with 0x800000... will need + * to be specified. Specifying a fixed address is not required on ppc64, + * i386 or x86_64. + * + * Note: The default shared memory limit is quite low on many kernels, + * you may need to increase it via: + * + * echo 268435456 > /proc/sys/kernel/shmmax + * + * This will increase the maximum size per shared memory segment to 256MB. + * The other limit that you will hit eventually is shmall which is the + * total amount of shared memory in pages. To set it to 16GB on a system + * with a 4kB pagesize do: + * + * echo 4194304 > /proc/sys/kernel/shmall */ +#include +#include #include +#include #include -#include #include -#include -extern int errno; +#ifndef SHM_HUGETLB #define SHM_HUGETLB 04000 -#define LPAGE_SIZE (256UL*1024UL*1024UL) -#define dprintf(x) printf(x) -#define ADDR (0x8000000000000000UL) -main() +#endif + +#define LENGTH (256UL*1024*1024) + +#define dprintf(x) printf(x) + +/* Only ia64 requires this */ +#ifdef __ia64__ +#define ADDR (void *)(0x8000000000000000UL) +#define SHMAT_FLAGS (SHM_RND) +#else +#define ADDR (void *)(0x0UL) +#define SHMAT_FLAGS (0) +#endif + +int main(void) { - int shmid; - int i, j, k; - volatile char *shmaddr; - - if ((shmid =shmget(2, LPAGE_SIZE, SHM_HUGETLB|IPC_CREAT|SHM_R|SHM_W )) -< 0) { - perror("Failure:"); - exit(1); - } - printf("shmid: 0x%x\n", shmid); - shmaddr = shmat(shmid, (void *)ADDR, SHM_RND) ; - if (errno != 0) { - perror("Shared Memory Attach Failure:"); - exit(2); - } - printf("shmaddr: %p\n", shmaddr); - - dprintf("Starting the writes:\n"); - for (i=0;i +#include #include +#include #include #include -#include #define FILE_NAME "/mnt/hugepagefile" -#define LENGTH (256*1024*1024) +#define LENGTH (256UL*1024*1024) #define PROTECTION (PROT_READ | PROT_WRITE) -#define FLAGS MAP_SHARED |MAP_FIXED -#define ADDRESS (char *)(0x60000000UL + 0x8000000000000000UL) -extern errno; +/* Only ia64 requires this */ +#ifdef __ia64__ +#define ADDR (void *)(0x8000000000000000UL) +#define FLAGS (MAP_SHARED | MAP_FIXED) +#else +#define ADDR (void *)(0x0UL) +#define FLAGS (MAP_SHARED) +#endif -check_bytes(char *addr) +void check_bytes(char *addr) { - printf("First hex is %x\n", *((unsigned int *)addr)); + printf("First hex is %x\n", *((unsigned int *)addr)); } -write_bytes(char *addr) +void write_bytes(char *addr) { - int i; - for (i=0;i L: linux-kernel@vger.kernel.org S: Maintained +IEEE 1394 ETHERNET (eth1394) +L: linux1394-devel@lists.sourceforge.net +W: http://www.linux1394.org/ +S: Orphan + +IEEE 1394 SBP2 +L: linux1394-devel@lists.sourceforge.net +W: http://www.linux1394.org/ +S: Orphan + IEEE 1394 SUBSYSTEM P: Ben Collins M: bcollins@debian.org +P: Jody McIntyre +M: scjody@steamballoon.com L: linux1394-devel@lists.sourceforge.net W: http://www.linux1394.org/ S: Maintained @@ -1057,13 +1111,15 @@ S: Maintained IEEE 1394 OHCI DRIVER P: Ben Collins M: bcollins@debian.org +P: Jody McIntyre +M: scjody@steamballoon.com L: linux1394-devel@lists.sourceforge.net W: http://www.linux1394.org/ S: Maintained IEEE 1394 PCILYNX DRIVER -P: Andreas Bombe -M: andreas.bombe@munich.netsurf.de +P: Jody McIntyre +M: scjody@steamballoon.com L: linux1394-devel@lists.sourceforge.net W: http://www.linux1394.org/ S: Maintained @@ -1071,6 +1127,8 @@ S: Maintained IEEE 1394 RAW I/O DRIVER P: Ben Collins M: bcollins@debian.org +P: Dan Dennedy +M: dan@dennedy.org L: linux1394-devel@lists.sourceforge.net W: http://www.linux1394.org/ S: Maintained @@ -1081,6 +1139,17 @@ M: lethal@chaoticdreams.org L: linux-fbdev-devel@lists.sourceforge.net S: Maintained +INFINIBAND SUBSYSTEM +P: Roland Dreier +M: roland@topspin.com +P: Sean Hefty +M: mshefty@ichips.intel.com +P: Hal Rosenstock +M: halr@voltaire.com +L: openib-general@openib.org +W: http://www.openib.org/ +S: Supported + INPUT (KEYBOARD, MOUSE, JOYSTICK) DRIVERS P: Vojtech Pavlik M: vojtech@suse.cz @@ -1140,13 +1209,6 @@ M: john.ronciak@intel.com W: http://sourceforge.net/projects/e1000/ S: Supported -INTERMEZZO FILE SYSTEM -P: Cluster File Systems -M: intermezzo-devel@lists.sf.net -W: http://www.inter-mezzo.org/ -L: intermezzo-discuss@lists.sourceforge.net -S: Maintained - IOC3 DRIVER P: Ralf Baechle M: ralf@linux-mips.org @@ -1161,7 +1223,7 @@ S: Maintained IPX NETWORK LAYER P: Arnaldo Carvalho de Melo M: acme@conectiva.com.br -L: linux-net@vger.kernel.org +L: netdev@vger.kernel.org S: Maintained IRDA SUBSYSTEM @@ -1208,8 +1270,8 @@ S: Maintained JFS FILESYSTEM P: Dave Kleikamp M: shaggy@austin.ibm.com -L: jfs-discussion@oss.software.ibm.com -W: http://oss.software.ibm.com/jfs/ +L: jfs-discussion@lists.sourceforge.net +W: http://jfs.sourceforge.net/ S: Supported KCONFIG @@ -1344,7 +1406,7 @@ W: http://www.penguinppc.org/ L: linuxppc-embedded@ozlabs.org S: Maintained -LINUX FOR POWERPC EMBEDDED PPC85XX +LINUX FOR POWERPC EMBEDDED PPC83XX AND PPC85XX P: Kumar Gala M: kumar.gala@freescale.com W: http://www.penguinppc.org/ @@ -1439,7 +1501,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 @@ -1450,7 +1512,7 @@ S: Maintained MEMORY TECHNOLOGY DEVICES P: David Woodhouse -M: dwmw2@redhat.com +M: dwmw2@infradead.org W: http://www.linux-mtd.infradead.org/ L: linux-mtd@lists.infradead.org S: Maintained @@ -1549,13 +1611,13 @@ P: Andrew Morton M: akpm@osdl.org P: Jeff Garzik M: jgarzik@pobox.com -L: linux-net@vger.kernel.org +L: netdev@vger.kernel.org S: Maintained NETWORKING [GENERAL] P: Networking Team -M: netdev@oss.sgi.com -L: linux-net@vger.kernel.org +M: netdev@vger.kernel.org +L: netdev@vger.kernel.org S: Maintained NETWORKING [IPv4/IPv6] @@ -1571,7 +1633,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 @@ -1579,7 +1641,6 @@ P: Wensong Zhang M: wensong@linux-vs.org P: Julian Anastasov M: ja@ssi.bg -L: lvs-users@linuxvirtualserver.org S: Maintained NFS CLIENT @@ -1592,7 +1653,7 @@ NI5010 NETWORK DRIVER P: Jan-Pascal van Best and Andreas Mohr M: Jan-Pascal van Best M: Andreas Mohr <100.30936@germany.net> -L: linux-net@vger.kernel.org +L: netdev@vger.kernel.org S: Maintained NINJA SCSI-3 / NINJA SCSI-32Bi (16bit/CardBus) PCMCIA SCSI HOST ADAPTER DRIVER @@ -1634,7 +1695,7 @@ P: Peter De Shrijver M: p2@ace.ulyssis.student.kuleuven.ac.be P: Mike Phillips M: mikep@linuxtr.net -L: linux-net@vger.kernel.org +L: netdev@vger.kernel.org L: linux-tr@linuxtr.net W: http://www.linuxtr.net S: Maintained @@ -1663,18 +1724,20 @@ P: Pavel Roskin M: proski@gnu.org P: David Gibson M: hermes@gibson.dropbear.id.au -W: http://www.ozlabs.org/people/dgibson/dldwd +L: orinoco-users@lists.sourceforge.net +L: orinoco-devel@lists.sourceforge.net +W: http://www.nongnu.org/orinoco/ S: Maintained PARALLEL PORT SUPPORT P: Phil Blundell -M: Philip.Blundell@pobox.com +M: philb@gnu.org P: Tim Waugh M: tim@cyberelk.net P: David Campbell M: campbell@torque.net P: Andrea Arcangeli -M: andrea@e-mind.com +M: andrea@suse.de L: linux-parport@lists.infradead.org W: http://people.redhat.com/twaugh/parport/ S: Maintained @@ -1717,14 +1780,14 @@ S: Maintained PCI SUBSYSTEM P: Greg Kroah-Hartman -M: greg@kroah.com +M: gregkh@suse.de L: linux-kernel@vger.kernel.org +L: linux-pci@atrey.karlin.mff.cuni.cz S: Supported PCI HOTPLUG CORE P: Greg Kroah-Hartman -M: greg@kroah.com -M: gregkh@us.ibm.com +M: gregkh@suse.de S: Supported PCI HOTPLUG COMPAQ DRIVER @@ -1739,7 +1802,7 @@ S: Unmaintained PCNET32 NETWORK DRIVER P: Thomas Bogendörfer M: tsbogend@alpha.franken.de -L: linux-net@vger.kernel.org +L: netdev@vger.kernel.org S: Maintained PHRAM MTD DRIVER @@ -1751,7 +1814,7 @@ S: Maintained POSIX CLOCKS and TIMERS P: George Anzinger M: george@mvista.com -L: linux-net@vger.kernel.org +L: netdev@vger.kernel.org S: Supported PNP SUPPORT @@ -1772,7 +1835,7 @@ S: Maintained PPP OVER ETHERNET P: Michal Ostrowski -M: mostrows@styx.uwaterloo.ca +M: mostrows@speakeasy.net S: Maintained PREEMPTIBLE KERNEL @@ -1786,7 +1849,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 @@ -1802,6 +1865,12 @@ M: nico@cam.org L: linux-arm-kernel@lists.arm.linux.org.uk S: Maintained +QLOGIC QLA2XXX FC-SCSI DRIVER +P: Andrew Vasquez +M: andrew.vasquez@qlogic.com +L: linux-scsi@vger.kernel.org +S: Supported + QNX4 FILESYSTEM P: Anders Larsen M: al@alarsen.net @@ -1810,14 +1879,14 @@ W: http://www.alarsen.net/linux/qnx4fs/ S: Maintained RADEON FRAMEBUFFER DISPLAY DRIVER -P: Ani Joshi -M: ajoshi@shell.unixbox.com +P: Benjamin Herrenschmidt +M: benh@kernel.crashing.org L: linux-fbdev-devel@lists.sourceforge.net S: Maintained RAGE128 FRAMEBUFFER DISPLAY DRIVER -P: Ani Joshi -M: ajoshi@shell.unixbox.com +P: Paul Mackerras +M: paulus@samba.org L: linux-fbdev-devel@lists.sourceforge.net S: Maintained @@ -1827,6 +1896,11 @@ M: corey@world.std.com L: linux-kernel@vger.kernel.org S: Maintained +RANDOM NUMBER DRIVER +P: Matt Mackall +M: mpm@selenic.com +S: Maintained + REAL TIME CLOCK DRIVER P: Paul Gortmaker M: p_gortmaker@yahoo.com @@ -1853,9 +1927,7 @@ L: linux-hams@vger.kernel.org S: Maintained RISCOM8 DRIVER -P: Dmitry Gorodchanin -L: linux-kernel@vger.kernel.org -S: Maintained +S: Orphan RTLINUX REALTIME LINUX P: Victor Yodaiken @@ -1935,6 +2007,11 @@ M: christer@weinigel.se W: http://www.weinigel.se S: Supported +SECURITY CONTACT +P: Security Officers +M: security@kernel.org +S: Supported + SELINUX SECURITY MODULE P: Stephen Smalley M: sds@epoch.ncsc.mil @@ -1964,6 +2041,20 @@ L: linux-visws-devel@lists.sf.net W: http://linux-visws.sf.net S: Maintained for 2.6. +SIMTEC EB110ATX (Chalice CATS) +P: Ben Dooks +P: Vincent Sanders +M: support@simtec.co.uk +W: http://www.simtec.co.uk/products/EB110ATX/ +S: Supported + +SIMTEC EB2410ITX (BAST) +P: Ben Dooks +P: Vincent Sanders +M: support@simtec.co.uk +W: http://www.simtec.co.uk/products/EB2410ITX/ +S: Supported + SIS 5513 IDE CONTROLLER DRIVER P: Lionel Bouton M: Lionel.Bouton@inet6.fr @@ -1972,10 +2063,11 @@ W: http://gyver.homeip.net/sis5513/index.html S: Maintained SIS 900/7016 FAST ETHERNET DRIVER -P: Ollie Lho -M: ollie@sis.com.tw -L: linux-net@vger.kernel.org -S: Supported +P: Daniele Venzano +M: venza@brownhat.org +W: http://www.brownhat.org/sis900.html +L: netdev@vger.kernel.org +S: Maintained SIS FRAMEBUFFER DRIVER P: Thomas Winischhofer @@ -1983,6 +2075,12 @@ M: thomas@winischhofer.net W: http://www.winischhofer.net/linuxsisvga.shtml S: Maintained +SIS USB2VGA DRIVER +P: Thomas Winischhofer +M: thomas@winischhofer.net +W: http://www.winischhofer.at/linuxsisusbvga.shtml +S: Maintained + SMSC47M1 HARDWARE MONITOR DRIVER P: Jean Delvare M: khali@linux-fr.org @@ -2027,7 +2125,7 @@ S: Maintained SONIC NETWORK DRIVER P: Thomas Bogendoerfer M: tsbogend@alpha.franken.de -L: linux-net@vger.kernel.org +L: netdev@vger.kernel.org S: Maintained SONY VAIO CONTROL DEVICE DRIVER @@ -2042,6 +2140,13 @@ M: perex@suse.cz L: alsa-devel@alsa-project.org S: Maintained +TPM DEVICE DRIVER +P: Kylene Hall +M: kjhall@us.ibm.com +W: http://tpmdd.sourceforge.net +L: tpmdd-devel@lists.sourceforge.net +S: Maintained + UltraSPARC (sparc64): P: David S. Miller M: davem@davemloft.net @@ -2055,6 +2160,13 @@ L: sparclinux@vger.kernel.org L: ultralinux@vger.kernel.org S: Maintained +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 +S: Maintained + SPARC (sparc32): P: William L. Irwin M: wli@holomorphy.com @@ -2064,14 +2176,13 @@ S: Maintained SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER P: Roger Wolff M: R.E.Wolff@BitWizard.nl -M: io8-linux@specialix.co.uk L: linux-kernel@vger.kernel.org ? S: Supported SPX NETWORK LAYER P: Jay Schulist M: jschlst@samba.org -L: linux-net@vger.kernel.org +L: netdev@vger.kernel.org S: Supported SRM (Alpha) environment access @@ -2111,9 +2222,10 @@ SUPERH64 (sh64) P: Paul Mundt M: lethal@linux-sh.org P: Richard Curnow -M: richard.curnow@superh.com +M: rc@rc0.org.uk L: linuxsh-shmedia-dev@lists.sourceforge.net W: http://www.linux-sh.org +W: http://www.rc0.org.uk/sh64 S: Maintained SUN3/3X @@ -2134,13 +2246,6 @@ P: Christoph Hellwig M: hch@infradead.org S: Maintained -TI GRAPH LINK USB (SilverLink) CABLE DRIVER -P: Romain Lievin -M: roms@lpg.ticalc.org -P: Julien Blache -M: jb@technologeek.org -S: Maintained - TI PARALLEL LINK CABLE DRIVER P: Romain Lievin M: roms@lpg.ticalc.org @@ -2156,7 +2261,7 @@ S: Maintained TOKEN-RING NETWORK DRIVER P: Mike Phillips M: mikep@linuxtr.net -L: linux-net@vger.kernel.org +L: netdev@vger.kernel.org L: linux-tr@linuxtr.net W: http://www.linuxtr.net S: Maintained @@ -2221,13 +2326,6 @@ L: linux_udf@hpesjro.fc.hp.com W: http://linux-udf.sourceforge.net S: Maintained -UMSDOS FILESYSTEM -P: Matija Nalis -M: Matija Nalis -L: linux-kernel@vger.kernel.org -W: http://linux.voyager.hr/umsdos/ -S: Maintained - UNIFORM CDROM DRIVER P: Jens Axboe M: axboe@suse.de @@ -2242,6 +2340,13 @@ L: linux-usb-users@lists.sourceforge.net L: linux-usb-devel@lists.sourceforge.net S: Maintained +USB BLOCK DRIVER (UB ub) +P: Pete Zaitcev +M: zaitcev@redhat.com +L: linux-kernel@vger.kernel.org +L: linux-usb-devel@lists.sourceforge.net +S: Supported + USB BLUETOOTH TTY CONVERTER DRIVER P: Greg Kroah-Hartman M: greg@kroah.com @@ -2339,6 +2444,12 @@ L: linux-usb-devel@lists.sourceforge.net W: http://www.chello.nl/~j.vreeken/se401/ S: Maintained +USB SERIAL CYBERJACK DRIVER +P: Matthias Bruestle and Harald Welte +M: support@reiner-sct.com +W: http://www.reiner-sct.de/support/treiber_cyberjack.php +S: Maintained + USB SERIAL DIGI ACCELEPORT DRIVER P: Peter Berger and Al Borchers M: pberger@brimson.com @@ -2349,11 +2460,10 @@ S: Maintained USB SERIAL DRIVER P: Greg Kroah-Hartman -M: greg@kroah.com +M: gregkh@suse.de L: linux-usb-users@lists.sourceforge.net L: linux-usb-devel@lists.sourceforge.net -S: Maintained -W: http://www.kroah.com/linux-usb/ +S: Supported USB SERIAL BELKIN F5U103 DRIVER P: William Greathouse @@ -2415,7 +2525,7 @@ S: Maintained USB SUBSYSTEM P: Greg Kroah-Hartman -M: greg@kroah.com +M: gregkh@suse.de L: linux-usb-users@lists.sourceforge.net L: linux-usb-devel@lists.sourceforge.net W: http://www.linux-usb.org @@ -2441,6 +2551,14 @@ L: linux-usb-devel@lists.sourceforge.net W: http://www.linux-projects.org S: Maintained +USB ZD1201 DRIVER +P: Jeroen Vreeken +M: pe1rxq@amsat.org +L: linux-usb-users@lists.sourceforge.net +L: linux-usb-devel@lists.sourceforge.net +W: http://linux-lc100020.sourceforge.net +S: Maintained + USER-MODE LINUX P: Jeff Dike M: jdike@karaya.com @@ -2464,8 +2582,9 @@ P: Roger Luethi M: rl@hellgate.ch S: Maintained -UCLINUX +UCLINUX (AND M68KNOMMU) P: Greg Ungerer +M: gerg@uclinux.org M: gerg@snapgear.com P: David McCullough M: davidm@snapgear.com @@ -2498,7 +2617,8 @@ S: Maintained VIDEO FOR LINUX P: Gerd Knorr M: kraxel@bytesex.org -S: Maintained +L: video4linux-list@redhat.com +S: Orphan W1 DALLAS'S 1-WIRE BUS P: Evgeniy Polyakov @@ -2576,11 +2696,11 @@ M: jpr@f6fbb.org L: linux-hams@vger.kernel.org S: Maintained -YMFPCI YAMAHA PCI SOUND +YMFPCI YAMAHA PCI SOUND (Use ALSA instead) P: Pete Zaitcev M: zaitcev@yahoo.com L: linux-kernel@vger.kernel.org -S: Maintained +S: Obsolete Z8530 DRIVER FOR AX.25 P: Joerg Reuter diff --git a/Makefile b/Makefile index 1adf8b7f4..8c9699f66 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ VERSION = 2 PATCHLEVEL = 6 -SUBLEVEL = 10 -EXTRAVERSION = -1.771_FC2.2.planetlab -NAME=AC +SUBLEVEL = 12 +EXTRAVERSION = -1.1_1390_FC4.1.planetlab.2005.08.04 +NAME=Woozy Beaver # *DOCUMENTATION* # To see a list of typical targets execute "make help" @@ -18,7 +18,7 @@ MAKEFLAGS += --no-print-directory # # Most importantly: sub-Makefiles should only ever modify files in # their own directory. If in some directory we have a dependency on -# a file in another dir (which doesn't happen often, but it's of +# a file in another dir (which doesn't happen often, but it's often # unavoidable when linking the built-in.o targets which finally # turn into vmlinux), we will call a sub make in that other dir, and # after that we are sure that everything which is in that other dir @@ -67,7 +67,7 @@ endif # kbuild supports saving output files in a separate directory. -# To locate output files in a separate directory two syntax'es are supported. +# To locate output files in a separate directory two syntaxes are supported. # In both cases the working directory must be the root of the kernel src. # 1) O= # Use "make O=dir/to/store/output/files/" @@ -78,7 +78,8 @@ endif # export KBUILD_OUTPUT=dir/to/store/output/files/ # make # -# The O= assigment takes precedence over the KBUILD_OUTPUT environment variable. +# The O= assignment takes precedence over the KBUILD_OUTPUT environment +# variable. # KBUILD_SRC is set on invocation of make in OBJ directory @@ -149,14 +150,13 @@ space := $(nullstring) # end of line # careful not to include files twice if building in the source # directory. LOCALVERSION from the command line override all of this -ifeq ($(objtree),$(srctree)) -localversion-files := $(wildcard $(srctree)/localversion*) -else -localversion-files := $(wildcard $(objtree)/localversion* $(srctree)/localversion*) -endif +localver := $(objtree)/localversion* $(srctree)/localversion* +localver := $(sort $(wildcard $(localver))) +# skip backup files (containing '~') +localver := $(foreach f, $(localver), $(if $(findstring ~, $(f)),,$(f))) LOCALVERSION = $(subst $(space),, \ - $(shell cat /dev/null $(localversion-files:%~=)) \ + $(shell cat /dev/null $(localver)) \ $(patsubst "%",%,$(CONFIG_LOCALVERSION))) KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)$(LOCALVERSION) @@ -291,7 +291,7 @@ check_gcc = $(warning check_gcc is deprecated - use cc-option) \ $(call cc-option, $(1),$(2)) # cc-option-yn -# Usage: flag := $(call gcc-option-yn, -march=winchip-c6) +# Usage: flag := $(call cc-option-yn, -march=winchip-c6) cc-option-yn = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \ > /dev/null 2>&1; then echo "y"; else echo "n"; fi;) @@ -331,6 +331,7 @@ DEPMOD = /sbin/depmod KALLSYMS = scripts/kallsyms PERL = perl CHECK = sparse + CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ MODFLAGS = -DMODULE CFLAGS_MODULE = $(MODFLAGS) @@ -339,7 +340,6 @@ LDFLAGS_MODULE = -r CFLAGS_KERNEL = AFLAGS_KERNEL = -NOSTDINC_FLAGS = -nostdinc -iwithprefix include # Use LINUXINCLUDE when you must reference the include/ directory. # Needed to be compatible with the O= option @@ -349,7 +349,8 @@ LINUXINCLUDE := -Iinclude \ CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE) CFLAGS := -Wall -Wstrict-prototypes -Wno-trigraphs \ - -fno-strict-aliasing -fno-common + -fno-strict-aliasing -fno-common \ + -ffreestanding AFLAGS := -D__ASSEMBLY__ export VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION LOCALVERSION KERNELRELEASE \ @@ -389,7 +390,7 @@ scripts_basic: # using a seperate output directory. This allows convinient use # of make in output directory outputmakefile: - $(Q)if /usr/bin/env test ! $(srctree) -ef $(objtree); then \ + $(Q)if test ! $(srctree) -ef $(objtree); then \ $(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \ $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL) \ > $(objtree)/Makefile; \ @@ -532,22 +533,27 @@ 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) +CHECKFLAGS += $(NOSTDINC_FLAGS) + # warn about C99 declaration after statement CFLAGS += $(call cc-option,-Wdeclaration-after-statement,) +# disable pointer signedness warnings in gcc 4.0 +CFLAGS += $(call cc-option,-Wno-pointer-sign,) + # Default kernel image to build when no specific target is given. # KBUILD_IMAGE may be overruled on the commandline or # set in the environment -# Also any assingments in arch/$(ARCH)/Makefiel take precedence over +# Also any assignments in arch/$(ARCH)/Makefile take precedence over # this default value export KBUILD_IMAGE ?= vmlinux # # INSTALL_PATH specifies where to place the updated kernel and system map -# images. Uncomment if you want to place them anywhere other than root. -# - -#export INSTALL_PATH=/boot +# images. Default is /boot, but you can set it to other values +export INSTALL_PATH ?= /boot # # INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory @@ -897,7 +903,7 @@ depmod_opts := -b $(INSTALL_MOD_PATH) -r endif .PHONY: _modinst_post _modinst_post: _modinst_ - if [ -r System.map ]; then $(DEPMOD) -ae -F System.map $(depmod_opts) $(KERNELRELEASE); fi + if [ -r System.map -a -x $(DEPMOD) ]; then $(DEPMOD) -ae -F System.map $(depmod_opts) $(KERNELRELEASE); fi else # CONFIG_MODULES @@ -950,7 +956,7 @@ CLEAN_FILES += vmlinux System.map \ MRPROPER_DIRS += include/config include2 MRPROPER_FILES += .config .config.old include/asm .version \ include/linux/autoconf.h include/linux/version.h \ - Module.symvers tags TAGS cscope* + Module.symvers tags TAGS cscope* include/.asm-ignore # clean - Delete most, but leave enough to build external modules # @@ -1095,9 +1101,17 @@ KBUILD_MODULES := 1 crmodverdir: $(Q)mkdir -p $(MODVERDIR) +.PHONY: $(objtree)/Module.symvers +$(objtree)/Module.symvers: + @test -e $(objtree)/Module.symvers || ( \ + echo; \ + echo " WARNING: Symbol version dump $(objtree)/Module.symvers"; \ + echo " is missing; modules will have no dependencies and modversions."; \ + echo ) + module-dirs := $(addprefix _module_,$(KBUILD_EXTMOD)) .PHONY: $(module-dirs) modules -$(module-dirs): crmodverdir +$(module-dirs): crmodverdir $(objtree)/Module.symvers $(Q)$(MAKE) $(build)=$(patsubst _module_%,%,$@) modules: $(module-dirs) @@ -1135,20 +1149,30 @@ endif # KBUILD_EXTMOD # Generate tags for editors # --------------------------------------------------------------------------- +#We want __srctree to totally vanish out when KBUILD_OUTPUT is not set +#(which is the most common case IMHO) to avoid unneeded clutter in the big tags file. +#Adding $(srctree) adds about 20M on i386 to the size of the output file! + +ifeq ($(KBUILD_OUTPUT),) +__srctree = +else +__srctree = $(srctree)/ +endif + define all-sources - ( find $(srctree) $(RCS_FIND_IGNORE) \ + ( find $(__srctree) $(RCS_FIND_IGNORE) \ \( -name include -o -name arch \) -prune -o \ -name '*.[chS]' -print; \ - find $(srctree)/arch/$(ARCH) $(RCS_FIND_IGNORE) \ + find $(__srctree)arch/$(ARCH) $(RCS_FIND_IGNORE) \ -name '*.[chS]' -print; \ - find $(srctree)/security/selinux/include $(RCS_FIND_IGNORE) \ + find $(__srctree)security/selinux/include $(RCS_FIND_IGNORE) \ -name '*.[chS]' -print; \ - find $(srctree)/include $(RCS_FIND_IGNORE) \ + find $(__srctree)include $(RCS_FIND_IGNORE) \ \( -name config -o -name 'asm-*' \) -prune \ -o -name '*.[chS]' -print; \ - find $(srctree)/include/asm-$(ARCH) $(RCS_FIND_IGNORE) \ + find $(__srctree)include/asm-$(ARCH) $(RCS_FIND_IGNORE) \ -name '*.[chS]' -print; \ - find $(srctree)/include/asm-generic $(RCS_FIND_IGNORE) \ + find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \ -name '*.[chS]' -print ) endef @@ -1170,7 +1194,7 @@ cmd_TAGS = $(all-sources) | etags - quiet_cmd_tags = MAKE $@ define cmd_tags rm -f $@; \ - CTAGSF=`ctags --version | grep -i exuberant >/dev/null && echo "-I __initdata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_NOVERS"`; \ + CTAGSF=`ctags --version | grep -i exuberant >/dev/null && echo "-I __initdata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_GPL --extra=+f"`; \ $(all-sources) | xargs ctags $$CTAGSF -a endef @@ -1214,6 +1238,9 @@ checkstack: $(OBJDUMP) -d vmlinux $$(find . -name '*.ko') | \ $(PERL) $(src)/scripts/checkstack.pl $(ARCH) +kernelrelease: + @echo $(KERNELRELEASE) + # FIXME Should go into a make.lib or something # =========================================================================== diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index 67ac95088..55d9d8572 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -28,6 +28,10 @@ config RWSEM_XCHGADD_ALGORITHM bool default y +config GENERIC_CALIBRATE_DELAY + bool + default y + config GENERIC_ISA_DMA bool default y @@ -276,6 +280,10 @@ config ISA (MCA) or VESA. ISA is an older system, now being displaced by PCI; newer boards don't support it. If you have ISA, say Y, otherwise N. +config ISA_DMA_API + bool + default y + config PCI bool depends on !ALPHA_JENSEN @@ -485,7 +493,7 @@ config SMP singleprocessor machines. On a singleprocessor machine, the kernel will run faster if you say N here. - See also the , and the SMP-HOWTO + See also the , and the SMP-HOWTO available at . If you don't know what to do here, say N. diff --git a/arch/alpha/defconfig b/arch/alpha/defconfig index 6ac8d4a7d..5e39b7a7c 100644 --- a/arch/alpha/defconfig +++ b/arch/alpha/defconfig @@ -411,7 +411,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m # CONFIG_IP_NF_TARGET_REDIRECT is not set # CONFIG_IP_NF_TARGET_NETMAP is not set # CONFIG_IP_NF_TARGET_SAME is not set -# CONFIG_IP_NF_NAT_LOCAL is not set # CONFIG_IP_NF_NAT_SNMP_BASIC is not set CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/alpha/kernel/core_marvel.c b/arch/alpha/kernel/core_marvel.c index bb4fe0498..44866cb26 100644 --- a/arch/alpha/kernel/core_marvel.c +++ b/arch/alpha/kernel/core_marvel.c @@ -118,7 +118,7 @@ alloc_io7(unsigned int pe) io7 = alloc_bootmem(sizeof(*io7)); io7->pe = pe; - io7->irq_lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&io7->irq_lock); for (h = 0; h < 4; h++) { io7->ports[h].io7 = io7; diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index f0927ee53..5e4de451d 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -873,22 +873,15 @@ sys_getxgid: .globl sys_getxpid .ent sys_getxpid sys_getxpid: + lda $sp, -16($sp) + stq $26, 0($sp) .prologue 0 - ldq $2, TI_TASK($8) - /* See linux/kernel/timer.c sys_getppid for discussion - about this loop. */ - ldq $3, TASK_REAL_PARENT($2) -1: ldl $1, TASK_TGID($3) -#ifdef CONFIG_SMP - mov $3, $4 - mb - ldq $3, TASK_REAL_PARENT($2) - cmpeq $3, $4, $4 - beq $4, 1b -#endif - stq $1, 80($sp) - ldl $0, TASK_TGID($2) + lda $16, 96($sp) + jsr $26, do_getxpid + ldq $26, 0($sp) + + lda $sp, 16($sp) ret .end sys_getxpid diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index dcad8d31d..167fd89f8 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -437,11 +437,10 @@ asmlinkage int osf_getdomainname(char __user *name, int namelen) { unsigned len; - int i, error; + int i; - error = verify_area(VERIFY_WRITE, name, namelen); - if (error) - goto out; + if (!access_ok(VERIFY_WRITE, name, namelen)) + return -EFAULT; len = namelen; if (namelen > 32) @@ -454,26 +453,10 @@ osf_getdomainname(char __user *name, int namelen) break; } up_read(&uts_sem); - out: - return error; -} - -asmlinkage long -osf_shmat(int shmid, void __user *shmaddr, int shmflg) -{ - unsigned long raddr; - long err; - err = do_shmat(shmid, shmaddr, shmflg, &raddr); - - /* - * This works because all user-level addresses are - * non-negative longs! - */ - return err ? err : (long)raddr; + return 0; } - /* * The following stuff should move into a header file should it ever * be labeled "officially supported." Right now, there is just enough @@ -990,18 +973,19 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, char *bits; size_t size; long timeout; - int ret; + int ret = -EINVAL; timeout = MAX_SCHEDULE_TIMEOUT; if (tvp) { time_t sec, usec; - if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp))) - || (ret = __get_user(sec, &tvp->tv_sec)) - || (ret = __get_user(usec, &tvp->tv_usec))) + if (!access_ok(VERIFY_READ, tvp, sizeof(*tvp)) + || __get_user(sec, &tvp->tv_sec) + || __get_user(usec, &tvp->tv_usec)) { + ret = -EFAULT; goto out_nofds; + } - ret = -EINVAL; if (sec < 0 || usec < 0) goto out_nofds; @@ -1011,7 +995,6 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, } } - ret = -EINVAL; if (n < 0 || n > current->files->max_fdset) goto out_nofds; @@ -1167,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/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c index 379617048..fa36b5d1e 100644 --- a/arch/alpha/kernel/ptrace.c +++ b/arch/alpha/kernel/ptrace.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -337,7 +338,7 @@ do_sys_ptrace(long request, long pid, long addr, long data, /* continue and stop at next (return from) syscall */ case PTRACE_CONT: /* restart after signal. */ ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; if (request == PTRACE_SYSCALL) set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); @@ -367,7 +368,7 @@ do_sys_ptrace(long request, long pid, long addr, long data, case PTRACE_SINGLESTEP: /* execute single instruction. */ ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; /* Mark single stepping. */ child->thread_info->bpt_nsaved = -1; diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c index 71d2205aa..b4e5f8ff2 100644 --- a/arch/alpha/kernel/setup.c +++ b/arch/alpha/kernel/setup.c @@ -111,8 +111,6 @@ struct alpha_machine_vector alpha_mv; int alpha_using_srm; #endif -unsigned char aux_device_present = 0xaa; - #define N(a) (sizeof(a)/sizeof(a[0])) static struct alpha_machine_vector *get_sysvec(unsigned long, unsigned long, @@ -213,14 +211,14 @@ static void __init reserve_std_resources(void) { static struct resource standard_io_resources[] = { - { "rtc", -1, -1 }, - { "dma1", 0x00, 0x1f }, - { "pic1", 0x20, 0x3f }, - { "timer", 0x40, 0x5f }, - { "keyboard", 0x60, 0x6f }, - { "dma page reg", 0x80, 0x8f }, - { "pic2", 0xa0, 0xbf }, - { "dma2", 0xc0, 0xdf }, + { .name = "rtc", .start = -1, .end = -1 }, + { .name = "dma1", .start = 0x00, .end = 0x1f }, + { .name = "pic1", .start = 0x20, .end = 0x3f }, + { .name = "timer", .start = 0x40, .end = 0x5f }, + { .name = "keyboard", .start = 0x60, .end = 0x6f }, + { .name = "dma page reg", .start = 0x80, .end = 0x8f }, + { .name = "pic2", .start = 0xa0, .end = 0xbf }, + { .name = "dma2", .start = 0xc0, .end = 0xdf }, }; struct resource *io = &ioport_resource; diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index 974329cf0..08fe8071a 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c @@ -91,7 +91,7 @@ osf_sigaction(int sig, const struct osf_sigaction __user *act, if (act) { old_sigset_t mask; - if (verify_area(VERIFY_READ, act, sizeof(*act)) || + if (!access_ok(VERIFY_READ, act, sizeof(*act)) || __get_user(new_ka.sa.sa_handler, &act->sa_handler) || __get_user(new_ka.sa.sa_flags, &act->sa_flags)) return -EFAULT; @@ -103,7 +103,7 @@ osf_sigaction(int sig, const struct osf_sigaction __user *act, ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); if (!ret && oact) { - if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || + if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || __put_user(old_ka.sa.sa_flags, &oact->sa_flags)) return -EFAULT; @@ -298,7 +298,7 @@ do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs, sigset_t set; /* Verify that it's a good sigcontext before using it */ - if (verify_area(VERIFY_READ, sc, sizeof(*sc))) + if (!access_ok(VERIFY_READ, sc, sizeof(*sc))) goto give_sigsegv; if (__get_user(set.sig[0], &sc->sc_mask)) goto give_sigsegv; @@ -336,7 +336,7 @@ do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs, sigset_t set; /* Verify that it's a good ucontext_t before using it */ - if (verify_area(VERIFY_READ, &frame->uc, sizeof(frame->uc))) + if (!access_ok(VERIFY_READ, &frame->uc, sizeof(frame->uc))) goto give_sigsegv; if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto give_sigsegv; @@ -446,7 +446,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, oldsp = rdusp(); frame = get_sigframe(ka, oldsp, sizeof(*frame)); - if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) + if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp); @@ -497,7 +497,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, oldsp = rdusp(); frame = get_sigframe(ka, oldsp, sizeof(*frame)); - if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) + if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; err |= copy_siginfo_to_user(&frame->info, info); diff --git a/arch/alpha/kernel/smc37c669.c b/arch/alpha/kernel/smc37c669.c index 363267242..fd467b207 100644 --- a/arch/alpha/kernel/smc37c669.c +++ b/arch/alpha/kernel/smc37c669.c @@ -1104,7 +1104,7 @@ static int SMC37c669_xlate_drq( int drq ); -static spinlock_t smc_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED; +static __cacheline_aligned DEFINE_SPINLOCK(smc_lock); /* **++ diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index 04a4d366b..8f1e78551 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c @@ -78,8 +78,6 @@ static unsigned long hwrpb_cpu_present_mask __initdata = 0; int smp_num_probed; /* Internal processor count */ int smp_num_cpus = 1; /* Number that came online. */ -cycles_t cacheflush_time; -unsigned long cache_decay_ticks; extern void calibrate_delay(void); @@ -177,57 +175,6 @@ smp_callin(void) cpu_idle(); } - -/* - * Rough estimation for SMP scheduling, this is the number of cycles it - * takes for a fully memory-limited process to flush the SMP-local cache. - * - * We are not told how much cache there is, so we have to guess. - */ -static void __init -smp_tune_scheduling (int cpuid) -{ - struct percpu_struct *cpu; - unsigned long on_chip_cache; /* kB */ - unsigned long freq; /* Hz */ - unsigned long bandwidth = 350; /* MB/s */ - - cpu = (struct percpu_struct*)((char*)hwrpb + hwrpb->processor_offset - + cpuid * hwrpb->processor_size); - switch (cpu->type) - { - case EV45_CPU: - on_chip_cache = 16 + 16; - break; - - case EV5_CPU: - case EV56_CPU: - on_chip_cache = 8 + 8 + 96; - break; - - case PCA56_CPU: - on_chip_cache = 16 + 8; - break; - - case EV6_CPU: - case EV67_CPU: - default: - on_chip_cache = 64 + 64; - break; - } - - freq = hwrpb->cycle_freq ? : est_cycle_freq; - - cacheflush_time = (freq / 1000000) * (on_chip_cache << 10) / bandwidth; - cache_decay_ticks = cacheflush_time / (freq / 1000) * HZ / 1000; - - printk("per-CPU timeslice cutoff: %ld.%02ld usecs.\n", - cacheflush_time/(freq/1000000), - (cacheflush_time*100/(freq/1000000)) % 100); - printk("task migration cache decay timeout: %ld msecs.\n", - (cache_decay_ticks + 1) * 1000 / HZ); -} - /* Wait until hwrpb->txrdy is clear for cpu. Return -1 on timeout. */ static int __init wait_for_txrdy (unsigned long cpumask) @@ -528,7 +475,6 @@ smp_prepare_cpus(unsigned int max_cpus) current_thread_info()->cpu = boot_cpuid; smp_store_cpu_info(boot_cpuid); - smp_tune_scheduling(boot_cpuid); smp_setup_percpu_timer(boot_cpuid); /* Nothing to do on a UP box, or when told not to. */ diff --git a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c index 6e334292b..9e36b07fa 100644 --- a/arch/alpha/kernel/sys_dp264.c +++ b/arch/alpha/kernel/sys_dp264.c @@ -43,7 +43,7 @@ static unsigned long cached_irq_mask; /* dp264 boards handle at max four CPUs */ static unsigned long cpu_irq_affinity[4] = { 0UL, 0UL, 0UL, 0UL }; -spinlock_t dp264_irq_lock = SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(dp264_irq_lock); static void tsunami_update_irq_hw(unsigned long mask) diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S index b1eaa9c78..6fd1015d6 100644 --- a/arch/alpha/kernel/systbls.S +++ b/arch/alpha/kernel/systbls.S @@ -227,7 +227,7 @@ sys_call_table: .quad sys_semop .quad osf_utsname .quad sys_lchown - .quad osf_shmat + .quad sys_shmat .quad sys_shmctl /* 210 */ .quad sys_shmdt .quad sys_shmget @@ -455,7 +455,7 @@ sys_call_table: .quad sys_stat64 /* 425 */ .quad sys_lstat64 .quad sys_fstat64 - .quad sys_ni_syscall /* sys_vserver */ + .quad sys_vserver /* sys_vserver */ .quad sys_ni_syscall /* sys_mbind */ .quad sys_ni_syscall /* sys_get_mempolicy */ .quad sys_ni_syscall /* sys_set_mempolicy */ @@ -466,6 +466,9 @@ sys_call_table: .quad sys_mq_notify .quad sys_mq_getsetattr .quad sys_waitid + .quad sys_add_key + .quad sys_request_key /* 440 */ + .quad sys_keyctl .size sys_call_table, . - sys_call_table .type sys_call_table, @object diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c index e74677115..8226c5cd7 100644 --- a/arch/alpha/kernel/time.c +++ b/arch/alpha/kernel/time.c @@ -63,7 +63,7 @@ extern unsigned long wall_jiffies; /* kernel/timer.c */ static int set_rtc_mmss(unsigned long); -spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(rtc_lock); #define TICK_SIZE (tick_nsec / 1000) diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c index 3ea81ca1c..65320bd35 100644 --- a/arch/alpha/mm/init.c +++ b/arch/alpha/mm/init.c @@ -20,6 +20,7 @@ #include #include /* max_low_pfn */ #include +#include #include #include @@ -42,10 +43,9 @@ pgd_alloc(struct mm_struct *mm) { pgd_t *ret, *init; - ret = (pgd_t *)__get_free_page(GFP_KERNEL); + ret = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO); init = pgd_offset(&init_mm, 0UL); if (ret) { - clear_page(ret); #ifdef CONFIG_ALPHA_LARGE_VMALLOC memcpy (ret + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD, (PTRS_PER_PGD - USER_PTRS_PER_PGD - 1)*sizeof(pgd_t)); @@ -63,9 +63,7 @@ pgd_alloc(struct mm_struct *mm) pte_t * pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) { - pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT); - if (pte) - clear_page(pte); + pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO); return pte; } diff --git a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c index a839578e9..ba81c4422 100644 --- a/arch/alpha/mm/numa.c +++ b/arch/alpha/mm/numa.c @@ -246,7 +246,7 @@ setup_memory_node(int nid, void *kernel_end) reserve_bootmem_node(NODE_DATA(nid), PFN_PHYS(bootmap_start), bootmap_size); printk(" reserving pages %ld:%ld\n", bootmap_start, bootmap_start+PFN_UP(bootmap_size)); - numnodes++; + node_set_online(nid); } void __init @@ -256,7 +256,7 @@ setup_memory(void *kernel_end) show_mem_layout(); - numnodes = 0; + nodes_clear(node_online_map); min_low_pfn = ~0UL; max_low_pfn = 0UL; @@ -303,7 +303,7 @@ void __init paging_init(void) */ dma_local_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; - for (nid = 0; nid < numnodes; nid++) { + for_each_online_node(nid) { unsigned long start_pfn = node_bdata[nid].node_boot_start >> PAGE_SHIFT; unsigned long end_pfn = node_bdata[nid].node_low_pfn; @@ -332,7 +332,7 @@ void __init mem_init(void) high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT); reservedpages = 0; - for (nid = 0; nid < numnodes; nid++) { + for_each_online_node(nid) { /* * This will free up the bootmem, ie, slot 0 memory */ @@ -372,7 +372,7 @@ show_mem(void) printk("\nMem-info:\n"); show_free_areas(); printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); - for (nid = 0; nid < numnodes; nid++) { + for_each_online_node(nid) { struct page * lmem_map = node_mem_map(nid); i = node_spanned_pages(nid); while (i-- > 0) { diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index dcd224655..c78bb3f13 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -57,6 +57,10 @@ config RWSEM_GENERIC_SPINLOCK config RWSEM_XCHGADD_ALGORITHM bool +config GENERIC_CALIBRATE_DELAY + bool + default y + config GENERIC_BUST_SPINLOCK bool @@ -67,6 +71,9 @@ config GENERIC_IOMAP bool default y +config FIQ + bool + source "init/Kconfig" menu "System Type" @@ -77,6 +84,8 @@ choice config ARCH_CLPS7500 bool "Cirrus-CL-PS7500FE" + select TIMER_ACORN + select ISA config ARCH_CLPS711X bool "CLPS711x/EP721x-based" @@ -88,6 +97,7 @@ config ARCH_CO285 config ARCH_EBSA110 bool "EBSA-110" + select ISA help This is an evaluation board for the StrongARM processor available from Digital. It has limited hardware on-board, including an onboard @@ -107,18 +117,25 @@ config ARCH_FOOTBRIDGE config ARCH_INTEGRATOR bool "Integrator" + select ARM_AMBA + select ICST525 config ARCH_IOP3XX bool "IOP3xx-based" + select PCI config ARCH_IXP4XX bool "IXP4xx-based" + select DMABOUNCE + select PCI config ARCH_IXP2000 bool "IXP2400/2800-based" + select PCI config ARCH_L7200 bool "LinkUp-L7200" + select FIQ help Say Y here if you intend to run this kernel on a LinkUp Systems L7200 Software Development Board which uses an ARM720T processor. @@ -127,29 +144,37 @@ config ARCH_L7200 If you have any questions or comments about the Linux kernel port - to this board, send e-mail to sjhill@cotw.com. + to this board, send e-mail to . config ARCH_PXA bool "PXA2xx-based" config ARCH_RPC bool "RiscPC" + select ARCH_ACORN + select FIQ + select TIMER_ACORN help On the Acorn Risc-PC, Linux can support the internal IDE disk and CD-ROM interface, serial and parallel port, and the floppy drive. config ARCH_SA1100 bool "SA1100-based" + select ISA + select DISCONTIGMEM config ARCH_S3C2410 bool "Samsung S3C2410" help Samsung S3C2410X CPU based systems, such as the Simtec Electronics - BAST (http://www.simtec.co.uk/products/EB110ITX/), the IPAQ 1940 or + BAST (), the IPAQ 1940 or the Samsung SMDK2410 development board (and derviatives). config ARCH_SHARK bool "Shark" + select ISA + select ISA_DMA + select PCI config ARCH_LH7A40X bool "Sharp LH7A40X" @@ -164,6 +189,8 @@ config ARCH_OMAP config ARCH_VERSATILE bool "Versatile" + select ARM_AMBA + select ICST307 help This enables support for ARM Ltd Versatile board. @@ -210,63 +237,47 @@ source "arch/arm/mach-versatile/Kconfig" # Definitions to make life easier config ARCH_ACORN bool - depends on ARCH_RPC - default y -config TIMER_ACORN - bool - depends on ARCH_ACORN || ARCH_CLPS7500 - default y +source arch/arm/mm/Kconfig -##################################################################### -# SA1111 support -config SA1111 +# bool 'Use XScale PMU as timer source' CONFIG_XSCALE_PMU_TIMER +config XSCALE_PMU bool - depends on ASSABET_NEPONSET || SA1100_ADSBITSY || SA1100_BADGE4 || SA1100_CONSUS || SA1100_GRAPHICSMASTER || SA1100_JORNADA720 || ARCH_LUBBOCK || SA1100_PFS168 || SA1100_PT_SYSTEM3 || SA1100_XP860 + depends on CPU_XSCALE && !XSCALE_PMU_TIMER default y -config SHARP_LOCOMO - bool - depends on SA1100_COLLIE - default y +endmenu + +source "arch/arm/common/Kconfig" config FORCE_MAX_ZONEORDER int depends on SA1111 default "9" -config DMABOUNCE - bool - depends on SA1111 || ARCH_IXP4XX - default y - -source arch/arm/mm/Kconfig +menu "Bus support" -# bool 'Use XScale PMU as timer source' CONFIG_XSCALE_PMU_TIMER -config XSCALE_PMU +config ARM_AMBA bool - depends on CPU_XSCALE && !XSCALE_PMU_TIMER - default y -endmenu +config ISA + bool + help + Find out whether you have ISA slots on your motherboard. ISA 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 PCI, EISA, MicroChannel + (MCA) or VESA. ISA is an older system, now being displaced by PCI; + newer boards don't support it. If you have ISA, say Y, otherwise N. -menu "General setup" +config ISA_DMA + bool -# Select various configuration options depending on the machine type -config DISCONTIGMEM +config ISA_DMA_API bool - depends on ARCH_EDB7211 || ARCH_SA1100 || (ARCH_LH7A40X && !LH7A40X_CONTIGMEM) default y - help - Say Y to support efficient handling of discontiguous physical memory, - for architectures which are either NUMA (Non-Uniform Memory Access) - or have huge holes in the physical address space for other reasons. - See for more. -# Now handle the bus types config PCI bool "PCI support" if ARCH_INTEGRATOR_AP - default y if ARCH_SHARK || FOOTBRIDGE_HOST || ARCH_IOP3XX || ARCH_IXP4XX || ARCH_IXP2000 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 @@ -284,41 +295,125 @@ config PCI_HOST_VIA82C505 depends on PCI && ARCH_SHARK default y -config ICST525 - bool - depends on ARCH_INTEGRATOR - default y +source "drivers/pci/Kconfig" -config ICST307 - bool - depends on ARCH_VERSATILE - default y +source "drivers/pcmcia/Kconfig" -config ARM_AMBA - bool - depends on ARCH_INTEGRATOR || ARCH_VERSATILE - default y +endmenu -config ISA - bool - depends on FOOTBRIDGE_HOST || ARCH_SHARK || ARCH_CLPS7500 || ARCH_EBSA110 || ARCH_CDB89712 || ARCH_EDB7211 || ARCH_SA1100 || ARCH_MX1ADS - default y +menu "Kernel Features" + +config SMP + bool "Symmetric Multi-Processing (EXPERIMENTAL)" + depends on EXPERIMENTAL #&& n help - Find out whether you have ISA slots on your motherboard. ISA 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 PCI, EISA, MicroChannel - (MCA) or VESA. ISA is an older system, now being displaced by PCI; - newer boards don't support it. If you have ISA, say Y, otherwise N. + This enables support for systems with more than one CPU. If you have + a system with only one CPU, like most personal computers, say N. If + you have a system with more than one CPU, say Y. -config ISA_DMA + If you say N here, the kernel will run on single and multiprocessor + machines, but will use only one CPU of a multiprocessor machine. If + you say Y here, the kernel will run on many, but not all, single + processor machines. On a single processor machine, the kernel will + run faster if you say N here. + + See also the , + , , + and the SMP-HOWTO available at + . + + If you don't know what to do here, say N. + +config NR_CPUS + int "Maximum number of CPUs (2-32)" + range 2 32 + depends on SMP + default "4" + +config PREEMPT + bool "Preemptible Kernel (EXPERIMENTAL)" + depends on EXPERIMENTAL + 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 DISCONTIGMEM bool - depends on FOOTBRIDGE_HOST || ARCH_SHARK - default y + default (ARCH_LH7A40X && !LH7A40X_CONTIGMEM) + help + Say Y to support efficient handling of discontiguous physical memory, + for architectures which are either NUMA (Non-Uniform Memory Access) + or have huge holes in the physical address space for other reasons. + See for more. -config FIQ +config LEDS + bool "Timer and CPU usage LEDs" + depends on ARCH_CDB89712 || ARCH_CO285 || ARCH_EBSA110 || \ + ARCH_EBSA285 || ARCH_IMX || ARCH_INTEGRATOR || \ + ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_NETWINDER || \ + ARCH_OMAP || ARCH_P720T || ARCH_PXA_IDP || \ + ARCH_SA1100 || ARCH_SHARK || ARCH_VERSATILE + help + If you say Y here, the LEDs on your machine will be used + to provide useful information about your current system status. + + If you are compiling a kernel for a NetWinder or EBSA-285, you will + be able to select which LEDs are active using the options below. If + you are compiling a kernel for the EBSA-110 or the LART however, the + red LED will simply flash regularly to indicate that the system is + still functional. It is safe to say Y here if you have a CATS + system, but the driver will do nothing. + +config LEDS_TIMER + bool "Timer LED" if (!ARCH_CDB89712 && !ARCH_OMAP) || \ + MACH_OMAP_H2 || MACH_OMAP_PERSEUS2 + depends on LEDS + default y if ARCH_EBSA110 + help + If you say Y here, one of the system LEDs (the green one on the + NetWinder, the amber one on the EBSA285, or the red one on the LART) + will flash regularly to indicate that the system is still + operational. This is mainly useful to kernel hackers who are + debugging unstable kernels. + + The LART uses the same LED for both Timer LED and CPU usage LED + functions. You may choose to use both, but the Timer LED function + will overrule the CPU usage LED. + +config LEDS_CPU + bool "CPU usage LED" if (!ARCH_CDB89712 && !ARCH_EBSA110 && \ + !ARCH_OMAP) || MACH_OMAP_H2 || MACH_OMAP_PERSEUS2 + depends on LEDS + help + If you say Y here, the red LED will be used to give a good real + time indication of CPU usage, by lighting whenever the idle task + is not currently executing. + + The LART uses the same LED for both Timer LED and CPU usage LED + functions. You may choose to use both, but the Timer LED function + will overrule the CPU usage LED. + +config ALIGNMENT_TRAP bool - depends on ARCH_ACORN || ARCH_L7200 - default y + default y if !ARCH_EBSA110 + help + ARM processors can not fetch/store information which is not + naturally aligned on the bus, i.e., a 4 byte fetch must start at an + address divisible by 4. On 32-bit ARM processors, these non-aligned + fetch/store instructions will be emulated in software if you say + here, which has a severe performance impact. This is necessary for + correct operation of some network protocols. With an IP-only + configuration it is safe to say N, otherwise say Y. + +endmenu + +menu "Boot options" # Compressed boot loader in ROM. Yes, we really want to ask about # TEXT and BSS so we preserve their values in the config files. @@ -352,6 +447,16 @@ config ZBOOT_ROM Say Y here if you intend to execute your compressed kernel image (zImage) directly from ROM or flash. If unsure, say N. +config CMDLINE + string "Default kernel command string" + default "" + 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 XIP_KERNEL bool "Kernel Execute-In-Place from ROM" depends on !ZBOOT_ROM @@ -382,27 +487,17 @@ config XIP_PHYS_ADDR be linked for and stored to. This address is dependent on your own flash usage. - Please note that, if you're using MTD, you must use a flash chip - that is NOT handled by MTD or the flash will be turned into non - data mode for status and query purposes which will instantaneously - crash the kernel. - - MTD can however be used with a XIP kernel on the same flash chip - but only if the flash memory supports multiple partitions in - hardware, like with the Intel K3 flash parts, and only if the - kernel is not stored within the firrst hardware partition of the - chip. - - In any case, make sure that MTD support is configured out for - the first attempt. +endmenu if (ARCH_SA1100 || ARCH_INTEGRATOR) +menu "CPU Frequency scaling" + 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 @@ -412,7 +507,7 @@ config CPU_FREQ_SA1110 config CPU_FREQ_INTEGRATOR tristate "CPUfreq driver for ARM Integrator CPUs" - depends on ARCH_INTEGRATOR && ICST525 && CPU_FREQ + depends on ARCH_INTEGRATOR && CPU_FREQ default y help This enables the CPUfreq driver for ARM Integrator CPUs. @@ -421,13 +516,13 @@ config CPU_FREQ_INTEGRATOR If in doubt, say Y. -endif +endmenu -source "drivers/pci/Kconfig" +endif -source "drivers/pcmcia/Kconfig" +menu "Floating point emulation" -comment "At least one math emulation must be selected" +comment "At least one emulation must be selected" config FPE_NWFPE bool "NWFPE math emulation" @@ -478,9 +573,24 @@ config VFP Say N if your target does not have VFP hardware. +endmenu + +menu "Userspace binary formats" + source "fs/Kconfig.binfmt" -source "drivers/base/Kconfig" +config ARTHUR + tristate "RISC OS personality" + help + Say Y here to include the kernel code necessary if you want to run + Acorn RISC OS/Arthur binaries under Linux. This code is still very + experimental; if this sounds frightening, say N and sleep in peace. + You can also say M here to compile this support as a module (which + will be called arthur). + +endmenu + +menu "Power management options" config PM bool "Power Management support" @@ -502,19 +612,6 @@ config PM will issue the hlt instruction if nothing is to be done, thereby sending the processor to sleep and saving power. -config PREEMPT - bool "Preemptible Kernel (EXPERIMENTAL)" - depends on CPU_32 && EXPERIMENTAL - 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 APM tristate "Advanced Power Management Emulation" depends on PM @@ -574,115 +671,46 @@ config APM To compile this driver as a module, choose M here: the module will be called apm. -config ARTHUR - tristate "RISC OS personality" - depends on CPU_32 - help - Say Y here to include the kernel code necessary if you want to run - Acorn RISC OS/Arthur binaries under Linux. This code is still very - experimental; if this sounds frightening, say N and sleep in peace. - You can also say M here to compile this support as a module (which - will be called arthur). - -config CMDLINE - string "Default kernel command string" - default "" - 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 LEDS - bool "Timer and CPU usage LEDs" - depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE || ARCH_IMX - help - If you say Y here, the LEDs on your machine will be used - to provide useful information about your current system status. - - If you are compiling a kernel for a NetWinder or EBSA-285, you will - be able to select which LEDs are active using the options below. If - you are compiling a kernel for the EBSA-110 or the LART however, the - red LED will simply flash regularly to indicate that the system is - still functional. It is safe to say Y here if you have a CATS - system, but the driver will do nothing. - -config LEDS_TIMER - bool "Timer LED" if LEDS && (ARCH_NETWINDER || ARCH_EBSA285 || ARCH_SHARK || MACH_MAINSTONE || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_P720T || ARCH_VERSATILE || ARCH_IMX) - depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE || ARCH_IMX - default y if ARCH_EBSA110 - help - If you say Y here, one of the system LEDs (the green one on the - NetWinder, the amber one on the EBSA285, or the red one on the LART) - will flash regularly to indicate that the system is still - operational. This is mainly useful to kernel hackers who are - debugging unstable kernels. - - The LART uses the same LED for both Timer LED and CPU usage LED - functions. You may choose to use both, but the Timer LED function - will overrule the CPU usage LED. - -config LEDS_CPU - bool "CPU usage LED" - depends on LEDS && (ARCH_NETWINDER || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_P720T || ARCH_VERSATILE || ARCH_IMX) - help - If you say Y here, the red LED will be used to give a good real - time indication of CPU usage, by lighting whenever the idle task - is not currently executing. - - The LART uses the same LED for both Timer LED and CPU usage LED - functions. You may choose to use both, but the Timer LED function - will overrule the CPU usage LED. - -config ALIGNMENT_TRAP - bool - depends on CPU_32 - default y if !ARCH_EBSA110 - help - ARM processors can not fetch/store information which is not - naturally aligned on the bus, i.e., a 4 byte fetch must start at an - address divisible by 4. On 32-bit ARM processors, these non-aligned - fetch/store instructions will be emulated in software if you say - here, which has a severe performance impact. This is necessary for - correct operation of some network protocols. With an IP-only - configuration it is safe to say N, otherwise say Y. - endmenu -source "drivers/parport/Kconfig" +menu "Device Drivers" + +source "drivers/base/Kconfig" if ALIGNMENT_TRAP source "drivers/mtd/Kconfig" endif +source "drivers/parport/Kconfig" + source "drivers/pnp/Kconfig" source "drivers/block/Kconfig" -source "drivers/md/Kconfig" - source "drivers/acorn/block/Kconfig" -source "net/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 source "drivers/scsi/Kconfig" +source "drivers/md/Kconfig" + source "drivers/message/fusion/Kconfig" source "drivers/ieee1394/Kconfig" source "drivers/message/i2o/Kconfig" +source "net/Kconfig" + source "drivers/isdn/Kconfig" -# # input before char - char/joystick depends on it. As does USB. -# + source "drivers/input/Kconfig" source "drivers/char/Kconfig" @@ -691,22 +719,24 @@ source "drivers/i2c/Kconfig" #source "drivers/l3/Kconfig" -source "drivers/media/Kconfig" - -source "fs/Kconfig" +source "drivers/misc/Kconfig" -source "arch/arm/oprofile/Kconfig" +source "drivers/media/Kconfig" source "drivers/video/Kconfig" source "sound/Kconfig" -source "drivers/misc/Kconfig" - source "drivers/usb/Kconfig" source "drivers/mmc/Kconfig" +endmenu + +source "fs/Kconfig" + +source "arch/arm/oprofile/Kconfig" + source "arch/arm/Kconfig.debug" source "kernel/vserver/Kconfig" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 8b9760b93..2277e3d17 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -22,15 +22,13 @@ CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog endif ifeq ($(CONFIG_CPU_BIG_ENDIAN),y) -CFLAGS += -mbig-endian +CPPFLAGS += -mbig-endian AS += -EB LD += -EB -AFLAGS += -mbig-endian else -CFLAGS += -mlittle-endian +CPPFLAGS += -mlittle-endian AS += -EL LD += -EL -AFLAGS += -mlittle-endian endif comma = , diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 55fcbb7af..6b505ce41 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -46,6 +46,10 @@ ifeq ($(CONFIG_CPU_XSCALE),y) OBJS += head-xscale.o endif +ifeq ($(CONFIG_PXA_SHARPSL),y) +OBJS += head-sharpsl.o +endif + ifeq ($(CONFIG_DEBUG_ICEDCC),y) OBJS += ice-dcc.o endif diff --git a/arch/arm/boot/compressed/head-xscale.S b/arch/arm/boot/compressed/head-xscale.S index 637e63773..d3fe25339 100644 --- a/arch/arm/boot/compressed/head-xscale.S +++ b/arch/arm/boot/compressed/head-xscale.S @@ -34,20 +34,6 @@ __XScale_start: bic r0, r0, #0x1000 @ clear Icache mcr p15, 0, r0, c1, c0, 0 -#ifdef CONFIG_ARCH_IQ80321 - mov r7, #MACH_TYPE_IQ80321 -#endif - -#ifdef CONFIG_ARCH_IQ31244 - mov r7, #(MACH_TYPE_IQ31244 & 0xff) - orr r7, r7, #(MACH_TYPE_IQ31244 & 0xff00) -#endif - -#ifdef CONFIG_ARCH_IQ80331 - mov r7, #(MACH_TYPE_IQ80331 & 0xff) - orr r7, r7, #(MACH_TYPE_IQ80331 & 0xff00) -#endif - #ifdef CONFIG_ARCH_LUBBOCK mov r7, #MACH_TYPE_LUBBOCK #endif @@ -56,3 +42,15 @@ __XScale_start: mov r7, #MACH_TYPE_COTULLA_IDP #endif +#ifdef CONFIG_MACH_GTWX5715 + mov r7, #(MACH_TYPE_GTWX5715 & 0xff) + 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/compressed/head.S b/arch/arm/boot/compressed/head.S index c0e7aff3d..7c7f475e2 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -18,48 +18,30 @@ * Please select one of the following when turning on debugging. */ #ifdef DEBUG -#if defined(CONFIG_DEBUG_DC21285_PORT) - .macro loadsp, rb - mov \rb, #0x42000000 - .endm - .macro writeb, rb - str \rb, [r3, #0x160] - .endm -#elif defined(CONFIG_DEBUG_ICEDCC) + +#include + +#if defined(CONFIG_DEBUG_ICEDCC) .macro loadsp, rb .endm - .macro writeb, rb - mcr p14, 0, \rb, c0, c1, 0 - .endm -#elif defined(CONFIG_FOOTBRIDGE) - .macro loadsp, rb - mov \rb, #0x7c000000 + .macro writeb, ch, rb + mcr p14, 0, \ch, c0, c1, 0 .endm - .macro writeb, rb - strb \rb, [r3, #0x3f8] +#else + .macro writeb, ch, rb + senduart \ch, \rb .endm -#elif defined(CONFIG_ARCH_RPC) + +#if defined(CONFIG_FOOTBRIDGE) || \ + defined(CONFIG_ARCH_RPC) || \ + defined(CONFIG_ARCH_INTEGRATOR) || \ + defined(CONFIG_ARCH_PXA) || \ + defined(CONFIG_ARCH_IXP4XX) || \ + defined(CONFIG_ARCH_IXP2000) || \ + defined(CONFIG_ARCH_LH7A40X) || \ + defined(CONFIG_ARCH_OMAP) .macro loadsp, rb - mov \rb, #0x03000000 - orr \rb, \rb, #0x00010000 - .endm - .macro writeb, rb - strb \rb, [r3, #0x3f8 << 2] - .endm -#elif defined(CONFIG_ARCH_INTEGRATOR) - .macro loadsp, rb - mov \rb, #0x16000000 - .endm - .macro writeb, rb - strb \rb, [r3, #0] - .endm -#elif defined(CONFIG_ARCH_PXA) /* Xscale-type */ - .macro loadsp, rb - mov \rb, #0x40000000 - orr \rb, \rb, #0x00100000 - .endm - .macro writeb, rb - strb \rb, [r3, #0] + addruart \rb .endm #elif defined(CONFIG_ARCH_SA1100) .macro loadsp, rb @@ -70,64 +52,21 @@ add \rb, \rb, #0x00010000 @ Ser1 # endif .endm - .macro writeb, rb - str \rb, [r3, #0x14] @ UTDR - .endm -#elif defined(CONFIG_ARCH_IXP4XX) - .macro loadsp, rb - mov \rb, #0xc8000000 - .endm - .macro writeb, rb - str \rb, [r3, #0] -#elif defined(CONFIG_ARCH_IXP2000) - .macro loadsp, rb - mov \rb, #0xc0000000 - orr \rb, \rb, #0x00030000 - .endm - .macro writeb, rb - str \rb, [r3, #0] - .endm -#elif defined(CONFIG_ARCH_LH7A40X) - .macro loadsp, rb - ldr \rb, =0x80000700 @ UART2 UARTBASE - .endm - .macro writeb, rb - strb \rb, [r3, #0] - .endm -#elif defined(CONFIG_ARCH_OMAP) - .macro loadsp, rb - mov \rb, #0xff000000 @ physical base address - add \rb, \rb, #0x00fb0000 -#if defined(CONFIG_OMAP_LL_DEBUG_UART2) || defined(CONFIG_OMAP_LL_DEBUG_UART3) - add \rb, \rb, #0x00000800 -#endif -#ifdef CONFIG_OMAP_LL_DEBUG_UART3 - add \rb, \rb, #0x00009000 -#endif - .endm - .macro writeb, rb - strb \rb, [r3] - .endm #elif defined(CONFIG_ARCH_IOP331) .macro loadsp, rb mov \rb, #0xff000000 orr \rb, \rb, #0x00ff0000 orr \rb, \rb, #0x0000f700 @ location of the UART .endm - .macro writeb, rb - str \rb, [r3, #0] - .endm #elif defined(CONFIG_ARCH_S3C2410) - .macro loadsp, rb + .macro loadsp, rb mov \rb, #0x50000000 add \rb, \rb, #0x4000 * CONFIG_S3C2410_LOWLEVEL_UART_PORT .endm - .macro writeb, rb - strb \rb, [r3, #0x20] - .endm #else #error no serial architecture defined #endif +#endif #endif .macro kputc,val @@ -734,7 +673,7 @@ puts: loadsp r3 1: ldrb r2, [r0], #1 teq r2, #0 moveq pc, lr -2: writeb r2 +2: writeb r2, r3 mov r1, #0x00020000 3: subs r1, r1, #1 bne 3b diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile index 5b9f9eddd..11f20a43e 100644 --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile @@ -11,3 +11,5 @@ obj-$(CONFIG_PCI_HOST_VIA82C505) += via82c505.o obj-$(CONFIG_DMABOUNCE) += dmabounce.o obj-$(CONFIG_TIMER_ACORN) += time-acorn.o obj-$(CONFIG_SHARP_LOCOMO) += locomo.o +obj-$(CONFIG_SHARP_PARAM) += sharpsl_param.o +obj-$(CONFIG_SHARP_SCOOP) += scoop.o diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index 9525e804b..21fce3414 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c @@ -53,7 +53,7 @@ struct sa1111 { unsigned long phys; int irq; spinlock_t lock; - void *base; + void __iomem *base; }; /* @@ -141,15 +141,16 @@ static void sa1111_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) { unsigned int stat0, stat1, i; + void __iomem *base = desc->data; - stat0 = sa1111_readl(desc->data + SA1111_INTSTATCLR0); - stat1 = sa1111_readl(desc->data + SA1111_INTSTATCLR1); + stat0 = sa1111_readl(base + SA1111_INTSTATCLR0); + stat1 = sa1111_readl(base + SA1111_INTSTATCLR1); - sa1111_writel(stat0, desc->data + SA1111_INTSTATCLR0); + sa1111_writel(stat0, base + SA1111_INTSTATCLR0); desc->chip->ack(irq); - sa1111_writel(stat1, desc->data + SA1111_INTSTATCLR1); + sa1111_writel(stat1, base + SA1111_INTSTATCLR1); if (stat0 == 0 && stat1 == 0) { do_bad_IRQ(irq, desc, regs); @@ -177,7 +178,7 @@ static void sa1111_ack_irq(unsigned int irq) static void sa1111_mask_lowirq(unsigned int irq) { - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); unsigned long ie0; ie0 = sa1111_readl(mapbase + SA1111_INTEN0); @@ -187,7 +188,7 @@ static void sa1111_mask_lowirq(unsigned int irq) static void sa1111_unmask_lowirq(unsigned int irq) { - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); unsigned long ie0; ie0 = sa1111_readl(mapbase + SA1111_INTEN0); @@ -205,7 +206,7 @@ static void sa1111_unmask_lowirq(unsigned int irq) static int sa1111_retrigger_lowirq(unsigned int irq) { unsigned int mask = SA1111_IRQMASK_LO(irq); - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); unsigned long ip0; int i; @@ -226,7 +227,7 @@ static int sa1111_retrigger_lowirq(unsigned int irq) static int sa1111_type_lowirq(unsigned int irq, unsigned int flags) { unsigned int mask = SA1111_IRQMASK_LO(irq); - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); unsigned long ip0; if (flags == IRQT_PROBE) @@ -249,7 +250,7 @@ static int sa1111_type_lowirq(unsigned int irq, unsigned int flags) static int sa1111_wake_lowirq(unsigned int irq, unsigned int on) { unsigned int mask = SA1111_IRQMASK_LO(irq); - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); unsigned long we0; we0 = sa1111_readl(mapbase + SA1111_WAKEEN0); @@ -273,7 +274,7 @@ static struct irqchip sa1111_low_chip = { static void sa1111_mask_highirq(unsigned int irq) { - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); unsigned long ie1; ie1 = sa1111_readl(mapbase + SA1111_INTEN1); @@ -283,7 +284,7 @@ static void sa1111_mask_highirq(unsigned int irq) static void sa1111_unmask_highirq(unsigned int irq) { - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); unsigned long ie1; ie1 = sa1111_readl(mapbase + SA1111_INTEN1); @@ -301,7 +302,7 @@ static void sa1111_unmask_highirq(unsigned int irq) static int sa1111_retrigger_highirq(unsigned int irq) { unsigned int mask = SA1111_IRQMASK_HI(irq); - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); unsigned long ip1; int i; @@ -322,7 +323,7 @@ static int sa1111_retrigger_highirq(unsigned int irq) static int sa1111_type_highirq(unsigned int irq, unsigned int flags) { unsigned int mask = SA1111_IRQMASK_HI(irq); - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); unsigned long ip1; if (flags == IRQT_PROBE) @@ -345,7 +346,7 @@ static int sa1111_type_highirq(unsigned int irq, unsigned int flags) static int sa1111_wake_highirq(unsigned int irq, unsigned int on) { unsigned int mask = SA1111_IRQMASK_HI(irq); - void *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chipdata(irq); unsigned long we1; we1 = sa1111_readl(mapbase + SA1111_WAKEEN1); @@ -369,7 +370,7 @@ static struct irqchip sa1111_high_chip = { static void sa1111_setup_irq(struct sa1111 *sachip) { - void *irqbase = sachip->base + SA1111_INTC; + void __iomem *irqbase = sachip->base + SA1111_INTC; unsigned int irq; /* @@ -723,7 +724,7 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq) static void __sa1111_remove(struct sa1111 *sachip) { struct list_head *l, *n; - void *irqbase = sachip->base + SA1111_INTC; + void __iomem *irqbase = sachip->base + SA1111_INTC; list_for_each_safe(l, n, &sachip->dev->children) { struct device *d = list_to_dev(l); @@ -797,15 +798,15 @@ struct sa1111_save_data { unsigned int wakeen1; }; -#ifdef CONFIG_PM +#ifdef CONFIG_PM -static int sa1111_suspend(struct device *dev, u32 state, u32 level) +static int sa1111_suspend(struct device *dev, pm_message_t state, u32 level) { struct sa1111 *sachip = dev_get_drvdata(dev); struct sa1111_save_data *save; unsigned long flags; unsigned int val; - char *base; + void __iomem *base; if (level != SUSPEND_DISABLE) return 0; @@ -866,7 +867,7 @@ static int sa1111_resume(struct device *dev, u32 level) struct sa1111 *sachip = dev_get_drvdata(dev); struct sa1111_save_data *save; unsigned long flags, id; - char *base; + void __iomem *base; if (level != RESUME_ENABLE) return 0; @@ -922,11 +923,10 @@ static int sa1111_resume(struct device *dev, u32 level) return 0; } -#else /* !CONFIG_PM */ -#define sa1111_resume NULL -#define sa1111_suspend NULL -#endif /* !CONFIG_PM */ - +#else +#define sa1111_suspend NULL +#define sa1111_resume NULL +#endif static int sa1111_probe(struct device *dev) { @@ -1095,7 +1095,7 @@ void sa1111_set_io_dir(struct sa1111_dev *sadev, struct sa1111 *sachip = sa1111_chip_driver(sadev); unsigned long flags; unsigned int val; - void *gpio = sachip->base + SA1111_GPIO; + void __iomem *gpio = sachip->base + SA1111_GPIO; #define MODIFY_BITS(port, mask, dir) \ if (mask) { \ @@ -1121,7 +1121,7 @@ void sa1111_set_io(struct sa1111_dev *sadev, unsigned int bits, unsigned int v) struct sa1111 *sachip = sa1111_chip_driver(sadev); unsigned long flags; unsigned int val; - void *gpio = sachip->base + SA1111_GPIO; + void __iomem *gpio = sachip->base + SA1111_GPIO; spin_lock_irqsave(&sachip->lock, flags); MODIFY_BITS(gpio + SA1111_GPIO_PADWR, bits & 15, v); @@ -1135,7 +1135,7 @@ void sa1111_set_sleep_io(struct sa1111_dev *sadev, unsigned int bits, unsigned i struct sa1111 *sachip = sa1111_chip_driver(sadev); unsigned long flags; unsigned int val; - void *gpio = sachip->base + SA1111_GPIO; + void __iomem *gpio = sachip->base + SA1111_GPIO; spin_lock_irqsave(&sachip->lock, flags); MODIFY_BITS(gpio + SA1111_GPIO_PASSR, bits & 15, v); @@ -1194,7 +1194,7 @@ static int sa1111_match(struct device *_dev, struct device_driver *_drv) return dev->devid == drv->devid; } -static int sa1111_bus_suspend(struct device *dev, u32 state) +static int sa1111_bus_suspend(struct device *dev, pm_message_t state) { struct sa1111_dev *sadev = SA1111_DEV(dev); struct sa1111_driver *drv = SA1111_DRV(dev->driver); diff --git a/arch/arm/configs/a5k_defconfig b/arch/arm/configs/a5k_defconfig deleted file mode 100644 index ec03535a7..000000000 --- a/arch/arm/configs/a5k_defconfig +++ /dev/null @@ -1,522 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_ARM=y -# CONFIG_SBUS is not set -CONFIG_UID16=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -CONFIG_OBSOLETE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y - -# -# System Type -# -CONFIG_ARCH_ARCA5K=y -# CONFIG_ARCH_CLPS7500 is not set -# CONFIG_ARCH_CO285 is not set -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_SA1100 is not set - -# -# Archimedes/A5000 Implementations -# - -# -# Archimedes/A5000 Implementations (select only ONE) -# -# CONFIG_ARCH_ARC is not set -CONFIG_ARCH_A5K=y - -# -# Footbridge Implementations -# - -# -# SA11x0 Implementations -# -CONFIG_ARCH_ACORN=y -# CONFIG_FOOTBRIDGE is not set -# CONFIG_FOOTBRIDGE_HOST is not set -# CONFIG_FOOTBRIDGE_ADDIN is not set -# CONFIG_CPU_32 is not set -CONFIG_CPU_26=y -# CONFIG_PAGESIZE_16 is not set - -# -# Processor Type -# -# CONFIG_DISCONTIGMEM is not set - -# -# General setup -# -# CONFIG_PCI is not set -# CONFIG_ISA is not set -# CONFIG_ISA_DMA is not set -# CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set -CONFIG_NET=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_NWFPE=y -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -CONFIG_BINFMT_AOUT=y -# CONFIG_BINFMT_ELF is not set -# CONFIG_BINFMT_MISC is not set -# CONFIG_PM is not set - -# -# Parallel port support -# -CONFIG_PARPORT=m -CONFIG_PARPORT_PC=m -# CONFIG_PARPORT_PC_FIFO is not set -CONFIG_PARPORT_PC_SUPERIO=y -# CONFIG_PARPORT_ARC is not set -# CONFIG_PARPORT_AMIGA is not set -# CONFIG_PARPORT_MFC3 is not set -# CONFIG_PARPORT_ATARI is not set -# CONFIG_PARPORT_SUNBPP is not set -# CONFIG_PARPORT_OTHER is not set -# CONFIG_PARPORT_1284 is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Plug and Play configuration -# -# CONFIG_PNP is not set -# CONFIG_ISAPNP is not set - -# -# Block devices -# -CONFIG_BLK_DEV_FD=y -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE 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_LOOP=m -# CONFIG_BLK_DEV_NBD is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y - -# -# Acorn-specific block devices -# -# CONFIG_BLK_DEV_FD1772 is not set -CONFIG_BLK_DEV_MFM=m -CONFIG_BLK_DEV_MFM_AUTODETECT=y - -# -# Networking options -# -# CONFIG_PACKET is not set -# CONFIG_NETLINK is not set -# CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set -CONFIG_UNIX=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set - -# -# -# -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_NET_SB1000 is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -CONFIG_ARM_ETHER1=y -CONFIG_ARM_ETHER3=y -# CONFIG_ARM_ETHERH is not set -# 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 -# CONFIG_DEPCA is not set -# CONFIG_NET_ISA is not set -# CONFIG_NET_PCI is not set -# CONFIG_NET_POCKET is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_SK98LIN is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices -# -# CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ATA/IDE/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_BLK_DEV_IDECS 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_BLK_DEV_IDESCSI is not set - -# -# IDE chipset support/bugfixes -# -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -# CONFIG_BLK_DEV_ISAPNP is not set -CONFIG_BLK_DEV_IDE_ICSIDE=y -# CONFIG_BLK_DEV_IDEDMA_ICS is not set -# CONFIG_IDEDMA_ICS_AUTO is not set -# CONFIG_BLK_DEV_IDEDMA is not set -# CONFIG_BLK_DEV_IDE_RAPIDE is not set -# CONFIG_IDE_CHIPSETS is not set -# CONFIG_IDEDMA_AUTO is not set - -# -# SCSI support -# -# CONFIG_SCSI is not set - -# -# I2O device support -# -# CONFIG_I2O is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -# CONFIG_ATOMWIDE_SERIAL is not set -# CONFIG_DUALSP_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set -# CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_UNIX98_PTYS is not set -# CONFIG_PRINTER is not set -# CONFIG_PPDEV is not set - -# -# I2C support -# -CONFIG_I2C=y -CONFIG_I2C_ALGOBIT=y -# CONFIG_I2C_ALGOPCF is not set -CONFIG_I2C_CHARDEV=y - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=y -# CONFIG_PSMOUSE is not set -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set - -# -# Joysticks -# -# CONFIG_JOYSTICK is not set - -# -# Input core support is needed for joysticks -# -# CONFIG_QIC02_TAPE is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set -# CONFIG_NVRAM is not set -# CONFIG_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_FTAPE is not set -# CONFIG_AGP is not set -# CONFIG_DRM is not set - -# -# File systems -# -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -CONFIG_AUTOFS4_FS=y -CONFIG_ADFS_FS=y -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BFS_FS is not set -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_RAMFS is not set -# CONFIG_ISO9660_FS is not set -# CONFIG_JOLIET is not set -# CONFIG_MINIX_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -# CONFIG_DEVPTS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y -# CONFIG_SYSV_FS is not set -# CONFIG_SYSV_FS_WRITE is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set -# CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set - -# -# Network File Systems -# -# CONFIG_CODA_FS is not set -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_ROOT_NFS is not set -# CONFIG_NFSD is not set -# CONFIG_NFSD_V3 is not set -CONFIG_SUNRPC=y -CONFIG_LOCKD=y -# CONFIG_SMB_FS is not set -# CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_MOUNT_SUBDIR is not set -# CONFIG_NCPFS_NDS_DOMAINS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -CONFIG_ACORN_PARTITION=y -CONFIG_ACORN_PARTITION_ADFS=y -CONFIG_ACORN_PARTITION_ICS=y -CONFIG_ACORN_PARTITION_POWERTEC=y -CONFIG_ACORN_PARTITION_RISCIX=y -CONFIG_NLS=y - -# -# Native Language Support -# -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_874 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_950 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_8 is not set -# CONFIG_NLS_ISO8859_9 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_UTF8 is not set - -# -# Console drivers -# -CONFIG_FB=y - -# -# Frame-buffer support -# -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_FB_ACORN=y -# CONFIG_FB_CYBER2000 is not set -# CONFIG_FB_VIRTUAL is not set -# CONFIG_FBCON_ADVANCED is not set -CONFIG_FBCON_MFB=y -CONFIG_FBCON_CFB2=y -CONFIG_FBCON_CFB4=y -CONFIG_FBCON_CFB8=y -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -CONFIG_FBCON_FONTS=y -# CONFIG_FONT_8x8 is not set -# CONFIG_FONT_8x16 is not set -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_PEARL_8x8 is not set -CONFIG_FONT_ACORN_8x8=y - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB is not set - -# -# Kernel hacking -# -CONFIG_FRAME_POINTER=y -CONFIG_DEBUG_ERRORS=y -CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_INFO is not set -CONFIG_MAGIC_SYSRQ=y -CONFIG_NO_PGT_CACHE=y -CONFIG_DEBUG_LL=y diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 7c56c5589..4a2af55e1 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_MODULES) += armksyms.o module.o obj-$(CONFIG_ARTHUR) += arthur.o obj-$(CONFIG_ISA_DMA) += dma-isa.o obj-$(CONFIG_PCI) += bios32.o +obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_IWMMXT) += iwmmxt.o AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt @@ -30,8 +31,3 @@ head-y := head.o obj-$(CONFIG_DEBUG_LL) += debug.o extra-y := $(head-y) init_task.o vmlinux.lds - -# Spell out some dependencies that aren't automatically figured out -$(obj)/entry-armv.o: $(obj)/entry-header.S include/asm-arm/constants.h -$(obj)/entry-common.o: $(obj)/entry-header.S include/asm-arm/constants.h \ - $(obj)/calls.S diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c index 93525fdf2..c1ff4d1f1 100644 --- a/arch/arm/kernel/asm-offsets.c +++ b/arch/arm/kernel/asm-offsets.c @@ -59,10 +59,31 @@ int main(void) DEFINE(TI_CPU_DOMAIN, offsetof(struct thread_info, cpu_domain)); DEFINE(TI_CPU_SAVE, offsetof(struct thread_info, cpu_context)); DEFINE(TI_USED_CP, offsetof(struct thread_info, used_cp)); + DEFINE(TI_TP_VALUE, offsetof(struct thread_info, tp_value)); DEFINE(TI_FPSTATE, offsetof(struct thread_info, fpstate)); DEFINE(TI_VFPSTATE, offsetof(struct thread_info, vfpstate)); DEFINE(TI_IWMMXT_STATE, (offsetof(struct thread_info, fpstate)+4)&~7); BLANK(); + DEFINE(S_R0, offsetof(struct pt_regs, ARM_r0)); + DEFINE(S_R1, offsetof(struct pt_regs, ARM_r1)); + DEFINE(S_R2, offsetof(struct pt_regs, ARM_r2)); + DEFINE(S_R3, offsetof(struct pt_regs, ARM_r3)); + DEFINE(S_R4, offsetof(struct pt_regs, ARM_r4)); + DEFINE(S_R5, offsetof(struct pt_regs, ARM_r5)); + DEFINE(S_R6, offsetof(struct pt_regs, ARM_r6)); + DEFINE(S_R7, offsetof(struct pt_regs, ARM_r7)); + DEFINE(S_R8, offsetof(struct pt_regs, ARM_r8)); + DEFINE(S_R9, offsetof(struct pt_regs, ARM_r9)); + DEFINE(S_R10, offsetof(struct pt_regs, ARM_r10)); + DEFINE(S_FP, offsetof(struct pt_regs, ARM_fp)); + DEFINE(S_IP, offsetof(struct pt_regs, ARM_ip)); + DEFINE(S_SP, offsetof(struct pt_regs, ARM_sp)); + DEFINE(S_LR, offsetof(struct pt_regs, ARM_lr)); + DEFINE(S_PC, offsetof(struct pt_regs, ARM_pc)); + DEFINE(S_PSR, offsetof(struct pt_regs, ARM_cpsr)); + DEFINE(S_OLD_R0, offsetof(struct pt_regs, ARM_ORIG_r0)); + DEFINE(S_FRAME_SIZE, sizeof(struct pt_regs)); + BLANK(); #if __LINUX_ARM_ARCH__ >= 6 DEFINE(MM_CONTEXT_ID, offsetof(struct mm_struct, context.id)); BLANK(); @@ -73,7 +94,7 @@ int main(void) DEFINE(VM_EXEC, VM_EXEC); BLANK(); DEFINE(PAGE_SZ, PAGE_SIZE); - DEFINE(VIRT_OFFSET, PAGE_OFFSET); + DEFINE(VIRT_OFFSET, PAGE_OFFSET); BLANK(); DEFINE(SYS_ERROR0, 0x9f0000); BLANK(); diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index e5d370c23..cb7c3062c 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S @@ -295,7 +295,6 @@ __syscall_start: .long sys_mq_notify .long sys_mq_getsetattr /* 280 */ .long sys_waitid - .long sys_socket .long sys_bind .long sys_connect .long sys_listen @@ -327,6 +326,7 @@ __syscall_start: /* 310 */ .long sys_request_key .long sys_keyctl .long sys_semtimedop + .long sys_vserver __syscall_end: .rept NR_syscalls - (__syscall_end - __syscall_start) / 4 diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S index 78146b6c3..caaa919ab 100644 --- a/arch/arm/kernel/debug.S +++ b/arch/arm/kernel/debug.S @@ -1,5 +1,5 @@ /* - * linux/arch/arm/kernel/debug-armv.S + * linux/arch/arm/kernel/debug.S * * Copyright (C) 1994-1999 Russell King * @@ -20,31 +20,8 @@ * printk isn't working). For DEBUGGING ONLY!!! Do not leave * references to these in a production kernel! */ -#if defined(CONFIG_ARCH_RPC) - .macro addruart,rx - mov \rx, #0xe0000000 - orr \rx, \rx, #0x00010000 - orr \rx, \rx, #0x00000fe0 - .endm - - .macro senduart,rd,rx - strb \rd, [\rx] - .endm - - .macro busyuart,rd,rx -1001: ldrb \rd, [\rx, #0x14] - and \rd, \rd, #0x60 - teq \rd, #0x60 - bne 1001b - .endm - - .macro waituart,rd,rx -1001: ldrb \rd, [\rx, #0x18] - tst \rd, #0x10 - beq 1001b - .endm -#elif defined(CONFIG_DEBUG_ICEDCC) +#if defined(CONFIG_DEBUG_ICEDCC) @@ debug using ARM EmbeddedICE DCC channel .macro addruart, rx .endm @@ -71,666 +48,8 @@ bne 1001b 1002: .endm - -#elif defined(CONFIG_ARCH_EBSA110) - .macro addruart,rx - mov \rx, #0xf0000000 - orr \rx, \rx, #0x00000be0 - .endm - - .macro senduart,rd,rx - strb \rd, [\rx] - .endm - - .macro busyuart,rd,rx -1002: ldrb \rd, [\rx, #0x14] - and \rd, \rd, #0x60 - teq \rd, #0x60 - bne 1002b - .endm - - .macro waituart,rd,rx -1001: ldrb \rd, [\rx, #0x18] - tst \rd, #0x10 - beq 1001b - .endm - -#elif defined(CONFIG_ARCH_SHARK) - .macro addruart,rx - mov \rx, #0xe0000000 - orr \rx, \rx, #0x000003f8 - .endm - - .macro senduart,rd,rx - strb \rd, [\rx] - .endm - - .macro busyuart,rd,rx - mov \rd, #0 -1001: add \rd, \rd, #1 - teq \rd, #0x10000 - bne 1001b - .endm - - .macro waituart,rd,rx - .endm - -#elif defined(CONFIG_FOOTBRIDGE) - -#include - -#ifndef CONFIG_DEBUG_DC21285_PORT - /* For NetWinder debugging */ - .macro addruart,rx - mrc p15, 0, \rx, c1, c0 - tst \rx, #1 @ MMU enabled? - moveq \rx, #0x7c000000 @ physical - movne \rx, #0xff000000 @ virtual - orr \rx, \rx, #0x000003f8 - .endm - - .macro senduart,rd,rx - strb \rd, [\rx] - .endm - - .macro busyuart,rd,rx -1002: ldrb \rd, [\rx, #0x5] - and \rd, \rd, #0x60 - teq \rd, #0x60 - bne 1002b - .endm - - .macro waituart,rd,rx -1001: ldrb \rd, [\rx, #0x6] - tst \rd, #0x10 - beq 1001b - .endm -#else - /* For EBSA285 debugging */ - .equ dc21285_high, ARMCSR_BASE & 0xff000000 - .equ dc21285_low, ARMCSR_BASE & 0x00ffffff - - .macro addruart,rx - mov \rx, #dc21285_high - .if dc21285_low - orr \rx, \rx, #dc21285_low - .endif - .endm - - .macro senduart,rd,rx - str \rd, [\rx, #0x160] @ UARTDR - .endm - - .macro busyuart,rd,rx -1001: ldr \rd, [\rx, #0x178] @ UARTFLG - tst \rd, #1 << 3 - bne 1001b - .endm - - .macro waituart,rd,rx - .endm -#endif -#elif defined(CONFIG_ARCH_FTVPCI) - .macro addruart,rx - mrc p15, 0, \rx, c1, c0 - tst \rx, #1 @ MMU enabled? - movne \rx, #0xe0000000 - moveq \rx, #0x10000000 - .endm - - .macro senduart,rd,rx - str \rd, [\rx, #0xc] - .endm - - .macro busyuart,rd,rx -1001: ldr \rd, [\rx, #0x4] - tst \rd, #1 << 2 - beq 1001b - .endm - - .macro waituart,rd,rx - .endm - -#elif defined(CONFIG_ARCH_SA1100) - - .macro addruart,rx - mrc p15, 0, \rx, c1, c0 - tst \rx, #1 @ MMU enabled? - moveq \rx, #0x80000000 @ physical base address - movne \rx, #0xf8000000 @ virtual address - - @ We probe for the active serial port here, coherently with - @ the comment in include/asm-arm/arch-sa1100/uncompress.h. - @ We assume r1 can be clobbered. - - @ see if Ser3 is active - add \rx, \rx, #0x00050000 - ldr r1, [\rx, #UTCR3] - tst r1, #UTCR3_TXE - - @ if Ser3 is inactive, then try Ser1 - addeq \rx, \rx, #(0x00010000 - 0x00050000) - ldreq r1, [\rx, #UTCR3] - tsteq r1, #UTCR3_TXE - - @ if Ser1 is inactive, then try Ser2 - addeq \rx, \rx, #(0x00030000 - 0x00010000) - ldreq r1, [\rx, #UTCR3] - tsteq r1, #UTCR3_TXE - - @ if all ports are inactive, then there is nothing we can do - moveq pc, lr - .endm - - .macro senduart,rd,rx - str \rd, [\rx, #UTDR] - .endm - - .macro waituart,rd,rx -1001: ldr \rd, [\rx, #UTSR1] - tst \rd, #UTSR1_TNF - beq 1001b - .endm - - .macro busyuart,rd,rx -1001: ldr \rd, [\rx, #UTSR1] - tst \rd, #UTSR1_TBY - bne 1001b - .endm - -#elif defined(CONFIG_ARCH_PXA) - - .macro addruart,rx - mrc p15, 0, \rx, c1, c0 - tst \rx, #1 @ MMU enabled? - moveq \rx, #0x40000000 @ physical - movne \rx, #io_p2v(0x40000000) @ virtual - orr \rx, \rx, #0x00100000 - .endm - - .macro senduart,rd,rx - str \rd, [\rx, #0] - .endm - - .macro busyuart,rd,rx -1002: ldr \rd, [\rx, #0x14] - tst \rd, #(1 << 6) - beq 1002b - .endm - - .macro waituart,rd,rx -1001: ldr \rd, [\rx, #0x14] - tst \rd, #(1 << 5) - beq 1001b - .endm -#elif defined(CONFIG_ARCH_CLPS7500) - .macro addruart,rx - mov \rx, #0xe0000000 - orr \rx, \rx, #0x00010000 - orr \rx, \rx, #0x00000be0 - .endm - - .macro senduart,rd,rx - strb \rd, [\rx] - .endm - - .macro busyuart,rd,rx - .endm - - .macro waituart,rd,rx -1001: ldrb \rd, [\rx, #0x14] - tst \rd, #0x20 - beq 1001b - .endm - -#elif defined(CONFIG_ARCH_L7200) - - .equ io_virt, IO_BASE - .equ io_phys, IO_START - - .macro addruart,rx - mrc p15, 0, \rx, c1, c0 - tst \rx, #1 @ MMU enabled? - moveq \rx, #io_phys @ physical base address - movne \rx, #io_virt @ virtual address - add \rx, \rx, #0x00044000 @ UART1 -@ add \rx, \rx, #0x00045000 @ UART2 - .endm - - .macro senduart,rd,rx - str \rd, [\rx, #0x0] @ UARTDR - .endm - - .macro waituart,rd,rx -1001: ldr \rd, [\rx, #0x18] @ UARTFLG - tst \rd, #1 << 5 @ UARTFLGUTXFF - 1 when full - bne 1001b - .endm - - .macro busyuart,rd,rx -1001: ldr \rd, [\rx, #0x18] @ UARTFLG - tst \rd, #1 << 3 @ UARTFLGUBUSY - 1 when busy - bne 1001b - .endm - -#elif defined(CONFIG_ARCH_INTEGRATOR) - -#include - - .macro addruart,rx - mrc p15, 0, \rx, c1, c0 - tst \rx, #1 @ MMU enabled? - moveq \rx, #0x16000000 @ physical base address - movne \rx, #0xf0000000 @ virtual base - addne \rx, \rx, #0x16000000 >> 4 - .endm - - .macro senduart,rd,rx - strb \rd, [\rx, #UART01x_DR] - .endm - - .macro waituart,rd,rx -1001: ldr \rd, [\rx, #0x18] @ UARTFLG - tst \rd, #1 << 5 @ UARTFLGUTXFF - 1 when full - bne 1001b - .endm - - .macro busyuart,rd,rx -1001: ldr \rd, [\rx, #0x18] @ UARTFLG - tst \rd, #1 << 3 @ UARTFLGUBUSY - 1 when busy - bne 1001b - .endm - -#elif defined(CONFIG_ARCH_CLPS711X) - -#include - - .macro addruart,rx - mrc p15, 0, \rx, c1, c0 - tst \rx, #1 @ MMU enabled? - moveq \rx, #CLPS7111_PHYS_BASE - movne \rx, #CLPS7111_VIRT_BASE -#ifndef CONFIG_DEBUG_CLPS711X_UART2 - add \rx, \rx, #0x0000 @ UART1 -#else - add \rx, \rx, #0x1000 @ UART2 -#endif - .endm - - .macro senduart,rd,rx - str \rd, [\rx, #0x0480] @ UARTDR - .endm - - .macro waituart,rd,rx -1001: ldr \rd, [\rx, #0x0140] @ SYSFLGx - tst \rd, #1 << 11 @ UBUSYx - bne 1001b - .endm - - .macro busyuart,rd,rx - tst \rx, #0x1000 @ UART2 does not have CTS here - bne 1002f -1001: ldr \rd, [\rx, #0x0140] @ SYSFLGx - tst \rd, #1 << 8 @ CTS - bne 1001b -1002: - .endm - -#elif defined(CONFIG_ARCH_CAMELOT) - -#include -#define UART00_TYPE -#include - - .macro addruart,rx - mrc p15, 0, \rx, c1, c0 - tst \rx, #1 @ MMU enabled? - ldr \rx, =EXC_UART00_BASE @ physical base address - orrne \rx, \rx, #0xff000000 @ virtual base - orrne \rx, \rx, #0x00f00000 - .endm - - .macro senduart,rd,rx - str \rd, [\rx, #UART_TD(0)] - .endm - - .macro waituart,rd,rx -1001: ldr \rd, [\rx, #UART_TSR(0)] - and \rd, \rd, #UART_TSR_TX_LEVEL_MSK - cmp \rd, #15 - beq 1001b - .endm - - .macro busyuart,rd,rx -1001: ldr \rd, [\rx, #UART_TSR(0)] - ands \rd, \rd, #UART_TSR_TX_LEVEL_MSK - bne 1001b - .endm - -#elif defined(CONFIG_ARCH_IOP3XX) - - .macro addruart,rx - mov \rx, #0xfe000000 @ physical -#if defined(CONFIG_ARCH_IQ80321) || defined(CONFIG_ARCH_IQ31244) - orr \rx, \rx, #0x00800000 @ location of the UART -#elif defined(CONFIG_ARCH_IOP331) - mrc p15, 0, \rx, c1, c0 - tst \rx, #1 @ MMU enabled? - moveq \rx, #0x000fe000 @ Physical Base - movne \rx, #0 - orr \rx, \rx, #0xfe000000 - orr \rx, \rx, #0x00f00000 @ Virtual Base - orr \rx, \rx, #0x00001700 @ location of the UART -#else -#error Unknown IOP3XX implementation -#endif - .endm - - .macro senduart,rd,rx - strb \rd, [\rx] - .endm - - .macro busyuart,rd,rx -1002: ldrb \rd, [\rx, #0x5] - and \rd, \rd, #0x60 - teq \rd, #0x60 - bne 1002b - .endm - - .macro waituart,rd,rx -#if !defined(CONFIG_ARCH_IQ80321) || !defined(CONFIG_ARCH_IQ31244) || !defined(CONFIG_ARCH_IQ80331) -1001: ldrb \rd, [\rx, #0x6] - tst \rd, #0x10 - beq 1001b -#endif - .endm - -#elif defined(CONFIG_ARCH_IXP4XX) - - .macro addruart,rx - mrc p15, 0, \rx, c1, c0 - tst \rx, #1 @ MMU enabled? - moveq \rx, #0xc8000000 - movne \rx, #0xff000000 - add \rx,\rx,#3 @ Uart regs are at off set of 3 if - @ byte writes used - Big Endian. - .endm - - .macro senduart,rd,rx - strb \rd, [\rx] - .endm - - .macro waituart,rd,rx -1002: ldrb \rd, [\rx, #0x14] - and \rd, \rd, #0x60 @ check THRE and TEMT bits - teq \rd, #0x60 - bne 1002b - .endm - - .macro busyuart,rd,rx - .endm - -#elif defined(CONFIG_ARCH_IXP2000) - - .macro addruart,rx - mrc p15, 0, \rx, c1, c0 - tst \rx, #1 @ MMU enabled? - moveq \rx, #0xc0000000 @ Physical base - movne \rx, #0xfe000000 @ virtual base - orrne \rx, \rx, #0x00f00000 - orr \rx, \rx, #0x00030000 -#ifdef __ARMEB__ - orr \rx, \rx, #0x00000003 -#endif - .endm - - .macro senduart,rd,rx - strb \rd, [\rx] - .endm - - .macro busyuart,rd,rx -1002: ldrb \rd, [\rx, #0x14] - tst \rd, #0x20 - beq 1002b - .endm - - .macro waituart,rd,rx - nop - nop - nop - .endm - -#elif defined(CONFIG_ARCH_OMAP) - - .macro addruart,rx - mrc p15, 0, \rx, c1, c0 - tst \rx, #1 @ MMU enabled? - moveq \rx, #0xff000000 @ physical base address - movne \rx, #0xfe000000 @ virtual base - orr \rx, \rx, #0x00fb0000 -#ifdef CONFIG_OMAP_LL_DEBUG_UART3 - orr \rx, \rx, #0x00009000 @ UART 3 -#endif -#if defined(CONFIG_OMAP_LL_DEBUG_UART2) || defined(CONFIG_OMAP_LL_DEBUG_UART3) - orr \rx, \rx, #0x00000800 @ UART 2 & 3 -#endif - .endm - - .macro senduart,rd,rx - strb \rd, [\rx] - .endm - - .macro busyuart,rd,rx -1001: ldrb \rd, [\rx, #(0x5 << 2)] @ OMAP-1510 and friends - and \rd, \rd, #0x60 - teq \rd, #0x60 - beq 1002f - ldrb \rd, [\rx, #(0x5 << 0)] @ OMAP-730 only - and \rd, \rd, #0x60 - teq \rd, #0x60 - bne 1001b -1002: - .endm - - .macro waituart,rd,rx - .endm - -#elif defined(CONFIG_ARCH_S3C2410) -#include -#include -#include -#define S3C2410_UART1_OFF (0x4000) -#define SHIFT_2440TXF (14-9) - - .macro addruart, rx - mrc p15, 0, \rx, c1, c0 - tst \rx, #1 - ldreq \rx, = S3C2410_PA_UART - ldrne \rx, = S3C2410_VA_UART -#if CONFIG_DEBUG_S3C2410_UART != 0 - add \rx, \rx, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C2410_UART) -#endif - .endm - - .macro senduart,rd,rx - str \rd, [\rx, # S3C2410_UTXH ] - .endm - - .macro busyuart, rd, rx - ldr \rd, [ \rx, # S3C2410_UFCON ] - tst \rd, #S3C2410_UFCON_FIFOMODE @ fifo enabled? - beq 1001f @ - @ FIFO enabled... -1003: - mrc p15, 0, \rd, c1, c0 - tst \rd, #1 - addeq \rd, \rx, #(S3C2410_PA_GPIO - S3C2410_PA_UART) - addne \rd, \rx, #(S3C2410_VA_GPIO - S3C2410_VA_UART) - bic \rd, \rd, #0xff000 - ldr \rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ] - and \rd, \rd, #0x00ff0000 - teq \rd, #0x00440000 @ is it 2440? - - ldr \rd, [ \rx, # S3C2410_UFSTAT ] - moveq \rd, \rd, lsr #SHIFT_2440TXF - tst \rd, #S3C2410_UFSTAT_TXFULL - bne 1003b - b 1002f - -1001: - @ busy waiting for non fifo - ldr \rd, [ \rx, # S3C2410_UTRSTAT ] - tst \rd, #S3C2410_UTRSTAT_TXFE - beq 1001b - -1002: @ exit busyuart - .endm - - .macro waituart,rd,rx - - ldr \rd, [ \rx, # S3C2410_UFCON ] - tst \rd, #S3C2410_UFCON_FIFOMODE @ fifo enabled? - beq 1001f @ - @ FIFO enabled... -1003: - mrc p15, 0, \rd, c1, c0 - tst \rd, #1 - addeq \rd, \rx, #(S3C2410_PA_GPIO - S3C2410_PA_UART) - addne \rd, \rx, #(S3C2410_VA_GPIO - S3C2410_VA_UART) - bic \rd, \rd, #0xff000 - ldr \rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ] - and \rd, \rd, #0x00ff0000 - teq \rd, #0x00440000 @ is it 2440? - - ldr \rd, [ \rx, # S3C2410_UFSTAT ] - andne \rd, \rd, #S3C2410_UFSTAT_TXMASK - andeq \rd, \rd, #S3C2440_UFSTAT_TXMASK - teq \rd, #0 - bne 1003b - b 1002f - -1001: - @ idle waiting for non fifo - ldr \rd, [ \rx, # S3C2410_UTRSTAT ] - tst \rd, #S3C2410_UTRSTAT_TXFE - beq 1001b - -1002: @ exit busyuart - .endm - -#elif defined(CONFIG_ARCH_LH7A40X) - @ It is not known if this will be appropriate for every 40x - @ board. - - .macro addruart,rx - mrc p15, 0, \rx, c1, c0 - tst \rx, #1 @ MMU enabled? - mov \rx, #0x00000700 @ offset from base - orreq \rx, \rx, #0x80000000 @ physical base - orrne \rx, \rx, #0xf8000000 @ virtual base - .endm - - .macro senduart,rd,rx - strb \rd, [\rx] @ DATA - .endm - - .macro busyuart,rd,rx @ spin while busy -1001: ldr \rd, [\rx, #0x10] @ STATUS - tst \rd, #1 << 3 @ BUSY (TX FIFO not empty) - bne 1001b @ yes, spin - .endm - - .macro waituart,rd,rx @ wait for Tx FIFO room -1001: ldrb \rd, [\rx, #0x10] @ STATUS - tst \rd, #1 << 5 @ TXFF (TX FIFO full) - bne 1001b @ yes, spin - .endm - - -#elif defined(CONFIG_ARCH_VERSATILE) - -#include - - .macro addruart,rx - mrc p15, 0, \rx, c1, c0 - tst \rx, #1 @ MMU enabled? - moveq \rx, #0x10000000 - movne \rx, #0xf1000000 @ virtual base - orr \rx, \rx, #0x001F0000 - orr \rx, \rx, #0x00001000 - .endm - - .macro senduart,rd,rx - strb \rd, [\rx, #UART01x_DR] - .endm - - .macro waituart,rd,rx -1001: ldr \rd, [\rx, #0x18] @ UARTFLG - tst \rd, #1 << 5 @ UARTFLGUTXFF - 1 when full - bne 1001b - .endm - - .macro busyuart,rd,rx -1001: ldr \rd, [\rx, #0x18] @ UARTFLG - tst \rd, #1 << 3 @ UARTFLGUBUSY - 1 when busy - bne 1001b - .endm - -#elif defined(CONFIG_ARCH_IMX) - - .macro addruart,rx - mrc p15, 0, \rx, c1, c0 - tst \rx, #1 @ MMU enabled? - moveq \rx, #0x00000000 @ physical - movne \rx, #0xe0000000 @ virtual - orr \rx, \rx, #0x00200000 - orr \rx, \rx, #0x00006000 @ UART1 offset - .endm - - .macro senduart,rd,rx - str \rd, [\rx, #0x40] @ TXDATA - .endm - - .macro waituart,rd,rx - .endm - - .macro busyuart,rd,rx -1002: ldr \rd, [\rx, #0x98] @ SR2 - tst \rd, #1 << 3 @ TXDC - beq 1002b @ wait until transmit done - .endm - -#elif defined(CONFIG_ARCH_H720X) - - .equ io_virt, IO_BASE - .equ io_phys, IO_START - - .macro addruart,rx - mrc p15, 0, \rx, c1, c0 - tst \rx, #1 @ MMU enabled? - moveq \rx, #io_phys @ physical base address - movne \rx, #io_virt @ virtual address - add \rx, \rx, #0x00020000 @ UART1 - .endm - - .macro senduart,rd,rx - str \rd, [\rx, #0x0] @ UARTDR - - .endm - - .macro waituart,rd,rx -1001: ldr \rd, [\rx, #0x18] @ UARTFLG - tst \rd, #1 << 5 @ UARTFLGUTXFF - 1 when full - bne 1001b - .endm - - .macro busyuart,rd,rx -1001: ldr \rd, [\rx, #0x18] @ UARTFLG - tst \rd, #1 << 3 @ UARTFLGUBUSY - 1 when busy - bne 1001b - .endm #else -#error Unknown architecture +#include #endif /* diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c index 3f6b4b529..3dc15b131 100644 --- a/arch/arm/kernel/ecard.c +++ b/arch/arm/kernel/ecard.c @@ -85,27 +85,21 @@ static struct expcard_blacklist __initdata blacklist[] = { }; asmlinkage extern int -ecard_loader_reset(volatile unsigned char *pa, loader_t loader); +ecard_loader_reset(unsigned long base, loader_t loader); asmlinkage extern int -ecard_loader_read(int off, volatile unsigned char *pa, loader_t loader); +ecard_loader_read(int off, unsigned long base, loader_t loader); -static const struct ecard_id * -ecard_match_device(const struct ecard_id *ids, struct expansion_card *ec); - -static inline unsigned short -ecard_getu16(unsigned char *v) +static inline unsigned short ecard_getu16(unsigned char *v) { return v[0] | v[1] << 8; } -static inline signed long -ecard_gets24(unsigned char *v) +static inline signed long ecard_gets24(unsigned char *v) { return v[0] | v[1] << 8 | v[2] << 16 | ((v[2] & 0x80) ? 0xff000000 : 0); } -static inline ecard_t * -slot_to_ecard(unsigned int slot) +static inline ecard_t *slot_to_ecard(unsigned int slot) { return slot < MAX_ECARDS ? slot_to_expcard[slot] : NULL; } @@ -122,26 +116,31 @@ slot_to_ecard(unsigned int slot) * From a security standpoint, we trust the card vendors. This * may be a misplaced trust. */ -#define BUS_ADDR(x) ((((unsigned long)(x)) << 2) + IO_BASE) -#define POD_INT_ADDR(x) ((volatile unsigned char *)\ - ((BUS_ADDR((x)) - IO_BASE) + IO_START)) - static void ecard_task_reset(struct ecard_request *req) { struct expansion_card *ec = req->ec; - if (ec->loader) - ecard_loader_reset(POD_INT_ADDR(ec->podaddr), ec->loader); + struct resource *res; + + res = ec->slot_no == 8 + ? &ec->resource[ECARD_RES_MEMC] + : ec->type == ECARD_EASI + ? &ec->resource[ECARD_RES_EASI] + : &ec->resource[ECARD_RES_IOCSYNC]; + + ecard_loader_reset(res->start, ec->loader); } static void ecard_task_readbytes(struct ecard_request *req) { - unsigned char *buf = (unsigned char *)req->buffer; - volatile unsigned char *base_addr = - (volatile unsigned char *)POD_INT_ADDR(req->ec->podaddr); + struct expansion_card *ec = req->ec; + unsigned char *buf = req->buffer; unsigned int len = req->length; unsigned int off = req->address; - if (req->ec->slot_no == 8) { + if (ec->slot_no == 8) { + void __iomem *base = (void __iomem *) + ec->resource[ECARD_RES_MEMC].start; + /* * The card maintains an index which increments the address * into a 4096-byte page on each access. We need to keep @@ -161,7 +160,7 @@ static void ecard_task_readbytes(struct ecard_request *req) * greater than the offset, reset the hardware index counter. */ if (off == 0 || index > off) { - *base_addr = 0; + writeb(0, base); index = 0; } @@ -170,21 +169,24 @@ static void ecard_task_readbytes(struct ecard_request *req) * required offset. The read bytes are discarded. */ while (index < off) { - unsigned char byte; - byte = base_addr[page]; + readb(base + page); index += 1; } while (len--) { - *buf++ = base_addr[page]; + *buf++ = readb(base + page); index += 1; } } else { + unsigned long base = (ec->type == ECARD_EASI + ? &ec->resource[ECARD_RES_EASI] + : &ec->resource[ECARD_RES_IOCSYNC])->start; + void __iomem *pbase = (void __iomem *)base; - if (!req->use_loader || !req->ec->loader) { + if (!req->use_loader || !ec->loader) { off *= 4; while (len--) { - *buf++ = base_addr[off]; + *buf++ = readb(pbase + off); off += 4; } } else { @@ -194,8 +196,8 @@ static void ecard_task_readbytes(struct ecard_request *req) * expansion card loader programs. */ *(unsigned long *)0x108 = 0; - *buf++ = ecard_loader_read(off++, base_addr, - req->ec->loader); + *buf++ = ecard_loader_read(off++, base, + ec->loader); } } } @@ -226,7 +228,7 @@ static void ecard_init_pgtables(struct mm_struct *mm) */ pgd_t *src_pgd, *dst_pgd; - src_pgd = pgd_offset(mm, IO_BASE); + src_pgd = pgd_offset(mm, (unsigned long)IO_BASE); dst_pgd = pgd_offset(mm, IO_START); memcpy(dst_pgd, src_pgd, sizeof(pgd_t) * (IO_SIZE / PGDIR_SIZE)); @@ -406,7 +408,7 @@ static void ecard_def_irq_disable(ecard_t *ec, int irqnr) static int ecard_def_irq_pending(ecard_t *ec) { - return !ec->irqmask || ec->irqaddr[0] & ec->irqmask; + return !ec->irqmask || readb(ec->irqaddr) & ec->irqmask; } static void ecard_def_fiq_enable(ecard_t *ec, int fiqnr) @@ -421,7 +423,7 @@ static void ecard_def_fiq_disable(ecard_t *ec, int fiqnr) static int ecard_def_fiq_pending(ecard_t *ec) { - return !ec->fiqmask || ec->fiqaddr[0] & ec->fiqmask; + return !ec->fiqmask || readb(ec->fiqaddr) & ec->fiqmask; } static expansioncard_ops_t ecard_default_ops = { @@ -522,7 +524,7 @@ static void ecard_dump_irq_state(void) ec->ops->irqpending(ec) ? "" : "not "); else printk("irqaddr %p, mask = %02X, status = %02X\n", - ec->irqaddr, ec->irqmask, *ec->irqaddr); + ec->irqaddr, ec->irqmask, readb(ec->irqaddr)); } } @@ -675,7 +677,7 @@ static int __init ecard_probeirqhw(void) #define IO_EC_MEMC8_BASE 0 #endif -unsigned int ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed) +unsigned int __ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed) { unsigned long address = 0; int slot = ec->slot_no; @@ -779,55 +781,89 @@ static void ecard_proc_init(void) get_ecard_dev_info); } -#define ec_set_resource(ec,nr,st,sz,flg) \ +#define ec_set_resource(ec,nr,st,sz) \ do { \ (ec)->resource[nr].name = ec->dev.bus_id; \ (ec)->resource[nr].start = st; \ (ec)->resource[nr].end = (st) + (sz) - 1; \ - (ec)->resource[nr].flags = flg; \ + (ec)->resource[nr].flags = IORESOURCE_MEM; \ } while (0) -static void __init ecard_init_resources(struct expansion_card *ec) +static void __init ecard_free_card(struct expansion_card *ec) +{ + int i; + + for (i = 0; i < ECARD_NUM_RESOURCES; i++) + if (ec->resource[i].flags) + release_resource(&ec->resource[i]); + + kfree(ec); +} + +static struct expansion_card *__init ecard_alloc_card(int type, int slot) { - unsigned long base = PODSLOT_IOC4_BASE; - unsigned int slot = ec->slot_no; + struct expansion_card *ec; + unsigned long base; int i; + ec = kmalloc(sizeof(ecard_t), GFP_KERNEL); + if (!ec) { + ec = ERR_PTR(-ENOMEM); + goto nomem; + } + + memset(ec, 0, sizeof(ecard_t)); + + ec->slot_no = slot; + ec->type = type; + ec->irq = NO_IRQ; + ec->fiq = NO_IRQ; + ec->dma = NO_DMA; + ec->ops = &ecard_default_ops; + + snprintf(ec->dev.bus_id, sizeof(ec->dev.bus_id), "ecard%d", slot); + ec->dev.parent = NULL; + ec->dev.bus = &ecard_bus_type; + ec->dev.dma_mask = &ec->dma_mask; + ec->dma_mask = (u64)0xffffffff; + if (slot < 4) { ec_set_resource(ec, ECARD_RES_MEMC, PODSLOT_MEMC_BASE + (slot << 14), - PODSLOT_MEMC_SIZE, IORESOURCE_MEM); - base = PODSLOT_IOC0_BASE; - } + PODSLOT_MEMC_SIZE); + base = PODSLOT_IOC0_BASE + (slot << 14); + } else + base = PODSLOT_IOC4_BASE + ((slot - 4) << 14); #ifdef CONFIG_ARCH_RPC if (slot < 8) { ec_set_resource(ec, ECARD_RES_EASI, PODSLOT_EASI_BASE + (slot << 24), - PODSLOT_EASI_SIZE, IORESOURCE_MEM); + PODSLOT_EASI_SIZE); } if (slot == 8) { - ec_set_resource(ec, ECARD_RES_MEMC, NETSLOT_BASE, - NETSLOT_SIZE, IORESOURCE_MEM); + ec_set_resource(ec, ECARD_RES_MEMC, NETSLOT_BASE, NETSLOT_SIZE); } else #endif - for (i = 0; i <= ECARD_RES_IOCSYNC - ECARD_RES_IOCSLOW; i++) { + for (i = 0; i <= ECARD_RES_IOCSYNC - ECARD_RES_IOCSLOW; i++) ec_set_resource(ec, i + ECARD_RES_IOCSLOW, - base + (slot << 14) + (i << 19), - PODSLOT_IOC_SIZE, IORESOURCE_MEM); - } + base + (i << 19), PODSLOT_IOC_SIZE); for (i = 0; i < ECARD_NUM_RESOURCES; i++) { - if (ec->resource[i].start && + if (ec->resource[i].flags && request_resource(&iomem_resource, &ec->resource[i])) { printk(KERN_ERR "%s: resource(s) not available\n", ec->dev.bus_id); ec->resource[i].end -= ec->resource[i].start; ec->resource[i].start = 0; + ec->resource[i].flags = 0; } } + + nomem: + return ec; } static ssize_t ecard_show_irq(struct device *dev, char *buf) @@ -836,16 +872,12 @@ static ssize_t ecard_show_irq(struct device *dev, char *buf) return sprintf(buf, "%u\n", ec->irq); } -static DEVICE_ATTR(irq, S_IRUGO, ecard_show_irq, NULL); - static ssize_t ecard_show_dma(struct device *dev, char *buf) { struct expansion_card *ec = ECARD_DEV(dev); return sprintf(buf, "%u\n", ec->dma); } -static DEVICE_ATTR(dma, S_IRUGO, ecard_show_dma, NULL); - static ssize_t ecard_show_resources(struct device *dev, char *buf) { struct expansion_card *ec = ECARD_DEV(dev); @@ -861,23 +893,33 @@ static ssize_t ecard_show_resources(struct device *dev, char *buf) return str - buf; } -static DEVICE_ATTR(resource, S_IRUGO, ecard_show_resources, NULL); - static ssize_t ecard_show_vendor(struct device *dev, char *buf) { struct expansion_card *ec = ECARD_DEV(dev); return sprintf(buf, "%u\n", ec->cid.manufacturer); } -static DEVICE_ATTR(vendor, S_IRUGO, ecard_show_vendor, NULL); - static ssize_t ecard_show_device(struct device *dev, char *buf) { struct expansion_card *ec = ECARD_DEV(dev); return sprintf(buf, "%u\n", ec->cid.product); } -static DEVICE_ATTR(device, S_IRUGO, ecard_show_device, NULL); +static ssize_t ecard_show_type(struct device *dev, char *buf) +{ + struct expansion_card *ec = ECARD_DEV(dev); + return sprintf(buf, "%s\n", ec->type == ECARD_EASI ? "EASI" : "IOC"); +} + +static struct device_attribute ecard_dev_attrs[] = { + __ATTR(device, S_IRUGO, ecard_show_device, NULL), + __ATTR(dma, S_IRUGO, ecard_show_dma, NULL), + __ATTR(irq, S_IRUGO, ecard_show_irq, NULL), + __ATTR(resource, S_IRUGO, ecard_show_resources, NULL), + __ATTR(type, S_IRUGO, ecard_show_type, NULL), + __ATTR(vendor, S_IRUGO, ecard_show_vendor, NULL), + __ATTR_NULL, +}; int ecard_request_resources(struct expansion_card *ec) @@ -927,21 +969,13 @@ ecard_probe(int slot, card_type_t type) ecard_t **ecp; ecard_t *ec; struct ex_ecid cid; - int i, rc = -ENOMEM; + int i, rc; - ec = kmalloc(sizeof(ecard_t), GFP_KERNEL); - if (!ec) + ec = ecard_alloc_card(type, slot); + if (IS_ERR(ec)) { + rc = PTR_ERR(ec); goto nomem; - - memset(ec, 0, sizeof(ecard_t)); - - ec->slot_no = slot; - ec->type = type; - ec->irq = NO_IRQ; - ec->fiq = NO_IRQ; - ec->dma = NO_DMA; - ec->card_desc = NULL; - ec->ops = &ecard_default_ops; + } rc = -ENODEV; if ((ec->podaddr = ecard_address(ec, type, ECARD_SYNC)) == 0) @@ -964,7 +998,7 @@ ecard_probe(int slot, card_type_t type) ec->cid.fiqmask = cid.r_fiqmask; ec->cid.fiqoff = ecard_gets24(cid.r_fiqoff); ec->fiqaddr = - ec->irqaddr = (unsigned char *)ioaddr(ec->podaddr); + ec->irqaddr = (void __iomem *)ioaddr(ec->podaddr); if (ec->cid.is) { ec->irqmask = ec->cid.irqmask; @@ -983,14 +1017,6 @@ ecard_probe(int slot, card_type_t type) break; } - snprintf(ec->dev.bus_id, sizeof(ec->dev.bus_id), "ecard%d", slot); - ec->dev.parent = NULL; - ec->dev.bus = &ecard_bus_type; - ec->dev.dma_mask = &ec->dma_mask; - ec->dma_mask = (u64)0xffffffff; - - ecard_init_resources(ec); - /* * hook the interrupt handlers */ @@ -1017,17 +1043,12 @@ ecard_probe(int slot, card_type_t type) slot_to_expcard[slot] = ec; device_register(&ec->dev); - device_create_file(&ec->dev, &dev_attr_dma); - device_create_file(&ec->dev, &dev_attr_irq); - device_create_file(&ec->dev, &dev_attr_resource); - device_create_file(&ec->dev, &dev_attr_vendor); - device_create_file(&ec->dev, &dev_attr_device); return 0; -nodev: - kfree(ec); -nomem: + nodev: + ecard_free_card(ec); + nomem: return rc; } @@ -1128,9 +1149,15 @@ static void ecard_drv_shutdown(struct device *dev) if (drv->shutdown) drv->shutdown(ec); ecard_release(ec); - req.fn = ecard_task_reset; - req.ec = ec; - ecard_call(&req); + + /* + * If this card has a loader, call the reset handler. + */ + if (ec->loader) { + req.fn = ecard_task_reset; + req.ec = ec; + ecard_call(&req); + } } int ecard_register_driver(struct ecard_driver *drv) @@ -1164,8 +1191,9 @@ static int ecard_match(struct device *_dev, struct device_driver *_drv) } struct bus_type ecard_bus_type = { - .name = "ecard", - .match = ecard_match, + .name = "ecard", + .dev_attrs = ecard_dev_attrs, + .match = ecard_match, }; static int ecard_bus_init(void) @@ -1176,7 +1204,7 @@ static int ecard_bus_init(void) postcore_initcall(ecard_bus_init); EXPORT_SYMBOL(ecard_readchunk); -EXPORT_SYMBOL(ecard_address); +EXPORT_SYMBOL(__ecard_address); EXPORT_SYMBOL(ecard_register_driver); EXPORT_SYMBOL(ecard_remove_driver); EXPORT_SYMBOL(ecard_bus_type); diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 44cd34784..e14278d59 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -14,1282 +14,383 @@ * it to save wrong values... Be aware! */ #include -#include -#include #include -#include #include +#include /* should be moved into entry-macro.S */ +#include /* should be moved into entry-macro.S */ +#include #include "entry-header.S" -#ifdef IOC_BASE -/* IOC / IOMD based hardware */ -#include - - .equ ioc_base_high, IOC_BASE & 0xff000000 - .equ ioc_base_low, IOC_BASE & 0x00ff0000 - .macro disable_fiq - mov r12, #ioc_base_high - .if ioc_base_low - orr r12, r12, #ioc_base_low - .endif - strb r12, [r12, #0x38] @ Disable FIQ register - .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - mov r4, #ioc_base_high @ point at IOC - .if ioc_base_low - orr r4, r4, #ioc_base_low - .endif - ldrb \irqstat, [r4, #IOMD_IRQREQB] @ get high priority first - ldr \base, =irq_prio_h - teq \irqstat, #0 -#ifdef IOMD_BASE - ldreqb \irqstat, [r4, #IOMD_DMAREQ] @ get dma - addeq \base, \base, #256 @ irq_prio_h table size - teqeq \irqstat, #0 - bne 2406f -#endif - ldreqb \irqstat, [r4, #IOMD_IRQREQA] @ get low priority - addeq \base, \base, #256 @ irq_prio_d table size - teqeq \irqstat, #0 -#ifdef IOMD_IRQREQC - ldreqb \irqstat, [r4, #IOMD_IRQREQC] - addeq \base, \base, #256 @ irq_prio_l table size - teqeq \irqstat, #0 -#endif -#ifdef IOMD_IRQREQD - ldreqb \irqstat, [r4, #IOMD_IRQREQD] - addeq \base, \base, #256 @ irq_prio_lc table size - teqeq \irqstat, #0 -#endif -2406: ldrneb \irqnr, [\base, \irqstat] @ get IRQ number - .endm - -/* - * Interrupt table (incorporates priority). Please note that we - * rely on the order of these tables (see above code). - */ - .macro irq_prio_table -irq_prio_h: .byte 0, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 12, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 - .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 -#ifdef IOMD_BASE -irq_prio_d: .byte 0,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 - .byte 20,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 - .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 - .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 - .byte 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 - .byte 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 - .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 - .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 - .byte 23,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 - .byte 23,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 - .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 - .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 - .byte 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 - .byte 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 - .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 - .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 -#endif -irq_prio_l: .byte 0, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 - .byte 4, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 - .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 - .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 - .byte 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3 - .byte 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3 - .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 - .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 - .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 - .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 - .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 - .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 - .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 - .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 - .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 - .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 -#ifdef IOMD_IRQREQC -irq_prio_lc: .byte 24,24,25,24,26,26,26,26,27,27,27,27,27,27,27,27 - .byte 28,24,25,24,26,26,26,26,27,27,27,27,27,27,27,27 - .byte 29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29 - .byte 29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29 - .byte 30,30,30,30,30,30,30,30,27,27,27,27,27,27,27,27 - .byte 30,30,30,30,30,30,30,30,27,27,27,27,27,27,27,27 - .byte 29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29 - .byte 29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29 - .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31 - .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31 - .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31 - .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31 - .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31 - .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31 - .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31 - .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31 -#endif -#ifdef IOMD_IRQREQD -irq_prio_ld: .byte 40,40,41,40,42,42,42,42,43,43,43,43,43,43,43,43 - .byte 44,40,41,40,42,42,42,42,43,43,43,43,43,43,43,43 - .byte 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45 - .byte 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45 - .byte 46,46,46,46,46,46,46,46,43,43,43,43,43,43,43,43 - .byte 46,46,46,46,46,46,46,46,43,43,43,43,43,43,43,43 - .byte 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45 - .byte 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45 - .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47 - .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47 - .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47 - .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47 - .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47 - .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47 - .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47 - .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47 -#endif - .endm - -#elif defined(CONFIG_ARCH_EBSA110) - -#define IRQ_STAT 0xff000000 /* read */ - - .macro disable_fiq - .endm - - .macro get_irqnr_and_base, irqnr, stat, base, tmp - mov \base, #IRQ_STAT - ldrb \stat, [\base] @ get interrupts - mov \irqnr, #0 - tst \stat, #15 - addeq \irqnr, \irqnr, #4 - moveq \stat, \stat, lsr #4 - tst \stat, #3 - addeq \irqnr, \irqnr, #2 - moveq \stat, \stat, lsr #2 - tst \stat, #1 - addeq \irqnr, \irqnr, #1 - moveq \stat, \stat, lsr #1 - tst \stat, #1 @ bit 0 should be set - .endm - - .macro irq_prio_table - .endm - -#elif defined(CONFIG_ARCH_SHARK) - - .macro disable_fiq - .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - mov r4, #0xe0000000 - - mov \irqstat, #0x0C - strb \irqstat, [r4, #0x20] @outb(0x0C, 0x20) /* Poll command */ - ldrb \irqnr, [r4, #0x20] @irq = inb(0x20) & 7 - and \irqstat, \irqnr, #0x80 - teq \irqstat, #0 - beq 43f - and \irqnr, \irqnr, #7 - teq \irqnr, #2 - bne 44f -43: mov \irqstat, #0x0C - strb \irqstat, [r4, #0xa0] @outb(0x0C, 0xA0) /* Poll command */ - ldrb \irqnr, [r4, #0xa0] @irq = (inb(0xA0) & 7) + 8 - and \irqstat, \irqnr, #0x80 - teq \irqstat, #0 - beq 44f - and \irqnr, \irqnr, #7 - add \irqnr, \irqnr, #8 -44: teq \irqstat, #0 - .endm - - .macro irq_prio_table - .endm - -#elif defined(CONFIG_FOOTBRIDGE) -#include - - .macro disable_fiq - .endm - - .equ dc21285_high, ARMCSR_BASE & 0xff000000 - .equ dc21285_low, ARMCSR_BASE & 0x00ffffff - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - mov r4, #dc21285_high - .if dc21285_low - orr r4, r4, #dc21285_low - .endif - ldr \irqstat, [r4, #0x180] @ get interrupts - - mov \irqnr, #IRQ_SDRAMPARITY - tst \irqstat, #IRQ_MASK_SDRAMPARITY - bne 1001f - - tst \irqstat, #IRQ_MASK_UART_RX - movne \irqnr, #IRQ_CONRX - bne 1001f - - tst \irqstat, #IRQ_MASK_DMA1 - movne \irqnr, #IRQ_DMA1 - bne 1001f - - tst \irqstat, #IRQ_MASK_DMA2 - movne \irqnr, #IRQ_DMA2 - bne 1001f - - tst \irqstat, #IRQ_MASK_IN0 - movne \irqnr, #IRQ_IN0 - bne 1001f - - tst \irqstat, #IRQ_MASK_IN1 - movne \irqnr, #IRQ_IN1 - bne 1001f - - tst \irqstat, #IRQ_MASK_IN2 - movne \irqnr, #IRQ_IN2 - bne 1001f - - tst \irqstat, #IRQ_MASK_IN3 - movne \irqnr, #IRQ_IN3 - bne 1001f - - tst \irqstat, #IRQ_MASK_PCI - movne \irqnr, #IRQ_PCI - bne 1001f - - tst \irqstat, #IRQ_MASK_DOORBELLHOST - movne \irqnr, #IRQ_DOORBELLHOST - bne 1001f - - tst \irqstat, #IRQ_MASK_I2OINPOST - movne \irqnr, #IRQ_I2OINPOST - bne 1001f - - tst \irqstat, #IRQ_MASK_TIMER1 - movne \irqnr, #IRQ_TIMER1 - bne 1001f - - tst \irqstat, #IRQ_MASK_TIMER2 - movne \irqnr, #IRQ_TIMER2 - bne 1001f - - tst \irqstat, #IRQ_MASK_TIMER3 - movne \irqnr, #IRQ_TIMER3 - bne 1001f - - tst \irqstat, #IRQ_MASK_UART_TX - movne \irqnr, #IRQ_CONTX - bne 1001f - - tst \irqstat, #IRQ_MASK_PCI_ABORT - movne \irqnr, #IRQ_PCI_ABORT - bne 1001f - - tst \irqstat, #IRQ_MASK_PCI_SERR - movne \irqnr, #IRQ_PCI_SERR - bne 1001f - - tst \irqstat, #IRQ_MASK_DISCARD_TIMER - movne \irqnr, #IRQ_DISCARD_TIMER - bne 1001f - - tst \irqstat, #IRQ_MASK_PCI_DPERR - movne \irqnr, #IRQ_PCI_DPERR - bne 1001f - - tst \irqstat, #IRQ_MASK_PCI_PERR - movne \irqnr, #IRQ_PCI_PERR -1001: - .endm - - .macro irq_prio_table - .endm - -#elif defined(CONFIG_ARCH_NEXUSPCI) - - .macro disable_fiq - .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - ldr \irqstat, =INTCONT_BASE - ldr \base, =soft_irq_mask - ldr \irqstat, [\irqstat] @ get interrupts - ldr \base, [\base] - mov \irqnr, #0 - and \irqstat, \irqstat, \base @ mask out disabled ones -1001: tst \irqstat, #1 - addeq \irqnr, \irqnr, #1 - moveq \irqstat, \irqstat, lsr #1 - tsteq \irqnr, #32 - beq 1001b - teq \irqnr, #32 - .endm - - .macro irq_prio_table - .ltorg - .bss -ENTRY(soft_irq_mask) - .word 0 - .text - .endm - -#elif defined(CONFIG_ARCH_TBOX) - - .macro disable_fiq - .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - ldr \irqstat, =0xffff7000 - ldr \irqstat, [\irqstat] @ get interrupts - ldr \base, =soft_irq_mask - ldr \base, [\base] - mov \irqnr, #0 - and \irqstat, \irqstat, \base @ mask out disabled ones -1001: tst \irqstat, #1 - addeq \irqnr, \irqnr, #1 - moveq \irqstat, \irqstat, lsr #1 - tsteq \irqnr, #32 - beq 1001b - teq \irqnr, #32 - .endm - - .macro irq_prio_table - .ltorg - .bss -ENTRY(soft_irq_mask) - .word 0 - .text - .endm - -#elif defined(CONFIG_ARCH_SA1100) - - .macro disable_fiq - .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - mov r4, #0xfa000000 @ ICIP = 0xfa050000 - add r4, r4, #0x00050000 - ldr \irqstat, [r4] @ get irqs - ldr \irqnr, [r4, #4] @ ICMR = 0xfa050004 - ands \irqstat, \irqstat, \irqnr - mov \irqnr, #0 - beq 1001f - tst \irqstat, #0xff - moveq \irqstat, \irqstat, lsr #8 - addeq \irqnr, \irqnr, #8 - tsteq \irqstat, #0xff - moveq \irqstat, \irqstat, lsr #8 - addeq \irqnr, \irqnr, #8 - tsteq \irqstat, #0xff - moveq \irqstat, \irqstat, lsr #8 - addeq \irqnr, \irqnr, #8 - tst \irqstat, #0x0f - moveq \irqstat, \irqstat, lsr #4 - addeq \irqnr, \irqnr, #4 - tst \irqstat, #0x03 - moveq \irqstat, \irqstat, lsr #2 - addeq \irqnr, \irqnr, #2 - tst \irqstat, #0x01 - addeqs \irqnr, \irqnr, #1 -1001: - .endm - - .macro irq_prio_table - .endm - -#elif defined(CONFIG_ARCH_L7200) -#include - - .equ irq_base_addr, IO_BASE_2 - - .macro disable_fiq - .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - mov \irqstat, #irq_base_addr @ Virt addr IRQ regs - add \irqstat, \irqstat, #0x00001000 @ Status reg - ldr \irqstat, [\irqstat, #0] @ get interrupts - mov \irqnr, #0 -1001: tst \irqstat, #1 - addeq \irqnr, \irqnr, #1 - moveq \irqstat, \irqstat, lsr #1 - tsteq \irqnr, #32 - beq 1001b - teq \irqnr, #32 - .endm - - .macro irq_prio_table - .endm - -#elif defined(CONFIG_ARCH_INTEGRATOR) - - .macro disable_fiq - .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp -/* FIXME: should not be using soo many LDRs here */ - ldr \base, =IO_ADDRESS(INTEGRATOR_IC_BASE) - mov \irqnr, #IRQ_PIC_START - ldr \irqstat, [\base, #IRQ_STATUS] @ get masked status - ldr \base, =IO_ADDRESS(INTEGRATOR_HDR_BASE) - teq \irqstat, #0 - ldreq \irqstat, [\base, #(INTEGRATOR_HDR_IC_OFFSET+IRQ_STATUS)] - moveq \irqnr, #IRQ_CIC_START - -1001: tst \irqstat, #15 - bne 1002f - add \irqnr, \irqnr, #4 - movs \irqstat, \irqstat, lsr #4 - bne 1001b -1002: tst \irqstat, #1 - bne 1003f - add \irqnr, \irqnr, #1 - movs \irqstat, \irqstat, lsr #1 - bne 1002b -1003: /* EQ will be set if no irqs pending */ - .endm - - .macro irq_prio_table - .endm - -#elif defined(CONFIG_ARCH_VERSATILE) - - .macro disable_fiq - .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - ldr \base, =IO_ADDRESS(VERSATILE_VIC_BASE) - ldr \irqstat, [\base, #VIC_IRQ_STATUS] @ get masked status - mov \irqnr, #0 - teq \irqstat, #0 - beq 1003f - -1001: tst \irqstat, #15 - bne 1002f - add \irqnr, \irqnr, #4 - movs \irqstat, \irqstat, lsr #4 - bne 1001b -1002: tst \irqstat, #1 - bne 1003f - add \irqnr, \irqnr, #1 - movs \irqstat, \irqstat, lsr #1 - bne 1002b -1003: /* EQ will be set if no irqs pending */ - -@ clz \irqnr, \irqstat -@1003: /* EQ will be set if we reach MAXIRQNUM */ - .endm - - .macro irq_prio_table - .endm - -#elif defined(CONFIG_ARCH_CLPS711X) - -#include - - .macro disable_fiq - .endm - -#if (INTSR2 - INTSR1) != (INTMR2 - INTMR1) -#error INTSR stride != INTMR stride -#endif - - .macro get_irqnr_and_base, irqnr, stat, base, mask - mov \base, #CLPS7111_BASE - ldr \stat, [\base, #INTSR1] - ldr \mask, [\base, #INTMR1] - mov \irqnr, #4 - mov \mask, \mask, lsl #16 - and \stat, \stat, \mask, lsr #16 - movs \stat, \stat, lsr #4 - bne 1001f - - add \base, \base, #INTSR2 - INTSR1 - ldr \stat, [\base, #INTSR1] - ldr \mask, [\base, #INTMR1] - mov \irqnr, #16 - mov \mask, \mask, lsl #16 - and \stat, \stat, \mask, lsr #16 - -1001: tst \stat, #255 - addeq \irqnr, \irqnr, #8 - moveq \stat, \stat, lsr #8 - tst \stat, #15 - addeq \irqnr, \irqnr, #4 - moveq \stat, \stat, lsr #4 - tst \stat, #3 - addeq \irqnr, \irqnr, #2 - moveq \stat, \stat, lsr #2 - tst \stat, #1 - addeq \irqnr, \irqnr, #1 - moveq \stat, \stat, lsr #1 - tst \stat, #1 @ bit 0 should be set - .endm - - .macro irq_prio_table - .endm - -#elif defined (CONFIG_ARCH_CAMELOT) -#include -#undef IRQ_MODE /* same name defined in asm/proc/ptrace.h */ -#include - - .macro disable_fiq - .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - - ldr \irqstat, =INT_ID(IO_ADDRESS(EXC_INT_CTRL00_BASE)) - ldr \irqnr,[\irqstat] - cmp \irqnr,#0 - subne \irqnr,\irqnr,#1 - - - .endm - - .macro irq_prio_table - .endm - -#elif defined(CONFIG_ARCH_IOP321) - .macro disable_fiq - .endm - - /* - * Note: only deal with normal interrupts, not FIQ - */ - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - mov \irqnr, #0 - mrc p6, 0, \irqstat, c8, c0, 0 @ Read IINTSRC - cmp \irqstat, #0 - beq 1001f - clz \irqnr, \irqstat - mov \base, #31 - subs \irqnr,\base,\irqnr - add \irqnr,\irqnr,#IRQ_IOP321_DMA0_EOT -1001: - .endm - - .macro irq_prio_table - .endm - -#elif defined(CONFIG_ARCH_IOP331) - .macro disable_fiq - .endm - - /* - * Note: only deal with normal interrupts, not FIQ - */ - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - mov \irqnr, #0 - mrc p6, 0, \irqstat, c4, c0, 0 @ Read IINTSRC0 - cmp \irqstat, #0 - bne 1002f - mrc p6, 0, \irqstat, c5, c0, 0 @ Read IINTSRC1 - cmp \irqstat, #0 - beq 1001f - clz \irqnr, \irqstat -/* - * mov \base, #31 - * subs \irqnr,\base,\irqnr - */ - rsbs \irqnr,\irqnr,#31 @ recommend by RMK - add \irqnr,\irqnr,#IRQ_IOP331_XINT8 - b 1001f -1002: clz \irqnr, \irqstat - mov \base, #31 - subs \irqnr,\base,\irqnr - add \irqnr,\irqnr,#IRQ_IOP331_DMA0_EOT -1001: - .endm - - .macro irq_prio_table - .endm - -#elif defined(CONFIG_ARCH_PXA) - - .macro disable_fiq - .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp -#ifdef CONFIG_PXA27x - mrc p6, 0, \irqstat, c0, c0, 0 @ ICIP - mrc p6, 0, \irqnr, c1, c0, 0 @ ICMR -#else - mov \base, #io_p2v(0x40000000) @ IIR Ctl = 0x40d00000 - add \base, \base, #0x00d00000 - ldr \irqstat, [\base, #0] @ ICIP - ldr \irqnr, [\base, #4] @ ICMR -#endif - ands \irqnr, \irqstat, \irqnr - beq 1001f - rsb \irqstat, \irqnr, #0 - and \irqstat, \irqstat, \irqnr - clz \irqnr, \irqstat - rsb \irqnr, \irqnr, #(31 - PXA_IRQ_SKIP) -1001: - .endm - - .macro irq_prio_table - .endm - -#elif defined(CONFIG_ARCH_IXP2000) - - .macro disable_fiq - .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - - mov \irqnr, #0x0 @clear out irqnr as default - mov \base, #0xfe000000 - orr \base, \base, #0x00ff0000 - orr \base, \base, #0x0000a000 - orr \base, \base, #0x08 - ldr \irqstat, [\base] @ get interrupts - mov \tmp, #IXP2000_VALID_IRQ_MASK & 0xff000000 - orr \tmp, \tmp, #IXP2000_VALID_IRQ_MASK & 0x00ff0000 - orr \tmp, \tmp, #IXP2000_VALID_IRQ_MASK & 0x0000ff00 - orr \tmp, \tmp, #IXP2000_VALID_IRQ_MASK & 0x000000ff - and \irqstat, \irqstat, \tmp - - cmp \irqstat, #0 - beq 1001f - - clz \irqnr, \irqstat - mov \base, #31 - subs \irqnr, \base, \irqnr - - /* - * We handle PCIA and PCIB here so we don't have an - * extra layer of code just to check these two bits. - */ - cmp \irqnr, #IRQ_IXP2000_PCI - bne 1001f - - mov \base, #0xfe000000 - orr \base, \base, #0x00fd0000 - orr \base, \base, #0x0000e100 - orr \base, \base, #0x00000058 - ldr \irqstat, [\base] - - mov \tmp, #(1<<26) - tst \irqstat, \tmp - movne \irqnr, #IRQ_IXP2000_PCIA - bne 1001f - - mov \tmp, #(1<<27) - tst \irqstat, \tmp - movne \irqnr, #IRQ_IXP2000_PCIB - -1001: - .endm - - .macro irq_prio_table - .endm - -#elif defined (CONFIG_ARCH_IXP4XX) - - .macro disable_fiq - .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - ldr \irqstat, =(IXP4XX_INTC_BASE_VIRT+IXP4XX_ICIP_OFFSET) - ldr \irqstat, [\irqstat] @ get interrupts - cmp \irqstat, #0 - beq 1002f - clz \irqnr, \irqstat - mov \base, #31 - subs \irqnr, \base, \irqnr - -/* -1001: tst \irqstat, #1 - addeq \irqnr, \irqnr, #1 - moveq \irqstat, \irqstat, lsr #1 - tsteq \irqnr, #32 - beq 1001b - teq \irqnr, #32 -*/ -1002: - .endm - - .macro irq_prio_table - .endm - -#elif defined(CONFIG_ARCH_OMAP) - - .macro disable_fiq - .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - ldr \base, =IO_ADDRESS(OMAP_IH1_BASE) - ldr \irqnr, [\base, #IRQ_ITR_REG_OFFSET] - ldr \tmp, [\base, #IRQ_MIR_REG_OFFSET] - mov \irqstat, #0xffffffff - bic \tmp, \irqstat, \tmp - tst \irqnr, \tmp - beq 1510f - - ldr \irqnr, [\base, #IRQ_SIR_FIQ_REG_OFFSET] - cmp \irqnr, #0 - ldreq \irqnr, [\base, #IRQ_SIR_IRQ_REG_OFFSET] - cmpeq \irqnr, #INT_IH2_IRQ - ldreq \base, =IO_ADDRESS(OMAP_IH2_BASE) - ldreq \irqnr, [\base, #IRQ_SIR_IRQ_REG_OFFSET] - addeqs \irqnr, \irqnr, #32 -1510: - .endm - - .macro irq_prio_table - .endm - -#elif defined(CONFIG_ARCH_S3C2410) - /* S3C2410X IRQ Handler, */ - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - -30000: - mov \tmp, #S3C2410_VA_IRQ - ldr \irqnr, [ \tmp, #0x14 ] @ get irq no - teq \irqnr, #4 - teqne \irqnr, #5 - beq 1002f @ external irq reg - teq \irqnr, #16 - beq 1003f @ lcd controller - - @ debug check to see if interrupt reported is the same - @ as the offset.... - - teq \irqnr, #0 - beq 20002f - ldr \irqstat, [ \tmp, #0x10 ] @ INTPND - mov \irqstat, \irqstat, lsr \irqnr - tst \irqstat, #1 - bne 20002f - -#if 1 - stmfd r13!, { r0 - r4 , r14 } - ldr r1, [ \tmp, #0x14 ] @ intoffset - ldr r2, [ \tmp, #0x10 ] @ INTPND - ldr r3, [ \tmp, #0x00 ] @ SRCPND - adr r0, 20003f - bl printk - b 20004f -#endif -20003: - .ascii "<7>irq: err - bad offset %d, intpnd=%08x, srcpnd=%08x\n" - .byte 0 - .align 4 -20004: - mov r1, #1 - mov \tmp, #S3C2410_VA_IRQ - ldmfd r13!, { r0 - r4 , r14 } - - @ try working out interript number for ourselves - mov \irqnr, #0 - ldr \irqstat, [ \tmp, #0x10 ] @ INTPND -10021: - movs \irqstat, \irqstat, lsr#1 - bcs 30000b @ try and re-start the proccess - add \irqnr, \irqnr, #1 - cmp \irqnr, #32 - ble 10021b - - @ found no interrupt, set Z flag and leave - movs \irqnr, #0 - b 1001f - -20005: -20002: @ exit - @ we base the s3c2410x interrupts at 16 and above to allow - @ isa peripherals to have their standard interrupts, also - @ ensure that Z flag is un-set on exit - - @ note, we cannot be sure if we get IRQ_EINT0 (0) that - @ there is simply no interrupt pending, so in all other - @ cases we jump to say we have found something, otherwise - @ we check to see if the interrupt really is assrted - adds \irqnr, \irqnr, #IRQ_EINT0 - teq \irqnr, #IRQ_EINT0 - bne 1001f @ exit - ldr \irqstat, [ \tmp, #0x10 ] @ INTPND - teq \irqstat, #0 - moveq \irqnr, #0 - b 1001f - - @ we get here from no main or external interrupts pending -1002: - add \tmp, \tmp, #S3C2410_VA_GPIO - S3C2410_VA_IRQ - ldr \irqstat, [ \tmp, # 0xa8 ] @ EXTINTPEND - ldr \irqnr, [ \tmp, # 0xa4 ] @ EXTINTMASK - - bic \irqstat, \irqstat, \irqnr @ clear masked irqs - - mov \irqnr, #IRQ_EINT4 @ start extint nos - mov \irqstat, \irqstat, lsr#4 @ ignore bottom 4 bits -10021: - movs \irqstat, \irqstat, lsr#1 - bcs 1004f - add \irqnr, \irqnr, #1 - cmp \irqnr, #IRQ_EINT23 - ble 10021b - - @ found no interrupt, set Z flag and leave - movs \irqnr, #0 - b 1001f - -1003: - @ lcd interrupt has been asserted... - add \tmp, \tmp, #S3C2410_VA_LCD - S3C2410_VA_IRQ - ldr \irqstat, [ \tmp, # 0x54 ] @ lcd int pending - - tst \irqstat, #2 - movne \irqnr, #IRQ_LCD_FRAME - tst \irqstat, #1 - movne \irqnr, #IRQ_LCD_FIFO - - @ fall through to exit with flags updated - -1004: @ ensure Z flag clear in case our MOVS shifted out the last bit - teq \irqnr, #0 -1001: - @ exit irq routine - .endm - - - /* currently don't need an disable_fiq macro */ - - .macro disable_fiq - .endm - - /* we don't have an irq priority table */ - .macro irq_prio_table - .endm - -#elif defined(CONFIG_ARCH_LH7A400) - -# if defined (CONFIG_ARCH_LH7A404) -# error "LH7A400 and LH7A404 are mutually exclusive" -# endif - .macro disable_fiq - .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - mov \irqnr, #0 - mov \base, #io_p2v(0x80000000) @ APB registers - ldr \irqstat, [\base, #0x500] @ PIC INTSR - -1001: movs \irqstat, \irqstat, lsr #1 @ Shift into carry - bcs 1008f @ Bit set; irq found - add \irqnr, \irqnr, #1 - bne 1001b @ Until no bits - b 1009f @ Nothing? Hmm. -1008: movs \irqstat, #1 @ Force !Z -1009: - .endm - - .macro irq_prio_table - .endm - -#elif defined(CONFIG_ARCH_LH7A404) - - .macro disable_fiq - .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - mov \irqnr, #0 @ VIC1 irq base - mov \base, #io_p2v(0x80000000) @ APB registers - add \base, \base, #0x8000 - ldr \tmp, [\base, #0x0030] @ VIC1_VECTADDR - tst \tmp, #VA_VECTORED @ Direct vectored - bne 1002f - tst \tmp, #VA_VIC1DEFAULT @ Default vectored VIC1 - ldrne \irqstat, [\base, #0] @ VIC1_IRQSTATUS - bne 1001f - add \base, \base, #(0xa000 - 0x8000) - ldr \tmp, [\base, #0x0030] @ VIC2_VECTADDR - tst \tmp, #VA_VECTORED @ Direct vectored - bne 1002f - ldr \irqstat, [\base, #0] @ VIC2_IRQSTATUS - mov \irqnr, #32 @ VIC2 irq base - -1001: movs \irqstat, \irqstat, lsr #1 @ Shift into carry - bcs 1008f @ Bit set; irq found - add \irqnr, \irqnr, #1 - bne 1001b @ Until no bits - b 1009f @ Nothing? Hmm. -1002: and \irqnr, \tmp, #0x3f @ Mask for valid bits -1008: movs \irqstat, #1 @ Force !Z - str \tmp, [\base, #0x0030] @ Clear vector -1009: - .endm - - .macro irq_prio_table - .endm - -#elif defined(CONFIG_ARCH_IMX) - - .macro disable_fiq - .endm -#define AITC_NIVECSR 0x40 - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - ldr \irqstat, =IO_ADDRESS(IMX_AITC_BASE) - @ Load offset & priority of the highest priority - @ interrupt pending. - ldr \irqnr, [\irqstat, #AITC_NIVECSR] - @ Shift off the priority leaving the offset or - @ "interrupt number" - mov \irqnr, \irqnr, lsr #16 - ldr \irqstat, =1 @ dummy compare - ldr \base, =0xFFFF // invalid interrupt - cmp \irqnr, \base - bne 1001f - ldr \irqstat, =0 -1001: - tst \irqstat, #1 @ to make the condition code = TRUE - .endm - - .macro irq_prio_table - .endm - -#elif defined(CONFIG_ARCH_H720X) - - .macro disable_fiq - .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp -#if defined (CONFIG_CPU_H7201) || defined (CONFIG_CPU_H7202) - @ we could use the id register on H7202, but this is not - @ properly updated when we come back from asm_do_irq - @ without a previous return from interrupt - @ (see loops below in irq_svc, irq_usr) - @ We see unmasked pending ints only, as the masked pending ints - @ are not visible here - - mov \base, #0xf0000000 @ base register - orr \base, \base, #0x24000 @ irqbase - ldr \irqstat, [\base, #0x04] @ get interrupt status -#if defined (CONFIG_CPU_H7201) - ldr \tmp, =0x001fffff -#else - mvn \tmp, #0xc0000000 -#endif - and \irqstat, \irqstat, \tmp @ mask out unused ints - mov \irqnr, #0 - - mov \tmp, #0xff00 - orr \tmp, \tmp, #0xff - tst \irqstat, \tmp - addeq \irqnr, \irqnr, #16 - moveq \irqstat, \irqstat, lsr #16 - tst \irqstat, #255 - addeq \irqnr, \irqnr, #8 - moveq \irqstat, \irqstat, lsr #8 - tst \irqstat, #15 - addeq \irqnr, \irqnr, #4 - moveq \irqstat, \irqstat, lsr #4 - tst \irqstat, #3 - addeq \irqnr, \irqnr, #2 - moveq \irqstat, \irqstat, lsr #2 - tst \irqstat, #1 - addeq \irqnr, \irqnr, #1 - moveq \irqstat, \irqstat, lsr #1 - tst \irqstat, #1 @ bit 0 should be set - .endm - - .macro irq_prio_table - .endm - -#else -#error hynix processor selection missmatch -#endif -#else -#error Unknown architecture -#endif - /* * Invalid mode handlers */ -__pabt_invalid: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go - stmia sp, {r0 - lr} @ Save XXX r0 - lr - ldr r4, .LCabt - mov r1, #BAD_PREFETCH - b 1f - -__dabt_invalid: sub sp, sp, #S_FRAME_SIZE - stmia sp, {r0 - lr} @ Save SVC r0 - lr [lr *should* be intact] - ldr r4, .LCabt - mov r1, #BAD_DATA - b 1f - -__irq_invalid: sub sp, sp, #S_FRAME_SIZE @ Allocate space on stack for frame - stmfd sp, {r0 - lr} @ Save r0 - lr - ldr r4, .LCirq - mov r1, #BAD_IRQ - b 1f - -__und_invalid: sub sp, sp, #S_FRAME_SIZE - stmia sp, {r0 - lr} - ldr r4, .LCund - mov r1, #BAD_UNDEFINSTR @ int reason - -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 - b bad_mode + .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 + mov r1, #\reason + .endm + +__pabt_invalid: + inv_entry abt, BAD_PREFETCH + b 1f + +__dabt_invalid: + inv_entry abt, BAD_DATA + b 1f + +__irq_invalid: + inv_entry irq, BAD_IRQ + b 1f + +__und_invalid: + inv_entry und, BAD_UNDEFINSTR + +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 + b bad_mode /* * SVC mode handlers */ - .align 5 -__dabt_svc: sub sp, sp, #S_FRAME_SIZE - stmia sp, {r0 - r12} @ save r0 - r12 - ldr r2, .LCabt - add r0, sp, #S_FRAME_SIZE - ldmia r2, {r2 - r4} @ get pc, cpsr - add r5, sp, #S_SP - mov r1, lr - stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro - mrs r9, cpsr @ Enable interrupts if they were - tst r3, #PSR_I_BIT - biceq r9, r9, #PSR_I_BIT @ previously -/* - * This routine must not corrupt r9 - */ + .macro svc_entry, sym + 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 + mov r1, lr + + @ + @ We are now ready to fill in the remaining blanks on the stack: + @ + @ r0 - sp_svc + @ r1 - lr_svc + @ r2 - lr_, already fixed up for correct return/restart + @ r3 - spsr_ + @ r4 - orig_r0 (see pt_regs definition in ptrace.h) + @ + stmia r5, {r0 - r4} + .endm + + .align 5 +__dabt_svc: + svc_entry abt + + @ + @ get ready to re-enable interrupts if appropriate + @ + mrs r9, cpsr + tst r3, #PSR_I_BIT + biceq r9, r9, #PSR_I_BIT + + @ + @ Call the processor-specific abort handler: + @ + @ r2 - aborted context pc + @ r3 - aborted context cpsr + @ + @ The abort handler must return the aborted address in r0, and + @ the fault status register in r1. r9 must be preserved. + @ #ifdef MULTI_ABORT - ldr r4, .LCprocfns @ pass r2, r3 to - mov lr, pc @ processor code - ldr pc, [r4] @ call processor specific code + ldr r4, .LCprocfns + mov lr, pc + ldr pc, [r4] #else - bl CPU_ABORT_HANDLER + bl CPU_ABORT_HANDLER #endif - msr cpsr_c, r9 - mov r2, sp - bl do_DataAbort - disable_irq r0 - ldr r0, [sp, #S_PSR] - msr spsr_cxsf, r0 - ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr - - .align 5 -__irq_svc: sub sp, sp, #S_FRAME_SIZE - stmia sp, {r0 - r12} @ save r0 - r12 - ldr r7, .LCirq - add r5, sp, #S_FRAME_SIZE - ldmia r7, {r7 - r9} - add r4, sp, #S_SP - mov r6, lr - stmia r4, {r5, r6, r7, r8, r9} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro + + @ + @ set desired IRQ state, then call main handler + @ + msr cpsr_c, r9 + mov r2, sp + bl do_DataAbort + + @ + @ IRQs off again before pulling preserved data off the stack + @ + disable_irq + + @ + @ restore SPSR and restart the instruction + @ + ldr r0, [sp, #S_PSR] + msr spsr_cxsf, r0 + ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr + + .align 5 +__irq_svc: + svc_entry irq #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 r8 + ldr r9, [r8, #TI_PREEMPT] @ get preempt count + add r7, r9, #1 @ increment it + str r7, [r8, #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 * - @ - adrsvc ne, lr, 1b - bne asm_do_IRQ +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_PREEMPT - ldr r0, [r8, #TI_FLAGS] @ get flags - tst r0, #_TIF_NEED_RESCHED - blne svc_preempt + ldr r0, [r8, #TI_FLAGS] @ get flags + tst r0, #_TIF_NEED_RESCHED + blne svc_preempt preempt_return: - ldr r0, [r8, #TI_PREEMPT] @ read preempt value - teq r0, r7 - str r9, [r8, #TI_PREEMPT] @ restore preempt count - strne r0, [r0, -r0] @ bug() + ldr r0, [r8, #TI_PREEMPT] @ read preempt value + 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 - msr spsr_cxsf, r0 - ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr + ldr r0, [sp, #S_PSR] @ irqs are already disabled + msr spsr_cxsf, r0 + ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr - .ltorg + .ltorg #ifdef CONFIG_PREEMPT -svc_preempt: teq r9, #0 @ was preempt count = 0 - ldreq r6, .LCirq_stat - movne pc, lr @ no - ldr r0, [r6, #4] @ local_irq_count - ldr r1, [r6, #8] @ local_bh_count - adds r0, r0, r1 - movne pc, lr - mov r7, #PREEMPT_ACTIVE - str r7, [r8, #TI_PREEMPT] @ set PREEMPT_ACTIVE -1: enable_irq r2 @ enable IRQs - bl schedule - disable_irq r0 @ disable IRQs - ldr r0, [r8, #TI_FLAGS] @ get new tasks TI_FLAGS - tst r0, #_TIF_NEED_RESCHED - beq preempt_return @ go again - b 1b +svc_preempt: + teq r9, #0 @ was preempt count = 0 + ldreq r6, .LCirq_stat + movne pc, lr @ no + ldr r0, [r6, #4] @ local_irq_count + ldr r1, [r6, #8] @ local_bh_count + adds r0, r0, r1 + movne pc, lr + mov r7, #0 @ preempt_schedule_irq + str r7, [r8, #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 + tst r0, #_TIF_NEED_RESCHED + beq preempt_return @ go again + b 1b #endif - .align 5 -__und_svc: sub sp, sp, #S_FRAME_SIZE - stmia sp, {r0 - r12} @ save r0 - r12 - ldr r3, .LCund - mov r4, lr - ldmia r3, {r5 - r7} - add r3, sp, #S_FRAME_SIZE - add r2, sp, #S_SP - stmia r2, {r3 - r7} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro - - ldr r0, [r5, #-4] @ r0 = instruction - adrsvc al, r9, 1f @ r9 = normal FP return - bl call_fpe @ lr = undefined instr return - - mov r0, sp @ struct pt_regs *regs - bl do_undefinstr - -1: disable_irq r0 - ldr lr, [sp, #S_PSR] @ Get SVC cpsr - msr spsr_cxsf, lr - ldmia sp, {r0 - pc}^ @ Restore SVC registers - - .align 5 -__pabt_svc: sub sp, sp, #S_FRAME_SIZE - stmia sp, {r0 - r12} @ save r0 - r12 - ldr r2, .LCabt - add r0, sp, #S_FRAME_SIZE - ldmia r2, {r2 - r4} @ get pc, cpsr - add r5, sp, #S_SP - mov r1, lr - stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro - mrs r9, cpsr @ Enable interrupts if they were - tst r3, #PSR_I_BIT - biceq r9, r9, #PSR_I_BIT @ previously - msr cpsr_c, r9 - mov r0, r2 @ address (pc) - mov r1, sp @ regs - bl do_PrefetchAbort @ call abort handler - disable_irq r0 - ldr r0, [sp, #S_PSR] - msr spsr_cxsf, r0 - ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr - - .align 5 -.LCirq: .word __temp_irq -.LCund: .word __temp_und -.LCabt: .word __temp_abt + .align 5 +__und_svc: + svc_entry und + + @ + @ call emulation code, which returns using r9 if it has emulated + @ the instruction, or the more conventional lr if we are to treat + @ this as a real undefined instruction + @ + @ r0 - instruction + @ + ldr r0, [r2, #-4] + adr r9, 1f + bl call_fpe + + mov r0, sp @ struct pt_regs *regs + bl do_undefinstr + + @ + @ IRQs off again before pulling preserved data off the stack + @ +1: disable_irq + + @ + @ restore SPSR and restart the instruction + @ + ldr lr, [sp, #S_PSR] @ Get SVC cpsr + msr spsr_cxsf, lr + ldmia sp, {r0 - pc}^ @ Restore SVC registers + + .align 5 +__pabt_svc: + svc_entry abt + + @ + @ re-enable interrupts if appropriate + @ + mrs r9, cpsr + tst r3, #PSR_I_BIT + biceq r9, r9, #PSR_I_BIT + msr cpsr_c, r9 + + @ + @ set args, then call main handler + @ + @ r0 - address of faulting instruction + @ r1 - pointer to registers on stack + @ + mov r0, r2 @ address (pc) + mov r1, sp @ regs + bl do_PrefetchAbort @ call abort handler + + @ + @ IRQs off again before pulling preserved data off the stack + @ + disable_irq + + @ + @ restore SPSR and restart the instruction + @ + ldr r0, [sp, #S_PSR] + msr spsr_cxsf, r0 + ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr + + .align 5 +.LCirq: + .word __temp_irq +.LCund: + .word __temp_und +.LCabt: + .word __temp_abt #ifdef MULTI_ABORT -.LCprocfns: .word processor +.LCprocfns: + .word processor #endif -.LCfp: .word fp_enter +.LCfp: + .word fp_enter #ifdef CONFIG_PREEMPT -.LCirq_stat: .word irq_stat +.LCirq_stat: + .word irq_stat #endif - irq_prio_table - /* * User mode handlers */ - .align 5 -__dabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go - stmia sp, {r0 - r12} @ save r0 - r12 - ldr r7, .LCabt - add r5, sp, #S_PC - ldmia r7, {r2 - r4} @ Get USR pc, cpsr - stmia r5, {r2 - r4} @ Save USR pc, cpsr, old_r0 - stmdb r5, {sp, lr}^ - alignment_trap r7, r7, __temp_abt - zero_fp + .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 && !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 +#endif + + @ + @ We are now ready to fill in the remaining blanks on the stack: + @ + @ r2 - lr_, already fixed up for correct return/restart + @ r3 - spsr_ + @ r4 - orig_r0 (see pt_regs definition in ptrace.h) + @ + @ Also, separately save sp_usr and lr_usr + @ + stmia r5, {r2 - r4} + stmdb r5, {sp, lr}^ + + @ + @ Enable the alignment trap while in kernel mode + @ + alignment_trap r7, r0, __temp_\sym + + @ + @ Clear FP to mark the first stack frame + @ + zero_fp + .endm + + .align 5 +__dabt_usr: + usr_entry abt + + @ + @ Call the processor-specific abort handler: + @ + @ r2 - aborted context pc + @ r3 - aborted context cpsr + @ + @ The abort handler must return the aborted address in r0, and + @ the fault status register in r1. + @ #ifdef MULTI_ABORT - ldr r4, .LCprocfns @ pass r2, r3 to - mov lr, pc @ processor code - ldr pc, [r4] @ call processor specific code + ldr r4, .LCprocfns + mov lr, pc + ldr pc, [r4] #else - bl CPU_ABORT_HANDLER + bl CPU_ABORT_HANDLER #endif - enable_irq r2 @ Enable interrupts - mov r2, sp - adrsvc al, lr, ret_from_exception - b do_DataAbort - - .align 5 -__irq_usr: sub sp, sp, #S_FRAME_SIZE - stmia sp, {r0 - r12} @ save r0 - r12 - ldr r4, .LCirq - add r8, sp, #S_PC - ldmia r4, {r5 - r7} @ get saved PC, SPSR - stmia r8, {r5 - r7} @ save pc, psr, old_r0 - stmdb r8, {sp, lr}^ - alignment_trap r4, r7, __temp_irq - zero_fp + + @ + @ IRQs on, then call the main handler + @ + enable_irq + mov r2, sp + adr lr, ret_from_exception + b do_DataAbort + + .align 5 +__irq_usr: + usr_entry irq + #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 r8 + ldr r9, [r8, #TI_PREEMPT] @ get preempt count + add r7, r9, #1 @ increment it + str r7, [r8, #TI_PREEMPT] #endif -1: get_irqnr_and_base r0, r6, r5, lr - movne r1, sp - adrsvc ne, lr, 1b - @ - @ routine called with r0 = irq number, r1 = struct pt_regs * - @ - bne asm_do_IRQ +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 #ifdef CONFIG_PREEMPT - ldr r0, [r8, #TI_PREEMPT] - teq r0, r7 - str r9, [r8, #TI_PREEMPT] - strne r0, [r0, -r0] - mov tsk, r8 + ldr r0, [r8, #TI_PREEMPT] + teq r0, r7 + str r9, [r8, #TI_PREEMPT] + strne r0, [r0, -r0] + mov tsk, r8 #else - get_thread_info tsk + get_thread_info tsk #endif - mov why, #0 - b ret_to_user - - .ltorg - - .align 5 -__und_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go - stmia sp, {r0 - r12} @ Save r0 - r12 - ldr r4, .LCund - add r8, sp, #S_PC - ldmia r4, {r5 - r7} - stmia r8, {r5 - r7} @ Save USR pc, cpsr, old_r0 - stmdb r8, {sp, lr}^ @ Save user sp, lr - alignment_trap r4, r7, __temp_und - zero_fp - tst r6, #PSR_T_BIT @ Thumb mode? - bne fpundefinstr @ ignore FP - sub r4, r5, #4 -1: ldrt r0, [r4] @ r0 = instruction - adrsvc al, r9, ret_from_exception @ r9 = normal FP return - adrsvc al, lr, fpundefinstr @ lr = undefined instr return + mov why, #0 + b ret_to_user + + .ltorg + + .align 5 +__und_usr: + usr_entry und + + tst r3, #PSR_T_BIT @ Thumb mode? + bne fpundefinstr @ ignore FP + sub r4, r2, #4 + + @ + @ fall through to the emulation code, which returns using r9 if + @ it has emulated the instruction, or the more conventional lr + @ if we are to treat this as a real undefined instruction + @ + @ r0 - instruction + @ +1: ldrt r0, [r4] + adr r9, ret_from_exception + adr lr, fpundefinstr + @ + @ fallthrough to call_fpe + @ /* * The out of line fixup for the ldrt above. */ - .section .fixup, "ax" -2: mov pc, r9 - .previous - .section __ex_table,"a" - .long 1b, 2b - .previous + .section .fixup, "ax" +2: mov pc, r9 + .previous + .section __ex_table,"a" + .long 1b, 2b + .previous /* - * r0 = instruction. - * * Check whether the instruction is a co-processor instruction. * If yes, we need to call the relevant co-processor handler. * @@ -1300,98 +401,95 @@ __und_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go * for the ARM6/ARM7 SWI bug. * * Emulators may wish to make use of the following registers: - * r0 - instruction opcode. - * r10 - this threads thread_info structure. + * r0 = instruction opcode. + * r2 = PC+4 + * r10 = this threads thread_info structure. */ call_fpe: - tst r0, #0x08000000 @ only CDP/CPRT/LDC/STC have bit 27 + tst r0, #0x08000000 @ only CDP/CPRT/LDC/STC have bit 27 #if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710) - and r8, r0, #0x0f000000 @ mask out op-code bits - teqne r8, #0x0f000000 @ SWI (ARM6/7 bug)? + and r8, r0, #0x0f000000 @ mask out op-code bits + teqne r8, #0x0f000000 @ SWI (ARM6/7 bug)? #endif - moveq pc, lr - get_thread_info r10 @ get current thread - and r8, r0, #0x00000f00 @ mask out CP number - mov r7, #1 - add r6, r10, #TI_USED_CP - strb r7, [r6, r8, lsr #8] @ set appropriate used_cp[] + moveq pc, lr + get_thread_info r10 @ get current thread + and r8, r0, #0x00000f00 @ mask out CP number + mov r7, #1 + add r6, r10, #TI_USED_CP + strb r7, [r6, r8, lsr #8] @ set appropriate used_cp[] #ifdef CONFIG_IWMMXT - @ Test if we need to give access to iWMMXt coprocessors - ldr r5, [r10, #TI_FLAGS] - rsbs r7, r8, #(1 << 8) @ CP 0 or 1 only - movcss r7, r5, lsr #(TIF_USING_IWMMXT + 1) - bcs iwmmxt_task_enable + @ Test if we need to give access to iWMMXt coprocessors + ldr r5, [r10, #TI_FLAGS] + rsbs r7, r8, #(1 << 8) @ CP 0 or 1 only + movcss r7, r5, lsr #(TIF_USING_IWMMXT + 1) + bcs iwmmxt_task_enable #endif - enable_irq r7 - add pc, pc, r8, lsr #6 - mov r0, r0 - - mov pc, lr @ CP#0 - b do_fpe @ CP#1 (FPE) - b do_fpe @ CP#2 (FPE) - mov pc, lr @ CP#3 - mov pc, lr @ CP#4 - mov pc, lr @ CP#5 - mov pc, lr @ CP#6 - mov pc, lr @ CP#7 - mov pc, lr @ CP#8 - mov pc, lr @ CP#9 + enable_irq + add pc, pc, r8, lsr #6 + mov r0, r0 + + mov pc, lr @ CP#0 + b do_fpe @ CP#1 (FPE) + b do_fpe @ CP#2 (FPE) + mov pc, lr @ CP#3 + mov pc, lr @ CP#4 + mov pc, lr @ CP#5 + mov pc, lr @ CP#6 + mov pc, lr @ CP#7 + mov pc, lr @ CP#8 + mov pc, lr @ CP#9 #ifdef CONFIG_VFP - b do_vfp @ CP#10 (VFP) - b do_vfp @ CP#11 (VFP) + b do_vfp @ CP#10 (VFP) + b do_vfp @ CP#11 (VFP) #else - mov pc, lr @ CP#10 (VFP) - mov pc, lr @ CP#11 (VFP) + mov pc, lr @ CP#10 (VFP) + mov pc, lr @ CP#11 (VFP) #endif - mov pc, lr @ CP#12 - mov pc, lr @ CP#13 - mov pc, lr @ CP#14 (Debug) - mov pc, lr @ CP#15 (Control) + mov pc, lr @ CP#12 + mov pc, lr @ CP#13 + mov pc, lr @ CP#14 (Debug) + mov pc, lr @ CP#15 (Control) -do_fpe: ldr r4, .LCfp - add r10, r10, #TI_FPSTATE @ r10 = workspace - ldr pc, [r4] @ Call FP module USR entry point +do_fpe: + ldr r4, .LCfp + add r10, r10, #TI_FPSTATE @ r10 = workspace + ldr pc, [r4] @ Call FP module USR entry point /* * The FP module is called with these registers set: * r0 = instruction - * r5 = PC + * r2 = PC+4 * r9 = normal "successful" return address * r10 = FP workspace * lr = unrecognised FP instruction return address */ - .data + .data ENTRY(fp_enter) - .word fpundefinstr - .text - -fpundefinstr: mov r0, sp - adrsvc al, lr, ret_from_exception - b do_undefinstr - - .align 5 -__pabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go - stmia sp, {r0 - r12} @ Save r0 - r12 - ldr r4, .LCabt - add r8, sp, #S_PC - ldmia r4, {r5 - r7} @ Get USR pc, cpsr - stmia r8, {r5 - r7} @ Save USR pc, cpsr, old_r0 - stmdb r8, {sp, lr}^ @ Save sp_usr lr_usr - alignment_trap r4, r7, __temp_abt - zero_fp - enable_irq r0 @ Enable interrupts - mov r0, r5 @ address (pc) - mov r1, sp @ regs - bl do_PrefetchAbort @ call abort handler - /* fall through */ + .word fpundefinstr + .text + +fpundefinstr: + mov r0, sp + adr lr, ret_from_exception + b do_undefinstr + + .align 5 +__pabt_usr: + usr_entry abt + + enable_irq @ Enable interrupts + mov r0, r2 @ address (pc) + mov r1, sp @ regs + bl do_PrefetchAbort @ call abort handler + /* fall through */ /* * This is the return code to user mode for abort handlers */ ENTRY(ret_from_exception) - get_thread_info tsk - mov why, #0 - b ret_to_user + get_thread_info tsk + mov why, #0 + b ret_to_user /* * Register switch for ARMv3 and ARMv4 processors @@ -1399,212 +497,369 @@ ENTRY(ret_from_exception) * previous and next are guaranteed not to be the same. */ ENTRY(__switch_to) - add ip, r1, #TI_CPU_SAVE - ldr r3, [r2, #TI_CPU_DOMAIN]! - stmia ip!, {r4 - sl, fp, sp, lr} @ Store most regs on stack + add ip, r1, #TI_CPU_SAVE + ldr r3, [r2, #TI_TP_VALUE] + stmia ip!, {r4 - sl, fp, sp, lr} @ Store most regs on stack + ldr r6, [r2, #TI_CPU_DOMAIN]! #if defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_IWMMXT) - mra r4, r5, acc0 - stmia ip, {r4, r5} + mra r4, r5, acc0 + stmia ip, {r4, r5} +#endif +#if defined(CONFIG_HAS_TLS_REG) + mcr p15, 0, r3, c13, c0, 3 @ set TLS register +#elif !defined(CONFIG_TLS_REG_EMUL) + mov r4, #0xffff0fff + str r3, [r4, #-15] @ TLS val at 0xffff0ff0 #endif - mcr p15, 0, r3, c3, c0, 0 @ Set domain register + mcr p15, 0, r6, c3, c0, 0 @ Set domain register #ifdef CONFIG_VFP - @ Always disable VFP so we can lazily save/restore the old - @ state. This occurs in the context of the previous thread. - VFPFMRX r4, FPEXC - bic r4, r4, #FPEXC_ENABLE - VFPFMXR FPEXC, r4 + @ Always disable VFP so we can lazily save/restore the old + @ state. This occurs in the context of the previous thread. + VFPFMRX r4, FPEXC + bic r4, r4, #FPEXC_ENABLE + VFPFMXR FPEXC, r4 #endif #if defined(CONFIG_IWMMXT) - bl iwmmxt_task_switch + bl iwmmxt_task_switch #elif defined(CONFIG_CPU_XSCALE) - add r4, r2, #40 @ cpu_context_save->extra - ldmib r4, {r4, r5} - mar acc0, r4, r5 + add r4, r2, #40 @ cpu_context_save->extra + ldmib r4, {r4, r5} + mar acc0, r4, r5 #endif - ldmib r2, {r4 - sl, fp, sp, pc} @ Load all regs saved previously + ldmib r2, {r4 - sl, fp, sp, pc} @ Load all regs saved previously + + __INIT - __INIT /* - * Vector stubs. NOTE that we only align 'vector_IRQ' to a cache line boundary, - * and we rely on each stub being exactly 48 (1.5 cache lines) in size. This - * means that we only ever load two cache lines for this code, or one if we're - * lucky. We also copy this code to 0x200 so that we can use branches in the - * vectors, rather than ldr's. + * User helpers. + * + * These are segment of kernel provided user code reachable from user space + * at a fixed address in kernel memory. This is used to provide user space + * with some operations which require kernel help because of unimplemented + * native feature and/or instructions in many ARM CPUs. The idea is for + * this code to be executed directly in user mode for best efficiency but + * which is too intimate with the kernel counter part to be left to user + * libraries. In fact this code might even differ from one CPU to another + * depending on the available instruction set and restrictions like on + * SMP systems. In other words, the kernel reserves the right to change + * this code as needed without warning. Only the entry points and their + * results are guaranteed to be stable. + * + * Each segment is 32-byte aligned and will be moved to the top of the high + * vector page. New segments (if ever needed) must be added in front of + * existing ones. This mechanism should be used only for things that are + * really small and justified, and not be abused freely. + * + * User space is expected to implement those things inline when optimizing + * for a processor that has the necessary native support, but only if such + * resulting binaries are already to be incompatible with earlier ARM + * processors due to the use of unsupported instructions other than what + * is provided here. In other words don't make binaries unable to run on + * earlier processors just for the sake of not using these kernel helpers + * if your compiled code is not going to use the new instructions for other + * purpose. */ - .align 5 + + .align 5 + .globl __kuser_helper_start +__kuser_helper_start: + +/* + * Reference prototype: + * + * int __kernel_cmpxchg(int oldval, int newval, int *ptr) + * + * Input: + * + * r0 = oldval + * r1 = newval + * r2 = ptr + * lr = return address + * + * Output: + * + * r0 = returned value (zero or non-zero) + * C flag = set if r0 == 0, clear if r0 != 0 + * + * Clobbered: + * + * r3, ip, flags + * + * Definition and user space usage example: + * + * typedef int (__kernel_cmpxchg_t)(int oldval, int newval, int *ptr); + * #define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0) + * + * Atomically store newval in *ptr if *ptr is equal to oldval for user space. + * Return zero if *ptr was changed or non-zero if no exchange happened. + * The C flag is also set if *ptr was changed to allow for assembly + * optimization in the calling code. + * + * For example, a user space atomic_add implementation could look like this: + * + * #define atomic_add(ptr, val) \ + * ({ register unsigned int *__ptr asm("r2") = (ptr); \ + * register unsigned int __result asm("r1"); \ + * asm volatile ( \ + * "1: @ atomic_add\n\t" \ + * "ldr r0, [r2]\n\t" \ + * "mov r3, #0xffff0fff\n\t" \ + * "add lr, pc, #4\n\t" \ + * "add r1, r0, %2\n\t" \ + * "add pc, r3, #(0xffff0fc0 - 0xffff0fff)\n\t" \ + * "bcc 1b" \ + * : "=&r" (__result) \ + * : "r" (__ptr), "rIL" (val) \ + * : "r0","r3","ip","lr","cc","memory" ); \ + * __result; }) + */ + +__kuser_cmpxchg: @ 0xffff0fc0 + +#if defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) + + /* + * 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: + * + * We set the Z flag before loading oldval. If ever an exception + * occurs we can not be sure the loaded value will still be the same + * when the exception returns, therefore the user exception handler + * will clear the Z flag whenever the interrupted user code was + * actually from the kernel address space (see the usr_entry macro). + * + * The post-increment on the str is used to prevent a race with an + * exception happening just after the str instruction which would + * clear the Z flag although the exchange was done. + */ + teq ip, ip @ set Z flag + ldr ip, [r2] @ load current val + add r3, r2, #1 @ prepare store ptr + teqeq ip, r0 @ compare with oldval if still allowed + streq r1, [r3, #-1]! @ store newval if still allowed + subs r0, r2, r3 @ if r2 == r3 the str occured + mov pc, lr + +#else + + ldrex r3, [r2] + subs r3, r3, r0 + strexeq r3, r1, [r2] + rsbs r0, r3, #0 + mov pc, lr + +#endif + + .align 5 + +/* + * Reference prototype: + * + * int __kernel_get_tls(void) + * + * Input: + * + * lr = return address + * + * Output: + * + * r0 = TLS value + * + * Clobbered: + * + * the Z flag might be lost + * + * Definition and user space usage example: + * + * typedef int (__kernel_get_tls_t)(void); + * #define __kernel_get_tls (*(__kernel_get_tls_t *)0xffff0fe0) + * + * Get the TLS value as previously set via the __ARM_NR_set_tls syscall. + * + * This could be used as follows: + * + * #define __kernel_get_tls() \ + * ({ register unsigned int __val asm("r0"); \ + * asm( "mov r0, #0xffff0fff; mov lr, pc; sub pc, r0, #31" \ + * : "=r" (__val) : : "lr","cc" ); \ + * __val; }) + */ + +__kuser_get_tls: @ 0xffff0fe0 + +#if !defined(CONFIG_HAS_TLS_REG) && !defined(CONFIG_TLS_REG_EMUL) + + ldr r0, [pc, #(16 - 8)] @ TLS stored at 0xffff0ff0 + mov pc, lr + +#else + + mrc p15, 0, r0, c13, c0, 3 @ read TLS register + mov pc, lr + +#endif + + .rep 5 + .word 0 @ pad up to __kuser_helper_version + .endr + +/* + * Reference declaration: + * + * extern unsigned int __kernel_helper_version; + * + * Definition and user space usage example: + * + * #define __kernel_helper_version (*(unsigned int *)0xffff0ffc) + * + * User space may read this to determine the curent number of helpers + * available. + */ + +__kuser_helper_version: @ 0xffff0ffc + .word ((__kuser_helper_end - __kuser_helper_start) >> 5) + + .globl __kuser_helper_end +__kuser_helper_end: + + +/* + * Vector stubs. + * + * This code is copied to 0xffff0200 so we can use branches in the + * vectors, rather than ldr's. Note that this code must not + * exceed 0x300 bytes. + * + * Common stub entry macro: + * Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC + */ + .macro vector_stub, name, sym, correction=0 + .align 5 + +vector_\name: + ldr r13, .LCs\sym + .if \correction + sub lr, lr, #\correction + .endif + str lr, [r13] @ save lr_IRQ + mrs lr, spsr + str lr, [r13, #4] @ save spsr_IRQ + @ + @ now branch to the relevant MODE handling routine + @ + mrs r13, cpsr + bic r13, r13, #MODE_MASK + orr r13, r13, #SVC_MODE + msr spsr_cxsf, r13 @ switch to SVC_32 mode + + and lr, lr, #15 + ldr lr, [pc, lr, lsl #2] + movs pc, lr @ Changes mode and branches + .endm + + .globl __stubs_start __stubs_start: /* * Interrupt dispatcher - * Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC */ -vector_IRQ: @ - @ save mode specific registers - @ - ldr r13, .LCsirq - sub lr, lr, #4 - str lr, [r13] @ save lr_IRQ - mrs lr, spsr - str lr, [r13, #4] @ save spsr_IRQ - @ - @ now branch to the relevant MODE handling routine - @ - mrs r13, cpsr - bic r13, r13, #MODE_MASK - orr r13, r13, #MODE_SVC - msr spsr_cxsf, r13 @ switch to SVC_32 mode - - and lr, lr, #15 - ldr lr, [pc, lr, lsl #2] - movs pc, lr @ Changes mode and branches - -.LCtab_irq: .word __irq_usr @ 0 (USR_26 / USR_32) - .word __irq_invalid @ 1 (FIQ_26 / FIQ_32) - .word __irq_invalid @ 2 (IRQ_26 / IRQ_32) - .word __irq_svc @ 3 (SVC_26 / SVC_32) - .word __irq_invalid @ 4 - .word __irq_invalid @ 5 - .word __irq_invalid @ 6 - .word __irq_invalid @ 7 - .word __irq_invalid @ 8 - .word __irq_invalid @ 9 - .word __irq_invalid @ a - .word __irq_invalid @ b - .word __irq_invalid @ c - .word __irq_invalid @ d - .word __irq_invalid @ e - .word __irq_invalid @ f - - .align 5 + vector_stub irq, irq, 4 + + .long __irq_usr @ 0 (USR_26 / USR_32) + .long __irq_invalid @ 1 (FIQ_26 / FIQ_32) + .long __irq_invalid @ 2 (IRQ_26 / IRQ_32) + .long __irq_svc @ 3 (SVC_26 / SVC_32) + .long __irq_invalid @ 4 + .long __irq_invalid @ 5 + .long __irq_invalid @ 6 + .long __irq_invalid @ 7 + .long __irq_invalid @ 8 + .long __irq_invalid @ 9 + .long __irq_invalid @ a + .long __irq_invalid @ b + .long __irq_invalid @ c + .long __irq_invalid @ d + .long __irq_invalid @ e + .long __irq_invalid @ f /* - * Data abort dispatcher - dispatches it to the correct handler for the processor mode + * Data abort dispatcher * Enter in ABT mode, spsr = USR CPSR, lr = USR PC */ -vector_data: @ - @ save mode specific registers - @ - ldr r13, .LCsabt - sub lr, lr, #8 - str lr, [r13] - mrs lr, spsr - str lr, [r13, #4] - @ - @ now branch to the relevant MODE handling routine - @ - mrs r13, cpsr - bic r13, r13, #MODE_MASK - orr r13, r13, #MODE_SVC - msr spsr_cxsf, r13 @ switch to SVC_32 mode - - and lr, lr, #15 - ldr lr, [pc, lr, lsl #2] - movs pc, lr @ Changes mode and branches - -.LCtab_dabt: .word __dabt_usr @ 0 (USR_26 / USR_32) - .word __dabt_invalid @ 1 (FIQ_26 / FIQ_32) - .word __dabt_invalid @ 2 (IRQ_26 / IRQ_32) - .word __dabt_svc @ 3 (SVC_26 / SVC_32) - .word __dabt_invalid @ 4 - .word __dabt_invalid @ 5 - .word __dabt_invalid @ 6 - .word __dabt_invalid @ 7 - .word __dabt_invalid @ 8 - .word __dabt_invalid @ 9 - .word __dabt_invalid @ a - .word __dabt_invalid @ b - .word __dabt_invalid @ c - .word __dabt_invalid @ d - .word __dabt_invalid @ e - .word __dabt_invalid @ f - - .align 5 + vector_stub dabt, abt, 8 + + .long __dabt_usr @ 0 (USR_26 / USR_32) + .long __dabt_invalid @ 1 (FIQ_26 / FIQ_32) + .long __dabt_invalid @ 2 (IRQ_26 / IRQ_32) + .long __dabt_svc @ 3 (SVC_26 / SVC_32) + .long __dabt_invalid @ 4 + .long __dabt_invalid @ 5 + .long __dabt_invalid @ 6 + .long __dabt_invalid @ 7 + .long __dabt_invalid @ 8 + .long __dabt_invalid @ 9 + .long __dabt_invalid @ a + .long __dabt_invalid @ b + .long __dabt_invalid @ c + .long __dabt_invalid @ d + .long __dabt_invalid @ e + .long __dabt_invalid @ f /* - * Prefetch abort dispatcher - dispatches it to the correct handler for the processor mode + * Prefetch abort dispatcher * Enter in ABT mode, spsr = USR CPSR, lr = USR PC */ -vector_prefetch: - @ - @ save mode specific registers - @ - ldr r13, .LCsabt - sub lr, lr, #4 - str lr, [r13] @ save lr_ABT - mrs lr, spsr - str lr, [r13, #4] @ save spsr_ABT - @ - @ now branch to the relevant MODE handling routine - @ - mrs r13, cpsr - bic r13, r13, #MODE_MASK - orr r13, r13, #MODE_SVC - msr spsr_cxsf, r13 @ switch to SVC_32 mode - - ands lr, lr, #15 - ldr lr, [pc, lr, lsl #2] - movs pc, lr - -.LCtab_pabt: .word __pabt_usr @ 0 (USR_26 / USR_32) - .word __pabt_invalid @ 1 (FIQ_26 / FIQ_32) - .word __pabt_invalid @ 2 (IRQ_26 / IRQ_32) - .word __pabt_svc @ 3 (SVC_26 / SVC_32) - .word __pabt_invalid @ 4 - .word __pabt_invalid @ 5 - .word __pabt_invalid @ 6 - .word __pabt_invalid @ 7 - .word __pabt_invalid @ 8 - .word __pabt_invalid @ 9 - .word __pabt_invalid @ a - .word __pabt_invalid @ b - .word __pabt_invalid @ c - .word __pabt_invalid @ d - .word __pabt_invalid @ e - .word __pabt_invalid @ f - - .align 5 + vector_stub pabt, abt, 4 + + .long __pabt_usr @ 0 (USR_26 / USR_32) + .long __pabt_invalid @ 1 (FIQ_26 / FIQ_32) + .long __pabt_invalid @ 2 (IRQ_26 / IRQ_32) + .long __pabt_svc @ 3 (SVC_26 / SVC_32) + .long __pabt_invalid @ 4 + .long __pabt_invalid @ 5 + .long __pabt_invalid @ 6 + .long __pabt_invalid @ 7 + .long __pabt_invalid @ 8 + .long __pabt_invalid @ 9 + .long __pabt_invalid @ a + .long __pabt_invalid @ b + .long __pabt_invalid @ c + .long __pabt_invalid @ d + .long __pabt_invalid @ e + .long __pabt_invalid @ f /* - * Undef instr entry dispatcher - dispatches it to the correct handler for the processor mode + * Undef instr entry dispatcher * Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC */ -vector_undefinstr: - @ - @ save mode specific registers - @ - ldr r13, .LCsund - str lr, [r13] @ save lr_UND - mrs lr, spsr - str lr, [r13, #4] @ save spsr_UND - @ - @ now branch to the relevant MODE handling routine - @ - mrs r13, cpsr - bic r13, r13, #MODE_MASK - orr r13, r13, #MODE_SVC - msr spsr_cxsf, r13 @ switch to SVC_32 mode - - and lr, lr, #15 - ldr lr, [pc, lr, lsl #2] - movs pc, lr @ Changes mode and branches - -.LCtab_und: .word __und_usr @ 0 (USR_26 / USR_32) - .word __und_invalid @ 1 (FIQ_26 / FIQ_32) - .word __und_invalid @ 2 (IRQ_26 / IRQ_32) - .word __und_svc @ 3 (SVC_26 / SVC_32) - .word __und_invalid @ 4 - .word __und_invalid @ 5 - .word __und_invalid @ 6 - .word __und_invalid @ 7 - .word __und_invalid @ 8 - .word __und_invalid @ 9 - .word __und_invalid @ a - .word __und_invalid @ b - .word __und_invalid @ c - .word __und_invalid @ d - .word __und_invalid @ e - .word __und_invalid @ f - - .align 5 + vector_stub und, und + + .long __und_usr @ 0 (USR_26 / USR_32) + .long __und_invalid @ 1 (FIQ_26 / FIQ_32) + .long __und_invalid @ 2 (IRQ_26 / IRQ_32) + .long __und_svc @ 3 (SVC_26 / SVC_32) + .long __und_invalid @ 4 + .long __und_invalid @ 5 + .long __und_invalid @ 6 + .long __und_invalid @ 7 + .long __und_invalid @ 8 + .long __und_invalid @ 9 + .long __und_invalid @ a + .long __und_invalid @ b + .long __und_invalid @ c + .long __und_invalid @ d + .long __und_invalid @ e + .long __und_invalid @ f + + .align 5 /*============================================================================= * Undefined FIQs @@ -1616,8 +871,9 @@ vector_undefinstr: * other mode than FIQ... Ok you can switch to another mode, but you can't * get out of that mode without clobbering one register. */ -vector_FIQ: disable_fiq - subs pc, lr, #4 +vector_fiq: + disable_fiq + subs pc, lr, #4 /*============================================================================= * Address exception handler @@ -1627,70 +883,65 @@ vector_FIQ: disable_fiq */ vector_addrexcptn: - b vector_addrexcptn + b vector_addrexcptn /* * We group all the following data together to optimise * for CPUs with separate I & D caches. */ - .align 5 + .align 5 -.LCvswi: .word vector_swi +.LCvswi: + .word vector_swi -.LCsirq: .word __temp_irq -.LCsund: .word __temp_und -.LCsabt: .word __temp_abt +.LCsirq: + .word __temp_irq +.LCsund: + .word __temp_und +.LCsabt: + .word __temp_abt + .globl __stubs_end __stubs_end: - .equ __real_stubs_start, .LCvectors + 0x200 - -.LCvectors: swi SYS_ERROR0 - b __real_stubs_start + (vector_undefinstr - __stubs_start) - ldr pc, __real_stubs_start + (.LCvswi - __stubs_start) - b __real_stubs_start + (vector_prefetch - __stubs_start) - b __real_stubs_start + (vector_data - __stubs_start) - b __real_stubs_start + (vector_addrexcptn - __stubs_start) - b __real_stubs_start + (vector_IRQ - __stubs_start) - b __real_stubs_start + (vector_FIQ - __stubs_start) - -ENTRY(__trap_init) - stmfd sp!, {r4 - r6, lr} - - mov r0, #0xff000000 - orr r0, r0, #0x00ff0000 @ high vectors position - adr r1, .LCvectors @ set up the vectors - ldmia r1, {r1, r2, r3, r4, r5, r6, ip, lr} - stmia r0, {r1, r2, r3, r4, r5, r6, ip, lr} - - add r2, r0, #0x200 - adr r0, __stubs_start @ copy stubs to 0x200 - adr r1, __stubs_end -1: ldr r3, [r0], #4 - str r3, [r2], #4 - cmp r0, r1 - blt 1b - LOADREGS(fd, sp!, {r4 - r6, pc}) - - .data + .equ stubs_offset, __vectors_start + 0x200 - __stubs_start + + .globl __vectors_start +__vectors_start: + swi SYS_ERROR0 + b vector_und + stubs_offset + ldr pc, .LCvswi + stubs_offset + b vector_pabt + stubs_offset + b vector_dabt + stubs_offset + b vector_addrexcptn + stubs_offset + b vector_irq + stubs_offset + b vector_fiq + stubs_offset + + .globl __vectors_end +__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 +__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: - .space 4 + .space 4 cr_no_alignment: - .space 4 + .space 4 diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 946c50c2a..473387729 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -14,10 +14,22 @@ #include #include +#include #include #include #include #include +#include +#include + +#define PROCINFO_MMUFLAGS 8 +#define PROCINFO_INITFUNC 12 + +#define MACHINFO_TYPE 0 +#define MACHINFO_PHYSRAM 4 +#define MACHINFO_PHYSIO 8 +#define MACHINFO_PGOFFIO 12 +#define MACHINFO_NAME 16 #ifndef CONFIG_XIP_KERNEL /* @@ -86,107 +98,143 @@ * circumstances, zImage) is for. */ __INIT - .type stext, #function + .type stext, %function ENTRY(stext) - mov r12, r0 - mov r0, #PSR_F_BIT | PSR_I_BIT | MODE_SVC @ make sure svc mode - msr cpsr_c, r0 @ and all irqs disabled - bl __lookup_processor_type - teq r10, #0 @ invalid processor? - moveq r0, #'p' @ yes, error 'p' - beq __error - bl __lookup_architecture_type - teq r7, #0 @ invalid architecture? - moveq r0, #'a' @ yes, error 'a' - beq __error + msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | MODE_SVC @ ensure svc mode + @ and irqs disabled + bl __lookup_processor_type @ r5=procinfo r9=cpuid + movs r10, r5 @ invalid processor (r5=0)? + beq __error_p @ yes, error 'p' + bl __lookup_machine_type @ r5=machinfo + movs r8, r5 @ invalid machine (r5=0)? + beq __error_a @ yes, error 'a' bl __create_page_tables /* * The following calls CPU specific code in a position independent * manner. See arch/arm/mm/proc-*.S for details. r10 = base of - * xxx_proc_info structure selected by __lookup_architecture_type + * xxx_proc_info structure selected by __lookup_machine_type * above. On return, the CPU will be ready for the MMU to be * turned on, and r0 will hold the CPU control register value. */ - adr lr, __turn_mmu_on @ return (PIC) address - add pc, r10, #12 + ldr r13, __switch_data @ address to jump to after + @ mmu has been enabled + adr lr, __enable_mmu @ return (PIC) address + add pc, r10, #PROCINFO_INITFUNC .type __switch_data, %object __switch_data: .long __mmap_switched - .long __data_loc @ r2 - .long __data_start @ r3 - .long __bss_start @ r4 - .long _end @ r5 - .long processor_id @ r6 - .long __machine_arch_type @ r7 - .long cr_alignment @ r8 - .long init_thread_union+8192 @ sp - -/* - * Enable the MMU. This completely changes the structure of the visible - * memory space. You will not be able to trace execution through this. - * If you have an enquiry about this, *please* check the linux-arm-kernel - * mailing list archives BEFORE sending another post to the list. - */ - .align 5 - .type __turn_mmu_on, %function -__turn_mmu_on: - ldr lr, __switch_data -#ifdef CONFIG_ALIGNMENT_TRAP - orr r0, r0, #2 @ ...........A. -#endif - mcr p15, 0, r0, c1, c0, 0 @ write control reg - mrc p15, 0, r3, c0, c0, 0 @ read id reg - mov r3, r3 - mov r3, r3 - mov pc, lr + .long __data_loc @ r4 + .long __data_start @ r5 + .long __bss_start @ r6 + .long _end @ r7 + .long processor_id @ r4 + .long __machine_arch_type @ r5 + .long cr_alignment @ r6 + .long init_thread_union + THREAD_START_SP @ sp /* * The following fragment of code is executed with the MMU on, and uses * absolute addresses; this is not position independent. * - * r0 = processor control register + * r0 = cp#15 control register * r1 = machine ID * r9 = processor ID - * r12 = value of r0 when kernel was called (currently always zero) */ - .align 5 + .type __mmap_switched, %function __mmap_switched: - adr r2, __switch_data + 4 - ldmia r2, {r2, r3, r4, r5, r6, r7, r8, sp} + adr r3, __switch_data + 4 - cmp r2, r3 @ Copy data segment if needed -1: cmpne r3, r4 - ldrne fp, [r2], #4 - strne fp, [r3], #4 + ldmia r3!, {r4, r5, r6, r7} + cmp r4, r5 @ Copy data segment if needed +1: cmpne r5, r6 + ldrne fp, [r4], #4 + strne fp, [r5], #4 bne 1b mov fp, #0 @ Clear BSS (and zero fp) -1: cmp r4, r5 - strcc fp, [r4],#4 +1: cmp r6, r7 + strcc fp, [r6],#4 bcc 1b - str r9, [r6] @ Save processor ID - str r1, [r7] @ Save machine type - bic r2, r0, #2 @ Clear 'A' bit - stmia r8, {r0, r2} @ Save control register values + ldmia r3, {r4, r5, r6, sp} + str r9, [r4] @ Save processor ID + str r1, [r5] @ Save machine type + bic r4, r0, #CR_A @ Clear 'A' bit + stmia r6, {r0, r4} @ Save control register values b start_kernel +/* + * Setup common bits before finally enabling the MMU. Essentially + * this is just loading the page table pointer and domain access + * registers. + */ + .type __enable_mmu, %function +__enable_mmu: +#ifdef CONFIG_ALIGNMENT_TRAP + orr r0, r0, #CR_A +#else + bic r0, r0, #CR_A +#endif +#ifdef CONFIG_CPU_DCACHE_DISABLE + bic r0, r0, #CR_C +#endif +#ifdef CONFIG_CPU_BPREDICT_DISABLE + bic r0, r0, #CR_Z +#endif +#ifdef CONFIG_CPU_ICACHE_DISABLE + bic r0, r0, #CR_I +#endif + mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \ + domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \ + domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \ + domain_val(DOMAIN_IO, DOMAIN_CLIENT)) + mcr p15, 0, r5, c3, c0, 0 @ load domain access register + mcr p15, 0, r4, c2, c0, 0 @ load page table pointer + b __turn_mmu_on + +/* + * Enable the MMU. This completely changes the structure of the visible + * memory space. You will not be able to trace execution through this. + * If you have an enquiry about this, *please* check the linux-arm-kernel + * mailing list archives BEFORE sending another post to the list. + * + * r0 = cp#15 control register + * r13 = *virtual* address to jump to upon completion + * + * other registers depend on the function called upon completion + */ + .align 5 + .type __turn_mmu_on, %function +__turn_mmu_on: + mov r0, r0 + mcr p15, 0, r0, c1, c0, 0 @ write control reg + mrc p15, 0, r3, c0, c0, 0 @ read id reg + mov r3, r3 + mov r3, r3 + mov pc, r13 + + /* * Setup the initial page tables. We only setup the barest * amount which are required to get the kernel running, which * generally means mapping in the kernel code. * - * r5 = physical address of start of RAM - * r6 = physical IO address - * r7 = byte offset into page tables for IO - * r8 = page table flags + * r8 = machinfo + * r9 = cpuid + * r10 = procinfo + * + * Returns: + * r0, r3, r5, r6, r7 corrupted + * r4 = physical page table address */ + .type __create_page_tables, %function __create_page_tables: + ldr r5, [r8, #MACHINFO_PHYSRAM] @ physram pgtbl r4, r5 @ page table address /* @@ -194,23 +242,25 @@ __create_page_tables: */ mov r0, r4 mov r3, #0 - add r2, r0, #0x4000 + add r6, r0, #0x4000 1: str r3, [r0], #4 str r3, [r0], #4 str r3, [r0], #4 str r3, [r0], #4 - teq r0, r2 + teq r0, r6 bne 1b + ldr r7, [r10, #PROCINFO_MMUFLAGS] @ mmuflags + /* * Create identity mapping for first MB of kernel to * cater for the MMU enable. This identity mapping * will be removed by paging_init(). We use our current program * counter to determine corresponding section base address. */ - mov r2, pc, lsr #20 @ start of kernel section - add r3, r8, r2, lsl #20 @ flags + kernel base - str r3, [r4, r2, lsl #2] @ identity mapping + mov r6, pc, lsr #20 @ start of kernel section + orr r3, r7, r6, lsl #20 @ flags + kernel base + str r3, [r4, r6, lsl #2] @ identity mapping /* * Now setup the pagetables for our kernel direct @@ -231,8 +281,8 @@ __create_page_tables: * Then map first 1MB of ram in case it contains our boot params. */ add r0, r4, #VIRT_OFFSET >> 18 - add r2, r5, r8 - str r2, [r0] + orr r6, r5, r7 + str r6, [r0] #ifdef CONFIG_XIP_KERNEL /* @@ -242,15 +292,15 @@ __create_page_tables: sub r3, r4, r5 mov r3, r3, lsr #20 add r0, r0, r3, lsl #2 - add r2, r2, r3, lsl #20 - str r2, [r0], #4 - add r2, r2, #(1 << 20) - str r2, [r0], #4 - add r2, r2, #(1 << 20) - str r2, [r0] + add r6, r6, r3, lsl #20 + str r6, [r0], #4 + add r6, r6, #(1 << 20) + str r6, [r0], #4 + add r6, r6, #(1 << 20) + str r6, [r0] #endif - bic r8, r8, #0x0c @ turn off cacheable + bic r7, r7, #0x0c @ turn off cacheable @ and bufferable bits #ifdef CONFIG_DEBUG_LL /* @@ -258,15 +308,17 @@ __create_page_tables: * This allows debug messages to be output * via a serial console before paging_init. */ - add r0, r4, r7 - rsb r3, r7, #0x4000 @ PTRS_PER_PGD*sizeof(long) - cmp r3, #0x0800 - addge r2, r0, #0x0800 - addlt r2, r0, r3 - orr r3, r6, r8 + ldr r3, [r8, #MACHINFO_PGOFFIO] + add r0, r4, r3 + rsb r3, r3, #0x4000 @ PTRS_PER_PGD*sizeof(long) + cmp r3, #0x0800 @ limit to 512MB + movhi r3, #0x0800 + add r6, r0, r3 + ldr r3, [r8, #MACHINFO_PHYSIO] + orr r3, r3, r7 1: str r3, [r0], #4 add r3, r3, #1 << 20 - teq r0, r2 + teq r0, r6 bne 1b #if defined(CONFIG_ARCH_NETWINDER) || defined(CONFIG_ARCH_CATS) /* @@ -278,7 +330,7 @@ __create_page_tables: bne 1f add r0, r4, #0x3fc0 @ ff000000 mov r3, #0x7c000000 - orr r3, r3, r8 + orr r3, r3, r7 str r3, [r0], #4 add r3, r3, #1 << 20 str r3, [r0], #4 @@ -293,7 +345,7 @@ __create_page_tables: */ add r0, r4, #0x80 @ 02000000 mov r3, #0x02000000 - orr r3, r3, r8 + orr r3, r3, r7 str r3, [r0] add r0, r4, #0x3600 @ d8000000 str r3, [r0] @@ -308,21 +360,59 @@ __create_page_tables: * ought to tell the user, but since we don't have any guarantee that * we're even running on the right architecture, we do virtually nothing. * - * r0 = ascii error character: - * a = invalid architecture - * p = invalid processor - * i = invalid calling convention - * - * Generally, only serious errors cause this. + * If CONFIG_DEBUG_LL is set we try to print out something about the error + * and hope for the best (useful if bootloader fails to pass a proper + * machine ID for example). */ -__error: + + .type __error_p, %function +__error_p: +#ifdef CONFIG_DEBUG_LL + adr r0, str_p1 + bl printascii + b __error +str_p1: .asciz "\nError: unrecognized/unsupported processor variant.\n" + .align +#endif + + .type __error_a, %function +__error_a: #ifdef CONFIG_DEBUG_LL - mov r8, r0 @ preserve r0 - adr r0, err_str + mov r4, r1 @ preserve machine ID + adr r0, str_a1 + bl printascii + mov r0, r4 + bl printhex8 + adr r0, str_a2 bl printascii - mov r0, r8 + adr r3, 3f + ldmia r3, {r4, r5, r6} @ get machine desc list + sub r4, r3, r4 @ get offset between virt&phys + add r5, r5, r4 @ convert virt addresses to + add r6, r6, r4 @ physical address space +1: ldr r0, [r5, #MACHINFO_TYPE] @ get machine type + bl printhex8 + mov r0, #'\t' bl printch + ldr r0, [r5, #MACHINFO_NAME] @ get machine name + add r0, r0, r4 + bl printascii + mov r0, #'\n' + bl printch + add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc + cmp r5, r6 + blo 1b + adr r0, str_a3 + bl printascii + b __error +str_a1: .asciz "\nError: unrecognized/unsupported machine ID (r1 = 0x" +str_a2: .asciz ").\n\nAvailable machine support:\n\nID (hex)\tNAME\n" +str_a3: .asciz "\nPlease check your kernel config and/or bootloader.\n" + .align #endif + + .type __error, %function +__error: #ifdef CONFIG_ARCH_RPC /* * Turn the screen red on a error - RiscPC only. @@ -339,11 +429,6 @@ __error: 1: mov r0, r0 b 1b -#ifdef CONFIG_DEBUG_LL -err_str: - .asciz "\nError: " - .align -#endif /* * Read processor ID register (CP#15, CR0), and look up in the linker-built @@ -353,35 +438,44 @@ err_str: * calculate the offset. * * Returns: - * r5, r6, r7 corrupted - * r8 = page table flags - * r9 = processor ID - * r10 = pointer to processor structure + * r3, r4, r6 corrupted + * r5 = proc_info pointer in physical address space + * r9 = cpuid */ + .type __lookup_processor_type, %function __lookup_processor_type: - adr r5, 2f - ldmia r5, {r7, r9, r10} - sub r5, r5, r10 @ convert addresses - add r7, r7, r5 @ to our address space - add r10, r9, r5 + adr r3, 3f + ldmda r3, {r5, r6, r9} + sub r3, r3, r9 @ get offset between virt&phys + add r5, r5, r3 @ convert virt addresses to + add r6, r6, r3 @ physical address space mrc p15, 0, r9, c0, c0 @ get processor id -1: ldmia r10, {r5, r6, r8} @ value, mask, mmuflags - and r6, r6, r9 @ mask wanted bits - teq r5, r6 - moveq pc, lr - add r10, r10, #PROC_INFO_SZ @ sizeof(proc_info_list) - cmp r10, r7 - blt 1b - mov r10, #0 @ unknown processor - mov pc, lr +1: ldmia r5, {r3, r4} @ value, mask + and r4, r4, r9 @ mask wanted bits + teq r3, r4 + beq 2f + add r5, r5, #PROC_INFO_SZ @ sizeof(proc_info_list) + cmp r5, r6 + blo 1b + mov r5, #0 @ unknown processor +2: mov pc, lr + +/* + * This provides a C-API version of the above function. + */ +ENTRY(lookup_processor_type) + stmfd sp!, {r4 - r6, r9, lr} + bl __lookup_processor_type + mov r0, r5 + ldmfd sp!, {r4 - r6, r9, pc} /* * Look in include/asm-arm/procinfo.h and arch/arm/kernel/arch.[ch] for * more information about the __proc_info and __arch_info structures. */ -2: .long __proc_info_end .long __proc_info_begin - .long 2b + .long __proc_info_end +3: .long . .long __arch_info_begin .long __arch_info_end @@ -393,24 +487,31 @@ __lookup_processor_type: * * r1 = machine architecture number * Returns: - * r2, r3, r4 corrupted - * r5 = physical start address of RAM - * r6 = physical address of IO - * r7 = byte offset into page tables for IO + * r3, r4, r6 corrupted + * r5 = mach_info pointer in physical address space */ -__lookup_architecture_type: - adr r4, 2b - ldmia r4, {r2, r3, r5, r6, r7} @ throw away r2, r3 - sub r5, r4, r5 @ convert addresses - add r4, r6, r5 @ to our address space - add r7, r7, r5 -1: ldr r5, [r4] @ get machine type - teq r5, r1 @ matches loader number? + .type __lookup_machine_type, %function +__lookup_machine_type: + adr r3, 3b + ldmia r3, {r4, r5, r6} + sub r3, r3, r4 @ get offset between virt&phys + add r5, r5, r3 @ convert virt addresses to + add r6, r6, r3 @ physical address space +1: ldr r3, [r5, #MACHINFO_TYPE] @ get machine type + teq r3, r1 @ matches loader number? beq 2f @ found - add r4, r4, #SIZEOF_MACHINE_DESC @ next machine_desc - cmp r4, r7 - blt 1b - mov r7, #0 @ unknown architecture - mov pc, lr -2: ldmib r4, {r5, r6, r7} @ found, get results - mov pc, lr + add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc + cmp r5, r6 + blo 1b + mov r5, #0 @ unknown machine +2: mov pc, lr + +/* + * This provides a C-API version of the above function. + */ +ENTRY(lookup_machine_type) + stmfd sp!, {r4 - r6, lr} + mov r1, r0 + bl __lookup_machine_type + mov r0, r5 + ldmfd sp!, {r4 - r6, pc} diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 5b35e76c3..ff187f430 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -48,12 +49,19 @@ static int noirqdebug; static volatile unsigned long irq_err_count; -static spinlock_t irq_controller_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(irq_controller_lock); static LIST_HEAD(irq_pending); struct irqdesc irq_desc[NR_IRQS]; void (*init_arch_irq)(void) __initdata = NULL; +/* + * No architecture-specific irq_finish function defined in arm/arch/irqs.h. + */ +#ifndef irq_finish +#define irq_finish(irq) do { } while (0) +#endif + /* * Dummy mask/unmask handler */ @@ -85,6 +93,23 @@ static struct irqdesc bad_irq_desc = { .disable_depth = 1, }; +#ifdef CONFIG_SMP +void synchronize_irq(unsigned int irq) +{ + struct irqdesc *desc = irq_desc + irq; + + while (desc->running) + barrier(); +} +EXPORT_SYMBOL(synchronize_irq); + +#define smp_set_running(desc) do { desc->running = 1; } while (0) +#define smp_clear_running(desc) do { desc->running = 0; } while (0) +#else +#define smp_set_running(desc) do { } while (0) +#define smp_clear_running(desc) do { } while (0) +#endif + /** * disable_irq_nosync - disable an irq without waiting * @irq: Interrupt to disable @@ -231,6 +256,9 @@ unlock: } else if (i == NR_IRQS) { #ifdef CONFIG_ARCH_ACORN show_fiq_list(p, v); +#endif +#ifdef CONFIG_SMP + show_ipi_list(p); #endif seq_printf(p, "Err: %10lu\n", irq_err_count); } @@ -329,18 +357,22 @@ void do_simple_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) { struct irqaction *action; - const int cpu = smp_processor_id(); + const unsigned int cpu = smp_processor_id(); desc->triggered = 1; kstat_cpu(cpu).irqs[irq]++; + smp_set_running(desc); + action = desc->action; if (action) { int ret = __do_irq(irq, action, regs); if (ret != IRQ_HANDLED) report_bad_irq(irq, regs, desc, ret); } + + smp_clear_running(desc); } /* @@ -350,7 +382,7 @@ do_simple_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) void do_edge_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) { - const int cpu = smp_processor_id(); + const unsigned int cpu = smp_processor_id(); desc->triggered = 1; @@ -414,7 +446,7 @@ void do_level_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) { struct irqaction *action; - const int cpu = smp_processor_id(); + const unsigned int cpu = smp_processor_id(); desc->triggered = 1; @@ -426,6 +458,8 @@ do_level_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) if (likely(!desc->disable_depth)) { kstat_cpu(cpu).irqs[irq]++; + smp_set_running(desc); + /* * Return with this interrupt masked if no action */ @@ -440,6 +474,8 @@ do_level_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) !check_irq_lock(desc, irq, regs))) desc->chip->unmask(irq); } + + smp_clear_running(desc); } } @@ -503,6 +539,8 @@ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) if (!list_empty(&irq_pending)) do_pending_irqs(regs); + irq_finish(irq); + spin_unlock(&irq_controller_lock); irq_exit(); } @@ -878,8 +916,97 @@ out: EXPORT_SYMBOL(probe_irq_off); +#ifdef CONFIG_SMP +static void route_irq(struct irqdesc *desc, unsigned int irq, unsigned int cpu) +{ + pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", irq, desc->cpu, cpu); + + spin_lock_irq(&irq_controller_lock); + desc->cpu = cpu; + desc->chip->set_cpu(desc, irq, cpu); + spin_unlock_irq(&irq_controller_lock); +} + +#ifdef CONFIG_PROC_FS +static int +irq_affinity_read_proc(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + struct irqdesc *desc = irq_desc + ((int)data); + int len = cpumask_scnprintf(page, count, desc->affinity); + + if (count - len < 2) + return -EINVAL; + page[len++] = '\n'; + page[len] = '\0'; + + return len; +} + +static int +irq_affinity_write_proc(struct file *file, const char __user *buffer, + unsigned long count, void *data) +{ + unsigned int irq = (unsigned int)data; + struct irqdesc *desc = irq_desc + irq; + cpumask_t affinity, tmp; + int ret = -EIO; + + if (!desc->chip->set_cpu) + goto out; + + ret = cpumask_parse(buffer, count, affinity); + if (ret) + goto out; + + cpus_and(tmp, affinity, cpu_online_map); + if (cpus_empty(tmp)) { + ret = -EINVAL; + goto out; + } + + desc->affinity = affinity; + route_irq(desc, irq, first_cpu(tmp)); + ret = count; + + out: + return ret; +} +#endif +#endif + void __init init_irq_proc(void) { +#if defined(CONFIG_SMP) && defined(CONFIG_PROC_FS) + struct proc_dir_entry *dir; + int irq; + + dir = proc_mkdir("irq", 0); + if (!dir) + return; + + for (irq = 0; irq < NR_IRQS; irq++) { + struct proc_dir_entry *entry; + struct irqdesc *desc; + char name[16]; + + desc = irq_desc + irq; + memset(name, 0, sizeof(name)); + snprintf(name, sizeof(name) - 1, "%u", irq); + + desc->procdir = proc_mkdir(name, dir); + if (!desc->procdir) + continue; + + entry = create_proc_entry("smp_affinity", 0600, desc->procdir); + if (entry) { + entry->nlink = 1; + entry->data = (void *)irq; + entry->read_proc = irq_affinity_read_proc; + entry->write_proc = irq_affinity_write_proc; + } + } +#endif } void __init init_IRQ(void) @@ -888,6 +1015,11 @@ void __init init_IRQ(void) extern void init_dma(void); int irq; +#ifdef CONFIG_SMP + bad_irq_desc.affinity = CPU_MASK_ALL; + bad_irq_desc.cpu = smp_processor_id(); +#endif + for (irq = 0, desc = irq_desc; irq < NR_IRQS; irq++, desc++) { *desc = bad_irq_desc; INIT_LIST_HEAD(&desc->pend); diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 9eb28f865..8f146a4b4 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -168,12 +168,11 @@ void machine_restart(char * __unused) EXPORT_SYMBOL(machine_restart); -void show_regs(struct pt_regs * regs) +void __show_regs(struct pt_regs *regs) { - unsigned long flags; - - flags = condition_codes(regs); + unsigned long flags = condition_codes(regs); + printk("CPU: %d\n", smp_processor_id()); print_symbol("PC is at %s\n", instruction_pointer(regs)); print_symbol("LR is at %s\n", regs->ARM_lr); printk("pc : [<%08lx>] lr : [<%08lx>] %s\n" @@ -213,6 +212,14 @@ void show_regs(struct pt_regs * regs) } } +void show_regs(struct pt_regs * regs) +{ + printk("\n"); + printk("Pid: %d, comm: %20s\n", current->pid, current->comm); + __show_regs(regs); + __backtrace(); +} + void show_fpregs(struct user_fp *regs) { int i; @@ -249,8 +256,6 @@ static unsigned long *thread_info_head; static unsigned int nr_thread_info; #define EXTRA_TASK_STRUCT 4 -#define ll_alloc_task_struct() ((struct thread_info *) __get_free_pages(GFP_KERNEL,1)) -#define ll_free_task_struct(p) free_pages((unsigned long)(p),1) struct thread_info *alloc_thread_info(struct task_struct *task) { @@ -267,17 +272,16 @@ struct thread_info *alloc_thread_info(struct task_struct *task) } if (!thread) - thread = ll_alloc_task_struct(); + thread = (struct thread_info *) + __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER); -#ifdef CONFIG_MAGIC_SYSRQ +#ifdef CONFIG_DEBUG_STACK_USAGE /* * The stack must be cleared if you want SYSRQ-T to * give sensible stack usage information */ - if (thread) { - char *p = (char *)thread; - memzero(p+KERNEL_STACK_SIZE, KERNEL_STACK_SIZE); - } + if (thread) + memzero(thread, THREAD_SIZE); #endif return thread; } @@ -290,7 +294,7 @@ void free_thread_info(struct thread_info *thread) thread_info_head = p; nr_thread_info += 1; } else - ll_free_task_struct(thread); + free_pages((unsigned long)thread, THREAD_SIZE_ORDER); } /* @@ -343,7 +347,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long stack_start, struct thread_info *thread = p->thread_info; struct pt_regs *childregs; - childregs = ((struct pt_regs *)((unsigned long)thread + THREAD_SIZE - 8)) - 1; + childregs = ((struct pt_regs *)((unsigned long)thread + THREAD_START_SP)) - 1; *childregs = *regs; childregs->ARM_r0 = 0; childregs->ARM_sp = stack_start; @@ -352,6 +356,9 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long stack_start, thread->cpu_context.sp = (unsigned long)childregs; thread->cpu_context.pc = (unsigned long)ret_from_fork; + if (clone_flags & CLONE_SETTLS) + thread->tp_value = regs->ARM_r3; + return 0; } @@ -437,15 +444,17 @@ EXPORT_SYMBOL(kernel_thread); unsigned long get_wchan(struct task_struct *p) { unsigned long fp, lr; - unsigned long stack_page; + unsigned long stack_start, stack_end; int count = 0; if (!p || p == current || p->state == TASK_RUNNING) return 0; - stack_page = 4096 + (unsigned long)p->thread_info; + stack_start = (unsigned long)(p->thread_info + 1); + stack_end = ((unsigned long)p->thread_info) + THREAD_SIZE; + fp = thread_saved_fp(p); do { - if (fp < stack_page || fp > 4092+stack_page) + if (fp < stack_start || fp > stack_end) return 0; lr = pc_pointer (((unsigned long *)fp)[-1]); if (!in_sched_functions(lr)) diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index ddb9322f3..bf0e87614 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -9,6 +9,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include #include #include #include @@ -18,6 +19,7 @@ #include #include #include +#include #include #include @@ -608,6 +610,44 @@ static int ptrace_setfpregs(struct task_struct *tsk, void __user *ufp) sizeof(struct user_fp)) ? -EFAULT : 0; } +#ifdef CONFIG_IWMMXT + +/* + * Get the child iWMMXt state. + */ +static int ptrace_getwmmxregs(struct task_struct *tsk, void __user *ufp) +{ + struct thread_info *thread = tsk->thread_info; + void *ptr = &thread->fpstate; + + if (!test_ti_thread_flag(thread, TIF_USING_IWMMXT)) + return -ENODATA; + iwmmxt_task_disable(thread); /* force it to ram */ + /* The iWMMXt state is stored doubleword-aligned. */ + if (((long) ptr) & 4) + ptr += 4; + return copy_to_user(ufp, ptr, 0x98) ? -EFAULT : 0; +} + +/* + * Set the child iWMMXt state. + */ +static int ptrace_setwmmxregs(struct task_struct *tsk, void __user *ufp) +{ + struct thread_info *thread = tsk->thread_info; + void *ptr = &thread->fpstate; + + if (!test_ti_thread_flag(thread, TIF_USING_IWMMXT)) + return -EACCES; + iwmmxt_task_release(thread); /* force a reload */ + /* The iWMMXt state is stored doubleword-aligned. */ + if (((long) ptr) & 4) + ptr += 4; + return copy_from_user(ptr, ufp, 0x98) ? -EFAULT : 0; +} + +#endif + static int do_ptrace(int request, struct task_struct *child, long addr, long data) { unsigned long tmp; @@ -654,7 +694,7 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat case PTRACE_SYSCALL: case PTRACE_CONT: ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; if (request == PTRACE_SYSCALL) set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); @@ -689,7 +729,7 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat */ case PTRACE_SINGLESTEP: ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; child->ptrace |= PT_SINGLESTEP; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); @@ -719,6 +759,21 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat ret = ptrace_setfpregs(child, (void __user *)data); break; +#ifdef CONFIG_IWMMXT + case PTRACE_GETWMMXREGS: + ret = ptrace_getwmmxregs(child, (void __user *)data); + break; + + case PTRACE_SETWMMXREGS: + ret = ptrace_setwmmxregs(child, (void __user *)data); + break; +#endif + + case PTRACE_GET_THREAD_AREA: + ret = put_user(child->thread_info->tp_value, + (unsigned long __user *) data); + break; + default: ret = ptrace_request(child, request, addr, data); break; diff --git a/arch/arm/kernel/semaphore.c b/arch/arm/kernel/semaphore.c index c232d3777..ac423e3e2 100644 --- a/arch/arm/kernel/semaphore.c +++ b/arch/arm/kernel/semaphore.c @@ -54,7 +54,7 @@ void __up(struct semaphore *sem) wake_up(&sem->wait); } -static spinlock_t semaphore_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(semaphore_lock); void __sched __down(struct semaphore * sem) { @@ -178,7 +178,7 @@ int __down_trylock(struct semaphore * sem) * registers (r0 to r3 and lr), but not ip, as we use it as a return * value in some cases.. */ -asm(" .section .sched.text \n\ +asm(" .section .sched.text,\"ax\" \n\ .align 5 \n\ .globl __down_failed \n\ __down_failed: \n\ diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index a78ccd76e..c2a7da3ac 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -91,8 +92,6 @@ struct cpu_user_fns cpu_user; struct cpu_cache_fns cpu_cache; #endif -unsigned char aux_device_present; - char elf_platform[ELF_PLATFORM_SIZE]; EXPORT_SYMBOL(elf_platform); @@ -108,6 +107,8 @@ static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } }; #define ENDIANNESS ((char)endian_test.l) +DEFINE_PER_CPU(struct cpuinfo_arm, cpu_data); + /* * Standard memory resources */ @@ -218,12 +219,12 @@ static const char *proc_arch[] = { #define CACHE_M(y) ((y) & (1 << 2)) #define CACHE_LINE(y) ((y) & 3) -static inline void dump_cache(const char *prefix, unsigned int cache) +static inline void dump_cache(const char *prefix, int cpu, unsigned int cache) { unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0); - printk("%s: %d bytes, associativity %d, %d byte lines, %d sets\n", - prefix, + printk("CPU%u: %s: %d bytes, associativity %d, %d byte lines, %d sets\n", + cpu, prefix, mult << (8 + CACHE_SIZE(cache)), (mult << CACHE_ASSOC(cache)) >> 1, 8 << CACHE_LINE(cache), @@ -231,18 +232,18 @@ static inline void dump_cache(const char *prefix, unsigned int cache) CACHE_LINE(cache))); } -static void __init dump_cpu_info(void) +static void __init dump_cpu_info(int cpu) { unsigned int info = read_cpuid(CPUID_CACHETYPE); if (info != processor_id) { - printk("CPU: D %s %s cache\n", cache_is_vivt() ? "VIVT" : "VIPT", + printk("CPU%u: D %s %s cache\n", cpu, cache_is_vivt() ? "VIVT" : "VIPT", cache_types[CACHE_TYPE(info)]); if (CACHE_S(info)) { - dump_cache("CPU: I cache", CACHE_ISIZE(info)); - dump_cache("CPU: D cache", CACHE_DSIZE(info)); + dump_cache("I cache", cpu, CACHE_ISIZE(info)); + dump_cache("D cache", cpu, CACHE_DSIZE(info)); } else { - dump_cache("CPU: cache", CACHE_ISIZE(info)); + dump_cache("cache", cpu, CACHE_ISIZE(info)); } } } @@ -264,9 +265,15 @@ int cpu_architecture(void) return cpu_arch; } +/* + * These functions re-use the assembly code in head.S, which + * already provide the required functionality. + */ +extern struct proc_info_list *lookup_processor_type(void); +extern struct machine_desc *lookup_machine_type(unsigned int); + static void __init setup_processor(void) { - extern struct proc_info_list __proc_info_begin, __proc_info_end; struct proc_info_list *list; /* @@ -274,15 +281,8 @@ static void __init setup_processor(void) * types. The linker builds this table for us from the * entries in arch/arm/mm/proc-*.S */ - for (list = &__proc_info_begin; list < &__proc_info_end ; list++) - if ((processor_id & list->cpu_mask) == list->cpu_val) - break; - - /* - * If processor type is unrecognised, then we - * can do nothing... - */ - if (list >= &__proc_info_end) { + list = lookup_processor_type(); + if (!list) { printk("CPU configuration botched (ID %08x), unable " "to continue.\n", processor_id); while (1); @@ -307,7 +307,7 @@ static void __init setup_processor(void) cpu_name, processor_id, (int)processor_id & 15, proc_arch[cpu_architecture()]); - dump_cpu_info(); + 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); @@ -318,22 +318,14 @@ static void __init setup_processor(void) static struct machine_desc * __init setup_machine(unsigned int nr) { - extern struct machine_desc __arch_info_begin, __arch_info_end; struct machine_desc *list; /* - * locate architecture in the list of supported architectures. + * locate machine in the list of supported machines. */ - for (list = &__arch_info_begin; list < &__arch_info_end; list++) - if (list->nr == nr) - break; - - /* - * If the architecture type is not recognised, then we - * can co nothing... - */ - if (list >= &__arch_info_end) { - printk("Architecture configuration botched (nr %d), unable " + list = lookup_machine_type(nr); + if (!list) { + printk("Machine configuration botched (nr %d), unable " "to continue.\n", nr); while (1); } @@ -739,11 +731,15 @@ void __init setup_arch(char **cmdline_p) #endif } -static struct cpu cpu[1]; static int __init topology_init(void) { - return register_cpu(cpu, 0, NULL); + int cpu; + + for_each_cpu(cpu) + register_cpu(&per_cpu(cpu_data, cpu).cpu, cpu, NULL); + + return 0; } subsys_initcall(topology_init); @@ -784,9 +780,18 @@ static int c_show(struct seq_file *m, void *v) seq_printf(m, "Processor\t: %s rev %d (%s)\n", cpu_name, (int)processor_id & 15, elf_platform); +#if defined(CONFIG_SMP) + for_each_online_cpu(i) { + seq_printf(m, "Processor\t: %d\n", i); + seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n", + per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ), + (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100); + } +#else /* CONFIG_SMP */ seq_printf(m, "BogoMIPS\t: %lu.%02lu\n", loops_per_jiffy / (500000/HZ), (loops_per_jiffy / (5000/HZ)) % 100); +#endif /* dump out the processor features */ seq_puts(m, "Features\t: "); diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index c1ff9e200..931919fd5 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include @@ -103,7 +102,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, if (act) { old_sigset_t mask; - if (verify_area(VERIFY_READ, act, sizeof(*act)) || + if (!access_ok(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; @@ -115,7 +114,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); if (!ret && oact) { - if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || + if (!access_ok(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; @@ -318,7 +317,7 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs) frame = (struct sigframe __user *)regs->ARM_sp; - if (verify_area(VERIFY_READ, frame, sizeof (*frame))) + if (!access_ok(VERIFY_READ, frame, sizeof (*frame))) goto badframe; if (__get_user(set.sig[0], &frame->sc.oldmask) || (_NSIG_WORDS > 1 @@ -366,7 +365,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) frame = (struct rt_sigframe __user *)regs->ARM_sp; - if (verify_area(VERIFY_READ, frame, sizeof (*frame))) + if (!access_ok(VERIFY_READ, frame, sizeof (*frame))) goto badframe; if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; @@ -689,10 +688,8 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) if (!user_mode(regs)) return 0; - if (current->flags & PF_FREEZE) { - refrigerator(0); + if (try_to_freeze(0)) goto no_signal; - } if (current->ptrace & PT_SINGLESTEP) ptrace_cancel_bpt(current); diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c index 154099aef..f897ce2cc 100644 --- a/arch/arm/kernel/sys_arm.c +++ b/arch/arm/kernel/sys_arm.c @@ -51,13 +51,6 @@ asmlinkage int sys_pipe(unsigned long __user *fildes) return error; } -/* - * This is the lowest virtual address we can permit any user space - * mapping to be mapped at. This is particularly important for - * non-high vector CPUs. - */ -#define MIN_MAP_ADDR (PAGE_SIZE) - /* common code for old and new mmaps */ inline long do_mmap2( unsigned long addr, unsigned long len, @@ -69,7 +62,7 @@ inline long do_mmap2( flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (flags & MAP_FIXED && addr < MIN_MAP_ADDR) + if (flags & MAP_FIXED && addr < FIRST_USER_ADDRESS) goto out; error = -EBADF; @@ -122,7 +115,7 @@ sys_arm_mremap(unsigned long addr, unsigned long old_len, { unsigned long ret = -EINVAL; - if (flags & MREMAP_FIXED && new_addr < MIN_MAP_ADDR) + if (flags & MREMAP_FIXED && new_addr < FIRST_USER_ADDRESS) goto out; down_write(¤t->mm->mmap_sem); @@ -169,7 +162,11 @@ asmlinkage int sys_ipc(uint call, int first, int second, int third, switch (call) { case SEMOP: - return sys_semop(first, (struct sembuf __user *)ptr, second); + return sys_semtimedop (first, (struct sembuf __user *)ptr, second, NULL); + case SEMTIMEDOP: + return sys_semtimedop(first, (struct sembuf __user *)ptr, second, + (const struct timespec __user *)fifth); + case SEMGET: return sys_semget (first, second, third); case SEMCTL: { @@ -241,18 +238,14 @@ asmlinkage int sys_fork(struct pt_regs *regs) /* Clone a task - this clones the calling program thread. * This is called indirectly via a small wrapper */ -asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, struct pt_regs *regs) +asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, + int __user *parent_tidptr, int tls_val, + int __user *child_tidptr, struct pt_regs *regs) { - /* - * We don't support SETTID / CLEARTID - */ - if (clone_flags & (CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID)) - return -EINVAL; - if (!newsp) newsp = regs->ARM_sp; - return do_fork(clone_flags, newsp, regs, 0, NULL, NULL); + return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); } asmlinkage int sys_vfork(struct pt_regs *regs) @@ -309,7 +302,7 @@ long execve(const char *filename, char **argv, char **envp) "b ret_to_user" : : "r" (current_thread_info()), - "Ir" (THREAD_SIZE - 8 - sizeof(regs)), + "Ir" (THREAD_START_SP - sizeof(regs)), "r" (®s), "Ir" (sizeof(regs)) : "r0", "r1", "r2", "r3", "ip", "memory"); diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index a46efa25f..c232f24f4 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -48,7 +48,7 @@ struct sys_timer *system_timer; extern unsigned long wall_jiffies; /* this needs a better home */ -spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(rtc_lock); #ifdef CONFIG_SA1100_RTC_MODULE EXPORT_SYMBOL(rtc_lock); @@ -63,7 +63,7 @@ unsigned long profile_pc(struct pt_regs *regs) unsigned long fp, pc = instruction_pointer(regs); if (in_lock_functions(pc)) { - fp = thread_saved_fp(current); + fp = regs->ARM_fp; pc = pc_pointer(((unsigned long *)fp)[-1]); } @@ -178,7 +178,7 @@ static ssize_t leds_store(struct sys_device *dev, const char *buf, size_t size) static SYSDEV_ATTR(event, 0200, NULL, leds_store); -static int leds_suspend(struct sys_device *dev, u32 state) +static int leds_suspend(struct sys_device *dev, pm_message_t state) { leds_event(led_stop); return 0; @@ -351,7 +351,7 @@ void timer_tick(struct pt_regs *regs) } #ifdef CONFIG_PM -static int timer_suspend(struct sys_device *dev, u32 state) +static int timer_suspend(struct sys_device *dev, pm_message_t state) { struct sys_timer *timer = container_of(dev, struct sys_timer, dev); diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index b80f8cee7..45d2a032d 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -31,9 +31,6 @@ #include "ptrace.h" -extern void c_backtrace (unsigned long fp, int pmode); -extern void show_pte(struct mm_struct *mm, unsigned long addr); - const char *processor_modes[]= { "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" , "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26", @@ -200,7 +197,7 @@ void show_stack(struct task_struct *tsk, unsigned long *sp) barrier(); } -spinlock_t die_lock = SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(die_lock); /* * This function is protected against re-entrancy. @@ -216,13 +213,13 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err) printk("Internal error: %s: %x [#%d]\n", str, err, ++die_counter); print_modules(); - printk("CPU: %d\n", smp_processor_id()); - show_regs(regs); + __show_regs(regs); printk("Process %s (pid: %d, stack limit = 0x%p)\n", tsk->comm, tsk->pid, tsk->thread_info + 1); if (!user_mode(regs) || in_interrupt()) { - dump_mem("Stack: ", regs->ARM_sp, 8192+(unsigned long)tsk->thread_info); + dump_mem("Stack: ", regs->ARM_sp, + THREAD_SIZE + (unsigned long)tsk->thread_info); dump_backtrace(regs, tsk); dump_instr(regs); } @@ -240,8 +237,21 @@ void die_if_kernel(const char *str, struct pt_regs *regs, int err) die(str, regs, err); } +static void notify_die(const char *str, struct pt_regs *regs, siginfo_t *info, + unsigned long err, unsigned long trap) +{ + if (user_mode(regs)) { + current->thread.error_code = err; + current->thread.trap_no = trap; + + force_sig_info(info->si_signo, info, current); + } else { + die(str, regs, err); + } +} + static LIST_HEAD(undef_hook); -static spinlock_t undef_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(undef_lock); void register_undef_hook(struct undef_hook *hook) { @@ -299,17 +309,12 @@ asmlinkage void do_undefinstr(struct pt_regs *regs) } #endif - current->thread.error_code = 0; - current->thread.trap_no = 6; - info.si_signo = SIGILL; info.si_errno = 0; info.si_code = ILL_ILLOPC; info.si_addr = pc; - force_sig_info(SIGILL, &info, current); - - die_if_kernel("Oops - undefined instruction", regs, 0); + notify_die("Oops - undefined instruction", regs, &info, 0, 6); } asmlinkage void do_unexp_fiq (struct pt_regs *regs) @@ -362,8 +367,8 @@ static int bad_syscall(int n, struct pt_regs *regs) info.si_addr = (void __user *)instruction_pointer(regs) - (thumb_mode(regs) ? 2 : 4); - force_sig_info(SIGILL, &info, current); - die_if_kernel("Oops - bad syscall", regs, n); + notify_die("Oops - bad syscall", regs, &info, n, 0); + return regs->ARM_r0; } @@ -393,6 +398,7 @@ do_cache_op(unsigned long start, unsigned long end, int flags) #define NR(x) ((__ARM_NR_##x) - __ARM_NR_BASE) asmlinkage int arm_syscall(int no, struct pt_regs *regs) { + struct thread_info *thread = current_thread_info(); siginfo_t info; if ((no >> 16) != 0x9f) @@ -405,9 +411,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) info.si_code = SEGV_MAPERR; info.si_addr = NULL; - force_sig_info(SIGSEGV, &info, current); - - die_if_kernel("branch through zero", regs, 0); + notify_die("branch through zero", regs, &info, 0, 0); return 0; case NR(breakpoint): /* SWI BREAK_POINT */ @@ -445,6 +449,70 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) regs->ARM_cpsr |= MODE32_BIT; return regs->ARM_r0; + case NR(set_tls): + thread->tp_value = regs->ARM_r0; +#if defined(CONFIG_HAS_TLS_REG) + asm ("mcr p15, 0, %0, c13, c0, 3" : : "r" (regs->ARM_r0) ); +#elif !defined(CONFIG_TLS_REG_EMUL) + /* + * User space must never try to access this directly. + * Expect your app to break eventually if you do so. + * The user helper at 0xffff0fe0 must be used instead. + * (see entry-armv.S for details) + */ + *((unsigned int *)0xffff0ff0) = regs->ARM_r0; +#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 @@ -464,7 +532,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) current->pid, current->comm, no); dump_instr(regs); if (user_mode(regs)) { - show_regs(regs); + __show_regs(regs); c_backtrace(regs->ARM_fp, processor_mode(regs)); } } @@ -475,11 +543,48 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) info.si_addr = (void __user *)instruction_pointer(regs) - (thumb_mode(regs) ? 2 : 4); - force_sig_info(SIGILL, &info, current); - die_if_kernel("Oops - bad syscall(2)", regs, no); + notify_die("Oops - bad syscall(2)", regs, &info, no, 0); + return 0; +} + +#ifdef CONFIG_TLS_REG_EMUL + +/* + * 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. + */ + +static int get_tp_trap(struct pt_regs *regs, unsigned int instr) +{ + int reg = (instr >> 12) & 15; + if (reg == 15) + return 1; + regs->uregs[reg] = current_thread_info()->tp_value; + regs->ARM_pc += 4; + return 0; +} + +static struct undef_hook arm_mrc_hook = { + .instr_mask = 0x0fff0fff, + .instr_val = 0x0e1d0f70, + .cpsr_mask = PSR_T_BIT, + .cpsr_val = 0, + .fn = get_tp_trap, +}; + +static int __init arm_mrc_hook_init(void) +{ + register_undef_hook(&arm_mrc_hook); return 0; } +late_initcall(arm_mrc_hook_init); + +#endif + void __bad_xchg(volatile void *ptr, int size) { printk("xchg: bad data size: pc 0x%p, ptr 0x%p, size %d\n", @@ -512,8 +617,7 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs) info.si_code = ILL_ILLOPC; info.si_addr = (void __user *)addr; - force_sig_info(SIGILL, &info, current); - die_if_kernel("unknown data abort code", regs, instr); + notify_die("unknown data abort code", regs, &info, instr, 0); } volatile void __bug(const char *file, int line, void *data) @@ -566,9 +670,19 @@ EXPORT_SYMBOL(abort); void __init trap_init(void) { - extern void __trap_init(void); + extern char __stubs_start[], __stubs_end[]; + extern char __vectors_start[], __vectors_end[]; + extern char __kuser_helper_start[], __kuser_helper_end[]; + int kuser_sz = __kuser_helper_end - __kuser_helper_start; - __trap_init(); + /* + * Copy the vectors, stubs and kuser helpers (in entry-armv.S) + * into the vector page, mapped at 0xffff0000, and ensure these + * are visible to the instruction stream. + */ + 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); flush_icache_range(0xffff0000, 0xffff0000 + PAGE_SIZE); modify_domain(DOMAIN_USER, DOMAIN_CLIENT); } diff --git a/arch/arm/mach-clps7500/core.c b/arch/arm/mach-clps7500/core.c index 1b37ac188..fdfededfd 100644 --- a/arch/arm/mach-clps7500/core.c +++ b/arch/arm/mach-clps7500/core.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -305,11 +306,10 @@ static struct irqaction clps7500_timer_irq = { static void __init clps7500_timer_init(void) { ioctime_init(); - setup_irq(IRQ_TIMER, &clps7500_timer_irq); } -static struct clps7500_timer = { +static struct sys_timer clps7500_timer = { .init = clps7500_timer_init, .offset = ioc_timer_gettimeoffset, }; @@ -358,9 +358,9 @@ static struct platform_device serial_device = { }, }; -static int __init clps7500_init(void) +static void __init clps7500_init(void) { - return platform_register_device(&serial_device); + platform_device_register(&serial_device); } MACHINE_START(CLPS7500, "CL-PS7500") @@ -368,6 +368,7 @@ MACHINE_START(CLPS7500, "CL-PS7500") BOOT_MEM(0x10000000, 0x03000000, 0xe0000000) MAPIO(clps7500_map_io) INITIRQ(clps7500_init_irq) - .timer = &clps7500_timer, + .init_machine = clps7500_init, + .timer = &clps7500_timer, MACHINE_END diff --git a/arch/arm/mach-ebsa110/io.c b/arch/arm/mach-ebsa110/io.c index f5181ed48..ef7eb5dc9 100644 --- a/arch/arm/mach-ebsa110/io.c +++ b/arch/arm/mach-ebsa110/io.c @@ -153,9 +153,9 @@ u8 __inb8(unsigned int port) * The SuperIO registers use sane addressing techniques... */ if (SUPERIO_PORT(port)) - ret = __raw_readb(ISAIO_BASE + (port << 2)); + ret = __raw_readb((void __iomem *)ISAIO_BASE + (port << 2)); else { - void __iomem *a = ISAIO_BASE + ((port & ~1) << 1); + void __iomem *a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1); /* * Shame nothing else does @@ -174,45 +174,33 @@ u8 __inb8(unsigned int port) */ u8 __inb16(unsigned int port) { - u32 ret; + unsigned int offset; /* * The SuperIO registers use sane addressing techniques... */ if (SUPERIO_PORT(port)) - ret = __raw_readb(ISAIO_BASE + (port << 2)); - else { - void __iomem *a = ISAIO_BASE + ((port & ~1) << 1); + offset = port << 2; + else + offset = (port & ~1) << 1 | (port & 1); - /* - * Shame nothing else does - */ - ret = __raw_readb(a + (port & 1)); - } - return ret; + return __raw_readb((void __iomem *)ISAIO_BASE + offset); } u16 __inw(unsigned int port) { - u32 ret; + unsigned int offset; /* * The SuperIO registers use sane addressing techniques... */ if (SUPERIO_PORT(port)) - ret = __raw_readw(ISAIO_BASE + (port << 2)); + offset = port << 2; else { - void __iomem *a = ISAIO_BASE + ((port & ~1) << 1); - - /* - * Shame nothing else does - */ - if (port & 1) - BUG(); - - ret = __raw_readw(a); + offset = port << 1; + BUG_ON(port & 1); } - return ret; + return __raw_readw((void __iomem *)ISAIO_BASE + offset); } /* @@ -225,7 +213,7 @@ u32 __inl(unsigned int port) if (SUPERIO_PORT(port) || port & 3) BUG(); - a = ISAIO_BASE + (port << 1); + a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1); return __raw_readw(a) | __raw_readw(a + 4) << 16; } @@ -241,9 +229,9 @@ void __outb8(u8 val, unsigned int port) * The SuperIO registers use sane addressing techniques... */ if (SUPERIO_PORT(port)) - __raw_writeb(val, ISAIO_BASE + (port << 2)); + __raw_writeb(val, (void __iomem *)ISAIO_BASE + (port << 2)); else { - void __iomem *a = ISAIO_BASE + ((port & ~1) << 1); + void __iomem *a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1); /* * Shame nothing else does @@ -257,37 +245,33 @@ void __outb8(u8 val, unsigned int port) void __outb16(u8 val, unsigned int port) { + unsigned int offset; + /* * The SuperIO registers use sane addressing techniques... */ if (SUPERIO_PORT(port)) - __raw_writeb(val, ISAIO_BASE + (port << 2)); - else { - void __iomem *a = ISAIO_BASE + ((port & ~1) << 1); + offset = port << 2; + else + offset = (port & ~1) << 1 | (port & 1); - /* - * Shame nothing else does - */ - __raw_writeb(val, a + (port & 1)); - } + __raw_writeb(val, (void __iomem *)ISAIO_BASE + offset); } void __outw(u16 val, unsigned int port) { - u32 off; + unsigned int offset; /* * The SuperIO registers use sane addressing techniques... */ if (SUPERIO_PORT(port)) - off = port << 2; + offset = port << 2; else { - off = port << 1; - if (port & 1) - BUG(); - + offset = port << 1; + BUG_ON(port & 1); } - __raw_writew(val, ISAIO_BASE + off); + __raw_writew(val, (void __iomem *)ISAIO_BASE + offset); } void __outl(u32 val, unsigned int port) @@ -300,13 +284,6 @@ EXPORT_SYMBOL(__outb16); EXPORT_SYMBOL(__outw); EXPORT_SYMBOL(__outl); -extern void __arch_writesb(unsigned long virt, const void *from, int len); -extern void __arch_writesw(unsigned long virt, const void *from, int len); -extern void __arch_writesl(unsigned long virt, const void *from, int len); -extern void __arch_readsb(unsigned long virt, void *from, int len); -extern void __arch_readsw(unsigned long virt, void *from, int len); -extern void __arch_readsl(unsigned long virt, void *from, int len); - void outsb(unsigned int port, const void *from, int len) { u32 off; @@ -319,7 +296,7 @@ void outsb(unsigned int port, const void *from, int len) BUG(); } - __raw_writesb(ISAIO_BASE + off, from, len); + __raw_writesb((void __iomem *)ISAIO_BASE + off, from, len); } void insb(unsigned int port, void *from, int len) @@ -334,7 +311,7 @@ void insb(unsigned int port, void *from, int len) BUG(); } - __raw_readsb(ISAIO_BASE + off, from, len); + __raw_readsb((void __iomem *)ISAIO_BASE + off, from, len); } EXPORT_SYMBOL(outsb); @@ -352,7 +329,7 @@ void outsw(unsigned int port, const void *from, int len) BUG(); } - __raw_writesw(ISAIO_BASE + off, from, len); + __raw_writesw((void __iomem *)ISAIO_BASE + off, from, len); } void insw(unsigned int port, void *from, int len) @@ -367,7 +344,7 @@ void insw(unsigned int port, void *from, int len) BUG(); } - __raw_readsw(ISAIO_BASE + off, from, len); + __raw_readsw((void __iomem *)ISAIO_BASE + off, from, len); } EXPORT_SYMBOL(outsw); @@ -384,7 +361,7 @@ void outsl(unsigned int port, const void *from, int len) if (SUPERIO_PORT(port) || port & 3) BUG(); - __raw_writesw(ISAIO_BASE + off, from, len << 1); + __raw_writesw((void __iomem *)ISAIO_BASE + off, from, len << 1); } void insl(unsigned int port, void *from, int len) @@ -394,7 +371,7 @@ void insl(unsigned int port, void *from, int len) if (SUPERIO_PORT(port) || port & 3) BUG(); - __raw_readsw(ISAIO_BASE + off, from, len << 1); + __raw_readsw((void __iomem *)ISAIO_BASE + off, from, len << 1); } EXPORT_SYMBOL(outsl); diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index eb16dea60..bd17b5154 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c @@ -115,7 +115,7 @@ arch_initcall(integrator_init); #define CM_CTRL IO_ADDRESS(INTEGRATOR_HDR_BASE) + INTEGRATOR_HDR_CTRL_OFFSET -static spinlock_t cm_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(cm_lock); /** * cm_control - update the CM_CTRL register. @@ -216,7 +216,9 @@ integrator_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) write_seqlock(&xtime_lock); - // ...clear the interrupt + /* + * clear the interrupt + */ timer1->TimerClear = 1; timer_tick(regs); @@ -264,7 +266,7 @@ void __init integrator_time_init(unsigned long reload, unsigned int ctrl) timer1->TimerValue = timer_reload; timer1->TimerControl = timer_ctrl; - /* + /* * Make irqs happen for the system timer */ setup_irq(IRQ_TIMERINT1, &integrator_timer_irq); diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c index 0859557e7..c3c2f17d0 100644 --- a/arch/arm/mach-integrator/impd1.c +++ b/arch/arm/mach-integrator/impd1.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -34,7 +35,7 @@ module_param_named(lmid, module_id, int, 0444); MODULE_PARM_DESC(lmid, "logic module stack position"); struct impd1_module { - void *base; + void __iomem *base; struct clk vcos[2]; }; @@ -259,6 +260,17 @@ static int impd1fb_clcd_setup(struct clcd_fb *fb) return ret; } +static int impd1fb_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma) +{ + unsigned long start, size; + + start = vma->vm_pgoff + (fb->fb.fix.smem_start >> PAGE_SHIFT); + size = vma->vm_end - vma->vm_start; + + return remap_pfn_range(vma, vma->vm_start, start, size, + vma->vm_page_prot); +} + static void impd1fb_clcd_remove(struct clcd_fb *fb) { iounmap(fb->fb.screen_base); @@ -272,6 +284,7 @@ static struct clcd_board impd1_clcd_data = { .disable = impd1fb_clcd_disable, .enable = impd1fb_clcd_enable, .setup = impd1fb_clcd_setup, + .mmap = impd1fb_clcd_mmap, .remove = impd1fb_clcd_remove, }; diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index ad667711d..91ba9fd79 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c @@ -68,7 +68,6 @@ * f1200000 12000000 EBI registers * f1300000 13000000 Counter/Timer * f1400000 14000000 Interrupt controller - * f1500000 15000000 RTC * f1600000 16000000 UART 0 * f1700000 17000000 UART 1 * f1a00000 1a000000 Debug LEDs @@ -81,7 +80,6 @@ static struct map_desc ap_io_desc[] __initdata = { { IO_ADDRESS(INTEGRATOR_EBI_BASE), INTEGRATOR_EBI_BASE, SZ_4K, MT_DEVICE }, { IO_ADDRESS(INTEGRATOR_CT_BASE), INTEGRATOR_CT_BASE, SZ_4K, MT_DEVICE }, { IO_ADDRESS(INTEGRATOR_IC_BASE), INTEGRATOR_IC_BASE, SZ_4K, MT_DEVICE }, - { IO_ADDRESS(INTEGRATOR_RTC_BASE), INTEGRATOR_RTC_BASE, SZ_4K, MT_DEVICE }, { IO_ADDRESS(INTEGRATOR_UART0_BASE), INTEGRATOR_UART0_BASE, SZ_4K, MT_DEVICE }, { IO_ADDRESS(INTEGRATOR_UART1_BASE), INTEGRATOR_UART1_BASE, SZ_4K, MT_DEVICE }, { IO_ADDRESS(INTEGRATOR_DBG_BASE), INTEGRATOR_DBG_BASE, SZ_4K, MT_DEVICE }, @@ -139,7 +137,7 @@ static void __init ap_init_irq(void) #ifdef CONFIG_PM static unsigned long ic_irq_enable; -static int irq_suspend(struct sys_device *dev, u32 state) +static int irq_suspend(struct sys_device *dev, pm_message_t state) { ic_irq_enable = readl(VA_IC_BASE + IRQ_ENABLE); return 0; diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 19809bba4..e0a01eef0 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 }, }; @@ -420,7 +419,22 @@ static struct clcd_panel vga = { */ static void cp_clcd_enable(struct clcd_fb *fb) { - cm_control(CM_CTRL_LCDMUXSEL_MASK, CM_CTRL_LCDMUXSEL_VGA); + u32 val; + + if (fb->fb.var.bits_per_pixel <= 8) + val = CM_CTRL_LCDMUXSEL_VGA_8421BPP; + else if (fb->fb.var.bits_per_pixel <= 16) + val = CM_CTRL_LCDMUXSEL_VGA_16BPP; + else + val = 0; /* no idea for this, don't trust the docs */ + + cm_control(CM_CTRL_LCDMUXSEL_MASK| + CM_CTRL_LCDEN0| + CM_CTRL_LCDEN1| + CM_CTRL_STATIC1| + CM_CTRL_STATIC2| + CM_CTRL_STATIC| + CM_CTRL_n24BITEN, val); } static unsigned long framesize = SZ_1M; @@ -444,6 +458,14 @@ static int cp_clcd_setup(struct clcd_fb *fb) return 0; } +static int cp_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma) +{ + return dma_mmap_writecombine(&fb->dev->dev, vma, + fb->fb.screen_base, + fb->fb.fix.smem_start, + fb->fb.fix.smem_len); +} + static void cp_clcd_remove(struct clcd_fb *fb) { dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len, @@ -456,6 +478,7 @@ static struct clcd_board clcd_data = { .decode = clcdfb_decode, .enable = cp_clcd_enable, .setup = cp_clcd_setup, + .mmap = cp_clcd_mmap, .remove = cp_clcd_remove, }; diff --git a/arch/arm/mach-ixp4xx/prpmc1100-pci.c b/arch/arm/mach-ixp4xx/prpmc1100-pci.c deleted file mode 100644 index 9ee0ab9da..000000000 --- a/arch/arm/mach-ixp4xx/prpmc1100-pci.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * arch/arm/mach-ixp4xx/prpmc1100-pci.c - * - * PrPMC1100 PCI initialization - * - * Copyright (C) 2003-2004 MontaVista Sofwtare, Inc. - * Based on IXDP425 code originally (C) Intel Corporation - * - * Author: Deepak Saxena - * - * PrPMC1100 PCI init code. GPIO usage is similar to that on - * IXDP425, but the IRQ routing is completely different and - * depends on what carrier you are using. This code is written - * to work on the Motorola PrPMC800 ATX carrier board. - * - * 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 -#include -#include -#include - -#include -#include -#include - -#include - - -void __init prpmc1100_pci_preinit(void) -{ - gpio_line_config(PRPMC1100_PCI_INTA_PIN, - IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW); - gpio_line_config(PRPMC1100_PCI_INTB_PIN, - IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW); - gpio_line_config(PRPMC1100_PCI_INTC_PIN, - IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW); - gpio_line_config(PRPMC1100_PCI_INTD_PIN, - IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW); - - gpio_line_isr_clear(PRPMC1100_PCI_INTA_PIN); - gpio_line_isr_clear(PRPMC1100_PCI_INTB_PIN); - gpio_line_isr_clear(PRPMC1100_PCI_INTC_PIN); - gpio_line_isr_clear(PRPMC1100_PCI_INTD_PIN); - - ixp4xx_pci_preinit(); -} - - -static int __init prpmc1100_map_irq(struct pci_dev *dev, u8 slot, u8 pin) -{ - int irq = -1; - - static int pci_irq_table[][4] = { - { /* IDSEL 16 - PMC A1 */ - IRQ_PRPMC1100_PCI_INTD, - IRQ_PRPMC1100_PCI_INTA, - IRQ_PRPMC1100_PCI_INTB, - IRQ_PRPMC1100_PCI_INTC - }, { /* IDSEL 17 - PRPMC-A-B */ - IRQ_PRPMC1100_PCI_INTD, - IRQ_PRPMC1100_PCI_INTA, - IRQ_PRPMC1100_PCI_INTB, - IRQ_PRPMC1100_PCI_INTC - }, { /* IDSEL 18 - PMC A1-B */ - IRQ_PRPMC1100_PCI_INTA, - IRQ_PRPMC1100_PCI_INTB, - IRQ_PRPMC1100_PCI_INTC, - IRQ_PRPMC1100_PCI_INTD - }, { /* IDSEL 19 - Unused */ - 0, 0, 0, 0 - }, { /* IDSEL 20 - P2P Bridge */ - IRQ_PRPMC1100_PCI_INTA, - IRQ_PRPMC1100_PCI_INTB, - IRQ_PRPMC1100_PCI_INTC, - IRQ_PRPMC1100_PCI_INTD - }, { /* IDSEL 21 - PMC A2 */ - IRQ_PRPMC1100_PCI_INTC, - IRQ_PRPMC1100_PCI_INTD, - IRQ_PRPMC1100_PCI_INTA, - IRQ_PRPMC1100_PCI_INTB - }, { /* IDSEL 22 - PMC A2-B */ - IRQ_PRPMC1100_PCI_INTD, - IRQ_PRPMC1100_PCI_INTA, - IRQ_PRPMC1100_PCI_INTB, - IRQ_PRPMC1100_PCI_INTC - }, - }; - - if (slot >= PRPMC1100_PCI_MIN_DEVID && slot <= PRPMC1100_PCI_MAX_DEVID - && pin >= 1 && pin <= PRPMC1100_PCI_IRQ_LINES) { - irq = pci_irq_table[slot - PRPMC1100_PCI_MIN_DEVID][pin - 1]; - } - - return irq; -} - - -struct hw_pci prpmc1100_pci __initdata = { - .nr_controllers = 1, - .preinit = prpmc1100_pci_preinit, - .swizzle = pci_std_swizzle, - .setup = ixp4xx_setup, - .scan = ixp4xx_scan_bus, - .map_irq = prpmc1100_map_irq, -}; - -int __init prpmc1100_pci_init(void) -{ - if (machine_is_prpmc1100()) - pci_common_init(&prpmc1100_pci); - return 0; -} - -subsys_initcall(prpmc1100_pci_init); - diff --git a/arch/arm/mach-ixp4xx/prpmc1100-setup.c b/arch/arm/mach-ixp4xx/prpmc1100-setup.c deleted file mode 100644 index ed4281565..000000000 --- a/arch/arm/mach-ixp4xx/prpmc1100-setup.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * arch/arm/mach-ixp4xx/prpmc1100-setup.c - * - * Motorola PrPMC1100 board setup - * - * Copyright (C) 2003-2004 MontaVista Software, Inc. - * - * Author: Deepak Saxena - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __ARMEB__ -#define REG_OFFSET 3 -#else -#define REG_OFFSET 0 -#endif - -/* - * Only one serial port is connected on the PrPMC1100 - */ -static struct uart_port prpmc1100_serial_port = { - .membase = (char*)(IXP4XX_UART1_BASE_VIRT + REG_OFFSET), - .mapbase = (IXP4XX_UART1_BASE_PHYS), - .irq = IRQ_IXP4XX_UART1, - .flags = UPF_SKIP_TEST, - .iotype = UPIO_MEM, - .regshift = 2, - .uartclk = IXP4XX_UART_XTAL, - .line = 0, - .type = PORT_XSCALE, - .fifosize = 32 -}; - -void __init prpmc1100_map_io(void) -{ - early_serial_setup(&prpmc1100_serial_port); - - ixp4xx_map_io(); -} - -static struct flash_platform_data prpmc1100_flash_data = { - .map_name = "cfi_probe", - .width = 2, -}; - -static struct resource prpmc1100_flash_resource = { - .start = PRPMC1100_FLASH_BASE, - .end = PRPMC1100_FLASH_BASE + PRPMC1100_FLASH_SIZE, - .flags = IORESOURCE_MEM, -}; - -static struct platform_device prpmc1100_flash = { - .name = "IXP4XX-Flash", - .id = 0, - .dev = { - .platform_data = &prpmc1100_flash_data, - }, - .num_resources = 1, - .resource = &prpmc1100_flash_resource, -}; - -static struct platform_device *prpmc1100_devices[] __initdata = { - &prpmc1100_flash -}; - -static void __init prpmc1100_init(void) -{ - ixp4xx_sys_init(); - - platform_add_devices(prpmc1100_devices, ARRAY_SIZE(prpmc1100_devices)); -} - -MACHINE_START(PRPMC1100, "Motorola PrPMC1100") - MAINTAINER("MontaVista Software, Inc.") - BOOT_MEM(PHYS_OFFSET, IXP4XX_PERIPHERAL_BASE_PHYS, - IXP4XX_PERIPHERAL_BASE_VIRT) - MAPIO(prpmc1100_map_io) - INITIRQ(ixp4xx_init_irq) - .timer = &ixp4xx_timer, - BOOT_PARAMS(0x0100) - INIT_MACHINE(prpmc1100_init) -MACHINE_END - diff --git a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c index 06373b295..c823447a1 100644 --- a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c +++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c @@ -157,8 +157,6 @@ static struct irqchip lpd7a40x_cpld_chip = { .unmask = lh7a40x_unmask_cpld_irq, }; -#define IRQ_DISPATCH(irq) irq_desc[irq].handle ((irq), &irq_desc[irq], regs) - static void lpd7a40x_cpld_handler (unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) { diff --git a/arch/arm/mach-omap/Makefile b/arch/arm/mach-omap/Makefile index 2a6c49542..4cafb11d2 100644 --- a/arch/arm/mach-omap/Makefile +++ b/arch/arm/mach-omap/Makefile @@ -16,6 +16,8 @@ obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o obj-$(CONFIG_MACH_OMAP_PERSEUS2) += board-perseus2.o obj-$(CONFIG_MACH_OMAP_OSK) += board-osk.o obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o +obj-$(CONFIG_MACH_VOICEBLUE) += board-voiceblue.o +obj-$(CONFIG_MACH_NETSTAR) += board-netstar.o # OCPI interconnect support for 1710, 1610 and 5912 obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o diff --git a/arch/arm/mach-omap/board-generic.c b/arch/arm/mach-omap/board-generic.c index 586bc1271..2102a2cd1 100644 --- a/arch/arm/mach-omap/board-generic.c +++ b/arch/arm/mach-omap/board-generic.c @@ -26,7 +26,6 @@ #include #include #include -#include #include "common.h" diff --git a/arch/arm/mach-omap/board-innovator.c b/arch/arm/mach-omap/board-innovator.c index 1ad7a4aaf..57cf4da88 100644 --- a/arch/arm/mach-omap/board-innovator.c +++ b/arch/arm/mach-omap/board-innovator.c @@ -20,23 +20,86 @@ #include #include #include +#include +#include #include #include #include +#include #include -#include -#include #include +#include +#include #include -#include #include "common.h" -#ifdef CONFIG_ARCH_OMAP1510 +static int __initdata innovator_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1}; + +static struct mtd_partition innovator_partitions[] = { + /* bootloader (U-Boot, etc) in first sector */ + { + .name = "bootloader", + .offset = 0, + .size = SZ_128K, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, + /* bootloader params in the next sector */ + { + .name = "params", + .offset = MTDPART_OFS_APPEND, + .size = SZ_128K, + .mask_flags = 0, + }, + /* kernel */ + { + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = SZ_2M, + .mask_flags = 0 + }, + /* rest of flash1 is a file system */ + { + .name = "rootfs", + .offset = MTDPART_OFS_APPEND, + .size = SZ_16M - SZ_2M - 2 * SZ_128K, + .mask_flags = 0 + }, + /* file system */ + { + .name = "filesystem", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + .mask_flags = 0 + } +}; -extern int omap_gpio_init(void); +static struct flash_platform_data innovator_flash_data = { + .map_name = "cfi_probe", + .width = 2, + .parts = innovator_partitions, + .nr_parts = ARRAY_SIZE(innovator_partitions), +}; + +static struct resource innovator_flash_resource = { + .start = OMAP_CS0_PHYS, + .end = OMAP_CS0_PHYS + SZ_32M - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device innovator_flash_device = { + .name = "omapflash", + .id = 0, + .dev = { + .platform_data = &innovator_flash_data, + }, + .num_resources = 1, + .resource = &innovator_flash_resource, +}; + +#ifdef CONFIG_ARCH_OMAP1510 /* Only FPGA needs to be mapped here. All others are done with ioremap */ static struct map_desc innovator1510_io_desc[] __initdata = { @@ -44,12 +107,10 @@ static struct map_desc innovator1510_io_desc[] __initdata = { MT_DEVICE }, }; -static int __initdata innovator_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1}; - static struct resource innovator1510_smc91x_resources[] = { [0] = { .start = OMAP1510_FPGA_ETHR_START, /* Physical */ - .end = OMAP1510_FPGA_ETHR_START + 16, + .end = OMAP1510_FPGA_ETHR_START + 0xf, .flags = IORESOURCE_MEM, }, [1] = { @@ -67,6 +128,7 @@ static struct platform_device innovator1510_smc91x_device = { }; static struct platform_device *innovator1510_devices[] __initdata = { + &innovator_flash_device, &innovator1510_smc91x_device, }; @@ -77,12 +139,12 @@ static struct platform_device *innovator1510_devices[] __initdata = { static struct resource innovator1610_smc91x_resources[] = { [0] = { .start = INNOVATOR1610_ETHR_START, /* Physical */ - .end = INNOVATOR1610_ETHR_START + SZ_4K, + .end = INNOVATOR1610_ETHR_START + 0xf, .flags = IORESOURCE_MEM, }, [1] = { - .start = 0, /* Really GPIO 0 */ - .end = 0, + .start = OMAP_GPIO_IRQ(0), + .end = OMAP_GPIO_IRQ(0), .flags = IORESOURCE_IRQ, }, }; @@ -95,20 +157,37 @@ static struct platform_device innovator1610_smc91x_device = { }; static struct platform_device *innovator1610_devices[] __initdata = { + &innovator_flash_device, &innovator1610_smc91x_device, }; #endif /* CONFIG_ARCH_OMAP16XX */ +static void __init innovator_init_smc91x(void) +{ + if (cpu_is_omap1510()) { + fpga_write(fpga_read(OMAP1510_FPGA_RST) & ~1, + OMAP1510_FPGA_RST); + udelay(750); + } else { + if ((omap_request_gpio(0)) < 0) { + printk("Error requesting gpio 0 for smc91x irq\n"); + return; + } + omap_set_gpio_edge_ctrl(0, OMAP_GPIO_RISING_EDGE); + } +} + void innovator_init_irq(void) { omap_init_irq(); + omap_gpio_init(); #ifdef CONFIG_ARCH_OMAP1510 if (cpu_is_omap1510()) { - omap_gpio_init(); omap1510_fpga_init_irq(); } #endif + innovator_init_smc91x(); } #ifdef CONFIG_ARCH_OMAP1510 diff --git a/arch/arm/mach-omap/board-osk.c b/arch/arm/mach-omap/board-osk.c index d7a20ca6e..a951fc824 100644 --- a/arch/arm/mach-omap/board-osk.c +++ b/arch/arm/mach-omap/board-osk.c @@ -35,11 +35,10 @@ #include #include -#include #include -#include #include -#include +#include +#include #include "common.h" @@ -53,36 +52,90 @@ static int __initdata osk_serial_ports[OMAP_MAX_NR_PORTS] = {1, 0, 0}; static struct resource osk5912_smc91x_resources[] = { [0] = { .start = OMAP_OSK_ETHR_START, /* Physical */ - .end = OMAP_OSK_ETHR_START + SZ_4K, + .end = OMAP_OSK_ETHR_START + 0xf, .flags = IORESOURCE_MEM, }, [1] = { - .start = 0, /* Really GPIO 0 */ - .end = 0, + .start = OMAP_GPIO_IRQ(0), + .end = OMAP_GPIO_IRQ(0), .flags = IORESOURCE_IRQ, }, }; static struct platform_device osk5912_smc91x_device = { .name = "smc91x", - .id = 0, + .id = -1, .num_resources = ARRAY_SIZE(osk5912_smc91x_resources), .resource = osk5912_smc91x_resources, }; +static struct resource osk5912_cf_resources[] = { + [0] = { + .start = OMAP_GPIO_IRQ(62), + .end = OMAP_GPIO_IRQ(62), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device osk5912_cf_device = { + .name = "omap_cf", + .id = -1, + .dev = { + .platform_data = (void *) 2 /* CS2 */, + }, + .num_resources = ARRAY_SIZE(osk5912_cf_resources), + .resource = osk5912_cf_resources, +}; + static struct platform_device *osk5912_devices[] __initdata = { &osk5912_smc91x_device, + &osk5912_cf_device, }; +static void __init osk_init_smc91x(void) +{ + if ((omap_request_gpio(0)) < 0) { + printk("Error requesting gpio 0 for smc91x irq\n"); + return; + } + omap_set_gpio_edge_ctrl(0, OMAP_GPIO_RISING_EDGE); + + /* Check EMIFS wait states to fix errors with SMC_GET_PKT_HDR */ + EMIFS_CCS(1) |= 0x2; +} + +static void __init osk_init_cf(void) +{ + omap_cfg_reg(M7_1610_GPIO62); + if ((omap_request_gpio(62)) < 0) { + printk("Error requesting gpio 62 for CF irq\n"); + return; + } + /* it's really active-low */ + omap_set_gpio_edge_ctrl(62, OMAP_GPIO_FALLING_EDGE); +} + void osk_init_irq(void) { omap_init_irq(); + omap_gpio_init(); + osk_init_smc91x(); + osk_init_cf(); } static struct omap_usb_config osk_usb_config __initdata = { - /* has usb host and device, but no Mini-AB port */ + /* has usb host connector (A) ... for development it can also + * be used, with a NONSTANDARD gender-bending cable/dongle, as + * a peripheral. + */ +#ifdef CONFIG_USB_GADGET_OMAP + .register_dev = 1, + .hmc_mode = 0, +#else .register_host = 1, .hmc_mode = 16, + .rwc = 1, +#endif .pins[0] = 2, }; @@ -92,9 +145,10 @@ static struct omap_board_config_kernel osk_config[] = { static void __init osk_init(void) { - platform_add_devices(osk5912_devices, ARRAY_SIZE(osk5912_devices)); + platform_add_devices(osk5912_devices, ARRAY_SIZE(osk5912_devices)); omap_board_config = osk_config; omap_board_config_size = ARRAY_SIZE(osk_config); + USB_TRANSCEIVER_CTRL_REG |= (3 << 1); } static void __init osk_map_io(void) diff --git a/arch/arm/mach-omap/board-perseus2.c b/arch/arm/mach-omap/board-perseus2.c index 17a936422..64515aeb4 100644 --- a/arch/arm/mach-omap/board-perseus2.c +++ b/arch/arm/mach-omap/board-perseus2.c @@ -14,29 +14,26 @@ #include #include #include +#include +#include +#include #include #include #include +#include #include -#include #include #include #include -#include #include "common.h" -void omap_perseus2_init_irq(void) -{ - omap_init_irq(); -} - static struct resource smc91x_resources[] = { [0] = { .start = H2P2_DBG_FPGA_ETHR_START, /* Physical */ - .end = H2P2_DBG_FPGA_ETHR_START + SZ_4K, + .end = H2P2_DBG_FPGA_ETHR_START + 0xf, .flags = IORESOURCE_MEM, }, [1] = { @@ -48,6 +45,60 @@ static struct resource smc91x_resources[] = { static int __initdata p2_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 0}; +static struct mtd_partition p2_partitions[] = { + /* bootloader (U-Boot, etc) in first sector */ + { + .name = "bootloader", + .offset = 0, + .size = SZ_128K, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, + /* bootloader params in the next sector */ + { + .name = "params", + .offset = MTDPART_OFS_APPEND, + .size = SZ_128K, + .mask_flags = 0, + }, + /* kernel */ + { + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = SZ_2M, + .mask_flags = 0 + }, + /* rest of flash is a file system */ + { + .name = "rootfs", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + .mask_flags = 0 + }, +}; + +static struct flash_platform_data p2_flash_data = { + .map_name = "cfi_probe", + .width = 2, + .parts = p2_partitions, + .nr_parts = ARRAY_SIZE(p2_partitions), +}; + +static struct resource p2_flash_resource = { + .start = OMAP_FLASH_0_START, + .end = OMAP_FLASH_0_START + OMAP_FLASH_0_SIZE - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device p2_flash_device = { + .name = "omapflash", + .id = 0, + .dev = { + .platform_data = &p2_flash_data, + }, + .num_resources = 1, + .resource = &p2_flash_resource, +}; + static struct platform_device smc91x_device = { .name = "smc91x", .id = 0, @@ -56,6 +107,7 @@ static struct platform_device smc91x_device = { }; static struct platform_device *devices[] __initdata = { + &p2_flash_device, &smc91x_device, }; @@ -64,6 +116,22 @@ static void __init omap_perseus2_init(void) (void) platform_add_devices(devices, ARRAY_SIZE(devices)); } +static void __init perseus2_init_smc91x(void) +{ + fpga_write(1, H2P2_DBG_FPGA_LAN_RESET); + mdelay(50); + fpga_write(fpga_read(H2P2_DBG_FPGA_LAN_RESET) & ~1, + H2P2_DBG_FPGA_LAN_RESET); + mdelay(50); +} + +void omap_perseus2_init_irq(void) +{ + omap_init_irq(); + omap_gpio_init(); + perseus2_init_smc91x(); +} + /* Only FPGA needs to be mapped here. All others are done with ioremap */ static struct map_desc omap_perseus2_io_desc[] __initdata = { {H2P2_DBG_FPGA_BASE, H2P2_DBG_FPGA_START, H2P2_DBG_FPGA_SIZE, diff --git a/arch/arm/mach-omap/dma.c b/arch/arm/mach-omap/dma.c index 4c3d7c27d..7a9ebe80d 100644 --- a/arch/arm/mach-omap/dma.c +++ b/arch/arm/mach-omap/dma.c @@ -6,6 +6,7 @@ * DMA channel linking for 1610 by Samuel Ortiz * Graphics DMA and LCD DMA graphics tranformations * by Imre Deak + * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc. * * Support functions for the OMAP internal DMA channels. * @@ -477,10 +478,6 @@ int omap_request_dma(int dev_id, const char *dev_name, if (dev_id == 0) break; } - if (dev_id != 0 && dma_chan[ch].dev_id == dev_id) { - spin_unlock_irqrestore(&dma_chan_lock, flags); - return -EAGAIN; - } } if (free_ch == -1) { spin_unlock_irqrestore(&dma_chan_lock, flags); @@ -497,7 +494,7 @@ int omap_request_dma(int dev_id, const char *dev_name, chan->data = data; chan->enabled_irqs = OMAP_DMA_TOUT_IRQ | OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ; - if (cpu_is_omap16xx() || cpu_is_omap730()) { + if (cpu_is_omap16xx()) { /* If the sync device is set, configure it dynamically. */ if (dev_id != 0) { set_gdma_dev(free_ch + 1, dev_id); @@ -931,6 +928,50 @@ void omap_stop_lcd_dma(void) OMAP1610_DMA_LCD_CCR); } +/* + * Clears any DMA state so the DMA engine is ready to restart with new buffers + * through omap_start_dma(). Any buffers in flight are discarded. + */ +void omap_clear_dma(int lch) +{ + unsigned long flags; + int status; + + local_irq_save(flags); + omap_writew(omap_readw(OMAP_DMA_CCR(lch)) & ~OMAP_DMA_CCR_EN, + OMAP_DMA_CCR(lch)); + status = OMAP_DMA_CSR(lch); /* clear pending interrupts */ + local_irq_restore(flags); +} + +/* + * Returns current physical source address for the given DMA channel. + * If the channel is running the caller must disable interrupts prior calling + * this function and process the returned value before re-enabling interrupt to + * prevent races with the interrupt handler. Note that in continuous mode there + * is a chance for CSSA_L register overflow inbetween the two reads resulting + * in incorrect return value. + */ +dma_addr_t omap_get_dma_src_pos(int lch) +{ + return (dma_addr_t) (OMAP_DMA_CSSA_L(lch) | + (OMAP_DMA_CSSA_U(lch) << 16)); +} + +/* + * Returns current physical destination address for the given DMA channel. + * If the channel is running the caller must disable interrupts prior calling + * this function and process the returned value before re-enabling interrupt to + * prevent races with the interrupt handler. Note that in continuous mode there + * is a chance for CDSA_L register overflow inbetween the two reads resulting + * in incorrect return value. + */ +dma_addr_t omap_get_dma_dst_pos(int lch) +{ + return (dma_addr_t) (OMAP_DMA_CDSA_L(lch) | + (OMAP_DMA_CDSA_U(lch) << 16)); +} + static int __init omap_init_dma(void) { int ch, r; @@ -999,9 +1040,13 @@ static int __init omap_init_dma(void) } return 0; } + arch_initcall(omap_init_dma); +EXPORT_SYMBOL(omap_get_dma_src_pos); +EXPORT_SYMBOL(omap_get_dma_dst_pos); +EXPORT_SYMBOL(omap_clear_dma); EXPORT_SYMBOL(omap_set_dma_priority); EXPORT_SYMBOL(omap_request_dma); EXPORT_SYMBOL(omap_free_dma); diff --git a/arch/arm/mach-omap/gpio.c b/arch/arm/mach-omap/gpio.c index e66dcf6ff..9045dfd46 100644 --- a/arch/arm/mach-omap/gpio.c +++ b/arch/arm/mach-omap/gpio.c @@ -114,7 +114,7 @@ static struct gpio_bank gpio_bank_1510[2] = { #ifdef CONFIG_ARCH_OMAP730 static struct gpio_bank gpio_bank_730[7] = { { OMAP_MPUIO_BASE, INT_730_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO }, - { OMAP730_GPIO1_BASE, INT_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_730 }, + { OMAP730_GPIO1_BASE, INT_730_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_730 }, { OMAP730_GPIO2_BASE, INT_730_GPIO_BANK2, IH_GPIO_BASE + 32, METHOD_GPIO_730 }, { OMAP730_GPIO3_BASE, INT_730_GPIO_BANK3, IH_GPIO_BASE + 64, METHOD_GPIO_730 }, { OMAP730_GPIO4_BASE, INT_730_GPIO_BANK4, IH_GPIO_BASE + 96, METHOD_GPIO_730 }, @@ -307,6 +307,9 @@ int omap_get_gpio_datain(int gpio) case METHOD_GPIO_1610: reg += OMAP1610_GPIO_DATAIN; break; + case METHOD_GPIO_730: + reg += OMAP730_GPIO_DATA_INPUT; + break; default: BUG(); return -1; @@ -407,13 +410,13 @@ static int _get_gpio_edge_ctrl(struct gpio_bank *bank, int gpio) } } -static void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio) +static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) { u32 reg = bank->base; switch (bank->method) { case METHOD_MPUIO: - /* MPUIO irqstatus cannot be cleared one bit at a time, + /* MPUIO irqstatus is reset by reading the status register, * so do nothing here */ return; case METHOD_GPIO_1510: @@ -429,10 +432,15 @@ static void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio) BUG(); return; } - __raw_writel(1 << get_gpio_index(gpio), reg); + __raw_writel(gpio_mask, reg); +} + +static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio) +{ + _clear_gpio_irqbank(bank, 1 << get_gpio_index(gpio)); } -static void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable) +static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enable) { u32 reg = bank->base; u32 l; @@ -442,33 +450,32 @@ static void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable) reg += OMAP_MPUIO_GPIO_MASKIT; l = __raw_readl(reg); if (enable) - l &= ~(1 << gpio); + l &= ~(gpio_mask); else - l |= 1 << gpio; + l |= gpio_mask; break; case METHOD_GPIO_1510: reg += OMAP1510_GPIO_INT_MASK; l = __raw_readl(reg); if (enable) - l &= ~(1 << gpio); + l &= ~(gpio_mask); else - l |= 1 << gpio; + l |= gpio_mask; break; case METHOD_GPIO_1610: - if (enable) { + if (enable) reg += OMAP1610_GPIO_SET_IRQENABLE1; - _clear_gpio_irqstatus(bank, gpio); - } else + else reg += OMAP1610_GPIO_CLEAR_IRQENABLE1; - l = 1 << gpio; + l = gpio_mask; break; case METHOD_GPIO_730: reg += OMAP730_GPIO_INT_MASK; l = __raw_readl(reg); if (enable) - l &= ~(1 << gpio); + l &= ~(gpio_mask); else - l |= 1 << gpio; + l |= gpio_mask; break; default: BUG(); @@ -477,6 +484,11 @@ static void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable) __raw_writel(l, reg); } +static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable) +{ + _enable_gpio_irqbank(bank, 1 << get_gpio_index(gpio), enable); +} + int omap_request_gpio(int gpio) { struct gpio_bank *bank; @@ -523,31 +535,31 @@ void omap_free_gpio(int gpio) } bank->reserved_map &= ~(1 << get_gpio_index(gpio)); _set_gpio_direction(bank, get_gpio_index(gpio), 1); - _set_gpio_irqenable(bank, get_gpio_index(gpio), 0); + _set_gpio_irqenable(bank, gpio, 0); + _clear_gpio_irqstatus(bank, gpio); spin_unlock(&bank->lock); } +/* + * We need to unmask the GPIO bank interrupt as soon as possible to + * avoid missing GPIO interrupts for other lines in the bank. + * Then we need to mask-read-clear-unmask the triggered GPIO lines + * in the bank to avoid missing nested interrupts for a GPIO line. + * If we wait to unmask individual GPIO lines in the bank after the + * line's interrupt handler has been run, we may miss some nested + * interrupts. + */ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) { u32 isr_reg = 0; - struct gpio_bank *bank = (struct gpio_bank *) desc->data; + u32 isr; + unsigned int gpio_irq; + struct gpio_bank *bank; - /* - * Acknowledge the parent IRQ. - */ desc->chip->ack(irq); - /* Since the level 1 GPIO interrupt cascade (IRQ14) is configured as - * edge-sensitive, we need to unmask it here in order to avoid missing - * any additional GPIO interrupts that might occur after the last time - * we check for pending GPIO interrupts here. - * We are relying on the fact that this interrupt handler was installed - * with the SA_INTERRUPT flag so that interrupts are disabled at the - * CPU while it is executing. - */ - desc->chip->unmask(irq); - + bank = (struct gpio_bank *) desc->data; if (bank->method == METHOD_MPUIO) isr_reg = bank->base + OMAP_MPUIO_GPIO_INT; #ifdef CONFIG_ARCH_OMAP1510 @@ -562,20 +574,23 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc, if (bank->method == METHOD_GPIO_730) isr_reg = bank->base + OMAP730_GPIO_INT_STATUS; #endif - for (;;) { - u32 isr = __raw_readl(isr_reg); - unsigned int gpio_irq; - - if (!isr) - break; - gpio_irq = bank->virtual_irq_start; - - for (; isr != 0; isr >>= 1, gpio_irq++) { - if (isr & 1) { - struct irqdesc *d = irq_desc + gpio_irq; - d->handle(gpio_irq, d, regs); - } - } + + isr = __raw_readl(isr_reg); + _enable_gpio_irqbank(bank, isr, 0); + _clear_gpio_irqbank(bank, isr); + _enable_gpio_irqbank(bank, isr, 1); + desc->chip->unmask(irq); + + if (unlikely(!isr)) + return; + + gpio_irq = bank->virtual_irq_start; + for (; isr != 0; isr >>= 1, gpio_irq++) { + struct irqdesc *d; + if (!(isr & 1)) + continue; + d = irq_desc + gpio_irq; + d->handle(gpio_irq, d, regs); } } @@ -584,18 +599,7 @@ static void gpio_ack_irq(unsigned int irq) unsigned int gpio = irq - IH_GPIO_BASE; struct gpio_bank *bank = get_gpio_bank(gpio); -#ifdef CONFIG_ARCH_OMAP1510 - if (bank->method == METHOD_GPIO_1510) - __raw_writew(1 << (gpio & 0x0f), bank->base + OMAP1510_GPIO_INT_STATUS); -#endif -#if defined(CONFIG_ARCH_OMAP16XX) - if (bank->method == METHOD_GPIO_1610) - __raw_writew(1 << (gpio & 0x0f), bank->base + OMAP1610_GPIO_IRQSTATUS1); -#endif -#ifdef CONFIG_ARCH_OMAP730 - if (bank->method == METHOD_GPIO_730) - __raw_writel(1 << (gpio & 0x1f), bank->base + OMAP730_GPIO_INT_STATUS); -#endif + _clear_gpio_irqstatus(bank, gpio); } static void gpio_mask_irq(unsigned int irq) @@ -603,7 +607,7 @@ static void gpio_mask_irq(unsigned int irq) unsigned int gpio = irq - IH_GPIO_BASE; struct gpio_bank *bank = get_gpio_bank(gpio); - _set_gpio_irqenable(bank, get_gpio_index(gpio), 0); + _set_gpio_irqenable(bank, gpio, 0); } static void gpio_unmask_irq(unsigned int irq) @@ -616,7 +620,7 @@ static void gpio_unmask_irq(unsigned int irq) gpio); _set_gpio_edge_ctrl(bank, get_gpio_index(gpio), OMAP_GPIO_RISING_EDGE); } - _set_gpio_irqenable(bank, get_gpio_index(gpio), 1); + _set_gpio_irqenable(bank, gpio, 1); } static void mpuio_ack_irq(unsigned int irq) @@ -629,7 +633,7 @@ static void mpuio_mask_irq(unsigned int irq) unsigned int gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE); struct gpio_bank *bank = get_gpio_bank(gpio); - _set_gpio_irqenable(bank, get_gpio_index(gpio), 0); + _set_gpio_irqenable(bank, gpio, 0); } static void mpuio_unmask_irq(unsigned int irq) @@ -637,7 +641,7 @@ static void mpuio_unmask_irq(unsigned int irq) unsigned int gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE); struct gpio_bank *bank = get_gpio_bank(gpio); - _set_gpio_irqenable(bank, get_gpio_index(gpio), 1); + _set_gpio_irqenable(bank, gpio, 1); } static struct irqchip gpio_irq_chip = { @@ -722,7 +726,7 @@ static int __init _omap_gpio_init(void) set_irq_chip(j, &mpuio_irq_chip); else set_irq_chip(j, &gpio_irq_chip); - set_irq_handler(j, do_edge_IRQ); + set_irq_handler(j, do_simple_IRQ); set_irq_flags(j, IRQF_VALID); } set_irq_chained_handler(bank->irq, gpio_irq_handler); diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index bb28824d8..405a55f22 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -8,6 +8,7 @@ choice config ARCH_LUBBOCK bool "Intel DBPXA250 Development Platform" select PXA25x + select SA1111 config MACH_MAINSTONE bool "Intel HCDDBBVA0 Development Platform" @@ -18,10 +19,41 @@ config ARCH_PXA_IDP bool "Accelent Xscale IDP" select PXA25x +config PXA_SHARPSL + bool "SHARP SL-5600 and SL-C7xx Models" + select PXA25x + select SHARP_SCOOP + select SHARP_PARAM + help + Say Y here if you intend to run this kernel on a + Sharp SL-5600 (Poodle), Sharp SL-C700 (Corgi), + SL-C750 (Shepherd) or a Sharp SL-C760 (Husky) + handheld computer. + endchoice endmenu +config MACH_POODLE + bool "Enable Sharp SL-5600 (Poodle) Support" + depends PXA_SHARPSL + select SHARP_LOCOMO + +config MACH_CORGI + bool "Enable Sharp SL-C700 (Corgi) Support" + depends PXA_SHARPSL + select PXA_SHARP_C7xx + +config MACH_SHEPHERD + bool "Enable Sharp SL-C750 (Shepherd) Support" + depends PXA_SHARPSL + select PXA_SHARP_C7xx + +config MACH_HUSKY + bool "Enable Sharp SL-C760 (Husky) Support" + depends PXA_SHARPSL + select PXA_SHARP_C7xx + config PXA25x bool help @@ -37,4 +69,9 @@ config IWMMXT help Enable support for iWMMXt +config PXA_SHARP_C7xx + bool + help + Enable support for all Sharp C7xx models + endif diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 23c51e388..c4e6d2523 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -11,6 +11,8 @@ obj-$(CONFIG_PXA27x) += pxa27x.o obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o obj-$(CONFIG_ARCH_PXA_IDP) += idp.o +obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o ssp.o +obj-$(CONFIG_MACH_POODLE) += poodle.o # Support for blinky lights led-y := leds.o diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index 3fe020210..a45aaa115 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c @@ -92,7 +92,7 @@ EXPORT_SYMBOL(pxa_set_cken); */ static struct map_desc standard_io_desc[] __initdata = { /* virtual physical length type */ - { 0xf2000000, 0x40000000, 0x01800000, MT_DEVICE }, /* Devs */ + { 0xf2000000, 0x40000000, 0x02000000, MT_DEVICE }, /* Devs */ { 0xf4000000, 0x44000000, 0x00100000, MT_DEVICE }, /* LCD */ { 0xf6000000, 0x48000000, 0x00100000, MT_DEVICE }, /* Mem Ctl */ { 0xf8000000, 0x4c000000, 0x00100000, MT_DEVICE }, /* USB host */ @@ -220,6 +220,30 @@ static struct platform_device stuart_device = { .id = 2, }; +static struct resource i2c_resources[] = { + { + .start = 0x40301680, + .end = 0x403016a3, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_I2C, + .end = IRQ_I2C, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device i2c_device = { + .name = "pxa2xx-i2c", + .id = 0, + .resource = i2c_resources, + .num_resources = ARRAY_SIZE(i2c_resources), +}; + +void __init pxa_set_i2c_info(struct i2c_pxa_platform_data *info) +{ + i2c_device.dev.platform_data = info; +} + static struct platform_device *devices[] __initdata = { &pxamci_device, &udc_device, @@ -227,6 +251,7 @@ static struct platform_device *devices[] __initdata = { &ffuart_device, &btuart_device, &stuart_device, + &i2c_device, }; static int __init pxa_init(void) diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c index 4333a0f19..c5a66bf4d 100644 --- a/arch/arm/mach-pxa/idp.c +++ b/arch/arm/mach-pxa/idp.c @@ -10,13 +10,16 @@ * 2001-09-13: Cliff Brake * Initial code * - * Expected command line: mem=32M initrd=0xa1000000,4M root=/dev/ram ramdisk=8192 + * 2005-02-15: Cliff Brake + * + * Updated for 2.6 kernel + * */ -#include + #include -#include -#include #include +#include +#include #include #include @@ -29,68 +32,133 @@ #include #include +#include +#include +#include #include "generic.h" -#ifndef PXA_IDP_REV02 -/* shadow registers for write only registers */ -unsigned int idp_cpld_led_control_shadow = 0x1; -unsigned int idp_cpld_periph_pwr_shadow = 0xd; -unsigned int ipd_cpld_cir_shadow = 0; -unsigned int idp_cpld_kb_col_high_shadow = 0; -unsigned int idp_cpld_kb_col_low_shadow = 0; -unsigned int idp_cpld_pccard_en_shadow = 0xC3; -unsigned int idp_cpld_gpioh_dir_shadow = 0; -unsigned int idp_cpld_gpioh_value_shadow = 0; -unsigned int idp_cpld_gpiol_dir_shadow = 0; -unsigned int idp_cpld_gpiol_value_shadow = 0; - -/* - * enable all LCD signals -- they should still be on - * write protect flash - * enable all serial port transceivers +/* TODO: + * - add pxa2xx_audio_ops_t device structure + * - Ethernet interrupt */ -unsigned int idp_control_port_shadow = ((0x7 << 21) | /* LCD power */ - (0x1 << 19) | /* disable flash write enable */ - (0x7 << 9)); /* enable serial port transeivers */ +static struct resource smc91x_resources[] = { + [0] = { + .start = (IDP_ETH_PHYS + 0x300), + .end = (IDP_ETH_PHYS + 0xfffff), + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_GPIO(4), + .end = IRQ_GPIO(4), + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device smc91x_device = { + .name = "smc91x", + .id = 0, + .num_resources = ARRAY_SIZE(smc91x_resources), + .resource = smc91x_resources, +}; + +static void idp_backlight_power(int on) +{ + if (on) { + IDP_CPLD_LCD |= (1<<1); + } else { + IDP_CPLD_LCD &= ~(1<<1); + } +} + +static void idp_vlcd(int on) +{ + if (on) { + IDP_CPLD_LCD |= (1<<2); + } else { + IDP_CPLD_LCD &= ~(1<<2); + } +} + +static void idp_lcd_power(int on) +{ + if (on) { + IDP_CPLD_LCD |= (1<<0); + } else { + IDP_CPLD_LCD &= ~(1<<0); + } + + /* call idp_vlcd for now as core driver does not support + * both power and vlcd hooks. Note, this is not technically + * the correct sequence, but seems to work. Disclaimer: + * this may eventually damage the display. + */ + + idp_vlcd(on); +} + +static struct pxafb_mach_info sharp_lm8v31 __initdata = { + .pixclock = 270000, + .xres = 640, + .yres = 480, + .bpp = 16, + .hsync_len = 1, + .left_margin = 3, + .right_margin = 3, + .vsync_len = 1, + .upper_margin = 0, + .lower_margin = 0, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .cmap_greyscale = 0, + .cmap_inverse = 0, + .cmap_static = 0, + .lccr0 = LCCR0_SDS, + .lccr3 = LCCR3_PCP | LCCR3_Acb(255), + .pxafb_backlight_power = &idp_backlight_power, + .pxafb_lcd_power = &idp_lcd_power +}; -#endif +static int idp_mci_init(struct device *dev, irqreturn_t (*idp_detect_int)(int, void *, struct pt_regs *), void *data) +{ + /* setup GPIO for PXA25x MMC controller */ + pxa_gpio_mode(GPIO6_MMCCLK_MD); + pxa_gpio_mode(GPIO8_MMCCS0_MD); + + return 0; +} + +static struct pxamci_platform_data idp_mci_platform_data = { + .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, + .init = idp_mci_init, +}; static void __init idp_init(void) { printk("idp_init()\n"); + + platform_device_register(&smc91x_device); + //platform_device_register(&mst_audio_device); + set_pxa_fb_info(&sharp_lm8v31); + pxa_set_mci_info(&idp_mci_platform_data); } static void __init idp_init_irq(void) { + pxa_init_irq(); + + set_irq_type(TOUCH_PANEL_IRQ, TOUCH_PANEL_IRQ_EDGE); } static struct map_desc idp_io_desc[] __initdata = { /* virtual physical length type */ - -#ifndef PXA_IDP_REV02 - { IDP_CTRL_PORT_BASE, - IDP_CTRL_PORT_PHYS, - IDP_CTRL_PORT_SIZE, - MT_DEVICE }, -#endif - - { IDP_IDE_BASE, - IDP_IDE_PHYS, - IDP_IDE_SIZE, - MT_DEVICE }, - { IDP_ETH_BASE, - IDP_ETH_PHYS, - IDP_ETH_SIZE, - MT_DEVICE }, - { IDP_COREVOLT_BASE, + { IDP_COREVOLT_VIRT, IDP_COREVOLT_PHYS, IDP_COREVOLT_SIZE, MT_DEVICE }, - { IDP_CPLD_BASE, + { IDP_CPLD_VIRT, IDP_CPLD_PHYS, IDP_CPLD_SIZE, MT_DEVICE } @@ -101,8 +169,6 @@ static void __init idp_map_io(void) pxa_map_io(); iotable_init(idp_io_desc, ARRAY_SIZE(idp_io_desc)); - set_irq_type(TOUCH_PANEL_IRQ, TOUCH_PANEL_IRQ_EDGE); - // serial ports 2 & 3 pxa_gpio_mode(GPIO42_BTRXD_MD); pxa_gpio_mode(GPIO43_BTTXD_MD); @@ -114,8 +180,8 @@ static void __init idp_map_io(void) } -MACHINE_START(PXA_IDP, "Accelent Xscale IDP") - MAINTAINER("Accelent Systems Inc.") +MACHINE_START(PXA_IDP, "Vibren PXA255 IDP") + MAINTAINER("Vibren Technologies") BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000)) MAPIO(idp_map_io) INITIRQ(idp_init_irq) diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c index 87fd729c3..f2c9e0d2b 100644 --- a/arch/arm/mach-pxa/lubbock.c +++ b/arch/arm/mach-pxa/lubbock.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -29,12 +30,13 @@ #include #include +#include + #include #include #include #include #include -#include #include "generic.h" @@ -105,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; @@ -137,6 +168,7 @@ static struct platform_device sa1111_device = { static struct resource smc91x_resources[] = { [0] = { + .name = "smc91x-regs", .start = 0x0c000000, .end = 0x0c0fffff, .flags = IORESOURCE_MEM, @@ -147,6 +179,7 @@ static struct resource smc91x_resources[] = { .flags = IORESOURCE_IRQ, }, [2] = { + .name = "smc91x-attrib", .start = 0x0e000000, .end = 0x0e0fffff, .flags = IORESOURCE_MEM, diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c index 901ee6880..9799fe80d 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] @@ -47,16 +44,28 @@ extern void pxa_cpu_resume(void); */ enum { SLEEP_SAVE_START = 0, - SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2, - SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2, - SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2, - SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2, - SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR2_L, - SLEEP_SAVE_GAFR0_U, SLEEP_SAVE_GAFR1_U, SLEEP_SAVE_GAFR2_U, + SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2, SLEEP_SAVE_GPLR3, + SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2, SLEEP_SAVE_GPDR3, + SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2, SLEEP_SAVE_GRER3, + SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2, SLEEP_SAVE_GFER3, + SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, SLEEP_SAVE_PGSR3, + + SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U, + SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR1_U, + SLEEP_SAVE_GAFR2_L, SLEEP_SAVE_GAFR2_U, + SLEEP_SAVE_GAFR3_L, SLEEP_SAVE_GAFR3_U, + + SLEEP_SAVE_PSTR, 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 @@ -69,9 +78,12 @@ static int pxa_pm_enter(suspend_state_t state) unsigned long checksum = 0; struct timespec delta, rtc; int i; + extern void pxa_cpu_pm_enter(suspend_state_t state); - if (state != PM_SUSPEND_MEM) - return -EINVAL; +#ifdef CONFIG_IWMMXT + /* force any iWMMXt context to ram **/ + iwmmxt_task_disable(NULL); +#endif /* preserve current time */ rtc.tv_sec = RCNR; @@ -82,34 +94,44 @@ static int pxa_pm_enter(suspend_state_t state) SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2); SAVE(GRER0); SAVE(GRER1); SAVE(GRER2); SAVE(GFER0); SAVE(GFER1); SAVE(GFER2); + SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2); + SAVE(GAFR0_L); SAVE(GAFR0_U); SAVE(GAFR1_L); SAVE(GAFR1_U); 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 */ /* clear GPIO transition detect bits */ GEDR0 = GEDR0; GEDR1 = GEDR1; GEDR2 = GEDR2; +#ifdef CONFIG_PXA27x + GEDR3 = GEDR3; +#endif /* 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); /* after sleeping, validate the checksum */ checksum = 0; @@ -121,7 +143,8 @@ static int pxa_pm_enter(suspend_state_t state) #ifdef CONFIG_ARCH_LUBBOCK LUB_HEXLED = 0xbadbadc5; #endif - while (1); + while (1) + pxa_cpu_pm_enter(state); } /* ensure not to come back here if it wasn't intended */ @@ -135,6 +158,15 @@ static int pxa_pm_enter(suspend_state_t state) RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2); RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2); RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2); + 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; @@ -144,6 +176,8 @@ static int pxa_pm_enter(suspend_state_t state) ICCR = 1; RESTORE(ICMR); + RESTORE(PSTR); + /* restore current time */ rtc.tv_sec = RCNR; restore_time_delta(&delta, &rtc); @@ -165,7 +199,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-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c index 2f60dea2a..815c53225 100644 --- a/arch/arm/mach-rpc/riscpc.c +++ b/arch/arm/mach-rpc/riscpc.c @@ -67,7 +67,7 @@ __tagtable(ATAG_ACORN, parse_tag_acorn); static struct map_desc rpc_io_desc[] __initdata = { { SCREEN_BASE, SCREEN_START, 2*1048576, MT_DEVICE }, /* VRAM */ - { IO_BASE, IO_START, IO_SIZE , MT_DEVICE }, /* IO space */ + { (u32)IO_BASE, IO_START, IO_SIZE , MT_DEVICE }, /* IO space */ { EASI_BASE, EASI_START, EASI_SIZE, MT_DEVICE } /* EASI space */ }; diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig index 40604ed09..534df0c6c 100644 --- a/arch/arm/mach-s3c2410/Kconfig +++ b/arch/arm/mach-s3c2410/Kconfig @@ -19,6 +19,14 @@ config ARCH_H1940 . +config MACH_N30 + bool "Acer N30" + select CPU_S3C2410 + help + Say Y here if you are using the Acer N30 + + . + config ARCH_SMDK2410 bool "SMDK2410/A9M2410" select CPU_S3C2410 @@ -26,6 +34,12 @@ config ARCH_SMDK2410 Say Y here if you are using the SMDK2410 or the derived module A9M2410 +config ARCH_S3C2440 + bool "SMDK2440" + select CPU_S3C2440 + help + Say Y here if you are using the SMDK2440. + config MACH_VR1000 bool "Thorcom VR1000" select CPU_S3C2410 @@ -41,9 +55,21 @@ config MACH_RX3715 help Say Y here if you are using the HP iPAQ rx3715. - See http://www.handhelds.org/projects/rx3715.html for more + See for more information on this project +config MACH_OTOM + bool "NexVision OTOM Board" + select CPU_S3C2410 + help + Say Y here if you are using the Nex Vision OTOM board + +config MACH_NEXCODER_2440 + bool "NexVision NEXCODER 2440 Light Board" + select CPU_S3C2440 + help + Say Y here if you are using the Nex Vision NEXCODER 2440 Light Board + endmenu config CPU_S3C2410 @@ -59,6 +85,26 @@ config CPU_S3C2440 help Support for S3C2440 Samsung Mobile CPU based systems. +comment "S3C2410 Boot" + +config S3C2410_BOOT_WATCHDOG + bool "S3C2410 Initialisation watchdog" + depends on ARCH_S3C2410 && S3C2410_WATCHDOG + help + Say y to enable the watchdog during the kernel decompression + stage. If the kernel fails to uncompress, then the watchdog + will trigger a reset and the system should restart. + + Although this uses the same hardware unit as the kernel watchdog + driver, it is not a replacement for it. If you use this option, + you will have to use the watchdg driver to either stop the timeout + or restart it. If you do not, then your kernel will reboot after + startup. + + The driver uses a fixed timeout value, so the exact time till the + system resets depends on the value of PCLK. The timeout on an + 200MHz s3c2410 should be about 30 seconds. + comment "S3C2410 Setup" config S3C2410_DMA @@ -77,7 +123,7 @@ config S3C2410_DMA_DEBUG to the kernel log, at priority KERN_DEBUG. Note, it is easy to create and fill the log buffer in a small - amount of time, as well as using an significant percantage of + amount of time, as well as using an significant percentage of the CPU time doing so. @@ -115,9 +161,9 @@ config S3C2410_LOWLEVEL_UART_PORT Choice of which UART port to use for the low-level messages, such as the `Uncompressing...` at start time. The value of this configuration should be between zero and two. The port - must have been initalised by the boot-loader before use. + must have been initialised by the boot-loader before use. Note, this does not affect the port used by the debug messages, - which is a seperate configuration. + which is a separate configuration. endif diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile index aa8b30874..7c379aad5 100644 --- a/arch/arm/mach-s3c2410/Makefile +++ b/arch/arm/mach-s3c2410/Makefile @@ -27,6 +27,10 @@ obj-$(CONFIG_CPU_S3C2440) += s3c2440.o s3c2440-dsc.o obj-$(CONFIG_ARCH_BAST) += mach-bast.o usb-simtec.o obj-$(CONFIG_ARCH_H1940) += mach-h1940.o +obj-$(CONFIG_MACH_N30) += mach-n30.o obj-$(CONFIG_ARCH_SMDK2410) += mach-smdk2410.o +obj-$(CONFIG_ARCH_S3C2440) += mach-smdk2440.o obj-$(CONFIG_MACH_VR1000) += mach-vr1000.o usb-simtec.o obj-$(CONFIG_MACH_RX3715) += mach-rx3715.o +obj-$(CONFIG_MACH_OTOM) += mach-otom.o +obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c index 7e6257c86..3bb97eb6e 100644 --- a/arch/arm/mach-s3c2410/mach-bast.c +++ b/arch/arm/mach-s3c2410/mach-bast.c @@ -1,6 +1,6 @@ /* linux/arch/arm/mach-s3c2410/mach-bast.c * - * Copyright (c) 2003,2004 Simtec Electronics + * Copyright (c) 2003-2005 Simtec Electronics * Ben Dooks * * http://www.simtec.co.uk/products/EB2410ITX/ @@ -20,6 +20,12 @@ * 18-Jan-2003 BJD Added serial port configuration * 05-Oct-2004 BJD Power management code * 04-Nov-2004 BJD Updated serial port clocks + * 04-Jan-2005 BJD New uart init call + * 10-Jan-2005 BJD Removed include of s3c2410.h + * 14-Jan-2005 BJD Add support for muitlple NAND devices + * 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 */ #include @@ -36,6 +42,7 @@ #include #include +#include #include #include @@ -46,21 +53,26 @@ #include #include #include +#include + +#include +#include +#include +#include -#include "s3c2410.h" #include "clock.h" #include "devs.h" #include "cpu.h" #include "usb-simtec.h" #include "pm.h" -#define COPYRIGHT ", (c) 2004 Simtec Electronics" +#define COPYRIGHT ", (c) 2004-2005 Simtec Electronics" /* macros for virtual address mods for the io space entries */ -#define VA_C5(item) ((item) + BAST_VAM_CS5) -#define VA_C4(item) ((item) + BAST_VAM_CS4) -#define VA_C3(item) ((item) + BAST_VAM_CS3) -#define VA_C2(item) ((item) + BAST_VAM_CS2) +#define VA_C5(item) ((unsigned long)(item) + BAST_VAM_CS5) +#define VA_C4(item) ((unsigned long)(item) + BAST_VAM_CS4) +#define VA_C3(item) ((unsigned long)(item) + BAST_VAM_CS3) +#define VA_C2(item) ((unsigned long)(item) + BAST_VAM_CS2) /* macros to modify the physical addresses for io space */ @@ -72,8 +84,8 @@ static struct map_desc bast_iodesc[] __initdata = { /* ISA IO areas */ - { S3C2410_VA_ISA_BYTE, PA_CS2(BAST_PA_ISAIO), SZ_16M, MT_DEVICE }, - { S3C2410_VA_ISA_WORD, PA_CS3(BAST_PA_ISAIO), SZ_16M, MT_DEVICE }, + { (u32)S3C24XX_VA_ISA_BYTE, PA_CS2(BAST_PA_ISAIO), SZ_16M, MT_DEVICE }, + { (u32)S3C24XX_VA_ISA_WORD, PA_CS3(BAST_PA_ISAIO), SZ_16M, MT_DEVICE }, /* we could possibly compress the next set down into a set of smaller tables * pagetables, but that would mean using an L2 section, and it still means @@ -81,26 +93,15 @@ static struct map_desc bast_iodesc[] __initdata = { */ /* bast CPLD control registers, and external interrupt controls */ - { BAST_VA_CTRL1, BAST_PA_CTRL1, SZ_1M, MT_DEVICE }, - { BAST_VA_CTRL2, BAST_PA_CTRL2, SZ_1M, MT_DEVICE }, - { BAST_VA_CTRL3, BAST_PA_CTRL3, SZ_1M, MT_DEVICE }, - { BAST_VA_CTRL4, BAST_PA_CTRL4, SZ_1M, MT_DEVICE }, + { (u32)BAST_VA_CTRL1, BAST_PA_CTRL1, SZ_1M, MT_DEVICE }, + { (u32)BAST_VA_CTRL2, BAST_PA_CTRL2, SZ_1M, MT_DEVICE }, + { (u32)BAST_VA_CTRL3, BAST_PA_CTRL3, SZ_1M, MT_DEVICE }, + { (u32)BAST_VA_CTRL4, BAST_PA_CTRL4, SZ_1M, MT_DEVICE }, /* PC104 IRQ mux */ - { BAST_VA_PC104_IRQREQ, BAST_PA_PC104_IRQREQ, SZ_1M, MT_DEVICE }, - { BAST_VA_PC104_IRQRAW, BAST_PA_PC104_IRQRAW, SZ_1M, MT_DEVICE }, - { BAST_VA_PC104_IRQMASK, BAST_PA_PC104_IRQMASK, SZ_1M, MT_DEVICE }, - - /* onboard 8bit lcd port */ - - { BAST_VA_LCD_RCMD1, BAST_PA_LCD_RCMD1, SZ_1M, MT_DEVICE }, - { BAST_VA_LCD_WCMD1, BAST_PA_LCD_WCMD1, SZ_1M, MT_DEVICE }, - { BAST_VA_LCD_RDATA1, BAST_PA_LCD_RDATA1, SZ_1M, MT_DEVICE }, - { BAST_VA_LCD_WDATA1, BAST_PA_LCD_WDATA1, SZ_1M, MT_DEVICE }, - { BAST_VA_LCD_RCMD2, BAST_PA_LCD_RCMD2, SZ_1M, MT_DEVICE }, - { BAST_VA_LCD_WCMD2, BAST_PA_LCD_WCMD2, SZ_1M, MT_DEVICE }, - { BAST_VA_LCD_RDATA2, BAST_PA_LCD_RDATA2, SZ_1M, MT_DEVICE }, - { BAST_VA_LCD_WDATA2, BAST_PA_LCD_WDATA2, SZ_1M, MT_DEVICE }, + { (u32)BAST_VA_PC104_IRQREQ, BAST_PA_PC104_IRQREQ, SZ_1M, MT_DEVICE }, + { (u32)BAST_VA_PC104_IRQRAW, BAST_PA_PC104_IRQRAW, SZ_1M, MT_DEVICE }, + { (u32)BAST_VA_PC104_IRQMASK, BAST_PA_PC104_IRQMASK, SZ_1M, MT_DEVICE }, /* peripheral space... one for each of fast/slow/byte/16bit */ /* note, ide is only decoded in word space, even though some registers @@ -219,6 +220,100 @@ static struct platform_device bast_device_nor = { .resource = bast_nor_resource, }; +/* NAND Flash on BAST board */ + + +static int smartmedia_map[] = { 0 }; +static int chip0_map[] = { 1 }; +static int chip1_map[] = { 2 }; +static int chip2_map[] = { 3 }; + +struct mtd_partition bast_default_nand_part[] = { + [0] = { + .name = "Boot Agent", + .size = SZ_16K, + .offset = 0 + }, + [1] = { + .name = "/boot", + .size = SZ_4M - SZ_16K, + .offset = SZ_16K, + }, + [2] = { + .name = "user", + .offset = SZ_4M, + .size = MTDPART_SIZ_FULL, + } +}; + +/* the bast has 4 selectable slots for nand-flash, the three + * on-board chip areas, as well as the external SmartMedia + * slot. + * + * Note, there is no current hot-plug support for the SmartMedia + * socket. +*/ + +static struct s3c2410_nand_set bast_nand_sets[] = { + [0] = { + .name = "SmartMedia", + .nr_chips = 1, + .nr_map = smartmedia_map, + .nr_partitions = ARRAY_SIZE(bast_default_nand_part), + .partitions = bast_default_nand_part + }, + [1] = { + .name = "chip0", + .nr_chips = 1, + .nr_map = chip0_map, + .nr_partitions = ARRAY_SIZE(bast_default_nand_part), + .partitions = bast_default_nand_part + }, + [2] = { + .name = "chip1", + .nr_chips = 1, + .nr_map = chip1_map, + .nr_partitions = ARRAY_SIZE(bast_default_nand_part), + .partitions = bast_default_nand_part + }, + [3] = { + .name = "chip2", + .nr_chips = 1, + .nr_map = chip2_map, + .nr_partitions = ARRAY_SIZE(bast_default_nand_part), + .partitions = bast_default_nand_part + } +}; + +static void bast_nand_select(struct s3c2410_nand_set *set, int slot) +{ + unsigned int tmp; + + slot = set->nr_map[slot] & 3; + + pr_debug("bast_nand: selecting slot %d (set %p,%p)\n", + slot, set, set->nr_map); + + tmp = __raw_readb(BAST_VA_CTRL2); + tmp &= BAST_CPLD_CTLR2_IDERST; + tmp |= slot; + tmp |= BAST_CPLD_CTRL2_WNAND; + + pr_debug("bast_nand: ctrl2 now %02x\n", tmp); + + __raw_writeb(tmp, BAST_VA_CTRL2); +} + +static struct s3c2410_platform_nand bast_nand_info = { + .tacls = 80, + .twrph0 = 80, + .twrph1 = 80, + .nr_sets = ARRAY_SIZE(bast_nand_sets), + .sets = bast_nand_sets, + .select_chip = bast_nand_select, +}; + + /* Standard BAST devices */ static struct platform_device *bast_devices[] __initdata = { @@ -228,6 +323,7 @@ static struct platform_device *bast_devices[] __initdata = { &s3c_device_i2c, &s3c_device_iis, &s3c_device_rtc, + &s3c_device_nand, &bast_device_nor }; @@ -261,15 +357,18 @@ void __init bast_map_io(void) s3c24xx_uclk.parent = &s3c24xx_clkout1; + s3c_device_nand.dev.platform_data = &bast_nand_info; + s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc)); - s3c2410_init_uarts(bast_uartcfgs, ARRAY_SIZE(bast_uartcfgs)); + s3c24xx_init_clocks(0); + s3c24xx_init_uarts(bast_uartcfgs, ARRAY_SIZE(bast_uartcfgs)); s3c24xx_set_board(&bast_board); usb_simtec_init(); } void __init bast_init_irq(void) { - s3c2410_init_irq(); + s3c24xx_init_irq(); } #ifdef CONFIG_PM @@ -301,10 +400,10 @@ static __init void bast_init_machine(void) MACHINE_START(BAST, "Simtec-BAST") MAINTAINER("Ben Dooks ") - BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART) + BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, (u32)S3C24XX_VA_UART) BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100) MAPIO(bast_map_io) INITIRQ(bast_init_irq) .init_machine = bast_init_machine, - .timer = &s3c2410_timer, + .timer = &s3c24xx_timer, MACHINE_END diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c index 8d0f08450..2924afc06 100644 --- a/arch/arm/mach-s3c2410/mach-h1940.c +++ b/arch/arm/mach-s3c2410/mach-h1940.c @@ -1,6 +1,6 @@ /* linux/arch/arm/mach-s3c2410/mach-h1940.c * - * Copyright (c) 2003,2004 Simtec Electronics + * Copyright (c) 2003-2005 Simtec Electronics * Ben Dooks * * http://www.handhelds.org/projects/h1940.html @@ -20,6 +20,10 @@ * 04-Sep-2004 BJD Changed uart init, renamed ipaq_ -> h1940_ * 18-Oct-2004 BJD Updated new board structure name * 04-Nov-2004 BJD Change for new serial clock + * 04-Jan-2005 BJD Updated uart init call + * 10-Jan-2005 BJD Removed include of s3c2410.h + * 14-Jan-2005 BJD Added clock init + * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA */ #include @@ -44,7 +48,6 @@ #include -#include "s3c2410.h" #include "clock.h" #include "devs.h" #include "cpu.h" @@ -102,21 +105,22 @@ static struct s3c24xx_board h1940_board __initdata = { void __init h1940_map_io(void) { s3c24xx_init_io(h1940_iodesc, ARRAY_SIZE(h1940_iodesc)); - s3c2410_init_uarts(h1940_uartcfgs, ARRAY_SIZE(h1940_uartcfgs)); + s3c24xx_init_clocks(0); + s3c24xx_init_uarts(h1940_uartcfgs, ARRAY_SIZE(h1940_uartcfgs)); s3c24xx_set_board(&h1940_board); } void __init h1940_init_irq(void) { - s3c2410_init_irq(); + s3c24xx_init_irq(); } MACHINE_START(H1940, "IPAQ-H1940") MAINTAINER("Ben Dooks ") - BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART) + BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, (u32)S3C24XX_VA_UART) BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100) MAPIO(h1940_map_io) INITIRQ(h1940_init_irq) - .timer = &s3c2410_timer, + .timer = &s3c24xx_timer, MACHINE_END diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c index 4079af11a..5512146b1 100644 --- a/arch/arm/mach-s3c2410/mach-vr1000.c +++ b/arch/arm/mach-s3c2410/mach-vr1000.c @@ -1,6 +1,6 @@ /* linux/arch/arm/mach-s3c2410/mach-vr1000.c * - * Copyright (c) 2003,2004 Simtec Electronics + * Copyright (c) 2003-2005 Simtec Electronics * Ben Dooks * * Machine support for Thorcom VR1000 board. Designed for Thorcom by @@ -18,6 +18,15 @@ * 05-Apr-2004 BJD Copied to make mach-vr1000.c * 18-Oct-2004 BJD Updated board struct * 04-Nov-2004 BJD Clock and serial configuration update + * + * 04-Jan-2005 BJD Updated uart init call + * 10-Jan-2005 BJD Removed include of s3c2410.h + * 14-Jan-2005 BJD Added clock init + * 15-Jan-2005 BJD Add serial port device definition + * 20-Jan-2005 BJD Use UPF_IOREMAP for ports + * 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 */ #include @@ -27,32 +36,38 @@ #include #include +#include +#include +#include +#include + #include #include #include #include #include +#include +#include #include #include #include #include -//#include #include +#include -#include "s3c2410.h" #include "clock.h" #include "devs.h" #include "cpu.h" #include "usb-simtec.h" /* macros for virtual address mods for the io space entries */ -#define VA_C5(item) ((item) + BAST_VAM_CS5) -#define VA_C4(item) ((item) + BAST_VAM_CS4) -#define VA_C3(item) ((item) + BAST_VAM_CS3) -#define VA_C2(item) ((item) + BAST_VAM_CS2) +#define VA_C5(item) ((unsigned long)(item) + BAST_VAM_CS5) +#define VA_C4(item) ((unsigned long)(item) + BAST_VAM_CS4) +#define VA_C3(item) ((unsigned long)(item) + BAST_VAM_CS3) +#define VA_C2(item) ((unsigned long)(item) + BAST_VAM_CS2) /* macros to modify the physical addresses for io space */ @@ -64,8 +79,8 @@ static struct map_desc vr1000_iodesc[] __initdata = { /* ISA IO areas */ - { S3C2410_VA_ISA_BYTE, PA_CS2(BAST_PA_ISAIO), SZ_16M, MT_DEVICE }, - { S3C2410_VA_ISA_WORD, PA_CS3(BAST_PA_ISAIO), SZ_16M, MT_DEVICE }, + { (u32)S3C24XX_VA_ISA_BYTE, PA_CS2(BAST_PA_ISAIO), SZ_16M, MT_DEVICE }, + { (u32)S3C24XX_VA_ISA_WORD, PA_CS3(BAST_PA_ISAIO), SZ_16M, MT_DEVICE }, /* we could possibly compress the next set down into a set of smaller tables * pagetables, but that would mean using an L2 section, and it still means @@ -73,10 +88,10 @@ static struct map_desc vr1000_iodesc[] __initdata = { */ /* bast CPLD control registers, and external interrupt controls */ - { VR1000_VA_CTRL1, VR1000_PA_CTRL1, SZ_1M, MT_DEVICE }, - { VR1000_VA_CTRL2, VR1000_PA_CTRL2, SZ_1M, MT_DEVICE }, - { VR1000_VA_CTRL3, VR1000_PA_CTRL3, SZ_1M, MT_DEVICE }, - { VR1000_VA_CTRL4, VR1000_PA_CTRL4, SZ_1M, MT_DEVICE }, + { (u32)VR1000_VA_CTRL1, VR1000_PA_CTRL1, SZ_1M, MT_DEVICE }, + { (u32)VR1000_VA_CTRL2, VR1000_PA_CTRL2, SZ_1M, MT_DEVICE }, + { (u32)VR1000_VA_CTRL3, VR1000_PA_CTRL3, SZ_1M, MT_DEVICE }, + { (u32)VR1000_VA_CTRL4, VR1000_PA_CTRL4, SZ_1M, MT_DEVICE }, /* peripheral space... one for each of fast/slow/byte/16bit */ /* note, ide is only decoded in word space, even though some registers @@ -164,12 +179,82 @@ static struct s3c2410_uartcfg vr1000_uartcfgs[] = { } }; +/* definitions for the vr1000 extra 16550 serial ports */ + +#define VR1000_BAUDBASE (3692307) + +#define VR1000_SERIAL_MAPBASE(x) (VR1000_PA_SERIAL + 0x80 + ((x) << 5)) + +static struct plat_serial8250_port serial_platform_data[] = { + [0] = { + .mapbase = VR1000_SERIAL_MAPBASE(0), + .irq = IRQ_VR1000_SERIAL + 0, + .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, + .iotype = UPIO_MEM, + .regshift = 0, + .uartclk = VR1000_BAUDBASE, + }, + [1] = { + .mapbase = VR1000_SERIAL_MAPBASE(1), + .irq = IRQ_VR1000_SERIAL + 1, + .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, + .iotype = UPIO_MEM, + .regshift = 0, + .uartclk = VR1000_BAUDBASE, + }, + [2] = { + .mapbase = VR1000_SERIAL_MAPBASE(2), + .irq = IRQ_VR1000_SERIAL + 2, + .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, + .iotype = UPIO_MEM, + .regshift = 0, + .uartclk = VR1000_BAUDBASE, + }, + [3] = { + .mapbase = VR1000_SERIAL_MAPBASE(3), + .irq = IRQ_VR1000_SERIAL + 3, + .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, + .iotype = UPIO_MEM, + .regshift = 0, + .uartclk = VR1000_BAUDBASE, + }, + { }, +}; + +static struct platform_device serial_device = { + .name = "serial8250", + .id = 0, + .dev = { + .platform_data = serial_platform_data, + }, +}; + +/* MTD NOR Flash */ + +static struct resource vr1000_nor_resource[] = { + [0] = { + .start = S3C2410_CS1 + 0x4000000, + .end = S3C2410_CS1 + 0x4000000 + SZ_16M - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device vr1000_nor = { + .name = "bast-nor", + .id = -1, + .num_resources = ARRAY_SIZE(vr1000_nor_resource), + .resource = vr1000_nor_resource, +}; + + static struct platform_device *vr1000_devices[] __initdata = { &s3c_device_usb, &s3c_device_lcd, &s3c_device_wdt, &s3c_device_i2c, &s3c_device_iis, + &serial_device, + &vr1000_nor, }; static struct clk *vr1000_clocks[] = { @@ -187,6 +272,11 @@ static struct s3c24xx_board vr1000_board __initdata = { .clocks_count = ARRAY_SIZE(vr1000_clocks), }; +static void vr1000_power_off(void) +{ + s3c2410_gpio_cfgpin(S3C2410_GPB9, S3C2410_GPB9_OUTP); + s3c2410_gpio_setpin(S3C2410_GPB9, 1); +} void __init vr1000_map_io(void) { @@ -203,22 +293,25 @@ void __init vr1000_map_io(void) s3c24xx_uclk.parent = &s3c24xx_clkout1; + pm_power_off = vr1000_power_off; + s3c24xx_init_io(vr1000_iodesc, ARRAY_SIZE(vr1000_iodesc)); - s3c2410_init_uarts(vr1000_uartcfgs, ARRAY_SIZE(vr1000_uartcfgs)); + s3c24xx_init_clocks(0); + s3c24xx_init_uarts(vr1000_uartcfgs, ARRAY_SIZE(vr1000_uartcfgs)); s3c24xx_set_board(&vr1000_board); usb_simtec_init(); } void __init vr1000_init_irq(void) { - s3c2410_init_irq(); + s3c24xx_init_irq(); } MACHINE_START(VR1000, "Thorcom-VR1000") MAINTAINER("Ben Dooks ") - BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART) + BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, (u32)S3C24XX_VA_UART) BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100) MAPIO(vr1000_map_io) INITIRQ(vr1000_init_irq) - .timer = &s3c2410_timer, + .timer = &s3c24xx_timer, MACHINE_END diff --git a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c index 66a34913c..ff2f25409 100644 --- a/arch/arm/mach-s3c2410/s3c2410.c +++ b/arch/arm/mach-s3c2410/s3c2410.c @@ -1,6 +1,6 @@ /* linux/arch/arm/mach-s3c2410/s3c2410.c * - * Copyright (c) 2003,2004 Simtec Electronics + * Copyright (c) 2003-2005 Simtec Electronics * Ben Dooks * * http://www.simtec.co.uk/products/EB2410ITX/ @@ -17,6 +17,7 @@ * 21-Aug-2004 BJD Added new struct s3c2410_board handler * 28-Sep-2004 BJD Updates for new serial port bits * 04-Nov-2004 BJD Updated UART configuration process + * 10-Jan-2005 BJD Removed s3c2410_clock_tick_rate */ #include @@ -42,8 +43,6 @@ #include "cpu.h" #include "clock.h" -int s3c2410_clock_tick_rate = 12*1000*1000; /* current timers at 12MHz */ - /* Initial IO mappings */ static struct map_desc s3c2410_iodesc[] __initdata = { @@ -152,44 +151,45 @@ void __init s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no) * * register the standard cpu IO areas, and any passed in from the * machine specific initialisation. - * - * this function also sets the initial clock frequencies from the - * settings passed in */ void __init s3c2410_map_io(struct map_desc *mach_desc, int mach_size) { - unsigned long tmp; - /* register our io-tables */ iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc)); iotable_init(mach_desc, mach_size); +} + +void __init s3c2410_init_clocks(int xtal) +{ + unsigned long tmp; + unsigned long fclk; + unsigned long hclk; + unsigned long pclk; /* now we've got our machine bits initialised, work out what * clocks we've got */ - s3c24xx_fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), - s3c24xx_xtal); + fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal); tmp = __raw_readl(S3C2410_CLKDIVN); /* work out clock scalings */ - s3c24xx_hclk = s3c24xx_fclk / ((tmp & S3C2410_CLKDIVN_HDIVN) ? 2 : 1); - s3c24xx_pclk = s3c24xx_hclk / ((tmp & S3C2410_CLKDIVN_PDIVN) ? 2 : 1); + hclk = fclk / ((tmp & S3C2410_CLKDIVN_HDIVN) ? 2 : 1); + pclk = hclk / ((tmp & S3C2410_CLKDIVN_PDIVN) ? 2 : 1); /* print brieft summary of clocks, etc */ printk("S3C2410: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n", - print_mhz(s3c24xx_fclk), print_mhz(s3c24xx_hclk), - print_mhz(s3c24xx_pclk)); + print_mhz(fclk), print_mhz(hclk), print_mhz(pclk)); /* initialise the clocks here, to allow other things like the * console to use them */ - s3c2410_init_clocks(); + s3c24xx_setup_clocks(xtal, fclk, hclk, pclk); } int __init s3c2410_init(void) diff --git a/arch/arm/mach-s3c2410/s3c2410.h b/arch/arm/mach-s3c2410/s3c2410.h index 93395637d..4d5312a48 100644 --- a/arch/arm/mach-s3c2410/s3c2410.h +++ b/arch/arm/mach-s3c2410/s3c2410.h @@ -1,7 +1,7 @@ /* arch/arm/mach-s3c2410/s3c2410.h * * Copyright (c) 2004 Simtec Electronics - * Ben Dooks + * Ben Dooks * * Header file for s3c2410 machine directory * @@ -14,17 +14,24 @@ * 20-Aug-2004 BJD Added s3c2410_board struct * 04-Sep-2004 BJD Added s3c2410_init_uarts() call * 17-Oct-2004 BJD Moved board out to cpu + * 04-Jan-2005 BJD Changed uart init + * 10-Jan-2005 BJD Removed timer to cpu.h, moved 2410 specific bits here + * 14-Jan-2005 BJD Added s3c2410_init_clocks call */ -struct s3c2410_uartcfg; +#ifdef CONFIG_CPU_S3C2410 -extern void s3c2410_map_io(struct map_desc *, int count); +extern int s3c2410_init(void); -extern void s3c2410_init_uarts(struct s3c2410_uartcfg *, int no); +extern void s3c2410_map_io(struct map_desc *mach_desc, int size); -extern void s3c2410_init_irq(void); +extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no); -struct sys_timer; -extern struct sys_timer s3c2410_timer; +extern void s3c2410_init_clocks(int xtal); -extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no); +#else +#define s3c2410_init_clocks NULL +#define s3c2410_init_uarts NULL +#define s3c2410_map_io NULL +#define s3c2410_init NULL +#endif diff --git a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig index aa7d1c792..6923316b3 100644 --- a/arch/arm/mach-sa1100/Kconfig +++ b/arch/arm/mach-sa1100/Kconfig @@ -11,6 +11,7 @@ config SA1100_ASSABET config ASSABET_NEPONSET bool "Include support for Neponset" depends on SA1100_ASSABET + select SA1111 help Say Y here if you are using the Intel(R) StrongARM(R) SA-1110 Microprocessor Development Board (Assabet) with the SA-1111 @@ -44,7 +45,9 @@ endchoice config SA1100_COLLIE bool "Sharp Zaurus SL5500" - depends on ARCH_SA1100 + select SHARP_LOCOMO + select SHARP_SCOOP + select SHARP_PARAM help Say Y here to support the Sharp Zaurus SL5500 PDAs. @@ -85,12 +88,14 @@ config SA1100_H3XXX config SA1100_BADGE4 bool "HP Labs BadgePAD 4" + select SA1111 help Say Y here if you want to build a kernel for the HP Laboratories BadgePAD 4. config SA1100_JORNADA720 bool "HP Jornada 720" + select SA1111 help Say Y here if you want to build a kernel for the HP Jornada 720 handheld computer. See @@ -145,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/assabet.c b/arch/arm/mach-sa1100/assabet.c index a3003b867..bedf88faf 100644 --- a/arch/arm/mach-sa1100/assabet.c +++ b/arch/arm/mach-sa1100/assabet.c @@ -259,9 +259,11 @@ static void __init map_sa1100_gpio_regs( void ) unsigned long phys = __PREG(GPLR) & PMD_MASK; unsigned long virt = io_p2v(phys); int prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_DOMAIN(DOMAIN_IO); - pmd_t pmd; - pmd_val(pmd) = phys | prot; - set_pmd(pmd_offset(pgd_offset_k(virt), virt), pmd); + pmd_t *pmd; + + pmd = pmd_offset(pgd_offset_k(virt), virt); + *pmd = __pmd(phys | prot); + flush_pmd_entry(pmd); } /* diff --git a/arch/arm/mach-sa1100/badge4.c b/arch/arm/mach-sa1100/badge4.c index 0e66ec02c..6a60b497a 100644 --- a/arch/arm/mach-sa1100/badge4.c +++ b/arch/arm/mach-sa1100/badge4.c @@ -57,7 +57,7 @@ static struct platform_device sa1111_device = { .name = "sa1111", .id = 0, .dev = { - .dma_mask = &sa1111_dmamask; + .dma_mask = &sa1111_dmamask, .coherent_dma_mask = 0xffffffff, }, .num_resources = ARRAY_SIZE(sa1111_resources), @@ -212,8 +212,7 @@ static int __init badge4_init(void) /* maybe turn on 5v0 from the start */ badge4_set_5V(BADGE4_5V_INITIALLY, five_v_on); - sa11x0_set_flash_data(badge4_flash_data, badge4_flash_resources, - ARRAY_SIZE(badge4_flash_resources); + sa11x0_set_flash_data(&badge4_flash_data, &badge4_flash_resource, 1); return 0; } diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c index 9788d3aef..84c865435 100644 --- a/arch/arm/mach-sa1100/h3600.c +++ b/arch/arm/mach-sa1100/h3600.c @@ -130,7 +130,7 @@ static int h3600_irda_set_power(struct device *dev, unsigned int state) return 0; } -static void h3600_irda_set_speed(struct device *dev, int speed) +static void h3600_irda_set_speed(struct device *dev, unsigned int speed) { if (speed < 4000000) { clr_h3600_egpio(IPAQ_EGPIO_IR_FSEL); diff --git a/arch/arm/mach-sa1100/shannon.c b/arch/arm/mach-sa1100/shannon.c index 66fe6fdf0..edddd559b 100644 --- a/arch/arm/mach-sa1100/shannon.c +++ b/arch/arm/mach-sa1100/shannon.c @@ -2,15 +2,17 @@ * linux/arch/arm/mach-sa1100/shannon.c */ +#include #include +#include #include #include #include #include #include +#include #include -#include #include #include @@ -52,7 +54,7 @@ static struct resource shannon_flash_resource = { static void __init shannon_init(void) { - sa11x0_set_flash_data(&shannon_flash_data, shannon_flash_resource, 1); + sa11x0_set_flash_data(&shannon_flash_data, &shannon_flash_resource, 1); } static void __init shannon_map_io(void) diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c index 81881e922..a9bc5d0db 100644 --- a/arch/arm/mach-shark/core.c +++ b/arch/arm/mach-shark/core.c @@ -93,8 +93,6 @@ static struct irqaction shark_timer_irq = { */ static void __init shark_timer_init(void) { - unsigned long flags; - outb(0x34, 0x43); /* binary, mode 0, LSB/MSB, Ch 0 */ outb(HZ_TIME & 0xff, 0x40); /* LSB of count */ outb(HZ_TIME >> 8, 0x40); diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 2e71ad683..302c2a7b9 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -543,7 +543,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; @@ -597,6 +597,14 @@ static int versatile_clcd_setup(struct clcd_fb *fb) return 0; } +static int versatile_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma) +{ + return dma_mmap_writecombine(&fb->dev->dev, vma, + fb->fb.screen_base, + fb->fb.fix.smem_start, + fb->fb.fix.smem_len); +} + static void versatile_clcd_remove(struct clcd_fb *fb) { dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len, @@ -610,6 +618,7 @@ static struct clcd_board clcd_plat_data = { .disable = versatile_clcd_disable, .enable = versatile_clcd_enable, .setup = versatile_clcd_setup, + .mmap = versatile_clcd_mmap, .remove = versatile_clcd_remove, }; diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 787daaa3a..3fefb43c6 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -82,9 +82,9 @@ config CPU_ARM920T # ARM922T config CPU_ARM922T - bool - depends on ARCH_CAMELOT || ARCH_LH7A40X - default y + bool "Support ARM922T processor" if ARCH_INTEGRATOR + depends on ARCH_CAMELOT || ARCH_LH7A40X || ARCH_INTEGRATOR + default y if ARCH_CAMELOT || ARCH_LH7A40X select CPU_32v4 select CPU_ABRT_EV4T select CPU_CACHE_V4WT @@ -101,9 +101,9 @@ config CPU_ARM922T # ARM925T config CPU_ARM925T - bool + bool "Support ARM925T processor" if ARCH_OMAP depends on ARCH_OMAP1510 - default y + default y if ARCH_OMAP1510 select CPU_32v4 select CPU_ABRT_EV4T select CPU_CACHE_V4WT @@ -121,8 +121,8 @@ config CPU_ARM925T # ARM926T config CPU_ARM926T bool "Support ARM926T processor" if ARCH_INTEGRATOR - depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP1610 || ARCH_OMAP5912 - default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB + depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX + default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX select CPU_32v5 select CPU_ABRT_EV5TJ select CPU_CACHE_VIVT @@ -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 @@ -392,8 +385,9 @@ config CPU_DCACHE_DISABLE config CPU_DCACHE_WRITETHROUGH bool "Force write through D-cache" depends on (CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020) && !CPU_DISABLE_DCACHE + default y if CPU_ARM925T help - Say Y here to use the data cache in writethough mode. Unless you + Say Y here to use the data cache in writethrough mode. Unless you specifically require this or are unsure, say N. config CPU_CACHE_ROUND_ROBIN @@ -408,3 +402,31 @@ config CPU_BPREDICT_DISABLE depends on CPU_ARM1020 help Say Y here to disable branch prediction. If unsure, say N. + +config TLS_REG_EMUL + bool + default y if SMP && (CPU_32v5 || CPU_32v4 || CPU_32v3) + help + 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 !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 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/consistent.c b/arch/arm/mm/consistent.c index 57b0be2ab..26356ce4d 100644 --- a/arch/arm/mm/consistent.c +++ b/arch/arm/mm/consistent.c @@ -1,7 +1,7 @@ /* * linux/arch/arm/mm/consistent.c * - * Copyright (C) 2000-2002 Russell King + * Copyright (C) 2000-2004 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 @@ -30,7 +30,7 @@ * This is the page table (2MB) covering uncached, DMA consistent allocations */ static pte_t *consistent_pte; -static spinlock_t consistent_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(consistent_lock); /* * VM region handling support. @@ -65,6 +65,7 @@ struct vm_region { struct list_head vm_list; unsigned long vm_start; unsigned long vm_end; + struct page *vm_pages; }; static struct vm_region consistent_head = { @@ -206,6 +207,8 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, int gfp, pte_t *pte = consistent_pte + CONSISTENT_OFFSET(c->vm_start); struct page *end = page + (1 << order); + c->vm_pages = page; + /* * Set the "dma handle" */ @@ -215,6 +218,9 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, int gfp, BUG_ON(!pte_none(*pte)); set_page_count(page, 1); + /* + * x86 does not mark the pages reserved... + */ SetPageReserved(page); set_pte(pte, mk_pte(page, prot)); page++; @@ -264,13 +270,60 @@ dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, int } EXPORT_SYMBOL(dma_alloc_writecombine); +static int dma_mmap(struct device *dev, struct vm_area_struct *vma, + void *cpu_addr, dma_addr_t dma_addr, size_t size) +{ + unsigned long flags, user_size, kern_size; + struct vm_region *c; + int ret = -ENXIO; + + user_size = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; + + spin_lock_irqsave(&consistent_lock, flags); + c = vm_region_find(&consistent_head, (unsigned long)cpu_addr); + spin_unlock_irqrestore(&consistent_lock, flags); + + if (c) { + unsigned long off = vma->vm_pgoff; + + kern_size = (c->vm_end - c->vm_start) >> PAGE_SHIFT; + + if (off < kern_size && + user_size <= (kern_size - off)) { + vma->vm_flags |= VM_RESERVED; + ret = remap_pfn_range(vma, vma->vm_start, + page_to_pfn(c->vm_pages) + off, + user_size << PAGE_SHIFT, + vma->vm_page_prot); + } + } + + return ret; +} + +int dma_mmap_coherent(struct device *dev, struct vm_area_struct *vma, + void *cpu_addr, dma_addr_t dma_addr, size_t size) +{ + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + return dma_mmap(dev, vma, cpu_addr, dma_addr, size); +} +EXPORT_SYMBOL(dma_mmap_coherent); + +int dma_mmap_writecombine(struct device *dev, struct vm_area_struct *vma, + void *cpu_addr, dma_addr_t dma_addr, size_t size) +{ + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + return dma_mmap(dev, vma, cpu_addr, dma_addr, size); +} +EXPORT_SYMBOL(dma_mmap_writecombine); + /* * free a page as defined by the above mapping. */ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t handle) { struct vm_region *c; - unsigned long flags; + unsigned long flags, addr; pte_t *ptep; size = PAGE_ALIGN(size); @@ -289,17 +342,23 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr } ptep = consistent_pte + CONSISTENT_OFFSET(c->vm_start); + addr = c->vm_start; do { - pte_t pte = ptep_get_and_clear(ptep); + pte_t pte = ptep_get_and_clear(&init_mm, addr, ptep); unsigned long pfn; ptep++; + addr += PAGE_SIZE; if (!pte_none(pte) && pte_present(pte)) { pfn = pte_pfn(pte); if (pfn_valid(pfn)) { struct page *page = pfn_to_page(pfn); + + /* + * x86 does not mark the pages reserved... + */ ClearPageReserved(page); __free_page(page); diff --git a/arch/arm/mm/copypage-v4mc.S b/arch/arm/mm/copypage-v4mc.S deleted file mode 100644 index 305af3dab..000000000 --- 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 -#include -#include - - .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-xscale.S b/arch/arm/mm/copypage-xscale.S deleted file mode 100644 index bb277316e..000000000 --- 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 -#include -#include - -/* - * 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/fault-armv.c b/arch/arm/mm/fault-armv.c index 5f0a79094..01967ddee 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c @@ -54,7 +54,7 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address) * fault (ie, is old), we can safely ignore any issues. */ if (pte_present(entry) && pte_val(entry) & shared_pte_mask) { - flush_cache_page(vma, address); + flush_cache_page(vma, address, pte_pfn(entry)); pte_val(entry) &= ~shared_pte_mask; set_pte(pte, entry); flush_tlb_page(vma, address); @@ -115,7 +115,7 @@ 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); + flush_cache_page(vma, addr, page_to_pfn(page)); } /* diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 51f3be19e..72a2b8cee 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -55,7 +56,7 @@ void show_mem(void) show_free_areas(); printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); - for (node = 0; node < numnodes; node++) { + for_each_online_node(node) { struct page *page, *end; page = NODE_MEM_MAP(node); @@ -178,18 +179,14 @@ find_memend_and_nodes(struct meminfo *mi, struct node_info *np) node = mi->bank[i].node; - if (node >= numnodes) { - numnodes = node + 1; - - /* - * Make sure we haven't exceeded the maximum number - * of nodes that we have in this configuration. If - * we have, we're in trouble. (maybe we ought to - * limit, instead of bugging?) - */ - if (numnodes > MAX_NUMNODES) - BUG(); - } + /* + * Make sure we haven't exceeded the maximum number of nodes + * that we have in this configuration. If we have, we're in + * trouble. (maybe we ought to limit, instead of bugging?) + */ + if (node >= MAX_NUMNODES) + BUG(); + node_set_online(node); /* * Get the start and end pfns for this bank @@ -211,7 +208,7 @@ find_memend_and_nodes(struct meminfo *mi, struct node_info *np) * Calculate the number of pages we require to * store the bootmem bitmaps. */ - for (i = 0; i < numnodes; i++) { + for_each_online_node(i) { if (np[i].end == 0) continue; @@ -226,6 +223,9 @@ find_memend_and_nodes(struct meminfo *mi, struct node_info *np) * This doesn't seem to be used by the Linux memory * manager any more. If we can get rid of it, we * also get rid of some of the stuff above as well. + * + * Note: max_low_pfn and max_pfn reflect the number + * of _pages_ in the system, not the maximum PFN. */ max_low_pfn = memend_pfn - O_PFN_DOWN(PHYS_OFFSET); max_pfn = memend_pfn - O_PFN_DOWN(PHYS_OFFSET); @@ -380,13 +380,13 @@ static void __init bootmem_init(struct meminfo *mi) * (we could also do with rolling bootmem_init and paging_init * into one generic "memory_init" type function). */ - np += numnodes - 1; - for (node = numnodes - 1; node >= 0; node--, np--) { + np += num_online_nodes() - 1; + for (node = num_online_nodes() - 1; node >= 0; node--, np--) { /* * If there are no pages in this node, ignore it. * Note that node 0 must always have some pages. */ - if (np->end == 0) { + if (np->end == 0 || !node_online(node)) { if (node == 0) BUG(); continue; @@ -449,7 +449,7 @@ void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc) /* * initialise the zones within each node */ - for (node = 0; node < numnodes; node++) { + for_each_online_node(node) { unsigned long zone_size[MAX_NR_ZONES]; unsigned long zhole_size[MAX_NR_ZONES]; struct bootmem_data *bdata; @@ -504,10 +504,6 @@ void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc) bdata->node_boot_start >> PAGE_SHIFT, zhole_size); } -#ifndef CONFIG_DISCONTIGMEM - mem_map = contig_page_data.node_mem_map; -#endif - /* * finish off the bad pages once * the mem_map is initialised @@ -558,7 +554,7 @@ void __init mem_init(void) create_memmap_holes(&meminfo); /* this will put all unused low memory onto the freelists */ - for (node = 0; node < numnodes; node++) { + for_each_online_node(node) { pg_data_t *pgdat = NODE_DATA(node); if (pgdat->node_spanned_pages != 0) diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index 49a57b9f0..00bb8fd37 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -148,7 +148,7 @@ __ioremap(unsigned long phys_addr, size_t size, unsigned long flags, */ offset = phys_addr & ~PAGE_MASK; phys_addr &= PAGE_MASK; - size = PAGE_ALIGN(last_addr) - phys_addr; + size = PAGE_ALIGN(last_addr + 1) - phys_addr; /* * Ok, go for it.. diff --git a/arch/arm/mm/minicache.c b/arch/arm/mm/minicache.c deleted file mode 100644 index dedf2ab01..000000000 --- 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 -#include - -#include -#include -#include - -/* - * 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 9150033e8..2c2b93d77 100644 --- a/arch/arm/mm/mm-armv.c +++ b/arch/arm/mm/mm-armv.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -36,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; @@ -141,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 */ @@ -219,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)) { @@ -239,18 +252,36 @@ free: /* * Create a SECTION PGD between VIRT and PHYS in domain - * DOMAIN with protection PROT + * DOMAIN with protection PROT. This operates on half- + * pgdir entry increments. */ 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++; - set_pmd(pmdp, __pmd(phys | prot)); + *pmdp = __pmd(phys | prot); + flush_pmd_entry(pmdp); +} + +/* + * Create a SUPER SECTION PGD between VIRT and PHYS with protection PROT + */ +static inline void +alloc_init_supersection(unsigned long virt, unsigned long phys, int prot) +{ + int i; + + for (i = 0; i < 16; i += 1) { + alloc_init_section(virt, phys & SUPERSECTION_MASK, + prot | PMD_SECT_SUPER); + + virt += (PGDIR_SIZE / 2); + phys += (PGDIR_SIZE / 2); + } } /* @@ -263,11 +294,9 @@ alloc_init_section(unsigned long virt, unsigned long phys, int prot) static inline void alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pgprot_t prot) { - pmd_t *pmdp; + pmd_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 * @@ -290,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 { @@ -336,6 +365,15 @@ static struct mem_types mem_types[] __initdata = { [MT_ROM] = { .prot_sect = PMD_TYPE_SECT, .domain = DOMAIN_KERNEL, + }, + [MT_IXP2000_DEVICE] = { /* IXP2400 requires XCB=101 for on-chip I/O */ + .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | + L_PTE_WRITE, + .prot_l1 = PMD_TYPE_TABLE, + .prot_sect = PMD_TYPE_SECT | PMD_SECT_UNCACHED | + PMD_SECT_AP_WRITE | PMD_SECT_BUFFERABLE | + PMD_SECT_TEX(1), + .domain = DOMAIN_IO, } }; @@ -382,9 +420,10 @@ static void __init build_mem_type_table(void) mem_types[MT_MEMORY].prot_sect &= ~PMD_BIT4; mem_types[MT_ROM].prot_sect &= ~PMD_BIT4; /* - * Mark cache clean areas read only from SVC mode - * and no access from userspace. + * Mark cache clean areas and XIP ROM read only + * from SVC mode and no access from userspace. */ + mem_types[MT_ROM].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; } @@ -434,7 +473,8 @@ static void __init build_mem_type_table(void) * Create the page directory entries and any necessary * page tables for the mapping specified by `md'. We * are able to cope here with varying sizes and address - * offsets, and we take full advantage of sections. + * offsets, and we take full advantage of sections and + * supersections. */ static void __init create_mapping(struct map_desc *md) { @@ -481,6 +521,33 @@ static void __init create_mapping(struct map_desc *md) length -= PAGE_SIZE; } + /* N.B. ARMv6 supersections are only defined to work with domain 0. + * Since domain assignments can in fact be arbitrary, the + * 'domain == 0' check below is required to insure that ARMv6 + * supersections are only allocated for domain 0 regardless + * of the actual domain assignments in use. + */ + if (cpu_architecture() >= CPU_ARCH_ARMv6 && domain == 0) { + /* Align to supersection boundary */ + while ((virt & ~SUPERSECTION_MASK || (virt + off) & + ~SUPERSECTION_MASK) && length >= (PGDIR_SIZE / 2)) { + alloc_init_section(virt, virt + off, prot_sect); + + virt += (PGDIR_SIZE / 2); + length -= (PGDIR_SIZE / 2); + } + + while (length >= SUPERSECTION_SIZE) { + alloc_init_supersection(virt, virt + off, prot_sect); + + virt += SUPERSECTION_SIZE; + length -= SUPERSECTION_SIZE; + } + } + + /* + * A section mapping covers half a "pgdir" entry. + */ while (length >= (PGDIR_SIZE / 2)) { alloc_init_section(virt, virt + off, prot_sect); @@ -520,8 +587,10 @@ 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); - set_pmd(pmd, __pmd(pmdval)); + pmd = pmd_off(pgd, i << PGDIR_SHIFT); + pmd[0] = __pmd(pmdval); + pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1))); + flush_pmd_entry(pmd); } } @@ -615,6 +684,8 @@ void __init memtable_init(struct meminfo *mi) flush_cache_all(); flush_tlb_all(); + + top_pmd = pmd_off_k(0xffff0000); } /* @@ -696,6 +767,6 @@ void __init create_memmap_holes(struct meminfo *mi) { int node; - for (node = 0; node < numnodes; node++) + for_each_online_node(node) free_unused_memmap_node(node, mi); } diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S index 5d444e49b..d447cd5f3 100644 --- a/arch/arm/mm/proc-sa1100.S +++ b/arch/arm/mm/proc-sa1100.S @@ -209,21 +209,31 @@ ENTRY(cpu_sa1100_set_pte) .type __sa1100_setup, #function __sa1100_setup: - mov r10, #0 - mcr p15, 0, r10, c7, c7 @ invalidate I,D caches on v4 - mcr p15, 0, r10, c7, c10, 4 @ drain write buffer on v4 - mcr p15, 0, r10, c8, c7 @ invalidate I,D TLBs on v4 - mov r0, #0x1f @ Domains 0, 1 = client - mcr p15, 0, r0, c3, c0 @ load domain access register - mcr p15, 0, r4, c2, c0 @ load page table pointer + mov r0, #0 + mcr p15, 0, r0, c7, c7 @ invalidate I,D caches on v4 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4 + mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4 mrc p15, 0, r0, c1, c0 @ get control register v4 - bic r0, r0, #0x0e00 @ ..VI ZFRS BLDP WCAM - bic r0, r0, #0x0002 @ .... 000. .... ..0. - orr r0, r0, #0x003d - orr r0, r0, #0x3100 @ ..11 ...1 ..11 11.1 + ldr r5, sa1100_cr1_clear + bic r0, r0, r5 + ldr r5, sa1100_cr1_set + orr r0, r0, r5 mov pc, lr .size __sa1100_setup, . - __sa1100_setup + /* + * R + * .RVI ZFRS BLDP WCAM + * ..11 0001 ..11 1101 + * + */ + .type sa1100_cr1_clear, #object + .type sa1100_cr1_set, #object +sa1100_cr1_clear: + .word 0x3f3f +sa1100_cr1_set: + .word 0x313d + __INITDATA /* @@ -276,7 +286,11 @@ cpu_sa1110_name: __sa1100_proc_info: .long 0x4401a110 .long 0xfffffff0 - .long 0x00000c0e + .long PMD_TYPE_SECT | \ + PMD_SECT_BUFFERABLE | \ + PMD_SECT_CACHEABLE | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __sa1100_setup .long cpu_arch_name .long cpu_elf_name @@ -292,7 +306,11 @@ __sa1100_proc_info: __sa1110_proc_info: .long 0x6901b110 .long 0xfffffff0 - .long 0x00000c0e + .long PMD_TYPE_SECT | \ + PMD_SECT_BUFFERABLE | \ + PMD_SECT_CACHEABLE | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __sa1100_setup .long cpu_arch_name .long cpu_elf_name diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S index 495167ca2..2d977b4ee 100644 --- a/arch/arm/mm/proc-xscale.S +++ b/arch/arm/mm/proc-xscale.S @@ -594,14 +594,9 @@ ENTRY(cpu_xscale_set_pte) .type __xscale_setup, #function __xscale_setup: - mov r0, #PSR_F_BIT|PSR_I_BIT|SVC_MODE - msr cpsr_c, r0 mcr p15, 0, ip, c7, c7, 0 @ invalidate I, D caches & BTB mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer mcr p15, 0, ip, c8, c7, 0 @ invalidate I, D TLBs - mcr p15, 0, r4, c2, c0, 0 @ load page table pointer - mov r0, #0x1f @ Domains 0, 1 = client - mcr p15, 0, r0, c3, c0, 0 @ load domain access register #ifdef CONFIG_IWMMXT mov r0, #0 @ initially disallow access to CP0/CP1 #else @@ -611,13 +606,26 @@ __xscale_setup: orr r0, r0, #1 << 13 @ Its undefined whether this mcr p15, 0, r0, c15, c1, 0 @ affects USR or SVC modes mrc p15, 0, r0, c1, c0, 0 @ get control register - bic r0, r0, #0x0200 @ .... ..R. .... .... - bic r0, r0, #0x0002 @ .... .... .... ..A. - orr r0, r0, #0x0005 @ .... .... .... .C.M - orr r0, r0, #0x3900 @ ..VI Z..S .... .... + ldr r5, xscale_cr1_clear + bic r0, r0, r5 + ldr r5, xscale_cr1_set + orr r0, r0, r5 mov pc, lr .size __xscale_setup, . - __xscale_setup + /* + * R + * .RVI ZFRS BLDP WCAM + * ..11 1.01 .... .101 + * + */ + .type xscale_cr1_clear, #object + .type xscale_cr1_set, #object +xscale_cr1_clear: + .word 0x3b07 +xscale_cr1_set: + .word 0x3905 + __INITDATA /* @@ -712,7 +720,11 @@ cpu_pxa270_name: __80200_proc_info: .long 0x69052000 .long 0xfffffff0 - .long 0x00000c0e + .long PMD_TYPE_SECT | \ + PMD_SECT_BUFFERABLE | \ + PMD_SECT_CACHEABLE | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __xscale_setup .long cpu_arch_name .long cpu_elf_name @@ -728,7 +740,11 @@ __80200_proc_info: __8032x_proc_info: .long 0x69052420 .long 0xfffff5e0 @ mask should accomodate IOP80219 also - .long 0x00000c0e + .long PMD_TYPE_SECT | \ + PMD_SECT_BUFFERABLE | \ + PMD_SECT_CACHEABLE | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __xscale_setup .long cpu_arch_name .long cpu_elf_name @@ -742,9 +758,13 @@ __8032x_proc_info: .type __8033x_proc_info,#object __8033x_proc_info: - .long 0x69054090 - .long 0xffffffb0 - .long 0x00000c0e + .long 0x69054010 + .long 0xffffff30 + .long PMD_TYPE_SECT | \ + PMD_SECT_BUFFERABLE | \ + PMD_SECT_CACHEABLE | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __xscale_setup .long cpu_arch_name .long cpu_elf_name @@ -760,7 +780,11 @@ __8033x_proc_info: __pxa250_proc_info: .long 0x69052100 .long 0xfffff7f0 - .long 0x00000c0e + .long PMD_TYPE_SECT | \ + PMD_SECT_BUFFERABLE | \ + PMD_SECT_CACHEABLE | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __xscale_setup .long cpu_arch_name .long cpu_elf_name @@ -776,7 +800,11 @@ __pxa250_proc_info: __pxa210_proc_info: .long 0x69052120 .long 0xfffff3f0 - .long 0x00000c0e + .long PMD_TYPE_SECT | \ + PMD_SECT_BUFFERABLE | \ + PMD_SECT_CACHEABLE | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __xscale_setup .long cpu_arch_name .long cpu_elf_name @@ -792,7 +820,11 @@ __pxa210_proc_info: __ixp2400_proc_info: .long 0x69054190 .long 0xfffffff0 - .long 0x00000c0e + .long PMD_TYPE_SECT | \ + PMD_SECT_BUFFERABLE | \ + PMD_SECT_CACHEABLE | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __xscale_setup .long cpu_arch_name .long cpu_elf_name @@ -808,7 +840,11 @@ __ixp2400_proc_info: __ixp2800_proc_info: .long 0x690541a0 .long 0xfffffff0 - .long 0x00000c0e + .long PMD_TYPE_SECT | \ + PMD_SECT_BUFFERABLE | \ + PMD_SECT_CACHEABLE | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __xscale_setup .long cpu_arch_name .long cpu_elf_name @@ -824,7 +860,11 @@ __ixp2800_proc_info: __ixp42x_proc_info: .long 0x690541c0 .long 0xffffffc0 - .long 0x00000c0e + .long PMD_TYPE_SECT | \ + PMD_SECT_BUFFERABLE | \ + PMD_SECT_CACHEABLE | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __xscale_setup .long cpu_arch_name .long cpu_elf_name @@ -856,7 +896,11 @@ __ixp46x_proc_info: __pxa255_proc_info: .long 0x69052d00 .long 0xfffffff0 - .long 0x00000c0e + .long PMD_TYPE_SECT | \ + PMD_SECT_BUFFERABLE | \ + PMD_SECT_CACHEABLE | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __xscale_setup .long cpu_arch_name .long cpu_elf_name @@ -872,7 +916,11 @@ __pxa255_proc_info: __pxa270_proc_info: .long 0x69054110 .long 0xfffffff0 - .long 0x00000c0e + .long PMD_TYPE_SECT | \ + PMD_SECT_BUFFERABLE | \ + PMD_SECT_CACHEABLE | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __xscale_setup .long cpu_arch_name .long cpu_elf_name diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index 82bdef299..30c1dfbb0 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -6,7 +6,7 @@ # To add an entry into this database, please see Documentation/arm/README, # or contact rmk@arm.linux.org.uk # -# Last update: Sun Nov 7 13:20:41 2004 +# Last update: Thu Mar 24 14:34:50 2005 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -226,7 +226,7 @@ dnp1110 SA1100_DNP1110 DNP1110 214 pnp1110 SA1100_PNP1110 PNP1110 215 csb226 ARCH_CSB226 CSB226 216 arnold SA1100_ARNOLD ARNOLD 217 -psiboard SA1100_PSIBOARD PSIBOARD 218 +voiceblue MACH_VOICEBLUE VOICEBLUE 218 jz8028 ARCH_JZ8028 JZ8028 219 h5400 ARCH_H5400 H5400 220 forte SA1100_FORTE FORTE 221 @@ -250,8 +250,8 @@ pxa_eagle250 ARCH_PXA_EAGLE250 PXA_EAGLE250 238 pdb ARCH_PDB PDB 239 blue_2g SA1100_BLUE_2G BLUE_2G 240 bluearch SA1100_BLUEARCH BLUEARCH 241 -ixdp2400 ARCH_IXDB2400 IXDB2400 242 -ixdp2800 ARCH_IXDB2800 IXDB2800 243 +ixdp2400 ARCH_IXDP2400 IXDP2400 242 +ixdp2800 ARCH_IXDP2800 IXDP2800 243 explorer SA1100_EXPLORER EXPLORER 244 ixdp425 ARCH_IXDP425 IXDP425 245 chimp ARCH_CHIMP CHIMP 246 @@ -381,7 +381,7 @@ s5c7375 ARCH_S5C7375 S5C7375 369 spearhead ARCH_SPEARHEAD SPEARHEAD 370 pantera ARCH_PANTERA PANTERA 371 prayoglite ARCH_PRAYOGLITE PRAYOGLITE 372 -gumstik ARCH_GUMSTIK GUMSTIK 373 +gumstix ARCH_GUMSTIK GUMSTIK 373 rcube ARCH_RCUBE RCUBE 374 rea_olv ARCH_REA_OLV REA_OLV 375 pxa_iphone ARCH_PXA_IPHONE PXA_IPHONE 376 @@ -634,3 +634,93 @@ ecia MACH_ECIA ECIA 623 cm4008 MACH_CM4008 CM4008 624 p2001 MACH_P2001 P2001 625 twister MACH_TWISTER TWISTER 626 +mudshark MACH_MUDSHARK MUDSHARK 627 +hb2 MACH_HB2 HB2 628 +iq80332 MACH_IQ80332 IQ80332 629 +sendt MACH_SENDT SENDT 630 +mx2jazz MACH_MX2JAZZ MX2JAZZ 631 +multiio MACH_MULTIIO MULTIIO 632 +hrdisplay MACH_HRDISPLAY HRDISPLAY 633 +scma11bb MACH_SCMA11BB SCMA11BB 634 +trizeps3 MACH_TRIZEPS3 TRIZEPS3 635 +zefeerdza MACH_ZEFEERDZA ZEFEERDZA 636 +zefeerdzb MACH_ZEFEERDZB ZEFEERDZB 637 +zefeerdzg MACH_ZEFEERDZG ZEFEERDZG 638 +zefeerdzn MACH_ZEFEERDZN ZEFEERDZN 639 +zefeerdzq MACH_ZEFEERDZQ ZEFEERDZQ 640 +gtwx5715 MACH_GTWX5715 GTWX5715 641 +astro_jack MACH_ASTRO_JACK ASTRO_JACK 643 +tip03 MACH_TIP03 TIP03 644 +a9200ec MACH_A9200EC A9200EC 645 +pnx0105 MACH_PNX0105 PNX0105 646 +adcpoecpu MACH_ADCPOECPU ADCPOECPU 647 +csb637 MACH_CSB637 CSB637 648 +ml69q6203 MACH_ML69Q6203 ML69Q6203 649 +mb9200 MACH_MB9200 MB9200 650 +kulun MACH_KULUN KULUN 651 +snapper MACH_SNAPPER SNAPPER 652 +optima MACH_OPTIMA OPTIMA 653 +dlhsbc MACH_DLHSBC DLHSBC 654 +x30 MACH_X30 X30 655 +n30 MACH_N30 N30 656 +manga_ks8695 MACH_MANGA_KS8695 MANGA_KS8695 657 +ajax MACH_AJAX AJAX 658 +nec_mp900 MACH_NEC_MP900 NEC_MP900 659 +vvtk1000 MACH_VVTK1000 VVTK1000 661 +kafa MACH_KAFA KAFA 662 +vvtk3000 MACH_VVTK3000 VVTK3000 663 +pimx1 MACH_PIMX1 PIMX1 664 +ollie MACH_OLLIE OLLIE 665 +skymax MACH_SKYMAX SKYMAX 666 +jazz MACH_JAZZ JAZZ 667 +tel_t3 MACH_TEL_T3 TEL_T3 668 +aisino_fcr255 MACH_AISINO_FCR255 AISINO_FCR255 669 +btweb MACH_BTWEB BTWEB 670 +dbg_lh79520 MACH_DBG_LH79520 DBG_LH79520 671 +cm41xx MACH_CM41XX CM41XX 672 +ts72xx MACH_TS72XX TS72XX 673 +nggpxa MACH_NGGPXA NGGPXA 674 +csb535 MACH_CSB535 CSB535 675 +csb536 MACH_CSB536 CSB536 676 +pxa_trakpod MACH_PXA_TRAKPOD PXA_TRAKPOD 677 +praxis MACH_PRAXIS PRAXIS 678 +lh75411 MACH_LH75411 LH75411 679 +otom MACH_OTOM OTOM 680 +nexcoder_2440 MACH_NEXCODER_2440 NEXCODER_2440 681 +loox410 MACH_LOOX410 LOOX410 682 +westlake MACH_WESTLAKE WESTLAKE 683 +nsb MACH_NSB NSB 684 +esl_sarva_stn MACH_ESL_SARVA_STN ESL_SARVA_STN 685 +esl_sarva_tft MACH_ESL_SARVA_TFT ESL_SARVA_TFT 686 +esl_sarva_iad MACH_ESL_SARVA_IAD ESL_SARVA_IAD 687 +esl_sarva_acc MACH_ESL_SARVA_ACC ESL_SARVA_ACC 688 +typhoon MACH_TYPHOON TYPHOON 689 +cnav MACH_CNAV CNAV 690 +a730 MACH_A730 A730 691 +netstar MACH_NETSTAR NETSTAR 692 +supercon MACH_PHASEFALE_SUPERCON PHASEFALE_SUPERCON 693 +shiva1100 MACH_SHIVA1100 SHIVA1100 694 +etexsc MACH_ETEXSC ETEXSC 695 +ixdpg465 MACH_IXDPG465 IXDPG465 696 +a9m2410 MACH_A9M2410 A9M2410 697 +a9m2440 MACH_A9M2440 A9M2440 698 +a9m9750 MACH_A9M9750 A9M9750 699 +a9m9360 MACH_A9M9360 A9M9360 700 +unc90 MACH_UNC90 UNC90 701 +eco920 MACH_ECO920 ECO920 702 +satview MACH_SATVIEW SATVIEW 703 +roadrunner MACH_ROADRUNNER ROADRUNNER 704 +at91rm9200ek MACH_AT91RM9200EK AT91RM9200EK 705 +gp32 MACH_GP32 GP32 706 +gem MACH_GEM GEM 707 +i858 MACH_I858 I858 708 +hx2750 MACH_HX2750 HX2750 709 +zeusevb MACH_ZEUSEVB ZEUSEVB 710 +p700 MACH_P700 P700 711 +cpe MACH_CPE CPE 712 +spitz MACH_SPITZ SPITZ 713 +nimbra340 MACH_NIMBRA340 NIMBRA340 714 +lpc22xx MACH_LPC22XX LPC22XX 715 +omap_comet3 MACH_COMET3 COMET3 716 +omap_comet4 MACH_COMET4 COMET4 717 +csb625 MACH_CSB625 CSB625 718 diff --git a/arch/arm26/Kconfig b/arch/arm26/Kconfig index 500780d9d..841bb5aa5 100644 --- a/arch/arm26/Kconfig +++ b/arch/arm26/Kconfig @@ -45,6 +45,10 @@ config RWSEM_GENERIC_SPINLOCK config RWSEM_XCHGADD_ALGORITHM bool +config GENERIC_CALIBRATE_DELAY + bool + default y + config GENERIC_BUST_SPINLOCK bool @@ -85,6 +89,10 @@ config PAGESIZE_16 machine with 4MB of memory. endmenu +config ISA_DMA_API + bool + default y + menu "General setup" # Compressed boot loader in ROM. Yes, we really want to ask about @@ -223,4 +231,3 @@ source "security/Kconfig" source "crypto/Kconfig" source "lib/Kconfig" - diff --git a/arch/arm26/boot/compressed/ofw-shark.c b/arch/arm26/boot/compressed/ofw-shark.c deleted file mode 100644 index 2091e68d4..000000000 --- a/arch/arm26/boot/compressed/ofw-shark.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * linux/arch/arm/boot/compressed/ofw-shark.c - * - * by Alexander Schulz - * - * This file is used to get some basic information - * about the memory layout of the shark we are running - * on. Memory is usually divided in blocks a 8 MB. - * And bootargs are copied from OpenFirmware. - */ - - -#include -#include -#include -#include - - -asmlinkage void -create_params (unsigned long *buffer) -{ - /* Is there a better address? Also change in mach-shark/core.c */ - struct tag *tag = (struct tag *) 0x08003000; - int j,i,m,k,nr_banks,size; - unsigned char *c; - - /* Head of the taglist */ - tag->hdr.tag = ATAG_CORE; - tag->hdr.size = tag_size(tag_core); - tag->u.core.flags = FLAG_READONLY; - tag->u.core.pagesize = PAGE_SIZE; - tag->u.core.rootdev = 0; - - /* Build up one tagged block for each memory region */ - size=0; - nr_banks=(unsigned int) buffer[0]; - for (j=0;jhdr.tag = ATAG_MEM; - tag->hdr.size = tag_size(tag_mem32); - tag->u.mem.size = buffer[2*k+2]; - tag->u.mem.start = buffer[2*k+1]; - - size += buffer[2*k+2]; - - buffer[2*k+1]=0xffffffff; /* mark as copied */ - } - - /* The command line */ - tag = tag_next(tag); - tag->hdr.tag = ATAG_CMDLINE; - - c=(unsigned char *)(&buffer[34]); - j=0; - while (*c) tag->u.cmdline.cmdline[j++]=*c++; - - tag->u.cmdline.cmdline[j]=0; - tag->hdr.size = (j + 7 + sizeof(struct tag_header)) >> 2; - - /* Hardware revision */ - tag = tag_next(tag); - tag->hdr.tag = ATAG_REVISION; - tag->hdr.size = tag_size(tag_revision); - tag->u.revision.rev = ((unsigned char) buffer[33])-'0'; - - /* End of the taglist */ - tag = tag_next(tag); - tag->hdr.tag = 0; - tag->hdr.size = 0; -} - - -typedef int (*ofw_handle_t)(void *); - -/* Everything below is called with a wrong MMU setting. - * This means: no string constants, no initialization of - * arrays, no global variables! This is ugly but I didn't - * want to write this in assembler :-) - */ - -int -of_decode_int(const unsigned char *p) -{ - unsigned int i = *p++ << 8; - i = (i + *p++) << 8; - i = (i + *p++) << 8; - return (i + *p); -} - -int -OF_finddevice(ofw_handle_t openfirmware, char *name) -{ - unsigned int args[8]; - char service[12]; - - service[0]='f'; - service[1]='i'; - service[2]='n'; - service[3]='d'; - service[4]='d'; - service[5]='e'; - service[6]='v'; - service[7]='i'; - service[8]='c'; - service[9]='e'; - service[10]='\0'; - - args[0]=(unsigned int)service; - args[1]=1; - args[2]=1; - args[3]=(unsigned int)name; - - if (openfirmware(args) == -1) - return -1; - return args[4]; -} - -int -OF_getproplen(ofw_handle_t openfirmware, int handle, char *prop) -{ - unsigned int args[8]; - char service[12]; - - service[0]='g'; - service[1]='e'; - service[2]='t'; - service[3]='p'; - service[4]='r'; - service[5]='o'; - service[6]='p'; - service[7]='l'; - service[8]='e'; - service[9]='n'; - service[10]='\0'; - - args[0] = (unsigned int)service; - args[1] = 2; - args[2] = 1; - args[3] = (unsigned int)handle; - args[4] = (unsigned int)prop; - - if (openfirmware(args) == -1) - return -1; - return args[5]; -} - -int -OF_getprop(ofw_handle_t openfirmware, int handle, char *prop, void *buf, unsigned int buflen) -{ - unsigned int args[8]; - char service[8]; - - service[0]='g'; - service[1]='e'; - service[2]='t'; - service[3]='p'; - service[4]='r'; - service[5]='o'; - service[6]='p'; - service[7]='\0'; - - args[0] = (unsigned int)service; - args[1] = 4; - args[2] = 1; - args[3] = (unsigned int)handle; - args[4] = (unsigned int)prop; - args[5] = (unsigned int)buf; - args[6] = buflen; - - if (openfirmware(args) == -1) - return -1; - return args[7]; -} - -asmlinkage void ofw_init(ofw_handle_t o, int *nomr, int *pointer) -{ - int phandle,i,mem_len,buffer[32]; - char temp[15]; - - temp[0]='/'; - temp[1]='m'; - temp[2]='e'; - temp[3]='m'; - temp[4]='o'; - temp[5]='r'; - temp[6]='y'; - temp[7]='\0'; - - phandle=OF_finddevice(o,temp); - - temp[0]='r'; - temp[1]='e'; - temp[2]='g'; - temp[3]='\0'; - - mem_len = OF_getproplen(o,phandle, temp); - OF_getprop(o,phandle, temp, buffer, mem_len); - *nomr=mem_len >> 3; - - for (i=0; i<=mem_len/4; i++) pointer[i]=of_decode_int((const unsigned char *)&buffer[i]); - - temp[0]='/'; - temp[1]='c'; - temp[2]='h'; - temp[3]='o'; - temp[4]='s'; - temp[5]='e'; - temp[6]='n'; - temp[7]='\0'; - - phandle=OF_finddevice(o,temp); - - temp[0]='b'; - temp[1]='o'; - temp[2]='o'; - temp[3]='t'; - temp[4]='a'; - temp[5]='r'; - temp[6]='g'; - temp[7]='s'; - temp[8]='\0'; - - mem_len = OF_getproplen(o,phandle, temp); - OF_getprop(o,phandle, temp, buffer, mem_len); - if (mem_len > 128) mem_len=128; - for (i=0; i<=mem_len/4; i++) pointer[i+33]=buffer[i]; - pointer[i+33]=0; - - temp[0]='/'; - temp[1]='\0'; - phandle=OF_finddevice(o,temp); - temp[0]='b'; - temp[1]='a'; - temp[2]='n'; - temp[3]='n'; - temp[4]='e'; - temp[5]='r'; - temp[6]='-'; - temp[7]='n'; - temp[8]='a'; - temp[9]='m'; - temp[10]='e'; - temp[11]='\0'; - mem_len = OF_getproplen(o,phandle, temp); - OF_getprop(o,phandle, temp, buffer, mem_len); - (unsigned char) pointer[32] = ((unsigned char *) buffer)[mem_len-2]; -} diff --git a/arch/arm26/kernel/calls.S b/arch/arm26/kernel/calls.S index e3d276827..3e8672a31 100644 --- a/arch/arm26/kernel/calls.S +++ b/arch/arm26/kernel/calls.S @@ -257,6 +257,11 @@ __syscall_start: .long sys_lremovexattr .long sys_fremovexattr .long sys_tkill + + .rept 313 - (. - __syscall_start) / 4 + .long sys_ni_syscall + .endr + .long sys_vserver /* 313 */ __syscall_end: .rept NR_syscalls - (__syscall_end - __syscall_start) / 4 diff --git a/arch/arm26/kernel/init_task.c b/arch/arm26/kernel/init_task.c index 5b510232a..4191565b8 100644 --- a/arch/arm26/kernel/init_task.c +++ b/arch/arm26/kernel/init_task.c @@ -1,5 +1,5 @@ /* - * linux/arch/arm/kernel/init_task.c + * linux/arch/arm26/kernel/init_task.c * * Copyright (C) 2003 Ian Molton * @@ -29,7 +29,9 @@ EXPORT_SYMBOL(init_mm); * We need to make sure that this is 8192-byte aligned due to the * way process stacks are handled. This is done by making sure * the linker maps this in the .text segment right after head.S, - * and making head.S ensure the proper alignment. + * and making the linker scripts ensure the proper alignment. + * + * FIXME - should this be 32K alignment on arm26? * * The things we do for performance... */ diff --git a/arch/arm26/kernel/irq.c b/arch/arm26/kernel/irq.c index be2ebeaa8..f3cc1036e 100644 --- a/arch/arm26/kernel/irq.c +++ b/arch/arm26/kernel/irq.c @@ -50,7 +50,7 @@ void __init arc_init_irq(void); #define MAX_IRQ_CNT 100000 static volatile unsigned long irq_err_count; -static spinlock_t irq_controller_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(irq_controller_lock); struct irqdesc irq_desc[NR_IRQS]; diff --git a/arch/arm26/kernel/process.c b/arch/arm26/kernel/process.c index 5b4efd620..46aea6ac1 100644 --- a/arch/arm26/kernel/process.c +++ b/arch/arm26/kernel/process.c @@ -67,42 +67,22 @@ static int __init hlt_setup(char *__unused) __setup("nohlt", nohlt_setup); __setup("hlt", hlt_setup); -/* - * The following aren't currently used. - */ -void (*pm_idle)(void); -void (*pm_power_off)(void); - /* * This is our default idle handler. We need to disable * interrupts here to ensure we don't miss a wakeup call. */ -void default_idle(void) -{ - local_irq_disable(); - if (!need_resched() && !hlt_counter) - local_irq_enable(); -} - -/* - * The idle thread. We try to conserve power, while trying to keep - * overall latency low. The architecture specific idle is passed - * a value to indicate the level of "idleness" of the system. - */ void cpu_idle(void) { /* endless idle loop with no priority at all */ preempt_disable(); while (1) { - void (*idle)(void) = pm_idle; - if (!idle) - idle = default_idle; - leds_event(led_idle_start); - while (!need_resched()) - idle(); - leds_event(led_idle_end); - schedule(); + while (!need_resched()) { + local_irq_disable(); + if (!need_resched() && !hlt_counter) + local_irq_enable(); + } } + schedule(); } static char reboot_mode = 'h'; @@ -115,20 +95,15 @@ int __init reboot_setup(char *str) __setup("reboot=", reboot_setup); +/* ARM26 cant do these but we still need to define them. */ void machine_halt(void) { - leds_event(led_halted); } - -EXPORT_SYMBOL(machine_halt); - void machine_power_off(void) { - leds_event(led_halted); - if (pm_power_off) - pm_power_off(); } +EXPORT_SYMBOL(machine_halt); EXPORT_SYMBOL(machine_power_off); void machine_restart(char * __unused) @@ -296,7 +271,7 @@ void flush_thread(void) memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); memset(&thread->fpstate, 0, sizeof(union fp_state)); - current->used_math = 0; + clear_used_math(); } void release_thread(struct task_struct *dead_task) @@ -306,7 +281,7 @@ void release_thread(struct task_struct *dead_task) asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); int -copy_thread(int nr, unsigned long clone_flags, unsigned long esp, +copy_thread(int nr, unsigned long clone_flags, unsigned long stack_start, unsigned long unused, struct task_struct *p, struct pt_regs *regs) { struct thread_info *thread = p->thread_info; @@ -315,7 +290,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long esp, childregs = __get_user_regs(thread); *childregs = *regs; childregs->ARM_r0 = 0; - childregs->ARM_sp = esp; + childregs->ARM_sp = stack_start; memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save)); thread->cpu_context.sp = (unsigned long)childregs; @@ -330,7 +305,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long esp, int dump_fpu (struct pt_regs *regs, struct user_fp *fp) { struct thread_info *thread = current_thread_info(); - int used_math = current->used_math; + int used_math = !!used_math(); if (used_math) memcpy(fp, &thread->fpstate.soft, sizeof (*fp)); @@ -367,35 +342,42 @@ void dump_thread(struct pt_regs * regs, struct user * dump) } /* - * This is the mechanism for creating a new kernel thread. - * - * NOTE! Only a kernel-only process(ie the swapper or direct descendants - * who haven't done an "execve()") should use this: it will work within - * a system call from a "real" process, but the process memory space will - * not be free'd until both the parent and the child have exited. - * FIXME - taken from arm32 + * Shuffle the argument into the correct register before calling the + * thread function. r1 is the thread argument, r2 is the pointer to + * the thread function, and r3 points to the exit function. + * FIXME - make sure this is right - the older code used to zero fp + * and cause the parent to call sys_exit (do_exit in this version) + */ +extern void kernel_thread_helper(void); + +asm( ".section .text\n" +" .align\n" +" .type kernel_thread_helper, #function\n" +"kernel_thread_helper:\n" +" mov r0, r1\n" +" mov lr, r3\n" +" mov pc, r2\n" +" .size kernel_thread_helper, . - kernel_thread_helper\n" +" .previous"); + +/* + * Create a kernel thread. */ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) { - register unsigned int r0 asm("r0") = flags | CLONE_VM | CLONE_UNTRACED; - register unsigned int r1 asm("r1") = 0; - register pid_t __ret asm("r0"); - - __asm__ __volatile__( - __syscall(clone)" @ kernel_thread sys_clone \n\ - movs %0, r0 @ if we are the child \n\ - bne 1f \n\ - mov fp, #0 @ ensure that fp is zero \n\ - mov r0, %4 \n\ - mov lr, pc \n\ - mov pc, %3 \n\ - b sys_exit \n\ -1: " - : "=r" (__ret) - : "0" (r0), "r" (r1), "r" (fn), "r" (arg) - : "lr"); - return __ret; + struct pt_regs regs; + + memset(®s, 0, sizeof(regs)); + + regs.ARM_r1 = (unsigned long)arg; + regs.ARM_r2 = (unsigned long)fn; + regs.ARM_r3 = (unsigned long)do_exit; + regs.ARM_pc = (unsigned long)kernel_thread_helper | MODE_SVC26; + + return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); } +EXPORT_SYMBOL(kernel_thread); + unsigned long get_wchan(struct task_struct *p) { diff --git a/arch/arm26/kernel/ptrace.c b/arch/arm26/kernel/ptrace.c index b2aea03ac..5ed598351 100644 --- a/arch/arm26/kernel/ptrace.c +++ b/arch/arm26/kernel/ptrace.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -540,7 +541,7 @@ static int ptrace_getfpregs(struct task_struct *tsk, void *ufp) */ static int ptrace_setfpregs(struct task_struct *tsk, void *ufp) { - tsk->used_math = 1; + set_stopped_child_used_math(tsk); return copy_from_user(&tsk->thread_info->fpstate, ufp, sizeof(struct user_fp)) ? -EFAULT : 0; } @@ -591,7 +592,7 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat case PTRACE_SYSCALL: case PTRACE_CONT: ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; if (request == PTRACE_SYSCALL) set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); @@ -626,7 +627,7 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat */ case PTRACE_SINGLESTEP: ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; child->ptrace |= PT_SINGLESTEP; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); diff --git a/arch/arm26/kernel/setup.c b/arch/arm26/kernel/setup.c index e02d41867..4eb329e38 100644 --- a/arch/arm26/kernel/setup.c +++ b/arch/arm26/kernel/setup.c @@ -1,5 +1,5 @@ /* - * linux/arch/arm/kernel/setup.c + * linux/arch/arm26/kernel/setup.c * * Copyright (C) 1995-2001 Russell King * Copyright (C) 2003 Ian Molton @@ -37,7 +37,7 @@ #endif #ifdef CONFIG_PREEMPT -spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(kernel_flag); #endif #if defined(CONFIG_FPE_NWFPE) @@ -74,7 +74,6 @@ unsigned int number_mfm_drives; struct processor processor; -unsigned char aux_device_present; char elf_platform[ELF_PLATFORM_SIZE]; unsigned long phys_initrd_start __initdata = 0; @@ -119,7 +118,7 @@ static void __init setup_processor(void) /* * locate processor in the list of supported processor * types. The linker builds this table for us from the - * entries in arch/arm/mm/proc-*.S + * entries in arch/arm26/mm/proc-*.S */ for (list = &__proc_info_begin; list < &__proc_info_end ; list++) if ((processor_id & list->cpu_mask) == list->cpu_val) diff --git a/arch/arm26/kernel/time-acorn.c b/arch/arm26/kernel/time-acorn.c deleted file mode 100644 index defbc96d5..000000000 --- a/arch/arm26/kernel/time-acorn.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * linux/arch/arm/kernel/time-acorn.c - * - * Copyright (c) 1996-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. - * - * Changelog: - * 24-Sep-1996 RMK Created - * 10-Oct-1996 RMK Brought up to date with arch-sa110eval - * 04-Dec-1997 RMK Updated for new arch/arm/time.c - * 13-May-2003 IM Brought over to ARM26 - */ -#include -#include -#include - -#include -#include -#include -#include - -extern unsigned long (*gettimeoffset)(void); - -static unsigned long ioctime_gettimeoffset(void) -{ - unsigned int count1, count2, status; - long offset; - - ioc_writeb (0, IOC_T0LATCH); - barrier (); - count1 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8); - barrier (); - status = ioc_readb(IOC_IRQREQA); - barrier (); - ioc_writeb (0, IOC_T0LATCH); - barrier (); - count2 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8); - - offset = count2; - if (count2 < count1) { - /* - * We have not had an interrupt between reading count1 - * and count2. - */ - if (status & (1 << 5)) - offset -= LATCH; - } else if (count2 > count1) { - /* - * We have just had another interrupt between reading - * count1 and count2. - */ - offset -= LATCH; - } - - offset = (LATCH - offset) * (tick_nsec / 1000); - return (offset + LATCH/2) / LATCH; -} - -void __init ioctime_init(void) -{ - ioc_writeb(LATCH & 255, IOC_T0LTCHL); - ioc_writeb(LATCH >> 8, IOC_T0LTCHH); - ioc_writeb(0, IOC_T0GO); - - gettimeoffset = ioctime_gettimeoffset; -} diff --git a/arch/arm26/lib/io-readsl-armv3.S b/arch/arm26/lib/io-readsl-armv3.S deleted file mode 100644 index ab7b9fd0f..000000000 --- a/arch/arm26/lib/io-readsl-armv3.S +++ /dev/null @@ -1,78 +0,0 @@ -/* - * linux/arch/arm/lib/io-readsl-armv3.S - * - * Copyright (C) 1995-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. - */ -#include -#include -#include - -/* - * Note that some reads can be aligned on half-word boundaries. - */ -ENTRY(__raw_readsl) - teq r2, #0 @ do we have to check for the zero len? - moveq pc, lr - ands ip, r1, #3 - bne 2f - -1: ldr r3, [r0] - str r3, [r1], #4 - subs r2, r2, #1 - bne 1b - mov pc, lr - -2: cmp ip, #2 - ldr ip, [r0] - blt 4f - bgt 6f - - strb ip, [r1], #1 - mov ip, ip, lsr #8 - strb ip, [r1], #1 - mov ip, ip, lsr #8 -3: subs r2, r2, #1 - ldrne r3, [r0] - orrne ip, ip, r3, lsl #16 - strne ip, [r1], #4 - movne ip, r3, lsr #16 - bne 3b - strb ip, [r1], #1 - mov ip, ip, lsr #8 - strb ip, [r1], #1 - mov pc, lr - -4: strb ip, [r1], #1 - mov ip, ip, lsr #8 - strb ip, [r1], #1 - mov ip, ip, lsr #8 - strb ip, [r1], #1 - mov ip, ip, lsr #8 -5: subs r2, r2, #1 - ldrne r3, [r0] - orrne ip, ip, r3, lsl #8 - strne ip, [r1], #4 - movne ip, r3, lsr #24 - bne 5b - strb ip, [r1], #1 - mov pc, lr - -6: strb ip, [r1], #1 - mov ip, ip, lsr #8 -7: subs r2, r2, #1 - ldrne r3, [r0] - orrne ip, ip, r3, lsl #24 - strne ip, [r1], #4 - movne ip, r3, lsr #8 - bne 7b - strb ip, [r1], #1 - mov ip, ip, lsr #8 - strb ip, [r1], #1 - mov ip, ip, lsr #8 - strb ip, [r1], #1 - mov pc, lr - diff --git a/arch/arm26/lib/io-readsw-armv3.S b/arch/arm26/lib/io-readsw-armv3.S deleted file mode 100644 index 476cf7f8a..000000000 --- a/arch/arm26/lib/io-readsw-armv3.S +++ /dev/null @@ -1,107 +0,0 @@ -/* - * linux/arch/arm/lib/io-readsw-armv3.S - * - * Copyright (C) 1995-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. - */ -#include -#include -#include - -.insw_bad_alignment: - adr r0, .insw_bad_align_msg - mov r2, lr - b panic -.insw_bad_align_msg: - .asciz "insw: bad buffer alignment (0x%p, lr=0x%08lX)\n" - .align - -.insw_align: tst r1, #1 - bne .insw_bad_alignment - - ldr r3, [r0] - strb r3, [r1], #1 - mov r3, r3, lsr #8 - strb r3, [r1], #1 - - subs r2, r2, #1 - RETINSTR(moveq, pc, lr) - -ENTRY(__raw_readsw) - teq r2, #0 @ do we have to check for the zero len? - moveq pc, lr - tst r1, #3 - bne .insw_align - -.insw_aligned: mov ip, #0xff - orr ip, ip, ip, lsl #8 - stmfd sp!, {r4, r5, r6, lr} - - subs r2, r2, #8 - bmi .no_insw_8 - -.insw_8_lp: ldr r3, [r0] - and r3, r3, ip - ldr r4, [r0] - orr r3, r3, r4, lsl #16 - - ldr r4, [r0] - and r4, r4, ip - ldr r5, [r0] - orr r4, r4, r5, lsl #16 - - ldr r5, [r0] - and r5, r5, ip - ldr r6, [r0] - orr r5, r5, r6, lsl #16 - - ldr r6, [r0] - and r6, r6, ip - ldr lr, [r0] - orr r6, r6, lr, lsl #16 - - stmia r1!, {r3 - r6} - - subs r2, r2, #8 - bpl .insw_8_lp - - tst r2, #7 - LOADREGS(eqfd, sp!, {r4, r5, r6, pc}) - -.no_insw_8: tst r2, #4 - beq .no_insw_4 - - ldr r3, [r0] - and r3, r3, ip - ldr r4, [r0] - orr r3, r3, r4, lsl #16 - - ldr r4, [r0] - and r4, r4, ip - ldr r5, [r0] - orr r4, r4, r5, lsl #16 - - stmia r1!, {r3, r4} - -.no_insw_4: tst r2, #2 - beq .no_insw_2 - - ldr r3, [r0] - and r3, r3, ip - ldr r4, [r0] - orr r3, r3, r4, lsl #16 - - str r3, [r1], #4 - -.no_insw_2: tst r2, #1 - ldrne r3, [r0] - strneb r3, [r1], #1 - movne r3, r3, lsr #8 - strneb r3, [r1] - - LOADREGS(fd, sp!, {r4, r5, r6, pc}) - - diff --git a/arch/arm26/lib/io-writesw-armv3.S b/arch/arm26/lib/io-writesw-armv3.S deleted file mode 100644 index 950e7e310..000000000 --- a/arch/arm26/lib/io-writesw-armv3.S +++ /dev/null @@ -1,127 +0,0 @@ -/* - * linux/arch/arm/lib/io-writesw-armv3.S - * - * Copyright (C) 1995-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. - */ -#include -#include -#include - -.outsw_bad_alignment: - adr r0, .outsw_bad_align_msg - mov r2, lr - b panic -.outsw_bad_align_msg: - .asciz "outsw: bad buffer alignment (0x%p, lr=0x%08lX)\n" - .align - -.outsw_align: tst r1, #1 - bne .outsw_bad_alignment - - add r1, r1, #2 - - ldr r3, [r1, #-4] - mov r3, r3, lsr #16 - orr r3, r3, r3, lsl #16 - str r3, [r0] - subs r2, r2, #1 - RETINSTR(moveq, pc, lr) - -ENTRY(__raw_writesw) - teq r2, #0 @ do we have to check for the zero len? - moveq pc, lr - tst r1, #3 - bne .outsw_align - -.outsw_aligned: stmfd sp!, {r4, r5, r6, lr} - - subs r2, r2, #8 - bmi .no_outsw_8 - -.outsw_8_lp: ldmia r1!, {r3, r4, r5, r6} - - mov ip, r3, lsl #16 - orr ip, ip, ip, lsr #16 - str ip, [r0] - - mov ip, r3, lsr #16 - orr ip, ip, ip, lsl #16 - str ip, [r0] - - mov ip, r4, lsl #16 - orr ip, ip, ip, lsr #16 - str ip, [r0] - - mov ip, r4, lsr #16 - orr ip, ip, ip, lsl #16 - str ip, [r0] - - mov ip, r5, lsl #16 - orr ip, ip, ip, lsr #16 - str ip, [r0] - - mov ip, r5, lsr #16 - orr ip, ip, ip, lsl #16 - str ip, [r0] - - mov ip, r6, lsl #16 - orr ip, ip, ip, lsr #16 - str ip, [r0] - - mov ip, r6, lsr #16 - orr ip, ip, ip, lsl #16 - str ip, [r0] - - subs r2, r2, #8 - bpl .outsw_8_lp - - tst r2, #7 - LOADREGS(eqfd, sp!, {r4, r5, r6, pc}) - -.no_outsw_8: tst r2, #4 - beq .no_outsw_4 - - ldmia r1!, {r3, r4} - - mov ip, r3, lsl #16 - orr ip, ip, ip, lsr #16 - str ip, [r0] - - mov ip, r3, lsr #16 - orr ip, ip, ip, lsl #16 - str ip, [r0] - - mov ip, r4, lsl #16 - orr ip, ip, ip, lsr #16 - str ip, [r0] - - mov ip, r4, lsr #16 - orr ip, ip, ip, lsl #16 - str ip, [r0] - -.no_outsw_4: tst r2, #2 - beq .no_outsw_2 - - ldr r3, [r1], #4 - - mov ip, r3, lsl #16 - orr ip, ip, ip, lsr #16 - str ip, [r0] - - mov ip, r3, lsr #16 - orr ip, ip, ip, lsl #16 - str ip, [r0] - -.no_outsw_2: tst r2, #1 - - ldrne r3, [r1] - - movne ip, r3, lsl #16 - orrne ip, ip, ip, lsr #16 - strne ip, [r0] - - LOADREGS(fd, sp!, {r4, r5, r6, pc}) diff --git a/arch/arm26/machine/head.S b/arch/arm26/machine/head.S deleted file mode 100644 index 7a8c4370c..000000000 --- a/arch/arm26/machine/head.S +++ /dev/null @@ -1,111 +0,0 @@ -/* - * linux/arch/arm/kernel/head-armo.S - * - * Copyright (C) 1994-2000 Russell King - * Copyright (C) 2003 Ian Molton - * - * 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. - * - * 26-bit kernel startup code - */ -#include -#include -#include - - .globl swapper_pg_dir - .equ swapper_pg_dir, 0x0207d000 - -/* - * Entry point. - */ - .section ".init.text",#alloc,#execinstr -ENTRY(stext) -__entry: cmp pc, #0x02000000 - ldrlt pc, LC0 @ if 0x01800000, call at 0x02080000 - teq r0, #0 @ Check for old calling method - blne oldparams @ Move page if old - adr r0, LC0 - ldmib r0, {r2-r5, sp} @ Setup stack (and fetch other values) - - mov r0, #0 @ Clear BSS -1: cmp r2, r3 - strcc r0, [r2], #4 - bcc 1b - - bl detect_proc_type - str r0, [r4] - bl detect_arch_type - str r0, [r5] - -#ifdef CONFIG_XIP_KERNEL - ldr r3, ETEXT @ data section copy - ldr r4, SDATA - ldr r5, EDATA -1: - ldr r6, [r3], #4 - str r6, [r4], #4 - cmp r4, r5 - blt 1b -#endif - - mov fp, #0 - b start_kernel - -LC0: .word _stext - .word __bss_start @ r2 - .word _end @ r3 - .word processor_id @ r4 - .word __machine_arch_type @ r5 - .word init_thread_union+8192 @ sp -#ifdef CONFIG_XIP_KERNEL -ETEXT: .word _endtext -SDATA: .word _sdata -EDATA: .word __bss_start -#endif - -arm2_id: .long 0x41560200 @ ARM2 and 250 dont have a CPUID -arm250_id: .long 0x41560250 @ So we create some after probing for them - .align - -oldparams: mov r4, #0x02000000 - add r3, r4, #0x00080000 - add r4, r4, #0x0007c000 -1: ldmia r0!, {r5 - r12} - stmia r4!, {r5 - r12} - cmp r4, r3 - blt 1b - mov pc, lr - -/* - * We need some way to automatically detect the difference between - * these two machines. Unfortunately, it is not possible to detect - * the presence of the SuperIO chip, because that will hang the old - * Archimedes machines solid. - */ -/* DAG: Outdated, these have been combined !!!!!!! */ -detect_arch_type: -#if defined(CONFIG_ARCH_ARC) - mov r0, #MACH_TYPE_ARCHIMEDES -#elif defined(CONFIG_ARCH_A5K) - mov r0, #MACH_TYPE_A5K -#endif - mov pc, lr - -detect_proc_type: - mov ip, lr - mov r2, #0xea000000 @ Point undef instr to continuation - adr r0, continue - 12 - orr r0, r2, r0, lsr #2 - mov r1, #0 - str r0, [r1, #4] - ldr r0, arm2_id - swp r2, r2, [r1] @ check for swp (ARM2 cant) - ldr r0, arm250_id - mrc 15, 0, r3, c0, c0 @ check for CP#15 (ARM250 cant) - mov r0, r3 -continue: mov r2, #0xeb000000 @ Make undef vector loop - sub r2, r2, #2 - str r2, [r1, #4] - mov pc, ip diff --git a/arch/arm26/machine/oldlatches.c b/arch/arm26/machine/oldlatches.c deleted file mode 100644 index 3003634d3..000000000 --- a/arch/arm26/machine/oldlatches.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * linux/arch/arm/kernel/oldlatches.c - * - * Copyright (C) David Alan Gilbert 1995/1996,2000 - * Copyright (C) Ian Molton 2003 - * - * 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. - * - * Support for the latches on the old Archimedes which control the floppy, - * hard disc and printer - */ -#include -#include -#include -#include - -#include -#include -#include -#include - -static unsigned char latch_a_copy; -static unsigned char latch_b_copy; - -/* newval=(oldval & ~mask)|newdata */ -void oldlatch_aupdate(unsigned char mask,unsigned char newdata) -{ - unsigned long flags; - - BUG_ON(!machine_is_archimedes()); - - local_irq_save(flags); //FIXME: was local_save_flags - latch_a_copy = (latch_a_copy & ~mask) | newdata; - __raw_writeb(latch_a_copy, LATCHA_BASE); - local_irq_restore(flags); - - printk("Latch: A = 0x%02x\n", latch_a_copy); -} - - -/* newval=(oldval & ~mask)|newdata */ -void oldlatch_bupdate(unsigned char mask,unsigned char newdata) -{ - unsigned long flags; - - BUG_ON(!machine_is_archimedes()); - - - local_irq_save(flags);//FIXME: was local_save_flags - latch_b_copy = (latch_b_copy & ~mask) | newdata; - __raw_writeb(latch_b_copy, LATCHB_BASE); - local_irq_restore(flags); - - printk("Latch: B = 0x%02x\n", latch_b_copy); -} - -static int __init oldlatch_init(void) -{ - if (machine_is_archimedes()) { - oldlatch_aupdate(0xff, 0xff); - /* Thats no FDC reset...*/ - oldlatch_bupdate(0xff, LATCHB_FDCRESET); - } - return 0; -} - -arch_initcall(oldlatch_init); - -EXPORT_SYMBOL(oldlatch_aupdate); -EXPORT_SYMBOL(oldlatch_bupdate); diff --git a/arch/arm26/machine/small_page.c b/arch/arm26/machine/small_page.c deleted file mode 100644 index 78e9198c2..000000000 --- a/arch/arm26/machine/small_page.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - * linux/arch/arm/mm/small_page.c - * - * Copyright (C) 1996 Russell King - * Copyright (C) 2003 Ian Molton - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Changelog: - * 26/01/1996 RMK Cleaned up various areas to make little more generic - * 07/02/1999 RMK Support added for 16K and 32K page sizes - * containing 8K blocks - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define PEDANTIC - -/* - * Requirement: - * We need to be able to allocate naturally aligned memory of finer - * granularity than the page size. This is typically used for the - * second level page tables on 32-bit ARMs. - * - * Theory: - * We "misuse" the Linux memory management system. We use alloc_page - * to allocate a page and then mark it as reserved. The Linux memory - * management system will then ignore the "offset", "next_hash" and - * "pprev_hash" entries in the mem_map for this page. - * - * We then use a bitstring in the "offset" field to mark which segments - * of the page are in use, and manipulate this as required during the - * allocation and freeing of these small pages. - * - * We also maintain a queue of pages being used for this purpose using - * the "next_hash" and "pprev_hash" entries of mem_map; - */ - -struct order { - struct list_head queue; - unsigned int mask; /* (1 << shift) - 1 */ - unsigned int shift; /* (1 << shift) size of page */ - unsigned int block_mask; /* nr_blocks - 1 */ - unsigned int all_used; /* (1 << nr_blocks) - 1 */ -}; - - -static struct order orders[] = { -#if PAGE_SIZE == 32768 - { LIST_HEAD_INIT(orders[0].queue), 2047, 11, 15, 0x0000ffff }, - { LIST_HEAD_INIT(orders[1].queue), 8191, 13, 3, 0x0000000f } -#else -#error unsupported page size (ARGH!) -#endif -}; - -#define USED_MAP(pg) ((pg)->index) -#define TEST_AND_CLEAR_USED(pg,off) (test_and_clear_bit(off, &USED_MAP(pg))) -#define SET_USED(pg,off) (set_bit(off, &USED_MAP(pg))) - -static spinlock_t small_page_lock = SPIN_LOCK_UNLOCKED; - -static unsigned long __get_small_page(int priority, struct order *order) -{ - unsigned long flags; - struct page *page; - int offset; - - do { - spin_lock_irqsave(&small_page_lock, flags); - - if (list_empty(&order->queue)) - goto need_new_page; - - page = list_entry(order->queue.next, struct page, list); -again: -#ifdef PEDANTIC - if (USED_MAP(page) & ~order->all_used) - PAGE_BUG(page); -#endif - offset = ffz(USED_MAP(page)); - SET_USED(page, offset); - if (USED_MAP(page) == order->all_used) - list_del_init(&page->lru); - spin_unlock_irqrestore(&small_page_lock, flags); - - return (unsigned long) page_address(page) + (offset << order->shift); - -need_new_page: - spin_unlock_irqrestore(&small_page_lock, flags); - page = alloc_page(priority); - spin_lock_irqsave(&small_page_lock, flags); - - if (list_empty(&order->queue)) { - if (!page) - goto no_page; - SetPageReserved(page); - USED_MAP(page) = 0; - list_add(&page->lru, &order->queue); - goto again; - } - - spin_unlock_irqrestore(&small_page_lock, flags); - __free_page(page); - } while (1); - -no_page: - spin_unlock_irqrestore(&small_page_lock, flags); - return 0; -} - -static void __free_small_page(unsigned long spage, struct order *order) -{ - unsigned long flags; - struct page *page; - - if (virt_addr_valid(spage)) { - page = virt_to_page(spage); - - /* - * The container-page must be marked Reserved - */ - if (!PageReserved(page) || spage & order->mask) - goto non_small; - -#ifdef PEDANTIC - if (USED_MAP(page) & ~order->all_used) - PAGE_BUG(page); -#endif - - spage = spage >> order->shift; - spage &= order->block_mask; - - /* - * the following must be atomic wrt get_page - */ - spin_lock_irqsave(&small_page_lock, flags); - - if (USED_MAP(page) == order->all_used) - list_add(&page->lru, &order->queue); - - if (!TEST_AND_CLEAR_USED(page, spage)) - goto already_free; - - if (USED_MAP(page) == 0) - goto free_page; - - spin_unlock_irqrestore(&small_page_lock, flags); - } - return; - -free_page: - /* - * unlink the page from the small page queue and free it - */ - list_del_init(&page->lru); - spin_unlock_irqrestore(&small_page_lock, flags); - ClearPageReserved(page); - __free_page(page); - return; - -non_small: - printk("Trying to free non-small page from %p\n", __builtin_return_address(0)); - return; -already_free: - printk("Trying to free free small page from %p\n", __builtin_return_address(0)); -} - -unsigned long get_page_8k(int priority) -{ - return __get_small_page(priority, orders+1); -} - -void free_page_8k(unsigned long spage) -{ - __free_small_page(spage, orders+1); -} diff --git a/arch/arm26/mm/init.c b/arch/arm26/mm/init.c index 17f7dc3e9..1f09a9d0f 100644 --- a/arch/arm26/mm/init.c +++ b/arch/arm26/mm/init.c @@ -1,5 +1,5 @@ /* - * linux/arch/arm/mm/init.c + * linux/arch/arm26/mm/init.c * * Copyright (C) 1995-2002 Russell King * @@ -26,7 +26,6 @@ #include #include -#include #include #include #include @@ -84,7 +83,7 @@ void show_mem(void) else if (!page_count(page)) free++; else - shared += atomic_read(&page->count) - 1; + shared += page_count(page) - 1; page++; } while (page < end); @@ -156,7 +155,8 @@ find_memend_and_nodes(struct meminfo *mi, struct node_info *np) { unsigned int memend_pfn = 0; - numnodes = 1; + nodes_clear(node_online_map); + node_set_online(0); np->bootmap_pages = 0; @@ -309,8 +309,6 @@ void __init paging_init(struct meminfo *mi) free_area_init_node(0, pgdat, zone_size, bdata->node_boot_start >> PAGE_SHIFT, zhole_size); - mem_map = NODE_DATA(0)->node_mem_map; - /* * finish off the bad pages once * the mem_map is initialised diff --git a/arch/arm26/mm/mm-memc.c b/arch/arm26/mm/mm-memc.c deleted file mode 100644 index 6b3d3ae80..000000000 --- a/arch/arm26/mm/mm-memc.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * linux/arch/arm/mm/mm-armo.c - * - * Copyright (C) 1998-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. - * - * Page table sludge for older ARM processor architectures. - */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#define MEMC_TABLE_SIZE (256*sizeof(unsigned long)) - -kmem_cache_t *pte_cache, *pgd_cache; -int page_nr; - -/* - * Allocate space for a page table and a MEMC table. - * Note that we place the MEMC - * table before the page directory. This means we can - * easily get to both tightly-associated data structures - * with a single pointer. - */ -static inline pgd_t *alloc_pgd_table(void) -{ - void *pg2k = kmem_cache_alloc(pgd_cache, GFP_KERNEL); - - if (pg2k) - pg2k += MEMC_TABLE_SIZE; - - return (pgd_t *)pg2k; -} - -/* - * Free a page table. this function is the counterpart to get_pgd_slow - * below, not alloc_pgd_table above. - */ -void free_pgd_slow(pgd_t *pgd) -{ - unsigned long tbl = (unsigned long)pgd; - - tbl -= MEMC_TABLE_SIZE; - - kmem_cache_free(pgd_cache, (void *)tbl); -} - -/* - * Allocate a new pgd and fill it in ready for use - * - * A new tasks pgd is completely empty (all pages !present) except for: - * - * o The machine vectors at virtual address 0x0 - * o The vmalloc region at the top of address space - * - */ -#define FIRST_KERNEL_PGD_NR (FIRST_USER_PGD_NR + USER_PTRS_PER_PGD) - -pgd_t *get_pgd_slow(struct mm_struct *mm) -{ - pgd_t *new_pgd, *init_pgd; - pmd_t *new_pmd, *init_pmd; - pte_t *new_pte, *init_pte; - - new_pgd = alloc_pgd_table(); - if (!new_pgd) - goto no_pgd; - - /* - * This lock is here just to satisfy pmd_alloc and pte_lock - * FIXME: I bet we could avoid taking it pretty much altogether - */ - spin_lock(&mm->page_table_lock); - - /* - * On ARM, first page must always be allocated since it contains - * the machine vectors. - */ - new_pmd = pmd_alloc(mm, new_pgd, 0); - if (!new_pmd) - goto no_pmd; - - new_pte = pte_alloc_kernel(mm, new_pmd, 0); - if (!new_pte) - goto no_pte; - - init_pgd = pgd_offset(&init_mm, 0); - init_pmd = pmd_offset(init_pgd, 0); - init_pte = pte_offset(init_pmd, 0); - - set_pte(new_pte, *init_pte); - - /* - * the page table entries are zeroed - * when the table is created. (see the cache_ctor functions below) - * Now we need to plonk the kernel (vmalloc) area at the end of - * the address space. We copy this from the init thread, just like - * the init_pte we copied above... - */ - memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR, - (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t)); - - spin_unlock(&mm->page_table_lock); - - /* update MEMC tables */ - cpu_memc_update_all(new_pgd); - return new_pgd; - -no_pte: - spin_unlock(&mm->page_table_lock); - pmd_free(new_pmd); - free_pgd_slow(new_pgd); - return NULL; - -no_pmd: - spin_unlock(&mm->page_table_lock); - free_pgd_slow(new_pgd); - return NULL; - -no_pgd: - return NULL; -} - -/* - * No special code is required here. - */ -void setup_mm_for_reboot(char mode) -{ -} - -/* - * This contains the code to setup the memory map on an ARM2/ARM250/ARM3 - * o swapper_pg_dir = 0x0207d000 - * o kernel proper starts at 0x0208000 - * o create (allocate) a pte to contain the machine vectors - * o populate the pte (points to 0x02078000) (FIXME - is it zeroed?) - * o populate the init tasks page directory (pgd) with the new pte - * o zero the rest of the init tasks pgdir (FIXME - what about vmalloc?!) - */ -void __init memtable_init(struct meminfo *mi) -{ - pte_t *pte; - int i; - - page_nr = max_low_pfn; - - pte = alloc_bootmem_low_pages(PTRS_PER_PTE * sizeof(pte_t)); - pte[0] = mk_pte_phys(PAGE_OFFSET + SCREEN_SIZE, PAGE_READONLY); - pmd_populate(&init_mm, pmd_offset(swapper_pg_dir, 0), pte); - - for (i = 1; i < PTRS_PER_PGD; i++) - pgd_val(swapper_pg_dir[i]) = 0; -} - -void __init iotable_init(struct map_desc *io_desc) -{ - /* nothing to do */ -} - -/* - * We never have holes in the memmap - */ -void __init create_memmap_holes(struct meminfo *mi) -{ -} - -static void pte_cache_ctor(void *pte, kmem_cache_t *cache, unsigned long flags) -{ - memzero(pte, sizeof(pte_t) * PTRS_PER_PTE); -} - -static void pgd_cache_ctor(void *pgd, kmem_cache_t *cache, unsigned long flags) -{ - memzero(pgd + MEMC_TABLE_SIZE, USER_PTRS_PER_PGD * sizeof(pgd_t)); -} - -void __init pgtable_cache_init(void) -{ - pte_cache = kmem_cache_create("pte-cache", - sizeof(pte_t) * PTRS_PER_PTE, - 0, 0, pte_cache_ctor, NULL); - if (!pte_cache) - BUG(); - - pgd_cache = kmem_cache_create("pgd-cache", MEMC_TABLE_SIZE + - sizeof(pgd_t) * PTRS_PER_PGD, - 0, 0, pgd_cache_ctor, NULL); - if (!pgd_cache) - BUG(); -} diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig index a8e4c25c7..112ba2771 100644 --- a/arch/cris/Kconfig +++ b/arch/cris/Kconfig @@ -20,6 +20,10 @@ config RWSEM_GENERIC_SPINLOCK config RWSEM_XCHGADD_ALGORITHM bool +config GENERIC_CALIBRATE_DELAY + bool + default y + config CRIS bool default y diff --git a/arch/cris/arch-v10/drivers/Kconfig b/arch/cris/arch-v10/drivers/Kconfig index f77b987a4..748374f25 100644 --- a/arch/cris/arch-v10/drivers/Kconfig +++ b/arch/cris/arch-v10/drivers/Kconfig @@ -557,7 +557,7 @@ config ETRAX_IDE select DMA_NONPCI help Enable this to get support for ATA/IDE. - You can't use parallell ports or SCSI ports + You can't use paralell ports or SCSI ports at the same time. diff --git a/arch/cris/arch-v10/drivers/eeprom.c b/arch/cris/arch-v10/drivers/eeprom.c index 960f4cbdc..316ca15d6 100644 --- a/arch/cris/arch-v10/drivers/eeprom.c +++ b/arch/cris/arch-v10/drivers/eeprom.c @@ -599,7 +599,7 @@ static ssize_t eeprom_write(struct file * file, const char * buf, size_t count, int i, written, restart=1; unsigned long p; - if (verify_area(VERIFY_READ, buf, count)) + if (!access_ok(VERIFY_READ, buf, count)) { return -EFAULT; } diff --git a/arch/cris/arch-v10/drivers/gpio.c b/arch/cris/arch-v10/drivers/gpio.c index 50548a234..c095de82a 100644 --- a/arch/cris/arch-v10/drivers/gpio.c +++ b/arch/cris/arch-v10/drivers/gpio.c @@ -355,7 +355,7 @@ static ssize_t gpio_write(struct file * file, const char * buf, size_t count, return -EFAULT; } - if (verify_area(VERIFY_READ, buf, count)) { + if (!access_ok(VERIFY_READ, buf, count)) { return -EFAULT; } clk_mask = priv->clk_mask; diff --git a/arch/cris/arch-v10/kernel/fasttimer.c b/arch/cris/arch-v10/kernel/fasttimer.c index 53b94eb3e..4717f7ae8 100644 --- a/arch/cris/arch-v10/kernel/fasttimer.c +++ b/arch/cris/arch-v10/kernel/fasttimer.c @@ -599,23 +599,8 @@ void schedule_usleep(unsigned long us) #ifdef CONFIG_PROC_FS static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) - ,int *eof, void *data_unused -#else - ,int unused -#endif - ); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) + ,int *eof, void *data_unused); static struct proc_dir_entry *fasttimer_proc_entry; -#else -static struct proc_dir_entry fasttimer_proc_entry = -{ - 0, 9, "fasttimer", - S_IFREG | S_IRUGO, 1, 0, 0, - 0, NULL /* ops -- default to array */, - &proc_fasttimer_read /* get_info */, -}; -#endif #endif /* CONFIG_PROC_FS */ #ifdef CONFIG_PROC_FS @@ -624,12 +609,7 @@ static struct proc_dir_entry fasttimer_proc_entry = #define BIG_BUF_SIZE (500 + NUM_TIMER_STATS * 300) static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) - ,int *eof, void *data_unused -#else - ,int unused -#endif - ) + ,int *eof, void *data_unused) { unsigned long flags; int i = 0; @@ -805,9 +785,7 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len memcpy(buf, bigbuf + offset, len); *start = buf; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) *eof = 1; -#endif return len; } @@ -982,12 +960,8 @@ void fast_timer_init(void) } #endif #ifdef CONFIG_PROC_FS -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) if ((fasttimer_proc_entry = create_proc_entry( "fasttimer", 0, 0 ))) fasttimer_proc_entry->read_proc = proc_fasttimer_read; -#else - proc_register_dynamic(&proc_root, &fasttimer_proc_entry); -#endif #endif /* PROC_FS */ if(request_irq(TIMER1_IRQ_NBR, timer1_handler, SA_SHIRQ, "fast timer int", NULL)) diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c index da15db8ae..581ecabaa 100644 --- a/arch/cris/arch-v10/kernel/ptrace.c +++ b/arch/cris/arch-v10/kernel/ptrace.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -184,7 +185,7 @@ sys_ptrace(long request, long pid, long addr, long data) case PTRACE_CONT: ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; if (request == PTRACE_SYSCALL) { @@ -219,7 +220,7 @@ sys_ptrace(long request, long pid, long addr, long data) case PTRACE_SINGLESTEP: ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); diff --git a/arch/cris/arch-v10/kernel/signal.c b/arch/cris/arch-v10/kernel/signal.c index 97b7af26a..85e0032e6 100644 --- a/arch/cris/arch-v10/kernel/signal.c +++ b/arch/cris/arch-v10/kernel/signal.c @@ -125,7 +125,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, if (act) { old_sigset_t mask; - if (verify_area(VERIFY_READ, act, sizeof(*act)) || + if (!access_ok(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; @@ -137,7 +137,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); if (!ret && oact) { - if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || + if (!access_ok(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; @@ -231,7 +231,7 @@ asmlinkage int sys_sigreturn(long r10, long r11, long r12, long r13, long mof, if (((long)frame) & 3) goto badframe; - if (verify_area(VERIFY_READ, frame, sizeof(*frame))) + if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) goto badframe; if (__get_user(set.sig[0], &frame->sc.oldmask) || (_NSIG_WORDS > 1 @@ -273,7 +273,7 @@ asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13, if (((long)frame) & 3) goto badframe; - if (verify_area(VERIFY_READ, frame, sizeof(*frame))) + if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) goto badframe; if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; diff --git a/arch/cris/kernel/irq.c b/arch/cris/kernel/irq.c index 2a9ed1806..d848b9407 100644 --- a/arch/cris/kernel/irq.c +++ b/arch/cris/kernel/irq.c @@ -158,11 +158,6 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs) local_irq_disable(); } irq_exit(); - - if (softirq_pending(cpu)) - do_softirq(); - - /* unmasking and bottom half handling is done magically for us. */ } /* this function links in a handler into the chain of handlers for the diff --git a/arch/cris/kernel/setup.c b/arch/cris/kernel/setup.c index 02f62310a..6ec267107 100644 --- a/arch/cris/kernel/setup.c +++ b/arch/cris/kernel/setup.c @@ -26,8 +26,6 @@ struct drive_info_struct { char dummy[32]; } drive_info; struct screen_info screen_info; -unsigned char aux_device_present; - extern int root_mountflags; extern char _etext, _edata, _end; diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig index d0b845ac0..b8499363a 100644 --- a/arch/h8300/Kconfig +++ b/arch/h8300/Kconfig @@ -33,6 +33,10 @@ config RWSEM_XCHGADD_ALGORITHM bool default n +config GENERIC_CALIBRATE_DELAY + bool + default y + config ISA bool default y diff --git a/arch/h8300/Makefile b/arch/h8300/Makefile index 5c6d67116..c9b80cffd 100644 --- a/arch/h8300/Makefile +++ b/arch/h8300/Makefile @@ -7,9 +7,6 @@ # # (C) Copyright 2002,2003 Yoshinori Sato # -ifndef include-config --include $(TOPDIR)/.config -endif platform-$(CONFIG_CPU_H8300H) := h8300h platform-$(CONFIG_CPU_H8S) := h8s @@ -47,9 +44,11 @@ LIBGCC := $(shell $(CROSS-COMPILE)$(CC) $(CFLAGS) -print-libgcc-file-name) head-y := arch/$(ARCH)/platform/$(platform-y)/$(board-y)/crt0_$(model-y).o core-y += arch/$(ARCH)/kernel/ \ - arch/$(ARCH)/mm/ \ - arch/$(ARCH)/platform/$(PLATFORM)/ \ + arch/$(ARCH)/mm/ +ifdef PLATFORM +core-y += arch/$(ARCH)/platform/$(PLATFORM)/ \ arch/$(ARCH)/platform/$(PLATFORM)/$(BOARD)/ +endif libs-y += arch/$(ARCH)/lib/ $(LIBGCC) diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c index 134aec1c6..b5f83e9f0 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/ptrace.c b/arch/h8300/kernel/ptrace.c index 7e5cce33b..f673dfd0a 100644 --- a/arch/h8300/kernel/ptrace.c +++ b/arch/h8300/kernel/ptrace.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -173,7 +174,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: { /* restart after signal. */ ret = -EIO; - if ((unsigned long) data >= _NSIG) + if (!valid_signal(data)) break ; if (request == PTRACE_SYSCALL) set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); @@ -204,7 +205,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) case PTRACE_SINGLESTEP: { /* set the trap flag. */ ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); child->exit_code = data; diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c index 962d4305a..a4799d633 100644 --- a/arch/h8300/kernel/signal.c +++ b/arch/h8300/kernel/signal.c @@ -113,7 +113,7 @@ sys_sigaction(int sig, const struct old_sigaction *act, if (act) { old_sigset_t mask; - if (verify_area(VERIFY_READ, act, sizeof(*act)) || + if (!access_ok(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; @@ -125,7 +125,7 @@ sys_sigaction(int sig, const struct old_sigaction *act, ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); if (!ret && oact) { - if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || + if (!access_ok(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; @@ -222,7 +222,7 @@ asmlinkage int do_sigreturn(unsigned long __unused,...) sigset_t set; int er0; - if (verify_area(VERIFY_READ, frame, sizeof(*frame))) + if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) goto badframe; if (__get_user(set.sig[0], &frame->sc.sc_mask) || (_NSIG_WORDS > 1 && @@ -253,7 +253,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused,...) sigset_t set; int er0; - if (verify_area(VERIFY_READ, frame, sizeof(*frame))) + if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) goto badframe; if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; diff --git a/arch/h8300/kernel/syscalls.S b/arch/h8300/kernel/syscalls.S index 1055a1bf7..79b3bda5c 100644 --- a/arch/h8300/kernel/syscalls.S +++ b/arch/h8300/kernel/syscalls.S @@ -289,6 +289,21 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_utimes) .long SYMBOL_NAME(sys_fadvise64_64) .long SYMBOL_NAME(sys_ni_syscall) /* sys_vserver */ + .long SYMBOL_NAME(sys_mbind) + .long SYMBOL_NAME(sys_get_mempolicy) + .long SYMBOL_NAME(sys_set_mempolicy) + .long SYMBOL_NAME(sys_mq_open) + .long SYMBOL_NAME(sys_mq_unlink) + .long SYMBOL_NAME(sys_mq_timedsend) + .long SYMBOL_NAME(sys_mq_timedreceive) /* 280 */ + .long SYMBOL_NAME(sys_mq_notify) + .long SYMBOL_NAME(sys_mq_getsetattr) + .long SYMBOL_NAME(sys_ni_syscall) /* reserved for kexec */ + .long SYMBOL_NAME(sys_waitid) + .long SYMBOL_NAME(sys_ni_syscall) /* 285 */ /* available */ + .long SYMBOL_NAME(sys_add_key) + .long SYMBOL_NAME(sys_request_key) + .long SYMBOL_NAME(sys_keyctl) .rept NR_syscalls-(.-SYMBOL_NAME(sys_call_table))/4 .long SYMBOL_NAME(sys_ni_syscall) diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index 1ed5b3831..3f4ad7fb7 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -183,6 +183,7 @@ config M386 - "Winchip-C6" for original IDT Winchip. - "Winchip-2" for IDT Winchip 2. - "Winchip-2A" for IDT Winchips with 3dNow! capabilities. + - "GeodeGX1" for Geode GX1 (Cyrix MediaGX). - "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3. - "VIA C3-2 for VIA C3-2 "Nehemiah" (model 9 and above). @@ -310,6 +311,11 @@ config MWINCHIP3D stores for this CPU, which can increase performance of some operations. +config MGEODEGX1 + bool "GeodeGX1" + help + Select this for a Geode GX1 (Cyrix MediaGX) chip. + config MCYRIXIII bool "CyrixIII/VIA-C3" help @@ -360,7 +366,7 @@ config X86_L1_CACHE_SHIFT int default "7" if MPENTIUM4 || X86_GENERIC default "4" if X86_ELAN || M486 || M386 - default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 + default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODEGX1 default "6" if MK7 || MK8 || MPENTIUMM config RWSEM_GENERIC_SPINLOCK @@ -373,9 +379,13 @@ config RWSEM_XCHGADD_ALGORITHM depends on !M386 default y +config GENERIC_CALIBRATE_DELAY + bool + default y + config X86_PPRO_FENCE bool - depends on M686 || M586MMX || M586TSC || M586 || M486 || M386 + depends on M686 || M586MMX || M586TSC || M586 || M486 || M386 || MGEODEGX1 default y config X86_F00F_BUG @@ -405,7 +415,7 @@ config X86_POPAD_OK config X86_ALIGNMENT_16 bool - depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 + depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1 default y config X86_GOOD_APIC @@ -513,10 +523,21 @@ 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 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 X86_UP_APIC - bool "Local APIC support on uniprocessors" if !SMP - depends on !(X86_VISWS || X86_VOYAGER) - ---help--- + bool "Local APIC support on uniprocessors" + depends on !SMP && !(X86_VISWS || X86_VOYAGER) + help A local APIC (Advanced Programmable Interrupt Controller) is an integrated interrupt controller in the CPU. If you have a single-CPU system which has a processor with a local APIC, you can say Y here to @@ -526,36 +547,36 @@ config X86_UP_APIC performance counters), and the NMI watchdog which detects hard lockups. - If you have a system with several CPUs, you do not need to say Y - here: the local APIC will be used automatically. - config X86_UP_IOAPIC bool "IO-APIC support on uniprocessors" - depends on !SMP && X86_UP_APIC + depends on X86_UP_APIC help An IO-APIC (I/O Advanced Programmable Interrupt Controller) is an SMP-capable replacement for PC-style interrupt controllers. Most - SMP systems and a small number of uniprocessor systems have one. + SMP systems and many recent uniprocessor systems have one. + If you have a single-CPU system with an IO-APIC, you can say Y here to use it. If you say Y here even though your machine doesn't have an IO-APIC, then the kernel will still run with no slowdown at all. - If you have a system with several CPUs, you do not need to say Y - here: the IO-APIC will be used automatically. - config X86_LOCAL_APIC bool - depends on !SMP && X86_UP_APIC + depends on X86_UP_APIC || ((X86_VISWS || SMP) && !X86_VOYAGER) default y config X86_IO_APIC bool - depends on !SMP && X86_UP_IOAPIC + depends on X86_UP_IOAPIC || (SMP && !(X86_VISWS || X86_VOYAGER)) + default y + +config X86_VISWS_APIC + bool + depends on X86_VISWS default y config KERNEL_HZ - int "Timer Frequency (100-20000)" - range 100 20000 + int "Timer Frequency (100-10000)" + range 100 10000 default "1000" help This allows you to specify the frequency at which the @@ -563,7 +584,7 @@ config KERNEL_HZ config X86_TSC bool - depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2) && !X86_NUMAQ + depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODEGX1) && !X86_NUMAQ default y config X86_MCE @@ -638,6 +659,24 @@ config I8K Say Y if you intend to run this kernel on a Dell Inspiron 8000. Say N otherwise. +config X86_REBOOTFIXUPS + bool "Enable X86 board specific fixups for reboot" + depends on X86 + default n + ---help--- + This enables chipset and/or board specific fixups to be done + in order to get reboot to work correctly. This is only needed on + some combinations of hardware and BIOS. The symptom, for which + this config is intended, is when reboot ends with a stalled/hung + system. + + Currently, the only fixup is for the Geode GX1/CS5530A/TROM2.1. + combination. + + Say Y if you want to enable the fixup. Currently, it's safe to + enable this option even if you don't need it. + Say N otherwise. + config MICROCODE tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support" ---help--- @@ -802,6 +841,16 @@ config HAVE_ARCH_BOOTMEM_NODE depends on NUMA default y +config HAVE_MEMORY_PRESENT + bool + depends on DISCONTIGMEM + default y + +config NEED_NODE_MEMMAP_SIZE + bool + depends on DISCONTIGMEM + default y + config HIGHPTE bool "Allocate 3rd-level pagetables from highmem" depends on HIGHMEM4G || HIGHMEM64G @@ -875,7 +924,6 @@ config EFI depends on ACPI default n ---help--- - This enables the the kernel to boot on EFI platforms using system configuration information passed to it from the firmware. This also enables the kernel to use any EFI runtime services that are @@ -914,7 +962,7 @@ config REGPARM depends on EXPERIMENTAL default n help - Compile the kernel with -mregparm=3. This uses an different ABI + Compile the kernel with -mregparm=3. This uses a different ABI and passes the first three arguments of a function call in registers. This will probably break binary only modules. @@ -969,6 +1017,24 @@ config BACKUP_SIZE default 32 help The size of the second kernel's memory. + +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//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 @@ -1133,21 +1199,6 @@ endmenu menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)" -config X86_VISWS_APIC - bool - depends on X86_VISWS - default y - -config X86_LOCAL_APIC - bool - depends on (X86_VISWS || SMP) && !X86_VOYAGER - default y - -config X86_IO_APIC - bool - depends on SMP && !(X86_VISWS || X86_VOYAGER) - default y - config PCI bool "PCI support" if !X86_VISWS depends on !X86_VOYAGER @@ -1208,12 +1259,18 @@ 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 +source "drivers/pci/pcie/Kconfig" + source "drivers/pci/Kconfig" +config ISA_DMA_API + bool + default y + config ISA bool "ISA support" depends on !(X86_VOYAGER || X86_VISWS) @@ -1243,18 +1300,14 @@ config EISA source "drivers/eisa/Kconfig" config MCA - bool "MCA support" - depends on !(X86_VISWS || X86_VOYAGER) + bool "MCA support" if !(X86_VISWS || X86_VOYAGER) + default y if X86_VOYAGER help MicroChannel Architecture is found in some IBM PS/2 machines and laptops. It is a bus system similar to PCI or ISA. See (and especially the web page given there) before attempting to build an MCA bus kernel. -config MCA - depends on X86_VOYAGER - default y if X86_VOYAGER - source "drivers/mca/Kconfig" config SCx200 diff --git a/arch/i386/Kconfig.debug b/arch/i386/Kconfig.debug index 7741c2711..9311158c7 100644 --- a/arch/i386/Kconfig.debug +++ b/arch/i386/Kconfig.debug @@ -3,7 +3,7 @@ menu "Kernel hacking" source "lib/Kconfig.debug" config EARLY_PRINTK - bool "Early printk" if EMBEDDED + bool "Early printk" if EMBEDDED && DEBUG_KERNEL default y help Write kernel log output directly into the VGA buffer or to a serial @@ -97,14 +97,27 @@ config STACK_PANIC help Panic if the stack grows to within specified byte range. +comment "Page alloc debug is incompatible with Software Suspend on i386" + depends on DEBUG_KERNEL && SOFTWARE_SUSPEND + config DEBUG_PAGEALLOC bool "Page alloc debugging" - depends on DEBUG_KERNEL + depends on DEBUG_KERNEL && !SOFTWARE_SUSPEND help Unmap pages from the kernel linear mapping after free_pages(). This results in a large slowdown, but helps to find certain types of memory corruptions. +config 4KSTACKS + bool "Use 4Kb for kernel stacks instead of 8Kb" + depends on DEBUG_KERNEL + help + If you say Y here the kernel will use a 4Kb stacksize for the + kernel stack attached to each process/thread. This facilitates + running more threads on a system and also reduces the pressure + on the VM subsystem for higher order allocations. This option + will also use IRQ stacks to compensate for the reduced stackspace. + config X86_FIND_SMP_CONFIG bool depends on X86_LOCAL_APIC || X86_VOYAGER diff --git a/arch/i386/Makefile b/arch/i386/Makefile index 5a5525ed8..4d22f78e0 100644 --- a/arch/i386/Makefile +++ b/arch/i386/Makefile @@ -14,13 +14,15 @@ # 19990713 Artur Skawina # Added '-march' and '-mpreferred-stack-boundary' support # +# 20050320 Kianusch Sayah Karadji +# Added support for GEODE CPU LDFLAGS := -m elf_i386 OBJCOPYFLAGS := -O binary -R .note -R .comment -S LDFLAGS_vmlinux := CHECKFLAGS += -D__i386__ -CFLAGS += -pipe -msoft-float -m32 -fno-builtin-sprintf -fno-builtin-log2 -fno-builtin-puts +CFLAGS += -pipe -msoft-float -m32 -fno-builtin-sprintf -fno-builtin-log2 -fno-builtin-puts # prevent gcc from keeping the stack 16 byte aligned CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2) @@ -31,11 +33,13 @@ cflags-$(CONFIG_M486) += -march=i486 cflags-$(CONFIG_M586) += -march=i586 cflags-$(CONFIG_M586TSC) += -march=i586 cflags-$(CONFIG_M586MMX) += $(call cc-option,-march=pentium-mmx,-march=i586) -cflags-$(CONFIG_M686) += -march=i686 +#cflags-$(CONFIG_M686) += -march=i686 -mtune=pentium4 +cflags-$(CONFIG_M686) += -march=i686 -mcpu=pentium4 cflags-$(CONFIG_MPENTIUMII) += -march=i686 $(call cc-option,-mtune=pentium2) cflags-$(CONFIG_MPENTIUMIII) += -march=i686 $(call cc-option,-mtune=pentium3) cflags-$(CONFIG_MPENTIUMM) += -march=i686 $(call cc-option,-mtune=pentium3) -cflags-$(CONFIG_MPENTIUM4) += -march=i686 $(call cc-option,-mtune=pentium4) +#cflags-$(CONFIG_MPENTIUM4) += -march=i686 $(call cc-option,-mtune=pentium4) +cflags-$(CONFIG_MPENTIUM4) += -march=i686 $(call cc-option,-march=pentium4) cflags-$(CONFIG_MK6) += -march=k6 # Please note, that patches that add -march=athlon-xp and friends are pointless. # They make zero difference whatsosever to performance at this time. @@ -52,6 +56,9 @@ cflags-$(CONFIG_MVIAC3_2) += $(call cc-option,-march=c3-2,-march=i686) # AMD Elan support cflags-$(CONFIG_X86_ELAN) += -march=i486 +# Geode GX1 support +cflags-$(CONFIG_MGEODEGX1) += $(call cc-option,-march=pentium-mmx,-march=i486) + # -mregparm=3 works ok on gcc-3.0 and later # GCC_VERSION := $(call cc-version) @@ -118,7 +125,7 @@ AFLAGS += $(mflags-y) -m32 boot := arch/i386/boot .PHONY: zImage bzImage compressed zlilo bzlilo \ - zdisk bzdisk fdimage fdimage144 fdimage288 install + zdisk bzdisk fdimage fdimage144 fdimage288 install kernel_install all: bzImage @@ -137,9 +144,13 @@ zlilo bzlilo: vmlinux zdisk bzdisk: vmlinux $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) zdisk -install fdimage fdimage144 fdimage288: vmlinux +fdimage fdimage144 fdimage288: vmlinux $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@ +install: vmlinux +install kernel_install: + $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install + prepare: include/asm-$(ARCH)/asm_offsets.h CLEAN_FILES += include/asm-$(ARCH)/asm_offsets.h diff --git a/arch/i386/boot/compressed/misc.c b/arch/i386/boot/compressed/misc.c index 9805b3730..7324ba503 100644 --- a/arch/i386/boot/compressed/misc.c +++ b/arch/i386/boot/compressed/misc.c @@ -12,7 +12,6 @@ #include #include #include -#include \n\n"; + print "\n"; } } -# output function in sgml DocBook -sub output_function_sgml(%) { +# output function in XML DocBook +sub output_function_xml(%) { my %args = %{$_[0]}; my ($parameter, $section); my $count; @@ -576,8 +581,14 @@ sub output_function_sgml(%) { $id =~ s/[^A-Za-z0-9]/-/g; print "\n"; + print "\n"; + print " LINUX\n"; + print " Kernel Hackers Manual\n"; + print " $man_date\n"; + print "\n"; print "\n"; - print "".$args{'function'}."\n"; + print " ".$args{'function'}."\n"; + print " 9\n"; print "\n"; print "\n"; print " ".$args{'function'}."\n"; @@ -607,7 +618,7 @@ sub output_function_sgml(%) { } } } else { - print " \n"; + print " \n"; } print " \n"; print "\n"; @@ -632,12 +643,12 @@ sub output_function_sgml(%) { } print "\n"; - output_section_sgml(@_); + output_section_xml(@_); print "\n\n"; } -# output struct in sgml DocBook -sub output_struct_sgml(%) { +# output struct in XML DocBook +sub output_struct_xml(%) { my %args = %{$_[0]}; my ($parameter, $section); my $id; @@ -646,8 +657,14 @@ sub output_struct_sgml(%) { $id =~ s/[^A-Za-z0-9]/-/g; print "\n"; + print "\n"; + print " LINUX\n"; + print " Kernel Hackers Manual\n"; + print " $man_date\n"; + print "\n"; print "\n"; - print "".$args{'type'}." ".$args{'struct'}."\n"; + print " ".$args{'type'}." ".$args{'struct'}."\n"; + print " 9\n"; print "\n"; print "\n"; print " ".$args{'type'}." ".$args{'struct'}."\n"; @@ -708,13 +725,13 @@ sub output_struct_sgml(%) { print " \n"; print " \n"; - output_section_sgml(@_); + output_section_xml(@_); print "\n\n"; } -# output enum in sgml DocBook -sub output_enum_sgml(%) { +# output enum in XML DocBook +sub output_enum_xml(%) { my %args = %{$_[0]}; my ($parameter, $section); my $count; @@ -724,8 +741,14 @@ sub output_enum_sgml(%) { $id =~ s/[^A-Za-z0-9]/-/g; print "\n"; + print "\n"; + print " LINUX\n"; + print " Kernel Hackers Manual\n"; + print " $man_date\n"; + print "\n"; print "\n"; - print "enum ".$args{'enum'}."\n"; + print " enum ".$args{'enum'}."\n"; + print " 9\n"; print "\n"; print "\n"; print " enum ".$args{'enum'}."\n"; @@ -769,13 +792,13 @@ sub output_enum_sgml(%) { print " \n"; print "\n"; - output_section_sgml(@_); + output_section_xml(@_); print "\n\n"; } -# output typedef in sgml DocBook -sub output_typedef_sgml(%) { +# output typedef in XML DocBook +sub output_typedef_xml(%) { my %args = %{$_[0]}; my ($parameter, $section); my $id; @@ -784,8 +807,14 @@ sub output_typedef_sgml(%) { $id =~ s/[^A-Za-z0-9]/-/g; print "\n"; + print "\n"; + print " LINUX\n"; + print " Kernel Hackers Manual\n"; + print " $man_date\n"; + print "\n"; print "\n"; - print "typedef ".$args{'typedef'}."\n"; + print " typedef ".$args{'typedef'}."\n"; + print " 9\n"; print "\n"; print "\n"; print " typedef ".$args{'typedef'}."\n"; @@ -800,13 +829,13 @@ sub output_typedef_sgml(%) { print " typedef ".$args{'typedef'}.";\n"; print "\n"; - output_section_sgml(@_); + output_section_xml(@_); print "\n\n"; } -# output in sgml DocBook -sub output_intro_sgml(%) { +# output in XML DocBook +sub output_intro_xml(%) { my %args = %{$_[0]}; my ($parameter, $section); my $count; @@ -831,7 +860,7 @@ sub output_intro_sgml(%) { print "\n\n"; } -# output in sgml DocBook +# output in XML DocBook sub output_function_gnome { my %args = %{$_[0]}; my ($parameter, $section); @@ -1465,6 +1494,8 @@ sub dump_function($$) { $prototype =~ s/^static +//; $prototype =~ s/^extern +//; + $prototype =~ s/^fastcall +//; + $prototype =~ s/^asmlinkage +//; $prototype =~ s/^inline +//; $prototype =~ s/^__inline__ +//; $prototype =~ s/^#define +//; #ak added @@ -1578,13 +1609,13 @@ sub process_state3_function($$) { my $x = shift; my $file = shift; - if ($x =~ m#\s*/\*\s+MACDOC\s*#io) { + if ($x =~ m#\s*/\*\s+MACDOC\s*#io || ($x =~ /^#/ && $x !~ /^#define/)) { # do nothing } elsif ($x =~ /([^\{]*)/) { $prototype .= $1; } - if (($x =~ /\{/) || ($x =~ /\#/) || ($x =~ /;/)) { + if (($x =~ /\{/) || ($x =~ /\#define/) || ($x =~ /;/)) { $prototype =~ s@/\*.*?\*/@@gos; # strip comments. $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's. $prototype =~ s@^\s+@@gos; # strip leading spaces @@ -1624,6 +1655,15 @@ sub process_state3_type($$) { } } +# replace <, >, and & +sub xml_escape($) { + my $text = shift; + $text =~ s/\&/\\\\\\amp;/g; + $text =~ s/\/\\\\\\gt;/g; + return $text; +} + sub process_file($) { my ($file) = "$ENV{'SRCTREE'}@_"; my $identifier; @@ -1664,7 +1704,7 @@ sub process_file($) { $state = 2; if (/-(.*)/) { - $declaration_purpose = $1; + $declaration_purpose = xml_escape($1); } else { $declaration_purpose = ""; } @@ -1695,10 +1735,7 @@ sub process_file($) { $newcontents = $2; if ($contents ne "") { - $contents =~ s/\&/\\\\\\amp;/g; - $contents =~ s/\/\\\\\\gt;/g; - dump_section($section, $contents); + dump_section($section, xml_escape($contents)); $section = $section_default; } @@ -1710,10 +1747,7 @@ sub process_file($) { } elsif (/$doc_end/) { if ($contents ne "") { - $contents =~ s/\&/\\\\\\amp;/g; - $contents =~ s/\/\\\\\\gt;/g; - dump_section($section, $contents); + dump_section($section, xml_escape($contents)); $section = $section_default; $contents = ""; } @@ -1727,10 +1761,7 @@ sub process_file($) { # @parameter line to signify start of description if ($1 eq "" && ($section =~ m/^@/ || $section eq $section_context)) { - $contents =~ s/\&/\\\\\\amp;/g; - $contents =~ s/\/\\\\\\gt;/g; - dump_section($section, $contents); + dump_section($section, xml_escape($contents)); $section = $section_default; $contents = ""; } else { @@ -1799,7 +1830,7 @@ sub process_file($) { } if ($initial_section_counter == $section_counter) { print STDERR "Warning(${file}): no structured comments found\n"; - if ($output_mode eq "sgml") { + if ($output_mode eq "xml") { # The template wants at least one RefEntry here; make one. print "\n"; print " \n"; diff --git a/scripts/makeman b/scripts/makeman deleted file mode 100755 index db3af647e..000000000 --- a/scripts/makeman +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/perl - -use strict; - -## Copyright (C) Michael Still (mikal@stillhq.com) -## Released under the terms of the GNU GPL -## -## A script to make or install the manpages extracted by split-man -## -## Arguements: $1 -- the word "convert" or "install" -## $2 -- the directory containing the SGML files for the manpages -## $3 -- the filename which contained the sgmldoc output -## (I need this so I know which manpages to convert) - -my($LISTING, $GENERATED, $INPUT, $OUTPUT, $front, $mode, $filename, $tmpdir); - -if($ARGV[0] eq ""){ - die "Usage: makeman [convert | install] \n"; -} - -if( ! -d "$ARGV[1]" ){ - die "Output directory \"$ARGV[1]\" does not exist\n"; -} - -if($ENV{"TMPDIR"} ne ""){ - $tmpdir = $ENV{"TMPDIR"}; -} -else{ - $tmpdir = "/tmp"; -} - -if($ARGV[0] eq "convert"){ - open LISTING, "grep \"\" $ARGV[2] |"; - while(){ - s/<\/.*$//; - s/^.*>//; - s/\.sgml//; - s/struct //; - s/typedef //; - - chomp; - $filename = $_; - print "Processing $filename\n"; - - # Open the input file to extract the front matter, generate the man page, - # and open it, and the rearrange everything until it is happy - open INPUT, "< $ARGV[1]/$filename.sgml"; - $front = ""; - $mode = 0; - - # The modes used here are: - # mode = 0 - # - # - # - # ...doco... - - # I know that some of the if statements in this while loop are in a funny - # order, but that is deliberate... - while(){ - if($mode > 0){ - s///; - s///i; - s<\/docinfo>//i; - s/^[ \t]*//i; - } - - if($mode == 2){ - if(//i){ - } - elsif(/<\/para>/i){ - $front = "$front.\\\" \n"; - } - elsif(/<\/legalnotice>/i){ - $mode = 4; - } - elsif(/^[ \t]*$/){ - } - else{ - $front = "$front.\\\" $_"; - } - } - - if($mode == 1){ - if(/(.*)<\/title>/i){ - $front = "$front.\\\" This documentation was generated from the book titled \"$1\", which is part of the Linux kernel source.\n.\\\" \n"; - } - elsif(/<legalnotice>/i){ - $front = "$front.\\\" This documentation comes with the following legal notice:\n.\\\" \n"; - $mode = 2; - } - - elsif(/<author>/i){ - $front = "$front.\\\" Documentation by: "; - } - elsif(/<firstname>(.*)<\/firstname>/i){ - $front = "$front$1 "; - } - elsif(/<surname>(.*)<\/surname>/i){ - $front = "$front$1 "; - } - elsif(/<email>(.*)<\/email>/i){ - $front = "$front($1)"; - } - elsif(/\/author>/i){ - $front = "$front\n"; - } - - elsif(/<copyright>/i){ - $front = "$front.\\\" Documentation copyright: "; - } - elsif(/<holder>(.*)<\/holder>/i){ - $front = "$front$1 "; - } - elsif(/<year>(.*)<\/year>/i){ - $front = "$front$1 "; - } - elsif(/\/copyright>/i){ - $front = "$front\n"; - } - - elsif(/^[ \t]*$/ - || /<affiliation>/i - || /<\/affiliation>/i - || /<address>/i - || /<\/address>/i - || /<authorgroup>/i - || /<\/authorgroup>/i - || /<\/legalnotice>/i - || /<date>/i - || /<\/date>/i - || /<edition>/i - || /<\/edition>/i - || /<pubdate>/i - || /<\/pubdate>/i){ - } - else{ - print "Unknown tag in manpage conversion: $_"; - } - } - - if($mode == 0){ - if(/<bookinfo>/i){ - $mode = 1; - } - } - - if($mode == 4){ - if(/<\/bookinfo>/i){ - $mode = 3; - } - } - } - close INPUT; - - system("cd $ARGV[1]; docbook2man $filename.sgml; mv $filename.9 $tmpdir/$$.9\n"); - open GENERATED, "< $tmpdir/$$.9"; - open OUTPUT, "> $ARGV[1]/$filename.9"; - - print OUTPUT "$front"; - print OUTPUT ".\\\" For comments on the formatting of this manpage, please contact Michael Still <mikal\@stillhq.com>\n\n"; - while(<GENERATED>){ - print OUTPUT "$_"; - } - close OUTPUT; - close GENERATED; - - system("gzip -f $ARGV[1]/$filename.9\n"); - unlink("$tmpdir/$$.9"); - } -} -elsif($ARGV[0] eq "install"){ - system("mkdir -p /usr/local/man/man9/; install $ARGV[1]/*.9.gz /usr/local/man/man9/"); -} -else{ - die "Usage: makeman [convert | install] <dir> <file>\n"; -} - -print "Done\n"; diff --git a/scripts/reference_init.pl b/scripts/reference_init.pl index 7c3d97c57..ab0d2b755 100644 --- a/scripts/reference_init.pl +++ b/scripts/reference_init.pl @@ -70,7 +70,7 @@ foreach $object (keys(%object)) { $l = read(OBJECT, $comment, $size); die "read $size bytes from $object .comment failed" if ($l != $size); close(OBJECT); - if ($comment =~ /GCC\:.*GCC\:/m) { + if ($comment =~ /GCC\:.*GCC\:/m || $object =~ /built-in\.o/) { ++$ignore; delete($object{$object}); } @@ -96,7 +96,9 @@ foreach $object (sort(keys(%object))) { $from !~ /\.text\.lock$/ && $from !~ /\.pci_fixup_header$/ && $from !~ /\.pci_fixup_final$/ && + $from !~ /\.pdr$/ && $from !~ /\__param$/ && + $from !~ /\.altinstructions/ && $from !~ /\.debug_/)) { printf("Error: %s %s refers to %s\n", $object, $from, $line); } diff --git a/scripts/split-man b/scripts/split-man deleted file mode 100755 index 03897fe6a..000000000 --- a/scripts/split-man +++ /dev/null @@ -1,112 +0,0 @@ -#!/usr/bin/perl - -use strict; - -## Copyright (C) Michael Still (mikal@stillhq.com) -## Released under the terms of the GNU GPL -## -## Hoon through the specified DocBook SGML file, and split out the -## man pages. These can then be processed into groff format, and -## installed if desired... -## -## Arguements: $1 -- the name of the sgml file -## $2 -- the directory to put the generated SGML files in -## $3 -- kernel version - -my($SGML, $REF, $front, $refdata, $mode, $filename); - -if(($ARGV[0] eq "") || ($ARGV[1] eq "") || ($ARGV[2] eq "")){ - die "Usage: split-man <sgml file> <output dir> <kernel version>\n"; -} - -open SGML, "< $ARGV[0]" or die "Could not open input file \"$ARGV[0]\"\n"; -if( ! -d "$ARGV[1]" ){ - die "Output directory \"$ARGV[1]\" does not exist\n"; -} - -# Possible modes: -# 0: Looking for input I care about -# 1: Inside book front matter -# 2: Inside a refentry -# 3: Inside a refentry, and we know the filename - -$mode = 0; -$refdata = ""; -$front = ""; -while(<SGML>){ - # Starting modes - if(/<bookinfo>/ || /<docinfo>/){ - $mode = 1; - } - elsif(/<refentry>/){ - $mode = 2; - } - elsif(/<refentrytitle><phrase[^>]*>([^<]*)<.*$/){ - $mode = 3; - $filename = $1; - - $filename =~ s/struct //; - $filename =~ s/typedef //; - - print "Found manpage for $filename\n"; - open REF, "> $ARGV[1]/$filename.sgml" or - die "Couldn't open output file \"$ARGV[1]/$filename.sgml\": $!\n"; - print REF <<EOF; -<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN"> - -<!-- BEGINFRONTTAG: The following is front matter for the parent book --> -$front -<!-- ENDFRONTTAG: End front matter --> - -$refdata -EOF - $refdata = ""; - } - - # Extraction - if($mode == 1){ - chomp $_; - $front = "$front<!-- $_ -->\n"; - } - elsif($mode == 2){ - $refdata = "$refdata$_"; - } - elsif($mode == 3){ - # There are some fixups which need to be applied - if(/<\/refmeta>/){ - print REF "<manvolnum>9</manvolnum>\n"; - } - if(/<\/refentry>/){ - print REF <<EOF; -<refsect1><title>About this document - -This documentation was generated with kernel version $ARGV[2]. - - -EOF - } - - # For some reason, we title the synopsis twice in the main DocBook - if(! /Synopsis<\/title>/){ - if(/<refentrytitle>/){ - s/struct //; - s/typedef //; - } - - print REF "$_"; - } - } - - # Ending modes - if(/<\/bookinfo>/ || /<\/docinfo>/){ - $mode = 0; - } - elsif(/<\/refentry>/){ - $mode = 0; - close REF; - } -} - -# And make sure we don't process this unnessesarily -$ARGV[0] =~ s/\.sgml/.9/; -`touch $ARGV[0]`; diff --git a/security/commoncap.c b/security/commoncap.c index 3668690ad..98114af88 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 = suid_dumpable; + current->mm->dumpable = 0; if (unsafe & ~LSM_UNSAFE_PTRACE_CAP) { if (!capable(CAP_SETUID)) { @@ -311,87 +311,19 @@ void cap_task_reparent_to_init (struct task_struct *p) int cap_syslog (int type) { - if ((type != 3 && type != 10) && !capable(CAP_SYS_ADMIN)) + if ((type != 3 && type != 10) && + !capable(CAP_SYS_ADMIN) && !vx_ccaps(VXC_SYSLOG)) return -EPERM; return 0; } -/* - * Check that a process has enough memory to allocate a new virtual - * mapping. 0 means there is enough memory for the allocation to - * succeed and -ENOMEM implies there is not. - * - * We currently support three overcommit policies, which are set via the - * vm.overcommit_memory sysctl. See Documentation/vm/overcommit-accounting - * - * Strict overcommit modes added 2002 Feb 26 by Alan Cox. - * Additional code 2002 Jul 20 by Robert Love. - */ int cap_vm_enough_memory(long pages) { - unsigned long free, allowed; - - vm_acct_memory(pages); - - /* - * Sometimes we want to use more memory than we have - */ - if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS) - return 0; - - if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) { - unsigned long n; - - free = get_page_cache_size(); - free += nr_swap_pages; - - /* - * Any slabs which are created with the - * SLAB_RECLAIM_ACCOUNT flag claim to have contents - * which are reclaimable, under pressure. The dentry - * cache and most inode caches should fall into this - */ - free += atomic_read(&slab_reclaim_pages); - - /* - * Leave the last 3% for root - */ - if (!capable(CAP_SYS_ADMIN)) - free -= free / 32; - - if (free > pages) - return 0; - - /* - * nr_free_pages() is very expensive on large systems, - * only call if we're about to fail. - */ - n = nr_free_pages(); - if (!capable(CAP_SYS_ADMIN)) - n -= n / 32; - free += n; - - if (free > pages) - return 0; - vm_unacct_memory(pages); - return -ENOMEM; - } - - allowed = (totalram_pages - hugetlb_total_pages()) - * sysctl_overcommit_ratio / 100; - /* - * Leave the last 3% for root - */ - if (!capable(CAP_SYS_ADMIN)) - allowed -= allowed / 32; - allowed += total_swap_pages; - - if (atomic_read(&vm_committed_space) < allowed) - return 0; - - vm_unacct_memory(pages); + int cap_sys_admin = 0; - return -ENOMEM; + if (cap_capable(current, CAP_SYS_ADMIN) == 0) + cap_sys_admin = 1; + return __vm_enough_memory(pages, cap_sys_admin); } EXPORT_SYMBOL(cap_capable); diff --git a/security/dummy.c b/security/dummy.c index 628de3506..b32eff146 100644 --- a/security/dummy.c +++ b/security/dummy.c @@ -74,11 +74,8 @@ static int dummy_acct (struct file *file) static int dummy_capable (struct task_struct *tsk, int cap) { - if (cap_is_fs_cap (cap) ? tsk->fsuid == 0 : tsk->euid == 0) - /* capability granted */ + if (cap_raised (tsk->cap_effective, cap)) return 0; - - /* capability denied */ return -EPERM; } @@ -92,7 +89,7 @@ static int dummy_quotactl (int cmds, int type, int id, struct super_block *sb) return 0; } -static int dummy_quota_on (struct file *f) +static int dummy_quota_on (struct dentry *dentry) { return 0; } @@ -111,61 +108,13 @@ static int dummy_settime(struct timespec *ts, struct timezone *tz) return 0; } -/* - * Check that a process has enough memory to allocate a new virtual - * mapping. 0 means there is enough memory for the allocation to - * succeed and -ENOMEM implies there is not. - * - * We currently support three overcommit policies, which are set via the - * vm.overcommit_memory sysctl. See Documentation/vm/overcommit-accounting - */ static int dummy_vm_enough_memory(long pages) { - unsigned long free, allowed; - - vm_acct_memory(pages); - - /* - * Sometimes we want to use more memory than we have - */ - if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS) - return 0; - - if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) { - free = get_page_cache_size(); - free += nr_free_pages(); - free += nr_swap_pages; - - /* - * Any slabs which are created with the - * SLAB_RECLAIM_ACCOUNT flag claim to have contents - * which are reclaimable, under pressure. The dentry - * cache and most inode caches should fall into this - */ - free += atomic_read(&slab_reclaim_pages); - - /* - * Leave the last 3% for root - */ - if (current->euid) - free -= free / 32; - - if (free > pages) - return 0; - vm_unacct_memory(pages); - return -ENOMEM; - } + int cap_sys_admin = 0; - allowed = (totalram_pages - hugetlb_total_pages()) - * sysctl_overcommit_ratio / 100; - allowed += total_swap_pages; - - if (atomic_read(&vm_committed_space) < allowed) - return 0; - - vm_unacct_memory(pages); - - return -ENOMEM; + if (dummy_capable(current, CAP_SYS_ADMIN) == 0) + cap_sys_admin = 1; + return __vm_enough_memory(pages, cap_sys_admin); } static int dummy_bprm_alloc_security (struct linux_binprm *bprm) @@ -181,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 = suid_dumpable; + current->mm->dumpable = 0; if ((unsafe & ~LSM_UNSAFE_PTRACE_CAP) && !capable(CAP_SETUID)) { bprm->e_uid = current->uid; @@ -191,6 +140,13 @@ static void dummy_bprm_apply_creds (struct linux_binprm *bprm, int unsafe) current->suid = current->euid = current->fsuid = bprm->e_uid; current->sgid = current->egid = current->fsgid = bprm->e_gid; + + dummy_capget(current, ¤t->cap_effective, ¤t->cap_inheritable, ¤t->cap_permitted); +} + +static void dummy_bprm_post_apply_creds (struct linux_binprm *bprm) +{ + return; } static int dummy_bprm_set_security (struct linux_binprm *bprm) @@ -490,13 +446,16 @@ static int dummy_file_ioctl (struct file *file, unsigned int command, return 0; } -static int dummy_file_mmap (struct file *file, unsigned long prot, +static int dummy_file_mmap (struct file *file, unsigned long reqprot, + unsigned long prot, unsigned long flags) { return 0; } -static int dummy_file_mprotect (struct vm_area_struct *vma, unsigned long prot) +static int dummy_file_mprotect (struct vm_area_struct *vma, + unsigned long reqprot, + unsigned long prot) { return 0; } @@ -550,6 +509,7 @@ static int dummy_task_setuid (uid_t id0, uid_t id1, uid_t id2, int flags) static int dummy_task_post_setuid (uid_t id0, uid_t id1, uid_t id2, int flags) { + dummy_capget(current, ¤t->cap_effective, ¤t->cap_inheritable, ¤t->cap_permitted); return 0; } @@ -728,10 +688,7 @@ static int dummy_sem_semop (struct sem_array *sma, static int dummy_netlink_send (struct sock *sk, struct sk_buff *skb) { - if (current->euid == 0) - cap_raise (NETLINK_CB (skb).eff_cap, CAP_NET_ADMIN); - else - NETLINK_CB (skb).eff_cap = 0; + NETLINK_CB(skb).eff_cap = current->cap_effective; return 0; } @@ -908,6 +865,7 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, bprm_alloc_security); set_to_dummy_if_null(ops, bprm_free_security); set_to_dummy_if_null(ops, bprm_apply_creds); + set_to_dummy_if_null(ops, bprm_post_apply_creds); set_to_dummy_if_null(ops, bprm_set_security); set_to_dummy_if_null(ops, bprm_check_security); set_to_dummy_if_null(ops, bprm_secureexec); diff --git a/security/security.c b/security/security.c index 4e9c19874..b45766441 100644 --- a/security/security.c +++ b/security/security.c @@ -38,8 +38,8 @@ static inline int verify(struct security_operations *ops) static void __init do_security_initcalls(void) { initcall_t *call; - call = &__security_initcall_start; - while (call < &__security_initcall_end) { + call = __security_initcall_start; + while (call < __security_initcall_end) { (*call) (); call++; } diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig index 5620fe924..b59582b92 100644 --- a/security/selinux/Kconfig +++ b/security/selinux/Kconfig @@ -1,6 +1,6 @@ config SECURITY_SELINUX bool "NSA SELinux Support" - depends on SECURITY && NET + depends on SECURITY && NET && INET default n help This selects NSA Security-Enhanced Linux (SELinux). @@ -34,7 +34,7 @@ config SECURITY_SELINUX_BOOTPARAM_VALUE 'selinux', which allows SELinux to be disabled at boot. If this option is set to 0 (zero), the SELinux kernel parameter will default to 0, disabling SELinux at bootup. If this option is - set to 1 (one), the SELinux kernel paramater will default to 1, + set to 1 (one), the SELinux kernel parameter will default to 1, enabling SELinux at bootup. If you are unsure how to answer this question, answer 1. @@ -75,13 +75,23 @@ config SECURITY_SELINUX_AVC_STATS This option collects access vector cache statistics to /selinux/avc/cache_stats, which may be monitored via tools such as avcstat. - -config SECURITY_SELINUX_MLS - bool "NSA SELinux MLS policy (EXPERIMENTAL)" - depends on SECURITY_SELINUX && EXPERIMENTAL - default n + +config SECURITY_SELINUX_CHECKREQPROT_VALUE + int "NSA SELinux checkreqprot default value" + depends on SECURITY_SELINUX + range 0 1 + default 1 help - This enables the NSA SELinux Multi-Level Security (MLS) policy in - addition to the default RBAC/TE policy. This policy is - experimental and has not been configured for use. Unless you - specifically want to experiment with MLS, say N. + This option sets the default value for the 'checkreqprot' flag + that determines whether SELinux checks the protection requested + by the application or the protection that will be applied by the + kernel (including any implied execute for read-implies-exec) for + mmap and mprotect calls. If this option is set to 0 (zero), + SELinux will default to checking the protection that will be applied + by the kernel. If this option is set to 1 (one), SELinux will + default to checking the protection requested by the application. + The checkreqprot flag may be changed from the default via the + 'checkreqprot=' boot parameter. It may also be changed at runtime + via /selinux/checkreqprot if authorized by policy. + + If you are unsure how to answer this question, answer 1. diff --git a/security/selinux/avc.c b/security/selinux/avc.c index c09e52932..2d088bb65 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -31,13 +31,44 @@ #include <net/ipv6.h> #include "avc.h" #include "avc_ss.h" + +static const struct av_perm_to_string +{ + u16 tclass; + u32 value; + const char *name; +} av_perm_to_string[] = { +#define S_(c, v, s) { c, v, s }, +#include "av_perm_to_string.h" +#undef S_ +}; + #ifdef CONFIG_AUDIT +static const char *class_to_string[] = { +#define S_(s) s, #include "class_to_string.h" +#undef S_ +}; #endif + +#define TB_(s) static const char * s [] = { +#define TE_(s) }; +#define S_(s) s, #include "common_perm_to_string.h" +#undef TB_ +#undef TE_ +#undef S_ + +static const struct av_inherit +{ + u16 tclass; + const char **common_pts; + u32 common_base; +} av_inherit[] = { +#define S_(c, i, b) { c, common_##i##_perm_to_string, b }, #include "av_inherit.h" -#include "av_perm_to_string.h" -#include "objsec.h" +#undef S_ +}; #define AVC_CACHE_SLOTS 512 #define AVC_DEF_CACHE_THRESHOLD 512 @@ -108,9 +139,9 @@ static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass) * @tclass: target security class * @av: access vector */ -void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av) +static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av) { - char **common_pts = NULL; + const char **common_pts = NULL; u32 common_base = 0; int i, i2, perm; @@ -131,8 +162,10 @@ void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av) i = 0; perm = 1; while (perm < common_base) { - if (perm & av) + if (perm & av) { audit_log_format(ab, " %s", common_pts[i]); + av &= ~perm; + } i++; perm <<= 1; } @@ -144,14 +177,19 @@ void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av) (av_perm_to_string[i2].value == perm)) break; } - if (i2 < ARRAY_SIZE(av_perm_to_string)) + if (i2 < ARRAY_SIZE(av_perm_to_string)) { audit_log_format(ab, " %s", av_perm_to_string[i2].name); + av &= ~perm; + } } i++; perm <<= 1; } + if (av) + audit_log_format(ab, " 0x%x", av); + audit_log_format(ab, " }"); } @@ -161,7 +199,7 @@ void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av) * @tsid: target security identifier * @tclass: target security class */ -void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tclass) +static void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tclass) { int rc; char *scontext; @@ -196,15 +234,15 @@ void __init avc_init(void) for (i = 0; i < AVC_CACHE_SLOTS; i++) { INIT_LIST_HEAD(&avc_cache.slots[i]); - avc_cache.slots_lock[i] = SPIN_LOCK_UNLOCKED; + spin_lock_init(&avc_cache.slots_lock[i]); } atomic_set(&avc_cache.active_nodes, 0); atomic_set(&avc_cache.lru_hint, 0); - + 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, GFP_KERNEL, AUDIT_KERNEL, "AVC INITIALIZED\n"); } int avc_get_hash_stats(char *page) @@ -296,17 +334,17 @@ out: static struct avc_node *avc_alloc_node(void) { struct avc_node *node; - + node = kmem_cache_alloc(avc_node_cachep, SLAB_ATOMIC); if (!node) goto out; - + memset(node, 0, sizeof(*node)); INIT_RCU_HEAD(&node->rhead); INIT_LIST_HEAD(&node->list); atomic_set(&node->ae.used, 1); avc_cache_stats_incr(allocations); - + if (atomic_inc_return(&avc_cache.active_nodes) > avc_cache_threshold) avc_reclaim_node(); @@ -384,7 +422,7 @@ out: static int avc_latest_notif_update(int seqno, int is_insert) { int ret = 0; - static spinlock_t notif_lock = SPIN_LOCK_UNLOCKED; + static DEFINE_SPINLOCK(notif_lock); unsigned long flag; spin_lock_irqsave(¬if_lock, flag); @@ -512,7 +550,7 @@ void avc_audit(u32 ssid, u32 tsid, return; } - ab = audit_log_start(current->audit_context); + ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_AVC); if (!ab) return; /* audit_panic has been called */ audit_log_format(ab, "avc: %s ", denied ? "denied" : "granted"); @@ -521,33 +559,8 @@ void avc_audit(u32 ssid, u32 tsid, if (a && a->tsk) tsk = a->tsk; if (tsk && tsk->pid) { - struct mm_struct *mm; - struct vm_area_struct *vma; - audit_log_format(ab, " pid=%d", tsk->pid); - if (tsk == current) - mm = current->mm; - else - mm = get_task_mm(tsk); - if (mm) { - if (down_read_trylock(&mm->mmap_sem)) { - vma = mm->mmap; - while (vma) { - if ((vma->vm_flags & VM_EXECUTABLE) && - vma->vm_file) { - audit_log_d_path(ab, "exe=", - vma->vm_file->f_dentry, - vma->vm_file->f_vfsmnt); - break; - } - vma = vma->vm_next; - } - up_read(&mm->mmap_sem); - } - if (tsk != current) - mmput(mm); - } else { - audit_log_format(ab, " comm=%s", tsk->comm); - } + audit_log_format(ab, " pid=%d comm=", tsk->pid); + audit_log_untrustedstring(ab, tsk->comm); } if (a) { switch (a->type) { @@ -560,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); } } @@ -592,7 +602,7 @@ void avc_audit(u32 ssid, u32 tsid, switch (sk->sk_family) { case AF_INET: { - struct inet_opt *inet = inet_sk(sk); + struct inet_sock *inet = inet_sk(sk); avc_print_ipv4_addr(ab, inet->rcv_saddr, inet->sport, @@ -603,7 +613,7 @@ void avc_audit(u32 ssid, u32 tsid, break; } case AF_INET6: { - struct inet_opt *inet = inet_sk(sk); + struct inet_sock *inet = inet_sk(sk); struct ipv6_pinfo *inet6 = inet6_sk(sk); avc_print_ipv6_addr(ab, &inet6->rcv_saddr, @@ -617,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; } } @@ -717,7 +725,7 @@ static inline int avc_sidcmp(u32 x, u32 y) * @event : Updating event * @perms : Permission mask bits * @ssid,@tsid,@tclass : identifier of an AVC entry - * + * * if a valid AVC entry doesn't exist,this function returns -ENOENT. * if kmalloc() called internal returns NULL, this function returns -ENOMEM. * otherwise, this function update the AVC entry. The original AVC-entry object @@ -759,7 +767,7 @@ static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass) */ avc_node_populate(node, ssid, tsid, tclass, &orig->ae); - + switch (event) { case AVC_CALLBACK_GRANT: node->ae.avd.allowed |= perms; @@ -788,136 +796,6 @@ out: return rc; } -static int avc_update_cache(u32 event, u32 ssid, u32 tsid, - u16 tclass, u32 perms) -{ - struct avc_node *node; - int i; - - rcu_read_lock(); - - if (ssid == SECSID_WILD || tsid == SECSID_WILD) { - /* apply to all matching nodes */ - for (i = 0; i < AVC_CACHE_SLOTS; i++) { - list_for_each_entry_rcu(node, &avc_cache.slots[i], list) { - if (avc_sidcmp(ssid, node->ae.ssid) && - avc_sidcmp(tsid, node->ae.tsid) && - tclass == node->ae.tclass ) { - avc_update_node(event, perms, node->ae.ssid, - node->ae.tsid, node->ae.tclass); - } - } - } - } else { - /* apply to one node */ - avc_update_node(event, perms, ssid, tsid, tclass); - } - - rcu_read_unlock(); - - return 0; -} - -static int avc_control(u32 event, u32 ssid, u32 tsid, - u16 tclass, u32 perms, - u32 seqno, u32 *out_retained) -{ - struct avc_callback_node *c; - u32 tretained = 0, cretained = 0; - int rc = 0; - - /* - * try_revoke only removes permissions from the cache - * state if they are not retained by the object manager. - * Hence, try_revoke must wait until after the callbacks have - * been invoked to update the cache state. - */ - if (event != AVC_CALLBACK_TRY_REVOKE) - avc_update_cache(event,ssid,tsid,tclass,perms); - - for (c = avc_callbacks; c; c = c->next) - { - if ((c->events & event) && - avc_sidcmp(c->ssid, ssid) && - avc_sidcmp(c->tsid, tsid) && - c->tclass == tclass && - (c->perms & perms)) { - cretained = 0; - rc = c->callback(event, ssid, tsid, tclass, - (c->perms & perms), - &cretained); - if (rc) - goto out; - tretained |= cretained; - } - } - - if (event == AVC_CALLBACK_TRY_REVOKE) { - /* revoke any unretained permissions */ - perms &= ~tretained; - avc_update_cache(event,ssid,tsid,tclass,perms); - *out_retained = tretained; - } - - avc_latest_notif_update(seqno, 0); - -out: - return rc; -} - -/** - * avc_ss_grant - Grant previously denied permissions. - * @ssid: source security identifier or %SECSID_WILD - * @tsid: target security identifier or %SECSID_WILD - * @tclass: target security class - * @perms: permissions to grant - * @seqno: policy sequence number - */ -int avc_ss_grant(u32 ssid, u32 tsid, u16 tclass, - u32 perms, u32 seqno) -{ - return avc_control(AVC_CALLBACK_GRANT, - ssid, tsid, tclass, perms, seqno, NULL); -} - -/** - * avc_ss_try_revoke - Try to revoke previously granted permissions. - * @ssid: source security identifier or %SECSID_WILD - * @tsid: target security identifier or %SECSID_WILD - * @tclass: target security class - * @perms: permissions to grant - * @seqno: policy sequence number - * @out_retained: subset of @perms that are retained - * - * Try to revoke previously granted permissions, but - * only if they are not retained as migrated permissions. - * Return the subset of permissions that are retained via @out_retained. - */ -int avc_ss_try_revoke(u32 ssid, u32 tsid, u16 tclass, - u32 perms, u32 seqno, u32 *out_retained) -{ - return avc_control(AVC_CALLBACK_TRY_REVOKE, - ssid, tsid, tclass, perms, seqno, out_retained); -} - -/** - * avc_ss_revoke - Revoke previously granted permissions. - * @ssid: source security identifier or %SECSID_WILD - * @tsid: target security identifier or %SECSID_WILD - * @tclass: target security class - * @perms: permissions to grant - * @seqno: policy sequence number - * - * Revoke previously granted permissions, even if - * they are retained as migrated permissions. - */ -int avc_ss_revoke(u32 ssid, u32 tsid, u16 tclass, - u32 perms, u32 seqno) -{ - return avc_control(AVC_CALLBACK_REVOKE, - ssid, tsid, tclass, perms, seqno, NULL); -} - /** * avc_ss_reset - Flush the cache and revalidate migrated permissions. * @seqno: policy sequence number @@ -950,46 +828,6 @@ out: return rc; } -/** - * avc_ss_set_auditallow - Enable or disable auditing of granted permissions. - * @ssid: source security identifier or %SECSID_WILD - * @tsid: target security identifier or %SECSID_WILD - * @tclass: target security class - * @perms: permissions to grant - * @seqno: policy sequence number - * @enable: enable flag. - */ -int avc_ss_set_auditallow(u32 ssid, u32 tsid, u16 tclass, - u32 perms, u32 seqno, u32 enable) -{ - if (enable) - return avc_control(AVC_CALLBACK_AUDITALLOW_ENABLE, - ssid, tsid, tclass, perms, seqno, NULL); - else - return avc_control(AVC_CALLBACK_AUDITALLOW_DISABLE, - ssid, tsid, tclass, perms, seqno, NULL); -} - -/** - * avc_ss_set_auditdeny - Enable or disable auditing of denied permissions. - * @ssid: source security identifier or %SECSID_WILD - * @tsid: target security identifier or %SECSID_WILD - * @tclass: target security class - * @perms: permissions to grant - * @seqno: policy sequence number - * @enable: enable flag. - */ -int avc_ss_set_auditdeny(u32 ssid, u32 tsid, u16 tclass, - u32 perms, u32 seqno, u32 enable) -{ - if (enable) - return avc_control(AVC_CALLBACK_AUDITDENY_ENABLE, - ssid, tsid, tclass, perms, seqno, NULL); - else - return avc_control(AVC_CALLBACK_AUDITDENY_DISABLE, - ssid, tsid, tclass, perms, seqno, NULL); -} - /** * avc_has_perm_noaudit - Check permissions but perform no auditing. * @ssid: source security identifier @@ -1045,7 +883,7 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, avc_update_node(AVC_CALLBACK_GRANT,requested, ssid,tsid,tclass); } - + rcu_read_unlock(); out: return rc; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 4b41310c1..b5220a266 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -10,6 +10,8 @@ * * Copyright (C) 2001,2002 Networks Associates Technology, Inc. * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com> + * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. + * <dgoeddel@trustedcs.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, @@ -65,6 +67,7 @@ #include <linux/hugetlb.h> #include <linux/personality.h> #include <linux/sysctl.h> +#include <linux/audit.h> #include "avc.h" #include "objsec.h" @@ -73,7 +76,7 @@ #define XATTR_SELINUX_SUFFIX "selinux" #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX -extern int policydb_loaded_version; +extern unsigned int policydb_loaded_version; extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); #ifdef CONFIG_SECURITY_SELINUX_DEVELOP @@ -110,7 +113,7 @@ static struct security_operations *secondary_ops = NULL; /* Lists of inode and superblock security structures initialized before the policy was loaded. */ static LIST_HEAD(superblock_security_head); -static spinlock_t sb_security_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(sb_security_lock); /* Allocate and free functions for each kind of security blob. */ @@ -589,7 +592,8 @@ next_inode: spin_unlock(&sbsec->isec_lock); inode = igrab(inode); if (inode) { - inode_doinit(inode); + if (!IS_PRIVATE (inode)) + inode_doinit(inode); iput(inode); } spin_lock(&sbsec->isec_lock); @@ -668,6 +672,8 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc return SECCLASS_NETLINK_IP6FW_SOCKET; case NETLINK_DNRTMSG: return SECCLASS_NETLINK_DNRT_SOCKET; + case NETLINK_KOBJECT_UEVENT: + return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET; default: return SECCLASS_NETLINK_SOCKET; } @@ -826,7 +832,9 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent __FUNCTION__, context, -rc, inode->i_sb->s_id, inode->i_ino); kfree(context); - goto out; + /* Leave with the unlabeled SID */ + rc = 0; + break; } } kfree(context); @@ -871,18 +879,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent isec->initialized = 1; out: - if (inode->i_sock) { - struct socket *sock = SOCKET_I(inode); - if (sock->sk) { - isec->sclass = socket_type_to_security_class(sock->sk->sk_family, - sock->sk->sk_type, - sock->sk->sk_protocol); - } else { - isec->sclass = SECCLASS_SOCKET; - } - } else { + if (isec->sclass == SECCLASS_FILE) isec->sclass = inode_mode_to_security_class(inode->i_mode); - } if (hold_sem) up(&isec->sem); @@ -918,9 +916,9 @@ static inline u32 signal_to_av(int sig) /* Check permission betweeen a pair of tasks, e.g. signal checks, fork check, ptrace check, etc. */ -int task_has_perm(struct task_struct *tsk1, - struct task_struct *tsk2, - u32 perms) +static int task_has_perm(struct task_struct *tsk1, + struct task_struct *tsk2, + u32 perms) { struct task_security_struct *tsec1, *tsec2; @@ -931,8 +929,8 @@ int task_has_perm(struct task_struct *tsk1, } /* Check whether a task is allowed to use a capability. */ -int task_has_capability(struct task_struct *tsk, - int cap) +static int task_has_capability(struct task_struct *tsk, + int cap) { struct task_security_struct *tsec; struct avc_audit_data ad; @@ -948,8 +946,8 @@ int task_has_capability(struct task_struct *tsk, } /* Check whether a task is allowed to use a system operation. */ -int task_has_system(struct task_struct *tsk, - u32 perms) +static int task_has_system(struct task_struct *tsk, + u32 perms) { struct task_security_struct *tsec; @@ -962,10 +960,10 @@ int task_has_system(struct task_struct *tsk, /* Check whether a task has a particular permission to an inode. The 'adp' parameter is optional and allows other audit data to be passed (e.g. the dentry). */ -int inode_has_perm(struct task_struct *tsk, - struct inode *inode, - u32 perms, - struct avc_audit_data *adp) +static int inode_has_perm(struct task_struct *tsk, + struct inode *inode, + u32 perms, + struct avc_audit_data *adp) { struct task_security_struct *tsec; struct inode_security_struct *isec; @@ -1187,10 +1185,10 @@ static inline int may_rename(struct inode *old_dir, } /* Check whether a task can perform a filesystem operation. */ -int superblock_has_perm(struct task_struct *tsk, - struct super_block *sb, - u32 perms, - struct avc_audit_data *ad) +static int superblock_has_perm(struct task_struct *tsk, + struct super_block *sb, + u32 perms, + struct avc_audit_data *ad) { struct task_security_struct *tsec; struct superblock_security_struct *sbsec; @@ -1247,7 +1245,7 @@ static inline u32 file_to_av(struct file *file) } /* Set an inode's SID to a specified value. */ -int inode_security_set_sid(struct inode *inode, u32 sid) +static int inode_security_set_sid(struct inode *inode, u32 sid) { struct inode_security_struct *isec = inode->i_security; struct superblock_security_struct *sbsec = inode->i_sb->s_security; @@ -1390,12 +1388,6 @@ static int selinux_capset_check(struct task_struct *target, kernel_cap_t *effect static void selinux_capset_set(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted) { - int error; - - error = task_has_perm(current, target, PROCESS__SETCAP); - if (error) - return; - secondary_ops->capset_set(target, effective, inheritable, permitted); } @@ -1481,9 +1473,9 @@ static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb) return rc; } -static int selinux_quota_on(struct file *f) +static int selinux_quota_on(struct dentry *dentry) { - return file_has_perm(current, f, FILE__QUOTAON); + return dentry_has_perm(current, NULL, dentry, FILE__QUOTAON); } static int selinux_syslog(int type) @@ -1521,69 +1513,29 @@ static int selinux_syslog(int type) * mapping. 0 means there is enough memory for the allocation to * succeed and -ENOMEM implies there is not. * - * We currently support three overcommit policies, which are set via the - * vm.overcommit_memory sysctl. See Documentation/vm/overcommit-accounting + * Note that secondary_ops->capable and task_has_perm_noaudit return 0 + * if the capability is granted, but __vm_enough_memory requires 1 if + * the capability is granted. * - * Strict overcommit modes added 2002 Feb 26 by Alan Cox. - * Additional code 2002 Jul 20 by Robert Love. + * Do not audit the selinux permission check, as this is applied to all + * processes that allocate mappings. */ static int selinux_vm_enough_memory(long pages) { - unsigned long free, allowed; - int rc; + int rc, cap_sys_admin = 0; struct task_security_struct *tsec = current->security; - vm_acct_memory(pages); - - /* - * Sometimes we want to use more memory than we have - */ - if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS) - return 0; - - if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) { - free = get_page_cache_size(); - free += nr_free_pages(); - free += nr_swap_pages; - - /* - * Any slabs which are created with the - * SLAB_RECLAIM_ACCOUNT flag claim to have contents - * which are reclaimable, under pressure. The dentry - * cache and most inode caches should fall into this - */ - free += atomic_read(&slab_reclaim_pages); - - /* - * Leave the last 3% for privileged processes. - * Don't audit the check, as it is applied to all processes - * that allocate mappings. - */ - rc = secondary_ops->capable(current, CAP_SYS_ADMIN); - if (!rc) { - rc = avc_has_perm_noaudit(tsec->sid, tsec->sid, - SECCLASS_CAPABILITY, - CAP_TO_MASK(CAP_SYS_ADMIN), NULL); - } - if (rc) - free -= free / 32; - - if (free > pages) - return 0; - vm_unacct_memory(pages); - return -ENOMEM; - } - - allowed = (totalram_pages - hugetlb_total_pages()) - * sysctl_overcommit_ratio / 100; - allowed += total_swap_pages; - - if (atomic_read(&vm_committed_space) < allowed) - return 0; + rc = secondary_ops->capable(current, CAP_SYS_ADMIN); + if (rc == 0) + rc = avc_has_perm_noaudit(tsec->sid, tsec->sid, + SECCLASS_CAPABILITY, + CAP_TO_MASK(CAP_SYS_ADMIN), + NULL); - vm_unacct_memory(pages); + if (rc == 0) + cap_sys_admin = 1; - return -ENOMEM; + return __vm_enough_memory(pages, cap_sys_admin); } /* binprm security operations */ @@ -1801,10 +1753,7 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) struct task_security_struct *tsec; struct bprm_security_struct *bsec; u32 sid; - struct av_decision avd; - struct itimerval itimer; - struct rlimit *rlim, *initrlim; - int rc, i; + int rc; secondary_ops->bprm_apply_creds(bprm, unsafe); @@ -1814,91 +1763,108 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) sid = bsec->sid; tsec->osid = tsec->sid; + bsec->unsafe = 0; if (tsec->sid != sid) { /* Check for shared state. If not ok, leave SID unchanged and kill. */ if (unsafe & LSM_UNSAFE_SHARE) { - rc = avc_has_perm_noaudit(tsec->sid, sid, - SECCLASS_PROCESS, PROCESS__SHARE, &avd); + rc = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS, + PROCESS__SHARE, NULL); if (rc) { - task_unlock(current); - avc_audit(tsec->sid, sid, SECCLASS_PROCESS, - PROCESS__SHARE, &avd, rc, NULL); - force_sig_specific(SIGKILL, current); - goto lock_out; + bsec->unsafe = 1; + return; } } /* Check for ptracing, and update the task SID if ok. Otherwise, leave SID unchanged and kill. */ if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) { - rc = avc_has_perm_noaudit(tsec->ptrace_sid, sid, - SECCLASS_PROCESS, PROCESS__PTRACE, &avd); - if (!rc) - tsec->sid = sid; - task_unlock(current); - avc_audit(tsec->ptrace_sid, sid, SECCLASS_PROCESS, - PROCESS__PTRACE, &avd, rc, NULL); + rc = avc_has_perm(tsec->ptrace_sid, sid, + SECCLASS_PROCESS, PROCESS__PTRACE, + NULL); if (rc) { - force_sig_specific(SIGKILL, current); - goto lock_out; + bsec->unsafe = 1; + return; } - } else { - tsec->sid = sid; - task_unlock(current); - } - - /* Close files for which the new task SID is not authorized. */ - flush_unauthorized_files(current->files); - - /* Check whether the new SID can inherit signal state - from the old SID. If not, clear itimers to avoid - subsequent signal generation and flush and unblock - signals. This must occur _after_ the task SID has - been updated so that any kill done after the flush - will be checked against the new SID. */ - rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS, - PROCESS__SIGINH, NULL); - if (rc) { - memset(&itimer, 0, sizeof itimer); - for (i = 0; i < 3; i++) - do_setitimer(i, &itimer, NULL); - flush_signals(current); - spin_lock_irq(¤t->sighand->siglock); - flush_signal_handlers(current, 1); - sigemptyset(¤t->blocked); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); } + tsec->sid = sid; + } +} - /* Check whether the new SID can inherit resource limits - from the old SID. If not, reset all soft limits to - the lower of the current task's hard limit and the init - task's soft limit. Note that the setting of hard limits - (even to lower them) can be controlled by the setrlimit - check. The inclusion of the init task's soft limit into - the computation is to avoid resetting soft limits higher - than the default soft limit for cases where the default - is lower than the hard limit, e.g. RLIMIT_CORE or - RLIMIT_STACK.*/ - rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS, - PROCESS__RLIMITINH, NULL); - if (rc) { - for (i = 0; i < RLIM_NLIMITS; i++) { - rlim = current->signal->rlim + i; - initrlim = init_task.signal->rlim+i; - rlim->rlim_cur = min(rlim->rlim_max,initrlim->rlim_cur); - } - } +/* + * called after apply_creds without the task lock held + */ +static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm) +{ + struct task_security_struct *tsec; + struct rlimit *rlim, *initrlim; + struct itimerval itimer; + struct bprm_security_struct *bsec; + int rc, i; - /* Wake up the parent if it is waiting so that it can - recheck wait permission to the new task SID. */ - wake_up_interruptible(¤t->parent->wait_chldexit); + tsec = current->security; + bsec = bprm->security; -lock_out: - task_lock(current); + if (bsec->unsafe) { + force_sig_specific(SIGKILL, current); return; } + if (tsec->osid == tsec->sid) + return; + + /* Close files for which the new task SID is not authorized. */ + flush_unauthorized_files(current->files); + + /* Check whether the new SID can inherit signal state + from the old SID. If not, clear itimers to avoid + subsequent signal generation and flush and unblock + signals. This must occur _after_ the task SID has + been updated so that any kill done after the flush + will be checked against the new SID. */ + rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS, + PROCESS__SIGINH, NULL); + if (rc) { + memset(&itimer, 0, sizeof itimer); + for (i = 0; i < 3; i++) + do_setitimer(i, &itimer, NULL); + flush_signals(current); + spin_lock_irq(¤t->sighand->siglock); + flush_signal_handlers(current, 1); + sigemptyset(¤t->blocked); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + } + + /* Check whether the new SID can inherit resource limits + from the old SID. If not, reset all soft limits to + the lower of the current task's hard limit and the init + task's soft limit. Note that the setting of hard limits + (even to lower them) can be controlled by the setrlimit + check. The inclusion of the init task's soft limit into + the computation is to avoid resetting soft limits higher + than the default soft limit for cases where the default + is lower than the hard limit, e.g. RLIMIT_CORE or + RLIMIT_STACK.*/ + rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS, + PROCESS__RLIMITINH, NULL); + if (rc) { + for (i = 0; i < RLIM_NLIMITS; i++) { + rlim = current->signal->rlim + i; + initrlim = init_task.signal->rlim+i; + rlim->rlim_cur = min(rlim->rlim_max,initrlim->rlim_cur); + } + if (current->signal->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) { + /* + * This will cause RLIMIT_CPU calculations + * to be refigured. + */ + current->it_prof_expires = jiffies_to_cputime(1); + } + } + + /* Wake up the parent if it is waiting so that it can + recheck wait permission to the new task SID. */ + wake_up_interruptible(¤t->parent->signal->wait_chldexit); } /* superblock security operations */ @@ -2179,6 +2145,9 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) if (rc) return rc; + if (iattr->ia_valid & ATTR_FORCE) + return 0; + if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_ATIME_SET | ATTR_MTIME_SET)) return dentry_has_perm(current, NULL, dentry, FILE__SETATTR); @@ -2239,6 +2208,11 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value if (rc) return rc; + rc = security_validate_transition(isec->sid, newsid, tsec->sid, + isec->sclass); + if (rc) + return rc; + return avc_has_perm(newsid, sbsec->sid, SECCLASS_FILESYSTEM, @@ -2443,6 +2417,19 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd, static int file_map_prot_check(struct file *file, unsigned long prot, int shared) { +#ifndef CONFIG_PPC32 + if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { + /* + * We are making executable an anonymous mapping or a + * private file mapping that will also be writable. + * This has an additional check. + */ + int rc = task_has_perm(current, current, PROCESS__EXECMEM); + if (rc) + return rc; + } +#endif + if (file) { /* read access is always possible with a mapping */ u32 av = FILE__READ; @@ -2459,27 +2446,49 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared return 0; } -static int selinux_file_mmap(struct file *file, unsigned long prot, unsigned long flags) +static int selinux_file_mmap(struct file *file, unsigned long reqprot, + unsigned long prot, unsigned long flags) { int rc; - rc = secondary_ops->file_mmap(file, prot, flags); + rc = secondary_ops->file_mmap(file, reqprot, prot, flags); if (rc) return rc; + if (selinux_checkreqprot) + prot = reqprot; + return file_map_prot_check(file, prot, (flags & MAP_TYPE) == MAP_SHARED); } static int selinux_file_mprotect(struct vm_area_struct *vma, + unsigned long reqprot, unsigned long prot) { int rc; - rc = secondary_ops->file_mprotect(vma, prot); + rc = secondary_ops->file_mprotect(vma, reqprot, prot); if (rc) return rc; + if (selinux_checkreqprot) + prot = reqprot; + +#ifndef CONFIG_PPC32 + if (vma->vm_file != NULL && vma->anon_vma != NULL && (prot & PROT_EXEC)) { + /* + * We are making executable a file mapping that has + * had some COW done. Since pages might have been written, + * check ability to execute the possibly modified content. + * This typically should only occur for text relocations. + */ + int rc = file_has_perm(current, vma->vm_file, FILE__EXECMOD); + if (rc) + return rc; + } +#endif + return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED); } @@ -2692,16 +2701,7 @@ static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim static int selinux_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp) { - struct task_security_struct *tsec1, *tsec2; - - tsec1 = current->security; - tsec2 = p->security; - - /* No auditing from the setscheduler hook, since the runqueue lock - is held and the system will deadlock if we try to log an audit - message. */ - return avc_has_perm_noaudit(tsec1->sid, tsec2->sid, - SECCLASS_PROCESS, PROCESS__SETSCHED, NULL); + return task_has_perm(current, p, PROCESS__SETSCHED); } static int selinux_task_getscheduler(struct task_struct *p) @@ -2855,8 +2855,7 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, struct avc_audit_data *ad nexthdr = ip6->nexthdr; offset += sizeof(_ipv6h); - offset = ipv6_skip_exthdr(skb, offset, &nexthdr, - skb->tail - skb->head - offset); + offset = ipv6_skip_exthdr(skb, offset, &nexthdr); if (offset < 0) goto out; @@ -2971,18 +2970,15 @@ out: static void selinux_socket_post_create(struct socket *sock, int family, int type, int protocol, int kern) { - int err; struct inode_security_struct *isec; struct task_security_struct *tsec; - err = inode_doinit(SOCK_INODE(sock)); - if (err < 0) - return; isec = SOCK_INODE(sock)->i_security; tsec = current->security; isec->sclass = socket_type_to_security_class(family, type, protocol); isec->sid = kern ? SECINITSID_KERNEL : tsec->sid; + isec->initialized = 1; return; } @@ -3086,7 +3082,53 @@ out: static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) { - return socket_has_perm(current, sock, SOCKET__CONNECT); + struct inode_security_struct *isec; + int err; + + err = socket_has_perm(current, sock, SOCKET__CONNECT); + if (err) + return err; + + /* + * If a TCP socket, check name_connect permission for the port. + */ + isec = SOCK_INODE(sock)->i_security; + if (isec->sclass == SECCLASS_TCP_SOCKET) { + struct sock *sk = sock->sk; + struct avc_audit_data ad; + struct sockaddr_in *addr4 = NULL; + struct sockaddr_in6 *addr6 = NULL; + unsigned short snum; + u32 sid; + + if (sk->sk_family == PF_INET) { + addr4 = (struct sockaddr_in *)address; + if (addrlen != sizeof(struct sockaddr_in)) + return -EINVAL; + snum = ntohs(addr4->sin_port); + } else { + addr6 = (struct sockaddr_in6 *)address; + if (addrlen != sizeof(struct sockaddr_in6)) + return -EINVAL; + snum = ntohs(addr6->sin6_port); + } + + err = security_port_sid(sk->sk_family, sk->sk_type, + sk->sk_protocol, snum, &sid); + if (err) + goto out; + + AVC_AUDIT_DATA_INIT(&ad,NET); + ad.u.net.dport = htons(snum); + ad.u.net.family = sk->sk_family; + err = avc_has_perm(isec->sid, sid, isec->sclass, + TCP_SOCKET__NAME_CONNECT, &ad); + if (err) + goto out; + } + +out: + return err; } static int selinux_socket_listen(struct socket *sock, int backlog) @@ -3104,14 +3146,12 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock) if (err) return err; - err = inode_doinit(SOCK_INODE(newsock)); - if (err < 0) - return err; newisec = SOCK_INODE(newsock)->i_security; isec = SOCK_INODE(sock)->i_security; newisec->sclass = isec->sclass; newisec->sid = isec->sid; + newisec->initialized = 1; return 0; } @@ -3378,6 +3418,15 @@ 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, GFP_KERNEL, AUDIT_SELINUX_ERR, + "SELinux: unrecognized netlink message" + " type=%hu for sclass=%hu\n", + nlh->nlmsg_type, isec->sclass); + if (!selinux_enforcing) + err = 0; + } + /* Ignore */ if (err == -ENOENT) err = 0; @@ -3527,12 +3576,20 @@ static inline int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) { - int err = 0; + struct task_security_struct *tsec; + struct av_decision avd; + int err; - if (capable(CAP_NET_ADMIN)) - cap_raise (NETLINK_CB (skb).eff_cap, CAP_NET_ADMIN); - else - NETLINK_CB(skb).eff_cap = 0; + err = secondary_ops->netlink_send(sk, skb); + if (err) + return err; + + tsec = current->security; + + avd.allowed = 0; + avc_has_perm_noaudit(tsec->sid, tsec->sid, + SECCLASS_CAPABILITY, ~0, &avd); + cap_mask(NETLINK_CB(skb).eff_cap, avd.allowed); if (policydb_loaded_version >= POLICYDB_VERSION_NLCLASS) err = selinux_nlmsg_perm(sk, skb); @@ -3610,7 +3667,7 @@ static void msg_msg_free_security(struct msg_msg *msg) } static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, - u16 sclass, u32 perms) + u32 perms) { struct task_security_struct *tsec; struct ipc_security_struct *isec; @@ -3622,7 +3679,7 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, AVC_AUDIT_DATA_INIT(&ad, IPC); ad.u.ipc_id = ipc_perms->key; - return avc_has_perm(tsec->sid, isec->sid, sclass, perms, &ad); + return avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad); } static int selinux_msg_msg_alloc_security(struct msg_msg *msg) @@ -3707,7 +3764,7 @@ static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd) return 0; } - err = ipc_has_perm(&msq->q_perm, SECCLASS_MSGQ, perms); + err = ipc_has_perm(&msq->q_perm, perms); return err; } @@ -3859,7 +3916,7 @@ static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd) return 0; } - err = ipc_has_perm(&shp->shm_perm, SECCLASS_SHM, perms); + err = ipc_has_perm(&shp->shm_perm, perms); return err; } @@ -3878,7 +3935,7 @@ static int selinux_shm_shmat(struct shmid_kernel *shp, else perms = SHM__READ | SHM__WRITE; - return ipc_has_perm(&shp->shm_perm, SECCLASS_SHM, perms); + return ipc_has_perm(&shp->shm_perm, perms); } /* Semaphore security operations */ @@ -3967,7 +4024,7 @@ static int selinux_sem_semctl(struct sem_array *sma, int cmd) return 0; } - err = ipc_has_perm(&sma->sem_perm, SECCLASS_SEM, perms); + err = ipc_has_perm(&sma->sem_perm, perms); return err; } @@ -3981,18 +4038,13 @@ static int selinux_sem_semop(struct sem_array *sma, else perms = SEM__READ; - return ipc_has_perm(&sma->sem_perm, SECCLASS_SEM, perms); + return ipc_has_perm(&sma->sem_perm, perms); } static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag) { - struct ipc_security_struct *isec = ipcp->security; - u16 sclass = SECCLASS_IPC; u32 av = 0; - if (isec && isec->magic == SELINUX_MAGIC) - sclass = isec->sclass; - av = 0; if (flag & S_IRUGO) av |= IPC__UNIX_READ; @@ -4002,11 +4054,11 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag) if (av == 0) return 0; - return ipc_has_perm(ipcp, sclass, av); + return ipc_has_perm(ipcp, av); } /* module stacking operations */ -int selinux_register_security (const char *name, struct security_operations *ops) +static int selinux_register_security (const char *name, struct security_operations *ops) { if (secondary_ops != original_ops) { printk(KERN_INFO "%s: There is already a secondary security " @@ -4023,7 +4075,7 @@ int selinux_register_security (const char *name, struct security_operations *ops return 0; } -int selinux_unregister_security (const char *name, struct security_operations *ops) +static int selinux_unregister_security (const char *name, struct security_operations *ops) { if (ops != secondary_ops) { printk (KERN_INFO "%s: trying to unregister a security module " @@ -4093,11 +4145,11 @@ static int selinux_setprocattr(struct task_struct *p, struct task_security_struct *tsec; u32 sid = 0; int error; + char *str = value; - if (current != p || !strcmp(name, "current")) { + if (current != p) { /* SELinux only allows a process to change its own - security attributes, and it only allows the process - current SID to change via exec. */ + security attributes. */ return -EACCES; } @@ -4110,14 +4162,19 @@ static int selinux_setprocattr(struct task_struct *p, error = task_has_perm(current, p, PROCESS__SETEXEC); else if (!strcmp(name, "fscreate")) error = task_has_perm(current, p, PROCESS__SETFSCREATE); + else if (!strcmp(name, "current")) + error = task_has_perm(current, p, PROCESS__SETCURRENT); else error = -EINVAL; if (error) return error; /* Obtain a SID for the context, if one was specified. */ - if (size) { - int error; + if (size && str[1] && str[1] != '\n') { + if (str[size-1] == '\n') { + str[size-1] = 0; + size--; + } error = security_context_to_sid(value, size, &sid); if (error) return error; @@ -4134,13 +4191,58 @@ static int selinux_setprocattr(struct task_struct *p, tsec->exec_sid = sid; else if (!strcmp(name, "fscreate")) tsec->create_sid = sid; + else if (!strcmp(name, "current")) { + struct av_decision avd; + + if (sid == 0) + return -EINVAL; + + /* Only allow single threaded processes to change context */ + if (atomic_read(&p->mm->mm_users) != 1) { + struct task_struct *g, *t; + struct mm_struct *mm = p->mm; + read_lock(&tasklist_lock); + do_each_thread(g, t) + if (t->mm == mm && t != p) { + read_unlock(&tasklist_lock); + return -EPERM; + } + while_each_thread(g, t); + read_unlock(&tasklist_lock); + } + + /* Check permissions for the transition. */ + error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS, + PROCESS__DYNTRANSITION, NULL); + if (error) + return error; + + /* Check for ptracing, and update the task SID if ok. + Otherwise, leave SID unchanged and fail. */ + task_lock(p); + if (p->ptrace & PT_PTRACED) { + error = avc_has_perm_noaudit(tsec->ptrace_sid, sid, + SECCLASS_PROCESS, + PROCESS__PTRACE, &avd); + if (!error) + tsec->sid = sid; + task_unlock(p); + avc_audit(tsec->ptrace_sid, sid, SECCLASS_PROCESS, + PROCESS__PTRACE, &avd, error, NULL); + if (error) + return error; + } else { + tsec->sid = sid; + task_unlock(p); + } + } else return -EINVAL; return size; } -struct security_operations selinux_ops = { +static struct security_operations selinux_ops = { .ptrace = selinux_ptrace, .capget = selinux_capget, .capset_check = selinux_capset_check, @@ -4158,6 +4260,7 @@ struct security_operations selinux_ops = { .bprm_alloc_security = selinux_bprm_alloc_security, .bprm_free_security = selinux_bprm_free_security, .bprm_apply_creds = selinux_bprm_apply_creds, + .bprm_post_apply_creds = selinux_bprm_post_apply_creds, .bprm_set_security = selinux_bprm_set_security, .bprm_check_security = selinux_bprm_check_security, .bprm_secureexec = selinux_bprm_secureexec, @@ -4288,7 +4391,7 @@ struct security_operations selinux_ops = { #endif }; -__init int selinux_init(void) +static __init int selinux_init(void) { struct task_security_struct *tsec; diff --git a/security/selinux/include/av_inherit.h b/security/selinux/include/av_inherit.h index c05e2ee6f..b0e6b1293 100644 --- a/security/selinux/include/av_inherit.h +++ b/security/selinux/include/av_inherit.h @@ -1,44 +1,31 @@ /* This file is automatically generated. Do not edit. */ -/* FLASK */ - -struct av_inherit -{ - u16 tclass; - char **common_pts; - u32 common_base; -}; - -static struct av_inherit av_inherit[] = { - { SECCLASS_DIR, common_file_perm_to_string, 0x00020000UL }, - { SECCLASS_FILE, common_file_perm_to_string, 0x00020000UL }, - { SECCLASS_LNK_FILE, common_file_perm_to_string, 0x00020000UL }, - { SECCLASS_CHR_FILE, common_file_perm_to_string, 0x00020000UL }, - { SECCLASS_BLK_FILE, common_file_perm_to_string, 0x00020000UL }, - { SECCLASS_SOCK_FILE, common_file_perm_to_string, 0x00020000UL }, - { SECCLASS_FIFO_FILE, common_file_perm_to_string, 0x00020000UL }, - { SECCLASS_SOCKET, common_socket_perm_to_string, 0x00400000UL }, - { SECCLASS_TCP_SOCKET, common_socket_perm_to_string, 0x00400000UL }, - { SECCLASS_UDP_SOCKET, common_socket_perm_to_string, 0x00400000UL }, - { SECCLASS_RAWIP_SOCKET, common_socket_perm_to_string, 0x00400000UL }, - { SECCLASS_NETLINK_SOCKET, common_socket_perm_to_string, 0x00400000UL }, - { SECCLASS_PACKET_SOCKET, common_socket_perm_to_string, 0x00400000UL }, - { SECCLASS_KEY_SOCKET, common_socket_perm_to_string, 0x00400000UL }, - { SECCLASS_UNIX_STREAM_SOCKET, common_socket_perm_to_string, 0x00400000UL }, - { SECCLASS_UNIX_DGRAM_SOCKET, common_socket_perm_to_string, 0x00400000UL }, - { SECCLASS_IPC, common_ipc_perm_to_string, 0x00000200UL }, - { SECCLASS_SEM, common_ipc_perm_to_string, 0x00000200UL }, - { SECCLASS_MSGQ, common_ipc_perm_to_string, 0x00000200UL }, - { SECCLASS_SHM, common_ipc_perm_to_string, 0x00000200UL }, - { SECCLASS_NETLINK_ROUTE_SOCKET, common_socket_perm_to_string, 0x00400000UL }, - { SECCLASS_NETLINK_FIREWALL_SOCKET, common_socket_perm_to_string, 0x00400000UL }, - { SECCLASS_NETLINK_TCPDIAG_SOCKET, common_socket_perm_to_string, 0x00400000UL }, - { SECCLASS_NETLINK_NFLOG_SOCKET, common_socket_perm_to_string, 0x00400000UL }, - { SECCLASS_NETLINK_XFRM_SOCKET, common_socket_perm_to_string, 0x00400000UL }, - { SECCLASS_NETLINK_SELINUX_SOCKET, common_socket_perm_to_string, 0x00400000UL }, - { SECCLASS_NETLINK_AUDIT_SOCKET, common_socket_perm_to_string, 0x00400000UL }, - { SECCLASS_NETLINK_IP6FW_SOCKET, common_socket_perm_to_string, 0x00400000UL }, - { SECCLASS_NETLINK_DNRT_SOCKET, common_socket_perm_to_string, 0x00400000UL }, -}; - - -/* FLASK */ + S_(SECCLASS_DIR, file, 0x00020000UL) + S_(SECCLASS_FILE, file, 0x00020000UL) + S_(SECCLASS_LNK_FILE, file, 0x00020000UL) + S_(SECCLASS_CHR_FILE, file, 0x00020000UL) + S_(SECCLASS_BLK_FILE, file, 0x00020000UL) + S_(SECCLASS_SOCK_FILE, file, 0x00020000UL) + S_(SECCLASS_FIFO_FILE, file, 0x00020000UL) + S_(SECCLASS_SOCKET, socket, 0x00400000UL) + S_(SECCLASS_TCP_SOCKET, socket, 0x00400000UL) + S_(SECCLASS_UDP_SOCKET, socket, 0x00400000UL) + S_(SECCLASS_RAWIP_SOCKET, socket, 0x00400000UL) + S_(SECCLASS_NETLINK_SOCKET, socket, 0x00400000UL) + S_(SECCLASS_PACKET_SOCKET, socket, 0x00400000UL) + S_(SECCLASS_KEY_SOCKET, socket, 0x00400000UL) + S_(SECCLASS_UNIX_STREAM_SOCKET, socket, 0x00400000UL) + S_(SECCLASS_UNIX_DGRAM_SOCKET, socket, 0x00400000UL) + S_(SECCLASS_IPC, ipc, 0x00000200UL) + S_(SECCLASS_SEM, ipc, 0x00000200UL) + S_(SECCLASS_MSGQ, ipc, 0x00000200UL) + S_(SECCLASS_SHM, ipc, 0x00000200UL) + S_(SECCLASS_NETLINK_ROUTE_SOCKET, socket, 0x00400000UL) + S_(SECCLASS_NETLINK_FIREWALL_SOCKET, socket, 0x00400000UL) + S_(SECCLASS_NETLINK_TCPDIAG_SOCKET, socket, 0x00400000UL) + S_(SECCLASS_NETLINK_NFLOG_SOCKET, socket, 0x00400000UL) + S_(SECCLASS_NETLINK_XFRM_SOCKET, socket, 0x00400000UL) + S_(SECCLASS_NETLINK_SELINUX_SOCKET, socket, 0x00400000UL) + S_(SECCLASS_NETLINK_AUDIT_SOCKET, socket, 0x00400000UL) + S_(SECCLASS_NETLINK_IP6FW_SOCKET, socket, 0x00400000UL) + S_(SECCLASS_NETLINK_DNRT_SOCKET, socket, 0x00400000UL) + S_(SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET, socket, 0x00400000UL) diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h index a3ea4310e..8928bb4d3 100644 --- a/security/selinux/include/av_perm_to_string.h +++ b/security/selinux/include/av_perm_to_string.h @@ -1,226 +1,238 @@ /* This file is automatically generated. Do not edit. */ -/* FLASK */ - -struct av_perm_to_string -{ - u16 tclass; - u32 value; - char *name; -}; - -static struct av_perm_to_string av_perm_to_string[] = { - { SECCLASS_FILESYSTEM, FILESYSTEM__MOUNT, "mount" }, - { SECCLASS_FILESYSTEM, FILESYSTEM__REMOUNT, "remount" }, - { SECCLASS_FILESYSTEM, FILESYSTEM__UNMOUNT, "unmount" }, - { SECCLASS_FILESYSTEM, FILESYSTEM__GETATTR, "getattr" }, - { SECCLASS_FILESYSTEM, FILESYSTEM__RELABELFROM, "relabelfrom" }, - { SECCLASS_FILESYSTEM, FILESYSTEM__RELABELTO, "relabelto" }, - { SECCLASS_FILESYSTEM, FILESYSTEM__TRANSITION, "transition" }, - { SECCLASS_FILESYSTEM, FILESYSTEM__ASSOCIATE, "associate" }, - { SECCLASS_FILESYSTEM, FILESYSTEM__QUOTAMOD, "quotamod" }, - { SECCLASS_FILESYSTEM, FILESYSTEM__QUOTAGET, "quotaget" }, - { SECCLASS_DIR, DIR__ADD_NAME, "add_name" }, - { SECCLASS_DIR, DIR__REMOVE_NAME, "remove_name" }, - { SECCLASS_DIR, DIR__REPARENT, "reparent" }, - { SECCLASS_DIR, DIR__SEARCH, "search" }, - { SECCLASS_DIR, DIR__RMDIR, "rmdir" }, - { SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, "execute_no_trans" }, - { SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint" }, - { SECCLASS_FD, FD__USE, "use" }, - { SECCLASS_TCP_SOCKET, TCP_SOCKET__CONNECTTO, "connectto" }, - { SECCLASS_TCP_SOCKET, TCP_SOCKET__NEWCONN, "newconn" }, - { SECCLASS_TCP_SOCKET, TCP_SOCKET__ACCEPTFROM, "acceptfrom" }, - { SECCLASS_TCP_SOCKET, TCP_SOCKET__NODE_BIND, "node_bind" }, - { SECCLASS_UDP_SOCKET, UDP_SOCKET__NODE_BIND, "node_bind" }, - { SECCLASS_RAWIP_SOCKET, RAWIP_SOCKET__NODE_BIND, "node_bind" }, - { SECCLASS_NODE, NODE__TCP_RECV, "tcp_recv" }, - { SECCLASS_NODE, NODE__TCP_SEND, "tcp_send" }, - { SECCLASS_NODE, NODE__UDP_RECV, "udp_recv" }, - { SECCLASS_NODE, NODE__UDP_SEND, "udp_send" }, - { SECCLASS_NODE, NODE__RAWIP_RECV, "rawip_recv" }, - { SECCLASS_NODE, NODE__RAWIP_SEND, "rawip_send" }, - { SECCLASS_NODE, NODE__ENFORCE_DEST, "enforce_dest" }, - { SECCLASS_NETIF, NETIF__TCP_RECV, "tcp_recv" }, - { SECCLASS_NETIF, NETIF__TCP_SEND, "tcp_send" }, - { SECCLASS_NETIF, NETIF__UDP_RECV, "udp_recv" }, - { SECCLASS_NETIF, NETIF__UDP_SEND, "udp_send" }, - { SECCLASS_NETIF, NETIF__RAWIP_RECV, "rawip_recv" }, - { SECCLASS_NETIF, NETIF__RAWIP_SEND, "rawip_send" }, - { SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__CONNECTTO, "connectto" }, - { SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__NEWCONN, "newconn" }, - { SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__ACCEPTFROM, "acceptfrom" }, - { SECCLASS_PROCESS, PROCESS__FORK, "fork" }, - { SECCLASS_PROCESS, PROCESS__TRANSITION, "transition" }, - { SECCLASS_PROCESS, PROCESS__SIGCHLD, "sigchld" }, - { SECCLASS_PROCESS, PROCESS__SIGKILL, "sigkill" }, - { SECCLASS_PROCESS, PROCESS__SIGSTOP, "sigstop" }, - { SECCLASS_PROCESS, PROCESS__SIGNULL, "signull" }, - { SECCLASS_PROCESS, PROCESS__SIGNAL, "signal" }, - { SECCLASS_PROCESS, PROCESS__PTRACE, "ptrace" }, - { SECCLASS_PROCESS, PROCESS__GETSCHED, "getsched" }, - { SECCLASS_PROCESS, PROCESS__SETSCHED, "setsched" }, - { SECCLASS_PROCESS, PROCESS__GETSESSION, "getsession" }, - { SECCLASS_PROCESS, PROCESS__GETPGID, "getpgid" }, - { SECCLASS_PROCESS, PROCESS__SETPGID, "setpgid" }, - { SECCLASS_PROCESS, PROCESS__GETCAP, "getcap" }, - { SECCLASS_PROCESS, PROCESS__SETCAP, "setcap" }, - { SECCLASS_PROCESS, PROCESS__SHARE, "share" }, - { SECCLASS_PROCESS, PROCESS__GETATTR, "getattr" }, - { SECCLASS_PROCESS, PROCESS__SETEXEC, "setexec" }, - { SECCLASS_PROCESS, PROCESS__SETFSCREATE, "setfscreate" }, - { SECCLASS_PROCESS, PROCESS__NOATSECURE, "noatsecure" }, - { SECCLASS_PROCESS, PROCESS__SIGINH, "siginh" }, - { SECCLASS_PROCESS, PROCESS__SETRLIMIT, "setrlimit" }, - { SECCLASS_PROCESS, PROCESS__RLIMITINH, "rlimitinh" }, - { SECCLASS_MSGQ, MSGQ__ENQUEUE, "enqueue" }, - { SECCLASS_MSG, MSG__SEND, "send" }, - { SECCLASS_MSG, MSG__RECEIVE, "receive" }, - { SECCLASS_SHM, SHM__LOCK, "lock" }, - { SECCLASS_SECURITY, SECURITY__COMPUTE_AV, "compute_av" }, - { SECCLASS_SECURITY, SECURITY__COMPUTE_CREATE, "compute_create" }, - { SECCLASS_SECURITY, SECURITY__COMPUTE_MEMBER, "compute_member" }, - { SECCLASS_SECURITY, SECURITY__CHECK_CONTEXT, "check_context" }, - { SECCLASS_SECURITY, SECURITY__LOAD_POLICY, "load_policy" }, - { SECCLASS_SECURITY, SECURITY__COMPUTE_RELABEL, "compute_relabel" }, - { SECCLASS_SECURITY, SECURITY__COMPUTE_USER, "compute_user" }, - { SECCLASS_SECURITY, SECURITY__SETENFORCE, "setenforce" }, - { SECCLASS_SECURITY, SECURITY__SETBOOL, "setbool" }, - { SECCLASS_SECURITY, SECURITY__SETSECPARAM, "setsecparam" }, - { SECCLASS_SYSTEM, SYSTEM__IPC_INFO, "ipc_info" }, - { SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, "syslog_read" }, - { SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, "syslog_mod" }, - { SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE, "syslog_console" }, - { SECCLASS_CAPABILITY, CAPABILITY__CHOWN, "chown" }, - { SECCLASS_CAPABILITY, CAPABILITY__DAC_OVERRIDE, "dac_override" }, - { SECCLASS_CAPABILITY, CAPABILITY__DAC_READ_SEARCH, "dac_read_search" }, - { SECCLASS_CAPABILITY, CAPABILITY__FOWNER, "fowner" }, - { SECCLASS_CAPABILITY, CAPABILITY__FSETID, "fsetid" }, - { SECCLASS_CAPABILITY, CAPABILITY__KILL, "kill" }, - { SECCLASS_CAPABILITY, CAPABILITY__SETGID, "setgid" }, - { SECCLASS_CAPABILITY, CAPABILITY__SETUID, "setuid" }, - { SECCLASS_CAPABILITY, CAPABILITY__SETPCAP, "setpcap" }, - { SECCLASS_CAPABILITY, CAPABILITY__LINUX_IMMUTABLE, "linux_immutable" }, - { SECCLASS_CAPABILITY, CAPABILITY__NET_BIND_SERVICE, "net_bind_service" }, - { SECCLASS_CAPABILITY, CAPABILITY__NET_BROADCAST, "net_broadcast" }, - { SECCLASS_CAPABILITY, CAPABILITY__NET_ADMIN, "net_admin" }, - { SECCLASS_CAPABILITY, CAPABILITY__NET_RAW, "net_raw" }, - { SECCLASS_CAPABILITY, CAPABILITY__IPC_LOCK, "ipc_lock" }, - { SECCLASS_CAPABILITY, CAPABILITY__IPC_OWNER, "ipc_owner" }, - { SECCLASS_CAPABILITY, CAPABILITY__SYS_MODULE, "sys_module" }, - { SECCLASS_CAPABILITY, CAPABILITY__SYS_RAWIO, "sys_rawio" }, - { SECCLASS_CAPABILITY, CAPABILITY__SYS_CHROOT, "sys_chroot" }, - { SECCLASS_CAPABILITY, CAPABILITY__SYS_PTRACE, "sys_ptrace" }, - { SECCLASS_CAPABILITY, CAPABILITY__SYS_PACCT, "sys_pacct" }, - { SECCLASS_CAPABILITY, CAPABILITY__SYS_ADMIN, "sys_admin" }, - { SECCLASS_CAPABILITY, CAPABILITY__SYS_BOOT, "sys_boot" }, - { SECCLASS_CAPABILITY, CAPABILITY__SYS_NICE, "sys_nice" }, - { SECCLASS_CAPABILITY, CAPABILITY__SYS_RESOURCE, "sys_resource" }, - { SECCLASS_CAPABILITY, CAPABILITY__SYS_TIME, "sys_time" }, - { SECCLASS_CAPABILITY, CAPABILITY__SYS_TTY_CONFIG, "sys_tty_config" }, - { SECCLASS_CAPABILITY, CAPABILITY__MKNOD, "mknod" }, - { SECCLASS_CAPABILITY, CAPABILITY__LEASE, "lease" }, - { SECCLASS_PASSWD, PASSWD__PASSWD, "passwd" }, - { SECCLASS_PASSWD, PASSWD__CHFN, "chfn" }, - { SECCLASS_PASSWD, PASSWD__CHSH, "chsh" }, - { SECCLASS_PASSWD, PASSWD__ROOTOK, "rootok" }, - { SECCLASS_DRAWABLE, DRAWABLE__CREATE, "create" }, - { SECCLASS_DRAWABLE, DRAWABLE__DESTROY, "destroy" }, - { SECCLASS_DRAWABLE, DRAWABLE__DRAW, "draw" }, - { SECCLASS_DRAWABLE, DRAWABLE__COPY, "copy" }, - { SECCLASS_DRAWABLE, DRAWABLE__GETATTR, "getattr" }, - { SECCLASS_GC, GC__CREATE, "create" }, - { SECCLASS_GC, GC__FREE, "free" }, - { SECCLASS_GC, GC__GETATTR, "getattr" }, - { SECCLASS_GC, GC__SETATTR, "setattr" }, - { SECCLASS_WINDOW, WINDOW__ADDCHILD, "addchild" }, - { SECCLASS_WINDOW, WINDOW__CREATE, "create" }, - { SECCLASS_WINDOW, WINDOW__DESTROY, "destroy" }, - { SECCLASS_WINDOW, WINDOW__MAP, "map" }, - { SECCLASS_WINDOW, WINDOW__UNMAP, "unmap" }, - { SECCLASS_WINDOW, WINDOW__CHSTACK, "chstack" }, - { SECCLASS_WINDOW, WINDOW__CHPROPLIST, "chproplist" }, - { SECCLASS_WINDOW, WINDOW__CHPROP, "chprop" }, - { SECCLASS_WINDOW, WINDOW__LISTPROP, "listprop" }, - { SECCLASS_WINDOW, WINDOW__GETATTR, "getattr" }, - { SECCLASS_WINDOW, WINDOW__SETATTR, "setattr" }, - { SECCLASS_WINDOW, WINDOW__SETFOCUS, "setfocus" }, - { SECCLASS_WINDOW, WINDOW__MOVE, "move" }, - { SECCLASS_WINDOW, WINDOW__CHSELECTION, "chselection" }, - { SECCLASS_WINDOW, WINDOW__CHPARENT, "chparent" }, - { SECCLASS_WINDOW, WINDOW__CTRLLIFE, "ctrllife" }, - { SECCLASS_WINDOW, WINDOW__ENUMERATE, "enumerate" }, - { SECCLASS_WINDOW, WINDOW__TRANSPARENT, "transparent" }, - { SECCLASS_WINDOW, WINDOW__MOUSEMOTION, "mousemotion" }, - { SECCLASS_WINDOW, WINDOW__CLIENTCOMEVENT, "clientcomevent" }, - { SECCLASS_WINDOW, WINDOW__INPUTEVENT, "inputevent" }, - { SECCLASS_WINDOW, WINDOW__DRAWEVENT, "drawevent" }, - { SECCLASS_WINDOW, WINDOW__WINDOWCHANGEEVENT, "windowchangeevent" }, - { SECCLASS_WINDOW, WINDOW__WINDOWCHANGEREQUEST, "windowchangerequest" }, - { SECCLASS_WINDOW, WINDOW__SERVERCHANGEEVENT, "serverchangeevent" }, - { SECCLASS_WINDOW, WINDOW__EXTENSIONEVENT, "extensionevent" }, - { SECCLASS_FONT, FONT__LOAD, "load" }, - { SECCLASS_FONT, FONT__FREE, "free" }, - { SECCLASS_FONT, FONT__GETATTR, "getattr" }, - { SECCLASS_FONT, FONT__USE, "use" }, - { SECCLASS_COLORMAP, COLORMAP__CREATE, "create" }, - { SECCLASS_COLORMAP, COLORMAP__FREE, "free" }, - { SECCLASS_COLORMAP, COLORMAP__INSTALL, "install" }, - { SECCLASS_COLORMAP, COLORMAP__UNINSTALL, "uninstall" }, - { SECCLASS_COLORMAP, COLORMAP__LIST, "list" }, - { SECCLASS_COLORMAP, COLORMAP__READ, "read" }, - { SECCLASS_COLORMAP, COLORMAP__STORE, "store" }, - { SECCLASS_COLORMAP, COLORMAP__GETATTR, "getattr" }, - { SECCLASS_COLORMAP, COLORMAP__SETATTR, "setattr" }, - { SECCLASS_PROPERTY, PROPERTY__CREATE, "create" }, - { SECCLASS_PROPERTY, PROPERTY__FREE, "free" }, - { SECCLASS_PROPERTY, PROPERTY__READ, "read" }, - { SECCLASS_PROPERTY, PROPERTY__WRITE, "write" }, - { SECCLASS_CURSOR, CURSOR__CREATE, "create" }, - { SECCLASS_CURSOR, CURSOR__CREATEGLYPH, "createglyph" }, - { SECCLASS_CURSOR, CURSOR__FREE, "free" }, - { SECCLASS_CURSOR, CURSOR__ASSIGN, "assign" }, - { SECCLASS_CURSOR, CURSOR__SETATTR, "setattr" }, - { SECCLASS_XCLIENT, XCLIENT__KILL, "kill" }, - { SECCLASS_XINPUT, XINPUT__LOOKUP, "lookup" }, - { SECCLASS_XINPUT, XINPUT__GETATTR, "getattr" }, - { SECCLASS_XINPUT, XINPUT__SETATTR, "setattr" }, - { SECCLASS_XINPUT, XINPUT__SETFOCUS, "setfocus" }, - { SECCLASS_XINPUT, XINPUT__WARPPOINTER, "warppointer" }, - { SECCLASS_XINPUT, XINPUT__ACTIVEGRAB, "activegrab" }, - { SECCLASS_XINPUT, XINPUT__PASSIVEGRAB, "passivegrab" }, - { SECCLASS_XINPUT, XINPUT__UNGRAB, "ungrab" }, - { SECCLASS_XINPUT, XINPUT__BELL, "bell" }, - { SECCLASS_XINPUT, XINPUT__MOUSEMOTION, "mousemotion" }, - { SECCLASS_XINPUT, XINPUT__RELABELINPUT, "relabelinput" }, - { SECCLASS_XSERVER, XSERVER__SCREENSAVER, "screensaver" }, - { SECCLASS_XSERVER, XSERVER__GETHOSTLIST, "gethostlist" }, - { SECCLASS_XSERVER, XSERVER__SETHOSTLIST, "sethostlist" }, - { SECCLASS_XSERVER, XSERVER__GETFONTPATH, "getfontpath" }, - { SECCLASS_XSERVER, XSERVER__SETFONTPATH, "setfontpath" }, - { SECCLASS_XSERVER, XSERVER__GETATTR, "getattr" }, - { SECCLASS_XSERVER, XSERVER__GRAB, "grab" }, - { SECCLASS_XSERVER, XSERVER__UNGRAB, "ungrab" }, - { SECCLASS_XEXTENSION, XEXTENSION__QUERY, "query" }, - { SECCLASS_XEXTENSION, XEXTENSION__USE, "use" }, - { SECCLASS_PAX, PAX__PAGEEXEC, "pageexec" }, - { SECCLASS_PAX, PAX__EMUTRAMP, "emutramp" }, - { SECCLASS_PAX, PAX__MPROTECT, "mprotect" }, - { SECCLASS_PAX, PAX__RANDMMAP, "randmmap" }, - { SECCLASS_PAX, PAX__RANDEXEC, "randexec" }, - { SECCLASS_PAX, PAX__SEGMEXEC, "segmexec" }, - { SECCLASS_NETLINK_ROUTE_SOCKET, NETLINK_ROUTE_SOCKET__NLMSG_READ, "nlmsg_read" }, - { SECCLASS_NETLINK_ROUTE_SOCKET, NETLINK_ROUTE_SOCKET__NLMSG_WRITE, "nlmsg_write" }, - { SECCLASS_NETLINK_FIREWALL_SOCKET, NETLINK_FIREWALL_SOCKET__NLMSG_READ, "nlmsg_read" }, - { SECCLASS_NETLINK_FIREWALL_SOCKET, NETLINK_FIREWALL_SOCKET__NLMSG_WRITE, "nlmsg_write" }, - { SECCLASS_NETLINK_TCPDIAG_SOCKET, NETLINK_TCPDIAG_SOCKET__NLMSG_READ, "nlmsg_read" }, - { SECCLASS_NETLINK_TCPDIAG_SOCKET, NETLINK_TCPDIAG_SOCKET__NLMSG_WRITE, "nlmsg_write" }, - { SECCLASS_NETLINK_XFRM_SOCKET, NETLINK_XFRM_SOCKET__NLMSG_READ, "nlmsg_read" }, - { SECCLASS_NETLINK_XFRM_SOCKET, NETLINK_XFRM_SOCKET__NLMSG_WRITE, "nlmsg_write" }, - { SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_READ, "nlmsg_read" }, - { SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_WRITE, "nlmsg_write" }, - { SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_READ, "nlmsg_read" }, - { SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_WRITE, "nlmsg_write" }, -}; - - -/* FLASK */ + S_(SECCLASS_FILESYSTEM, FILESYSTEM__MOUNT, "mount") + S_(SECCLASS_FILESYSTEM, FILESYSTEM__REMOUNT, "remount") + S_(SECCLASS_FILESYSTEM, FILESYSTEM__UNMOUNT, "unmount") + S_(SECCLASS_FILESYSTEM, FILESYSTEM__GETATTR, "getattr") + S_(SECCLASS_FILESYSTEM, FILESYSTEM__RELABELFROM, "relabelfrom") + S_(SECCLASS_FILESYSTEM, FILESYSTEM__RELABELTO, "relabelto") + S_(SECCLASS_FILESYSTEM, FILESYSTEM__TRANSITION, "transition") + S_(SECCLASS_FILESYSTEM, FILESYSTEM__ASSOCIATE, "associate") + S_(SECCLASS_FILESYSTEM, FILESYSTEM__QUOTAMOD, "quotamod") + S_(SECCLASS_FILESYSTEM, FILESYSTEM__QUOTAGET, "quotaget") + S_(SECCLASS_DIR, DIR__ADD_NAME, "add_name") + S_(SECCLASS_DIR, DIR__REMOVE_NAME, "remove_name") + S_(SECCLASS_DIR, DIR__REPARENT, "reparent") + S_(SECCLASS_DIR, DIR__SEARCH, "search") + S_(SECCLASS_DIR, DIR__RMDIR, "rmdir") + S_(SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, "execute_no_trans") + S_(SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint") + S_(SECCLASS_FILE, FILE__EXECMOD, "execmod") + S_(SECCLASS_CHR_FILE, CHR_FILE__EXECUTE_NO_TRANS, "execute_no_trans") + S_(SECCLASS_CHR_FILE, CHR_FILE__ENTRYPOINT, "entrypoint") + S_(SECCLASS_CHR_FILE, CHR_FILE__EXECMOD, "execmod") + S_(SECCLASS_FD, FD__USE, "use") + S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__CONNECTTO, "connectto") + S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NEWCONN, "newconn") + S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__ACCEPTFROM, "acceptfrom") + S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NODE_BIND, "node_bind") + S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NAME_CONNECT, "name_connect") + S_(SECCLASS_UDP_SOCKET, UDP_SOCKET__NODE_BIND, "node_bind") + S_(SECCLASS_RAWIP_SOCKET, RAWIP_SOCKET__NODE_BIND, "node_bind") + S_(SECCLASS_NODE, NODE__TCP_RECV, "tcp_recv") + S_(SECCLASS_NODE, NODE__TCP_SEND, "tcp_send") + S_(SECCLASS_NODE, NODE__UDP_RECV, "udp_recv") + S_(SECCLASS_NODE, NODE__UDP_SEND, "udp_send") + S_(SECCLASS_NODE, NODE__RAWIP_RECV, "rawip_recv") + S_(SECCLASS_NODE, NODE__RAWIP_SEND, "rawip_send") + S_(SECCLASS_NODE, NODE__ENFORCE_DEST, "enforce_dest") + S_(SECCLASS_NETIF, NETIF__TCP_RECV, "tcp_recv") + S_(SECCLASS_NETIF, NETIF__TCP_SEND, "tcp_send") + S_(SECCLASS_NETIF, NETIF__UDP_RECV, "udp_recv") + S_(SECCLASS_NETIF, NETIF__UDP_SEND, "udp_send") + S_(SECCLASS_NETIF, NETIF__RAWIP_RECV, "rawip_recv") + S_(SECCLASS_NETIF, NETIF__RAWIP_SEND, "rawip_send") + S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__CONNECTTO, "connectto") + S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__NEWCONN, "newconn") + S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__ACCEPTFROM, "acceptfrom") + S_(SECCLASS_PROCESS, PROCESS__FORK, "fork") + S_(SECCLASS_PROCESS, PROCESS__TRANSITION, "transition") + S_(SECCLASS_PROCESS, PROCESS__SIGCHLD, "sigchld") + S_(SECCLASS_PROCESS, PROCESS__SIGKILL, "sigkill") + S_(SECCLASS_PROCESS, PROCESS__SIGSTOP, "sigstop") + S_(SECCLASS_PROCESS, PROCESS__SIGNULL, "signull") + S_(SECCLASS_PROCESS, PROCESS__SIGNAL, "signal") + S_(SECCLASS_PROCESS, PROCESS__PTRACE, "ptrace") + S_(SECCLASS_PROCESS, PROCESS__GETSCHED, "getsched") + S_(SECCLASS_PROCESS, PROCESS__SETSCHED, "setsched") + S_(SECCLASS_PROCESS, PROCESS__GETSESSION, "getsession") + S_(SECCLASS_PROCESS, PROCESS__GETPGID, "getpgid") + S_(SECCLASS_PROCESS, PROCESS__SETPGID, "setpgid") + S_(SECCLASS_PROCESS, PROCESS__GETCAP, "getcap") + S_(SECCLASS_PROCESS, PROCESS__SETCAP, "setcap") + S_(SECCLASS_PROCESS, PROCESS__SHARE, "share") + S_(SECCLASS_PROCESS, PROCESS__GETATTR, "getattr") + S_(SECCLASS_PROCESS, PROCESS__SETEXEC, "setexec") + S_(SECCLASS_PROCESS, PROCESS__SETFSCREATE, "setfscreate") + S_(SECCLASS_PROCESS, PROCESS__NOATSECURE, "noatsecure") + S_(SECCLASS_PROCESS, PROCESS__SIGINH, "siginh") + S_(SECCLASS_PROCESS, PROCESS__SETRLIMIT, "setrlimit") + S_(SECCLASS_PROCESS, PROCESS__RLIMITINH, "rlimitinh") + S_(SECCLASS_PROCESS, PROCESS__DYNTRANSITION, "dyntransition") + S_(SECCLASS_PROCESS, PROCESS__SETCURRENT, "setcurrent") + S_(SECCLASS_PROCESS, PROCESS__EXECMEM, "execmem") + S_(SECCLASS_MSGQ, MSGQ__ENQUEUE, "enqueue") + S_(SECCLASS_MSG, MSG__SEND, "send") + S_(SECCLASS_MSG, MSG__RECEIVE, "receive") + S_(SECCLASS_SHM, SHM__LOCK, "lock") + S_(SECCLASS_SECURITY, SECURITY__COMPUTE_AV, "compute_av") + S_(SECCLASS_SECURITY, SECURITY__COMPUTE_CREATE, "compute_create") + S_(SECCLASS_SECURITY, SECURITY__COMPUTE_MEMBER, "compute_member") + S_(SECCLASS_SECURITY, SECURITY__CHECK_CONTEXT, "check_context") + S_(SECCLASS_SECURITY, SECURITY__LOAD_POLICY, "load_policy") + S_(SECCLASS_SECURITY, SECURITY__COMPUTE_RELABEL, "compute_relabel") + S_(SECCLASS_SECURITY, SECURITY__COMPUTE_USER, "compute_user") + S_(SECCLASS_SECURITY, SECURITY__SETENFORCE, "setenforce") + S_(SECCLASS_SECURITY, SECURITY__SETBOOL, "setbool") + S_(SECCLASS_SECURITY, SECURITY__SETSECPARAM, "setsecparam") + S_(SECCLASS_SECURITY, SECURITY__SETCHECKREQPROT, "setcheckreqprot") + S_(SECCLASS_SYSTEM, SYSTEM__IPC_INFO, "ipc_info") + S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, "syslog_read") + S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, "syslog_mod") + S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE, "syslog_console") + S_(SECCLASS_CAPABILITY, CAPABILITY__CHOWN, "chown") + S_(SECCLASS_CAPABILITY, CAPABILITY__DAC_OVERRIDE, "dac_override") + S_(SECCLASS_CAPABILITY, CAPABILITY__DAC_READ_SEARCH, "dac_read_search") + S_(SECCLASS_CAPABILITY, CAPABILITY__FOWNER, "fowner") + S_(SECCLASS_CAPABILITY, CAPABILITY__FSETID, "fsetid") + S_(SECCLASS_CAPABILITY, CAPABILITY__KILL, "kill") + S_(SECCLASS_CAPABILITY, CAPABILITY__SETGID, "setgid") + S_(SECCLASS_CAPABILITY, CAPABILITY__SETUID, "setuid") + S_(SECCLASS_CAPABILITY, CAPABILITY__SETPCAP, "setpcap") + S_(SECCLASS_CAPABILITY, CAPABILITY__LINUX_IMMUTABLE, "linux_immutable") + S_(SECCLASS_CAPABILITY, CAPABILITY__NET_BIND_SERVICE, "net_bind_service") + S_(SECCLASS_CAPABILITY, CAPABILITY__NET_BROADCAST, "net_broadcast") + S_(SECCLASS_CAPABILITY, CAPABILITY__NET_ADMIN, "net_admin") + S_(SECCLASS_CAPABILITY, CAPABILITY__NET_RAW, "net_raw") + S_(SECCLASS_CAPABILITY, CAPABILITY__IPC_LOCK, "ipc_lock") + S_(SECCLASS_CAPABILITY, CAPABILITY__IPC_OWNER, "ipc_owner") + S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_MODULE, "sys_module") + S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_RAWIO, "sys_rawio") + S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_CHROOT, "sys_chroot") + S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_PTRACE, "sys_ptrace") + S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_PACCT, "sys_pacct") + S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_ADMIN, "sys_admin") + S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_BOOT, "sys_boot") + S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_NICE, "sys_nice") + S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_RESOURCE, "sys_resource") + S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_TIME, "sys_time") + S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_TTY_CONFIG, "sys_tty_config") + S_(SECCLASS_CAPABILITY, CAPABILITY__MKNOD, "mknod") + S_(SECCLASS_CAPABILITY, CAPABILITY__LEASE, "lease") + S_(SECCLASS_CAPABILITY, CAPABILITY__AUDIT_WRITE, "audit_write") + S_(SECCLASS_CAPABILITY, CAPABILITY__AUDIT_CONTROL, "audit_control") + S_(SECCLASS_PASSWD, PASSWD__PASSWD, "passwd") + S_(SECCLASS_PASSWD, PASSWD__CHFN, "chfn") + S_(SECCLASS_PASSWD, PASSWD__CHSH, "chsh") + S_(SECCLASS_PASSWD, PASSWD__ROOTOK, "rootok") + S_(SECCLASS_PASSWD, PASSWD__CRONTAB, "crontab") + S_(SECCLASS_DRAWABLE, DRAWABLE__CREATE, "create") + S_(SECCLASS_DRAWABLE, DRAWABLE__DESTROY, "destroy") + S_(SECCLASS_DRAWABLE, DRAWABLE__DRAW, "draw") + S_(SECCLASS_DRAWABLE, DRAWABLE__COPY, "copy") + S_(SECCLASS_DRAWABLE, DRAWABLE__GETATTR, "getattr") + S_(SECCLASS_GC, GC__CREATE, "create") + S_(SECCLASS_GC, GC__FREE, "free") + S_(SECCLASS_GC, GC__GETATTR, "getattr") + S_(SECCLASS_GC, GC__SETATTR, "setattr") + S_(SECCLASS_WINDOW, WINDOW__ADDCHILD, "addchild") + S_(SECCLASS_WINDOW, WINDOW__CREATE, "create") + S_(SECCLASS_WINDOW, WINDOW__DESTROY, "destroy") + S_(SECCLASS_WINDOW, WINDOW__MAP, "map") + S_(SECCLASS_WINDOW, WINDOW__UNMAP, "unmap") + S_(SECCLASS_WINDOW, WINDOW__CHSTACK, "chstack") + S_(SECCLASS_WINDOW, WINDOW__CHPROPLIST, "chproplist") + S_(SECCLASS_WINDOW, WINDOW__CHPROP, "chprop") + S_(SECCLASS_WINDOW, WINDOW__LISTPROP, "listprop") + S_(SECCLASS_WINDOW, WINDOW__GETATTR, "getattr") + S_(SECCLASS_WINDOW, WINDOW__SETATTR, "setattr") + S_(SECCLASS_WINDOW, WINDOW__SETFOCUS, "setfocus") + S_(SECCLASS_WINDOW, WINDOW__MOVE, "move") + S_(SECCLASS_WINDOW, WINDOW__CHSELECTION, "chselection") + S_(SECCLASS_WINDOW, WINDOW__CHPARENT, "chparent") + S_(SECCLASS_WINDOW, WINDOW__CTRLLIFE, "ctrllife") + S_(SECCLASS_WINDOW, WINDOW__ENUMERATE, "enumerate") + S_(SECCLASS_WINDOW, WINDOW__TRANSPARENT, "transparent") + S_(SECCLASS_WINDOW, WINDOW__MOUSEMOTION, "mousemotion") + S_(SECCLASS_WINDOW, WINDOW__CLIENTCOMEVENT, "clientcomevent") + S_(SECCLASS_WINDOW, WINDOW__INPUTEVENT, "inputevent") + S_(SECCLASS_WINDOW, WINDOW__DRAWEVENT, "drawevent") + S_(SECCLASS_WINDOW, WINDOW__WINDOWCHANGEEVENT, "windowchangeevent") + S_(SECCLASS_WINDOW, WINDOW__WINDOWCHANGEREQUEST, "windowchangerequest") + S_(SECCLASS_WINDOW, WINDOW__SERVERCHANGEEVENT, "serverchangeevent") + S_(SECCLASS_WINDOW, WINDOW__EXTENSIONEVENT, "extensionevent") + S_(SECCLASS_FONT, FONT__LOAD, "load") + S_(SECCLASS_FONT, FONT__FREE, "free") + S_(SECCLASS_FONT, FONT__GETATTR, "getattr") + S_(SECCLASS_FONT, FONT__USE, "use") + S_(SECCLASS_COLORMAP, COLORMAP__CREATE, "create") + S_(SECCLASS_COLORMAP, COLORMAP__FREE, "free") + S_(SECCLASS_COLORMAP, COLORMAP__INSTALL, "install") + S_(SECCLASS_COLORMAP, COLORMAP__UNINSTALL, "uninstall") + S_(SECCLASS_COLORMAP, COLORMAP__LIST, "list") + S_(SECCLASS_COLORMAP, COLORMAP__READ, "read") + S_(SECCLASS_COLORMAP, COLORMAP__STORE, "store") + S_(SECCLASS_COLORMAP, COLORMAP__GETATTR, "getattr") + S_(SECCLASS_COLORMAP, COLORMAP__SETATTR, "setattr") + S_(SECCLASS_PROPERTY, PROPERTY__CREATE, "create") + S_(SECCLASS_PROPERTY, PROPERTY__FREE, "free") + S_(SECCLASS_PROPERTY, PROPERTY__READ, "read") + S_(SECCLASS_PROPERTY, PROPERTY__WRITE, "write") + S_(SECCLASS_CURSOR, CURSOR__CREATE, "create") + S_(SECCLASS_CURSOR, CURSOR__CREATEGLYPH, "createglyph") + S_(SECCLASS_CURSOR, CURSOR__FREE, "free") + S_(SECCLASS_CURSOR, CURSOR__ASSIGN, "assign") + S_(SECCLASS_CURSOR, CURSOR__SETATTR, "setattr") + S_(SECCLASS_XCLIENT, XCLIENT__KILL, "kill") + S_(SECCLASS_XINPUT, XINPUT__LOOKUP, "lookup") + S_(SECCLASS_XINPUT, XINPUT__GETATTR, "getattr") + S_(SECCLASS_XINPUT, XINPUT__SETATTR, "setattr") + S_(SECCLASS_XINPUT, XINPUT__SETFOCUS, "setfocus") + S_(SECCLASS_XINPUT, XINPUT__WARPPOINTER, "warppointer") + S_(SECCLASS_XINPUT, XINPUT__ACTIVEGRAB, "activegrab") + S_(SECCLASS_XINPUT, XINPUT__PASSIVEGRAB, "passivegrab") + S_(SECCLASS_XINPUT, XINPUT__UNGRAB, "ungrab") + S_(SECCLASS_XINPUT, XINPUT__BELL, "bell") + S_(SECCLASS_XINPUT, XINPUT__MOUSEMOTION, "mousemotion") + S_(SECCLASS_XINPUT, XINPUT__RELABELINPUT, "relabelinput") + S_(SECCLASS_XSERVER, XSERVER__SCREENSAVER, "screensaver") + S_(SECCLASS_XSERVER, XSERVER__GETHOSTLIST, "gethostlist") + S_(SECCLASS_XSERVER, XSERVER__SETHOSTLIST, "sethostlist") + S_(SECCLASS_XSERVER, XSERVER__GETFONTPATH, "getfontpath") + S_(SECCLASS_XSERVER, XSERVER__SETFONTPATH, "setfontpath") + S_(SECCLASS_XSERVER, XSERVER__GETATTR, "getattr") + S_(SECCLASS_XSERVER, XSERVER__GRAB, "grab") + S_(SECCLASS_XSERVER, XSERVER__UNGRAB, "ungrab") + S_(SECCLASS_XEXTENSION, XEXTENSION__QUERY, "query") + S_(SECCLASS_XEXTENSION, XEXTENSION__USE, "use") + S_(SECCLASS_PAX, PAX__PAGEEXEC, "pageexec") + S_(SECCLASS_PAX, PAX__EMUTRAMP, "emutramp") + S_(SECCLASS_PAX, PAX__MPROTECT, "mprotect") + S_(SECCLASS_PAX, PAX__RANDMMAP, "randmmap") + S_(SECCLASS_PAX, PAX__RANDEXEC, "randexec") + S_(SECCLASS_PAX, PAX__SEGMEXEC, "segmexec") + S_(SECCLASS_NETLINK_ROUTE_SOCKET, NETLINK_ROUTE_SOCKET__NLMSG_READ, "nlmsg_read") + S_(SECCLASS_NETLINK_ROUTE_SOCKET, NETLINK_ROUTE_SOCKET__NLMSG_WRITE, "nlmsg_write") + S_(SECCLASS_NETLINK_FIREWALL_SOCKET, NETLINK_FIREWALL_SOCKET__NLMSG_READ, "nlmsg_read") + S_(SECCLASS_NETLINK_FIREWALL_SOCKET, NETLINK_FIREWALL_SOCKET__NLMSG_WRITE, "nlmsg_write") + S_(SECCLASS_NETLINK_TCPDIAG_SOCKET, NETLINK_TCPDIAG_SOCKET__NLMSG_READ, "nlmsg_read") + S_(SECCLASS_NETLINK_TCPDIAG_SOCKET, NETLINK_TCPDIAG_SOCKET__NLMSG_WRITE, "nlmsg_write") + S_(SECCLASS_NETLINK_XFRM_SOCKET, NETLINK_XFRM_SOCKET__NLMSG_READ, "nlmsg_read") + S_(SECCLASS_NETLINK_XFRM_SOCKET, NETLINK_XFRM_SOCKET__NLMSG_WRITE, "nlmsg_write") + S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_READ, "nlmsg_read") + S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_WRITE, "nlmsg_write") + S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_RELAY, "nlmsg_relay") + S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_READPRIV, "nlmsg_readpriv") + S_(SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_READ, "nlmsg_read") + S_(SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_WRITE, "nlmsg_write") + S_(SECCLASS_DBUS, DBUS__ACQUIRE_SVC, "acquire_svc") + S_(SECCLASS_DBUS, DBUS__SEND_MSG, "send_msg") + S_(SECCLASS_NSCD, NSCD__GETPWD, "getpwd") + S_(SECCLASS_NSCD, NSCD__GETGRP, "getgrp") + S_(SECCLASS_NSCD, NSCD__GETHOST, "gethost") + S_(SECCLASS_NSCD, NSCD__GETSTAT, "getstat") + S_(SECCLASS_NSCD, NSCD__ADMIN, "admin") + S_(SECCLASS_NSCD, NSCD__SHMEMPWD, "shmempwd") + S_(SECCLASS_NSCD, NSCD__SHMEMGRP, "shmemgrp") + S_(SECCLASS_NSCD, NSCD__SHMEMHOST, "shmemhost") + S_(SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, "sendto") + S_(SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, "recvfrom") diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h index 65141ec0c..bdfce4ca8 100644 --- a/security/selinux/include/av_permissions.h +++ b/security/selinux/include/av_permissions.h @@ -1,6 +1,4 @@ /* This file is automatically generated. Do not edit. */ -/* FLASK */ - #define COMMON_FILE__IOCTL 0x00000001UL #define COMMON_FILE__READ 0x00000002UL #define COMMON_FILE__WRITE 0x00000004UL @@ -107,6 +105,7 @@ #define FILE__EXECUTE_NO_TRANS 0x00020000UL #define FILE__ENTRYPOINT 0x00040000UL +#define FILE__EXECMOD 0x00080000UL #define LNK_FILE__IOCTL 0x00000001UL #define LNK_FILE__READ 0x00000002UL @@ -144,6 +143,10 @@ #define CHR_FILE__QUOTAON 0x00008000UL #define CHR_FILE__MOUNTON 0x00010000UL +#define CHR_FILE__EXECUTE_NO_TRANS 0x00020000UL +#define CHR_FILE__ENTRYPOINT 0x00040000UL +#define CHR_FILE__EXECMOD 0x00080000UL + #define BLK_FILE__IOCTL 0x00000001UL #define BLK_FILE__READ 0x00000002UL #define BLK_FILE__WRITE 0x00000004UL @@ -250,6 +253,7 @@ #define TCP_SOCKET__NEWCONN 0x00800000UL #define TCP_SOCKET__ACCEPTFROM 0x01000000UL #define TCP_SOCKET__NODE_BIND 0x02000000UL +#define TCP_SOCKET__NAME_CONNECT 0x04000000UL #define UDP_SOCKET__IOCTL 0x00000001UL #define UDP_SOCKET__READ 0x00000002UL @@ -458,6 +462,9 @@ #define PROCESS__SIGINH 0x00100000UL #define PROCESS__SETRLIMIT 0x00200000UL #define PROCESS__RLIMITINH 0x00400000UL +#define PROCESS__DYNTRANSITION 0x00800000UL +#define PROCESS__SETCURRENT 0x01000000UL +#define PROCESS__EXECMEM 0x02000000UL #define IPC__CREATE 0x00000001UL #define IPC__DESTROY 0x00000002UL @@ -516,6 +523,7 @@ #define SECURITY__SETENFORCE 0x00000080UL #define SECURITY__SETBOOL 0x00000100UL #define SECURITY__SETSECPARAM 0x00000200UL +#define SECURITY__SETCHECKREQPROT 0x00000400UL #define SYSTEM__IPC_INFO 0x00000001UL #define SYSTEM__SYSLOG_READ 0x00000002UL @@ -551,11 +559,14 @@ #define CAPABILITY__SYS_TTY_CONFIG 0x04000000UL #define CAPABILITY__MKNOD 0x08000000UL #define CAPABILITY__LEASE 0x10000000UL +#define CAPABILITY__AUDIT_WRITE 0x20000000UL +#define CAPABILITY__AUDIT_CONTROL 0x40000000UL #define PASSWD__PASSWD 0x00000001UL #define PASSWD__CHFN 0x00000002UL #define PASSWD__CHSH 0x00000004UL #define PASSWD__ROOTOK 0x00000008UL +#define PASSWD__CRONTAB 0x00000010UL #define DRAWABLE__CREATE 0x00000001UL #define DRAWABLE__DESTROY 0x00000002UL @@ -829,6 +840,8 @@ #define NETLINK_AUDIT_SOCKET__NLMSG_READ 0x00400000UL #define NETLINK_AUDIT_SOCKET__NLMSG_WRITE 0x00800000UL +#define NETLINK_AUDIT_SOCKET__NLMSG_RELAY 0x01000000UL +#define NETLINK_AUDIT_SOCKET__NLMSG_READPRIV 0x02000000UL #define NETLINK_IP6FW_SOCKET__IOCTL 0x00000001UL #define NETLINK_IP6FW_SOCKET__READ 0x00000002UL @@ -877,5 +890,43 @@ #define NETLINK_DNRT_SOCKET__SENDTO 0x00040000UL #define NETLINK_DNRT_SOCKET__RECV_MSG 0x00080000UL #define NETLINK_DNRT_SOCKET__SEND_MSG 0x00100000UL +#define NETLINK_DNRT_SOCKET__NAME_BIND 0x00200000UL + +#define DBUS__ACQUIRE_SVC 0x00000001UL +#define DBUS__SEND_MSG 0x00000002UL + +#define NSCD__GETPWD 0x00000001UL +#define NSCD__GETGRP 0x00000002UL +#define NSCD__GETHOST 0x00000004UL +#define NSCD__GETSTAT 0x00000008UL +#define NSCD__ADMIN 0x00000010UL +#define NSCD__SHMEMPWD 0x00000020UL +#define NSCD__SHMEMGRP 0x00000040UL +#define NSCD__SHMEMHOST 0x00000080UL + +#define ASSOCIATION__SENDTO 0x00000001UL +#define ASSOCIATION__RECVFROM 0x00000002UL + +#define NETLINK_KOBJECT_UEVENT_SOCKET__IOCTL 0x00000001UL +#define NETLINK_KOBJECT_UEVENT_SOCKET__READ 0x00000002UL +#define NETLINK_KOBJECT_UEVENT_SOCKET__WRITE 0x00000004UL +#define NETLINK_KOBJECT_UEVENT_SOCKET__CREATE 0x00000008UL +#define NETLINK_KOBJECT_UEVENT_SOCKET__GETATTR 0x00000010UL +#define NETLINK_KOBJECT_UEVENT_SOCKET__SETATTR 0x00000020UL +#define NETLINK_KOBJECT_UEVENT_SOCKET__LOCK 0x00000040UL +#define NETLINK_KOBJECT_UEVENT_SOCKET__RELABELFROM 0x00000080UL +#define NETLINK_KOBJECT_UEVENT_SOCKET__RELABELTO 0x00000100UL +#define NETLINK_KOBJECT_UEVENT_SOCKET__APPEND 0x00000200UL +#define NETLINK_KOBJECT_UEVENT_SOCKET__BIND 0x00000400UL +#define NETLINK_KOBJECT_UEVENT_SOCKET__CONNECT 0x00000800UL +#define NETLINK_KOBJECT_UEVENT_SOCKET__LISTEN 0x00001000UL +#define NETLINK_KOBJECT_UEVENT_SOCKET__ACCEPT 0x00002000UL +#define NETLINK_KOBJECT_UEVENT_SOCKET__GETOPT 0x00004000UL +#define NETLINK_KOBJECT_UEVENT_SOCKET__SETOPT 0x00008000UL +#define NETLINK_KOBJECT_UEVENT_SOCKET__SHUTDOWN 0x00010000UL +#define NETLINK_KOBJECT_UEVENT_SOCKET__RECVFROM 0x00020000UL +#define NETLINK_KOBJECT_UEVENT_SOCKET__SENDTO 0x00040000UL +#define NETLINK_KOBJECT_UEVENT_SOCKET__RECV_MSG 0x00080000UL +#define NETLINK_KOBJECT_UEVENT_SOCKET__SEND_MSG 0x00100000UL +#define NETLINK_KOBJECT_UEVENT_SOCKET__NAME_BIND 0x00200000UL -/* FLASK */ diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index ca2fdf557..960ef18dd 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h @@ -92,13 +92,6 @@ struct avc_cache_stats unsigned int frees; }; -/* - * AVC display support - */ -struct audit_buffer; -void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av); -void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tclass); - /* * AVC operations */ diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h index a65e25eb6..77b2c5996 100644 --- a/security/selinux/include/class_to_string.h +++ b/security/selinux/include/class_to_string.h @@ -2,59 +2,59 @@ /* * Security object class definitions */ -static char *class_to_string[] = -{ - "null", - "security", - "process", - "system", - "capability", - "filesystem", - "file", - "dir", - "fd", - "lnk_file", - "chr_file", - "blk_file", - "sock_file", - "fifo_file", - "socket", - "tcp_socket", - "udp_socket", - "rawip_socket", - "node", - "netif", - "netlink_socket", - "packet_socket", - "key_socket", - "unix_stream_socket", - "unix_dgram_socket", - "sem", - "msg", - "msgq", - "shm", - "ipc", - "passwd", - "drawable", - "window", - "gc", - "font", - "colormap", - "property", - "cursor", - "xclient", - "xinput", - "xserver", - "xextension", - "pax", - "netlink_route_socket", - "netlink_firewall_socket", - "netlink_tcpdiag_socket", - "netlink_nflog_socket", - "netlink_xfrm_socket", - "netlink_selinux_socket", - "netlink_audit_socket", - "netlink_ip6fw_socket", - "netlink_dnrt_socket", -}; - + S_("null") + S_("security") + S_("process") + S_("system") + S_("capability") + S_("filesystem") + S_("file") + S_("dir") + S_("fd") + S_("lnk_file") + S_("chr_file") + S_("blk_file") + S_("sock_file") + S_("fifo_file") + S_("socket") + S_("tcp_socket") + S_("udp_socket") + S_("rawip_socket") + S_("node") + S_("netif") + S_("netlink_socket") + S_("packet_socket") + S_("key_socket") + S_("unix_stream_socket") + S_("unix_dgram_socket") + S_("sem") + S_("msg") + S_("msgq") + S_("shm") + S_("ipc") + S_("passwd") + S_("drawable") + S_("window") + S_("gc") + S_("font") + S_("colormap") + S_("property") + S_("cursor") + S_("xclient") + S_("xinput") + S_("xserver") + S_("xextension") + S_("pax") + S_("netlink_route_socket") + S_("netlink_firewall_socket") + S_("netlink_tcpdiag_socket") + S_("netlink_nflog_socket") + S_("netlink_xfrm_socket") + S_("netlink_selinux_socket") + S_("netlink_audit_socket") + S_("netlink_ip6fw_socket") + S_("netlink_dnrt_socket") + S_("dbus") + S_("nscd") + S_("association") + S_("netlink_kobject_uevent_socket") diff --git a/security/selinux/include/flask.h b/security/selinux/include/flask.h index a392a3d06..eb9f50823 100644 --- a/security/selinux/include/flask.h +++ b/security/selinux/include/flask.h @@ -56,6 +56,10 @@ #define SECCLASS_NETLINK_AUDIT_SOCKET 49 #define SECCLASS_NETLINK_IP6FW_SOCKET 50 #define SECCLASS_NETLINK_DNRT_SOCKET 51 +#define SECCLASS_DBUS 52 +#define SECCLASS_NSCD 53 +#define SECCLASS_ASSOCIATION 54 +#define SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET 55 /* * Security identifier indices for initial entities diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index d1516e47e..887937c81 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -87,6 +87,12 @@ struct bprm_security_struct { struct linux_binprm *bprm; /* back pointer to bprm object */ u32 sid; /* SID for transformed process */ unsigned char set; + + /* + * unsafe is used to share failure information from bprm_apply_creds() + * to bprm_post_apply_creds(). + */ + char unsafe; }; struct netif_security_struct { @@ -101,6 +107,6 @@ struct sk_security_struct { u32 peer_sid; /* SID of peer */ }; -extern int inode_security_set_sid(struct inode *inode, u32 sid); +extern unsigned int selinux_checkreqprot; #endif /* _SELINUX_OBJSEC_H_ */ diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 5931e46d4..fa187c9a3 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -21,10 +21,12 @@ #define POLICYDB_VERSION_BOOL 16 #define POLICYDB_VERSION_IPV6 17 #define POLICYDB_VERSION_NLCLASS 18 +#define POLICYDB_VERSION_VALIDATETRANS 19 +#define POLICYDB_VERSION_MLS 19 /* Range of policy versions we understand*/ #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE -#define POLICYDB_VERSION_MAX POLICYDB_VERSION_NLCLASS +#define POLICYDB_VERSION_MAX POLICYDB_VERSION_MLS #ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM extern int selinux_enabled; @@ -32,11 +34,7 @@ extern int selinux_enabled; #define selinux_enabled 1 #endif -#ifdef CONFIG_SECURITY_SELINUX_MLS -#define selinux_mls_enabled 1 -#else -#define selinux_mls_enabled 0 -#endif +extern int selinux_mls_enabled; int security_load_policy(void * data, size_t len); @@ -79,6 +77,9 @@ int security_netif_sid(char *name, u32 *if_sid, int security_node_sid(u16 domain, void *addr, u32 addrlen, u32 *out_sid); +int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, + u16 tclass); + #define SECURITY_FS_USE_XATTR 1 /* use xattr */ #define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */ #define SECURITY_FS_USE_TASK 3 /* use task SIDs, e.g. pipefs/sockfs */ diff --git a/security/selinux/netif.c b/security/selinux/netif.c index e3ffae522..718d7be9f 100644 --- a/security/selinux/netif.c +++ b/security/selinux/netif.c @@ -45,7 +45,7 @@ struct sel_netif static u32 sel_netif_total; static LIST_HEAD(sel_netif_list); -static spinlock_t sel_netif_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(sel_netif_lock); static struct list_head sel_netif_hash[SEL_NETIF_HASH_SIZE]; static inline u32 sel_netif_hasfn(struct net_device *dev) diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index ddc39ffee..07221568b 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -34,6 +34,16 @@ #include "objsec.h" #include "conditional.h" +unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE; + +static int __init checkreqprot_setup(char *str) +{ + selinux_checkreqprot = simple_strtoul(str,NULL,0) ? 1 : 0; + return 1; +} +__setup("checkreqprot=", checkreqprot_setup); + + static DECLARE_MUTEX(sel_sem); /* global data for booleans */ @@ -44,8 +54,8 @@ static int *bool_pending_values = NULL; extern void selnl_notify_setenforce(int val); /* Check whether a task is allowed to use a security operation. */ -int task_has_security(struct task_struct *tsk, - u32 perms) +static int task_has_security(struct task_struct *tsk, + u32 perms) { struct task_security_struct *tsec; @@ -71,6 +81,8 @@ enum sel_inos { SEL_MLS, /* return if MLS policy is enabled */ SEL_DISABLE, /* disable SELinux until next reboot */ SEL_AVC, /* AVC management directory */ + SEL_MEMBER, /* compute polyinstantiation membership decision */ + SEL_CHECKREQPROT, /* check requested protection, not kernel-applied one */ }; #define TMPBUFLEN 12 @@ -299,6 +311,54 @@ static struct file_operations sel_context_ops = { .write = sel_write_context, }; +static ssize_t sel_read_checkreqprot(struct file *filp, char __user *buf, + size_t count, loff_t *ppos) +{ + char tmpbuf[TMPBUFLEN]; + ssize_t length; + + length = scnprintf(tmpbuf, TMPBUFLEN, "%u", selinux_checkreqprot); + return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); +} + +static ssize_t sel_write_checkreqprot(struct file * file, const char __user * buf, + size_t count, loff_t *ppos) +{ + char *page; + ssize_t length; + unsigned int new_value; + + length = task_has_security(current, SECURITY__SETCHECKREQPROT); + if (length) + return length; + + if (count < 0 || count >= PAGE_SIZE) + return -ENOMEM; + if (*ppos != 0) { + /* No partial writes. */ + return -EINVAL; + } + page = (char*)get_zeroed_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + length = -EFAULT; + if (copy_from_user(page, buf, count)) + goto out; + + length = -EINVAL; + if (sscanf(page, "%u", &new_value) != 1) + goto out; + + selinux_checkreqprot = new_value ? 1 : 0; + length = count; +out: + free_page((unsigned long) page); + return length; +} +static struct file_operations sel_checkreqprot_ops = { + .read = sel_read_checkreqprot, + .write = sel_write_checkreqprot, +}; /* * Remaining nodes use transaction based IO methods like nfsd/nfsctl.c @@ -307,12 +367,14 @@ static ssize_t sel_write_access(struct file * file, char *buf, size_t size); static ssize_t sel_write_create(struct file * file, char *buf, size_t size); static ssize_t sel_write_relabel(struct file * file, char *buf, size_t size); static ssize_t sel_write_user(struct file * file, char *buf, size_t size); +static ssize_t sel_write_member(struct file * file, char *buf, size_t size); static ssize_t (*write_op[])(struct file *, char *, size_t) = { [SEL_ACCESS] = sel_write_access, [SEL_CREATE] = sel_write_create, [SEL_RELABEL] = sel_write_relabel, [SEL_USER] = sel_write_user, + [SEL_MEMBER] = sel_write_member, }; static ssize_t selinux_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos) @@ -582,6 +644,67 @@ out: return length; } +static ssize_t sel_write_member(struct file * file, char *buf, size_t size) +{ + char *scon, *tcon; + u32 ssid, tsid, newsid; + u16 tclass; + ssize_t length; + char *newcon; + u32 len; + + length = task_has_security(current, SECURITY__COMPUTE_MEMBER); + if (length) + return length; + + length = -ENOMEM; + scon = kmalloc(size+1, GFP_KERNEL); + if (!scon) + return length; + memset(scon, 0, size+1); + + tcon = kmalloc(size+1, GFP_KERNEL); + if (!tcon) + goto out; + memset(tcon, 0, size+1); + + length = -EINVAL; + if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) + goto out2; + + length = security_context_to_sid(scon, strlen(scon)+1, &ssid); + if (length < 0) + goto out2; + length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid); + if (length < 0) + goto out2; + + length = security_member_sid(ssid, tsid, tclass, &newsid); + if (length < 0) + goto out2; + + length = security_sid_to_context(newsid, &newcon, &len); + if (length < 0) + goto out2; + + if (len > SIMPLE_TRANSACTION_LIMIT) { + printk(KERN_ERR "%s: context size (%u) exceeds payload " + "max\n", __FUNCTION__, len); + length = -ERANGE; + goto out3; + } + + memcpy(buf, newcon, len); + length = len; +out3: + kfree(newcon); +out2: + kfree(tcon); +out: + kfree(scon); + return length; +} + static struct inode *sel_make_inode(struct super_block *sb, int mode) { struct inode *ret = new_inode(sb); @@ -946,7 +1069,7 @@ static ssize_t sel_write_avc_cache_threshold(struct file * file, ret = count; out_free: free_page((unsigned long)page); -out: +out: return ret; } @@ -955,7 +1078,7 @@ static ssize_t sel_read_avc_hash_stats(struct file *filp, char __user *buf, { char *page; ssize_t ret = 0; - + page = (char *)__get_free_page(GFP_KERNEL); if (!page) { ret = -ENOMEM; @@ -982,7 +1105,7 @@ static struct file_operations sel_avc_hash_stats_ops = { static struct avc_cache_stats *sel_avc_get_stat_idx(loff_t *idx) { int cpu; - + for (cpu = *idx; cpu < NR_CPUS; ++cpu) { if (!cpu_possible(cpu)) continue; @@ -998,7 +1121,7 @@ static void *sel_avc_stats_seq_start(struct seq_file *seq, loff_t *pos) if (*pos == 0) return SEQ_START_TOKEN; - + return sel_avc_get_stat_idx(&n); } @@ -1010,7 +1133,7 @@ static void *sel_avc_stats_seq_next(struct seq_file *seq, void *v, loff_t *pos) static int sel_avc_stats_seq_show(struct seq_file *seq, void *v) { struct avc_cache_stats *st = v; - + if (v == SEQ_START_TOKEN) seq_printf(seq, "lookups hits misses allocations reclaims " "frees\n"); @@ -1044,17 +1167,6 @@ static struct file_operations sel_avc_cache_stats_ops = { }; #endif -/* XXX upstream: d_alloc_name() */ -struct dentry *sel_alloc_name(struct dentry *parent, const char *name) -{ - struct qstr q; - - q.name = name; - q.len = strlen(name); - q.hash = full_name_hash(q.name, q.len); - return d_alloc(parent, &q); -} - static int sel_make_avc_files(struct dentry *dir) { int i, ret = 0; @@ -1071,7 +1183,7 @@ static int sel_make_avc_files(struct dentry *dir) struct inode *inode; struct dentry *dentry; - dentry = sel_alloc_name(dir, files[i].name); + dentry = d_alloc_name(dir, files[i].name); if (!dentry) { ret = -ENOMEM; goto err; @@ -1105,7 +1217,7 @@ static int sel_make_dir(struct super_block *sb, struct dentry *dentry) inode->i_op = &simple_dir_inode_operations; inode->i_fop = &simple_dir_operations; d_add(dentry, inode); -out: +out: return ret; } @@ -1128,6 +1240,8 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent) [SEL_COMMIT_BOOLS] = {"commit_pending_bools", &sel_commit_bools_ops, S_IWUSR}, [SEL_MLS] = {"mls", &sel_mls_ops, S_IRUGO}, [SEL_DISABLE] = {"disable", &sel_disable_ops, S_IWUSR}, + [SEL_MEMBER] = {"member", &transaction_ops, S_IRUGO|S_IWUGO}, + [SEL_CHECKREQPROT] = {"checkreqprot", &sel_checkreqprot_ops, S_IRUGO|S_IWUSR}, /* last one */ {""} }; ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files); @@ -1164,19 +1278,19 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent) init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, MKDEV(MEM_MAJOR, 3)); d_add(dentry, inode); selinux_null = dentry; - - dentry = sel_alloc_name(sb->s_root, "avc"); + + dentry = d_alloc_name(sb->s_root, "avc"); if (!dentry) return -ENOMEM; - + ret = sel_make_dir(sb, dentry); if (ret) goto out; - + ret = sel_make_avc_files(dentry); if (ret) goto out; - + return 0; out: dput(dentry); diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index bcfec7674..f238c034c 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c @@ -31,7 +31,8 @@ static kmem_cache_t *avtab_node_cachep; static struct avtab_node* -avtab_insert_node(struct avtab *h, int hvalue, struct avtab_node * prev, struct avtab_node * cur, +avtab_insert_node(struct avtab *h, int hvalue, + struct avtab_node * prev, struct avtab_node * cur, struct avtab_key *key, struct avtab_datum *datum) { struct avtab_node * newnode; @@ -53,7 +54,7 @@ avtab_insert_node(struct avtab *h, int hvalue, struct avtab_node * prev, struct return newnode; } -int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum) +static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum) { int hvalue; struct avtab_node *prev, *cur, *newnode; @@ -237,30 +238,6 @@ void avtab_destroy(struct avtab *h) } -int avtab_map(struct avtab *h, - int (*apply) (struct avtab_key *k, - struct avtab_datum *d, - void *args), - void *args) -{ - int i, ret; - struct avtab_node *cur; - - if (!h) - return 0; - - for (i = 0; i < AVTAB_SIZE; i++) { - cur = h->htable[i]; - while (cur != NULL) { - ret = apply(&cur->key, &cur->datum, args); - if (ret) - return ret; - cur = cur->next; - } - } - return 0; -} - int avtab_init(struct avtab *h) { int i; @@ -303,20 +280,25 @@ void avtab_hash_eval(struct avtab *h, char *tag) int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avkey) { - __u32 *buf; - __u32 items, items2; + u32 buf[7]; + u32 items, items2; + int rc; memset(avkey, 0, sizeof(struct avtab_key)); memset(avdatum, 0, sizeof(struct avtab_datum)); - buf = next_entry(fp, sizeof(__u32)); - if (!buf) { + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) { printk(KERN_ERR "security: avtab: truncated entry\n"); goto bad; } items2 = le32_to_cpu(buf[0]); - buf = next_entry(fp, sizeof(__u32)*items2); - if (!buf) { + if (items2 > ARRAY_SIZE(buf)) { + printk(KERN_ERR "security: avtab: entry overflow\n"); + goto bad; + } + rc = next_entry(buf, fp, sizeof(u32)*items2); + if (rc < 0) { printk(KERN_ERR "security: avtab: truncated entry\n"); goto bad; } @@ -362,26 +344,29 @@ bad: int avtab_read(struct avtab *a, void *fp, u32 config) { - int i, rc = -EINVAL; + int rc; struct avtab_key avkey; struct avtab_datum avdatum; - u32 *buf; - u32 nel; + u32 buf[1]; + u32 nel, i; - buf = next_entry(fp, sizeof(u32)); - if (!buf) { + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) { printk(KERN_ERR "security: avtab: truncated table\n"); goto bad; } nel = le32_to_cpu(buf[0]); if (!nel) { printk(KERN_ERR "security: avtab: table is empty\n"); + rc = -EINVAL; goto bad; } for (i = 0; i < nel; i++) { - if (avtab_read_item(fp, &avdatum, &avkey)) + if (avtab_read_item(fp, &avdatum, &avkey)) { + rc = -EINVAL; goto bad; + } rc = avtab_insert(a, &avkey, &avdatum); if (rc) { if (rc == -ENOMEM) diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h index f636ac844..519d4f6dc 100644 --- a/security/selinux/ss/avtab.h +++ b/security/selinux/ss/avtab.h @@ -58,14 +58,8 @@ struct avtab { }; int avtab_init(struct avtab *); -int avtab_insert(struct avtab *h, struct avtab_key *k, struct avtab_datum *d); struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *k, int specified); void avtab_destroy(struct avtab *h); -int avtab_map(struct avtab *h, - int (*apply) (struct avtab_key *k, - struct avtab_datum *d, - void *args), - void *args); void avtab_hash_eval(struct avtab *h, char *tag); int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avkey); diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c index f8958ba34..b53441184 100644 --- a/security/selinux/ss/conditional.c +++ b/security/selinux/ss/conditional.c @@ -208,7 +208,7 @@ int cond_index_bool(void *key, void *datum, void *datap) return 0; } -int bool_isvalid(struct cond_bool_datum *b) +static int bool_isvalid(struct cond_bool_datum *b) { if (!(b->state == 0 || b->state == 1)) return 0; @@ -219,15 +219,16 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp) { char *key = NULL; struct cond_bool_datum *booldatum; - __u32 *buf, len; + u32 buf[3], len; + int rc; booldatum = kmalloc(sizeof(struct cond_bool_datum), GFP_KERNEL); if (!booldatum) return -1; memset(booldatum, 0, sizeof(struct cond_bool_datum)); - buf = next_entry(fp, sizeof(__u32) * 3); - if (!buf) + rc = next_entry(buf, fp, sizeof buf); + if (rc < 0) goto err; booldatum->value = le32_to_cpu(buf[0]); @@ -238,13 +239,12 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp) len = le32_to_cpu(buf[2]); - buf = next_entry(fp, len); - if (!buf) - goto err; key = kmalloc(len + 1, GFP_KERNEL); if (!key) goto err; - memcpy(key, buf, len); + rc = next_entry(key, fp, len); + if (rc < 0) + goto err; key[len] = 0; if (hashtab_insert(h, key, booldatum)) goto err; @@ -262,15 +262,15 @@ static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list * struct avtab_key key; struct avtab_datum datum; struct avtab_node *node_ptr; - int len, i; - __u32 *buf; - __u8 found; + int rc; + u32 buf[1], i, len; + u8 found; *ret_list = NULL; len = 0; - buf = next_entry(fp, sizeof(__u32)); - if (!buf) + rc = next_entry(buf, fp, sizeof buf); + if (rc < 0) return -1; len = le32_to_cpu(buf[0]); @@ -369,27 +369,27 @@ static int expr_isvalid(struct policydb *p, struct cond_expr *expr) static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp) { - __u32 *buf; - int len, i; + u32 buf[2], len, i; + int rc; struct cond_expr *expr = NULL, *last = NULL; - buf = next_entry(fp, sizeof(__u32)); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) return -1; node->cur_state = le32_to_cpu(buf[0]); len = 0; - buf = next_entry(fp, sizeof(__u32)); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) return -1; /* expr */ len = le32_to_cpu(buf[0]); for (i = 0; i < len; i++ ) { - buf = next_entry(fp, sizeof(__u32) * 2); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32) * 2); + if (rc < 0) goto err; expr = kmalloc(sizeof(struct cond_expr), GFP_KERNEL); @@ -401,8 +401,10 @@ static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp) expr->expr_type = le32_to_cpu(buf[0]); expr->bool = le32_to_cpu(buf[1]); - if (!expr_isvalid(p, expr)) + if (!expr_isvalid(p, expr)) { + kfree(expr); goto err; + } if (i == 0) { node->expr = expr; @@ -425,11 +427,11 @@ err: int cond_read_list(struct policydb *p, void *fp) { struct cond_node *node, *last = NULL; - __u32 *buf; - int i, len; + u32 buf[1], i, len; + int rc; - buf = next_entry(fp, sizeof(__u32)); - if (!buf) + rc = next_entry(buf, fp, sizeof buf); + if (rc < 0) return -1; len = le32_to_cpu(buf[0]); diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index 0912af410..d8ce9cc0b 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c @@ -9,49 +9,6 @@ #include "ebitmap.h" #include "policydb.h" -int ebitmap_or(struct ebitmap *dst, struct ebitmap *e1, struct ebitmap *e2) -{ - struct ebitmap_node *n1, *n2, *new, *prev; - - ebitmap_init(dst); - - n1 = e1->node; - n2 = e2->node; - prev = NULL; - while (n1 || n2) { - new = kmalloc(sizeof(*new), GFP_ATOMIC); - if (!new) { - ebitmap_destroy(dst); - return -ENOMEM; - } - memset(new, 0, sizeof(*new)); - if (n1 && n2 && n1->startbit == n2->startbit) { - new->startbit = n1->startbit; - new->map = n1->map | n2->map; - n1 = n1->next; - n2 = n2->next; - } else if (!n2 || (n1 && n1->startbit < n2->startbit)) { - new->startbit = n1->startbit; - new->map = n1->map; - n1 = n1->next; - } else { - new->startbit = n2->startbit; - new->map = n2->map; - n2 = n2->next; - } - - new->next = NULL; - if (prev) - prev->next = new; - else - dst->node = new; - prev = new; - } - - dst->highbit = (e1->highbit > e2->highbit) ? e1->highbit : e2->highbit; - return 0; -} - int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2) { struct ebitmap_node *n1, *n2; @@ -237,15 +194,15 @@ void ebitmap_destroy(struct ebitmap *e) int ebitmap_read(struct ebitmap *e, void *fp) { - int rc = -EINVAL; + int rc; struct ebitmap_node *n, *l; - u32 *buf, mapsize, count, i; + u32 buf[3], mapsize, count, i; u64 map; ebitmap_init(e); - buf = next_entry(fp, sizeof(u32)*3); - if (!buf) + rc = next_entry(buf, fp, sizeof buf); + if (rc < 0) goto out; mapsize = le32_to_cpu(buf[0]); @@ -256,7 +213,7 @@ int ebitmap_read(struct ebitmap *e, void *fp) printk(KERN_ERR "security: ebitmap: map size %u does not " "match my size %Zd (high bit was %d)\n", mapsize, MAPSIZE, e->highbit); - goto out; + goto bad; } if (!e->highbit) { e->node = NULL; @@ -269,8 +226,8 @@ int ebitmap_read(struct ebitmap *e, void *fp) } l = NULL; for (i = 0; i < count; i++) { - buf = next_entry(fp, sizeof(u32)); - if (!buf) { + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) { printk(KERN_ERR "security: ebitmap: truncated map\n"); goto bad; } @@ -296,12 +253,11 @@ int ebitmap_read(struct ebitmap *e, void *fp) n->startbit, (e->highbit - MAPSIZE)); goto bad_free; } - buf = next_entry(fp, sizeof(u64)); - if (!buf) { + rc = next_entry(&map, fp, sizeof(u64)); + if (rc < 0) { printk(KERN_ERR "security: ebitmap: truncated map\n"); goto bad_free; } - memcpy(&map, buf, sizeof(u64)); n->map = le64_to_cpu(map); if (!n->map) { @@ -330,6 +286,8 @@ out: bad_free: kfree(n); bad: + if (!rc) + rc = -EINVAL; ebitmap_destroy(e); goto out; } diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index 9f0614150..756036bcc 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c @@ -3,6 +3,14 @@ * * Author : Stephen Smalley, <sds@epoch.ncsc.mil> */ +/* + * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com> + * + * Support for enhanced MLS infrastructure. + * + * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. + */ + #include <linux/kernel.h> #include <linux/slab.h> #include <linux/string.h> @@ -11,80 +19,48 @@ #include "policydb.h" #include "services.h" -/* - * Remove any permissions from `allowed' that are - * denied by the MLS policy. - */ -void mls_compute_av(struct context *scontext, - struct context *tcontext, - struct class_datum *tclass, - u32 *allowed) -{ - unsigned int rel[2]; - int l; - - for (l = 0; l < 2; l++) - rel[l] = mls_level_relation(scontext->range.level[l], - tcontext->range.level[l]); - - if (rel[1] != MLS_RELATION_EQ) { - if (rel[1] != MLS_RELATION_DOM && - !ebitmap_get_bit(&policydb.trustedreaders, scontext->type - 1) && - !ebitmap_get_bit(&policydb.trustedobjects, tcontext->type - 1)) { - /* read(s,t) = (s.high >= t.high) = False */ - *allowed = (*allowed) & ~(tclass->mlsperms.read); - } - if (rel[1] != MLS_RELATION_DOMBY && - !ebitmap_get_bit(&policydb.trustedreaders, tcontext->type - 1) && - !ebitmap_get_bit(&policydb.trustedobjects, scontext->type - 1)) { - /* readby(s,t) = read(t,s) = False */ - *allowed = (*allowed) & ~(tclass->mlsperms.readby); - } - } - if (((rel[0] != MLS_RELATION_DOMBY && rel[0] != MLS_RELATION_EQ) || - ((!mls_level_eq(tcontext->range.level[0], - tcontext->range.level[1])) && - (rel[1] != MLS_RELATION_DOM && rel[1] != MLS_RELATION_EQ))) && - !ebitmap_get_bit(&policydb.trustedwriters, scontext->type - 1) && - !ebitmap_get_bit(&policydb.trustedobjects, tcontext->type - 1)) { - /* - * write(s,t) = ((s.low <= t.low = t.high) or (s.low - * <= t.low <= t.high <= s.high)) = False - */ - *allowed = (*allowed) & ~(tclass->mlsperms.write); - } - - if (((rel[0] != MLS_RELATION_DOM && rel[0] != MLS_RELATION_EQ) || - ((!mls_level_eq(scontext->range.level[0], - scontext->range.level[1])) && - (rel[1] != MLS_RELATION_DOMBY && rel[1] != MLS_RELATION_EQ))) && - !ebitmap_get_bit(&policydb.trustedwriters, tcontext->type - 1) && - !ebitmap_get_bit(&policydb.trustedobjects, scontext->type - 1)) { - /* writeby(s,t) = write(t,s) = False */ - *allowed = (*allowed) & ~(tclass->mlsperms.writeby); - } -} - /* * Return the length in bytes for the MLS fields of the * security context string representation of `context'. */ int mls_compute_context_len(struct context * context) { - int i, l, len; + int i, l, len, range; + if (!selinux_mls_enabled) + return 0; - len = 0; + len = 1; /* for the beginning ":" */ for (l = 0; l < 2; l++) { - len += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]) + 1; + range = 0; + len += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]); - for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++) - if (ebitmap_get_bit(&context->range.level[l].cat, i - 1)) - len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1; + for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++) { + if (ebitmap_get_bit(&context->range.level[l].cat, i - 1)) { + if (range) { + range++; + continue; + } - if (mls_level_relation(context->range.level[0], context->range.level[1]) - == MLS_RELATION_EQ) - break; + len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1; + range++; + } else { + if (range > 1) + len += strlen(policydb.p_cat_val_to_name[i - 2]) + 1; + range = 0; + } + } + /* Handle case where last category is the end of range */ + if (range > 1) + len += strlen(policydb.p_cat_val_to_name[i - 2]) + 1; + + if (l == 0) { + if (mls_level_eq(&context->range.level[0], + &context->range.level[1])) + break; + else + len++; + } } return len; @@ -95,40 +71,81 @@ int mls_compute_context_len(struct context * context) * the MLS fields of `context' into the string `*scontext'. * Update `*scontext' to point to the end of the MLS fields. */ -int mls_sid_to_context(struct context *context, - char **scontext) +void mls_sid_to_context(struct context *context, + char **scontext) { char *scontextp; - int i, l; + int i, l, range, wrote_sep; + + if (!selinux_mls_enabled) + return; scontextp = *scontext; + *scontextp = ':'; + scontextp++; + for (l = 0; l < 2; l++) { + range = 0; + wrote_sep = 0; strcpy(scontextp, policydb.p_sens_val_to_name[context->range.level[l].sens - 1]); scontextp += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]); - *scontextp = ':'; - scontextp++; - for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++) + + /* categories */ + for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++) { if (ebitmap_get_bit(&context->range.level[l].cat, i - 1)) { + if (range) { + range++; + continue; + } + + if (!wrote_sep) { + *scontextp++ = ':'; + wrote_sep = 1; + } else + *scontextp++ = ','; strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]); scontextp += strlen(policydb.p_cat_val_to_name[i - 1]); - *scontextp = ','; - scontextp++; + range++; + } else { + if (range > 1) { + if (range > 2) + *scontextp++ = '.'; + else + *scontextp++ = ','; + + strcpy(scontextp, policydb.p_cat_val_to_name[i - 2]); + scontextp += strlen(policydb.p_cat_val_to_name[i - 2]); + } + range = 0; } - if (mls_level_relation(context->range.level[0], context->range.level[1]) - != MLS_RELATION_EQ) { - scontextp--; - sprintf(scontextp, "-"); - scontextp++; + } - } else { - break; + /* Handle case where last category is the end of range */ + if (range > 1) { + if (range > 2) + *scontextp++ = '.'; + else + *scontextp++ = ','; + + strcpy(scontextp, policydb.p_cat_val_to_name[i - 2]); + scontextp += strlen(policydb.p_cat_val_to_name[i - 2]); + } + + if (l == 0) { + if (mls_level_eq(&context->range.level[0], + &context->range.level[1])) + break; + else { + *scontextp = '-'; + scontextp++; + } } } *scontext = scontextp; - return 0; + return; } /* @@ -137,20 +154,19 @@ int mls_sid_to_context(struct context *context, */ int mls_context_isvalid(struct policydb *p, struct context *c) { - unsigned int relation; struct level_datum *levdatum; struct user_datum *usrdatum; - struct mls_range_list *rnode; int i, l; + if (!selinux_mls_enabled) + return 1; + /* * MLS range validity checks: high must dominate low, low level must * be valid (category set <-> sensitivity check), and high level must * be valid (category set <-> sensitivity check) */ - relation = mls_level_relation(c->range.level[1], - c->range.level[0]); - if (!(relation & (MLS_RELATION_DOM | MLS_RELATION_EQ))) + if (!mls_level_dom(&c->range.level[1], &c->range.level[0])) /* High does not dominate low. */ return 0; @@ -185,18 +201,12 @@ int mls_context_isvalid(struct policydb *p, struct context *c) if (!c->user || c->user > p->p_users.nprim) return 0; usrdatum = p->user_val_to_struct[c->user - 1]; - for (rnode = usrdatum->ranges; rnode; rnode = rnode->next) { - if (mls_range_contains(rnode->range, c->range)) - break; - } - if (!rnode) - /* user may not be associated with range */ - return 0; + if (!mls_range_contains(usrdatum->range, c->range)) + return 0; /* user may not be associated with range */ return 1; } - /* * Set the MLS fields in the security context structure * `context' based on the string representation in @@ -213,23 +223,17 @@ int mls_context_to_sid(char oldc, { char delim; - char *scontextp, *p; + char *scontextp, *p, *rngptr; struct level_datum *levdatum; - struct cat_datum *catdatum; + struct cat_datum *catdatum, *rngdatum; int l, rc = -EINVAL; - if (!oldc) { - /* No MLS component to the security context. Try - to use a default 'unclassified' value. */ - levdatum = hashtab_search(policydb.p_levels.table, - "unclassified"); - if (!levdatum) - goto out; - context->range.level[0].sens = levdatum->level->sens; - context->range.level[1].sens = context->range.level[0].sens; - rc = 0; + if (!selinux_mls_enabled) + return 0; + + /* No MLS component to the security context. */ + if (!oldc) goto out; - } /* Extract low sensitivity. */ scontextp = p = *scontext; @@ -242,13 +246,15 @@ int mls_context_to_sid(char oldc, for (l = 0; l < 2; l++) { levdatum = hashtab_search(policydb.p_levels.table, scontextp); - if (!levdatum) + if (!levdatum) { + rc = -EINVAL; goto out; + } context->range.level[l].sens = levdatum->level->sens; if (delim == ':') { - /* Extract low category set. */ + /* Extract category set. */ while (1) { scontextp = p; while (*p && *p != ',' && *p != '-') @@ -257,15 +263,46 @@ int mls_context_to_sid(char oldc, if (delim != 0) *p++ = 0; + /* Separate into range if exists */ + if ((rngptr = strchr(scontextp, '.')) != NULL) { + /* Remove '.' */ + *rngptr++ = 0; + } + catdatum = hashtab_search(policydb.p_cats.table, scontextp); - if (!catdatum) + if (!catdatum) { + rc = -EINVAL; goto out; + } rc = ebitmap_set_bit(&context->range.level[l].cat, catdatum->value - 1, 1); if (rc) goto out; + + /* If range, set all categories in range */ + if (rngptr) { + int i; + + rngdatum = hashtab_search(policydb.p_cats.table, rngptr); + if (!rngdatum) { + rc = -EINVAL; + goto out; + } + + if (catdatum->value >= rngdatum->value) { + rc = -EINVAL; + goto out; + } + + for (i = catdatum->value; i < rngdatum->value; i++) { + rc = ebitmap_set_bit(&context->range.level[l].cat, i, 1); + if (rc) + goto out; + } + } + if (delim != ',') break; } @@ -306,7 +343,6 @@ static inline int mls_copy_context(struct context *dst, /* Copy the MLS range from the source context */ for (l = 0; l < 2; l++) { - dst->range.level[l].sens = src->range.level[l].sens; rc = ebitmap_cpy(&dst->range.level[l].cat, &src->range.level[l].cat); @@ -317,6 +353,84 @@ static inline int mls_copy_context(struct context *dst, return rc; } +/* + * Copies the effective MLS range from `src' into `dst'. + */ +static inline int mls_scopy_context(struct context *dst, + struct context *src) +{ + int l, rc = 0; + + /* Copy the MLS range from the source context */ + for (l = 0; l < 2; l++) { + dst->range.level[l].sens = src->range.level[0].sens; + rc = ebitmap_cpy(&dst->range.level[l].cat, + &src->range.level[0].cat); + if (rc) + break; + } + + return rc; +} + +/* + * Copies the MLS range `range' into `context'. + */ +static inline int mls_range_set(struct context *context, + struct mls_range *range) +{ + int l, rc = 0; + + /* Copy the MLS range into the context */ + for (l = 0; l < 2; l++) { + context->range.level[l].sens = range->level[l].sens; + rc = ebitmap_cpy(&context->range.level[l].cat, + &range->level[l].cat); + if (rc) + break; + } + + return rc; +} + +int mls_setup_user_range(struct context *fromcon, struct user_datum *user, + struct context *usercon) +{ + if (selinux_mls_enabled) { + struct mls_level *fromcon_sen = &(fromcon->range.level[0]); + struct mls_level *fromcon_clr = &(fromcon->range.level[1]); + struct mls_level *user_low = &(user->range.level[0]); + struct mls_level *user_clr = &(user->range.level[1]); + struct mls_level *user_def = &(user->dfltlevel); + struct mls_level *usercon_sen = &(usercon->range.level[0]); + struct mls_level *usercon_clr = &(usercon->range.level[1]); + + /* Honor the user's default level if we can */ + if (mls_level_between(user_def, fromcon_sen, fromcon_clr)) { + *usercon_sen = *user_def; + } else if (mls_level_between(fromcon_sen, user_def, user_clr)) { + *usercon_sen = *fromcon_sen; + } else if (mls_level_between(fromcon_clr, user_low, user_def)) { + *usercon_sen = *user_low; + } else + return -EINVAL; + + /* Lower the clearance of available contexts + if the clearance of "fromcon" is lower than + that of the user's default clearance (but + only if the "fromcon" clearance dominates + the user's computed sensitivity level) */ + if (mls_level_dom(user_clr, fromcon_clr)) { + *usercon_clr = *fromcon_clr; + } else if (mls_level_dom(fromcon_clr, user_clr)) { + *usercon_clr = *user_clr; + } else + return -EINVAL; + } + + return 0; +} + /* * Convert the MLS fields in the security context * structure `c' from the values specified in the @@ -331,6 +445,9 @@ int mls_convert_context(struct policydb *oldp, struct ebitmap bitmap; int l, i; + if (!selinux_mls_enabled) + return 0; + for (l = 0; l < 2; l++) { levdatum = hashtab_search(newp->p_levels.table, oldp->p_sens_val_to_name[c->range.level[l].sens - 1]); @@ -366,17 +483,38 @@ int mls_compute_sid(struct context *scontext, u32 specified, struct context *newcontext) { + if (!selinux_mls_enabled) + return 0; + switch (specified) { case AVTAB_TRANSITION: + if (tclass == SECCLASS_PROCESS) { + struct range_trans *rangetr; + /* Look for a range transition rule. */ + for (rangetr = policydb.range_tr; rangetr; + rangetr = rangetr->next) { + if (rangetr->dom == scontext->type && + rangetr->type == tcontext->type) { + /* Set the range from the rule */ + return mls_range_set(newcontext, + &rangetr->range); + } + } + } + /* Fallthrough */ case AVTAB_CHANGE: - /* Use the process MLS attributes. */ - return mls_copy_context(newcontext, scontext); + if (tclass == SECCLASS_PROCESS) + /* Use the process MLS attributes. */ + return mls_copy_context(newcontext, scontext); + else + /* Use the process effective MLS attributes. */ + return mls_scopy_context(newcontext, scontext); case AVTAB_MEMBER: /* Only polyinstantiate the MLS attributes if the type is being polyinstantiated */ if (newcontext->type != tcontext->type) { - /* Use the process MLS attributes. */ - return mls_copy_context(newcontext, scontext); + /* Use the process effective MLS attributes. */ + return mls_scopy_context(newcontext, scontext); } else { /* Use the related object MLS attributes. */ return mls_copy_context(newcontext, tcontext); @@ -387,368 +525,3 @@ int mls_compute_sid(struct context *scontext, return -EINVAL; } -void mls_user_destroy(struct user_datum *usrdatum) -{ - struct mls_range_list *rnode, *rtmp; - rnode = usrdatum->ranges; - while (rnode) { - rtmp = rnode; - rnode = rnode->next; - ebitmap_destroy(&rtmp->range.level[0].cat); - ebitmap_destroy(&rtmp->range.level[1].cat); - kfree(rtmp); - } -} - -int mls_read_perm(struct perm_datum *perdatum, void *fp) -{ - u32 *buf; - - buf = next_entry(fp, sizeof(u32)); - if (!buf) - return -EINVAL; - perdatum->base_perms = le32_to_cpu(buf[0]); - return 0; -} - -/* - * Read a MLS level structure from a policydb binary - * representation file. - */ -struct mls_level *mls_read_level(void *fp) -{ - struct mls_level *l; - u32 *buf; - - l = kmalloc(sizeof(*l), GFP_ATOMIC); - if (!l) { - printk(KERN_ERR "security: mls: out of memory\n"); - return NULL; - } - memset(l, 0, sizeof(*l)); - - buf = next_entry(fp, sizeof(u32)); - if (!buf) { - printk(KERN_ERR "security: mls: truncated level\n"); - goto bad; - } - l->sens = cpu_to_le32(buf[0]); - - if (ebitmap_read(&l->cat, fp)) { - printk(KERN_ERR "security: mls: error reading level " - "categories\n"); - goto bad; - } - return l; - -bad: - kfree(l); - return NULL; -} - - -/* - * Read a MLS range structure from a policydb binary - * representation file. - */ -static int mls_read_range_helper(struct mls_range *r, void *fp) -{ - u32 *buf; - int items, rc = -EINVAL; - - buf = next_entry(fp, sizeof(u32)); - if (!buf) - goto out; - - items = le32_to_cpu(buf[0]); - buf = next_entry(fp, sizeof(u32) * items); - if (!buf) { - printk(KERN_ERR "security: mls: truncated range\n"); - goto out; - } - r->level[0].sens = le32_to_cpu(buf[0]); - if (items > 1) { - r->level[1].sens = le32_to_cpu(buf[1]); - } else { - r->level[1].sens = r->level[0].sens; - } - - rc = ebitmap_read(&r->level[0].cat, fp); - if (rc) { - printk(KERN_ERR "security: mls: error reading low " - "categories\n"); - goto out; - } - if (items > 1) { - rc = ebitmap_read(&r->level[1].cat, fp); - if (rc) { - printk(KERN_ERR "security: mls: error reading high " - "categories\n"); - goto bad_high; - } - } else { - rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat); - if (rc) { - printk(KERN_ERR "security: mls: out of memory\n"); - goto bad_high; - } - } - - rc = 0; -out: - return rc; -bad_high: - ebitmap_destroy(&r->level[0].cat); - goto out; -} - -int mls_read_range(struct context *c, void *fp) -{ - return mls_read_range_helper(&c->range, fp); -} - - -/* - * Read a MLS perms structure from a policydb binary - * representation file. - */ -int mls_read_class(struct class_datum *cladatum, void *fp) -{ - struct mls_perms *p = &cladatum->mlsperms; - u32 *buf; - - buf = next_entry(fp, sizeof(u32)*4); - if (!buf) { - printk(KERN_ERR "security: mls: truncated mls permissions\n"); - return -EINVAL; - } - p->read = le32_to_cpu(buf[0]); - p->readby = le32_to_cpu(buf[1]); - p->write = le32_to_cpu(buf[2]); - p->writeby = le32_to_cpu(buf[3]); - return 0; -} - -int mls_read_user(struct user_datum *usrdatum, void *fp) -{ - struct mls_range_list *r, *l; - int rc = 0; - u32 nel, i; - u32 *buf; - - buf = next_entry(fp, sizeof(u32)); - if (!buf) { - rc = -EINVAL; - goto out; - } - nel = le32_to_cpu(buf[0]); - l = NULL; - for (i = 0; i < nel; i++) { - r = kmalloc(sizeof(*r), GFP_ATOMIC); - if (!r) { - rc = -ENOMEM; - goto out; - } - memset(r, 0, sizeof(*r)); - - rc = mls_read_range_helper(&r->range, fp); - if (rc) { - kfree(r); - goto out; - } - - if (l) - l->next = r; - else - usrdatum->ranges = r; - l = r; - } -out: - return rc; -} - -int mls_read_nlevels(struct policydb *p, void *fp) -{ - u32 *buf; - - buf = next_entry(fp, sizeof(u32)); - if (!buf) - return -EINVAL; - p->nlevels = le32_to_cpu(buf[0]); - return 0; -} - -int mls_read_trusted(struct policydb *p, void *fp) -{ - int rc = 0; - - rc = ebitmap_read(&p->trustedreaders, fp); - if (rc) - goto out; - rc = ebitmap_read(&p->trustedwriters, fp); - if (rc) - goto bad; - rc = ebitmap_read(&p->trustedobjects, fp); - if (rc) - goto bad2; -out: - return rc; -bad2: - ebitmap_destroy(&p->trustedwriters); -bad: - ebitmap_destroy(&p->trustedreaders); - goto out; -} - -int sens_index(void *key, void *datum, void *datap) -{ - struct policydb *p; - struct level_datum *levdatum; - - - levdatum = datum; - p = datap; - - if (!levdatum->isalias) - p->p_sens_val_to_name[levdatum->level->sens - 1] = key; - - return 0; -} - -int cat_index(void *key, void *datum, void *datap) -{ - struct policydb *p; - struct cat_datum *catdatum; - - - catdatum = datum; - p = datap; - - - if (!catdatum->isalias) - p->p_cat_val_to_name[catdatum->value - 1] = key; - - return 0; -} - -int sens_destroy(void *key, void *datum, void *p) -{ - struct level_datum *levdatum; - - kfree(key); - levdatum = datum; - if (!levdatum->isalias) { - ebitmap_destroy(&levdatum->level->cat); - kfree(levdatum->level); - } - kfree(datum); - return 0; -} - -int cat_destroy(void *key, void *datum, void *p) -{ - kfree(key); - kfree(datum); - return 0; -} - -int sens_read(struct policydb *p, struct hashtab *h, void *fp) -{ - char *key = NULL; - struct level_datum *levdatum; - int rc; - u32 *buf, len; - - levdatum = kmalloc(sizeof(*levdatum), GFP_ATOMIC); - if (!levdatum) { - rc = -ENOMEM; - goto out; - } - memset(levdatum, 0, sizeof(*levdatum)); - - buf = next_entry(fp, sizeof(u32)*2); - if (!buf) { - rc = -EINVAL; - goto bad; - } - - len = le32_to_cpu(buf[0]); - levdatum->isalias = le32_to_cpu(buf[1]); - - buf = next_entry(fp, len); - if (!buf) { - rc = -EINVAL; - goto bad; - } - key = kmalloc(len + 1,GFP_ATOMIC); - if (!key) { - rc = -ENOMEM; - goto bad; - } - memcpy(key, buf, len); - key[len] = 0; - - levdatum->level = mls_read_level(fp); - if (!levdatum->level) { - rc = -EINVAL; - goto bad; - } - - rc = hashtab_insert(h, key, levdatum); - if (rc) - goto bad; -out: - return rc; -bad: - sens_destroy(key, levdatum, NULL); - goto out; -} - - -int cat_read(struct policydb *p, struct hashtab *h, void *fp) -{ - char *key = NULL; - struct cat_datum *catdatum; - int rc; - u32 *buf, len; - - catdatum = kmalloc(sizeof(*catdatum), GFP_ATOMIC); - if (!catdatum) { - rc = -ENOMEM; - goto out; - } - memset(catdatum, 0, sizeof(*catdatum)); - - buf = next_entry(fp, sizeof(u32)*3); - if (!buf) { - rc = -EINVAL; - goto bad; - } - - len = le32_to_cpu(buf[0]); - catdatum->value = le32_to_cpu(buf[1]); - catdatum->isalias = le32_to_cpu(buf[2]); - - buf = next_entry(fp, len); - if (!buf) { - rc = -EINVAL; - goto bad; - } - key = kmalloc(len + 1,GFP_ATOMIC); - if (!key) { - rc = -ENOMEM; - goto bad; - } - memcpy(key, buf, len); - key[len] = 0; - - rc = hashtab_insert(h, key, catdatum); - if (rc) - goto bad; -out: - return rc; - -bad: - cat_destroy(key, catdatum, NULL); - goto out; -} diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index e10ed0e1e..14190efbf 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -4,10 +4,16 @@ * Author : Stephen Smalley, <sds@epoch.ncsc.mil> */ -/* Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com> +/* + * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com> + * + * Support for enhanced MLS infrastructure. + * + * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com> * * Added conditional policy language extensions * + * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. * Copyright (C) 2003 - 2004 Tresys Technology, LLC * 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 @@ -33,12 +39,13 @@ static char *symtab_name[SYM_NUM] = { "roles", "types", "users", - mls_symtab_names - "bools" + "bools", + "levels", + "categories", }; #endif -int policydb_loaded_version; +int selinux_mls_enabled = 0; static unsigned int symtab_sizes[SYM_NUM] = { 2, @@ -46,8 +53,9 @@ static unsigned int symtab_sizes[SYM_NUM] = { 16, 512, 128, - mls_symtab_sizes - 16 + 16, + 16, + 16, }; struct policydb_compat_info { @@ -60,21 +68,26 @@ struct policydb_compat_info { static struct policydb_compat_info policydb_compat[] = { { .version = POLICYDB_VERSION_BASE, - .sym_num = SYM_NUM - 1, + .sym_num = SYM_NUM - 3, .ocon_num = OCON_NUM - 1, }, { .version = POLICYDB_VERSION_BOOL, - .sym_num = SYM_NUM, + .sym_num = SYM_NUM - 2, .ocon_num = OCON_NUM - 1, }, { .version = POLICYDB_VERSION_IPV6, - .sym_num = SYM_NUM, + .sym_num = SYM_NUM - 2, .ocon_num = OCON_NUM, }, { .version = POLICYDB_VERSION_NLCLASS, + .sym_num = SYM_NUM - 2, + .ocon_num = OCON_NUM, + }, + { + .version = POLICYDB_VERSION_MLS, .sym_num = SYM_NUM, .ocon_num = OCON_NUM, }, @@ -97,7 +110,7 @@ static struct policydb_compat_info *policydb_lookup_compat(int version) /* * Initialize the role table. */ -int roles_init(struct policydb *p) +static int roles_init(struct policydb *p) { char *key = NULL; int rc; @@ -136,7 +149,7 @@ out_free_role: /* * Initialize a policy database structure. */ -int policydb_init(struct policydb *p) +static int policydb_init(struct policydb *p) { int i, rc; @@ -254,6 +267,41 @@ static int user_index(void *key, void *datum, void *datap) return 0; } +static int sens_index(void *key, void *datum, void *datap) +{ + struct policydb *p; + struct level_datum *levdatum; + + levdatum = datum; + p = datap; + + if (!levdatum->isalias) { + if (!levdatum->level->sens || + levdatum->level->sens > p->p_levels.nprim) + return -EINVAL; + p->p_sens_val_to_name[levdatum->level->sens - 1] = key; + } + + return 0; +} + +static int cat_index(void *key, void *datum, void *datap) +{ + struct policydb *p; + struct cat_datum *catdatum; + + catdatum = datum; + p = datap; + + if (!catdatum->isalias) { + if (!catdatum->value || catdatum->value > p->p_cats.nprim) + return -EINVAL; + p->p_cat_val_to_name[catdatum->value - 1] = key; + } + + return 0; +} + static int (*index_f[SYM_NUM]) (void *key, void *datum, void *datap) = { common_index, @@ -261,8 +309,9 @@ static int (*index_f[SYM_NUM]) (void *key, void *datum, void *datap) = role_index, type_index, user_index, - mls_index_f - cond_index_bool + cond_index_bool, + sens_index, + cat_index, }; /* @@ -272,7 +321,7 @@ static int (*index_f[SYM_NUM]) (void *key, void *datum, void *datap) = * * Caller must clean up upon failure. */ -int policydb_index_classes(struct policydb *p) +static int policydb_index_classes(struct policydb *p) { int rc; @@ -329,13 +378,15 @@ static void symtab_hash_eval(struct symtab *s) * * Caller must clean up on failure. */ -int policydb_index_others(struct policydb *p) +static int policydb_index_others(struct policydb *p) { int i, rc = 0; printk(KERN_INFO "security: %d users, %d roles, %d types, %d bools", p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim); - mls_policydb_index_others(p); + if (selinux_mls_enabled) + printk(", %d sens, %d cats", p->p_levels.nprim, + p->p_cats.nprim); printk("\n"); printk(KERN_INFO "security: %d classes, %d rules\n", @@ -431,6 +482,21 @@ static int class_destroy(void *key, void *datum, void *p) constraint = constraint->next; kfree(ctemp); } + + constraint = cladatum->validatetrans; + while (constraint) { + e = constraint->expr; + while (e) { + ebitmap_destroy(&e->names); + etmp = e; + e = e->next; + kfree(etmp); + } + ctemp = constraint; + constraint = constraint->next; + kfree(ctemp); + } + kfree(cladatum->comkey); kfree(datum); return 0; @@ -462,7 +528,28 @@ static int user_destroy(void *key, void *datum, void *p) kfree(key); usrdatum = datum; ebitmap_destroy(&usrdatum->roles); - mls_user_destroy(usrdatum); + ebitmap_destroy(&usrdatum->range.level[0].cat); + ebitmap_destroy(&usrdatum->range.level[1].cat); + ebitmap_destroy(&usrdatum->dfltlevel.cat); + kfree(datum); + return 0; +} + +static int sens_destroy(void *key, void *datum, void *p) +{ + struct level_datum *levdatum; + + kfree(key); + levdatum = datum; + ebitmap_destroy(&levdatum->level->cat); + kfree(levdatum->level); + kfree(datum); + return 0; +} + +static int cat_destroy(void *key, void *datum, void *p) +{ + kfree(key); kfree(datum); return 0; } @@ -474,11 +561,12 @@ static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) = role_destroy, type_destroy, user_destroy, - mls_destroy_f - cond_destroy_bool + cond_destroy_bool, + sens_destroy, + cat_destroy, }; -void ocontext_destroy(struct ocontext *c, int i) +static void ocontext_destroy(struct ocontext *c, int i) { context_destroy(&c->context[0]); context_destroy(&c->context[1]); @@ -625,6 +713,65 @@ int policydb_context_isvalid(struct policydb *p, struct context *c) return 1; } +/* + * Read a MLS range structure from a policydb binary + * representation file. + */ +static int mls_read_range_helper(struct mls_range *r, void *fp) +{ + u32 buf[2], items; + int rc; + + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) + goto out; + + items = le32_to_cpu(buf[0]); + if (items > ARRAY_SIZE(buf)) { + printk(KERN_ERR "security: mls: range overflow\n"); + rc = -EINVAL; + goto out; + } + rc = next_entry(buf, fp, sizeof(u32) * items); + if (rc < 0) { + printk(KERN_ERR "security: mls: truncated range\n"); + goto out; + } + r->level[0].sens = le32_to_cpu(buf[0]); + if (items > 1) + r->level[1].sens = le32_to_cpu(buf[1]); + else + r->level[1].sens = r->level[0].sens; + + rc = ebitmap_read(&r->level[0].cat, fp); + if (rc) { + printk(KERN_ERR "security: mls: error reading low " + "categories\n"); + goto out; + } + if (items > 1) { + rc = ebitmap_read(&r->level[1].cat, fp); + if (rc) { + printk(KERN_ERR "security: mls: error reading high " + "categories\n"); + goto bad_high; + } + } else { + rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat); + if (rc) { + printk(KERN_ERR "security: mls: out of memory\n"); + goto bad_high; + } + } + + rc = 0; +out: + return rc; +bad_high: + ebitmap_destroy(&r->level[0].cat); + goto out; +} + /* * Read and validate a security context structure * from a policydb binary representation file. @@ -633,23 +780,24 @@ static int context_read_and_validate(struct context *c, struct policydb *p, void *fp) { - u32 *buf; - int rc = 0; + u32 buf[3]; + int rc; - buf = next_entry(fp, sizeof(u32)*3); - if (!buf) { + rc = next_entry(buf, fp, sizeof buf); + if (rc < 0) { printk(KERN_ERR "security: context truncated\n"); - rc = -EINVAL; goto out; } c->user = le32_to_cpu(buf[0]); c->role = le32_to_cpu(buf[1]); c->type = le32_to_cpu(buf[2]); - if (mls_read_range(c, fp)) { - printk(KERN_ERR "security: error reading MLS range of " - "context\n"); - rc = -EINVAL; - goto out; + if (p->policyvers >= POLICYDB_VERSION_MLS) { + if (mls_read_range_helper(&c->range, fp)) { + printk(KERN_ERR "security: error reading MLS range of " + "context\n"); + rc = -EINVAL; + goto out; + } } if (!policydb_context_isvalid(p, c)) { @@ -672,7 +820,7 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp) char *key = NULL; struct perm_datum *perdatum; int rc; - u32 *buf, len; + u32 buf[2], len; perdatum = kmalloc(sizeof(*perdatum), GFP_KERNEL); if (!perdatum) { @@ -681,29 +829,21 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp) } memset(perdatum, 0, sizeof(*perdatum)); - buf = next_entry(fp, sizeof(u32)*2); - if (!buf) { - rc = -EINVAL; + rc = next_entry(buf, fp, sizeof buf); + if (rc < 0) goto bad; - } len = le32_to_cpu(buf[0]); perdatum->value = le32_to_cpu(buf[1]); - rc = mls_read_perm(perdatum, fp); - if (rc) - goto bad; - buf = next_entry(fp, len); - if (!buf) { - rc = -EINVAL; - goto bad; - } key = kmalloc(len + 1,GFP_KERNEL); if (!key) { rc = -ENOMEM; goto bad; } - memcpy(key, buf, len); + rc = next_entry(key, fp, len); + if (rc < 0) + goto bad; key[len] = 0; rc = hashtab_insert(h, key, perdatum); @@ -720,7 +860,7 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp) { char *key = NULL; struct common_datum *comdatum; - u32 *buf, len, nel; + u32 buf[4], len, nel; int i, rc; comdatum = kmalloc(sizeof(*comdatum), GFP_KERNEL); @@ -730,11 +870,9 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp) } memset(comdatum, 0, sizeof(*comdatum)); - buf = next_entry(fp, sizeof(u32)*4); - if (!buf) { - rc = -EINVAL; + rc = next_entry(buf, fp, sizeof buf); + if (rc < 0) goto bad; - } len = le32_to_cpu(buf[0]); comdatum->value = le32_to_cpu(buf[1]); @@ -745,17 +883,14 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp) comdatum->permissions.nprim = le32_to_cpu(buf[2]); nel = le32_to_cpu(buf[3]); - buf = next_entry(fp, len); - if (!buf) { - rc = -EINVAL; - goto bad; - } key = kmalloc(len + 1,GFP_KERNEL); if (!key) { rc = -ENOMEM; goto bad; } - memcpy(key, buf, len); + rc = next_entry(key, fp, len); + if (rc < 0) + goto bad; key[len] = 0; for (i = 0; i < nel; i++) { @@ -774,27 +909,108 @@ bad: goto out; } +static int read_cons_helper(struct constraint_node **nodep, int ncons, + int allowxtarget, void *fp) +{ + struct constraint_node *c, *lc; + struct constraint_expr *e, *le; + u32 buf[3], nexpr; + int rc, i, j, depth; + + lc = NULL; + for (i = 0; i < ncons; i++) { + c = kmalloc(sizeof(*c), GFP_KERNEL); + if (!c) + return -ENOMEM; + memset(c, 0, sizeof(*c)); + + if (lc) { + lc->next = c; + } else { + *nodep = c; + } + + rc = next_entry(buf, fp, (sizeof(u32) * 2)); + if (rc < 0) + return rc; + c->permissions = le32_to_cpu(buf[0]); + nexpr = le32_to_cpu(buf[1]); + le = NULL; + depth = -1; + for (j = 0; j < nexpr; j++) { + e = kmalloc(sizeof(*e), GFP_KERNEL); + if (!e) + return -ENOMEM; + memset(e, 0, sizeof(*e)); + + if (le) { + le->next = e; + } else { + c->expr = e; + } + + rc = next_entry(buf, fp, (sizeof(u32) * 3)); + if (rc < 0) + return rc; + e->expr_type = le32_to_cpu(buf[0]); + e->attr = le32_to_cpu(buf[1]); + e->op = le32_to_cpu(buf[2]); + + switch (e->expr_type) { + case CEXPR_NOT: + if (depth < 0) + return -EINVAL; + break; + case CEXPR_AND: + case CEXPR_OR: + if (depth < 1) + return -EINVAL; + depth--; + break; + case CEXPR_ATTR: + if (depth == (CEXPR_MAXDEPTH - 1)) + return -EINVAL; + depth++; + break; + case CEXPR_NAMES: + if (!allowxtarget && (e->attr & CEXPR_XTARGET)) + return -EINVAL; + if (depth == (CEXPR_MAXDEPTH - 1)) + return -EINVAL; + depth++; + if (ebitmap_read(&e->names, fp)) + return -EINVAL; + break; + default: + return -EINVAL; + } + le = e; + } + if (depth != 0) + return -EINVAL; + lc = c; + } + + return 0; +} + static int class_read(struct policydb *p, struct hashtab *h, void *fp) { char *key = NULL; struct class_datum *cladatum; - struct constraint_node *c, *lc; - struct constraint_expr *e, *le; - u32 *buf, len, len2, ncons, nexpr, nel; - int i, j, depth, rc; + u32 buf[6], len, len2, ncons, nel; + int i, rc; cladatum = kmalloc(sizeof(*cladatum), GFP_KERNEL); if (!cladatum) { rc = -ENOMEM; - goto bad; + goto out; } memset(cladatum, 0, sizeof(*cladatum)); - buf = next_entry(fp, sizeof(u32)*6); - if (!buf) { - rc = -EINVAL; + rc = next_entry(buf, fp, sizeof(u32)*6); + if (rc < 0) goto bad; - } len = le32_to_cpu(buf[0]); len2 = le32_to_cpu(buf[1]); @@ -808,17 +1024,14 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) ncons = le32_to_cpu(buf[5]); - buf = next_entry(fp, len); - if (!buf) { - rc = -EINVAL; - goto bad; - } key = kmalloc(len + 1,GFP_KERNEL); if (!key) { rc = -ENOMEM; goto bad; } - memcpy(key, buf, len); + rc = next_entry(key, fp, len); + if (rc < 0) + goto bad; key[len] = 0; if (len2) { @@ -827,12 +1040,9 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) rc = -ENOMEM; goto bad; } - buf = next_entry(fp, len2); - if (!buf) { - rc = -EINVAL; + rc = next_entry(cladatum->comkey, fp, len2); + if (rc < 0) goto bad; - } - memcpy(cladatum->comkey, buf, len2); cladatum->comkey[len2] = 0; cladatum->comdatum = hashtab_search(p->p_commons.table, @@ -850,90 +1060,26 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) goto bad; } - lc = NULL; - rc = -EINVAL; - for (i = 0; i < ncons; i++) { - c = kmalloc(sizeof(*c), GFP_KERNEL); - if (!c) { - rc = -ENOMEM; - goto bad; - } - memset(c, 0, sizeof(*c)); - - if (lc) { - lc->next = c; - } else { - cladatum->constraints = c; - } + rc = read_cons_helper(&cladatum->constraints, ncons, 0, fp); + if (rc) + goto bad; - buf = next_entry(fp, sizeof(u32)*2); - if (!buf) + if (p->policyvers >= POLICYDB_VERSION_VALIDATETRANS) { + /* grab the validatetrans rules */ + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) goto bad; - c->permissions = le32_to_cpu(buf[0]); - nexpr = le32_to_cpu(buf[1]); - le = NULL; - depth = -1; - for (j = 0; j < nexpr; j++) { - e = kmalloc(sizeof(*e), GFP_KERNEL); - if (!e) { - rc = -ENOMEM; - goto bad; - } - memset(e, 0, sizeof(*e)); - - if (le) { - le->next = e; - } else { - c->expr = e; - } - - buf = next_entry(fp, sizeof(u32)*3); - if (!buf) - goto bad; - e->expr_type = le32_to_cpu(buf[0]); - e->attr = le32_to_cpu(buf[1]); - e->op = le32_to_cpu(buf[2]); - - switch (e->expr_type) { - case CEXPR_NOT: - if (depth < 0) - goto bad; - break; - case CEXPR_AND: - case CEXPR_OR: - if (depth < 1) - goto bad; - depth--; - break; - case CEXPR_ATTR: - if (depth == (CEXPR_MAXDEPTH-1)) - goto bad; - depth++; - break; - case CEXPR_NAMES: - if (depth == (CEXPR_MAXDEPTH-1)) - goto bad; - depth++; - if (ebitmap_read(&e->names, fp)) - goto bad; - break; - default: - goto bad; - } - le = e; - } - if (depth != 0) + ncons = le32_to_cpu(buf[0]); + rc = read_cons_helper(&cladatum->validatetrans, ncons, 1, fp); + if (rc) goto bad; - lc = c; } - rc = mls_read_class(cladatum, fp); - if (rc) - goto bad; - rc = hashtab_insert(h, key, cladatum); if (rc) goto bad; + + rc = 0; out: return rc; bad: @@ -946,7 +1092,7 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp) char *key = NULL; struct role_datum *role; int rc; - u32 *buf, len; + u32 buf[2], len; role = kmalloc(sizeof(*role), GFP_KERNEL); if (!role) { @@ -955,26 +1101,21 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp) } memset(role, 0, sizeof(*role)); - buf = next_entry(fp, sizeof(u32)*2); - if (!buf) { - rc = -EINVAL; + rc = next_entry(buf, fp, sizeof buf); + if (rc < 0) goto bad; - } len = le32_to_cpu(buf[0]); role->value = le32_to_cpu(buf[1]); - buf = next_entry(fp, len); - if (!buf) { - rc = -EINVAL; - goto bad; - } key = kmalloc(len + 1,GFP_KERNEL); if (!key) { rc = -ENOMEM; goto bad; } - memcpy(key, buf, len); + rc = next_entry(key, fp, len); + if (rc < 0) + goto bad; key[len] = 0; rc = ebitmap_read(&role->dominates, fp); @@ -1011,7 +1152,7 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp) char *key = NULL; struct type_datum *typdatum; int rc; - u32 *buf, len; + u32 buf[3], len; typdatum = kmalloc(sizeof(*typdatum),GFP_KERNEL); if (!typdatum) { @@ -1020,27 +1161,22 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp) } memset(typdatum, 0, sizeof(*typdatum)); - buf = next_entry(fp, sizeof(u32)*3); - if (!buf) { - rc = -EINVAL; + rc = next_entry(buf, fp, sizeof buf); + if (rc < 0) goto bad; - } len = le32_to_cpu(buf[0]); typdatum->value = le32_to_cpu(buf[1]); typdatum->primary = le32_to_cpu(buf[2]); - buf = next_entry(fp, len); - if (!buf) { - rc = -EINVAL; - goto bad; - } key = kmalloc(len + 1,GFP_KERNEL); if (!key) { rc = -ENOMEM; goto bad; } - memcpy(key, buf, len); + rc = next_entry(key, fp, len); + if (rc < 0) + goto bad; key[len] = 0; rc = hashtab_insert(h, key, typdatum); @@ -1053,13 +1189,42 @@ bad: goto out; } + +/* + * Read a MLS level structure from a policydb binary + * representation file. + */ +static int mls_read_level(struct mls_level *lp, void *fp) +{ + u32 buf[1]; + int rc; + + memset(lp, 0, sizeof(*lp)); + + rc = next_entry(buf, fp, sizeof buf); + if (rc < 0) { + printk(KERN_ERR "security: mls: truncated level\n"); + goto bad; + } + lp->sens = le32_to_cpu(buf[0]); + + if (ebitmap_read(&lp->cat, fp)) { + printk(KERN_ERR "security: mls: error reading level " + "categories\n"); + goto bad; + } + return 0; + +bad: + return -EINVAL; +} + static int user_read(struct policydb *p, struct hashtab *h, void *fp) { char *key = NULL; struct user_datum *usrdatum; int rc; - u32 *buf, len; - + u32 buf[2], len; usrdatum = kmalloc(sizeof(*usrdatum), GFP_KERNEL); if (!usrdatum) { @@ -1068,35 +1233,35 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp) } memset(usrdatum, 0, sizeof(*usrdatum)); - buf = next_entry(fp, sizeof(u32)*2); - if (!buf) { - rc = -EINVAL; + rc = next_entry(buf, fp, sizeof buf); + if (rc < 0) goto bad; - } len = le32_to_cpu(buf[0]); usrdatum->value = le32_to_cpu(buf[1]); - buf = next_entry(fp, len); - if (!buf) { - rc = -EINVAL; - goto bad; - } key = kmalloc(len + 1,GFP_KERNEL); if (!key) { rc = -ENOMEM; goto bad; } - memcpy(key, buf, len); + rc = next_entry(key, fp, len); + if (rc < 0) + goto bad; key[len] = 0; rc = ebitmap_read(&usrdatum->roles, fp); if (rc) goto bad; - rc = mls_read_user(usrdatum, fp); - if (rc) - goto bad; + if (p->policyvers >= POLICYDB_VERSION_MLS) { + rc = mls_read_range_helper(&usrdatum->range, fp); + if (rc) + goto bad; + rc = mls_read_level(&usrdatum->dfltlevel, fp); + if (rc) + goto bad; + } rc = hashtab_insert(h, key, usrdatum); if (rc) @@ -1108,6 +1273,100 @@ bad: goto out; } +static int sens_read(struct policydb *p, struct hashtab *h, void *fp) +{ + char *key = NULL; + struct level_datum *levdatum; + int rc; + u32 buf[2], len; + + levdatum = kmalloc(sizeof(*levdatum), GFP_ATOMIC); + if (!levdatum) { + rc = -ENOMEM; + goto out; + } + memset(levdatum, 0, sizeof(*levdatum)); + + rc = next_entry(buf, fp, sizeof buf); + if (rc < 0) + goto bad; + + len = le32_to_cpu(buf[0]); + levdatum->isalias = le32_to_cpu(buf[1]); + + key = kmalloc(len + 1,GFP_ATOMIC); + if (!key) { + rc = -ENOMEM; + goto bad; + } + rc = next_entry(key, fp, len); + if (rc < 0) + goto bad; + key[len] = 0; + + levdatum->level = kmalloc(sizeof(struct mls_level), GFP_ATOMIC); + if (!levdatum->level) { + rc = -ENOMEM; + goto bad; + } + if (mls_read_level(levdatum->level, fp)) { + rc = -EINVAL; + goto bad; + } + + rc = hashtab_insert(h, key, levdatum); + if (rc) + goto bad; +out: + return rc; +bad: + sens_destroy(key, levdatum, NULL); + goto out; +} + +static int cat_read(struct policydb *p, struct hashtab *h, void *fp) +{ + char *key = NULL; + struct cat_datum *catdatum; + int rc; + u32 buf[3], len; + + catdatum = kmalloc(sizeof(*catdatum), GFP_ATOMIC); + if (!catdatum) { + rc = -ENOMEM; + goto out; + } + memset(catdatum, 0, sizeof(*catdatum)); + + rc = next_entry(buf, fp, sizeof buf); + if (rc < 0) + goto bad; + + len = le32_to_cpu(buf[0]); + catdatum->value = le32_to_cpu(buf[1]); + catdatum->isalias = le32_to_cpu(buf[2]); + + key = kmalloc(len + 1,GFP_ATOMIC); + if (!key) { + rc = -ENOMEM; + goto bad; + } + rc = next_entry(key, fp, len); + if (rc < 0) + goto bad; + key[len] = 0; + + rc = hashtab_insert(h, key, catdatum); + if (rc) + goto bad; +out: + return rc; + +bad: + cat_destroy(key, catdatum, NULL); + goto out; +} + static int (*read_f[SYM_NUM]) (struct policydb *p, struct hashtab *h, void *fp) = { common_read, @@ -1115,12 +1374,12 @@ static int (*read_f[SYM_NUM]) (struct policydb *p, struct hashtab *h, void *fp) role_read, type_read, user_read, - mls_read_f - cond_read_bool + cond_read_bool, + sens_read, + cat_read, }; -#define mls_config(x) \ - ((x) & POLICYDB_CONFIG_MLS) ? "mls" : "no_mls" +extern int ss_initialized; /* * Read the configuration data from a policy database binary @@ -1132,22 +1391,21 @@ int policydb_read(struct policydb *p, void *fp) struct role_trans *tr, *ltr; struct ocontext *l, *c, *newc; struct genfs *genfs_p, *genfs, *newgenfs; - int i, j, rc, r_policyvers = 0; - u32 *buf, len, len2, config, nprim, nel, nel2; + int i, j, rc; + u32 buf[8], len, len2, config, nprim, nel, nel2; char *policydb_str; struct policydb_compat_info *info; + struct range_trans *rt, *lrt; config = 0; - mls_set_config(config); rc = policydb_init(p); if (rc) goto out; - rc = -EINVAL; /* Read the magic number and string length. */ - buf = next_entry(fp, sizeof(u32)* 2); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32)* 2); + if (rc < 0) goto bad; for (i = 0; i < 2; i++) @@ -1167,11 +1425,6 @@ int policydb_read(struct policydb *p, void *fp) len, strlen(POLICYDB_STRING)); goto bad; } - buf = next_entry(fp, len); - if (!buf) { - printk(KERN_ERR "security: truncated policydb string identifier\n"); - goto bad; - } policydb_str = kmalloc(len + 1,GFP_KERNEL); if (!policydb_str) { printk(KERN_ERR "security: unable to allocate memory for policydb " @@ -1179,7 +1432,12 @@ int policydb_read(struct policydb *p, void *fp) rc = -ENOMEM; goto bad; } - memcpy(policydb_str, buf, len); + rc = next_entry(policydb_str, fp, len); + if (rc < 0) { + printk(KERN_ERR "security: truncated policydb string identifier\n"); + kfree(policydb_str); + goto bad; + } policydb_str[len] = 0; if (strcmp(policydb_str, POLICYDB_STRING)) { printk(KERN_ERR "security: policydb string %s does not match " @@ -1192,34 +1450,47 @@ int policydb_read(struct policydb *p, void *fp) policydb_str = NULL; /* Read the version, config, and table sizes. */ - buf = next_entry(fp, sizeof(u32)*4); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32)*4); + if (rc < 0) goto bad; for (i = 0; i < 4; i++) buf[i] = le32_to_cpu(buf[i]); - r_policyvers = buf[0]; - if (r_policyvers < POLICYDB_VERSION_MIN || - r_policyvers > POLICYDB_VERSION_MAX) { + p->policyvers = buf[0]; + if (p->policyvers < POLICYDB_VERSION_MIN || + p->policyvers > POLICYDB_VERSION_MAX) { printk(KERN_ERR "security: policydb version %d does not match " "my version range %d-%d\n", buf[0], POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX); goto bad; } - if (buf[1] != config) { - printk(KERN_ERR "security: policydb configuration (%s) does " - "not match my configuration (%s)\n", - mls_config(buf[1]), - mls_config(config)); - goto bad; - } + if ((buf[1] & POLICYDB_CONFIG_MLS)) { + if (ss_initialized && !selinux_mls_enabled) { + printk(KERN_ERR "Cannot switch between non-MLS and MLS " + "policies\n"); + goto bad; + } + selinux_mls_enabled = 1; + config |= POLICYDB_CONFIG_MLS; + if (p->policyvers < POLICYDB_VERSION_MLS) { + printk(KERN_ERR "security policydb version %d (MLS) " + "not backwards compatible\n", p->policyvers); + goto bad; + } + } else { + if (ss_initialized && selinux_mls_enabled) { + printk(KERN_ERR "Cannot switch between MLS and non-MLS " + "policies\n"); + goto bad; + } + } - info = policydb_lookup_compat(r_policyvers); + info = policydb_lookup_compat(p->policyvers); if (!info) { printk(KERN_ERR "security: unable to find policy compat info " - "for version %d\n", r_policyvers); + "for version %d\n", p->policyvers); goto bad; } @@ -1230,16 +1501,10 @@ int policydb_read(struct policydb *p, void *fp) goto bad; } - rc = mls_read_nlevels(p, fp); - if (rc) - goto bad; - for (i = 0; i < info->sym_num; i++) { - buf = next_entry(fp, sizeof(u32)*2); - if (!buf) { - rc = -EINVAL; + rc = next_entry(buf, fp, sizeof(u32)*2); + if (rc < 0) goto bad; - } nprim = le32_to_cpu(buf[0]); nel = le32_to_cpu(buf[1]); for (j = 0; j < nel; j++) { @@ -1255,17 +1520,15 @@ int policydb_read(struct policydb *p, void *fp) if (rc) goto bad; - if (r_policyvers >= POLICYDB_VERSION_BOOL) { + if (p->policyvers >= POLICYDB_VERSION_BOOL) { rc = cond_read_list(p, fp); if (rc) goto bad; } - buf = next_entry(fp, sizeof(u32)); - if (!buf) { - rc = -EINVAL; + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) goto bad; - } nel = le32_to_cpu(buf[0]); ltr = NULL; for (i = 0; i < nel; i++) { @@ -1280,22 +1543,18 @@ int policydb_read(struct policydb *p, void *fp) } else { p->role_tr = tr; } - buf = next_entry(fp, sizeof(u32)*3); - if (!buf) { - rc = -EINVAL; + rc = next_entry(buf, fp, sizeof(u32)*3); + if (rc < 0) goto bad; - } tr->role = le32_to_cpu(buf[0]); tr->type = le32_to_cpu(buf[1]); tr->new_role = le32_to_cpu(buf[2]); ltr = tr; } - buf = next_entry(fp, sizeof(u32)); - if (!buf) { - rc = -EINVAL; + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) goto bad; - } nel = le32_to_cpu(buf[0]); lra = NULL; for (i = 0; i < nel; i++) { @@ -1310,11 +1569,9 @@ int policydb_read(struct policydb *p, void *fp) } else { p->role_allow = ra; } - buf = next_entry(fp, sizeof(u32)*2); - if (!buf) { - rc = -EINVAL; + rc = next_entry(buf, fp, sizeof(u32)*2); + if (rc < 0) goto bad; - } ra->role = le32_to_cpu(buf[0]); ra->new_role = le32_to_cpu(buf[1]); lra = ra; @@ -1329,11 +1586,9 @@ int policydb_read(struct policydb *p, void *fp) goto bad; for (i = 0; i < info->ocon_num; i++) { - buf = next_entry(fp, sizeof(u32)); - if (!buf) { - rc = -EINVAL; + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) goto bad; - } nel = le32_to_cpu(buf[0]); l = NULL; for (j = 0; j < nel; j++) { @@ -1352,8 +1607,8 @@ int policydb_read(struct policydb *p, void *fp) rc = -EINVAL; switch (i) { case OCON_ISID: - buf = next_entry(fp, sizeof(u32)); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) goto bad; c->sid[0] = le32_to_cpu(buf[0]); rc = context_read_and_validate(&c->context[0], p, fp); @@ -1362,19 +1617,18 @@ int policydb_read(struct policydb *p, void *fp) break; case OCON_FS: case OCON_NETIF: - buf = next_entry(fp, sizeof(u32)); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); - buf = next_entry(fp, len); - if (!buf) - goto bad; c->u.name = kmalloc(len + 1,GFP_KERNEL); if (!c->u.name) { rc = -ENOMEM; goto bad; } - memcpy(c->u.name, buf, len); + rc = next_entry(c->u.name, fp, len); + if (rc < 0) + goto bad; c->u.name[len] = 0; rc = context_read_and_validate(&c->context[0], p, fp); if (rc) @@ -1384,8 +1638,8 @@ int policydb_read(struct policydb *p, void *fp) goto bad; break; case OCON_PORT: - buf = next_entry(fp, sizeof(u32)*3); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32)*3); + if (rc < 0) goto bad; c->u.port.protocol = le32_to_cpu(buf[0]); c->u.port.low_port = le32_to_cpu(buf[1]); @@ -1395,8 +1649,8 @@ int policydb_read(struct policydb *p, void *fp) goto bad; break; case OCON_NODE: - buf = next_entry(fp, sizeof(u32)* 2); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32)* 2); + if (rc < 0) goto bad; c->u.node.addr = le32_to_cpu(buf[0]); c->u.node.mask = le32_to_cpu(buf[1]); @@ -1405,22 +1659,21 @@ int policydb_read(struct policydb *p, void *fp) goto bad; break; case OCON_FSUSE: - buf = next_entry(fp, sizeof(u32)*2); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32)*2); + if (rc < 0) goto bad; c->v.behavior = le32_to_cpu(buf[0]); if (c->v.behavior > SECURITY_FS_USE_NONE) goto bad; len = le32_to_cpu(buf[1]); - buf = next_entry(fp, len); - if (!buf) - goto bad; c->u.name = kmalloc(len + 1,GFP_KERNEL); if (!c->u.name) { rc = -ENOMEM; goto bad; } - memcpy(c->u.name, buf, len); + rc = next_entry(c->u.name, fp, len); + if (rc < 0) + goto bad; c->u.name[len] = 0; rc = context_read_and_validate(&c->context[0], p, fp); if (rc) @@ -1429,8 +1682,8 @@ int policydb_read(struct policydb *p, void *fp) case OCON_NODE6: { int k; - buf = next_entry(fp, sizeof(u32) * 8); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32) * 8); + if (rc < 0) goto bad; for (k = 0; k < 4; k++) c->u.node6.addr[k] = le32_to_cpu(buf[k]); @@ -1444,22 +1697,17 @@ int policydb_read(struct policydb *p, void *fp) } } - buf = next_entry(fp, sizeof(u32)); - if (!buf) { - rc = -EINVAL; + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) goto bad; - } nel = le32_to_cpu(buf[0]); genfs_p = NULL; rc = -EINVAL; for (i = 0; i < nel; i++) { - buf = next_entry(fp, sizeof(u32)); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); - buf = next_entry(fp, len); - if (!buf) - goto bad; newgenfs = kmalloc(sizeof(*newgenfs), GFP_KERNEL); if (!newgenfs) { rc = -ENOMEM; @@ -1473,7 +1721,12 @@ int policydb_read(struct policydb *p, void *fp) kfree(newgenfs); goto bad; } - memcpy(newgenfs->fstype, buf, len); + rc = next_entry(newgenfs->fstype, fp, len); + if (rc < 0) { + kfree(newgenfs->fstype); + kfree(newgenfs); + goto bad; + } newgenfs->fstype[len] = 0; for (genfs_p = NULL, genfs = p->genfs; genfs; genfs_p = genfs, genfs = genfs->next) { @@ -1492,18 +1745,15 @@ int policydb_read(struct policydb *p, void *fp) genfs_p->next = newgenfs; else p->genfs = newgenfs; - buf = next_entry(fp, sizeof(u32)); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) goto bad; nel2 = le32_to_cpu(buf[0]); for (j = 0; j < nel2; j++) { - buf = next_entry(fp, sizeof(u32)); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); - buf = next_entry(fp, len); - if (!buf) - goto bad; newc = kmalloc(sizeof(*newc), GFP_KERNEL); if (!newc) { @@ -1517,10 +1767,12 @@ int policydb_read(struct policydb *p, void *fp) rc = -ENOMEM; goto bad_newc; } - memcpy(newc->u.name, buf, len); + rc = next_entry(newc->u.name, fp, len); + if (rc < 0) + goto bad_newc; newc->u.name[len] = 0; - buf = next_entry(fp, sizeof(u32)); - if (!buf) + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) goto bad_newc; newc->v.sclass = le32_to_cpu(buf[0]); if (context_read_and_validate(&newc->context[0], p, fp)) @@ -1549,15 +1801,43 @@ int policydb_read(struct policydb *p, void *fp) } } - rc = mls_read_trusted(p, fp); - if (rc) - goto bad; + if (p->policyvers >= POLICYDB_VERSION_MLS) { + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) + goto bad; + nel = le32_to_cpu(buf[0]); + lrt = NULL; + for (i = 0; i < nel; i++) { + rt = kmalloc(sizeof(*rt), GFP_KERNEL); + if (!rt) { + rc = -ENOMEM; + goto bad; + } + memset(rt, 0, sizeof(*rt)); + if (lrt) + lrt->next = rt; + else + p->range_tr = rt; + rc = next_entry(buf, fp, (sizeof(u32) * 2)); + if (rc < 0) + goto bad; + rt->dom = le32_to_cpu(buf[0]); + rt->type = le32_to_cpu(buf[1]); + rc = mls_read_range_helper(&rt->range, fp); + if (rc) + goto bad; + lrt = rt; + } + } + + rc = 0; out: - policydb_loaded_version = r_policyvers; return rc; bad_newc: ocontext_destroy(newc,OCON_FSUSE); bad: + if (!rc) + rc = -EINVAL; policydb_destroy(p); goto out; } diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 97341688c..2947cf85d 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -4,17 +4,17 @@ * Authors : Stephen Smalley, <sds@epoch.ncsc.mil> * James Morris <jmorris@redhat.com> * - * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com> + * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.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. + * Support for enhanced MLS infrastructure. * * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com> * * Added conditional policy language extensions * + * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. * Copyright (C) 2003 - 2004 Tresys Technology, LLC + * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@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, version 2. @@ -40,9 +40,9 @@ #include "mls.h" extern void selnl_notify_policyload(u32 seqno); -extern int policydb_loaded_version; +unsigned int policydb_loaded_version; -static rwlock_t policy_rwlock = RW_LOCK_UNLOCKED; +static DEFINE_RWLOCK(policy_rwlock); #define POLICY_RDLOCK read_lock(&policy_rwlock) #define POLICY_WRLOCK write_lock_irq(&policy_rwlock) #define POLICY_RDUNLOCK read_unlock(&policy_rwlock) @@ -52,7 +52,7 @@ static DECLARE_MUTEX(load_sem); #define LOAD_LOCK down(&load_sem) #define LOAD_UNLOCK up(&load_sem) -struct sidtab sidtab; +static struct sidtab sidtab; struct policydb policydb; int ss_initialized = 0; @@ -64,18 +64,30 @@ int ss_initialized = 0; */ static u32 latest_granting = 0; +/* Forward declaration. */ +static int context_struct_to_string(struct context *context, char **scontext, + u32 *scontext_len); + /* * Return the boolean value of a constraint expression * when it is applied to the specified source and target * security contexts. + * + * xcontext is a special beast... It is used by the validatetrans rules + * only. For these rules, scontext is the context before the transition, + * tcontext is the context after the transition, and xcontext is the context + * of the process performing the transition. All other callers of + * constraint_expr_eval should pass in NULL for xcontext. */ static int constraint_expr_eval(struct context *scontext, struct context *tcontext, + struct context *xcontext, struct constraint_expr *cexpr) { u32 val1, val2; struct context *c; struct role_datum *r1, *r2; + struct mls_level *l1, *l2; struct constraint_expr *e; int s[CEXPR_MAXDEPTH]; int sp = -1; @@ -132,6 +144,52 @@ static int constraint_expr_eval(struct context *scontext, break; } break; + case CEXPR_L1L2: + l1 = &(scontext->range.level[0]); + l2 = &(tcontext->range.level[0]); + goto mls_ops; + case CEXPR_L1H2: + l1 = &(scontext->range.level[0]); + l2 = &(tcontext->range.level[1]); + goto mls_ops; + case CEXPR_H1L2: + l1 = &(scontext->range.level[1]); + l2 = &(tcontext->range.level[0]); + goto mls_ops; + case CEXPR_H1H2: + l1 = &(scontext->range.level[1]); + l2 = &(tcontext->range.level[1]); + goto mls_ops; + case CEXPR_L1H1: + l1 = &(scontext->range.level[0]); + l2 = &(scontext->range.level[1]); + goto mls_ops; + case CEXPR_L2H2: + l1 = &(tcontext->range.level[0]); + l2 = &(tcontext->range.level[1]); + goto mls_ops; +mls_ops: + switch (e->op) { + case CEXPR_EQ: + s[++sp] = mls_level_eq(l1, l2); + continue; + case CEXPR_NEQ: + s[++sp] = !mls_level_eq(l1, l2); + continue; + case CEXPR_DOM: + s[++sp] = mls_level_dom(l1, l2); + continue; + case CEXPR_DOMBY: + s[++sp] = mls_level_dom(l2, l1); + continue; + case CEXPR_INCOMP: + s[++sp] = mls_level_incomp(l2, l1); + continue; + default: + BUG(); + return 0; + } + break; default: BUG(); return 0; @@ -155,6 +213,13 @@ static int constraint_expr_eval(struct context *scontext, c = scontext; if (e->attr & CEXPR_TARGET) c = tcontext; + else if (e->attr & CEXPR_XTARGET) { + c = xcontext; + if (!c) { + BUG(); + return 0; + } + } if (e->attr & CEXPR_USER) val1 = c->user; else if (e->attr & CEXPR_ROLE) @@ -252,17 +317,13 @@ static int context_struct_compute_av(struct context *scontext, cond_compute_av(&policydb.te_cond_avtab, &avkey, avd); /* - * Remove any permissions prohibited by the MLS policy. - */ - mls_compute_av(scontext, tcontext, tclass_datum, &avd->allowed); - - /* - * Remove any permissions prohibited by a constraint. + * Remove any permissions prohibited by a constraint (this includes + * the MLS policy). */ constraint = tclass_datum->constraints; while (constraint) { if ((constraint->permissions & (avd->allowed)) && - !constraint_expr_eval(scontext, tcontext, + !constraint_expr_eval(scontext, tcontext, NULL, constraint->expr)) { avd->allowed = (avd->allowed) & ~(constraint->permissions); } @@ -275,7 +336,7 @@ static int context_struct_compute_av(struct context *scontext, * pair. */ if (tclass == SECCLASS_PROCESS && - (avd->allowed & PROCESS__TRANSITION) && + (avd->allowed & (PROCESS__TRANSITION | PROCESS__DYNTRANSITION)) && scontext->role != tcontext->role) { for (ra = policydb.role_allow; ra; ra = ra->next) { if (scontext->role == ra->role && @@ -283,12 +344,115 @@ static int context_struct_compute_av(struct context *scontext, break; } if (!ra) - avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION); + avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION | + PROCESS__DYNTRANSITION); } return 0; } +static int security_validtrans_handle_fail(struct context *ocontext, + struct context *ncontext, + struct context *tcontext, + u16 tclass) +{ + char *o = NULL, *n = NULL, *t = NULL; + u32 olen, nlen, tlen; + + if (context_struct_to_string(ocontext, &o, &olen) < 0) + goto out; + if (context_struct_to_string(ncontext, &n, &nlen) < 0) + goto out; + if (context_struct_to_string(tcontext, &t, &tlen) < 0) + goto out; + audit_log(current->audit_context, GFP_ATOMIC, 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]); +out: + kfree(o); + kfree(n); + kfree(t); + + if (!selinux_enforcing) + return 0; + return -EPERM; +} + +int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, + u16 tclass) +{ + struct context *ocontext; + struct context *ncontext; + struct context *tcontext; + struct class_datum *tclass_datum; + struct constraint_node *constraint; + int rc = 0; + + if (!ss_initialized) + return 0; + + POLICY_RDLOCK; + + /* + * Remap extended Netlink classes for old policy versions. + * Do this here rather than socket_type_to_security_class() + * in case a newer policy version is loaded, allowing sockets + * to remain in the correct class. + */ + if (policydb_loaded_version < POLICYDB_VERSION_NLCLASS) + if (tclass >= SECCLASS_NETLINK_ROUTE_SOCKET && + tclass <= SECCLASS_NETLINK_DNRT_SOCKET) + tclass = SECCLASS_NETLINK_SOCKET; + + if (!tclass || tclass > policydb.p_classes.nprim) { + printk(KERN_ERR "security_validate_transition: " + "unrecognized class %d\n", tclass); + rc = -EINVAL; + goto out; + } + tclass_datum = policydb.class_val_to_struct[tclass - 1]; + + ocontext = sidtab_search(&sidtab, oldsid); + if (!ocontext) { + printk(KERN_ERR "security_validate_transition: " + " unrecognized SID %d\n", oldsid); + rc = -EINVAL; + goto out; + } + + ncontext = sidtab_search(&sidtab, newsid); + if (!ncontext) { + printk(KERN_ERR "security_validate_transition: " + " unrecognized SID %d\n", newsid); + rc = -EINVAL; + goto out; + } + + tcontext = sidtab_search(&sidtab, tasksid); + if (!tcontext) { + printk(KERN_ERR "security_validate_transition: " + " unrecognized SID %d\n", tasksid); + rc = -EINVAL; + goto out; + } + + constraint = tclass_datum->validatetrans; + while (constraint) { + if (!constraint_expr_eval(ocontext, ncontext, tcontext, + constraint->expr)) { + rc = security_validtrans_handle_fail(ocontext, ncontext, + tcontext, tclass); + goto out; + } + constraint = constraint->next; + } + +out: + POLICY_RDUNLOCK; + return rc; +} + /** * security_compute_av - Compute access vector decisions. * @ssid: source security identifier @@ -312,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; @@ -351,7 +515,7 @@ out: * to point to this string and set `*scontext_len' to * the length of the string. */ -int context_struct_to_string(struct context *context, char **scontext, u32 *scontext_len) +static int context_struct_to_string(struct context *context, char **scontext, u32 *scontext_len) { char *scontextp; @@ -365,7 +529,7 @@ int context_struct_to_string(struct context *context, char **scontext, u32 *scon *scontext_len += mls_compute_context_len(context); /* Allocate space for the context; caller must free this space. */ - scontextp = kmalloc(*scontext_len+1,GFP_ATOMIC); + scontextp = kmalloc(*scontext_len, GFP_ATOMIC); if (!scontextp) { return -ENOMEM; } @@ -374,17 +538,16 @@ int context_struct_to_string(struct context *context, char **scontext, u32 *scon /* * Copy the user name, role name and type name into the context. */ - sprintf(scontextp, "%s:%s:%s:", + sprintf(scontextp, "%s:%s:%s", policydb.p_user_val_to_name[context->user - 1], policydb.p_role_val_to_name[context->role - 1], policydb.p_type_val_to_name[context->type - 1]); scontextp += strlen(policydb.p_user_val_to_name[context->user - 1]) + 1 + strlen(policydb.p_role_val_to_name[context->role - 1]) + - 1 + strlen(policydb.p_type_val_to_name[context->type - 1]) + 1; + 1 + strlen(policydb.p_type_val_to_name[context->type - 1]); mls_sid_to_context(context, &scontextp); - scontextp--; *scontextp = 0; return 0; @@ -579,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, GFP_ATOMIC, AUDIT_SELINUX_ERR, "security_compute_sid: invalid context %s" " for scontext=%s" " tcontext=%s" @@ -714,23 +877,8 @@ static int security_compute_sid(u32 ssid, } } } - - if (!type_change && !roletr) { - /* No change in process role or type. */ - *out_sid = ssid; - goto out_unlock; - - } break; default: - if (!type_change && - (newcontext.user == tcontext->user) && - mls_context_cmp(scontext, tcontext)) { - /* No change in object type, owner, - or MLS attributes. */ - *out_sid = tsid; - goto out_unlock; - } break; } @@ -1046,10 +1194,13 @@ int security_load_policy(void *data, size_t len) avtab_cache_destroy(); return -EINVAL; } + 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; } @@ -1094,7 +1245,7 @@ int security_load_policy(void *data, size_t len) memcpy(&policydb, &newpolicydb, sizeof policydb); sidtab_set(&sidtab, &newsidtab); seqno = ++latest_granting; - + policydb_loaded_version = policydb.policyvers; POLICY_WRUNLOCK; LOAD_UNLOCK; @@ -1361,36 +1512,37 @@ int security_get_user_sids(u32 fromsid, if (!ebitmap_get_bit(&role->types, j)) continue; usercon.type = j+1; - mls_for_user_ranges(user,usercon) { - rc = context_struct_compute_av(fromcon, &usercon, - SECCLASS_PROCESS, - PROCESS__TRANSITION, - &avd); - if (rc || !(avd.allowed & PROCESS__TRANSITION)) - continue; - rc = sidtab_context_to_sid(&sidtab, &usercon, &sid); - if (rc) { + + if (mls_setup_user_range(fromcon, user, &usercon)) + continue; + + rc = context_struct_compute_av(fromcon, &usercon, + SECCLASS_PROCESS, + PROCESS__TRANSITION, + &avd); + if (rc || !(avd.allowed & PROCESS__TRANSITION)) + continue; + rc = sidtab_context_to_sid(&sidtab, &usercon, &sid); + if (rc) { + kfree(mysids); + goto out_unlock; + } + if (mynel < maxnel) { + mysids[mynel++] = sid; + } else { + maxnel += SIDS_NEL; + mysids2 = kmalloc(maxnel*sizeof(*mysids2), GFP_ATOMIC); + if (!mysids2) { + rc = -ENOMEM; kfree(mysids); goto out_unlock; } - if (mynel < maxnel) { - mysids[mynel++] = sid; - } else { - maxnel += SIDS_NEL; - mysids2 = kmalloc(maxnel*sizeof(*mysids2), GFP_ATOMIC); - if (!mysids2) { - rc = -ENOMEM; - kfree(mysids); - goto out_unlock; - } - memset(mysids2, 0, maxnel*sizeof(*mysids2)); - memcpy(mysids2, mysids, mynel * sizeof(*mysids2)); - kfree(mysids); - mysids = mysids2; - mysids[mynel++] = sid; - } + memset(mysids2, 0, maxnel*sizeof(*mysids2)); + memcpy(mysids2, mysids, mynel * sizeof(*mysids2)); + kfree(mysids); + mysids = mysids2; + mysids[mynel++] = sid; } - mls_end_user_ranges; } } diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c index 77d000246..871c33bd0 100644 --- a/security/selinux/ss/sidtab.c +++ b/security/selinux/ss/sidtab.c @@ -87,42 +87,6 @@ out: return rc; } -int sidtab_remove(struct sidtab *s, u32 sid) -{ - int hvalue, rc = 0; - struct sidtab_node *cur, *last; - - if (!s) { - rc = -ENOENT; - goto out; - } - - hvalue = SIDTAB_HASH(sid); - last = NULL; - cur = s->htable[hvalue]; - while (cur != NULL && sid > cur->sid) { - last = cur; - cur = cur->next; - } - - if (cur == NULL || sid != cur->sid) { - rc = -ENOENT; - goto out; - } - - if (last == NULL) - s->htable[hvalue] = cur->next; - else - last->next = cur->next; - - context_destroy(&cur->context); - - kfree(cur); - s->nel--; -out: - return rc; -} - struct context *sidtab_search(struct sidtab *s, u32 sid) { int hvalue; diff --git a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c index 782fed3c9..174bc032d 100644 --- a/sound/arm/sa11xx-uda1341.c +++ b/sound/arm/sa11xx-uda1341.c @@ -21,7 +21,7 @@ * merged HAL layer (patches from Brian) */ -/* $Id: sa11xx-uda1341.c,v 1.18 2004/07/20 15:54:09 cladisch Exp $ */ +/* $Id: sa11xx-uda1341.c,v 1.21 2005/01/28 19:34:04 tiwai Exp $ */ /*************************************************************************************************** * @@ -862,7 +862,7 @@ static int __init snd_card_sa11xx_uda1341_pcm(sa11xx_uda1341_t *sa11xx_uda1341, #ifdef CONFIG_PM -static int snd_sa11xx_uda1341_suspend(snd_card_t *card, unsigned int state) +static int snd_sa11xx_uda1341_suspend(snd_card_t *card, pm_message_t state) { sa11xx_uda1341_t *chip = card->pm_private_data; @@ -875,11 +875,10 @@ static int snd_sa11xx_uda1341_suspend(snd_card_t *card, unsigned int state) #endif l3_command(chip->uda1341, CMD_SUSPEND, NULL); sa11xx_uda1341_audio_shutdown(chip); - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } -static int snd_sa11xx_uda1341_resume(snd_card_t *card, unsigned int state) +static int snd_sa11xx_uda1341_resume(snd_card_t *card) { sa11xx_uda1341_t *chip = card->pm_private_data; @@ -891,7 +890,6 @@ static int snd_sa11xx_uda1341_resume(snd_card_t *card, unsigned int state) #else //FIXME #endif - snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; } #endif /* COMFIG_PM */ @@ -940,7 +938,7 @@ static int __init sa11xx_uda1341_init(void) if ((err = snd_card_sa11xx_uda1341_pcm(sa11xx_uda1341, 0)) < 0) goto nodev; - snd_card_set_dev_pm_callback(card, PM_SYS_DEV, + snd_card_set_generic_pm_callback(card, snd_sa11xx_uda1341_suspend, snd_sa11_uda1341_resume, sa11xx_uda1341); diff --git a/sound/core/Kconfig b/sound/core/Kconfig index a62b83988..d1e800b98 100644 --- a/sound/core/Kconfig +++ b/sound/core/Kconfig @@ -1,16 +1,20 @@ # ALSA soundcard-configuration config SND_TIMER tristate + depends on SND config SND_PCM tristate select SND_TIMER + depends on SND config SND_HWDEP tristate + depends on SND config SND_RAWMIDI tristate + depends on SND config SND_SEQUENCER tristate "Sequencer support" @@ -40,6 +44,7 @@ config SND_SEQ_DUMMY config SND_OSSEMUL bool + depends on SND config SND_MIXER_OSS tristate "OSS Mixer API" @@ -70,7 +75,7 @@ config SND_PCM_OSS config SND_SEQUENCER_OSS bool "OSS Sequencer API" - depends on SND_SEQUENCER + depends on SND && SND_SEQUENCER select SND_OSSEMUL help Say Y here to enable OSS sequencer emulation (both @@ -81,20 +86,6 @@ config SND_SEQUENCER_OSS To compile this driver as a module, choose M here: the module will be called snd-seq-oss. -config SND_BIT32_EMUL - tristate "Emulation for 32-bit applications" - depends on SND && (MIPS64 || SPARC64 || PPC64 || X86_64 && IA32_EMULATION) - select SND_PCM - select SND_RAWMIDI - select SND_TIMER - select SND_HWDEP - help - Say Y here to enable the emulation for 32-bit ALSA-native - applications. - - To compile this driver as a module, choose M here: the module - will be called snd-ioctl32. - config SND_RTCTIMER tristate "RTC Timer support" depends on SND && RTC @@ -137,3 +128,6 @@ config SND_DEBUG_DETECT Say Y here to enable extra-verbose log messages printed when detecting devices. +config SND_GENERIC_PM + bool + depends on SND diff --git a/sound/core/control.c b/sound/core/control.c index 191a0ed67..f4ea6bff1 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -31,6 +31,9 @@ #include <sound/info.h> #include <sound/control.h> +/* max number of user-defined controls */ +#define MAX_USER_CONTROLS 32 + typedef struct _snd_kctl_ioctl { struct list_head list; /* list of all ioctls */ snd_kctl_ioctl_func_t fioctl; @@ -40,6 +43,9 @@ typedef struct _snd_kctl_ioctl { static DECLARE_RWSEM(snd_ioctl_rwsem); static LIST_HEAD(snd_control_ioctls); +#ifdef CONFIG_COMPAT +static LIST_HEAD(snd_control_compat_ioctls); +#endif static int snd_ctl_open(struct inode *inode, struct file *file) { @@ -513,20 +519,25 @@ snd_kcontrol_t *snd_ctl_find_id(snd_card_t * card, snd_ctl_elem_id_t *id) static int snd_ctl_card_info(snd_card_t * card, snd_ctl_file_t * ctl, unsigned int cmd, void __user *arg) { - snd_ctl_card_info_t info; + snd_ctl_card_info_t *info; - memset(&info, 0, sizeof(info)); + info = kcalloc(1, sizeof(*info), GFP_KERNEL); + if (! info) + return -ENOMEM; down_read(&snd_ioctl_rwsem); - info.card = card->number; - strlcpy(info.id, card->id, sizeof(info.id)); - strlcpy(info.driver, card->driver, sizeof(info.driver)); - strlcpy(info.name, card->shortname, sizeof(info.name)); - strlcpy(info.longname, card->longname, sizeof(info.longname)); - strlcpy(info.mixername, card->mixername, sizeof(info.mixername)); - strlcpy(info.components, card->components, sizeof(info.components)); + info->card = card->number; + strlcpy(info->id, card->id, sizeof(info->id)); + strlcpy(info->driver, card->driver, sizeof(info->driver)); + strlcpy(info->name, card->shortname, sizeof(info->name)); + strlcpy(info->longname, card->longname, sizeof(info->longname)); + strlcpy(info->mixername, card->mixername, sizeof(info->mixername)); + strlcpy(info->components, card->components, sizeof(info->components)); up_read(&snd_ioctl_rwsem); - if (copy_to_user(arg, &info, sizeof(snd_ctl_card_info_t))) + if (copy_to_user(arg, info, sizeof(snd_ctl_card_info_t))) { + kfree(info); return -EFAULT; + } + kfree(info); return 0; } @@ -592,43 +603,51 @@ static int snd_ctl_elem_list(snd_card_t *card, snd_ctl_elem_list_t __user *_list return 0; } -static int snd_ctl_elem_info(snd_ctl_file_t *ctl, snd_ctl_elem_info_t __user *_info) +static int snd_ctl_elem_info(snd_ctl_file_t *ctl, snd_ctl_elem_info_t *info) { snd_card_t *card = ctl->card; - snd_ctl_elem_info_t info; snd_kcontrol_t *kctl; snd_kcontrol_volatile_t *vd; unsigned int index_offset; int result; - if (copy_from_user(&info, _info, sizeof(info))) - return -EFAULT; down_read(&card->controls_rwsem); - kctl = snd_ctl_find_id(card, &info.id); + kctl = snd_ctl_find_id(card, &info->id); if (kctl == NULL) { up_read(&card->controls_rwsem); return -ENOENT; } #ifdef CONFIG_SND_DEBUG - info.access = 0; + info->access = 0; #endif - result = kctl->info(kctl, &info); + result = kctl->info(kctl, info); if (result >= 0) { - snd_assert(info.access == 0, ); - index_offset = snd_ctl_get_ioff(kctl, &info.id); + snd_assert(info->access == 0, ); + index_offset = snd_ctl_get_ioff(kctl, &info->id); vd = &kctl->vd[index_offset]; - snd_ctl_build_ioff(&info.id, kctl, index_offset); - info.access = vd->access; + snd_ctl_build_ioff(&info->id, kctl, index_offset); + info->access = vd->access; if (vd->owner) { - info.access |= SNDRV_CTL_ELEM_ACCESS_LOCK; + info->access |= SNDRV_CTL_ELEM_ACCESS_LOCK; if (vd->owner == ctl) - info.access |= SNDRV_CTL_ELEM_ACCESS_OWNER; - info.owner = vd->owner_pid; + info->access |= SNDRV_CTL_ELEM_ACCESS_OWNER; + info->owner = vd->owner_pid; } else { - info.owner = -1; + info->owner = -1; } } up_read(&card->controls_rwsem); + return result; +} + +static int snd_ctl_elem_info_user(snd_ctl_file_t *ctl, snd_ctl_elem_info_t __user *_info) +{ + snd_ctl_elem_info_t info; + int result; + + if (copy_from_user(&info, _info, sizeof(info))) + return -EFAULT; + result = snd_ctl_elem_info(ctl, &info); if (result >= 0) if (copy_to_user(_info, &info, sizeof(info))) return -EFAULT; @@ -685,9 +704,8 @@ static int snd_ctl_elem_read_user(snd_card_t *card, snd_ctl_elem_value_t __user return result; } -int snd_ctl_elem_write(snd_ctl_file_t *file, snd_ctl_elem_value_t *control) +int snd_ctl_elem_write(snd_card_t *card, snd_ctl_file_t *file, snd_ctl_elem_value_t *control) { - snd_card_t *card = file->card; snd_kcontrol_t *kctl; snd_kcontrol_volatile_t *vd; unsigned int index_offset; @@ -706,7 +724,7 @@ int snd_ctl_elem_write(snd_ctl_file_t *file, snd_ctl_elem_value_t *control) } else { if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_WRITE) || kctl->put == NULL || - (vd->owner != NULL && vd->owner != file)) { + (file && vd->owner != NULL && vd->owner != file)) { result = -EPERM; } else { snd_ctl_build_ioff(&control->id, kctl, index_offset); @@ -735,7 +753,7 @@ static int snd_ctl_elem_write_user(snd_ctl_file_t *file, snd_ctl_elem_value_t __ kfree(control); return -EFAULT; } - result = snd_ctl_elem_write(file, control); + result = snd_ctl_elem_write(file->card, file, control); if (result >= 0) if (copy_to_user(_control, control, sizeof(*control))) result = -EFAULT; @@ -802,35 +820,18 @@ static int snd_ctl_elem_unlock(snd_ctl_file_t *file, snd_ctl_elem_id_t __user *_ } struct user_element { - enum sndrv_ctl_elem_type type; /* element type */ - unsigned int elem_count; /* count of elements */ - union { - struct { - unsigned int items; - } enumerated; - } u; + snd_ctl_elem_info_t info; void *elem_data; /* element data */ unsigned long elem_data_size; /* size of element data in bytes */ void *priv_data; /* private data (like strings for enumerated type) */ unsigned long priv_data_size; /* size of private data in bytes */ - unsigned short dimen_count; /* count of dimensions */ - unsigned short dimen[0]; /* array of dimensions */ }; static int snd_ctl_elem_user_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) { struct user_element *ue = kcontrol->private_data; - uinfo->type = ue->type; - uinfo->count = ue->elem_count; - if (ue->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) { - uinfo->value.enumerated.items = ue->u.enumerated.items; - if (uinfo->value.enumerated.item >= ue->u.enumerated.items) - uinfo->value.enumerated.item = 0; - strlcpy(uinfo->value.enumerated.name, - (char *)ue->priv_data + uinfo->value.enumerated.item * 64, - 64); - } + *uinfo = ue->info; return 0; } @@ -847,9 +848,10 @@ static int snd_ctl_elem_user_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t int change; struct user_element *ue = kcontrol->private_data; - change = memcmp(&ucontrol->value, ue->elem_data, ue->elem_data_size); - memcpy(ue->elem_data, &ucontrol->value, ue->elem_data_size); - return !!change; + change = memcmp(&ucontrol->value, ue->elem_data, ue->elem_data_size) != 0; + if (change) + memcpy(ue->elem_data, &ucontrol->value, ue->elem_data_size); + return change; } static void snd_ctl_elem_user_free(snd_kcontrol_t * kcontrol) @@ -857,114 +859,82 @@ static void snd_ctl_elem_user_free(snd_kcontrol_t * kcontrol) kfree(kcontrol->private_data); } -static int snd_ctl_elem_add(snd_ctl_file_t *file, snd_ctl_elem_info_t __user *_info, int replace) +static int snd_ctl_elem_add(snd_ctl_file_t *file, snd_ctl_elem_info_t *info, int replace) { snd_card_t *card = file->card; - snd_ctl_elem_info_t info; snd_kcontrol_t kctl, *_kctl; unsigned int access; - long private_size, dimen_size, extra_size; + long private_size; struct user_element *ue; int idx, err; - if (copy_from_user(&info, _info, sizeof(info))) - return -EFAULT; - if (info.count > 1024) - return -EINVAL; - access = info.access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : - (info.access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|SNDRV_CTL_ELEM_ACCESS_INACTIVE| - SNDRV_CTL_ELEM_ACCESS_DINDIRECT|SNDRV_CTL_ELEM_ACCESS_INDIRECT)); - if (access & (SNDRV_CTL_ELEM_ACCESS_DINDIRECT | SNDRV_CTL_ELEM_ACCESS_INDIRECT)) + if (card->user_ctl_count >= MAX_USER_CONTROLS) + return -ENOMEM; + if (info->count > 1024) return -EINVAL; - info.id.numid = 0; + access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : + (info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|SNDRV_CTL_ELEM_ACCESS_INACTIVE)); + info->id.numid = 0; memset(&kctl, 0, sizeof(kctl)); down_write(&card->controls_rwsem); - if (!!((_kctl = snd_ctl_find_id(card, &info.id)) != NULL) ^ replace) { - up_write(&card->controls_rwsem); - return !replace ? -EBUSY : -ENOENT; - } - if (replace) { - err = snd_ctl_remove(card, _kctl); - if (err < 0) { - up_write(&card->controls_rwsem); - return err; - } + _kctl = snd_ctl_find_id(card, &info->id); + err = 0; + if (_kctl) { + if (replace) + err = snd_ctl_remove(card, _kctl); + else + err = -EBUSY; + } else { + if (replace) + err = -ENOENT; } up_write(&card->controls_rwsem); - memcpy(&kctl.id, &info.id, sizeof(info.id)); - kctl.count = info.owner ? info.owner : 1; + if (err < 0) + return err; + memcpy(&kctl.id, &info->id, sizeof(info->id)); + kctl.count = info->owner ? info->owner : 1; access |= SNDRV_CTL_ELEM_ACCESS_USER; kctl.info = snd_ctl_elem_user_info; if (access & SNDRV_CTL_ELEM_ACCESS_READ) kctl.get = snd_ctl_elem_user_get; if (access & SNDRV_CTL_ELEM_ACCESS_WRITE) kctl.put = snd_ctl_elem_user_put; - extra_size = 0; - switch (info.type) { + switch (info->type) { case SNDRV_CTL_ELEM_TYPE_BOOLEAN: private_size = sizeof(char); - if (info.count > 128) + if (info->count > 128) return -EINVAL; break; case SNDRV_CTL_ELEM_TYPE_INTEGER: private_size = sizeof(long); - if (info.count > 128) + if (info->count > 128) return -EINVAL; break; case SNDRV_CTL_ELEM_TYPE_INTEGER64: private_size = sizeof(long long); - if (info.count > 64) - return -EINVAL; - break; - case SNDRV_CTL_ELEM_TYPE_ENUMERATED: - private_size = sizeof(unsigned int); - if (info.count > 128) + if (info->count > 64) return -EINVAL; - if (info.value.enumerated.items > 1024) - return -EINVAL; - extra_size = info.value.enumerated.items * 64; break; case SNDRV_CTL_ELEM_TYPE_BYTES: private_size = sizeof(unsigned char); - if (info.count > 512) + if (info->count > 512) return -EINVAL; break; case SNDRV_CTL_ELEM_TYPE_IEC958: private_size = sizeof(struct sndrv_aes_iec958); - if (info.count != 1) + if (info->count != 1) return -EINVAL; break; default: return -EINVAL; } - private_size *= info.count; - if (private_size > 1024 * 1024) - return -EINVAL; - dimen_size = 0; - if (!(info.access & SNDRV_CTL_ELEM_ACCESS_DINDIRECT)) - for (idx = 0; idx < 4 && info.dimen.d[idx]; idx++) - dimen_size += sizeof(unsigned short); - ue = kcalloc(1, sizeof(struct user_element) + dimen_size + private_size + extra_size, GFP_KERNEL); + private_size *= info->count; + ue = kcalloc(1, sizeof(struct user_element) + private_size, GFP_KERNEL); if (ue == NULL) return -ENOMEM; - ue->type = info.type; - ue->elem_count = info.count; - if (!(info.access & SNDRV_CTL_ELEM_ACCESS_DINDIRECT)) { - for (idx = 0; idx < 4 && info.dimen.d[idx]; idx++) - ue->dimen[idx] = info.dimen.d[idx]; - ue->dimen_count = dimen_size / sizeof(unsigned short); - } - ue->elem_data = (char *)ue + sizeof(ue) + dimen_size; + ue->info = *info; + ue->elem_data = (char *)ue + sizeof(*ue); ue->elem_data_size = private_size; - if (extra_size) { - ue->priv_data = (char *)ue + sizeof(ue) + dimen_size + private_size; - ue->priv_data_size = extra_size; - if (ue->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) { - if (copy_from_user(ue->priv_data, *(char **)info.value.enumerated.name, extra_size)) - return -EFAULT; - ue->u.enumerated.items = info.value.enumerated.items; - } - } kctl.private_free = snd_ctl_elem_user_free; _kctl = snd_ctl_new(&kctl, access); if (_kctl == NULL) { @@ -979,16 +949,37 @@ static int snd_ctl_elem_add(snd_ctl_file_t *file, snd_ctl_elem_info_t __user *_i snd_ctl_free_one(_kctl); return err; } + + down_write(&card->controls_rwsem); + card->user_ctl_count++; + up_write(&card->controls_rwsem); + return 0; } +static int snd_ctl_elem_add_user(snd_ctl_file_t *file, snd_ctl_elem_info_t __user *_info, int replace) +{ + snd_ctl_elem_info_t info; + if (copy_from_user(&info, _info, sizeof(info))) + return -EFAULT; + return snd_ctl_elem_add(file, &info, replace); +} + static int snd_ctl_elem_remove(snd_ctl_file_t *file, snd_ctl_elem_id_t __user *_id) { snd_ctl_elem_id_t id; + int err; if (copy_from_user(&id, _id, sizeof(id))) return -EFAULT; - return snd_ctl_remove_unlocked_id(file, &id); + err = snd_ctl_remove_unlocked_id(file, &id); + if (! err) { + snd_card_t *card = file->card; + down_write(&card->controls_rwsem); + card->user_ctl_count--; + up_write(&card->controls_rwsem); + } + return err; } static int snd_ctl_subscribe_events(snd_ctl_file_t *file, int __user *ptr) @@ -1020,18 +1011,21 @@ static int snd_ctl_set_power_state(snd_card_t *card, unsigned int power_state) { switch (power_state) { case SNDRV_CTL_POWER_D0: - case SNDRV_CTL_POWER_D1: - case SNDRV_CTL_POWER_D2: - if (card->power_state != power_state) - /* FIXME: pass the correct state value */ - card->pm_resume(card, 0); + if (card->power_state != power_state) { + card->pm_resume(card); + snd_power_change_state(card, power_state); + } break; case SNDRV_CTL_POWER_D3hot: - case SNDRV_CTL_POWER_D3cold: - if (card->power_state != power_state) - /* FIXME: pass the correct state value */ - card->pm_suspend(card, 0); + if (card->power_state != power_state) { + card->pm_suspend(card, PMSG_SUSPEND); + snd_power_change_state(card, power_state); + } break; + case SNDRV_CTL_POWER_D1: + case SNDRV_CTL_POWER_D2: + case SNDRV_CTL_POWER_D3cold: + /* not supported yet */ default: return -EINVAL; } @@ -1039,8 +1033,7 @@ static int snd_ctl_set_power_state(snd_card_t *card, unsigned int power_state) } #endif -static inline int _snd_ctl_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { snd_ctl_file_t *ctl; snd_card_t *card; @@ -1061,7 +1054,7 @@ static inline int _snd_ctl_ioctl(struct inode *inode, struct file *file, case SNDRV_CTL_IOCTL_ELEM_LIST: return snd_ctl_elem_list(ctl->card, argp); case SNDRV_CTL_IOCTL_ELEM_INFO: - return snd_ctl_elem_info(ctl, argp); + return snd_ctl_elem_info_user(ctl, argp); case SNDRV_CTL_IOCTL_ELEM_READ: return snd_ctl_elem_read_user(ctl->card, argp); case SNDRV_CTL_IOCTL_ELEM_WRITE: @@ -1071,9 +1064,9 @@ static inline int _snd_ctl_ioctl(struct inode *inode, struct file *file, case SNDRV_CTL_IOCTL_ELEM_UNLOCK: return snd_ctl_elem_unlock(ctl, argp); case SNDRV_CTL_IOCTL_ELEM_ADD: - return snd_ctl_elem_add(ctl, argp, 0); + return snd_ctl_elem_add_user(ctl, argp, 0); case SNDRV_CTL_IOCTL_ELEM_REPLACE: - return snd_ctl_elem_add(ctl, argp, 1); + return snd_ctl_elem_add_user(ctl, argp, 1); case SNDRV_CTL_IOCTL_ELEM_REMOVE: return snd_ctl_elem_remove(ctl, argp); case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS: @@ -1113,17 +1106,6 @@ static inline int _snd_ctl_ioctl(struct inode *inode, struct file *file, return -ENOTTY; } -/* FIXME: need to unlock BKL to allow preemption */ -static int snd_ctl_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int err; - unlock_kernel(); - err = _snd_ctl_ioctl(inode, file, cmd, arg); - lock_kernel(); - return err; -} - static ssize_t snd_ctl_read(struct file *file, char __user *buffer, size_t count, loff_t * offset) { snd_ctl_file_t *ctl; @@ -1199,7 +1181,7 @@ static unsigned int snd_ctl_poll(struct file *file, poll_table * wait) * register the device-specific control-ioctls. * called from each device manager like pcm.c, hwdep.c, etc. */ -int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn) +static int _snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn, struct list_head *lists) { snd_kctl_ioctl_t *pn; @@ -1208,22 +1190,34 @@ int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn) return -ENOMEM; pn->fioctl = fcn; down_write(&snd_ioctl_rwsem); - list_add_tail(&pn->list, &snd_control_ioctls); + list_add_tail(&pn->list, lists); up_write(&snd_ioctl_rwsem); return 0; } +int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn) +{ + return _snd_ctl_register_ioctl(fcn, &snd_control_ioctls); +} + +#ifdef CONFIG_COMPAT +int snd_ctl_register_ioctl_compat(snd_kctl_ioctl_func_t fcn) +{ + return _snd_ctl_register_ioctl(fcn, &snd_control_compat_ioctls); +} +#endif + /* * de-register the device-specific control-ioctls. */ -int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn) +static int _snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn, struct list_head *lists) { struct list_head *list; snd_kctl_ioctl_t *p; snd_runtime_check(fcn != NULL, return -EINVAL); down_write(&snd_ioctl_rwsem); - list_for_each(list, &snd_control_ioctls) { + list_for_each(list, lists) { p = list_entry(list, snd_kctl_ioctl_t, list); if (p->fioctl == fcn) { list_del(&p->list); @@ -1237,6 +1231,19 @@ int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn) return -EINVAL; } +int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn) +{ + return _snd_ctl_unregister_ioctl(fcn, &snd_control_ioctls); +} + +#ifdef CONFIG_COMPAT +int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn) +{ + return _snd_ctl_unregister_ioctl(fcn, &snd_control_compat_ioctls); +} + +#endif + static int snd_ctl_fasync(int fd, struct file * file, int on) { snd_ctl_file_t *ctl; @@ -1248,6 +1255,15 @@ static int snd_ctl_fasync(int fd, struct file * file, int on) return 0; } +/* + * ioctl32 compat + */ +#ifdef CONFIG_COMPAT +#include "control_compat.c" +#else +#define snd_ctl_ioctl_compat NULL +#endif + /* * INIT PART */ @@ -1259,7 +1275,8 @@ static struct file_operations snd_ctl_f_ops = .open = snd_ctl_open, .release = snd_ctl_release, .poll = snd_ctl_poll, - .ioctl = snd_ctl_ioctl, + .unlocked_ioctl = snd_ctl_ioctl, + .compat_ioctl = snd_ctl_ioctl_compat, .fasync = snd_ctl_fasync, }; @@ -1270,11 +1287,11 @@ static snd_minor_t snd_ctl_reg = }; /* - * registration of the control device: - * called from init.c + * registration of the control device */ -int snd_ctl_register(snd_card_t *card) +static int snd_ctl_dev_register(snd_device_t *device) { + snd_card_t *card = device->device_data; int err, cardnum; char name[16]; @@ -1289,11 +1306,11 @@ int snd_ctl_register(snd_card_t *card) } /* - * disconnection of the control device: - * called from init.c + * disconnection of the control device */ -int snd_ctl_disconnect(snd_card_t *card) +static int snd_ctl_dev_disconnect(snd_device_t *device) { + snd_card_t *card = device->device_data; struct list_head *flist; snd_ctl_file_t *ctl; @@ -1308,19 +1325,13 @@ int snd_ctl_disconnect(snd_card_t *card) } /* - * de-registration of the control device: - * called from init.c + * free all controls */ -int snd_ctl_unregister(snd_card_t *card) +static int snd_ctl_dev_free(snd_device_t *device) { - int err, cardnum; + snd_card_t *card = device->device_data; snd_kcontrol_t *control; - snd_assert(card != NULL, return -ENXIO); - cardnum = card->number; - snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO); - if ((err = snd_unregister_device(SNDRV_DEVICE_TYPE_CONTROL, card, 0)) < 0) - return err; down_write(&card->controls_rwsem); while (!list_empty(&card->controls)) { control = snd_kcontrol(card->controls.next); @@ -1329,3 +1340,36 @@ int snd_ctl_unregister(snd_card_t *card) up_write(&card->controls_rwsem); return 0; } + +/* + * de-registration of the control device + */ +static int snd_ctl_dev_unregister(snd_device_t *device) +{ + snd_card_t *card = device->device_data; + int err, cardnum; + + snd_assert(card != NULL, return -ENXIO); + cardnum = card->number; + snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO); + if ((err = snd_unregister_device(SNDRV_DEVICE_TYPE_CONTROL, card, 0)) < 0) + return err; + return snd_ctl_dev_free(device); +} + +/* + * create control core: + * called from init.c + */ +int snd_ctl_create(snd_card_t *card) +{ + static snd_device_ops_t ops = { + .dev_free = snd_ctl_dev_free, + .dev_register = snd_ctl_dev_register, + .dev_disconnect = snd_ctl_dev_disconnect, + .dev_unregister = snd_ctl_dev_unregister + }; + + snd_assert(card != NULL, return -ENXIO); + return snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops); +} diff --git a/sound/core/init.c b/sound/core/init.c index efa128c27..d72f58f45 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -37,10 +37,9 @@ struct snd_shutdown_f_ops { struct snd_shutdown_f_ops *next; }; -int snd_cards_count = 0; unsigned int snd_cards_lock = 0; /* locked for registering/using */ snd_card_t *snd_cards[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = NULL}; -rwlock_t snd_card_rwlock = RW_LOCK_UNLOCKED; +DEFINE_RWLOCK(snd_card_rwlock); #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) int (*snd_mixer_oss_notify_callback)(snd_card_t *card, int free_flag); @@ -85,16 +84,13 @@ snd_card_t *snd_card_new(int idx, const char *xid, write_lock(&snd_card_rwlock); if (idx < 0) { int idx2; - for (idx2 = 0; idx2 < snd_ecards_limit; idx2++) - if (!(snd_cards_lock & (1 << idx2))) { + for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++) + if (~snd_cards_lock & idx & 1<<idx2) { idx = idx2; + if (idx >= snd_ecards_limit) + snd_ecards_limit = idx + 1; break; } - if (idx < 0 && snd_ecards_limit < SNDRV_CARDS) - /* for dynamically additional devices like hotplug: - * increment the limit if still free slot exists. - */ - idx = snd_ecards_limit++; } else if (idx < snd_ecards_limit) { if (snd_cards_lock & (1 << idx)) err = -ENODEV; /* invalid */ @@ -125,7 +121,7 @@ snd_card_t *snd_card_new(int idx, const char *xid, #endif /* the control interface cannot be accessed from the user space until */ /* snd_cards_bitmask and snd_cards are set with snd_card_register */ - if ((err = snd_ctl_register(card)) < 0) { + if ((err = snd_ctl_create(card)) < 0) { snd_printd("unable to register control minors\n"); goto __error; } @@ -138,7 +134,7 @@ snd_card_t *snd_card_new(int idx, const char *xid, return card; __error_ctl: - snd_ctl_unregister(card); + snd_device_free_all(card, SNDRV_DEV_CMD_PRE); __error: kfree(card); return NULL; @@ -217,8 +213,6 @@ int snd_card_disconnect(snd_card_t * card) /* phase 3: notify all connected devices about disconnection */ /* at this point, they cannot respond to any calls except release() */ - snd_ctl_disconnect(card); - #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) if (snd_mixer_oss_notify_callback) snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_DISCONNECT); @@ -232,6 +226,10 @@ int snd_card_disconnect(snd_card_t * card) return 0; } +#if defined(CONFIG_PM) && defined(CONFIG_SND_GENERIC_PM) +static void snd_generic_device_unregister(struct snd_generic_device *dev); +#endif + /** * snd_card_free - frees given soundcard structure * @card: soundcard structure @@ -251,14 +249,13 @@ int snd_card_free(snd_card_t * card) return -EINVAL; write_lock(&snd_card_rwlock); snd_cards[card->number] = NULL; - snd_cards_count--; write_unlock(&snd_card_rwlock); #ifdef CONFIG_PM wake_up(&card->power_sleep); -#ifdef CONFIG_ISA +#ifdef CONFIG_SND_GENERIC_PM if (card->pm_dev) { - pm_unregister(card->pm_dev); + snd_generic_device_unregister(card->pm_dev); card->pm_dev = NULL; } #endif @@ -279,10 +276,6 @@ int snd_card_free(snd_card_t * card) snd_printk(KERN_ERR "unable to free all devices (normal)\n"); /* Fatal, but this situation should never occur */ } - if (snd_ctl_unregister(card) < 0) { - snd_printk(KERN_ERR "unable to unregister control minors\n"); - /* Not fatal error */ - } if (snd_device_free_all(card, SNDRV_DEV_CMD_POST) < 0) { snd_printk(KERN_ERR "unable to free all devices (post)\n"); /* Fatal, but this situation should never occur */ @@ -382,7 +375,7 @@ static void choose_default_id(snd_card_t * card) while (1) { if (loops-- == 0) { - snd_printk(KERN_ERR "unable to choose default card id (%s)", id); + snd_printk(KERN_ERR "unable to choose default card id (%s)\n", id); strcpy(card->id, card->proc_root->name); return; } @@ -441,7 +434,6 @@ int snd_card_register(snd_card_t * card) if (card->id[0] == '\0') choose_default_id(card); snd_cards[card->number] = card; - snd_cards_count++; write_unlock(&snd_card_rwlock); if ((err = snd_info_card_register(card)) < 0) { snd_printd("unable to create card info\n"); @@ -665,12 +657,11 @@ int snd_card_file_remove(snd_card_t *card, struct file *file) spin_unlock(&card->files_lock); if (card->files == NULL) wake_up(&card->shutdown_sleep); - if (mfile) { - kfree(mfile); - } else { + if (!mfile) { snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file); return -ENOENT; } + kfree(mfile); return 0; } @@ -729,8 +720,8 @@ int snd_power_wait(snd_card_t *card, unsigned int power_state, struct file *file * handler and from the control API. */ int snd_card_set_pm_callback(snd_card_t *card, - int (*suspend)(snd_card_t *, unsigned int), - int (*resume)(snd_card_t *, unsigned int), + int (*suspend)(snd_card_t *, pm_message_t), + int (*resume)(snd_card_t *), void *private_data) { card->pm_suspend = suspend; @@ -739,50 +730,132 @@ int snd_card_set_pm_callback(snd_card_t *card, return 0; } -static int snd_generic_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) +#ifdef CONFIG_SND_GENERIC_PM +/* + * use platform_device for generic power-management without a proper bus + * (e.g. ISA) + */ +struct snd_generic_device { + struct platform_device pdev; + snd_card_t *card; +}; + +#define get_snd_generic_card(dev) container_of(to_platform_device(dev), struct snd_generic_device, pdev)->card + +#define SND_GENERIC_NAME "snd_generic_pm" + +static int snd_generic_suspend(struct device *dev, pm_message_t state, u32 level); +static int snd_generic_resume(struct device *dev, u32 level); + +static struct device_driver snd_generic_driver = { + .name = SND_GENERIC_NAME, + .bus = &platform_bus_type, + .suspend = snd_generic_suspend, + .resume = snd_generic_resume, +}; + +static int generic_driver_registered; + +static void generic_driver_unregister(void) +{ + if (generic_driver_registered) { + generic_driver_registered--; + if (! generic_driver_registered) + driver_unregister(&snd_generic_driver); + } +} + +static struct snd_generic_device *snd_generic_device_register(snd_card_t *card) { - snd_card_t *card = dev->data; + struct snd_generic_device *dev; - switch (rqst) { - case PM_SUSPEND: - /* FIXME: the correct state value? */ - card->pm_suspend(card, 0); - break; - case PM_RESUME: - /* FIXME: the correct state value? */ - card->pm_resume(card, 0); - break; + if (! generic_driver_registered) { + if (driver_register(&snd_generic_driver) < 0) + return NULL; + } + generic_driver_registered++; + + dev = kcalloc(1, sizeof(*dev), GFP_KERNEL); + if (! dev) { + generic_driver_unregister(); + return NULL; } + + dev->pdev.name = SND_GENERIC_NAME; + dev->pdev.id = card->number; + dev->card = card; + if (platform_device_register(&dev->pdev) < 0) { + kfree(dev); + generic_driver_unregister(); + return NULL; + } + return dev; +} + +static void snd_generic_device_unregister(struct snd_generic_device *dev) +{ + platform_device_unregister(&dev->pdev); + kfree(dev); + generic_driver_unregister(); +} + +/* suspend/resume callbacks for snd_generic platform device */ +static int snd_generic_suspend(struct device *dev, pm_message_t state, u32 level) +{ + snd_card_t *card; + + if (level != SUSPEND_DISABLE) + return 0; + + card = get_snd_generic_card(dev); + if (card->power_state == SNDRV_CTL_POWER_D3hot) + return 0; + card->pm_suspend(card, PMSG_SUSPEND); + snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); + return 0; +} + +static int snd_generic_resume(struct device *dev, u32 level) +{ + snd_card_t *card; + + if (level != RESUME_ENABLE) + return 0; + + card = get_snd_generic_card(dev); + if (card->power_state == SNDRV_CTL_POWER_D0) + return 0; + card->pm_resume(card); + snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; } /** - * snd_card_set_dev_pm_callback - set the generic power-management callbacks + * snd_card_set_generic_pm_callback - set the generic power-management callbacks * @card: soundcard structure - * @type: PM device type (PM_XXX) * @suspend: suspend callback function * @resume: resume callback function * @private_data: private data to pass to the callback functions * * Registers the power-management and sets the lowlevel callbacks for - * the given card with the given PM type. These callbacks are called - * from the ALSA's common PM handler and from the control API. + * the given card. These callbacks are called from the ALSA's common + * PM handler and from the control API. */ -int snd_card_set_dev_pm_callback(snd_card_t *card, int type, - int (*suspend)(snd_card_t *, unsigned int), - int (*resume)(snd_card_t *, unsigned int), +int snd_card_set_generic_pm_callback(snd_card_t *card, + int (*suspend)(snd_card_t *, pm_message_t), + int (*resume)(snd_card_t *), void *private_data) { - card->pm_dev = pm_register(type, 0, snd_generic_pm_callback); + card->pm_dev = snd_generic_device_register(card); if (! card->pm_dev) return -ENOMEM; - card->pm_dev->data = card; snd_card_set_pm_callback(card, suspend, resume, private_data); return 0; } +#endif /* CONFIG_SND_GENERIC_PM */ #ifdef CONFIG_PCI -int snd_card_pci_suspend(struct pci_dev *dev, u32 state) +int snd_card_pci_suspend(struct pci_dev *dev, pm_message_t state) { snd_card_t *card = pci_get_drvdata(dev); int err; @@ -790,9 +863,9 @@ int snd_card_pci_suspend(struct pci_dev *dev, u32 state) return 0; if (card->power_state == SNDRV_CTL_POWER_D3hot) return 0; - /* FIXME: correct state value? */ - err = card->pm_suspend(card, 0); + err = card->pm_suspend(card, PMSG_SUSPEND); pci_save_state(dev); + snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return err; } @@ -805,8 +878,9 @@ int snd_card_pci_resume(struct pci_dev *dev) return 0; /* restore the PCI config space */ pci_restore_state(dev); - /* FIXME: correct state value? */ - return card->pm_resume(card, 0); + card->pm_resume(card); + snd_power_change_state(card, SNDRV_CTL_POWER_D0); + return 0; } #endif diff --git a/sound/core/ioctl32/Makefile b/sound/core/ioctl32/Makefile deleted file mode 100644 index 0d0eacd42..000000000 --- a/sound/core/ioctl32/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz> -# - -snd-ioctl32-objs := ioctl32.o pcm32.o rawmidi32.o timer32.o hwdep32.o -ifneq ($(CONFIG_SND_SEQUENCER),n) - snd-ioctl32-objs += seq32.o -endif - -obj-$(CONFIG_SND_BIT32_EMUL) += snd-ioctl32.o diff --git a/sound/core/ioctl32/hwdep32.c b/sound/core/ioctl32/hwdep32.c deleted file mode 100644 index d3fd14c6a..000000000 --- a/sound/core/ioctl32/hwdep32.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 32bit -> 64bit ioctl wrapper for hwdep API - * Copyright (c) by Takashi Iwai <tiwai@suse.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 - * - */ - -#include <sound/driver.h> -#include <linux/time.h> -#include <linux/fs.h> -#include <sound/core.h> -#include <sound/hwdep.h> -#include <asm/uaccess.h> -#include "ioctl32.h" - -struct sndrv_hwdep_dsp_image32 { - u32 index; - unsigned char name[64]; - u32 image; /* pointer */ - u32 length; - u32 driver_data; -} /* don't set packed attribute here */; - -static inline int _snd_ioctl32_hwdep_dsp_image(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl) -{ - struct sndrv_hwdep_dsp_image __user *data, *dst; - struct sndrv_hwdep_dsp_image32 __user *data32, *src; - compat_caddr_t ptr; - - data32 = compat_ptr(arg); - data = compat_alloc_user_space(sizeof(*data)); - - /* index and name */ - if (copy_in_user(data, data32, 4 + 64)) - return -EFAULT; - if (__get_user(ptr, &data32->image) || - __put_user(compat_ptr(ptr), &data->image)) - return -EFAULT; - src = data32; - dst = data; - COPY_CVT(length); - COPY_CVT(driver_data); - return file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data); -} - -DEFINE_ALSA_IOCTL_ENTRY(hwdep_dsp_image, hwdep_dsp_image, SNDRV_HWDEP_IOCTL_DSP_LOAD); - -#define AP(x) snd_ioctl32_##x - -enum { - SNDRV_HWDEP_IOCTL_DSP_LOAD32 = _IOW('H', 0x03, struct sndrv_hwdep_dsp_image32) -}; - -struct ioctl32_mapper hwdep_mappers[] = { - MAP_COMPAT(SNDRV_HWDEP_IOCTL_PVERSION), - MAP_COMPAT(SNDRV_HWDEP_IOCTL_INFO), - MAP_COMPAT(SNDRV_HWDEP_IOCTL_DSP_STATUS), - { SNDRV_HWDEP_IOCTL_DSP_LOAD32, AP(hwdep_dsp_image) }, - { 0 }, -}; diff --git a/sound/core/ioctl32/ioctl32.c b/sound/core/ioctl32/ioctl32.c deleted file mode 100644 index 633a980ad..000000000 --- a/sound/core/ioctl32/ioctl32.c +++ /dev/null @@ -1,490 +0,0 @@ -/* - * 32bit -> 64bit ioctl wrapper for control API - * Copyright (c) by Takashi Iwai <tiwai@suse.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 - * - */ - -#include <sound/driver.h> -#include <linux/sched.h> -#include <linux/smp_lock.h> -#include <linux/init.h> -#include <linux/time.h> -#include <linux/slab.h> -#include <linux/fs.h> -#include <sound/core.h> -#include <sound/control.h> -#include <sound/minors.h> -#include <asm/uaccess.h> -#include "ioctl32.h" - - -/* - * register/unregister mappers - * exported for other modules - */ - -MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); -MODULE_DESCRIPTION("ioctl32 wrapper for ALSA"); -MODULE_LICENSE("GPL"); - -int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *)); -int unregister_ioctl32_conversion(unsigned int cmd); - - -int snd_ioctl32_register(struct ioctl32_mapper *mappers) -{ - int err; - struct ioctl32_mapper *m; - - for (m = mappers; m->cmd; m++) { - err = register_ioctl32_conversion(m->cmd, m->handler); - if (err >= 0) - m->registered++; - } - return 0; -} - -void snd_ioctl32_unregister(struct ioctl32_mapper *mappers) -{ - struct ioctl32_mapper *m; - - for (m = mappers; m->cmd; m++) { - if (m->registered) { - unregister_ioctl32_conversion(m->cmd); - m->registered = 0; - } - } -} - - -/* - * compatible wrapper - */ -int snd_ioctl32_compat(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *filp) -{ - if (! filp->f_op || ! filp->f_op->ioctl) - return -ENOTTY; - return filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg); -} - - -/* - * Controls - */ - -struct sndrv_ctl_elem_list32 { - u32 offset; - u32 space; - u32 used; - u32 count; - u32 pids; - unsigned char reserved[50]; -} /* don't set packed attribute here */; - -static inline int _snd_ioctl32_ctl_elem_list(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl) -{ - struct sndrv_ctl_elem_list32 __user *data32; - struct sndrv_ctl_elem_list __user *data; - compat_caddr_t ptr; - int err; - - data32 = compat_ptr(arg); - data = compat_alloc_user_space(sizeof(*data)); - - /* offset, space, used, count */ - if (copy_in_user(data, data32, 4 * sizeof(u32))) - return -EFAULT; - /* pids */ - if (__get_user(ptr, &data32->pids) || - __put_user(compat_ptr(ptr), &data->pids)) - return -EFAULT; - err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data); - if (err < 0) - return err; - /* copy the result */ - if (copy_in_user(data32, data, 4 * sizeof(u32))) - return -EFAULT; - return 0; -} - -DEFINE_ALSA_IOCTL_ENTRY(ctl_elem_list, ctl_elem_list, SNDRV_CTL_IOCTL_ELEM_LIST); - -/* - * control element info - * it uses union, so the things are not easy.. - */ - -struct sndrv_ctl_elem_info32 { - struct sndrv_ctl_elem_id id; // the size of struct is same - s32 type; - u32 access; - u32 count; - s32 owner; - union { - struct { - s32 min; - s32 max; - s32 step; - } integer; - struct { - u64 min; - u64 max; - u64 step; - } integer64; - struct { - u32 items; - u32 item; - char name[64]; - } enumerated; - unsigned char reserved[128]; - } value; - unsigned char reserved[64]; -} __attribute__((packed)); - -static inline int _snd_ioctl32_ctl_elem_info(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl) -{ - struct sndrv_ctl_elem_info __user *data, *src; - struct sndrv_ctl_elem_info32 __user *data32, *dst; - unsigned int type; - int err; - - data32 = compat_ptr(arg); - data = compat_alloc_user_space(sizeof(*data)); - - /* copy id */ - if (copy_in_user(&data->id, &data32->id, sizeof(data->id))) - return -EFAULT; - /* we need to copy the item index. - * hope this doesn't break anything.. - */ - if (copy_in_user(&data->value.enumerated.item, - &data32->value.enumerated.item, - sizeof(data->value.enumerated.item))) - return -EFAULT; - err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data); - if (err < 0) - return err; - /* restore info to 32bit */ - /* for COPY_CVT macro */ - src = data; - dst = data32; - /* id, type, access, count */ - if (copy_in_user(&data32->id, &data->id, sizeof(data->id)) || - copy_in_user(&data32->type, &data->type, 3 * sizeof(u32))) - return -EFAULT; - COPY_CVT(owner); - __get_user(type, &data->type); - switch (type) { - case SNDRV_CTL_ELEM_TYPE_BOOLEAN: - case SNDRV_CTL_ELEM_TYPE_INTEGER: - COPY_CVT(value.integer.min); - COPY_CVT(value.integer.max); - COPY_CVT(value.integer.step); - break; - case SNDRV_CTL_ELEM_TYPE_INTEGER64: - if (copy_in_user(&data32->value.integer64, - &data->value.integer64, - sizeof(data->value.integer64))) - return -EFAULT; - break; - case SNDRV_CTL_ELEM_TYPE_ENUMERATED: - if (copy_in_user(&data32->value.enumerated, - &data->value.enumerated, - sizeof(data->value.enumerated))) - return -EFAULT; - break; - default: - break; - } - return 0; -} - -DEFINE_ALSA_IOCTL_ENTRY(ctl_elem_info, ctl_elem_info, SNDRV_CTL_IOCTL_ELEM_INFO); - -struct sndrv_ctl_elem_value32 { - struct sndrv_ctl_elem_id id; - unsigned int indirect; /* bit-field causes misalignment */ - union { - union { - s32 value[128]; - u32 value_ptr; - } integer; - union { - s64 value[64]; - u32 value_ptr; - } integer64; - union { - u32 item[128]; - u32 item_ptr; - } enumerated; - union { - unsigned char data[512]; - u32 data_ptr; - } bytes; - struct sndrv_aes_iec958 iec958; - } value; - unsigned char reserved[128]; -}; - - -/* hmm, it's so hard to retrieve the value type from the control id.. */ -static int get_ctl_type(snd_card_t *card, snd_ctl_elem_id_t *id) -{ - snd_kcontrol_t *kctl; - snd_ctl_elem_info_t info; - int err; - - down_read(&card->controls_rwsem); - kctl = snd_ctl_find_id(card, id); - if (! kctl) { - up_read(&card->controls_rwsem); - return -ENXIO; - } - info.id = *id; - err = kctl->info(kctl, &info); - up_read(&card->controls_rwsem); - if (err >= 0) - err = info.type; - return err; -} - -extern int snd_major; - -static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl) -{ - struct sndrv_ctl_elem_value *data; - struct sndrv_ctl_elem_value32 __user *data32; - snd_ctl_file_t *ctl; - int err, i; - int type; - - /* sanity check */ - if (imajor(file->f_dentry->d_inode) != snd_major || - SNDRV_MINOR_DEVICE(iminor(file->f_dentry->d_inode)) != SNDRV_MINOR_CONTROL) - return -ENOTTY; - - if ((ctl = file->private_data) == NULL) - return -ENOTTY; - - data32 = compat_ptr(arg); - data = kmalloc(sizeof(*data), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - - if (copy_from_user(&data->id, &data32->id, sizeof(data->id))) { - err = -EFAULT; - goto __end; - } - if (__get_user(data->indirect, &data32->indirect)) { - err = -EFAULT; - goto __end; - } - /* FIXME: indirect access is not supported */ - if (data->indirect) { - err = -EINVAL; - goto __end; - } - type = get_ctl_type(ctl->card, &data->id); - if (type < 0) { - err = type; - goto __end; - } - - switch (type) { - case SNDRV_CTL_ELEM_TYPE_BOOLEAN: - case SNDRV_CTL_ELEM_TYPE_INTEGER: - for (i = 0; i < 128; i++) { - int val; - if (__get_user(val, &data32->value.integer.value[i])) { - err = -EFAULT; - goto __end; - } - data->value.integer.value[i] = val; - } - break; - case SNDRV_CTL_ELEM_TYPE_INTEGER64: - if (__copy_from_user(data->value.integer64.value, - data32->value.integer64.value, - sizeof(data->value.integer64.value))) { - err = -EFAULT; - goto __end; - } - break; - case SNDRV_CTL_ELEM_TYPE_ENUMERATED: - if (__copy_from_user(data->value.enumerated.item, - data32->value.enumerated.item, - sizeof(data32->value.enumerated.item))) { - err = -EFAULT; - goto __end; - } - break; - case SNDRV_CTL_ELEM_TYPE_BYTES: - if (__copy_from_user(data->value.bytes.data, - data32->value.bytes.data, - sizeof(data32->value.bytes.data))) { - err = -EFAULT; - goto __end; - } - break; - case SNDRV_CTL_ELEM_TYPE_IEC958: - if (__copy_from_user(&data->value.iec958, - &data32->value.iec958, - sizeof(data32->value.iec958))) { - err = -EFAULT; - goto __end; - } - break; - default: - printk(KERN_ERR "snd_ioctl32_ctl_elem_value: unknown type %d\n", type); - err = -EINVAL; - goto __end; - } - - if (native_ctl == SNDRV_CTL_IOCTL_ELEM_READ) - err = snd_ctl_elem_read(ctl->card, data); - else - err = snd_ctl_elem_write(ctl, data); - if (err < 0) - goto __end; - /* restore info to 32bit */ - switch (type) { - case SNDRV_CTL_ELEM_TYPE_BOOLEAN: - case SNDRV_CTL_ELEM_TYPE_INTEGER: - for (i = 0; i < 128; i++) { - int val; - val = data->value.integer.value[i]; - if (__put_user(val, &data32->value.integer.value[i])) { - err = -EFAULT; - goto __end; - } - } - break; - case SNDRV_CTL_ELEM_TYPE_INTEGER64: - if (__copy_to_user(data32->value.integer64.value, - data->value.integer64.value, - sizeof(data32->value.integer64.value))) { - err = -EFAULT; - goto __end; - } - break; - case SNDRV_CTL_ELEM_TYPE_ENUMERATED: - if (__copy_to_user(data32->value.enumerated.item, - data->value.enumerated.item, - sizeof(data32->value.enumerated.item))) { - err = -EFAULT; - goto __end; - } - break; - case SNDRV_CTL_ELEM_TYPE_BYTES: - if (__copy_to_user(data32->value.bytes.data, - data->value.bytes.data, - sizeof(data32->value.bytes.data))) { - err = -EFAULT; - goto __end; - } - break; - case SNDRV_CTL_ELEM_TYPE_IEC958: - if (__copy_to_user(&data32->value.iec958, - &data->value.iec958, - sizeof(data32->value.iec958))) { - err = -EFAULT; - goto __end; - } - break; - } - err = 0; - __end: - if (data) - kfree(data); - return err; -} - -DEFINE_ALSA_IOCTL_ENTRY(ctl_elem_read, ctl_elem_value, SNDRV_CTL_IOCTL_ELEM_READ); -DEFINE_ALSA_IOCTL_ENTRY(ctl_elem_write, ctl_elem_value, SNDRV_CTL_IOCTL_ELEM_WRITE); - -/* - */ - -#define AP(x) snd_ioctl32_##x - -enum { - SNDRV_CTL_IOCTL_ELEM_LIST32 = _IOWR('U', 0x10, struct sndrv_ctl_elem_list32), - SNDRV_CTL_IOCTL_ELEM_INFO32 = _IOWR('U', 0x11, struct sndrv_ctl_elem_info32), - SNDRV_CTL_IOCTL_ELEM_READ32 = _IOWR('U', 0x12, struct sndrv_ctl_elem_value32), - SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct sndrv_ctl_elem_value32), -}; - -static struct ioctl32_mapper control_mappers[] = { - /* controls (without rawmidi, hwdep, timer releated ones) */ - MAP_COMPAT(SNDRV_CTL_IOCTL_PVERSION), - MAP_COMPAT(SNDRV_CTL_IOCTL_CARD_INFO), - { SNDRV_CTL_IOCTL_ELEM_LIST32, AP(ctl_elem_list) }, - { SNDRV_CTL_IOCTL_ELEM_INFO32, AP(ctl_elem_info) }, - { SNDRV_CTL_IOCTL_ELEM_READ32, AP(ctl_elem_read) }, - { SNDRV_CTL_IOCTL_ELEM_WRITE32, AP(ctl_elem_write) }, - MAP_COMPAT(SNDRV_CTL_IOCTL_ELEM_LOCK), - MAP_COMPAT(SNDRV_CTL_IOCTL_ELEM_UNLOCK), - MAP_COMPAT(SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS), - MAP_COMPAT(SNDRV_CTL_IOCTL_HWDEP_INFO), - MAP_COMPAT(SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE), - MAP_COMPAT(SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE), - MAP_COMPAT(SNDRV_CTL_IOCTL_PCM_INFO), - MAP_COMPAT(SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE), - MAP_COMPAT(SNDRV_CTL_IOCTL_POWER), - MAP_COMPAT(SNDRV_CTL_IOCTL_POWER_STATE), - { 0 } -}; - - -/* - */ - -extern struct ioctl32_mapper pcm_mappers[]; -extern struct ioctl32_mapper rawmidi_mappers[]; -extern struct ioctl32_mapper timer_mappers[]; -extern struct ioctl32_mapper hwdep_mappers[]; -#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) -extern struct ioctl32_mapper seq_mappers[]; -#endif - -static void snd_ioctl32_done(void) -{ -#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) - snd_ioctl32_unregister(seq_mappers); -#endif - snd_ioctl32_unregister(hwdep_mappers); - snd_ioctl32_unregister(timer_mappers); - snd_ioctl32_unregister(rawmidi_mappers); - snd_ioctl32_unregister(pcm_mappers); - snd_ioctl32_unregister(control_mappers); -} - -static int __init snd_ioctl32_init(void) -{ - snd_ioctl32_register(control_mappers); - snd_ioctl32_register(pcm_mappers); - snd_ioctl32_register(rawmidi_mappers); - snd_ioctl32_register(timer_mappers); - snd_ioctl32_register(hwdep_mappers); -#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) - snd_ioctl32_register(seq_mappers); -#endif - return 0; -} - -module_init(snd_ioctl32_init) -module_exit(snd_ioctl32_done) diff --git a/sound/core/ioctl32/ioctl32.h b/sound/core/ioctl32/ioctl32.h deleted file mode 100644 index a8825a87a..000000000 --- a/sound/core/ioctl32/ioctl32.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 32bit -> 64bit ioctl helpers - * Copyright (c) by Takashi Iwai <tiwai@suse.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 - * - * - * This file registers the converters from 32-bit ioctls to 64-bit ones. - * The converter assumes that a 32-bit user-pointer can be casted by compat_ptr(x) - * macro to a valid 64-bit pointer which is accessible via copy_from/to_user. - * - */ - -#ifndef __ALSA_IOCTL32_H -#define __ALSA_IOCTL32_H - -#include <linux/compat.h> - -#define COPY(x) \ - do { \ - if (copy_in_user(&dst->x, &src->x, sizeof(dst->x))) \ - return -EFAULT; \ - } while (0) - -#define COPY_ARRAY(x) \ - do { \ - if (copy_in_user(dst->x, src->x, sizeof(dst->x))) \ - return -EFAULT; \ - } while (0) - -#define COPY_CVT(x) \ - do { \ - __typeof__(src->x) __val_tmp; \ - if (get_user(__val_tmp, &src->x) || \ - put_user(__val_tmp, &dst->x))\ - return -EFAULT; \ - } while (0) - -#define convert_from_32(type, dstp, srcp)\ -{\ - struct sndrv_##type __user *dst = dstp;\ - struct sndrv_##type##32 __user *src = srcp;\ - CVT_##sndrv_##type();\ -} - -#define convert_to_32(type, dstp, srcp)\ -{\ - struct sndrv_##type __user *src = srcp;\ - struct sndrv_##type##32 __user *dst = dstp;\ - CVT_##sndrv_##type();\ -} - - -#define DEFINE_ALSA_IOCTL(type) \ -static inline int _snd_ioctl32_##type(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)\ -{\ - struct sndrv_##type##32 __user *data32;\ - struct sndrv_##type __user *data;\ - int err;\ - data32 = compat_ptr(arg);\ - data = compat_alloc_user_space(sizeof(*data));\ - convert_from_32(type, data, data32);\ - err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);\ - if (err < 0) \ - return err;\ - if (native_ctl & (_IOC_READ << _IOC_DIRSHIFT)) {\ - convert_to_32(type, data32, data);\ - }\ - return 0;\ -} - -#define DEFINE_ALSA_IOCTL_ENTRY(name,type,native_ctl) \ -static int snd_ioctl32_##name(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file) {\ - return _snd_ioctl32_##type(fd, cmd, arg, file, native_ctl);\ -} - -#define MAP_COMPAT(ctl) { ctl, snd_ioctl32_compat } - -struct ioctl32_mapper { - unsigned int cmd; - int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp); - int registered; -}; - -int snd_ioctl32_compat(unsigned int, unsigned int, unsigned long, struct file *); - -int snd_ioctl32_register(struct ioctl32_mapper *mappers); -void snd_ioctl32_unregister(struct ioctl32_mapper *mappers); - -#endif /* __ALSA_IOCTL32_H */ diff --git a/sound/core/ioctl32/pcm32.c b/sound/core/ioctl32/pcm32.c deleted file mode 100644 index 66ce5e161..000000000 --- a/sound/core/ioctl32/pcm32.c +++ /dev/null @@ -1,461 +0,0 @@ -/* - * 32bit -> 64bit ioctl wrapper for PCM API - * Copyright (c) by Takashi Iwai <tiwai@suse.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 - * - */ - -#include <sound/driver.h> -#include <linux/time.h> -#include <linux/slab.h> -#include <linux/compat.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/minors.h> -#include "ioctl32.h" - - -/* wrapper for sndrv_pcm_[us]frames */ -struct sndrv_pcm_sframes_str { - sndrv_pcm_sframes_t val; -}; -struct sndrv_pcm_sframes_str32 { - s32 val; -}; -struct sndrv_pcm_uframes_str { - sndrv_pcm_uframes_t val; -}; -struct sndrv_pcm_uframes_str32 { - u32 val; -}; - -#define CVT_sndrv_pcm_sframes_str() { COPY_CVT(val); } -#define CVT_sndrv_pcm_uframes_str() { COPY_CVT(val); } - - -struct sndrv_pcm_hw_params32 { - u32 flags; - struct sndrv_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; /* this must be identical */ - struct sndrv_mask mres[5]; /* reserved masks */ - struct sndrv_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1]; - struct sndrv_interval ires[9]; /* reserved intervals */ - u32 rmask; - u32 cmask; - u32 info; - u32 msbits; - u32 rate_num; - u32 rate_den; - u32 fifo_size; - unsigned char reserved[64]; -} __attribute__((packed)); - -struct sndrv_pcm_sw_params32 { - s32 tstamp_mode; - u32 period_step; - u32 sleep_min; - u32 avail_min; - u32 xfer_align; - u32 start_threshold; - u32 stop_threshold; - u32 silence_threshold; - u32 silence_size; - u32 boundary; - unsigned char reserved[64]; -} __attribute__((packed)); - -#define CVT_sndrv_pcm_sw_params()\ -{\ - COPY(tstamp_mode);\ - COPY(period_step);\ - COPY(sleep_min);\ - COPY_CVT(avail_min);\ - COPY_CVT(xfer_align);\ - COPY_CVT(start_threshold);\ - COPY_CVT(stop_threshold);\ - COPY_CVT(silence_threshold);\ - COPY_CVT(silence_size);\ - COPY_CVT(boundary);\ -} - -struct sndrv_pcm_channel_info32 { - u32 channel; - u32 offset; - u32 first; - u32 step; -} __attribute__((packed)); - -#define CVT_sndrv_pcm_channel_info()\ -{\ - COPY(channel);\ - COPY_CVT(offset);\ - COPY(first);\ - COPY(step);\ -} - -struct sndrv_pcm_status32 { - s32 state; - struct compat_timespec trigger_tstamp; - struct compat_timespec tstamp; - u32 appl_ptr; - u32 hw_ptr; - s32 delay; - u32 avail; - u32 avail_max; - u32 overrange; - s32 suspended_state; - unsigned char reserved[60]; -} __attribute__((packed)); - -#define CVT_sndrv_pcm_status()\ -{\ - COPY(state);\ - COPY_CVT(trigger_tstamp.tv_sec);\ - COPY_CVT(trigger_tstamp.tv_nsec);\ - COPY_CVT(tstamp.tv_sec);\ - COPY_CVT(tstamp.tv_nsec);\ - COPY_CVT(appl_ptr);\ - COPY_CVT(hw_ptr);\ - COPY_CVT(delay);\ - COPY_CVT(avail);\ - COPY_CVT(avail_max);\ - COPY_CVT(overrange);\ - COPY(suspended_state);\ -} - -DEFINE_ALSA_IOCTL(pcm_uframes_str); -DEFINE_ALSA_IOCTL(pcm_sframes_str); -DEFINE_ALSA_IOCTL(pcm_sw_params); -DEFINE_ALSA_IOCTL(pcm_channel_info); -DEFINE_ALSA_IOCTL(pcm_status); - -/* sanity device check */ -extern int snd_major; -static int sanity_check_pcm(struct file *file) -{ - unsigned short minor; - if (imajor(file->f_dentry->d_inode) != snd_major) - return -ENOTTY; - minor = iminor(file->f_dentry->d_inode); - if (minor >= 256 || - minor % SNDRV_MINOR_DEVICES < SNDRV_MINOR_PCM_PLAYBACK) - return -ENOTTY; - return 0; -} - -/* recalcuate the boundary within 32bit */ -static void recalculate_boundary(snd_pcm_runtime_t *runtime) -{ - if (! runtime->buffer_size) - return; - runtime->boundary = runtime->buffer_size; - while (runtime->boundary * 2 <= 0x7fffffffUL - runtime->buffer_size) - runtime->boundary *= 2; -} - -/* both for HW_PARAMS and HW_REFINE */ -static int _snd_ioctl32_pcm_hw_params(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl) -{ - struct sndrv_pcm_hw_params32 __user *data32; - struct sndrv_pcm_hw_params *data; - snd_pcm_file_t *pcm_file; - snd_pcm_substream_t *substream; - snd_pcm_runtime_t *runtime; - int err; - - if (sanity_check_pcm(file)) - return -ENOTTY; - if (! (pcm_file = file->private_data)) - return -ENOTTY; - if (! (substream = pcm_file->substream)) - return -ENOTTY; - if (! (runtime = substream->runtime)) - return -ENOTTY; - - data32 = compat_ptr(arg); - data = kmalloc(sizeof(*data), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - if (copy_from_user(data, data32, sizeof(*data32))) { - err = -EFAULT; - goto error; - } - if (native_ctl == SNDRV_PCM_IOCTL_HW_REFINE) - err = snd_pcm_hw_refine(substream, data); - else - err = snd_pcm_hw_params(substream, data); - if (err < 0) - goto error; - if (copy_to_user(data32, data, sizeof(*data32)) || - __put_user((u32)data->fifo_size, &data32->fifo_size)) { - err = -EFAULT; - goto error; - } - - if (native_ctl == SNDRV_PCM_IOCTL_HW_PARAMS) - recalculate_boundary(runtime); - error: - kfree(data); - return err; -} - - -/* - */ -struct sndrv_xferi32 { - s32 result; - u32 buf; - u32 frames; -} __attribute__((packed)); - -static int _snd_ioctl32_xferi(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl) -{ - struct sndrv_xferi32 data32; - struct sndrv_xferi __user *data; - snd_pcm_sframes_t result; - int err; - - if (copy_from_user(&data32, (void __user *)arg, sizeof(data32))) - return -EFAULT; - data = compat_alloc_user_space(sizeof(*data)); - if (put_user((snd_pcm_sframes_t)data32.result, &data->result) || - __put_user(compat_ptr(data32.buf), &data->buf) || - __put_user((snd_pcm_uframes_t)data32.frames, &data->frames)) - return -EFAULT; - err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data); - if (err < 0) - return err; - /* copy the result */ - if (__get_user(result, &data->result)) - return -EFAULT; - data32.result = result; - if (copy_to_user((void __user *)arg, &data32, sizeof(data32))) - return -EFAULT; - return 0; -} - - -/* snd_xfern needs remapping of bufs */ -struct sndrv_xfern32 { - s32 result; - u32 bufs; /* this is void **; */ - u32 frames; -} __attribute__((packed)); - -/* - * xfern ioctl nees to copy (up to) 128 pointers on stack. - * although we may pass the copied pointers through f_op->ioctl, but the ioctl - * handler there expands again the same 128 pointers on stack, so it is better - * to handle the function (calling pcm_readv/writev) directly in this handler. - */ -static int _snd_ioctl32_xfern(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl) -{ - snd_pcm_file_t *pcm_file; - snd_pcm_substream_t *substream; - struct sndrv_xfern32 __user *srcptr = compat_ptr(arg); - struct sndrv_xfern32 data32; - void __user **bufs; - int err = 0, ch, i; - u32 __user *bufptr; - - if (sanity_check_pcm(file)) - return -ENOTTY; - if (! (pcm_file = file->private_data)) - return -ENOTTY; - if (! (substream = pcm_file->substream)) - return -ENOTTY; - if (! substream->runtime) - return -ENOTTY; - - /* check validty of the command */ - switch (native_ctl) { - case SNDRV_PCM_IOCTL_WRITEN_FRAMES: - if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) - return -EINVAL; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) - return -EBADFD; - break; - case SNDRV_PCM_IOCTL_READN_FRAMES: - if (substream->stream != SNDRV_PCM_STREAM_CAPTURE) - return -EINVAL; - break; - } - if ((ch = substream->runtime->channels) > 128) - return -EINVAL; - if (copy_from_user(&data32, (void __user *)arg, sizeof(data32))) - return -EFAULT; - bufptr = compat_ptr(data32.bufs); - bufs = kmalloc(sizeof(void __user *) * ch, GFP_KERNEL); - if (bufs == NULL) - return -ENOMEM; - for (i = 0; i < ch; i++) { - u32 ptr; - if (get_user(ptr, bufptr)) { - kfree(bufs); - return -EFAULT; - } - bufs[ch] = compat_ptr(ptr); - bufptr++; - } - switch (native_ctl) { - case SNDRV_PCM_IOCTL_WRITEN_FRAMES: - err = snd_pcm_lib_writev(substream, bufs, data32.frames); - break; - case SNDRV_PCM_IOCTL_READN_FRAMES: - err = snd_pcm_lib_readv(substream, bufs, data32.frames); - break; - } - if (err >= 0) { - if (put_user(err, &srcptr->result)) - err = -EFAULT; - } - kfree(bufs); - return err; -} - - -struct sndrv_pcm_mmap_status32 { - s32 state; - s32 pad1; - u32 hw_ptr; - struct compat_timespec tstamp; - s32 suspended_state; -} __attribute__((packed)); - -struct sndrv_pcm_mmap_control32 { - u32 appl_ptr; - u32 avail_min; -} __attribute__((packed)); - -struct sndrv_pcm_sync_ptr32 { - u32 flags; - union { - struct sndrv_pcm_mmap_status32 status; - unsigned char reserved[64]; - } s; - union { - struct sndrv_pcm_mmap_control32 control; - unsigned char reserved[64]; - } c; -} __attribute__((packed)); - -#define CVT_sndrv_pcm_sync_ptr()\ -{\ - COPY(flags);\ - COPY(s.status.state);\ - COPY(s.status.pad1);\ - COPY_CVT(s.status.hw_ptr);\ - COPY_CVT(s.status.tstamp.tv_sec);\ - COPY_CVT(s.status.tstamp.tv_nsec);\ - COPY(s.status.suspended_state);\ - COPY_CVT(c.control.appl_ptr);\ - COPY_CVT(c.control.avail_min);\ -} - -DEFINE_ALSA_IOCTL(pcm_sync_ptr); - -/* - */ - -DEFINE_ALSA_IOCTL_ENTRY(pcm_hw_refine, pcm_hw_params, SNDRV_PCM_IOCTL_HW_REFINE); -DEFINE_ALSA_IOCTL_ENTRY(pcm_hw_params, pcm_hw_params, SNDRV_PCM_IOCTL_HW_PARAMS); -DEFINE_ALSA_IOCTL_ENTRY(pcm_sw_params, pcm_sw_params, SNDRV_PCM_IOCTL_SW_PARAMS); -DEFINE_ALSA_IOCTL_ENTRY(pcm_status, pcm_status, SNDRV_PCM_IOCTL_STATUS); -DEFINE_ALSA_IOCTL_ENTRY(pcm_delay, pcm_sframes_str, SNDRV_PCM_IOCTL_DELAY); -DEFINE_ALSA_IOCTL_ENTRY(pcm_channel_info, pcm_channel_info, SNDRV_PCM_IOCTL_CHANNEL_INFO); -DEFINE_ALSA_IOCTL_ENTRY(pcm_rewind, pcm_uframes_str, SNDRV_PCM_IOCTL_REWIND); -DEFINE_ALSA_IOCTL_ENTRY(pcm_readi, xferi, SNDRV_PCM_IOCTL_READI_FRAMES); -DEFINE_ALSA_IOCTL_ENTRY(pcm_writei, xferi, SNDRV_PCM_IOCTL_WRITEI_FRAMES); -DEFINE_ALSA_IOCTL_ENTRY(pcm_readn, xfern, SNDRV_PCM_IOCTL_READN_FRAMES); -DEFINE_ALSA_IOCTL_ENTRY(pcm_writen, xfern, SNDRV_PCM_IOCTL_WRITEN_FRAMES); -DEFINE_ALSA_IOCTL_ENTRY(pcm_sync_ptr, pcm_sync_ptr, SNDRV_PCM_IOCTL_SYNC_PTR); - - -/* - * When PCM is used on 32bit mode, we need to disable - * mmap of PCM status/control records because of the size - * incompatibility. - * - * Since INFO ioctl is always called at first, we mark the - * mmap-disabling in this ioctl wrapper. - */ -static int snd_pcm_info_ioctl32(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *filp) -{ - snd_pcm_file_t *pcm_file; - snd_pcm_substream_t *substream; - if (! filp->f_op || ! filp->f_op->ioctl) - return -ENOTTY; - pcm_file = filp->private_data; - if (! pcm_file) - return -ENOTTY; - substream = pcm_file->substream; - if (! substream) - return -ENOTTY; - substream->no_mmap_ctrl = 1; - return filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg); -} - -/* - */ -#define AP(x) snd_ioctl32_##x - -enum { - SNDRV_PCM_IOCTL_HW_REFINE32 = _IOWR('A', 0x10, struct sndrv_pcm_hw_params32), - SNDRV_PCM_IOCTL_HW_PARAMS32 = _IOWR('A', 0x11, struct sndrv_pcm_hw_params32), - SNDRV_PCM_IOCTL_SW_PARAMS32 = _IOWR('A', 0x13, struct sndrv_pcm_sw_params32), - SNDRV_PCM_IOCTL_STATUS32 = _IOR('A', 0x20, struct sndrv_pcm_status32), - SNDRV_PCM_IOCTL_DELAY32 = _IOR('A', 0x21, s32), - SNDRV_PCM_IOCTL_CHANNEL_INFO32 = _IOR('A', 0x32, struct sndrv_pcm_channel_info32), - SNDRV_PCM_IOCTL_REWIND32 = _IOW('A', 0x46, u32), - SNDRV_PCM_IOCTL_WRITEI_FRAMES32 = _IOW('A', 0x50, struct sndrv_xferi32), - SNDRV_PCM_IOCTL_READI_FRAMES32 = _IOR('A', 0x51, struct sndrv_xferi32), - SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct sndrv_xfern32), - SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct sndrv_xfern32), - SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct sndrv_pcm_sync_ptr32), - -}; - -struct ioctl32_mapper pcm_mappers[] = { - MAP_COMPAT(SNDRV_PCM_IOCTL_PVERSION), - /* MAP_COMPAT(SNDRV_PCM_IOCTL_INFO), */ - { SNDRV_PCM_IOCTL_INFO, snd_pcm_info_ioctl32 }, - MAP_COMPAT(SNDRV_PCM_IOCTL_TSTAMP), - { SNDRV_PCM_IOCTL_HW_REFINE32, AP(pcm_hw_refine) }, - { SNDRV_PCM_IOCTL_HW_PARAMS32, AP(pcm_hw_params) }, - MAP_COMPAT(SNDRV_PCM_IOCTL_HW_FREE), - { SNDRV_PCM_IOCTL_SW_PARAMS32, AP(pcm_sw_params) }, - { SNDRV_PCM_IOCTL_STATUS32, AP(pcm_status) }, - { SNDRV_PCM_IOCTL_DELAY32, AP(pcm_delay) }, - MAP_COMPAT(SNDRV_PCM_IOCTL_HWSYNC), - { SNDRV_PCM_IOCTL_SYNC_PTR32, AP(pcm_sync_ptr) }, - { SNDRV_PCM_IOCTL_CHANNEL_INFO32, AP(pcm_channel_info) }, - MAP_COMPAT(SNDRV_PCM_IOCTL_PREPARE), - MAP_COMPAT(SNDRV_PCM_IOCTL_RESET), - MAP_COMPAT(SNDRV_PCM_IOCTL_START), - MAP_COMPAT(SNDRV_PCM_IOCTL_DROP), - MAP_COMPAT(SNDRV_PCM_IOCTL_DRAIN), - MAP_COMPAT(SNDRV_PCM_IOCTL_PAUSE), - { SNDRV_PCM_IOCTL_REWIND32, AP(pcm_rewind) }, - MAP_COMPAT(SNDRV_PCM_IOCTL_RESUME), - MAP_COMPAT(SNDRV_PCM_IOCTL_XRUN), - { SNDRV_PCM_IOCTL_WRITEI_FRAMES32, AP(pcm_writei) }, - { SNDRV_PCM_IOCTL_READI_FRAMES32, AP(pcm_readi) }, - { SNDRV_PCM_IOCTL_WRITEN_FRAMES32, AP(pcm_writen) }, - { SNDRV_PCM_IOCTL_READN_FRAMES32, AP(pcm_readn) }, - MAP_COMPAT(SNDRV_PCM_IOCTL_LINK), - MAP_COMPAT(SNDRV_PCM_IOCTL_UNLINK), - - { 0 }, -}; diff --git a/sound/core/ioctl32/rawmidi32.c b/sound/core/ioctl32/rawmidi32.c deleted file mode 100644 index c1d894886..000000000 --- a/sound/core/ioctl32/rawmidi32.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 32bit -> 64bit ioctl wrapper for raw MIDI API - * Copyright (c) by Takashi Iwai <tiwai@suse.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 - * - */ - -#include <sound/driver.h> -#include <linux/time.h> -#include <linux/fs.h> -#include <linux/compat.h> -#include <sound/core.h> -#include <sound/rawmidi.h> -#include <asm/uaccess.h> -#include "ioctl32.h" - -struct sndrv_rawmidi_params32 { - s32 stream; - u32 buffer_size; - u32 avail_min; - unsigned int no_active_sensing; /* avoid bit-field */ - unsigned char reserved[16]; -} __attribute__((packed)); - -#define CVT_sndrv_rawmidi_params()\ -{\ - COPY(stream);\ - COPY_CVT(buffer_size);\ - COPY_CVT(avail_min);\ - if (copy_in_user(((size_t __user *)&dst->avail_min + 1),\ - ((size_t __user *)&src->avail_min + 1), 4)) \ - return -EFAULT;\ -} - -struct sndrv_rawmidi_status32 { - s32 stream; - struct compat_timespec tstamp; - u32 avail; - u32 xruns; - unsigned char reserved[16]; -} __attribute__((packed)); - -#define CVT_sndrv_rawmidi_status()\ -{\ - COPY(stream);\ - COPY_CVT(tstamp.tv_sec);\ - COPY_CVT(tstamp.tv_nsec);\ - COPY_CVT(avail);\ - COPY_CVT(xruns);\ -} - -DEFINE_ALSA_IOCTL(rawmidi_params); -DEFINE_ALSA_IOCTL(rawmidi_status); - -DEFINE_ALSA_IOCTL_ENTRY(rawmidi_params, rawmidi_params, SNDRV_RAWMIDI_IOCTL_PARAMS); -DEFINE_ALSA_IOCTL_ENTRY(rawmidi_status, rawmidi_status, SNDRV_RAWMIDI_IOCTL_STATUS); - -#define AP(x) snd_ioctl32_##x - -enum { - SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct sndrv_rawmidi_params32), - SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct sndrv_rawmidi_status32), -}; - -struct ioctl32_mapper rawmidi_mappers[] = { - MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_PVERSION), - MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_INFO), - { SNDRV_RAWMIDI_IOCTL_PARAMS32, AP(rawmidi_params) }, - { SNDRV_RAWMIDI_IOCTL_STATUS32, AP(rawmidi_status) }, - MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_DROP), - MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_DRAIN), - - MAP_COMPAT(SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE), - MAP_COMPAT(SNDRV_CTL_IOCTL_RAWMIDI_INFO), - MAP_COMPAT(SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE), - - { 0 }, -}; diff --git a/sound/core/ioctl32/seq32.c b/sound/core/ioctl32/seq32.c deleted file mode 100644 index c349feaf3..000000000 --- a/sound/core/ioctl32/seq32.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * 32bit -> 64bit ioctl wrapper for sequencer API - * Copyright (c) by Takashi Iwai <tiwai@suse.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 - * - */ - -#include <sound/driver.h> -#include <linux/time.h> -#include <linux/fs.h> -#include <sound/core.h> -#include <sound/timer.h> -#include <asm/uaccess.h> -#include <sound/asequencer.h> -#include "ioctl32.h" - -struct sndrv_seq_port_info32 { - struct sndrv_seq_addr addr; /* client/port numbers */ - char name[64]; /* port name */ - - u32 capability; /* port capability bits */ - u32 type; /* port type bits */ - s32 midi_channels; /* channels per MIDI port */ - s32 midi_voices; /* voices per MIDI port */ - s32 synth_voices; /* voices per SYNTH port */ - - s32 read_use; /* R/O: subscribers for output (from this port) */ - s32 write_use; /* R/O: subscribers for input (to this port) */ - - u32 kernel; /* reserved for kernel use (must be NULL) */ - u32 flags; /* misc. conditioning */ - unsigned char time_queue; /* queue # for timestamping */ - char reserved[59]; /* for future use */ -}; - -#define CVT_sndrv_seq_port_info()\ -{\ - COPY(addr);\ - COPY_ARRAY(name);\ - COPY(capability);\ - COPY(type);\ - COPY(midi_channels);\ - COPY(midi_voices);\ - COPY(synth_voices);\ - COPY(read_use);\ - COPY(write_use);\ - COPY(flags);\ - COPY(time_queue);\ -} - -DEFINE_ALSA_IOCTL(seq_port_info); -DEFINE_ALSA_IOCTL_ENTRY(create_port, seq_port_info, SNDRV_SEQ_IOCTL_CREATE_PORT); -DEFINE_ALSA_IOCTL_ENTRY(delete_port, seq_port_info, SNDRV_SEQ_IOCTL_DELETE_PORT); -DEFINE_ALSA_IOCTL_ENTRY(get_port_info, seq_port_info, SNDRV_SEQ_IOCTL_GET_PORT_INFO); -DEFINE_ALSA_IOCTL_ENTRY(set_port_info, seq_port_info, SNDRV_SEQ_IOCTL_SET_PORT_INFO); -DEFINE_ALSA_IOCTL_ENTRY(query_next_port, seq_port_info, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT); - -/* - */ -#define AP(x) snd_ioctl32_##x - -enum { - SNDRV_SEQ_IOCTL_CREATE_PORT32 = _IOWR('S', 0x20, struct sndrv_seq_port_info32), - SNDRV_SEQ_IOCTL_DELETE_PORT32 = _IOW ('S', 0x21, struct sndrv_seq_port_info32), - SNDRV_SEQ_IOCTL_GET_PORT_INFO32 = _IOWR('S', 0x22, struct sndrv_seq_port_info32), - SNDRV_SEQ_IOCTL_SET_PORT_INFO32 = _IOW ('S', 0x23, struct sndrv_seq_port_info32), - SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32 = _IOWR('S', 0x52, struct sndrv_seq_port_info32), -}; - -struct ioctl32_mapper seq_mappers[] = { - MAP_COMPAT(SNDRV_SEQ_IOCTL_PVERSION), - MAP_COMPAT(SNDRV_SEQ_IOCTL_CLIENT_ID), - MAP_COMPAT(SNDRV_SEQ_IOCTL_SYSTEM_INFO), - MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_CLIENT_INFO), - MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_CLIENT_INFO), - { SNDRV_SEQ_IOCTL_CREATE_PORT32, AP(create_port) }, - { SNDRV_SEQ_IOCTL_DELETE_PORT32, AP(delete_port) }, - { SNDRV_SEQ_IOCTL_GET_PORT_INFO32, AP(get_port_info) }, - { SNDRV_SEQ_IOCTL_SET_PORT_INFO32, AP(set_port_info) }, - MAP_COMPAT(SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT), - MAP_COMPAT(SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT), - MAP_COMPAT(SNDRV_SEQ_IOCTL_CREATE_QUEUE), - MAP_COMPAT(SNDRV_SEQ_IOCTL_DELETE_QUEUE), - MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_INFO), - MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_QUEUE_INFO), - MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE), - MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS), - MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO), - MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO), - MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER), - MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER), - MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT), - MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT), - MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_CLIENT_POOL), - MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_CLIENT_POOL), - MAP_COMPAT(SNDRV_SEQ_IOCTL_REMOVE_EVENTS), - MAP_COMPAT(SNDRV_SEQ_IOCTL_QUERY_SUBS), - MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION), - MAP_COMPAT(SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT), - { SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32, AP(query_next_port) }, - MAP_COMPAT(SNDRV_SEQ_IOCTL_RUNNING_MODE), - { 0 }, -}; diff --git a/sound/core/ioctl32/timer32.c b/sound/core/ioctl32/timer32.c deleted file mode 100644 index 5f1a2d97a..000000000 --- a/sound/core/ioctl32/timer32.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 32bit -> 64bit ioctl wrapper for timer API - * Copyright (c) by Takashi Iwai <tiwai@suse.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 - * - */ - -#include <sound/driver.h> -#include <linux/time.h> -#include <linux/fs.h> -#include <linux/compat.h> -#include <sound/core.h> -#include <sound/timer.h> -#include <asm/uaccess.h> -#include "ioctl32.h" - -struct sndrv_timer_info32 { - u32 flags; - s32 card; - unsigned char id[64]; - unsigned char name[80]; - u32 reserved0; - u32 resolution; - unsigned char reserved[64]; -}; - -#define CVT_sndrv_timer_info()\ -{\ - COPY(flags);\ - COPY(card);\ - COPY_ARRAY(id);\ - COPY_ARRAY(name);\ - COPY_CVT(resolution);\ -} - -struct sndrv_timer_status32 { - struct compat_timespec tstamp; - u32 resolution; - u32 lost; - u32 overrun; - u32 queue; - unsigned char reserved[64]; -}; - -#define CVT_sndrv_timer_status()\ -{\ - COPY_CVT(tstamp.tv_sec);\ - COPY_CVT(tstamp.tv_nsec);\ - COPY(resolution);\ - COPY(lost);\ - COPY(overrun);\ - COPY(queue);\ -} - -DEFINE_ALSA_IOCTL(timer_info); -DEFINE_ALSA_IOCTL(timer_status); - -DEFINE_ALSA_IOCTL_ENTRY(timer_info, timer_info, SNDRV_TIMER_IOCTL_INFO); -DEFINE_ALSA_IOCTL_ENTRY(timer_status, timer_status, SNDRV_TIMER_IOCTL_STATUS); - -/* - */ - -#define AP(x) snd_ioctl32_##x - -enum { - SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct sndrv_timer_info32), - SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct sndrv_timer_status32), -}; - -struct ioctl32_mapper timer_mappers[] = { - MAP_COMPAT(SNDRV_TIMER_IOCTL_PVERSION), - MAP_COMPAT(SNDRV_TIMER_IOCTL_NEXT_DEVICE), - MAP_COMPAT(SNDRV_TIMER_IOCTL_SELECT), - { SNDRV_TIMER_IOCTL_INFO32, AP(timer_info) }, - MAP_COMPAT(SNDRV_TIMER_IOCTL_PARAMS), - { SNDRV_TIMER_IOCTL_STATUS32, AP(timer_status) }, -#if 0 - /* ** FIXME ** - * The following four entries are disabled because they conflict - * with the TCOC* definitions. - * Unfortunately, the current ioctl32 wrapper uses a single - * hash table for all devices. Once when the wrapper is fixed - * with the table based on devices, they'll be back again. - */ - MAP_COMPAT(SNDRV_TIMER_IOCTL_START), - MAP_COMPAT(SNDRV_TIMER_IOCTL_STOP), - MAP_COMPAT(SNDRV_TIMER_IOCTL_CONTINUE), - MAP_COMPAT(SNDRV_TIMER_IOCTL_PAUSE), -#endif - { 0 }, -}; diff --git a/sound/core/memory.c b/sound/core/memory.c index 45d419c96..20860fec9 100644 --- a/sound/core/memory.c +++ b/sound/core/memory.c @@ -50,8 +50,8 @@ static long snd_alloc_kmalloc; static long snd_alloc_vmalloc; static LIST_HEAD(snd_alloc_kmalloc_list); static LIST_HEAD(snd_alloc_vmalloc_list); -static spinlock_t snd_alloc_kmalloc_lock = SPIN_LOCK_UNLOCKED; -static spinlock_t snd_alloc_vmalloc_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(snd_alloc_kmalloc_lock); +static DEFINE_SPINLOCK(snd_alloc_vmalloc_lock); #define KMALLOC_MAGIC 0x87654321 #define VMALLOC_MAGIC 0x87654320 static snd_info_entry_t *snd_memory_info_entry; @@ -89,7 +89,7 @@ void snd_memory_done(void) } } -void *__snd_kmalloc(size_t size, int flags, void *caller) +static void *__snd_kmalloc(size_t size, int flags, void *caller) { unsigned long cpu_flags; struct snd_alloc_track *t; @@ -131,10 +131,8 @@ void snd_hidden_kfree(const void *obj) { unsigned long flags; struct snd_alloc_track *t; - if (obj == NULL) { - snd_printk(KERN_WARNING "null kfree (called from %p)\n", __builtin_return_address(0)); + if (obj == NULL) return; - } t = snd_alloc_track_entry(obj); if (t->magic != KMALLOC_MAGIC) { snd_printk(KERN_WARNING "bad kfree (called from %p)\n", __builtin_return_address(0)); @@ -170,10 +168,8 @@ void *snd_hidden_vmalloc(unsigned long size) void snd_hidden_vfree(void *obj) { struct snd_alloc_track *t; - if (obj == NULL) { - snd_printk(KERN_WARNING "null vfree (called from %p)\n", __builtin_return_address(0)); + if (obj == NULL) return; - } t = snd_alloc_track_entry(obj); if (t->magic != VMALLOC_MAGIC) { snd_printk(KERN_ERR "bad vfree (called from %p)\n", __builtin_return_address(0)); @@ -267,7 +263,7 @@ int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size size_t c = count; if (c > sizeof(buf)) c = sizeof(buf); - memcpy_fromio(buf, src, c); + memcpy_fromio(buf, (void __iomem *)src, c); if (copy_to_user(dst, buf, c)) return -EFAULT; count -= c; diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index e98c08927..77a79f210 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -46,7 +46,7 @@ static int dsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 0}; static int adsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1}; -static int nonblock_open; +static int nonblock_open = 1; MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Abramo Bagnara <abramo@alsa-project.org>"); MODULE_DESCRIPTION("PCM OSS emulation for ALSA."); @@ -77,7 +77,7 @@ static inline void snd_leave_user(mm_segment_t fs) set_fs(fs); } -int snd_pcm_oss_plugin_clear(snd_pcm_substream_t *substream) +static int snd_pcm_oss_plugin_clear(snd_pcm_substream_t *substream) { snd_pcm_runtime_t *runtime = substream->runtime; snd_pcm_plugin_t *plugin, *next; @@ -92,7 +92,7 @@ int snd_pcm_oss_plugin_clear(snd_pcm_substream_t *substream) return 0; } -int snd_pcm_plugin_insert(snd_pcm_plugin_t *plugin) +static int snd_pcm_plugin_insert(snd_pcm_plugin_t *plugin) { snd_pcm_runtime_t *runtime = plugin->plug->runtime; plugin->next = runtime->oss.plugin_first; @@ -513,8 +513,7 @@ static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream) runtime->oss.params = 0; runtime->oss.prepare = 1; - if (runtime->oss.buffer != NULL) - vfree(runtime->oss.buffer); + vfree(runtime->oss.buffer); runtime->oss.buffer = vmalloc(runtime->oss.period_bytes); runtime->oss.buffer_used = 0; if (runtime->dma_area) @@ -524,12 +523,9 @@ static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream) err = 0; failure: - if (sw_params) - kfree(sw_params); - if (params) - kfree(params); - if (sparams) - kfree(sparams); + kfree(sw_params); + kfree(params); + kfree(sparams); return err; } @@ -640,10 +636,10 @@ snd_pcm_sframes_t snd_pcm_oss_write3(snd_pcm_substream_t *substream, const char if (in_kernel) { mm_segment_t fs; fs = snd_enter_user(); - ret = snd_pcm_lib_write(substream, ptr, frames); + ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames); snd_leave_user(fs); } else { - ret = snd_pcm_lib_write(substream, ptr, frames); + ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames); } if (ret != -EPIPE && ret != -ESTRPIPE) break; @@ -683,10 +679,10 @@ snd_pcm_sframes_t snd_pcm_oss_read3(snd_pcm_substream_t *substream, char *ptr, s if (in_kernel) { mm_segment_t fs; fs = snd_enter_user(); - ret = snd_pcm_lib_read(substream, ptr, frames); + ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames); snd_leave_user(fs); } else { - ret = snd_pcm_lib_read(substream, ptr, frames); + ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames); } if (ret == -EPIPE) { if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { @@ -722,10 +718,10 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(snd_pcm_substream_t *substream, void **buf if (in_kernel) { mm_segment_t fs; fs = snd_enter_user(); - ret = snd_pcm_lib_writev(substream, bufs, frames); + ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames); snd_leave_user(fs); } else { - ret = snd_pcm_lib_writev(substream, bufs, frames); + ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames); } if (ret != -EPIPE && ret != -ESTRPIPE) break; @@ -762,10 +758,10 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(snd_pcm_substream_t *substream, void **bufs if (in_kernel) { mm_segment_t fs; fs = snd_enter_user(); - ret = snd_pcm_lib_readv(substream, bufs, frames); + ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames); snd_leave_user(fs); } else { - ret = snd_pcm_lib_readv(substream, bufs, frames); + ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames); } if (ret != -EPIPE && ret != -ESTRPIPE) break; @@ -781,7 +777,7 @@ static ssize_t snd_pcm_oss_write2(snd_pcm_substream_t *substream, const char *bu snd_pcm_plugin_channel_t *channels; size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8; if (!in_kernel) { - if (copy_from_user(runtime->oss.buffer, buf, bytes)) + if (copy_from_user(runtime->oss.buffer, (const char __user *)buf, bytes)) return -EFAULT; buf = runtime->oss.buffer; } @@ -843,7 +839,7 @@ static ssize_t snd_pcm_oss_write1(snd_pcm_substream_t *substream, const char __u return xfer > 0 ? xfer : -EAGAIN; } } else { - tmp = snd_pcm_oss_write2(substream, (char *)buf, runtime->oss.period_bytes, 0); + tmp = snd_pcm_oss_write2(substream, (const char *)buf, runtime->oss.period_bytes, 0); if (tmp <= 0) return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp; runtime->oss.bytes += tmp; @@ -862,7 +858,7 @@ static ssize_t snd_pcm_oss_read2(snd_pcm_substream_t *substream, char *buf, size { snd_pcm_runtime_t *runtime = substream->runtime; snd_pcm_sframes_t frames, frames1; - char *final_dst = buf; + char __user *final_dst = (char __user *)buf; if (runtime->oss.plugin_first) { snd_pcm_plugin_channel_t *channels; size_t oss_frame_bytes = (runtime->oss.plugin_last->dst_width * runtime->oss.plugin_last->dst_format.channels) / 8; @@ -1062,6 +1058,7 @@ static int snd_pcm_oss_sync(snd_pcm_oss_file_t *pcm_oss_file) if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) { size = (runtime->frame_bits * size) / 8; while (size > 0) { + mm_segment_t fs; size_t size1 = size < runtime->oss.period_bytes ? size : runtime->oss.period_bytes; size -= size1; size1 *= 8; @@ -1069,7 +1066,9 @@ static int snd_pcm_oss_sync(snd_pcm_oss_file_t *pcm_oss_file) snd_pcm_format_set_silence(runtime->format, runtime->oss.buffer, size1); - snd_pcm_lib_write(substream, runtime->oss.buffer, size1); + fs = snd_enter_user(); + snd_pcm_lib_write(substream, (void __user *)runtime->oss.buffer, size1); + snd_leave_user(fs); } } else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) { void __user *buffers[runtime->channels]; @@ -1671,8 +1670,7 @@ static void snd_pcm_oss_release_substream(snd_pcm_substream_t *substream) { snd_pcm_runtime_t *runtime; runtime = substream->runtime; - if (runtime->oss.buffer) - vfree(runtime->oss.buffer); + vfree(runtime->oss.buffer); snd_pcm_oss_plugin_clear(substream); substream->oss.file = NULL; substream->oss.oss = 0; @@ -1925,8 +1923,7 @@ static int snd_pcm_oss_release(struct inode *inode, struct file *file) return 0; } -static inline int _snd_pcm_oss_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { snd_pcm_oss_file_t *pcm_oss_file; int __user *p = (int __user *)arg; @@ -2085,16 +2082,12 @@ static inline int _snd_pcm_oss_ioctl(struct inode *inode, struct file *file, return -EINVAL; } -/* FIXME: need to unlock BKL to allow preemption */ -static int snd_pcm_oss_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int err; - unlock_kernel(); - err = _snd_pcm_oss_ioctl(inode, file, cmd, arg); - lock_kernel(); - return err; -} +#ifdef CONFIG_COMPAT +/* all compatible */ +#define snd_pcm_oss_ioctl_compat snd_pcm_oss_ioctl +#else +#define snd_pcm_oss_ioctl_compat NULL +#endif static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t count, loff_t *offset) { @@ -2308,7 +2301,7 @@ static void snd_pcm_oss_proc_write(snd_info_entry_t *entry, snd_info_buffer_t * buffer) { snd_pcm_str_t *pstr = (snd_pcm_str_t *)entry->private_data; - char line[256], str[32], task_name[32], *ptr; + char line[128], str[32], task_name[32], *ptr; int idx1; snd_pcm_oss_setup_t *setup, *setup1, template; @@ -2422,7 +2415,8 @@ static struct file_operations snd_pcm_oss_f_reg = .open = snd_pcm_oss_open, .release = snd_pcm_oss_release, .poll = snd_pcm_oss_poll, - .ioctl = snd_pcm_oss_ioctl, + .unlocked_ioctl = snd_pcm_oss_ioctl, + .compat_ioctl = snd_pcm_oss_ioctl_compat, .mmap = snd_pcm_oss_mmap, }; diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c index 855071fcb..6bb31009f 100644 --- a/sound/core/oss/pcm_plugin.c +++ b/sound/core/oss/pcm_plugin.c @@ -86,8 +86,7 @@ static int snd_pcm_plugin_alloc(snd_pcm_plugin_t *plugin, snd_pcm_uframes_t fram snd_assert((size % 8) == 0, return -ENXIO); size /= 8; if (plugin->buf_frames < frames) { - if (plugin->buf) - vfree(plugin->buf); + vfree(plugin->buf); plugin->buf = vmalloc(size); plugin->buf_frames = frames; } @@ -217,14 +216,10 @@ int snd_pcm_plugin_free(snd_pcm_plugin_t *plugin) return 0; if (plugin->private_free) plugin->private_free(plugin); - if (plugin->buf_channels) - kfree(plugin->buf_channels); - if (plugin->buf) - vfree(plugin->buf); - if (plugin->src_vmask) - kfree(plugin->src_vmask); - if (plugin->dst_vmask) - kfree(plugin->dst_vmask); + kfree(plugin->buf_channels); + vfree(plugin->buf); + kfree(plugin->src_vmask); + kfree(plugin->dst_vmask); kfree(plugin); return 0; } @@ -390,7 +385,7 @@ int snd_pcm_plug_format_plugins(snd_pcm_plug_t *plug, snd_pcm_plugin_format_t srcformat; int src_access, dst_access; snd_pcm_plugin_t *plugin = NULL; - int err, first; + int err; int stream = snd_pcm_plug_stream(plug); int slave_interleaved = (params_channels(slave_params) == 1 || params_access(slave_params) == SNDRV_PCM_ACCESS_RW_INTERLEAVED); @@ -442,7 +437,6 @@ int snd_pcm_plug_format_plugins(snd_pcm_plug_t *plug, tmpformat.format = dstformat.format; else tmpformat.format = SNDRV_PCM_FORMAT_S16; - first = plugin == NULL; switch (srcformat.format) { case SNDRV_PCM_FORMAT_MU_LAW: err = snd_pcm_plugin_build_mulaw(plug, @@ -656,8 +650,8 @@ snd_pcm_sframes_t snd_pcm_plug_client_channels_buf(snd_pcm_plug_t *plug, return count; } -int snd_pcm_plug_playback_channels_mask(snd_pcm_plug_t *plug, - bitset_t *client_vmask) +static int snd_pcm_plug_playback_channels_mask(snd_pcm_plug_t *plug, + bitset_t *client_vmask) { snd_pcm_plugin_t *plugin = snd_pcm_plug_last(plug); if (plugin == NULL) { @@ -687,33 +681,6 @@ int snd_pcm_plug_playback_channels_mask(snd_pcm_plug_t *plug, } } -int snd_pcm_plug_capture_channels_mask(snd_pcm_plug_t *plug, - bitset_t *client_vmask) -{ - snd_pcm_plugin_t *plugin = snd_pcm_plug_first(plug); - if (plugin == NULL) { - return 0; - } else { - int schannels = plugin->src_format.channels; - bitset_t bs[bitset_size(schannels)]; - bitset_t *srcmask = bs; - bitset_t *dstmask; - int err; - bitset_one(srcmask, schannels); - while (1) { - err = plugin->dst_channels_mask(plugin, srcmask, &dstmask); - if (err < 0) - return err; - srcmask = dstmask; - if (plugin->next == NULL) - break; - plugin = plugin->next; - } - bitset_and(client_vmask, srcmask, plugin->dst_format.channels); - return 0; - } -} - static int snd_pcm_plug_playback_disable_useless_channels(snd_pcm_plug_t *plug, snd_pcm_plugin_channel_t *src_channels) { diff --git a/sound/core/oss/route.c b/sound/core/oss/route.c index 4d53bea2e..c955b7dfd 100644 --- a/sound/core/oss/route.c +++ b/sound/core/oss/route.c @@ -46,9 +46,6 @@ typedef void (*route_channel_f)(snd_pcm_plugin_t *plugin, typedef struct { int channel; int as_int; -#if ROUTE_PLUGIN_USE_FLOAT - float as_float; -#endif } ttable_src_t; struct ttable_dst { @@ -59,7 +56,7 @@ struct ttable_dst { }; struct route_private_data { - enum {R_UINT32=0, R_UINT64=1, R_FLOAT=2} sum_type; + enum {R_UINT32=0, R_UINT64=1} sum_type; int get, put; int conv; int src_sample_size; @@ -69,9 +66,6 @@ struct route_private_data { typedef union { u_int32_t as_uint32; u_int64_t as_uint64; -#if ROUTE_PLUGIN_USE_FLOAT - float as_float; -#endif } sum_t; @@ -136,20 +130,13 @@ static void route_to_channel(snd_pcm_plugin_t *plugin, #include "plugin_ops.h" #undef GET_U_LABELS #undef PUT_U32_LABELS - static void *zero_labels[3] = { &&zero_int32, &&zero_int64, -#if ROUTE_PLUGIN_USE_FLOAT - &&zero_float -#endif - }; + static void *zero_labels[2] = { &&zero_int32, &&zero_int64 }; /* sum_type att */ - static void *add_labels[3 * 2] = { &&add_int32_noatt, &&add_int32_att, + static void *add_labels[2 * 2] = { &&add_int32_noatt, &&add_int32_att, &&add_int64_noatt, &&add_int64_att, -#if ROUTE_PLUGIN_USE_FLOAT - &&add_float_noatt, &&add_float_att -#endif }; /* sum_type att shift */ - static void *norm_labels[3 * 2 * 4] = { NULL, + static void *norm_labels[2 * 2 * 4] = { NULL, &&norm_int32_8_noatt, &&norm_int32_16_noatt, &&norm_int32_24_noatt, @@ -165,16 +152,6 @@ static void route_to_channel(snd_pcm_plugin_t *plugin, &&norm_int64_8_att, &&norm_int64_16_att, &&norm_int64_24_att, -#if ROUTE_PLUGIN_USE_FLOAT - &&norm_float_0, - &&norm_float_8, - &&norm_float_16, - &&norm_float_24, - &&norm_float_0, - &&norm_float_8, - &&norm_float_16, - &&norm_float_24, -#endif }; route_t *data = (route_t *)plugin->extra_data; void *zero, *get, *add, *norm, *put_u32; @@ -225,11 +202,6 @@ static void route_to_channel(snd_pcm_plugin_t *plugin, zero_int64: sum.as_uint64 = 0; goto zero_end; -#if ROUTE_PLUGIN_USE_FLOAT - zero_float: - sum.as_float = 0.0; - goto zero_end; -#endif zero_end: for (srcidx = 0; srcidx < nsrcs; ++srcidx) { char *src = srcs[srcidx]; @@ -257,15 +229,6 @@ static void route_to_channel(snd_pcm_plugin_t *plugin, if (ttp->as_int) sum.as_uint64 += sample; goto after_sum; -#if ROUTE_PLUGIN_USE_FLOAT - add_float_att: - sum.as_float += sample * ttp->as_float; - goto after_sum; - add_float_noatt: - if (ttp->as_int) - sum.as_float += sample; - goto after_sum; -#endif after_sum: srcs[srcidx] += src_steps[srcidx]; ttp++; @@ -321,25 +284,6 @@ static void route_to_channel(snd_pcm_plugin_t *plugin, sample = sum.as_uint64; goto after_norm; -#if ROUTE_PLUGIN_USE_FLOAT - norm_float_8: - sum.as_float *= 1 << 8; - goto norm_float; - norm_float_16: - sum.as_float *= 1 << 16; - goto norm_float; - norm_float_24: - sum.as_float *= 1 << 24; - goto norm_float; - norm_float_0: - norm_float: - sum.as_float = floor(sum.as_float + 0.5); - if (sum.as_float > (u_int32_t)0xffffffff) - sample = (u_int32_t)0xffffffff; - else - sample = sum.as_float; - goto after_norm; -#endif after_norm: /* Put sample */ @@ -353,9 +297,9 @@ static void route_to_channel(snd_pcm_plugin_t *plugin, } } -int route_src_channels_mask(snd_pcm_plugin_t *plugin, - bitset_t *dst_vmask, - bitset_t **src_vmask) +static int route_src_channels_mask(snd_pcm_plugin_t *plugin, + bitset_t *dst_vmask, + bitset_t **src_vmask) { route_t *data = (route_t *)plugin->extra_data; int schannels = plugin->src_format.channels; @@ -377,9 +321,9 @@ int route_src_channels_mask(snd_pcm_plugin_t *plugin, return 0; } -int route_dst_channels_mask(snd_pcm_plugin_t *plugin, - bitset_t *src_vmask, - bitset_t **dst_vmask) +static int route_dst_channels_mask(snd_pcm_plugin_t *plugin, + bitset_t *src_vmask, + bitset_t **dst_vmask) { route_t *data = (route_t *)plugin->extra_data; int dchannels = plugin->dst_format.channels; @@ -407,8 +351,7 @@ static void route_free(snd_pcm_plugin_t *plugin) route_t *data = (route_t *)plugin->extra_data; unsigned int dst_channel; for (dst_channel = 0; dst_channel < plugin->dst_format.channels; ++dst_channel) { - if (data->ttable[dst_channel].srcs != NULL) - kfree(data->ttable[dst_channel].srcs); + kfree(data->ttable[dst_channel].srcs); } } @@ -434,13 +377,7 @@ static int route_load_ttable(snd_pcm_plugin_t *plugin, snd_assert(*sptr >= 0 || *sptr <= FULL, return -ENXIO); if (*sptr != 0) { srcs[nsrcs].channel = src_channel; -#if ROUTE_PLUGIN_USE_FLOAT - /* Also in user space for non attenuated */ - srcs[nsrcs].as_int = (*sptr == FULL ? ROUTE_PLUGIN_RESOLUTION : 0); - srcs[nsrcs].as_float = *sptr; -#else srcs[nsrcs].as_int = *sptr; -#endif if (*sptr != FULL) att = 1; t += *sptr; @@ -559,17 +496,15 @@ int snd_pcm_plugin_build_route(snd_pcm_plug_t *plug, data = (route_t *) plugin->extra_data; data->get = getput_index(src_format->format); + snd_assert(data->get >= 0 && data->get < 4*2*2, return -EINVAL); data->put = getput_index(dst_format->format); + snd_assert(data->get >= 0 && data->get < 4*2*2, return -EINVAL); data->conv = conv_index(src_format->format, dst_format->format); -#if ROUTE_PLUGIN_USE_FLOAT - data->sum_type = R_FLOAT; -#else if (snd_pcm_format_width(src_format->format) == 32) data->sum_type = R_UINT64; else data->sum_type = R_UINT32; -#endif data->src_sample_size = snd_pcm_format_width(src_format->format) / 8; if ((err = route_load_ttable(plugin, ttable)) < 0) { diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 4d0b0f719..151fd99ca 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -371,7 +371,7 @@ static inline unsigned int muldiv32(unsigned int a, unsigned int b, return n; } -int snd_interval_refine_min(snd_interval_t *i, unsigned int min, int openmin) +static int snd_interval_refine_min(snd_interval_t *i, unsigned int min, int openmin) { int changed = 0; assert(!snd_interval_empty(i)); @@ -396,7 +396,7 @@ int snd_interval_refine_min(snd_interval_t *i, unsigned int min, int openmin) return changed; } -int snd_interval_refine_max(snd_interval_t *i, unsigned int max, int openmax) +static int snd_interval_refine_max(snd_interval_t *i, unsigned int max, int openmax) { int changed = 0; assert(!snd_interval_empty(i)); @@ -474,7 +474,7 @@ int snd_interval_refine(snd_interval_t *i, const snd_interval_t *v) return changed; } -int snd_interval_refine_first(snd_interval_t *i) +static int snd_interval_refine_first(snd_interval_t *i) { assert(!snd_interval_empty(i)); if (snd_interval_single(i)) @@ -486,7 +486,7 @@ int snd_interval_refine_first(snd_interval_t *i) return 1; } -int snd_interval_refine_last(snd_interval_t *i) +static int snd_interval_refine_last(snd_interval_t *i) { assert(!snd_interval_empty(i)); if (snd_interval_single(i)) @@ -498,7 +498,7 @@ int snd_interval_refine_last(snd_interval_t *i) return 1; } -int snd_interval_refine_set(snd_interval_t *i, unsigned int val) +static int snd_interval_refine_set(snd_interval_t *i, unsigned int val) { snd_interval_t t; t.empty = 0; @@ -718,9 +718,9 @@ int snd_interval_ratnum(snd_interval_t *i, * * Returns non-zero if the value is changed, zero if not changed. */ -int snd_interval_ratden(snd_interval_t *i, - unsigned int rats_count, ratden_t *rats, - unsigned int *nump, unsigned int *denp) +static int snd_interval_ratden(snd_interval_t *i, + unsigned int rats_count, ratden_t *rats, + unsigned int *nump, unsigned int *denp) { unsigned int best_num, best_diff, best_den; unsigned int k; @@ -858,7 +858,7 @@ int snd_interval_list(snd_interval_t *i, unsigned int count, unsigned int *list, return changed; } -int snd_interval_step(snd_interval_t *i, unsigned int min, unsigned int step) +static int snd_interval_step(snd_interval_t *i, unsigned int min, unsigned int step) { unsigned int n; int changed = 0; @@ -1856,80 +1856,6 @@ int snd_pcm_lib_ioctl(snd_pcm_substream_t *substream, * Conditions */ -/** - * snd_pcm_playback_ready - check whether the playback buffer is available - * @substream: the pcm substream instance - * - * Checks whether enough free space is available on the playback buffer. - * - * Returns non-zero if available, or zero if not. - */ -int snd_pcm_playback_ready(snd_pcm_substream_t *substream) -{ - snd_pcm_runtime_t *runtime = substream->runtime; - return snd_pcm_playback_avail(runtime) >= runtime->control->avail_min; -} - -/** - * snd_pcm_capture_ready - check whether the capture buffer is available - * @substream: the pcm substream instance - * - * Checks whether enough capture data is available on the capture buffer. - * - * Returns non-zero if available, or zero if not. - */ -int snd_pcm_capture_ready(snd_pcm_substream_t *substream) -{ - snd_pcm_runtime_t *runtime = substream->runtime; - return snd_pcm_capture_avail(runtime) >= runtime->control->avail_min; -} - -/** - * snd_pcm_playback_data - check whether any data exists on the playback buffer - * @substream: the pcm substream instance - * - * Checks whether any data exists on the playback buffer. If stop_threshold - * is bigger or equal to boundary, then this function returns always non-zero. - * - * Returns non-zero if exists, or zero if not. - */ -int snd_pcm_playback_data(snd_pcm_substream_t *substream) -{ - snd_pcm_runtime_t *runtime = substream->runtime; - - if (runtime->stop_threshold >= runtime->boundary) - return 1; - return snd_pcm_playback_avail(runtime) < runtime->buffer_size; -} - -/** - * snd_pcm_playback_empty - check whether the playback buffer is empty - * @substream: the pcm substream instance - * - * Checks whether the playback buffer is empty. - * - * Returns non-zero if empty, or zero if not. - */ -int snd_pcm_playback_empty(snd_pcm_substream_t *substream) -{ - snd_pcm_runtime_t *runtime = substream->runtime; - return snd_pcm_playback_avail(runtime) >= runtime->buffer_size; -} - -/** - * snd_pcm_capture_empty - check whether the capture buffer is empty - * @substream: the pcm substream instance - * - * Checks whether the capture buffer is empty. - * - * Returns non-zero if empty, or zero if not. - */ -int snd_pcm_capture_empty(snd_pcm_substream_t *substream) -{ - snd_pcm_runtime_t *runtime = substream->runtime; - return snd_pcm_capture_avail(runtime) == 0; -} - static void snd_pcm_system_tick_set(snd_pcm_substream_t *substream, unsigned long ticks) { @@ -1937,9 +1863,8 @@ static void snd_pcm_system_tick_set(snd_pcm_substream_t *substream, if (ticks == 0) del_timer(&runtime->tick_timer); else { + ticks += (1000000 / HZ) - 1; ticks /= (1000000 / HZ); - if (ticks % (1000000 / HZ)) - ticks++; mod_timer(&runtime->tick_timer, jiffies + ticks); } } @@ -2216,11 +2141,9 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream, break; } appl_ptr += frames; - if (appl_ptr >= runtime->boundary) { - runtime->control->appl_ptr = 0; - } else { - runtime->control->appl_ptr = appl_ptr; - } + if (appl_ptr >= runtime->boundary) + appl_ptr -= runtime->boundary; + runtime->control->appl_ptr = appl_ptr; if (substream->ops->ack) substream->ops->ack(substream); @@ -2515,11 +2438,9 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(snd_pcm_substream_t *substream, break; } appl_ptr += frames; - if (appl_ptr >= runtime->boundary) { - runtime->control->appl_ptr = 0; - } else { - runtime->control->appl_ptr = appl_ptr; - } + if (appl_ptr >= runtime->boundary) + appl_ptr -= runtime->boundary; + runtime->control->appl_ptr = appl_ptr; if (substream->ops->ack) substream->ops->ack(substream); @@ -2643,7 +2564,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_ratden); EXPORT_SYMBOL(snd_interval_muldivk); EXPORT_SYMBOL(snd_interval_mulkdiv); EXPORT_SYMBOL(snd_interval_div); @@ -2675,10 +2595,6 @@ EXPORT_SYMBOL(snd_pcm_hw_rule_add); EXPORT_SYMBOL(snd_pcm_set_ops); EXPORT_SYMBOL(snd_pcm_set_sync); EXPORT_SYMBOL(snd_pcm_lib_ioctl); -EXPORT_SYMBOL(snd_pcm_playback_ready); -EXPORT_SYMBOL(snd_pcm_capture_ready); -EXPORT_SYMBOL(snd_pcm_playback_data); -EXPORT_SYMBOL(snd_pcm_capture_empty); EXPORT_SYMBOL(snd_pcm_stop); EXPORT_SYMBOL(snd_pcm_period_elapsed); EXPORT_SYMBOL(snd_pcm_lib_write); @@ -2688,7 +2604,6 @@ EXPORT_SYMBOL(snd_pcm_lib_readv); EXPORT_SYMBOL(snd_pcm_lib_buffer_bytes); EXPORT_SYMBOL(snd_pcm_lib_period_bytes); /* pcm_memory.c */ -EXPORT_SYMBOL(snd_pcm_lib_preallocate_free); EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all); EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages); EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all); diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c index 16a81240a..f1d5f7a6e 100644 --- a/sound/core/pcm_memory.c +++ b/sound/core/pcm_memory.c @@ -37,7 +37,7 @@ static int maximum_substreams = 4; module_param(maximum_substreams, int, 0444); MODULE_PARM_DESC(maximum_substreams, "Maximum substreams with preallocated DMA memory."); -const static size_t snd_minimum_buffer = 16384; +static const size_t snd_minimum_buffer = 16384; /* @@ -291,7 +291,7 @@ struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned lon * @substream: the substream to allocate the DMA buffer to * @size: the requested buffer size in bytes * - * Allocates the DMA buffer on the BUS type given by + * Allocates the DMA buffer on the BUS type given earlier to * snd_pcm_lib_preallocate_xxx_pages(). * * Returns 1 if the buffer is changed, 0 if not changed, or a negative diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 366e00fac..cad9bbde9 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -65,7 +65,7 @@ static int snd_pcm_hw_params_old_user(snd_pcm_substream_t * substream, struct sn * */ -rwlock_t snd_pcm_link_rwlock = RW_LOCK_UNLOCKED; +DEFINE_RWLOCK(snd_pcm_link_rwlock); static DECLARE_RWSEM(snd_pcm_link_rwsem); @@ -113,10 +113,18 @@ int snd_pcm_info(snd_pcm_substream_t * substream, snd_pcm_info_t *info) int snd_pcm_info_user(snd_pcm_substream_t * substream, snd_pcm_info_t __user * _info) { - snd_pcm_info_t info; - int err = snd_pcm_info(substream, &info); - if (copy_to_user(_info, &info, sizeof(info))) - return -EFAULT; + snd_pcm_info_t *info; + int err; + + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (! info) + return -ENOMEM; + err = snd_pcm_info(substream, info); + if (err >= 0) { + if (copy_to_user(_info, info, sizeof(*info))) + err = -EFAULT; + } + kfree(info); return err; } @@ -602,17 +610,13 @@ static int snd_pcm_status_user(snd_pcm_substream_t * substream, snd_pcm_status_t return 0; } -static int snd_pcm_channel_info(snd_pcm_substream_t * substream, snd_pcm_channel_info_t __user * _info) +static int snd_pcm_channel_info(snd_pcm_substream_t * substream, snd_pcm_channel_info_t * info) { - snd_pcm_channel_info_t info; snd_pcm_runtime_t *runtime; - int res; unsigned int channel; snd_assert(substream != NULL, return -ENXIO); - if (copy_from_user(&info, _info, sizeof(info))) - return -EFAULT; - channel = info.channel; + channel = info->channel; runtime = substream->runtime; snd_pcm_stream_lock_irq(substream); if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { @@ -622,9 +626,19 @@ static int snd_pcm_channel_info(snd_pcm_substream_t * substream, snd_pcm_channel snd_pcm_stream_unlock_irq(substream); if (channel >= runtime->channels) return -EINVAL; - memset(&info, 0, sizeof(info)); - info.channel = channel; - res = substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_CHANNEL_INFO, &info); + memset(info, 0, sizeof(*info)); + info->channel = channel; + return substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_CHANNEL_INFO, info); +} + +static int snd_pcm_channel_info_user(snd_pcm_substream_t * substream, snd_pcm_channel_info_t __user * _info) +{ + snd_pcm_channel_info_t info; + int res; + + if (copy_from_user(&info, _info, sizeof(info))) + return -EFAULT; + res = snd_pcm_channel_info(substream, &info); if (res < 0) return res; if (copy_to_user(_info, &info, sizeof(info))) @@ -1032,7 +1046,13 @@ static struct action_ops snd_pcm_action_suspend = { */ int snd_pcm_suspend(snd_pcm_substream_t *substream) { - return snd_pcm_action(&snd_pcm_action_suspend, substream, 0); + int err; + unsigned long flags; + + snd_pcm_stream_lock_irqsave(substream, flags); + err = snd_pcm_action(&snd_pcm_action_suspend, substream, 0); + snd_pcm_stream_unlock_irqrestore(substream, flags); + return err; } /** @@ -1051,11 +1071,8 @@ int snd_pcm_suspend_all(snd_pcm_t *pcm) /* FIXME: the open/close code should lock this as well */ if (substream->runtime == NULL) continue; - snd_pcm_stream_lock(substream); - if (substream->runtime->status->state != SNDRV_PCM_STATE_SUSPENDED) - err = snd_pcm_suspend(substream); - snd_pcm_stream_unlock(substream); - if (err < 0) + err = snd_pcm_suspend(substream); + if (err < 0 && err != -EBUSY) return err; } } @@ -1445,7 +1462,7 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream) _end: snd_pcm_stream_unlock_irq(substream); - if (drec && drec != &drec_tmp) + if (drec != &drec_tmp) kfree(drec); _unlock: snd_power_unlock(card); @@ -2020,7 +2037,7 @@ static int snd_pcm_open_file(struct file *file, return 0; } -int snd_pcm_open(struct inode *inode, struct file *file) +static int snd_pcm_open(struct inode *inode, struct file *file) { int cardnum = SNDRV_MINOR_CARD(iminor(inode)); int device = SNDRV_MINOR_DEVICE(iminor(inode)); @@ -2079,7 +2096,7 @@ int snd_pcm_open(struct inode *inode, struct file *file) return err; } -int snd_pcm_release(struct inode *inode, struct file *file) +static int snd_pcm_release(struct inode *inode, struct file *file) { snd_pcm_t *pcm; snd_pcm_substream_t *substream; @@ -2101,7 +2118,7 @@ int snd_pcm_release(struct inode *inode, struct file *file) return 0; } -snd_pcm_sframes_t snd_pcm_playback_rewind(snd_pcm_substream_t *substream, snd_pcm_uframes_t frames) +static snd_pcm_sframes_t snd_pcm_playback_rewind(snd_pcm_substream_t *substream, snd_pcm_uframes_t frames) { snd_pcm_runtime_t *runtime = substream->runtime; snd_pcm_sframes_t appl_ptr; @@ -2150,7 +2167,7 @@ snd_pcm_sframes_t snd_pcm_playback_rewind(snd_pcm_substream_t *substream, snd_pc return ret; } -snd_pcm_sframes_t snd_pcm_capture_rewind(snd_pcm_substream_t *substream, snd_pcm_uframes_t frames) +static snd_pcm_sframes_t snd_pcm_capture_rewind(snd_pcm_substream_t *substream, snd_pcm_uframes_t frames) { snd_pcm_runtime_t *runtime = substream->runtime; snd_pcm_sframes_t appl_ptr; @@ -2199,7 +2216,7 @@ snd_pcm_sframes_t snd_pcm_capture_rewind(snd_pcm_substream_t *substream, snd_pcm return ret; } -snd_pcm_sframes_t snd_pcm_playback_forward(snd_pcm_substream_t *substream, snd_pcm_uframes_t frames) +static snd_pcm_sframes_t snd_pcm_playback_forward(snd_pcm_substream_t *substream, snd_pcm_uframes_t frames) { snd_pcm_runtime_t *runtime = substream->runtime; snd_pcm_sframes_t appl_ptr; @@ -2249,7 +2266,7 @@ snd_pcm_sframes_t snd_pcm_playback_forward(snd_pcm_substream_t *substream, snd_p return ret; } -snd_pcm_sframes_t snd_pcm_capture_forward(snd_pcm_substream_t *substream, snd_pcm_uframes_t frames) +static snd_pcm_sframes_t snd_pcm_capture_forward(snd_pcm_substream_t *substream, snd_pcm_uframes_t frames) { snd_pcm_runtime_t *runtime = substream->runtime; snd_pcm_sframes_t appl_ptr; @@ -2440,7 +2457,7 @@ static int snd_pcm_common_ioctl1(snd_pcm_substream_t *substream, case SNDRV_PCM_IOCTL_STATUS: return snd_pcm_status_user(substream, arg); case SNDRV_PCM_IOCTL_CHANNEL_INFO: - return snd_pcm_channel_info(substream, arg); + return snd_pcm_channel_info_user(substream, arg); case SNDRV_PCM_IOCTL_PREPARE: return snd_pcm_prepare(substream); case SNDRV_PCM_IOCTL_RESET: @@ -2640,40 +2657,28 @@ static int snd_pcm_capture_ioctl1(snd_pcm_substream_t *substream, return snd_pcm_common_ioctl1(substream, cmd, arg); } -static int snd_pcm_playback_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { snd_pcm_file_t *pcm_file; - int err; pcm_file = file->private_data; if (((cmd >> 8) & 0xff) != 'A') return -ENOTTY; - /* FIXME: need to unlock BKL to allow preemption */ - unlock_kernel(); - err = snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg); - lock_kernel(); - return err; + return snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg); } -static int snd_pcm_capture_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { snd_pcm_file_t *pcm_file; - int err; pcm_file = file->private_data; if (((cmd >> 8) & 0xff) != 'A') return -ENOTTY; - /* FIXME: need to unlock BKL to allow preemption */ - unlock_kernel(); - err = snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg); - lock_kernel(); - return err; + return snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg); } int snd_pcm_kernel_playback_ioctl(snd_pcm_substream_t *substream, @@ -2683,7 +2688,7 @@ int snd_pcm_kernel_playback_ioctl(snd_pcm_substream_t *substream, int result; fs = snd_enter_user(); - result = snd_pcm_playback_ioctl1(substream, cmd, arg); + result = snd_pcm_playback_ioctl1(substream, cmd, (void __user *)arg); snd_leave_user(fs); return result; } @@ -2695,7 +2700,7 @@ int snd_pcm_kernel_capture_ioctl(snd_pcm_substream_t *substream, int result; fs = snd_enter_user(); - result = snd_pcm_capture_ioctl1(substream, cmd, arg); + result = snd_pcm_capture_ioctl1(substream, cmd, (void __user *)arg); snd_leave_user(fs); return result; } @@ -2835,7 +2840,7 @@ static ssize_t snd_pcm_writev(struct file *file, const struct iovec *_vector, return result; } -unsigned int snd_pcm_playback_poll(struct file *file, poll_table * wait) +static unsigned int snd_pcm_playback_poll(struct file *file, poll_table * wait) { snd_pcm_file_t *pcm_file; snd_pcm_substream_t *substream; @@ -2873,7 +2878,7 @@ unsigned int snd_pcm_playback_poll(struct file *file, poll_table * wait) return mask; } -unsigned int snd_pcm_capture_poll(struct file *file, poll_table * wait) +static unsigned int snd_pcm_capture_poll(struct file *file, poll_table * wait) { snd_pcm_file_t *pcm_file; snd_pcm_substream_t *substream; @@ -3103,8 +3108,8 @@ int snd_pcm_lib_mmap_iomem(snd_pcm_substream_t *substream, struct vm_area_struct area->vm_flags |= VM_IO; size = area->vm_end - area->vm_start; offset = area->vm_pgoff << PAGE_SHIFT; - if (io_remap_page_range(area, area->vm_start, - substream->runtime->dma_addr + offset, + if (io_remap_pfn_range(area, area->vm_start, + (substream->runtime->dma_addr + offset) >> PAGE_SHIFT, size, area->vm_page_prot)) return -EAGAIN; atomic_inc(&substream->runtime->mmap_count); @@ -3197,6 +3202,15 @@ static int snd_pcm_fasync(int fd, struct file * file, int on) return 0; } +/* + * ioctl32 compat + */ +#ifdef CONFIG_COMPAT +#include "pcm_compat.c" +#else +#define snd_pcm_ioctl_compat NULL +#endif + /* * To be removed helpers to keep binary compatibility */ @@ -3318,7 +3332,8 @@ static struct file_operations snd_pcm_f_ops_playback = { .open = snd_pcm_open, .release = snd_pcm_release, .poll = snd_pcm_playback_poll, - .ioctl = snd_pcm_playback_ioctl, + .unlocked_ioctl = snd_pcm_playback_ioctl, + .compat_ioctl = snd_pcm_ioctl_compat, .mmap = snd_pcm_mmap, .fasync = snd_pcm_fasync, }; @@ -3330,7 +3345,8 @@ static struct file_operations snd_pcm_f_ops_capture = { .open = snd_pcm_open, .release = snd_pcm_release, .poll = snd_pcm_capture_poll, - .ioctl = snd_pcm_capture_ioctl, + .unlocked_ioctl = snd_pcm_capture_ioctl, + .compat_ioctl = snd_pcm_ioctl_compat, .mmap = snd_pcm_mmap, .fasync = snd_pcm_fasync, }; diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 6c7609329..edba41182 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -29,6 +29,8 @@ #include <linux/time.h> #include <linux/wait.h> #include <linux/moduleparam.h> +#include <linux/delay.h> +#include <linux/wait.h> #include <sound/rawmidi.h> #include <sound/info.h> #include <sound/control.h> @@ -54,7 +56,7 @@ static int snd_rawmidi_dev_register(snd_device_t *device); static int snd_rawmidi_dev_disconnect(snd_device_t *device); static int snd_rawmidi_dev_unregister(snd_device_t *device); -snd_rawmidi_t *snd_rawmidi_devices[SNDRV_CARDS * SNDRV_RAWMIDI_DEVICES]; +static snd_rawmidi_t *snd_rawmidi_devices[SNDRV_CARDS * SNDRV_RAWMIDI_DEVICES]; static DECLARE_MUTEX(register_mutex); @@ -83,11 +85,34 @@ static inline int snd_rawmidi_ready_append(snd_rawmidi_substream_t * substream, (!substream->append || runtime->avail >= count); } -static int snd_rawmidi_init(snd_rawmidi_substream_t *substream) +static void snd_rawmidi_input_event_tasklet(unsigned long data) { - snd_rawmidi_runtime_t *runtime = substream->runtime; + snd_rawmidi_substream_t *substream = (snd_rawmidi_substream_t *)data; + substream->runtime->event(substream); +} + +static void snd_rawmidi_output_trigger_tasklet(unsigned long data) +{ + snd_rawmidi_substream_t *substream = (snd_rawmidi_substream_t *)data; + substream->ops->trigger(substream, 1); +} + +static int snd_rawmidi_runtime_create(snd_rawmidi_substream_t * substream) +{ + snd_rawmidi_runtime_t *runtime; + + if ((runtime = kcalloc(1, sizeof(*runtime), GFP_KERNEL)) == NULL) + return -ENOMEM; spin_lock_init(&runtime->lock); init_waitqueue_head(&runtime->sleep); + if (substream->stream == SNDRV_RAWMIDI_STREAM_INPUT) + tasklet_init(&runtime->tasklet, + snd_rawmidi_input_event_tasklet, + (unsigned long)substream); + else + tasklet_init(&runtime->tasklet, + snd_rawmidi_output_trigger_tasklet, + (unsigned long)substream); runtime->event = NULL; runtime->buffer_size = PAGE_SIZE; runtime->avail_min = 1; @@ -95,32 +120,53 @@ static int snd_rawmidi_init(snd_rawmidi_substream_t *substream) runtime->avail = 0; else runtime->avail = runtime->buffer_size; - if ((runtime->buffer = kmalloc(runtime->buffer_size, GFP_KERNEL)) == NULL) + if ((runtime->buffer = kmalloc(runtime->buffer_size, GFP_KERNEL)) == NULL) { + kfree(runtime); return -ENOMEM; + } runtime->appl_ptr = runtime->hw_ptr = 0; + substream->runtime = runtime; return 0; } -static int snd_rawmidi_done_buffer(snd_rawmidi_runtime_t *runtime) +static int snd_rawmidi_runtime_free(snd_rawmidi_substream_t * substream) { - if (runtime->buffer) { - kfree(runtime->buffer); - runtime->buffer = NULL; - } + snd_rawmidi_runtime_t *runtime = substream->runtime; + + kfree(runtime->buffer); + kfree(runtime); + substream->runtime = NULL; return 0; } +static inline void snd_rawmidi_output_trigger(snd_rawmidi_substream_t * substream, int up) +{ + if (up) { + tasklet_hi_schedule(&substream->runtime->tasklet); + } else { + tasklet_kill(&substream->runtime->tasklet); + substream->ops->trigger(substream, 0); + } +} + +static void snd_rawmidi_input_trigger(snd_rawmidi_substream_t * substream, int up) +{ + substream->ops->trigger(substream, up); + if (!up && substream->runtime->event) + tasklet_kill(&substream->runtime->tasklet); +} + int snd_rawmidi_drop_output(snd_rawmidi_substream_t * substream) { + unsigned long flags; snd_rawmidi_runtime_t *runtime = substream->runtime; - substream->ops->trigger(substream, 0); - runtime->trigger = 0; + snd_rawmidi_output_trigger(substream, 0); runtime->drain = 0; - /* interrupts are not enabled at this moment, - so spinlock is not required */ + spin_lock_irqsave(&runtime->lock, flags); runtime->appl_ptr = runtime->hw_ptr = 0; runtime->avail = runtime->buffer_size; + spin_unlock_irqrestore(&runtime->lock, flags); return 0; } @@ -132,27 +178,22 @@ int snd_rawmidi_drain_output(snd_rawmidi_substream_t * substream) err = 0; runtime->drain = 1; - while (runtime->avail < runtime->buffer_size) { - timeout = interruptible_sleep_on_timeout(&runtime->sleep, 10 * HZ); - if (signal_pending(current)) { - err = -ERESTARTSYS; - break; - } - if (runtime->avail < runtime->buffer_size && !timeout) { - snd_printk(KERN_WARNING "rawmidi drain error (avail = %li, buffer_size = %li)\n", (long)runtime->avail, (long)runtime->buffer_size); - err = -EIO; - break; - } + timeout = wait_event_interruptible_timeout(runtime->sleep, + (runtime->avail >= runtime->buffer_size), + 10*HZ); + if (signal_pending(current)) + err = -ERESTARTSYS; + if (runtime->avail < runtime->buffer_size && !timeout) { + snd_printk(KERN_WARNING "rawmidi drain error (avail = %li, buffer_size = %li)\n", (long)runtime->avail, (long)runtime->buffer_size); + err = -EIO; } runtime->drain = 0; if (err != -ERESTARTSYS) { /* we need wait a while to make sure that Tx FIFOs are empty */ if (substream->ops->drain) substream->ops->drain(substream); - else { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ / 20); - } + else + msleep(50); snd_rawmidi_drop_output(substream); } return err; @@ -160,14 +201,15 @@ int snd_rawmidi_drain_output(snd_rawmidi_substream_t * substream) int snd_rawmidi_drain_input(snd_rawmidi_substream_t * substream) { + unsigned long flags; snd_rawmidi_runtime_t *runtime = substream->runtime; - substream->ops->trigger(substream, 0); - runtime->trigger = 0; + snd_rawmidi_input_trigger(substream, 0); runtime->drain = 0; - /* interrupts aren't enabled at this moment, so spinlock isn't needed */ + spin_lock_irqsave(&runtime->lock, flags); runtime->appl_ptr = runtime->hw_ptr = 0; runtime->avail = 0; + spin_unlock_irqrestore(&runtime->lock, flags); return 0; } @@ -176,7 +218,7 @@ int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice, { snd_rawmidi_t *rmidi; struct list_head *list1, *list2; - snd_rawmidi_substream_t *sinput, *soutput; + snd_rawmidi_substream_t *sinput = NULL, *soutput = NULL; snd_rawmidi_runtime_t *input = NULL, *output = NULL; int err; @@ -267,20 +309,11 @@ int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice, list2 = list2->next; } if (mode & SNDRV_RAWMIDI_LFLG_INPUT) { - input = kcalloc(1, sizeof(*input), GFP_KERNEL); - if (input == NULL) { - err = -ENOMEM; - goto __error; - } - sinput->runtime = input; - if (snd_rawmidi_init(sinput) < 0) { - err = -ENOMEM; + if ((err = snd_rawmidi_runtime_create(sinput)) < 0) goto __error; - } - if ((err = sinput->ops->open(sinput)) < 0) { - sinput->runtime = NULL; + input = sinput->runtime; + if ((err = sinput->ops->open(sinput)) < 0) goto __error; - } sinput->opened = 1; rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_opened++; } else { @@ -289,26 +322,15 @@ int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice, if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) { if (soutput->opened) goto __skip_output; - output = kcalloc(1, sizeof(*output), GFP_KERNEL); - if (output == NULL) { - err = -ENOMEM; - goto __error; - } - soutput->runtime = output; - if (snd_rawmidi_init(soutput) < 0) { - if (mode & SNDRV_RAWMIDI_LFLG_INPUT) { + if ((err = snd_rawmidi_runtime_create(soutput)) < 0) { + if (mode & SNDRV_RAWMIDI_LFLG_INPUT) sinput->ops->close(sinput); - sinput->runtime = NULL; - } - err = -ENOMEM; goto __error; } + output = soutput->runtime; if ((err = soutput->ops->open(soutput)) < 0) { - if (mode & SNDRV_RAWMIDI_LFLG_INPUT) { + if (mode & SNDRV_RAWMIDI_LFLG_INPUT) sinput->ops->close(sinput); - sinput->runtime = NULL; - } - soutput->runtime = NULL; goto __error; } __skip_output: @@ -331,14 +353,10 @@ int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice, return 0; __error: - if (input != NULL) { - snd_rawmidi_done_buffer(input); - kfree(input); - } - if (output != NULL) { - snd_rawmidi_done_buffer(output); - kfree(output); - } + if (input != NULL) + snd_rawmidi_runtime_free(sinput); + if (output != NULL) + snd_rawmidi_runtime_free(soutput); module_put(rmidi->card->module); if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK)) up(&rmidi->open_mutex); @@ -465,14 +483,11 @@ int snd_rawmidi_kernel_release(snd_rawmidi_file_t * rfile) substream = rfile->input; rfile->input = NULL; runtime = substream->runtime; - runtime->trigger = 0; - substream->ops->trigger(substream, 0); + snd_rawmidi_input_trigger(substream, 0); substream->ops->close(substream); - snd_rawmidi_done_buffer(runtime); if (runtime->private_free != NULL) runtime->private_free(substream); - kfree(runtime); - substream->runtime = NULL; + snd_rawmidi_runtime_free(substream); substream->opened = 0; rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_opened--; } @@ -487,13 +502,11 @@ int snd_rawmidi_kernel_release(snd_rawmidi_file_t * rfile) snd_rawmidi_kernel_write(substream, &buf, 1); } if (snd_rawmidi_drain_output(substream) == -ERESTARTSYS) - substream->ops->trigger(substream, 0); + snd_rawmidi_output_trigger(substream, 0); substream->ops->close(substream); - snd_rawmidi_done_buffer(runtime); if (runtime->private_free != NULL) runtime->private_free(substream); - kfree(runtime); - substream->runtime = NULL; + snd_rawmidi_runtime_free(substream); substream->opened = 0; substream->append = 0; } @@ -673,8 +686,7 @@ static int snd_rawmidi_input_status(snd_rawmidi_substream_t * substream, return 0; } -static inline int _snd_rawmidi_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { snd_rawmidi_file_t *rfile; void __user *argp = (void __user *)arg; @@ -747,7 +759,7 @@ static inline int _snd_rawmidi_ioctl(struct inode *inode, struct file *file, case SNDRV_RAWMIDI_IOCTL_DROP: { int val; - if (get_user(val, (long __user *) argp)) + if (get_user(val, (int __user *) argp)) return -EFAULT; switch (val) { case SNDRV_RAWMIDI_STREAM_OUTPUT: @@ -761,7 +773,7 @@ static inline int _snd_rawmidi_ioctl(struct inode *inode, struct file *file, case SNDRV_RAWMIDI_IOCTL_DRAIN: { int val; - if (get_user(val, (long __user *) argp)) + if (get_user(val, (int __user *) argp)) return -EFAULT; switch (val) { case SNDRV_RAWMIDI_STREAM_OUTPUT: @@ -784,19 +796,10 @@ static inline int _snd_rawmidi_ioctl(struct inode *inode, struct file *file, return -ENOTTY; } -/* FIXME: need to unlock BKL to allow preemption */ -static int snd_rawmidi_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int err; - unlock_kernel(); - err = _snd_rawmidi_ioctl(inode, file, cmd, arg); - lock_kernel(); - return err; -} - -int snd_rawmidi_control_ioctl(snd_card_t * card, snd_ctl_file_t * control, - unsigned int cmd, unsigned long arg) +static int snd_rawmidi_control_ioctl(snd_card_t * card, + snd_ctl_file_t * control, + unsigned int cmd, + unsigned long arg) { void __user *argp = (void __user *)arg; unsigned int tmp; @@ -885,7 +888,7 @@ int snd_rawmidi_receive(snd_rawmidi_substream_t * substream, const unsigned char count1 = count; if (count1 > (int)(runtime->buffer_size - runtime->avail)) { count1 = runtime->buffer_size - runtime->avail; - runtime->xruns = count - count1; + runtime->xruns += count - count1; } if (count1 > 0) { memcpy(runtime->buffer, buffer, count1); @@ -895,13 +898,13 @@ int snd_rawmidi_receive(snd_rawmidi_substream_t * substream, const unsigned char } } } - if (result > 0 && runtime->event == NULL) { - if (snd_rawmidi_ready(substream)) + if (result > 0) { + if (runtime->event) + tasklet_hi_schedule(&runtime->tasklet); + else if (snd_rawmidi_ready(substream)) wake_up(&runtime->sleep); } spin_unlock_irqrestore(&runtime->lock, flags); - if (result > 0 && runtime->event) - runtime->event(substream); return result; } @@ -923,7 +926,8 @@ static long snd_rawmidi_kernel_read1(snd_rawmidi_substream_t *substream, memcpy(buf + result, runtime->buffer + runtime->appl_ptr, count1); } else { spin_unlock_irqrestore(&runtime->lock, flags); - if (copy_to_user(buf + result, runtime->buffer + runtime->appl_ptr, count1)) { + if (copy_to_user((char __user *)buf + result, + runtime->buffer + runtime->appl_ptr, count1)) { return result > 0 ? result : -EFAULT; } spin_lock_irqsave(&runtime->lock, flags); @@ -940,8 +944,7 @@ static long snd_rawmidi_kernel_read1(snd_rawmidi_substream_t *substream, long snd_rawmidi_kernel_read(snd_rawmidi_substream_t *substream, unsigned char *buf, long count) { - substream->runtime->trigger = 1; - substream->ops->trigger(substream, 1); + snd_rawmidi_input_trigger(substream, 1); return snd_rawmidi_kernel_read1(substream, buf, count, 1); } @@ -958,8 +961,7 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun if (substream == NULL) return -EIO; runtime = substream->runtime; - runtime->trigger = 1; - substream->ops->trigger(substream, 1); + snd_rawmidi_input_trigger(substream, 1); result = 0; while (count > 0) { spin_lock_irq(&runtime->lock); @@ -982,7 +984,7 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun spin_lock_irq(&runtime->lock); } spin_unlock_irq(&runtime->lock); - count1 = snd_rawmidi_kernel_read1(substream, buf, count, 0); + count1 = snd_rawmidi_kernel_read1(substream, (unsigned char *)buf, count, 0); if (count1 < 0) return result > 0 ? result : count1; result += count1; @@ -1010,8 +1012,6 @@ int snd_rawmidi_transmit_empty(snd_rawmidi_substream_t * substream) } spin_lock_irqsave(&runtime->lock, flags); result = runtime->avail >= runtime->buffer_size; - if (result) - runtime->trigger = 1; spin_unlock_irqrestore(&runtime->lock, flags); return result; } @@ -1044,7 +1044,6 @@ int snd_rawmidi_transmit_peek(snd_rawmidi_substream_t * substream, unsigned char spin_lock_irqsave(&runtime->lock, flags); if (runtime->avail >= runtime->buffer_size) { /* warning: lowlevel layer MUST trigger down the hardware */ - runtime->trigger = 0; goto __skip; } if (count == 1) { /* special case, faster code */ @@ -1059,8 +1058,12 @@ int snd_rawmidi_transmit_peek(snd_rawmidi_substream_t * substream, unsigned char memcpy(buffer, runtime->buffer + runtime->hw_ptr, count1); count -= count1; result += count1; - if (count > 0) + if (count > 0) { + if (count > (int)(runtime->buffer_size - runtime->avail - count1)) + count = runtime->buffer_size - runtime->avail - count1; memcpy(buffer + count1, runtime->buffer, count); + result += count; + } } __skip: spin_unlock_irqrestore(&runtime->lock, flags); @@ -1093,15 +1096,11 @@ int snd_rawmidi_transmit_ack(snd_rawmidi_substream_t * substream, int count) runtime->hw_ptr %= runtime->buffer_size; runtime->avail += count; substream->bytes += count; - if (runtime->drain) - wake_up(&runtime->sleep); - else - if (count > 0 && runtime->event == NULL) - if (snd_rawmidi_ready(substream)) - wake_up(&runtime->sleep); + if (count > 0) { + if (runtime->drain || snd_rawmidi_ready(substream)) + wake_up(&runtime->sleep); + } spin_unlock_irqrestore(&runtime->lock, flags); - if (count > 0 && runtime->event) - runtime->event(substream); return count; } @@ -1150,7 +1149,8 @@ static long snd_rawmidi_kernel_write1(snd_rawmidi_substream_t * substream, const memcpy(runtime->buffer + runtime->appl_ptr, buf, count1); } else { spin_unlock_irqrestore(&runtime->lock, flags); - if (copy_from_user(runtime->buffer + runtime->appl_ptr, buf, count1)) { + if (copy_from_user(runtime->buffer + runtime->appl_ptr, + (char __user *)buf, count1)) { spin_lock_irqsave(&runtime->lock, flags); result = result > 0 ? result : -EFAULT; goto __end; @@ -1165,12 +1165,10 @@ static long snd_rawmidi_kernel_write1(snd_rawmidi_substream_t * substream, const count -= count1; } __end: - if (result > 0) - runtime->trigger = 1; count1 = runtime->avail < runtime->buffer_size; spin_unlock_irqrestore(&runtime->lock, flags); if (count1) - substream->ops->trigger(substream, 1); + snd_rawmidi_output_trigger(substream, 1); return result; } @@ -1215,7 +1213,7 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, size spin_lock_irq(&runtime->lock); } spin_unlock_irq(&runtime->lock); - count1 = snd_rawmidi_kernel_write1(substream, buf, count, 0); + count1 = snd_rawmidi_kernel_write1(substream, (unsigned char *)buf, count, 0); if (count1 < 0) return result > 0 ? result : count1; result += count1; @@ -1255,8 +1253,7 @@ static unsigned int snd_rawmidi_poll(struct file *file, poll_table * wait) rfile = file->private_data; if (rfile->input != NULL) { runtime = rfile->input->runtime; - runtime->trigger = 1; - rfile->input->ops->trigger(rfile->input, 1); + snd_rawmidi_input_trigger(rfile->input, 1); poll_wait(file, &runtime->sleep, wait); } if (rfile->output != NULL) { @@ -1275,6 +1272,14 @@ static unsigned int snd_rawmidi_poll(struct file *file, poll_table * wait) return mask; } +/* + */ +#ifdef CONFIG_COMPAT +#include "rawmidi_compat.c" +#else +#define snd_rawmidi_ioctl_compat NULL +#endif + /* */ @@ -1345,7 +1350,8 @@ static struct file_operations snd_rawmidi_f_ops = .open = snd_rawmidi_open, .release = snd_rawmidi_release, .poll = snd_rawmidi_poll, - .ioctl = snd_rawmidi_ioctl, + .unlocked_ioctl = snd_rawmidi_ioctl, + .compat_ioctl = snd_rawmidi_ioctl_compat, }; static snd_minor_t snd_rawmidi_reg = @@ -1626,6 +1632,7 @@ static int __init alsa_rawmidi_init(void) { snd_ctl_register_ioctl(snd_rawmidi_control_ioctl); + snd_ctl_register_ioctl_compat(snd_rawmidi_control_ioctl); #ifdef CONFIG_SND_OSSEMUL { int i; /* check device map table */ @@ -1647,6 +1654,7 @@ static int __init alsa_rawmidi_init(void) static void __exit alsa_rawmidi_exit(void) { snd_ctl_unregister_ioctl(snd_rawmidi_control_ioctl); + snd_ctl_unregister_ioctl_compat(snd_rawmidi_control_ioctl); } module_init(alsa_rawmidi_init) diff --git a/sound/core/rtctimer.c b/sound/core/rtctimer.c index e957b1396..bd5d584d2 100644 --- a/sound/core/rtctimer.c +++ b/sound/core/rtctimer.c @@ -183,4 +183,6 @@ MODULE_PARM_DESC(rtctimer_freq, "timer frequency in Hz"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("snd-timer-" __stringify(SNDRV_TIMER_GLOBAL_RTC)); + #endif /* CONFIG_RTC || CONFIG_RTC_MODULE */ diff --git a/sound/core/seq/Makefile b/sound/core/seq/Makefile index d7b79d976..64cb50d7b 100644 --- a/sound/core/seq/Makefile +++ b/sound/core/seq/Makefile @@ -37,6 +37,8 @@ obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o obj-$(CONFIG_SND_VIRMIDI) += snd-seq-virmidi.o snd-seq-midi-event.o obj-$(call sequencer,$(CONFIG_SND_RAWMIDI)) += snd-seq-midi.o snd-seq-midi-event.o obj-$(call sequencer,$(CONFIG_SND_OPL3_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o +obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o +obj-$(call sequencer,$(CONFIG_SND_GUS_SYNTH)) += snd-seq-instr.o obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += snd-seq-midi-emul.o snd-seq-virmidi.o obj-$(call sequencer,$(CONFIG_SND_EMU10K1)) += snd-seq-midi-emul.o snd-seq-virmidi.o obj-$(call sequencer,$(CONFIG_SND_TRIDENT)) += snd-seq-midi-emul.o snd-seq-instr.o diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c index 53eb75489..4c0558c0a 100644 --- a/sound/core/seq/oss/seq_oss.c +++ b/sound/core/seq/oss/seq_oss.c @@ -59,7 +59,7 @@ static int odev_open(struct inode *inode, struct file *file); static int odev_release(struct inode *inode, struct file *file); static ssize_t odev_read(struct file *file, char __user *buf, size_t count, loff_t *offset); static ssize_t odev_write(struct file *file, const char __user *buf, size_t count, loff_t *offset); -static int odev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); +static long odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg); static unsigned int odev_poll(struct file *file, poll_table * wait); #ifdef CONFIG_PROC_FS static void info_read(snd_info_entry_t *entry, snd_info_buffer_t *buf); @@ -177,20 +177,20 @@ odev_write(struct file *file, const char __user *buf, size_t count, loff_t *offs return snd_seq_oss_write(dp, buf, count, file); } -static int -odev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +static long +odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { seq_oss_devinfo_t *dp; - int err; dp = file->private_data; snd_assert(dp != NULL, return -EIO); - /* FIXME: need to unlock BKL to allow preemption */ - unlock_kernel(); - err = snd_seq_oss_ioctl(dp, cmd, arg); - lock_kernel(); - return err; + return snd_seq_oss_ioctl(dp, cmd, arg); } +#ifdef CONFIG_COMPAT +#define odev_ioctl_compat odev_ioctl +#else +#define odev_ioctl_compat NULL +#endif static unsigned int odev_poll(struct file *file, poll_table * wait) @@ -213,7 +213,8 @@ static struct file_operations seq_oss_f_ops = .open = odev_open, .release = odev_release, .poll = odev_poll, - .ioctl = odev_ioctl, + .unlocked_ioctl = odev_ioctl, + .compat_ioctl = odev_ioctl_compat, }; static snd_minor_t seq_oss_reg = { diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c index cecf3f825..bac4b4f1a 100644 --- a/sound/core/seq/oss/seq_oss_init.c +++ b/sound/core/seq/oss/seq_oss_init.c @@ -66,10 +66,17 @@ snd_seq_oss_create_client(void) { int rc; snd_seq_client_callback_t callback; - snd_seq_client_info_t info; - snd_seq_port_info_t port; + snd_seq_client_info_t *info; + snd_seq_port_info_t *port; snd_seq_port_callback_t port_callback; + info = kmalloc(sizeof(*info), GFP_KERNEL); + port = kmalloc(sizeof(*port), GFP_KERNEL); + if (!info || !port) { + rc = -ENOMEM; + goto __error; + } + /* create ALSA client */ memset(&callback, 0, sizeof(callback)); @@ -79,38 +86,38 @@ snd_seq_oss_create_client(void) rc = snd_seq_create_kernel_client(NULL, SNDRV_SEQ_CLIENT_OSS, &callback); if (rc < 0) - return rc; + goto __error; system_client = rc; debug_printk(("new client = %d\n", rc)); /* set client information */ - memset(&info, 0, sizeof(info)); - info.client = system_client; - info.type = KERNEL_CLIENT; - strcpy(info.name, "OSS sequencer"); + memset(info, 0, sizeof(*info)); + info->client = system_client; + info->type = KERNEL_CLIENT; + strcpy(info->name, "OSS sequencer"); - rc = call_ctl(SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &info); + rc = call_ctl(SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, info); /* look up midi devices */ snd_seq_oss_midi_lookup_ports(system_client); /* create annoucement receiver port */ - memset(&port, 0, sizeof(port)); - strcpy(port.name, "Receiver"); - port.addr.client = system_client; - port.capability = SNDRV_SEQ_PORT_CAP_WRITE; /* receive only */ - port.type = 0; + memset(port, 0, sizeof(*port)); + strcpy(port->name, "Receiver"); + port->addr.client = system_client; + port->capability = SNDRV_SEQ_PORT_CAP_WRITE; /* receive only */ + port->type = 0; memset(&port_callback, 0, sizeof(port_callback)); /* don't set port_callback.owner here. otherwise the module counter * is incremented and we can no longer release the module.. */ port_callback.event_input = receive_announce; - port.kernel = &port_callback; + port->kernel = &port_callback; - call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, &port); - if ((system_port = port.addr.port) >= 0) { + call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, port); + if ((system_port = port->addr.port) >= 0) { snd_seq_port_subscribe_t subs; memset(&subs, 0, sizeof(subs)); @@ -120,9 +127,12 @@ snd_seq_oss_create_client(void) subs.dest.port = system_port; call_ctl(SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &subs); } + rc = 0; - - return 0; + __error: + kfree(port); + kfree(info); + return rc; } @@ -491,6 +501,26 @@ snd_seq_oss_reset(seq_oss_devinfo_t *dp) snd_seq_oss_timer_stop(dp->timer); } + +/* + * misc. functions for proc interface + */ +char * +enabled_str(int bool) +{ + return bool ? "enabled" : "disabled"; +} + +static char * +filemode_str(int val) +{ + static char *str[] = { + "none", "read", "write", "read/write", + }; + return str[val & SNDRV_SEQ_OSS_FILE_ACMODE]; +} + + /* * proc interface */ @@ -523,22 +553,3 @@ snd_seq_oss_system_info_read(snd_info_buffer_t *buf) } } -/* - * misc. functions for proc interface - */ -char * -enabled_str(int bool) -{ - return bool ? "enabled" : "disabled"; -} - -char * -filemode_str(int val) -{ - static char *str[] = { - "none", "read", "write", "read/write", - }; - return str[val & SNDRV_SEQ_OSS_FILE_ACMODE]; -} - - diff --git a/sound/core/seq/oss/seq_oss_misc.c b/sound/core/seq/oss/seq_oss_misc.c deleted file mode 100644 index ea4a056e2..000000000 --- a/sound/core/seq/oss/seq_oss_misc.c +++ /dev/null @@ -1,110 +0,0 @@ -/*---------------------------------------------------------------- - * miscellaneous functions - *----------------------------------------------------------------*/ - -unsigned short snd_seq_oss_semitone_tuning[24] = -{ -/* 0 */ 10000, 10595, 11225, 11892, 12599, 13348, 14142, 14983, -/* 8 */ 15874, 16818, 17818, 18877, 20000, 21189, 22449, 23784, -/* 16 */ 25198, 26697, 28284, 29966, 31748, 33636, 35636, 37755 -}; - -unsigned short snd_seq_oss_cent_tuning[100] = -{ -/* 0 */ 10000, 10006, 10012, 10017, 10023, 10029, 10035, 10041, -/* 8 */ 10046, 10052, 10058, 10064, 10070, 10075, 10081, 10087, -/* 16 */ 10093, 10099, 10105, 10110, 10116, 10122, 10128, 10134, -/* 24 */ 10140, 10145, 10151, 10157, 10163, 10169, 10175, 10181, -/* 32 */ 10187, 10192, 10198, 10204, 10210, 10216, 10222, 10228, -/* 40 */ 10234, 10240, 10246, 10251, 10257, 10263, 10269, 10275, -/* 48 */ 10281, 10287, 10293, 10299, 10305, 10311, 10317, 10323, -/* 56 */ 10329, 10335, 10341, 10347, 10353, 10359, 10365, 10371, -/* 64 */ 10377, 10383, 10389, 10395, 10401, 10407, 10413, 10419, -/* 72 */ 10425, 10431, 10437, 10443, 10449, 10455, 10461, 10467, -/* 80 */ 10473, 10479, 10485, 10491, 10497, 10503, 10509, 10515, -/* 88 */ 10521, 10528, 10534, 10540, 10546, 10552, 10558, 10564, -/* 96 */ 10570, 10576, 10582, 10589 -}; - -/* convert from MIDI note to frequency */ -int -snd_seq_oss_note_to_freq(int note_num) -{ - - /* - * This routine converts a midi note to a frequency (multiplied by 1000) - */ - - int note, octave, note_freq; - static int notes[] = { - 261632, 277189, 293671, 311132, 329632, 349232, - 369998, 391998, 415306, 440000, 466162, 493880 - }; - -#define BASE_OCTAVE 5 - - octave = note_num / 12; - note = note_num % 12; - - note_freq = notes[note]; - - if (octave < BASE_OCTAVE) - note_freq >>= (BASE_OCTAVE - octave); - else if (octave > BASE_OCTAVE) - note_freq <<= (octave - BASE_OCTAVE); - - /* - * note_freq >>= 1; - */ - - return note_freq; -} - -unsigned long -snd_seq_oss_compute_finetune(unsigned long base_freq, int bend, int range, int vibrato_cents) -{ - unsigned long amount; - int negative, semitones, cents, multiplier = 1; - - if (!bend || !range || !base_freq) - return base_freq; - - if (range >= 8192) - range = 8192; - - bend = bend * range / 8192; /* Convert to cents */ - bend += vibrato_cents; - - if (!bend) - return base_freq; - - negative = bend < 0 ? 1 : 0; - - if (bend < 0) - bend *= -1; - if (bend > range) - bend = range; - - /* - if (bend > 2399) - bend = 2399; - */ - while (bend > 2399) { - multiplier *= 4; - bend -= 2400; - } - - semitones = bend / 100; - if (semitones > 99) - semitones = 99; - cents = bend % 100; - - amount = (int) (snd_seq_oss_semitone_tuning[semitones] * multiplier * - snd_seq_oss_cent_tuning[cents]) / 10000; - - if (negative) - return (base_freq * 10000) / amount; /* Bend down */ - else - return (base_freq * amount) / 10000; /* Bend up */ -} - diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index dd7650ddd..d8f76afd2 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -37,8 +37,8 @@ #include "seq_info.h" #include "seq_system.h" #include <sound/seq_device.h> -#if defined(CONFIG_SND_BIT32_EMUL) || defined(CONFIG_SND_BIT32_EMUL_MODULE) -#include "../ioctl32/ioctl32.h" +#ifdef CONFIG_COMPAT +#include <linux/compat.h> #endif /* Client Manager @@ -51,7 +51,7 @@ #define SNDRV_SEQ_LFLG_OUTPUT 0x0002 #define SNDRV_SEQ_LFLG_OPEN (SNDRV_SEQ_LFLG_INPUT|SNDRV_SEQ_LFLG_OUTPUT) -static spinlock_t clients_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(clients_lock); static DECLARE_MUTEX(register_mutex); /* @@ -375,7 +375,7 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count, l if (!(snd_seq_file_flags(file) & SNDRV_SEQ_LFLG_INPUT)) return -ENXIO; - if (verify_area(VERIFY_WRITE, buf, count)) + if (!access_ok(VERIFY_WRITE, buf, count)) return -EFAULT; /* check client structures are in place */ @@ -413,7 +413,7 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count, l } count -= sizeof(snd_seq_event_t); buf += sizeof(snd_seq_event_t); - err = snd_seq_expand_var_event(&cell->event, count, buf, 0, sizeof(snd_seq_event_t)); + err = snd_seq_expand_var_event(&cell->event, count, (char *)buf, 0, sizeof(snd_seq_event_t)); if (err < 0) break; result += err; @@ -751,8 +751,8 @@ static int multicast_event(client_t *client, snd_seq_event_t *event, * n == 0 : the event was not passed to any client. * n < 0 : error - event was not processed. */ -int snd_seq_deliver_event(client_t *client, snd_seq_event_t *event, - int atomic, int hop) +static int snd_seq_deliver_event(client_t *client, snd_seq_event_t *event, + int atomic, int hop) { int result; @@ -904,7 +904,7 @@ static int snd_seq_client_enqueue_event(client_t *client, return -ENXIO; /* queue is not allocated */ /* allocate an event cell */ - err = snd_seq_event_dup(client->pool, event, &cell, !blocking && !atomic, file); + err = snd_seq_event_dup(client->pool, event, &cell, !blocking || atomic, file); if (err < 0) return err; @@ -1012,7 +1012,7 @@ static ssize_t snd_seq_write(struct file *file, const char __user *buf, size_t c event.data.ext.ptr = (char*)buf + sizeof(snd_seq_event_t); len += extlen; /* increment data length */ } else { -#if defined(CONFIG_SND_BIT32_EMUL) || defined(CONFIG_SND_BIT32_EMUL_MODULE) +#ifdef CONFIG_COMPAT if (client->convert32 && snd_seq_ev_is_varusr(&event)) { void *ptr = compat_ptr(event.data.raw32.d[1]); event.data.ext.ptr = ptr; @@ -2131,21 +2131,20 @@ static int snd_seq_do_ioctl(client_t *client, unsigned int cmd, void __user *arg } -static int snd_seq_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_seq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { client_t *client = (client_t *) file->private_data; - int err; snd_assert(client != NULL, return -ENXIO); - /* FIXME: need to unlock BKL to allow preemption */ - unlock_kernel(); - err = snd_seq_do_ioctl(client, cmd, (void __user *) arg); - lock_kernel(); - return err; + return snd_seq_do_ioctl(client, cmd, (void __user *) arg); } +#ifdef CONFIG_COMPAT +#include "seq_compat.c" +#else +#define snd_seq_ioctl_compat NULL +#endif /* -------------------------------------------------------- */ @@ -2321,7 +2320,7 @@ int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg) if (client == NULL) return -ENXIO; fs = snd_enter_user(); - result = snd_seq_do_ioctl(client, cmd, arg); + result = snd_seq_do_ioctl(client, cmd, (void __user *)arg); snd_leave_user(fs); return result; } @@ -2462,7 +2461,8 @@ static struct file_operations snd_seq_f_ops = .open = snd_seq_open, .release = snd_seq_release, .poll = snd_seq_poll, - .ioctl = snd_seq_ioctl, + .unlocked_ioctl = snd_seq_ioctl, + .compat_ioctl = snd_seq_ioctl_compat, }; static snd_minor_t snd_seq_reg = diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c index 6380acfe6..e88967c5b 100644 --- a/sound/core/seq/seq_dummy.c +++ b/sound/core/seq/seq_dummy.c @@ -63,6 +63,7 @@ MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); MODULE_DESCRIPTION("ALSA sequencer MIDI-through client"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("snd-seq-client-" __stringify(SNDRV_SEQ_CLIENT_DUMMY)); static int ports = 1; static int duplex = 0; diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c index f61d8bfe3..18247db45 100644 --- a/sound/core/seq/seq_midi.c +++ b/sound/core/seq/seq_midi.c @@ -43,10 +43,10 @@ Possible options for midisynth module: MODULE_AUTHOR("Frank van de Pol <fvdpol@coil.demon.nl>, Jaroslav Kysela <perex@suse.cz>"); MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer MIDI synth."); MODULE_LICENSE("GPL"); -int output_buffer_size = PAGE_SIZE; +static int output_buffer_size = PAGE_SIZE; module_param(output_buffer_size, int, 0644); MODULE_PARM_DESC(output_buffer_size, "Output buffer size in bytes."); -int input_buffer_size = PAGE_SIZE; +static int input_buffer_size = PAGE_SIZE; module_param(input_buffer_size, int, 0644); MODULE_PARM_DESC(input_buffer_size, "Input buffer size in bytes."); @@ -284,13 +284,13 @@ static int set_client_name(seq_midisynth_client_t *client, snd_card_t *card, } /* register new midi synth port */ -int +static int snd_seq_midisynth_register_port(snd_seq_device_t *dev) { seq_midisynth_client_t *client; seq_midisynth_t *msynth, *ms; - snd_seq_port_info_t port; - snd_rawmidi_info_t info; + snd_seq_port_info_t *port; + snd_rawmidi_info_t *info; int newclient = 0; unsigned int p, ports; snd_seq_client_callback_t callbacks; @@ -300,20 +300,25 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev) unsigned int input_count = 0, output_count = 0; snd_assert(card != NULL && device >= 0 && device < SNDRV_RAWMIDI_DEVICES, return -EINVAL); - info.device = device; - info.stream = SNDRV_RAWMIDI_STREAM_OUTPUT; - info.subdevice = 0; - if (snd_rawmidi_info_select(card, &info) >= 0) - output_count = info.subdevices_count; - info.stream = SNDRV_RAWMIDI_STREAM_INPUT; - if (snd_rawmidi_info_select(card, &info) >= 0) { - input_count = info.subdevices_count; + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (! info) + return -ENOMEM; + info->device = device; + info->stream = SNDRV_RAWMIDI_STREAM_OUTPUT; + info->subdevice = 0; + if (snd_rawmidi_info_select(card, info) >= 0) + output_count = info->subdevices_count; + info->stream = SNDRV_RAWMIDI_STREAM_INPUT; + if (snd_rawmidi_info_select(card, info) >= 0) { + input_count = info->subdevices_count; } ports = output_count; if (ports < input_count) ports = input_count; - if (ports == 0) + if (ports == 0) { + kfree(info); return -ENODEV; + } if (ports > (256 / SNDRV_RAWMIDI_DEVICES)) ports = 256 / SNDRV_RAWMIDI_DEVICES; @@ -324,6 +329,7 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev) client = kcalloc(1, sizeof(*client), GFP_KERNEL); if (client == NULL) { up(®ister_mutex); + kfree(info); return -ENOMEM; } memset(&callbacks, 0, sizeof(callbacks)); @@ -333,14 +339,16 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev) if (client->seq_client < 0) { kfree(client); up(®ister_mutex); + kfree(info); return -ENOMEM; } - set_client_name(client, card, &info); + set_client_name(client, card, info); } else if (device == 0) - set_client_name(client, card, &info); /* use the first device's name */ + set_client_name(client, card, info); /* use the first device's name */ msynth = kcalloc(ports, sizeof(seq_midisynth_t), GFP_KERNEL); - if (msynth == NULL) + port = kmalloc(sizeof(*port), GFP_KERNEL); + if (msynth == NULL || port == NULL) goto __nomem; for (p = 0; p < ports; p++) { @@ -350,42 +358,42 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev) goto __nomem; /* declare port */ - memset(&port, 0, sizeof(port)); - port.addr.client = client->seq_client; - port.addr.port = device * (256 / SNDRV_RAWMIDI_DEVICES) + p; - port.flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT; - memset(&info, 0, sizeof(info)); - info.device = device; + memset(port, 0, sizeof(*port)); + port->addr.client = client->seq_client; + port->addr.port = device * (256 / SNDRV_RAWMIDI_DEVICES) + p; + port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT; + memset(info, 0, sizeof(*info)); + info->device = device; if (p < output_count) - info.stream = SNDRV_RAWMIDI_STREAM_OUTPUT; + info->stream = SNDRV_RAWMIDI_STREAM_OUTPUT; else - info.stream = SNDRV_RAWMIDI_STREAM_INPUT; - info.subdevice = p; - if (snd_rawmidi_info_select(card, &info) >= 0) - strcpy(port.name, info.subname); - if (! port.name[0]) { - if (info.name[0]) { + info->stream = SNDRV_RAWMIDI_STREAM_INPUT; + info->subdevice = p; + if (snd_rawmidi_info_select(card, info) >= 0) + strcpy(port->name, info->subname); + if (! port->name[0]) { + if (info->name[0]) { if (ports > 1) - snprintf(port.name, sizeof(port.name), "%s-%d", info.name, p); + snprintf(port->name, sizeof(port->name), "%s-%d", info->name, p); else - snprintf(port.name, sizeof(port.name), "%s", info.name); + snprintf(port->name, sizeof(port->name), "%s", info->name); } else { /* last resort */ if (ports > 1) - sprintf(port.name, "MIDI %d-%d-%d", card->number, device, p); + sprintf(port->name, "MIDI %d-%d-%d", card->number, device, p); else - sprintf(port.name, "MIDI %d-%d", card->number, device); + sprintf(port->name, "MIDI %d-%d", card->number, device); } } - if ((info.flags & SNDRV_RAWMIDI_INFO_OUTPUT) && p < output_count) - port.capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SYNC_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE; - if ((info.flags & SNDRV_RAWMIDI_INFO_INPUT) && p < input_count) - port.capability |= SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SYNC_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ; - if ((port.capability & (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ)) == (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ) && - info.flags & SNDRV_RAWMIDI_INFO_DUPLEX) - port.capability |= SNDRV_SEQ_PORT_CAP_DUPLEX; - port.type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC; - port.midi_channels = 16; + if ((info->flags & SNDRV_RAWMIDI_INFO_OUTPUT) && p < output_count) + port->capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SYNC_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE; + if ((info->flags & SNDRV_RAWMIDI_INFO_INPUT) && p < input_count) + port->capability |= SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SYNC_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ; + if ((port->capability & (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ)) == (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ) && + info->flags & SNDRV_RAWMIDI_INFO_DUPLEX) + port->capability |= SNDRV_SEQ_PORT_CAP_DUPLEX; + port->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC; + port->midi_channels = 16; memset(&pcallbacks, 0, sizeof(pcallbacks)); pcallbacks.owner = THIS_MODULE; pcallbacks.private_data = ms; @@ -394,11 +402,11 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev) pcallbacks.use = midisynth_use; pcallbacks.unuse = midisynth_unuse; pcallbacks.event_input = event_process_midi; - port.kernel = &pcallbacks; - if (snd_seq_kernel_client_ctl(client->seq_client, SNDRV_SEQ_IOCTL_CREATE_PORT, &port)<0) + port->kernel = &pcallbacks; + if (snd_seq_kernel_client_ctl(client->seq_client, SNDRV_SEQ_IOCTL_CREATE_PORT, port)<0) goto __nomem; ms->seq_client = client->seq_client; - ms->seq_port = port.addr.port; + ms->seq_port = port->addr.port; } client->ports_per_device[device] = ports; client->ports[device] = msynth; @@ -418,12 +426,14 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev) snd_seq_delete_kernel_client(client->seq_client); kfree(client); } + kfree(info); + kfree(port); up(®ister_mutex); return -ENOMEM; } /* release midi synth port */ -int +static int snd_seq_midisynth_unregister_port(snd_seq_device_t *dev) { seq_midisynth_client_t *client; diff --git a/sound/core/sound.c b/sound/core/sound.c index d478a41e3..88e052079 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -48,7 +48,6 @@ module_param(major, int, 0444); MODULE_PARM_DESC(major, "Major # for sound driver."); module_param(cards_limit, int, 0444); MODULE_PARM_DESC(cards_limit, "Count of auto-loadable soundcards."); -MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR); #ifdef CONFIG_DEVFS_FS module_param(device_mode, int, 0444); MODULE_PARM_DESC(device_mode, "Device file permission mask for devfs."); @@ -159,7 +158,7 @@ static int snd_open(struct inode *inode, struct file *file) return err; } -struct file_operations snd_fops = +static struct file_operations snd_fops = { .owner = THIS_MODULE, .open = snd_open @@ -228,12 +227,11 @@ int snd_register_device(int type, snd_card_t * card, int dev, snd_minor_t * reg, return -EBUSY; } list_add_tail(&preg->list, &snd_minors_hash[SNDRV_MINOR_CARD(minor)]); - if (strncmp(name, "controlC", 8) || card->number >= cards_limit) { + if (strncmp(name, "controlC", 8) || card->number >= cards_limit) 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); - } + if (card) + device = card->dev; + class_simple_device_add(sound_class, MKDEV(major, minor), device, name); up(&sound_mutex); return 0; @@ -263,10 +261,9 @@ int snd_unregister_device(int type, snd_card_t * card, int dev) return -EINVAL; } - if (strncmp(mptr->name, "controlC", 8) || card->number >= cards_limit) { /* created in sound.c */ + 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_simple_device_remove(MKDEV(major, minor)); list_del(&mptr->list); up(&sound_mutex); @@ -357,10 +354,8 @@ static int __init alsa_sound_init(void) return -ENOMEM; } snd_info_minor_register(); - for (controlnum = 0; controlnum < cards_limit; controlnum++) { + for (controlnum = 0; controlnum < cards_limit; controlnum++) devfs_mk_cdev(MKDEV(major, controlnum<<5), S_IFCHR | device_mode, "snd/controlC%d", controlnum); - class_simple_device_add(sound_class, MKDEV(major, controlnum<<5), NULL, "controlC%d", controlnum); - } #ifndef MODULE printk(KERN_INFO "Advanced Linux Sound Architecture Driver Version " CONFIG_SND_VERSION CONFIG_SND_DATE ".\n"); #endif @@ -371,10 +366,8 @@ static void __exit alsa_sound_exit(void) { short controlnum; - for (controlnum = 0; controlnum < cards_limit; controlnum++) { + for (controlnum = 0; controlnum < cards_limit; controlnum++) devfs_remove("snd/controlC%d", controlnum); - class_simple_device_remove(MKDEV(major, controlnum<<5)); - } snd_info_minor_unregister(); snd_info_done(); @@ -411,7 +404,6 @@ EXPORT_SYMBOL(snd_kmalloc_strdup); EXPORT_SYMBOL(copy_to_user_fromio); EXPORT_SYMBOL(copy_from_user_toio); /* init.c */ -EXPORT_SYMBOL(snd_cards_count); EXPORT_SYMBOL(snd_cards); #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) EXPORT_SYMBOL(snd_mixer_oss_notify_callback); @@ -427,7 +419,9 @@ EXPORT_SYMBOL(snd_card_file_remove); #ifdef CONFIG_PM EXPORT_SYMBOL(snd_power_wait); EXPORT_SYMBOL(snd_card_set_pm_callback); -EXPORT_SYMBOL(snd_card_set_dev_pm_callback); +#if defined(CONFIG_PM) && defined(CONFIG_SND_GENERIC_PM) +EXPORT_SYMBOL(snd_card_set_generic_pm_callback); +#endif #ifdef CONFIG_PCI EXPORT_SYMBOL(snd_card_pci_suspend); EXPORT_SYMBOL(snd_card_pci_resume); @@ -447,8 +441,6 @@ EXPORT_SYMBOL(snd_dma_pointer); /* info.c */ #ifdef CONFIG_PROC_FS EXPORT_SYMBOL(snd_seq_root); -EXPORT_SYMBOL(snd_create_proc_entry); -EXPORT_SYMBOL(snd_remove_proc_entry); EXPORT_SYMBOL(snd_iprintf); EXPORT_SYMBOL(snd_info_get_line); EXPORT_SYMBOL(snd_info_get_str); @@ -477,9 +469,11 @@ EXPORT_SYMBOL(snd_ctl_notify); EXPORT_SYMBOL(snd_ctl_register_ioctl); EXPORT_SYMBOL(snd_ctl_unregister_ioctl); #ifdef CONFIG_COMPAT +EXPORT_SYMBOL(snd_ctl_register_ioctl_compat); +EXPORT_SYMBOL(snd_ctl_unregister_ioctl_compat); +#endif EXPORT_SYMBOL(snd_ctl_elem_read); EXPORT_SYMBOL(snd_ctl_elem_write); -#endif /* misc.c */ EXPORT_SYMBOL(snd_task_name); #ifdef CONFIG_SND_VERBOSE_PRINTK diff --git a/sound/core/timer.c b/sound/core/timer.c index cee5f47c7..fa762ca43 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -37,10 +37,12 @@ #include <linux/kerneld.h> #endif -#if !defined(CONFIG_SND_RTCTIMER) && !defined(CONFIG_SND_RTCTIMER_MODULE) -#define DEFAULT_TIMER_LIMIT 1 -#else +#if defined(CONFIG_SND_HPET) || defined(CONFIG_SND_HPET_MODULE) +#define DEFAULT_TIMER_LIMIT 3 +#elif defined(CONFIG_SND_RTCTIMER) || defined(CONFIG_SND_RTCTIMER_MODULE) #define DEFAULT_TIMER_LIMIT 2 +#else +#define DEFAULT_TIMER_LIMIT 1 #endif static int timer_limit = DEFAULT_TIMER_LIMIT; @@ -76,7 +78,7 @@ static LIST_HEAD(snd_timer_list); static LIST_HEAD(snd_timer_slave_list); /* lock for slave active lists */ -static spinlock_t slave_active_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(slave_active_lock); static DECLARE_MUTEX(register_mutex); @@ -351,8 +353,7 @@ int snd_timer_close(snd_timer_instance_t * timeri) } if (timeri->private_free) timeri->private_free(timeri); - if (timeri->owner) - kfree(timeri->owner); + kfree(timeri->owner); kfree(timeri); if (timer && timer->card) module_put(timer->card->module); @@ -1004,8 +1005,7 @@ static struct _snd_timer_hardware snd_timer_system = static void snd_timer_free_system(snd_timer_t *timer) { - if (timer->private_data) - kfree(timer->private_data); + kfree(timer->private_data); } static int snd_timer_register_system(void) @@ -1119,7 +1119,8 @@ static void snd_timer_user_append_to_tqueue(snd_timer_user_t *tu, snd_timer_trea if (tu->qused >= tu->queue_size) { tu->overrun++; } else { - memcpy(&tu->queue[tu->qtail++], tread, sizeof(*tread)); + memcpy(&tu->tqueue[tu->qtail++], tread, sizeof(*tread)); + tu->qtail %= tu->queue_size; tu->qused++; } } @@ -1142,6 +1143,8 @@ static void snd_timer_user_ccallback(snd_timer_instance_t *timeri, spin_lock(&tu->qlock); snd_timer_user_append_to_tqueue(tu, &r1); spin_unlock(&tu->qlock); + kill_fasync(&tu->fasync, SIGIO, POLL_IN); + wake_up(&tu->qchange_sleep); } static void snd_timer_user_tinterrupt(snd_timer_instance_t *timeri, @@ -1226,10 +1229,8 @@ static int snd_timer_user_release(struct inode *inode, struct file *file) fasync_helper(-1, file, 0, &tu->fasync); if (tu->timeri) snd_timer_close(tu->timeri); - if (tu->queue) - kfree(tu->queue); - if (tu->tqueue) - kfree(tu->tqueue); + kfree(tu->queue); + kfree(tu->tqueue); kfree(tu); } return 0; @@ -1346,39 +1347,45 @@ static int snd_timer_user_next_device(snd_timer_id_t __user *_tid) static int snd_timer_user_ginfo(struct file *file, snd_timer_ginfo_t __user *_ginfo) { - snd_timer_ginfo_t ginfo; + snd_timer_ginfo_t *ginfo; snd_timer_id_t tid; snd_timer_t *t; struct list_head *p; int err = 0; - if (copy_from_user(&ginfo, _ginfo, sizeof(ginfo))) + ginfo = kmalloc(sizeof(*ginfo), GFP_KERNEL); + if (! ginfo) + return -ENOMEM; + if (copy_from_user(ginfo, _ginfo, sizeof(*ginfo))) { + kfree(ginfo); return -EFAULT; - tid = ginfo.tid; - memset(&ginfo, 0, sizeof(ginfo)); - ginfo.tid = tid; + } + tid = ginfo->tid; + memset(ginfo, 0, sizeof(*ginfo)); + ginfo->tid = tid; down(®ister_mutex); t = snd_timer_find(&tid); if (t != NULL) { - ginfo.card = t->card ? t->card->number : -1; + ginfo->card = t->card ? t->card->number : -1; if (t->hw.flags & SNDRV_TIMER_HW_SLAVE) - ginfo.flags |= SNDRV_TIMER_FLG_SLAVE; - strlcpy(ginfo.id, t->id, sizeof(ginfo.id)); - strlcpy(ginfo.name, t->name, sizeof(ginfo.name)); - ginfo.resolution = t->hw.resolution; + ginfo->flags |= SNDRV_TIMER_FLG_SLAVE; + strlcpy(ginfo->id, t->id, sizeof(ginfo->id)); + strlcpy(ginfo->name, t->name, sizeof(ginfo->name)); + ginfo->resolution = t->hw.resolution; if (t->hw.resolution_min > 0) { - ginfo.resolution_min = t->hw.resolution_min; - ginfo.resolution_max = t->hw.resolution_max; + ginfo->resolution_min = t->hw.resolution_min; + ginfo->resolution_max = t->hw.resolution_max; } list_for_each(p, &t->open_list_head) { - ginfo.clients++; + ginfo->clients++; } } else { err = -ENODEV; } up(®ister_mutex); - if (err >= 0 && copy_to_user(_ginfo, &ginfo, sizeof(ginfo))) + if (err >= 0 && copy_to_user(_ginfo, ginfo, sizeof(*ginfo))) err = -EFAULT; + kfree(ginfo); return err; } @@ -1492,23 +1499,28 @@ static int snd_timer_user_tselect(struct file *file, snd_timer_select_t __user * static int snd_timer_user_info(struct file *file, snd_timer_info_t __user *_info) { snd_timer_user_t *tu; - snd_timer_info_t info; + snd_timer_info_t *info; snd_timer_t *t; + int err = 0; tu = file->private_data; snd_assert(tu->timeri != NULL, return -ENXIO); t = tu->timeri->timer; snd_assert(t != NULL, return -ENXIO); - memset(&info, 0, sizeof(info)); - info.card = t->card ? t->card->number : -1; + + info = kcalloc(1, sizeof(*info), GFP_KERNEL); + if (! info) + return -ENOMEM; + info->card = t->card ? t->card->number : -1; if (t->hw.flags & SNDRV_TIMER_HW_SLAVE) - info.flags |= SNDRV_TIMER_FLG_SLAVE; - strlcpy(info.id, t->id, sizeof(info.id)); - strlcpy(info.name, t->name, sizeof(info.name)); - info.resolution = t->hw.resolution; - if (copy_to_user(_info, &info, sizeof(*_info))) - return -EFAULT; - return 0; + info->flags |= SNDRV_TIMER_FLG_SLAVE; + strlcpy(info->id, t->id, sizeof(info->id)); + strlcpy(info->name, t->name, sizeof(info->name)); + info->resolution = t->hw.resolution; + if (copy_to_user(_info, info, sizeof(*_info))) + err = -EFAULT; + kfree(info); + return err; } static int snd_timer_user_params(struct file *file, snd_timer_params_t __user *_params) @@ -1657,8 +1669,7 @@ static int snd_timer_user_continue(struct file *file) return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0; } -static inline int _snd_timer_user_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { snd_timer_user_t *tu; void __user *argp = (void __user *)arg; @@ -1705,17 +1716,6 @@ static inline int _snd_timer_user_ioctl(struct inode *inode, struct file *file, return -ENOTTY; } -/* FIXME: need to unlock BKL to allow preemption */ -static int snd_timer_user_ioctl(struct inode *inode, struct file * file, - unsigned int cmd, unsigned long arg) -{ - int err; - unlock_kernel(); - err = _snd_timer_user_ioctl(inode, file, cmd, arg); - lock_kernel(); - return err; -} - static int snd_timer_user_fasync(int fd, struct file * file, int on) { snd_timer_user_t *tu; @@ -1807,6 +1807,12 @@ static unsigned int snd_timer_user_poll(struct file *file, poll_table * wait) return mask; } +#ifdef CONFIG_COMPAT +#include "timer_compat.c" +#else +#define snd_timer_user_ioctl_compat NULL +#endif + static struct file_operations snd_timer_f_ops = { .owner = THIS_MODULE, @@ -1814,7 +1820,8 @@ static struct file_operations snd_timer_f_ops = .open = snd_timer_user_open, .release = snd_timer_user_release, .poll = snd_timer_user_poll, - .ioctl = snd_timer_user_ioctl, + .unlocked_ioctl = snd_timer_user_ioctl, + .compat_ioctl = snd_timer_user_ioctl_compat, .fasync = snd_timer_user_fasync, }; diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c index 6b22d2e08..cb36ecb78 100644 --- a/sound/drivers/mpu401/mpu401.c +++ b/sound/drivers/mpu401/mpu401.c @@ -1,12 +1,7 @@ /* * Driver for generic MPU-401 boards (UART mode only) * Copyright (c) by Jaroslav Kysela <perex@suse.cz> - * - * ACPI PnP Copyright (c) 2004 by Clemens Ladisch <clemens@ladisch.de> - * based on 8250_acpi.c - * Copyright (c) 2002-2003 Matthew Wilcox for Hewlett-Packard - * Copyright (C) 2004 Hewlett-Packard Co - * Bjorn Helgaas <bjorn.helgaas@hp.com> + * Copyright (c) 2004 by Castet Matthieu <castet.matthieu@free.fr> * * * This program is free software; you can redistribute it and/or modify @@ -27,27 +22,21 @@ #include <sound/driver.h> #include <linux/init.h> -#ifdef CONFIG_ACPI_BUS -#include <linux/acpi.h> -#endif +#include <linux/pnp.h> #include <linux/moduleparam.h> #include <sound/core.h> #include <sound/mpu401.h> #include <sound/initval.h> -#ifdef CONFIG_ACPI_BUS -#define USE_ACPI_PNP -#endif - MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); MODULE_DESCRIPTION("MPU-401 UART"); MODULE_LICENSE("GPL"); -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ +static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* exclude the first card */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ -#ifdef USE_ACPI_PNP -static int acpipnp[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 1 }; +#ifdef CONFIG_PNP +static int pnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; #endif static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* MPU-401 port number */ static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* MPU-401 IRQ */ @@ -58,115 +47,36 @@ module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for MPU-401 device."); module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable MPU-401 device."); -#ifdef USE_ACPI_PNP -module_param_array(acpipnp, bool, NULL, 0444); -MODULE_PARM_DESC(acpipnp, "ACPI PnP detection for MPU-401 device."); +#ifdef CONFIG_PNP +module_param_array(pnp, bool, NULL, 0444); +MODULE_PARM_DESC(pnp, "PnP detection for MPU-401 device."); #endif module_param_array(port, long, NULL, 0444); MODULE_PARM_DESC(port, "Port # for MPU-401 device."); module_param_array(irq, int, NULL, 0444); MODULE_PARM_DESC(irq, "IRQ # for MPU-401 device."); -#ifndef CONFIG_ACPI_BUS -struct acpi_device; -#endif - static snd_card_t *snd_mpu401_legacy_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; -static int cards; - -#ifdef USE_ACPI_PNP - -static int acpi_driver_registered; - -struct mpu401_resources { - unsigned long port; - int irq; -}; +static int pnp_registered = 0; -static acpi_status __devinit snd_mpu401_acpi_resource(struct acpi_resource *res, - void *data) -{ - struct mpu401_resources *resources = (struct mpu401_resources *)data; - - if (res->id == ACPI_RSTYPE_IRQ) { - if (res->data.irq.number_of_interrupts > 0) { - resources->irq = acpi_register_gsi(res->data.irq.interrupts[0], - res->data.irq.edge_level, - res->data.irq.active_high_low); - } - } else if (res->id == ACPI_RSTYPE_IO) { - if (res->data.io.range_length >= 2) { - resources->port = res->data.io.min_base_address; - } - } - return AE_OK; -} - -static int __devinit snd_mpu401_acpi_pnp(int dev, struct acpi_device *device) -{ - struct mpu401_resources res; - acpi_status status; - - res.port = SNDRV_AUTO_PORT; - res.irq = SNDRV_AUTO_IRQ; - status = acpi_walk_resources(device->handle, METHOD_NAME__CRS, - snd_mpu401_acpi_resource, &res); - if (ACPI_FAILURE(status)) - return -ENODEV; - if (res.port == SNDRV_AUTO_PORT || res.irq == SNDRV_AUTO_IRQ) { - snd_printk(KERN_ERR "no port or irq in %s _CRS\n", - acpi_device_bid(device)); - return -ENODEV; - } - port[dev] = res.port; - irq[dev] = res.irq; - return 0; -} - -#endif /* USE_ACPI_PNP */ - -static int __devinit snd_card_mpu401_probe(int dev, struct acpi_device *device) +static int snd_mpu401_create(int dev, snd_card_t **rcard) { snd_card_t *card; int err; -#ifdef USE_ACPI_PNP - if (!device) { -#endif - if (port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR "specify port\n"); - return -EINVAL; - } - if (irq[dev] == SNDRV_AUTO_IRQ) { - snd_printk(KERN_ERR "specify or disable IRQ port\n"); - return -EINVAL; - } -#ifdef USE_ACPI_PNP - } -#endif - -#ifdef USE_ACPI_PNP - if (device && (err = snd_mpu401_acpi_pnp(dev, device)) < 0) - return err; -#endif - + *rcard = NULL; card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); if (card == NULL) return -ENOMEM; strcpy(card->driver, "MPU-401 UART"); strcpy(card->shortname, card->driver); - sprintf(card->longname, "%s at 0x%lx, ", card->shortname, port[dev]); + sprintf(card->longname, "%s at %#lx, ", card->shortname, port[dev]); if (irq[dev] >= 0) { - sprintf(card->longname + strlen(card->longname), "IRQ %d", irq[dev]); + sprintf(card->longname + strlen(card->longname), "irq %d", irq[dev]); } else { strcat(card->longname, "polled"); } -#ifdef USE_ACPI_PNP - if (device) { - strcat(card->longname, ", ACPI id "); - strlcat(card->longname, acpi_device_bid(device), sizeof(card->longname)); - } -#endif + if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port[dev], 0, @@ -179,89 +89,127 @@ static int __devinit snd_card_mpu401_probe(int dev, struct acpi_device *device) snd_card_free(card); return err; } -#ifdef USE_ACPI_PNP - if (device) - acpi_driver_data(device) = card; - else -#endif - snd_mpu401_legacy_cards[dev] = card; - ++cards; + *rcard = card; return 0; } -#ifdef USE_ACPI_PNP +static int __devinit snd_mpu401_probe(int dev) +{ + if (port[dev] == SNDRV_AUTO_PORT) { + snd_printk(KERN_ERR "specify port\n"); + return -EINVAL; + } + if (irq[dev] == SNDRV_AUTO_IRQ) { + snd_printk(KERN_ERR "specify or disable IRQ\n"); + return -EINVAL; + } + return snd_mpu401_create(dev, &snd_mpu401_legacy_cards[dev]); +} + +#ifdef CONFIG_PNP + +#define IO_EXTENT 2 + +static struct pnp_device_id snd_mpu401_pnpids[] = { + { .id = "PNPb006" }, + { .id = "" } +}; + +MODULE_DEVICE_TABLE(pnp, snd_mpu401_pnpids); + +static int __init snd_mpu401_pnp(int dev, struct pnp_dev *device, + const struct pnp_device_id *id) +{ + if (!pnp_port_valid(device, 0) || + pnp_port_flags(device, 0) & IORESOURCE_DISABLED) { + snd_printk(KERN_ERR "no PnP port\n"); + return -ENODEV; + } + if (pnp_port_len(device, 0) < IO_EXTENT) { + snd_printk(KERN_ERR "PnP port length is %ld, expected %d\n", + pnp_port_len(device, 0), IO_EXTENT); + return -ENODEV; + } + port[dev] = pnp_port_start(device, 0); + + if (!pnp_irq_valid(device, 0) || + pnp_irq_flags(device, 0) & IORESOURCE_DISABLED) { + snd_printk(KERN_WARNING "no PnP irq, using polling\n"); + irq[dev] = -1; + } else { + irq[dev] = pnp_irq(device, 0); + } + return 0; +} -static int __devinit snd_mpu401_acpi_add(struct acpi_device *device) +static int __devinit snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev, + const struct pnp_device_id *id) { static int dev; + snd_card_t *card; int err; for ( ; dev < SNDRV_CARDS; ++dev) { - if (!enable[dev] || !acpipnp[dev]) + if (!enable[dev] || !pnp[dev]) continue; - err = snd_card_mpu401_probe(dev, device); + err = snd_mpu401_pnp(dev, pnp_dev, id); + if (err < 0) + return err; + err = snd_mpu401_create(dev, &card); if (err < 0) return err; + snd_card_set_dev(card, &pnp_dev->dev); + pnp_set_drvdata(pnp_dev, card); ++dev; return 0; } return -ENODEV; } -static int __devexit snd_mpu401_acpi_remove(struct acpi_device *device, - int type) +static void __devexit snd_mpu401_pnp_remove(struct pnp_dev *dev) { - snd_card_t *card; - - if (!device) - return -EINVAL; - card = (snd_card_t *)acpi_driver_data(device); - if (!card) - return -EINVAL; + snd_card_t *card = (snd_card_t *) pnp_get_drvdata(dev); snd_card_disconnect(card); snd_card_free_in_thread(card); - acpi_driver_data(device) = NULL; - return 0; } -static struct acpi_driver snd_mpu401_acpi_driver = { - .name = "MPU-401 Driver", - .class = "mpu401", - .ids = "PNPB006", - .ops = { - .add = snd_mpu401_acpi_add, - .remove = __devexit_p(snd_mpu401_acpi_remove), - }, +static struct pnp_driver snd_mpu401_pnp_driver = { + .name = "mpu401", + .id_table = snd_mpu401_pnpids, + .probe = snd_mpu401_pnp_probe, + .remove = __devexit_p(snd_mpu401_pnp_remove), }; - -#endif /* USE_ACPI_PNP */ +#else +static struct pnp_driver snd_mpu401_pnp_driver; +#endif static int __init alsa_card_mpu401_init(void) { - int dev; + int dev, devices = 0; + int err; -#ifdef USE_ACPI_PNP - if (acpi_bus_register_driver(&snd_mpu401_acpi_driver) >= 0) - acpi_driver_registered = 1; -#endif for (dev = 0; dev < SNDRV_CARDS; dev++) { if (!enable[dev]) continue; -#ifdef USE_ACPI_PNP - if (acpipnp[dev] && acpi_driver_registered) +#ifdef CONFIG_PNP + if (pnp[dev]) continue; #endif - snd_card_mpu401_probe(dev, NULL); + if (snd_mpu401_probe(dev) >= 0) + devices++; } - if (!cards) { + if ((err = pnp_register_driver(&snd_mpu401_pnp_driver)) >= 0) { + pnp_registered = 1; + devices += err; + } + + if (!devices) { #ifdef MODULE printk(KERN_ERR "MPU-401 device not found or device busy\n"); #endif -#ifdef USE_ACPI_PNP - if (acpi_driver_registered) - acpi_bus_unregister_driver(&snd_mpu401_acpi_driver); -#endif + if (pnp_registered) + pnp_unregister_driver(&snd_mpu401_pnp_driver); return -ENODEV; } return 0; @@ -271,10 +219,8 @@ static void __exit alsa_card_mpu401_exit(void) { int idx; -#ifdef USE_ACPI_PNP - if (acpi_driver_registered) - acpi_bus_unregister_driver(&snd_mpu401_acpi_driver); -#endif + if (pnp_registered) + pnp_unregister_driver(&snd_mpu401_pnp_driver); for (idx = 0; idx < SNDRV_CARDS; idx++) snd_card_free(snd_mpu401_legacy_cards[idx]); } diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c index 2c572345c..1280a57c4 100644 --- a/sound/drivers/mtpav.c +++ b/sound/drivers/mtpav.c @@ -413,10 +413,11 @@ static void snd_mtpav_input_trigger(snd_rawmidi_substream_t * substream, int up) static void snd_mtpav_output_timer(unsigned long data) { + unsigned long flags; mtpav_t *chip = (mtpav_t *)data; int p; - spin_lock(&chip->spinlock); + spin_lock_irqsave(&chip->spinlock, flags); /* reprogram timer */ chip->timer.expires = 1 + jiffies; add_timer(&chip->timer); @@ -426,7 +427,7 @@ static void snd_mtpav_output_timer(unsigned long data) if ((portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED) && portp->output) snd_mtpav_output_port_write(portp, portp->output); } - spin_unlock(&chip->spinlock); + spin_unlock_irqrestore(&chip->spinlock, flags); } /* spinlock held! */ @@ -514,9 +515,7 @@ static void snd_mtpav_inmidi_process(mtpav_t *mcrd, u8 inbyte) portp = &mcrd->ports[mcrd->inmidiport]; if (portp->mode & MTPAV_MODE_INPUT_TRIGGERED) { - spin_unlock(&mcrd->spinlock); snd_rawmidi_receive(portp->input, &inbyte, 1); - spin_lock(&mcrd->spinlock); } } diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c index c25fcc381..c313e5205 100644 --- a/sound/drivers/opl3/opl3_lib.c +++ b/sound/drivers/opl3/opl3_lib.c @@ -37,7 +37,7 @@ MODULE_LICENSE("GPL"); extern char snd_opl3_regmap[MAX_OPL2_VOICES][4]; -void snd_opl2_command(opl3_t * opl3, unsigned short cmd, unsigned char val) +static void snd_opl2_command(opl3_t * opl3, unsigned short cmd, unsigned char val) { unsigned long flags; unsigned long port; @@ -60,7 +60,7 @@ void snd_opl2_command(opl3_t * opl3, unsigned short cmd, unsigned char val) spin_unlock_irqrestore(&opl3->reg_lock, flags); } -void snd_opl3_command(opl3_t * opl3, unsigned short cmd, unsigned char val) +static void snd_opl3_command(opl3_t * opl3, unsigned short cmd, unsigned char val) { unsigned long flags; unsigned long port; @@ -364,7 +364,7 @@ int snd_opl3_new(snd_card_t *card, spin_lock_init(&opl3->timer_lock); init_MUTEX(&opl3->access_mutex); - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, opl3, &ops)) < 0) { + if ((err = snd_device_new(card, SNDRV_DEV_CODEC, opl3, &ops)) < 0) { snd_opl3_free(opl3); return err; } diff --git a/sound/drivers/opl3/opl3_seq.c b/sound/drivers/opl3/opl3_seq.c index 048b33ac5..136964b84 100644 --- a/sound/drivers/opl3/opl3_seq.c +++ b/sound/drivers/opl3/opl3_seq.c @@ -96,7 +96,7 @@ void snd_opl3_synth_cleanup(opl3_t * opl3) up(&opl3->access_mutex); } -int snd_opl3_synth_use(void *private_data, snd_seq_port_subscribe_t * info) +static int snd_opl3_synth_use(void *private_data, snd_seq_port_subscribe_t * info) { opl3_t *opl3 = private_data; int err; @@ -123,7 +123,7 @@ int snd_opl3_synth_use(void *private_data, snd_seq_port_subscribe_t * info) return 0; } -int snd_opl3_synth_unuse(void *private_data, snd_seq_port_subscribe_t * info) +static int snd_opl3_synth_unuse(void *private_data, snd_seq_port_subscribe_t * info) { opl3_t *opl3 = private_data; diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c index 1dac18638..964b97e70 100644 --- a/sound/drivers/serial-u16550.c +++ b/sound/drivers/serial-u16550.c @@ -232,7 +232,7 @@ static void snd_uart16550_io_loop(snd_uart16550_t * uart) } else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) && (uart->midi_input[substream] != NULL)) { snd_rawmidi_receive(uart->midi_input[substream], &c, 1); - } + } } else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) && (uart->midi_input[substream] != NULL)) { snd_rawmidi_receive(uart->midi_input[substream], &c, 1); } @@ -309,13 +309,14 @@ static irqreturn_t snd_uart16550_interrupt(int irq, void *dev_id, struct pt_regs /* When the polling mode, this function calls snd_uart16550_io_loop. */ static void snd_uart16550_buffer_timer(unsigned long data) { + unsigned long flags; snd_uart16550_t *uart; uart = (snd_uart16550_t *)data; - spin_lock(&uart->open_lock); + spin_lock_irqsave(&uart->open_lock, flags); snd_uart16550_del_timer(uart); snd_uart16550_io_loop(uart); - spin_unlock(&uart->open_lock); + spin_unlock_irqrestore(&uart->open_lock, flags); } /* @@ -840,6 +841,16 @@ static int __init snd_uart16550_create(snd_card_t * card, return 0; } +static void __init snd_uart16550_substreams(snd_rawmidi_str_t *stream) +{ + struct list_head *list; + + list_for_each(list, &stream->substreams) { + snd_rawmidi_substream_t *substream = list_entry(list, snd_rawmidi_substream_t, list); + sprintf(substream->name, "Serial MIDI %d", substream->number + 1); + } +} + static int __init snd_uart16550_rmidi(snd_uart16550_t *uart, int device, int outs, int ins, snd_rawmidi_t **rmidi) { snd_rawmidi_t *rrawmidi; @@ -849,7 +860,9 @@ static int __init snd_uart16550_rmidi(snd_uart16550_t *uart, int device, int out return err; snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_uart16550_input); snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_uart16550_output); - sprintf(rrawmidi->name, "uart16550 MIDI #%d", device); + strcpy(rrawmidi->name, "Serial MIDI"); + snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]); + snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]); rrawmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; @@ -906,7 +919,7 @@ static int __init snd_serial_probe(int dev) return -ENOMEM; strcpy(card->driver, "Serial"); - strcpy(card->shortname, "Serial midi (uart16550A)"); + strcpy(card->shortname, "Serial MIDI (UART16550A)"); if ((err = snd_uart16550_create(card, port[dev], diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c index e7c831424..c6fa5afa3 100644 --- a/sound/drivers/vx/vx_core.c +++ b/sound/drivers/vx/vx_core.c @@ -25,6 +25,8 @@ #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/init.h> +#include <linux/device.h> +#include <linux/firmware.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/asoundef.h> @@ -44,12 +46,10 @@ MODULE_LICENSE("GPL"); */ void snd_vx_delay(vx_core_t *chip, int xmsec) { - if (! in_interrupt() && xmsec >= 1000 / HZ) { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((xmsec * HZ + 999) / 1000); - } else { + if (! in_interrupt() && xmsec >= 1000 / HZ) + msleep(xmsec); + else mdelay(xmsec); - } } /* @@ -430,20 +430,19 @@ int vx_send_rih(vx_core_t *chip, int cmd) * snd_vx_boot_xilinx - boot up the xilinx interface * @boot: the boot record to load */ -int snd_vx_load_boot_image(vx_core_t *chip, const snd_hwdep_dsp_image_t *boot) +int snd_vx_load_boot_image(vx_core_t *chip, const struct firmware *boot) { unsigned int i; int no_fillup = vx_has_new_dsp(chip); /* check the length of boot image */ - snd_assert(boot->length > 0, return -EINVAL); - snd_assert(boot->length % 3 == 0, return -EINVAL); - snd_assert(boot->image, return -EINVAL); + snd_assert(boot->size > 0, return -EINVAL); + snd_assert(boot->size % 3 == 0, return -EINVAL); #if 0 { /* more strict check */ - unsigned int c = ((u32)boot->image[0] << 16) | ((u32)boot->image[1] << 8) | boot->image[2]; - snd_assert(boot->length == (c + 2) * 3, return -EINVAL); + unsigned int c = ((u32)boot->data[0] << 16) | ((u32)boot->data[1] << 8) | boot->data[2]; + snd_assert(boot->size == (c + 2) * 3, return -EINVAL); } #endif @@ -454,7 +453,7 @@ int snd_vx_load_boot_image(vx_core_t *chip, const snd_hwdep_dsp_image_t *boot) /* download boot strap */ for (i = 0; i < 0x600; i += 3) { - if (i >= boot->length) { + if (i >= boot->size) { if (no_fillup) break; if (vx_wait_isr_bit(chip, ISR_TX_EMPTY) < 0) { @@ -465,9 +464,7 @@ int snd_vx_load_boot_image(vx_core_t *chip, const snd_hwdep_dsp_image_t *boot) vx_outb(chip, TXM, 0); vx_outb(chip, TXL, 0); } else { - unsigned char image[3]; - if (copy_from_user(image, boot->image + i, 3)) - return -EFAULT; + unsigned char *image = boot->data + i; if (vx_wait_isr_bit(chip, ISR_TX_EMPTY) < 0) { snd_printk(KERN_ERR "dsp boot failed at %d\n", i); return -EIO; @@ -612,6 +609,10 @@ static void vx_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer) static char *uer_type[] = { "Consumer", "Professional", "Not Present" }; snd_iprintf(buffer, "%s\n", chip->card->longname); + snd_iprintf(buffer, "Xilinx Firmware: %s\n", + chip->chip_status & VX_STAT_XILINX_LOADED ? "Loaded" : "No"); + snd_iprintf(buffer, "Device Initialized: %s\n", + chip->chip_status & VX_STAT_DEVICE_INIT ? "Yes" : "No"); snd_iprintf(buffer, "DSP audio info:"); if (chip->audio_info & VX_AUDIO_INFO_REAL_TIME) snd_iprintf(buffer, " realtime"); @@ -653,7 +654,7 @@ static void vx_proc_init(vx_core_t *chip) /** * snd_vx_dsp_boot - load the DSP boot */ -int snd_vx_dsp_boot(vx_core_t *chip, const snd_hwdep_dsp_image_t *boot) +int snd_vx_dsp_boot(vx_core_t *chip, const struct firmware *boot) { int err; int cold_reset = !(chip->chip_status & VX_STAT_DEVICE_INIT); @@ -671,21 +672,20 @@ int snd_vx_dsp_boot(vx_core_t *chip, const snd_hwdep_dsp_image_t *boot) /** * snd_vx_dsp_load - load the DSP image */ -int snd_vx_dsp_load(vx_core_t *chip, const snd_hwdep_dsp_image_t *dsp) +int snd_vx_dsp_load(vx_core_t *chip, const struct firmware *dsp) { unsigned int i; int err; unsigned int csum = 0; - unsigned char image[3], *cptr; + unsigned char *image, *cptr; - snd_assert(dsp->length % 3 == 0, return -EINVAL); + snd_assert(dsp->size % 3 == 0, return -EINVAL); vx_toggle_dac_mute(chip, 1); /* Transfert data buffer from PC to DSP */ - for (i = 0; i < dsp->length; i += 3) { - if (copy_from_user(image, dsp->image + i, 3)) - return -EFAULT; + for (i = 0; i < dsp->size; i += 3) { + image = dsp->data + i; /* Wait DSP ready for a new read */ if ((err = vx_wait_isr_bit(chip, ISR_TX_EMPTY)) < 0) { printk("dsp loading error at position %d\n", i); @@ -717,6 +717,54 @@ int snd_vx_dsp_load(vx_core_t *chip, const snd_hwdep_dsp_image_t *dsp) return 0; } +#ifdef CONFIG_PM +/* + * suspend + */ +static int snd_vx_suspend(snd_card_t *card, pm_message_t state) +{ + vx_core_t *chip = card->pm_private_data; + unsigned int i; + + snd_assert(chip, return -EINVAL); + + chip->chip_status |= VX_STAT_IN_SUSPEND; + for (i = 0; i < chip->hw->num_codecs; i++) + snd_pcm_suspend_all(chip->pcm[i]); + + return 0; +} + +/* + * resume + */ +static int snd_vx_resume(snd_card_t *card) +{ + vx_core_t *chip = card->pm_private_data; + int i, err; + + snd_assert(chip, return -EINVAL); + + chip->chip_status &= ~VX_STAT_CHIP_INIT; + + for (i = 0; i < 4; i++) { + if (! chip->firmware[i]) + continue; + err = chip->ops->load_dsp(chip, i, chip->firmware[i]); + if (err < 0) { + snd_printk(KERN_ERR "vx: firmware resume error at DSP %d\n", i); + return -EIO; + } + } + + chip->chip_status |= VX_STAT_CHIP_INIT; + chip->chip_status &= ~VX_STAT_IN_SUSPEND; + + return 0; +} + +#endif + /** * snd_vx_create - constructor for vx_core_t * @hw: hardware specific record @@ -753,37 +801,13 @@ vx_core_t *snd_vx_create(snd_card_t *card, struct snd_vx_hardware *hw, strcpy(card->driver, hw->name); sprintf(card->shortname, "Digigram %s", hw->name); + snd_card_set_pm_callback(card, snd_vx_suspend, snd_vx_resume, chip); + vx_proc_init(chip); return chip; } -#ifdef CONFIG_PM -/* - * suspend - */ -void snd_vx_suspend(vx_core_t *chip) -{ - unsigned int i; - - chip->chip_status |= VX_STAT_IN_SUSPEND; - for (i = 0; i < chip->hw->num_codecs; i++) - snd_pcm_suspend_all(chip->pcm[i]); - if (chip->hwdep) - chip->hwdep->dsp_loaded = 0; -} - -/* - * resume - */ -void snd_vx_resume(vx_core_t *chip) -{ - /* clear all stuff... */ - chip->chip_status &= ~(VX_STAT_IN_SUSPEND|VX_STAT_CHIP_INIT); -} - -#endif - /* * module entries */ @@ -804,13 +828,10 @@ module_exit(alsa_vx_core_exit) */ EXPORT_SYMBOL(snd_vx_check_reg_bit); EXPORT_SYMBOL(snd_vx_create); -EXPORT_SYMBOL(snd_vx_hwdep_new); +EXPORT_SYMBOL(snd_vx_setup_firmware); +EXPORT_SYMBOL(snd_vx_free_firmware); EXPORT_SYMBOL(snd_vx_irq_handler); EXPORT_SYMBOL(snd_vx_delay); EXPORT_SYMBOL(snd_vx_dsp_boot); EXPORT_SYMBOL(snd_vx_dsp_load); EXPORT_SYMBOL(snd_vx_load_boot_image); -#ifdef CONFIG_PM -EXPORT_SYMBOL(snd_vx_suspend); -EXPORT_SYMBOL(snd_vx_resume); -#endif diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index 7e6cedb41..3a3228b18 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig @@ -3,6 +3,16 @@ menu "ISA devices" depends on SND!=n && ISA +config SND_AD1848_LIB + tristate + select SND_PCM + select SND_GENERIC_PM + +config SND_CS4231_LIB + tristate + select SND_PCM + select SND_GENERIC_PM + config SND_AD1816A tristate "Analog Devices SoundPort AD1816A" depends on SND && ISAPNP @@ -19,7 +29,7 @@ config SND_AD1816A config SND_AD1848 tristate "Generic AD1848/CS4248 driver" depends on SND - select SND_PCM + select SND_AD1848_LIB help Say Y here to include support for AD1848 (Analog Devices) or CS4248 (Cirrus Logic - Crystal Semiconductors) chips. @@ -34,7 +44,7 @@ config SND_CS4231 tristate "Generic Cirrus Logic CS4231 driver" depends on SND select SND_MPU401_UART - select SND_PCM + select SND_CS4231_LIB help Say Y here to include support for CS4231 chips from Cirrus Logic - Crystal Semiconductors. @@ -47,7 +57,7 @@ config SND_CS4232 depends on SND select SND_OPL3_LIB select SND_MPU401_UART - select SND_PCM + select SND_CS4231_LIB help Say Y here to include support for CS4232 chips from Cirrus Logic - Crystal Semiconductors. @@ -60,7 +70,7 @@ config SND_CS4236 depends on SND select SND_OPL3_LIB select SND_MPU401_UART - select SND_PCM + select SND_CS4231_LIB help Say Y to include support for CS4235,CS4236,CS4237B,CS4238B, CS4239 chips from Cirrus Logic - Crystal Semiconductors. @@ -98,6 +108,7 @@ config SND_ES18XX select SND_OPL3_LIB select SND_MPU401_UART select SND_PCM + select SND_GENERIC_PM help Say Y here to include support for ESS AudioDrive ES18xx chips. @@ -138,7 +149,7 @@ config SND_GUSMAX tristate "Gravis UltraSound MAX" depends on SND select SND_RAWMIDI - select SND_PCM + select SND_CS4231_LIB select SND_GUS_SYNTH help Say Y here to include support for Gravis UltraSound MAX @@ -151,8 +162,9 @@ config SND_INTERWAVE tristate "AMD InterWave, Gravis UltraSound PnP" depends on SND select SND_RAWMIDI - select SND_PCM + select SND_CS4231_LIB select SND_GUS_SYNTH + select ISAPNP help Say Y here to include support for AMD InterWave based soundcards (Gravis UltraSound Plug & Play, STB SoundRage32, @@ -165,7 +177,7 @@ config SND_INTERWAVE_STB tristate "AMD InterWave + TEA6330T (UltraSound 32-Pro)" depends on SND select SND_RAWMIDI - select SND_PCM + select SND_CS4231_LIB select SND_GUS_SYNTH help Say Y here to include support for AMD InterWave based @@ -181,7 +193,7 @@ config SND_OPTI92X_AD1848 select SND_OPL3_LIB select SND_OPL4_LIB select SND_MPU401_UART - select SND_PCM + select SND_AD1848_LIB help Say Y here to include support for soundcards based on Opti 82C92x or OTI-601 chips and using an AD1848 codec. @@ -195,7 +207,7 @@ config SND_OPTI92X_CS4231 select SND_OPL3_LIB select SND_OPL4_LIB select SND_MPU401_UART - select SND_PCM + select SND_CS4231_LIB help Say Y here to include support for soundcards based on Opti 82C92x chips and using a CS4231 codec. @@ -268,7 +280,7 @@ config SND_WAVEFRONT depends on SND select SND_OPL3_LIB select SND_MPU401_UART - select SND_PCM + select SND_CS4231_LIB help Say Y here to include support for Turtle Beach Maui, Tropez and Tropez+ soundcards based on the Wavefront chip. @@ -294,7 +306,7 @@ config SND_AZT2320 depends on SND && ISAPNP select SND_OPL3_LIB select SND_MPU401_UART - select SND_PCM + select SND_CS4231_LIB help Say Y here to include support for soundcards based on the Aztech Systems AZT2320 chip. @@ -305,7 +317,7 @@ config SND_AZT2320 config SND_CMI8330 tristate "C-Media CMI8330" depends on SND - select SND_PCM + select SND_AD1848_LIB help Say Y here to include support for soundcards based on the C-Media CMI8330 chip. @@ -331,7 +343,7 @@ config SND_OPL3SA2 depends on SND select SND_OPL3_LIB select SND_MPU401_UART - select SND_PCM + select SND_CS4231_LIB help Say Y here to include support for Yamaha OPL3-SA2 and OPL3-SA3 chips. @@ -342,7 +354,7 @@ config SND_OPL3SA2 config SND_SGALAXY tristate "Aztech Sound Galaxy" depends on SND - select SND_PCM + select SND_AD1848_LIB help Say Y here to include support for Aztech Sound Galaxy soundcards. @@ -355,7 +367,7 @@ config SND_SSCAPE depends on SND select SND_HWDEP select SND_MPU401_UART - select SND_PCM + select SND_CS4231_LIB help Say Y here to include support for Ensoniq SoundScape PnP soundcards. diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c index d0a62f71b..8fb3db103 100644 --- a/sound/isa/ad1848/ad1848_lib.c +++ b/sound/isa/ad1848/ad1848_lib.c @@ -119,9 +119,8 @@ void snd_ad1848_out(ad1848_t *chip, #endif } -void snd_ad1848_dout(ad1848_t *chip, - unsigned char reg, - unsigned char value) +static void snd_ad1848_dout(ad1848_t *chip, + unsigned char reg, unsigned char value) { int timeout; @@ -132,7 +131,7 @@ void snd_ad1848_dout(ad1848_t *chip, mb(); } -unsigned char snd_ad1848_in(ad1848_t *chip, unsigned char reg) +static unsigned char snd_ad1848_in(ad1848_t *chip, unsigned char reg) { int timeout; @@ -147,9 +146,9 @@ unsigned char snd_ad1848_in(ad1848_t *chip, unsigned char reg) return inb(AD1848P(chip, REG)); } -#ifdef CONFIG_SND_DEBUG +#if 0 -void snd_ad1848_debug(ad1848_t *chip) +static void snd_ad1848_debug(ad1848_t *chip) { printk("AD1848 REGS: INDEX = 0x%02x ", inb(AD1848P(chip, REGSEL))); printk(" STATUS = 0x%02x\n", inb(AD1848P(chip, STATUS))); @@ -177,7 +176,7 @@ void snd_ad1848_debug(ad1848_t *chip) * AD1848 detection / MCE routines */ -void snd_ad1848_mce_up(ad1848_t *chip) +static void snd_ad1848_mce_up(ad1848_t *chip) { unsigned long flags; int timeout; @@ -198,7 +197,7 @@ void snd_ad1848_mce_up(ad1848_t *chip) spin_unlock_irqrestore(&chip->reg_lock, flags); } -void snd_ad1848_mce_down(ad1848_t *chip) +static void snd_ad1848_mce_down(ad1848_t *chip) { unsigned long flags; int timeout; @@ -584,7 +583,7 @@ static int snd_ad1848_capture_prepare(snd_pcm_substream_t * substream) return 0; } -irqreturn_t snd_ad1848_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t snd_ad1848_interrupt(int irq, void *dev_id, struct pt_regs *regs) { ad1848_t *chip = dev_id; @@ -645,36 +644,28 @@ static void snd_ad1848_thinkpad_twiddle(ad1848_t *chip, int on) { } #ifdef CONFIG_PM -static int snd_ad1848_suspend(snd_card_t *card, unsigned int state) +static int snd_ad1848_suspend(snd_card_t *card, pm_message_t state) { ad1848_t *chip = card->pm_private_data; - if (card->power_state == SNDRV_CTL_POWER_D3hot) - return 0; - snd_pcm_suspend_all(chip->pcm); /* FIXME: save registers? */ if (chip->thinkpad_flag) snd_ad1848_thinkpad_twiddle(chip, 0); - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } -static int snd_ad1848_resume(snd_card_t *card, unsigned int state) +static int snd_ad1848_resume(snd_card_t *card) { ad1848_t *chip = card->pm_private_data; - if (card->power_state == SNDRV_CTL_POWER_D0) - return 0; - if (chip->thinkpad_flag) snd_ad1848_thinkpad_twiddle(chip, 1); /* FIXME: restore registers? */ - snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; } #endif /* CONFIG_PM */ @@ -1264,12 +1255,7 @@ int snd_ad1848_mixer(ad1848_t *chip) return 0; } -EXPORT_SYMBOL(snd_ad1848_in); EXPORT_SYMBOL(snd_ad1848_out); -EXPORT_SYMBOL(snd_ad1848_dout); -EXPORT_SYMBOL(snd_ad1848_mce_up); -EXPORT_SYMBOL(snd_ad1848_mce_down); -EXPORT_SYMBOL(snd_ad1848_interrupt); EXPORT_SYMBOL(snd_ad1848_create); EXPORT_SYMBOL(snd_ad1848_pcm); EXPORT_SYMBOL(snd_ad1848_get_pcm_ops); diff --git a/sound/isa/als100.c b/sound/isa/als100.c index f0f1c4251..ac8f13664 100644 --- a/sound/isa/als100.c +++ b/sound/isa/als100.c @@ -94,6 +94,8 @@ static struct pnp_card_device_id snd_als100_pnpids[] = { { .id = "ALS0120", .devs = { { "@@@2001" }, { "@X@2001" }, { "@H@2001" } } }, /* ALS200 */ { .id = "ALS0200", .devs = { { "@@@0020" }, { "@X@0020" }, { "@H@0001" } } }, + /* ALS200 OEM */ + { .id = "ALS0200", .devs = { { "@@@0020" }, { "@X@0020" }, { "@H@0020" } } }, /* RTL3000 */ { .id = "RTL3000", .devs = { { "@@@2001" }, { "@X@2001" }, { "@H@2001" } } }, { .id = "", } /* end */ @@ -119,7 +121,7 @@ static int __devinit snd_card_als100_pnp(int dev, struct snd_card_als100 *acard, return -ENODEV; } acard->devmpu = pnp_request_card_device(card, id->devs[1].id, acard->dev); - acard->devopl = pnp_request_card_device(card, id->devs[2].id, acard->devmpu); + acard->devopl = pnp_request_card_device(card, id->devs[2].id, acard->dev); pdev = acard->dev; diff --git a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c index d323e3637..3e7a2a33a 100644 --- a/sound/isa/cs423x/cs4231_lib.c +++ b/sound/isa/cs423x/cs4231_lib.c @@ -166,8 +166,8 @@ static __CS4231_INLINE__ u8 cs4231_inb(cs4231_t *chip, u8 offset) #endif } -void snd_cs4231_outm(cs4231_t *chip, unsigned char reg, - unsigned char mask, unsigned char value) +static void snd_cs4231_outm(cs4231_t *chip, unsigned char reg, + unsigned char mask, unsigned char value) { int timeout; unsigned char tmp; @@ -271,9 +271,9 @@ unsigned char snd_cs4236_ext_in(cs4231_t *chip, unsigned char reg) #endif } -#ifdef CONFIG_SND_DEBUG +#if 0 -void snd_cs4231_debug(cs4231_t *chip) +static void snd_cs4231_debug(cs4231_t *chip) { printk("CS4231 REGS: INDEX = 0x%02x ", cs4231_inb(chip, CS4231P(REGSEL))); printk(" STATUS = 0x%02x\n", cs4231_inb(chip, CS4231P(STATUS))); @@ -356,7 +356,6 @@ void snd_cs4231_mce_down(cs4231_t *chip) { unsigned long flags; int timeout; - signed long time; snd_cs4231_busy_wait(chip); #if 0 @@ -390,34 +389,26 @@ void snd_cs4231_mce_down(cs4231_t *chip) #if 0 printk("(2) timeout = %i, jiffies = %li\n", timeout, jiffies); #endif - timeout = HZ / 4 / 2; - time = 2; + /* in 10 ms increments, check condition, up to 250 ms */ + timeout = 25; while (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) { - set_current_state(TASK_INTERRUPTIBLE); - time = schedule_timeout(time); - if (time > 0) - continue; - time = 2; if (--timeout < 0) { snd_printk("mce_down - auto calibration time out (2)\n"); return; } + msleep(10); } #if 0 printk("(3) jiffies = %li\n", jiffies); #endif - timeout = HZ / 10 / 2; - time = 2; + /* in 10 ms increments, check condition, up to 100 ms */ + timeout = 10; while (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) { - set_current_state(TASK_INTERRUPTIBLE); - time = schedule_timeout(time); - if (time > 0) - continue; - time = 2; if (--timeout < 0) { snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n"); return; } + msleep(10); } #if 0 printk("(4) jiffies = %li\n", jiffies); @@ -694,7 +685,7 @@ static void snd_cs4231_init(cs4231_t *chip) snd_cs4231_mce_down(chip); -#ifdef SNDRV_DEBUGq_MCE +#ifdef SNDRV_DEBUG_MCE snd_printk("init: (1)\n"); #endif snd_cs4231_mce_up(chip); @@ -1035,7 +1026,7 @@ static snd_pcm_uframes_t snd_cs4231_capture_pointer(snd_pcm_substream_t * substr */ -int snd_cs4231_probe(cs4231_t *chip) +static int snd_cs4231_probe(cs4231_t *chip) { unsigned long flags; int i, id, rev; @@ -1403,23 +1394,19 @@ static void snd_cs4231_resume(cs4231_t *chip) #endif } -static int snd_cs4231_pm_suspend(snd_card_t *card, unsigned int state) +static int snd_cs4231_pm_suspend(snd_card_t *card, pm_message_t state) { cs4231_t *chip = card->pm_private_data; - if (chip->suspend) { + if (chip->suspend) chip->suspend(chip); - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - } return 0; } -static int snd_cs4231_pm_resume(snd_card_t *card, unsigned int state) +static int snd_cs4231_pm_resume(snd_card_t *card) { cs4231_t *chip = card->pm_private_data; - if (chip->resume) { + if (chip->resume) chip->resume(chip); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - } return 0; } #endif /* CONFIG_PM */ @@ -1943,7 +1930,6 @@ int snd_cs4231_mixer(cs4231_t *chip) EXPORT_SYMBOL(snd_cs4231_out); EXPORT_SYMBOL(snd_cs4231_in); -EXPORT_SYMBOL(snd_cs4231_outm); EXPORT_SYMBOL(snd_cs4236_ext_out); EXPORT_SYMBOL(snd_cs4236_ext_in); EXPORT_SYMBOL(snd_cs4231_mce_up); diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index 79e32744e..e745a54e0 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c @@ -242,6 +242,8 @@ static struct pnp_card_device_id snd_cs423x_pnpids[] = { { .id = "CSCd937", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, /* CS4235 without MPU401 */ { .id = "CSCe825", .devs = { { "CSC0100" }, { "CSC0110" } } }, + /* Unknown SiS530 - CS4235 */ + { .id = "CSC4825", .devs = { { "CSC0100" }, { "CSC0110" } } }, /* IBM IntelliStation M Pro 6898 11U - CS4236B */ { .id = "CSCe835", .devs = { { "CSC0000" }, { "CSC0010" } } }, /* IBM PC 300PL Onboard - CS4236B */ diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index 9b0d5a9ec..1d832b2ad 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c @@ -268,7 +268,7 @@ static int snd_es18xx_bits(es18xx_t *chip, unsigned char reg, return ret; } -inline void snd_es18xx_mixer_write(es18xx_t *chip, +static inline void snd_es18xx_mixer_write(es18xx_t *chip, unsigned char reg, unsigned char data) { unsigned long flags; @@ -281,7 +281,7 @@ inline void snd_es18xx_mixer_write(es18xx_t *chip, #endif } -inline int snd_es18xx_mixer_read(es18xx_t *chip, unsigned char reg) +static inline int snd_es18xx_mixer_read(es18xx_t *chip, unsigned char reg) { unsigned long flags; int data; @@ -1569,7 +1569,7 @@ static void snd_es18xx_pcm_free(snd_pcm_t *pcm) snd_pcm_lib_preallocate_free_for_all(pcm); } -int __devinit snd_es18xx_pcm(es18xx_t *chip, int device, snd_pcm_t ** rpcm) +static int __devinit snd_es18xx_pcm(es18xx_t *chip, int device, snd_pcm_t ** rpcm) { snd_pcm_t *pcm; char str[16]; @@ -1612,7 +1612,7 @@ int __devinit snd_es18xx_pcm(es18xx_t *chip, int device, snd_pcm_t ** rpcm) /* Power Management support functions */ #ifdef CONFIG_PM -static int snd_es18xx_suspend(snd_card_t *card, unsigned int state) +static int snd_es18xx_suspend(snd_card_t *card, pm_message_t state) { es18xx_t *chip = card->pm_private_data; @@ -1624,18 +1624,16 @@ static int snd_es18xx_suspend(snd_card_t *card, unsigned int state) snd_es18xx_write(chip, ES18XX_PM, chip->pm_reg); snd_es18xx_write(chip, ES18XX_PM, chip->pm_reg ^= ES18XX_PM_SUS); - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } -static int snd_es18xx_resume(snd_card_t *card, unsigned int state) +static int snd_es18xx_resume(snd_card_t *card) { es18xx_t *chip = card->pm_private_data; /* restore PM register, we won't wake till (not 0x07) i/o activity though */ snd_es18xx_write(chip, ES18XX_PM, chip->pm_reg ^= ES18XX_PM_FM); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; } #endif /* CONFIG_PM */ @@ -1849,7 +1847,7 @@ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this car static int isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; #endif static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260,0x280 */ -#ifndef CONFIG_PNP_ +#ifndef CONFIG_PNP static long mpu_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1}; #else static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; @@ -1988,7 +1986,7 @@ static int __devinit snd_audiodrive_pnp(int dev, struct snd_audiodrive *acard, kfree(cfg); return 0; } -#endif /* CONFIG_PNP_ */ +#endif /* CONFIG_PNP */ static int __devinit snd_audiodrive_probe(int dev, struct pnp_card_link *pcard, const struct pnp_card_device_id *pid) diff --git a/sound/isa/gus/gus_lfo.c b/sound/isa/gus/gus_lfo.c deleted file mode 100644 index 94d068850..000000000 --- a/sound/isa/gus/gus_lfo.c +++ /dev/null @@ -1,429 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@suse.cz> - * Routines for control of LFO generators (tremolo & vibrato) for - * GF1/InterWave chips... - * - * - * 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 <sound/core.h> -#include <sound/gus.h> - -/* - * called by engine routines - */ - -static signed char snd_gf1_lfo_compute_value(snd_gus_card_t * gus, - unsigned char *ptr) -{ - unsigned int twaveinc, depth_delta; - signed int result; - unsigned short control, twave, depth, depth_final; - unsigned char *ptr1; - - control = *(unsigned short *) (ptr + 0x00); - ptr1 = ptr + ((control & 0x4000) >> 12); - /* 1. add TWAVEINC to TWAVE and write the result back */ - /* LFO update rate is 689Hz, effect timer is in ms */ - if (gus->gf1.timer_slave) - twaveinc = (689 * gus->gf1.timer_master_gus->gf1.effect_timer) / 1000; - else - twaveinc = (689 * gus->gf1.effect_timer) / 1000; - if (!twaveinc) - twaveinc++; -#if 0 - printk("twaveinc = 0x%x, effect_timer = %i\n", twaveinc, gus->gf1.effect_timer); -#endif - - depth = *(unsigned short *) (ptr1 + 0x0a); - depth_final = *(unsigned char *) (ptr + 0x02) << 5; - if (depth != depth_final) { - depth_delta = ((twaveinc * *(ptr + 0x03)) + *(unsigned short *) (ptr + 0x04)); - *(unsigned short *) (ptr + 0x04) = depth_delta % 8000; - depth_delta /= 8000; - if (depth < depth_final) { - if (depth + depth_delta > depth_final) - depth = depth_final; - else - depth += depth_delta; - } - if (depth > depth_final) { - if (depth - depth_delta < depth_final) - depth = depth_final; - else - depth -= depth_delta; - } - *(unsigned short *) (ptr1 + 0x0a) = depth; - } - twaveinc *= (unsigned int) control & 0x7ff; - twaveinc += *(unsigned short *) (ptr + 0x06); - *(unsigned short *) (ptr + 0x06) = twaveinc % 1000; - - twave = *(unsigned short *) (ptr1 + 0x08); - twave += (unsigned short) (twaveinc / (unsigned int) 1000); - *(unsigned short *) (ptr1 + 0x08) = twave; - - if (!(control & 0x2000)) { - /* 2. if shift is low */ - if (twave & 0x4000) { /* bit 14 high -> invert TWAVE 13-0 */ - twave ^= 0x3fff; - twave &= ~0x4000; - } - /* TWAVE bit 15 is exclusive or'd with the invert bit (12) */ - twave ^= (control & 0x1000) << 3; - } else { - /* 2. if shift is high */ - if (twave & 0x8000) /* bit 15 high -> invert TWAVE 14-0 */ - twave ^= 0x7fff; - /* the invert bit (12) is used as sign bit */ - if (control & 0x1000) - twave |= 0x8000; - else - twave &= ~0x8000; - } - /* 3. multiply the 14-bit LFO waveform magnitude by 13-bit DEPTH */ -#if 0 - printk("c=0x%x,tw=0x%x,to=0x%x,d=0x%x,df=0x%x,di=0x%x,r=0x%x,r1=%i\n", - control, twave, - *(unsigned short *) (ptr1 + 0x08), - depth, depth_final, *(ptr + 0x03), - (twave & 0x7fff) * depth, ((twave & 0x7fff) * depth) >> 21); -#endif - result = (twave & 0x7fff) * depth; - if (result) { - /* shift */ - result >>= 21; - result &= 0x3f; - } - /* add sign */ - if (twave & 0x8000) - result = -result; -#if 0 - printk("lfo final value = %i\n", result); -#endif - return result; -} - -static void snd_gf1_lfo_register_setup(snd_gus_card_t * gus, - snd_gf1_voice_t * voice, - int lfo_type) -{ - unsigned long flags; - - if (gus->gf1.enh_mode) { - CLI(&flags); - gf1_select_voice(gus, voice->number); - if (lfo_type & 1) { - snd_gf1_write8(gus, GF1_VB_FREQUENCY_LFO, voice->lfo_fc); - voice->lfo_fc = 0; - } - if (lfo_type & 2) { - snd_gf1_write8(gus, GF1_VB_VOLUME_LFO, voice->lfo_volume); - voice->lfo_volume = 0; - } - STI(&flags); - } else { - /* - * ok.. with old GF1 chip can be only vibrato emulated... - * volume register can be in volume ramp state, so tremolo isn't simple.. - */ - if (!(lfo_type & 1)) - return; -#if 0 - if (voice->lfo_fc) - printk("setup - %i = %i\n", voice->number, voice->lfo_fc); -#endif - CLI(&flags); - gf1_select_voice(gus, voice->number); - snd_gf1_write16(gus, GF1_VW_FREQUENCY, voice->fc_register + voice->lfo_fc); - STI(&flags); - } -} - -void snd_gf1_lfo_effect_interrupt(snd_gus_card_t * gus, snd_gf1_voice_t * voice) -{ - unsigned char *ptr; - -#if 0 - if (voice->number != 0) - return; -#endif - ptr = gus->gf1.lfos + ((voice->number) << 5); - /* 1. vibrato */ - if (*(unsigned short *) (ptr + 0x00) & 0x8000) - voice->lfo_fc = snd_gf1_lfo_compute_value(gus, ptr); - /* 2. tremolo */ - ptr += 16; - if (*(unsigned short *) (ptr + 0x00) & 0x8000) - voice->lfo_volume = snd_gf1_lfo_compute_value(gus, ptr); - /* 3. register setup */ - snd_gf1_lfo_register_setup(gus, voice, 3); -} - -/* - - */ - -void snd_gf1_lfo_init(snd_gus_card_t * gus) -{ - if (gus->gf1.hw_lfo) { - snd_gf1_i_write16(gus, GF1_GW_LFO_BASE, 0x0000); - snd_gf1_dram_setmem(gus, 0, 0x0000, 1024); - /* now enable LFO */ - snd_gf1_i_write8(gus, GF1_GB_GLOBAL_MODE, snd_gf1_i_look8(gus, GF1_GB_GLOBAL_MODE) | 0x02); - } - if (gus->gf1.sw_lfo) { -#if 1 - gus->gf1.lfos = snd_calloc(1024); - if (!gus->gf1.lfos) -#endif - gus->gf1.sw_lfo = 0; - } -} - -void snd_gf1_lfo_done(snd_gus_card_t * gus) -{ - if (gus->gf1.sw_lfo) { - if (gus->gf1.lfos) { - snd_gf1_free(gus->gf1.lfos, 1024); - gus->gf1.lfos = NULL; - } - } -} - -void snd_gf1_lfo_program(snd_gus_card_t * gus, int voice, int lfo_type, - struct ULTRA_STRU_IW_LFO_PROGRAM *program) -{ - unsigned int lfo_addr, wave_select; - - wave_select = (program->freq_and_control & 0x4000) >> 12; - lfo_addr = (voice << 5) | (lfo_type << 4); - if (gus->gf1.hw_lfo) { -#if 0 - printk("LMCI = 0x%x\n", snd_gf1_i_look8(gus, 0x53)); - printk("lfo_program: lfo_addr=0x%x,wave_sel=0x%x,fac=0x%x,df=0x%x,di=0x%x,twave=0x%x,depth=0x%x\n", - lfo_addr, wave_select, - program->freq_and_control, - program->depth_final, - program->depth_inc, - program->twave, - program->depth); -#endif - snd_gf1_poke(gus, lfo_addr + 0x02, program->depth_final); - snd_gf1_poke(gus, lfo_addr + 0x03, program->depth_inc); - snd_gf1_pokew(gus, lfo_addr + 0x08 + wave_select, program->twave); - snd_gf1_pokew(gus, lfo_addr + 0x0a + wave_select, program->depth); - snd_gf1_pokew(gus, lfo_addr + 0x00, program->freq_and_control); -#if 0 - { - int i = 0; - for (i = 0; i < 16; i++) - printk("%02x:", snd_gf1_peek(gus, lfo_addr + i)); - printk("\n"); - } -#endif - } - if (gus->gf1.sw_lfo) { - unsigned char *ptr = gus->gf1.lfos + lfo_addr; - - *(ptr + 0x02) = program->depth_final; - *(ptr + 0x03) = program->depth_inc; - *(unsigned short *) (ptr + 0x08 + wave_select) = program->twave; - *(unsigned short *) (ptr + 0x0a + wave_select) = program->depth; - *(unsigned short *) (ptr + 0x00) = program->freq_and_control; - } -} - -void snd_gf1_lfo_enable(snd_gus_card_t * gus, int voice, int lfo_type) -{ - unsigned int lfo_addr; - - lfo_addr = (voice << 5) | (lfo_type << 4); - if (gus->gf1.hw_lfo) - snd_gf1_pokew(gus, lfo_addr + 0x00, snd_gf1_peekw(gus, lfo_addr + 0x00) | 0x8000); - if (gus->gf1.sw_lfo) { - unsigned char *ptr = gus->gf1.lfos + lfo_addr; - - *(unsigned short *) (ptr + 0x00) |= 0x8000; - } -} - -void snd_gf1_lfo_disable(snd_gus_card_t * gus, int voice, int lfo_type) -{ - unsigned int lfo_addr; - - lfo_addr = (voice << 5) | (lfo_type << 4); - if (gus->gf1.hw_lfo) - snd_gf1_pokew(gus, lfo_addr + 0x00, - snd_gf1_peekw(gus, lfo_addr + 0x00) & ~0x8000); - if (gus->gf1.sw_lfo) { - unsigned char *ptr = gus->gf1.lfos + lfo_addr; - - *(unsigned short *) (ptr + 0x00) &= ~0x8000; - } -} - -void snd_gf1_lfo_change_freq(snd_gus_card_t * gus, int voice, - int lfo_type, int freq) -{ - unsigned int lfo_addr; - - lfo_addr = (voice << 5) | (lfo_type << 4); - if (gus->gf1.hw_lfo) - snd_gf1_pokew(gus, lfo_addr + 0x00, - (snd_gf1_peekw(gus, lfo_addr + 0x00) & ~0x7ff) | (freq & 0x7ff)); - if (gus->gf1.sw_lfo) { - unsigned long flags; - unsigned char *ptr = gus->gf1.lfos + lfo_addr; - - CLI(&flags); - *(unsigned short *) (ptr + 0x00) &= ~0x7ff; - *(unsigned short *) (ptr + 0x00) |= freq & 0x7ff; - STI(&flags); - } -} - -void snd_gf1_lfo_change_depth(snd_gus_card_t * gus, int voice, - int lfo_type, int depth) -{ - unsigned long flags; - unsigned int lfo_addr; - unsigned short control = 0; - unsigned char *ptr; - - lfo_addr = (voice << 5) | (lfo_type << 4); - ptr = gus->gf1.lfos + lfo_addr; - if (gus->gf1.hw_lfo) - control = snd_gf1_peekw(gus, lfo_addr + 0x00); - if (gus->gf1.sw_lfo) - control = *(unsigned short *) (ptr + 0x00); - if (depth < 0) { - control |= 0x1000; - depth = -depth; - } else - control &= ~0x1000; - if (gus->gf1.hw_lfo) { - CLI(&flags); - snd_gf1_poke(gus, lfo_addr + 0x02, (unsigned char) depth); - snd_gf1_pokew(gus, lfo_addr + 0x0a + ((control & 0x4000) >> 12), depth << 5); - snd_gf1_pokew(gus, lfo_addr + 0x00, control); - STI(&flags); - } - if (gus->gf1.sw_lfo) { - unsigned char *ptr = gus->gf1.lfos + lfo_addr; - - CLI(&flags); - *(ptr + 0x02) = (unsigned char) depth; - *(unsigned short *) (ptr + 0x0a + ((control & 0x4000) >> 12)) = depth << 5; - *(unsigned short *) (ptr + 0x00) = control; - STI(&flags); - } -} - -void snd_gf1_lfo_setup(snd_gus_card_t * gus, int voice, int lfo_type, - int freq, int current_depth, int depth, int sweep, - int shape) -{ - struct ULTRA_STRU_IW_LFO_PROGRAM program; - - program.freq_and_control = 0x8000 | (freq & 0x7ff); - if (shape & ULTRA_STRU_IW_LFO_SHAPE_POSTRIANGLE) - program.freq_and_control |= 0x2000; - if (depth < 0) { - program.freq_and_control |= 0x1000; - depth = -depth; - } - program.twave = 0; - program.depth = current_depth; - program.depth_final = depth; - if (sweep) { - program.depth_inc = (unsigned char) (((int) ((depth << 5) - current_depth) << 9) / (sweep * 4410L)); - if (!program.depth_inc) - program.depth_inc++; - } else - program.depth = (unsigned short) (depth << 5); - snd_gf1_lfo_program(gus, voice, lfo_type, &program); -} - -void snd_gf1_lfo_shutdown(snd_gus_card_t * gus, int voice, int lfo_type) -{ - unsigned long flags; - unsigned int lfo_addr; - - lfo_addr = (voice << 5) | (lfo_type << 4); - if (gus->gf1.hw_lfo) { - snd_gf1_pokew(gus, lfo_addr + 0x00, 0x0000); - CLI(&flags); - gf1_select_voice(gus, voice); - snd_gf1_write8(gus, lfo_type == ULTRA_LFO_VIBRATO ? GF1_VB_FREQUENCY_LFO : GF1_VB_VOLUME_LFO, 0); - STI(&flags); - } - if (gus->gf1.sw_lfo) { - unsigned char *ptr = gus->gf1.lfos + lfo_addr; - snd_gf1_voice_t *pvoice; - - *(unsigned short *) (ptr + 0x00) = 0; - *(unsigned short *) (ptr + 0x04) = 0; - *(unsigned short *) (ptr + 0x06) = 0; - if (gus->gf1.syn_voices) { - pvoice = gus->gf1.syn_voices + voice; - if (lfo_type == ULTRA_LFO_VIBRATO) - pvoice->lfo_fc = 0; - else - pvoice->lfo_volume = 0; - snd_gf1_lfo_register_setup(gus, pvoice, lfo_type == ULTRA_LFO_VIBRATO ? 1 : 2); - } else if (gus->gf1.enh_mode) { - CLI(&flags); - gf1_select_voice(gus, voice); - snd_gf1_write8(gus, lfo_type == ULTRA_LFO_VIBRATO ? GF1_VB_FREQUENCY_LFO : GF1_VB_VOLUME_LFO, 0); - STI(&flags); - } - } -} - -void snd_gf1_lfo_command(snd_gus_card_t * gus, int voice, unsigned char *data) -{ - int lfo_type; - int lfo_command; - int temp1, temp2; - - lfo_type = *data >> 7; - lfo_command = *data & 0x7f; - switch (lfo_command) { - case ULTRA_LFO_SETUP: /* setup */ - temp1 = snd_gf1_get_word(data, 2); - temp2 = snd_gf1_get_word(data, 4); - snd_gf1_lfo_setup(gus, voice, lfo_type, temp1 & 0x7ff, 0, temp2 > 255 ? 255 : temp2, snd_gf1_get_byte(data, 1), (temp1 & 0x2000) >> 13); - break; - case ULTRA_LFO_FREQ: /* freq */ - snd_gf1_lfo_change_depth(gus, voice, lfo_type, snd_gf1_get_word(data, 2)); - break; - case ULTRA_LFO_DEPTH: /* depth */ - snd_gf1_lfo_change_freq(gus, voice, lfo_type, snd_gf1_get_word(data, 2)); - break; - case ULTRA_LFO_ENABLE: /* enable */ - snd_gf1_lfo_enable(gus, voice, lfo_type); - break; - case ULTRA_LFO_DISABLE: /* disable */ - snd_gf1_lfo_disable(gus, voice, lfo_type); - break; - case ULTRA_LFO_SHUTDOWN: /* shutdown */ - snd_gf1_lfo_shutdown(gus, voice, lfo_type); - break; - } -} diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index c3f2c6b5c..46e867dab 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c @@ -79,8 +79,10 @@ module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for InterWave soundcard."); module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable InterWave soundcard."); +#ifdef CONFIG_PNP module_param_array(isapnp, bool, NULL, 0444); MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard."); +#endif module_param_array(port, long, NULL, 0444); MODULE_PARM_DESC(port, "Port # for InterWave driver."); #ifdef SNDRV_STB diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index d7462cc8a..95c7b3e53 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c @@ -341,7 +341,7 @@ static int snd_opl3sa2_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t return 0; } -int snd_opl3sa2_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_opl3sa2_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { opl3sa2_t *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; @@ -358,7 +358,7 @@ int snd_opl3sa2_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * uco return 0; } -int snd_opl3sa2_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_opl3sa2_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { opl3sa2_t *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; @@ -388,7 +388,7 @@ int snd_opl3sa2_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * uco .get = snd_opl3sa2_get_double, .put = snd_opl3sa2_put_double, \ .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) } -int snd_opl3sa2_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) +static int snd_opl3sa2_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) { int mask = (kcontrol->private_value >> 24) & 0xff; @@ -399,7 +399,7 @@ int snd_opl3sa2_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinf return 0; } -int snd_opl3sa2_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_opl3sa2_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { opl3sa2_t *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; @@ -421,7 +421,7 @@ int snd_opl3sa2_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * uco return 0; } -int snd_opl3sa2_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_opl3sa2_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { opl3sa2_t *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; @@ -529,7 +529,7 @@ static int __init snd_opl3sa2_mixer(opl3sa2_t *chip) /* Power Management support functions */ #ifdef CONFIG_PM -static int snd_opl3sa2_suspend(snd_card_t *card, unsigned int state) +static int snd_opl3sa2_suspend(snd_card_t *card, pm_message_t state) { opl3sa2_t *chip = card->pm_private_data; @@ -539,11 +539,10 @@ static int snd_opl3sa2_suspend(snd_card_t *card, unsigned int state) /* power down */ snd_opl3sa2_write(chip, OPL3SA2_PM_CTRL, OPL3SA2_PM_D3); - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } -static int snd_opl3sa2_resume(snd_card_t *card, unsigned int state) +static int snd_opl3sa2_resume(snd_card_t *card) { opl3sa2_t *chip = card->pm_private_data; int i; @@ -563,7 +562,6 @@ static int snd_opl3sa2_resume(snd_card_t *card, unsigned int state) /* restore cs4231 */ chip->cs4231_resume(chip->cs4231); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; } #endif /* CONFIG_PM */ @@ -789,7 +787,7 @@ static int __devinit snd_opl3sa2_pnp_detect(struct pnp_card_link *card, int res; for ( ; dev < SNDRV_CARDS; dev++) { - if (!enable[dev] && !isapnp[dev]) + if (!enable[dev] || !isapnp[dev]) continue; res = snd_opl3sa2_probe(dev, card, id); if (res < 0) diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index c4fbf6fff..411a702d8 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -1095,7 +1095,7 @@ static void snd_opti93x_overrange(opti93x_t *chip) spin_unlock_irqrestore(&chip->lock, flags); } -irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id, struct pt_regs *regs) { opti93x_t *codec = dev_id; unsigned char status; @@ -1263,9 +1263,9 @@ static const char *snd_opti93x_chip_id(opti93x_t *codec) } } -int snd_opti93x_create(snd_card_t *card, opti9xx_t *chip, - int dma1, int dma2, - opti93x_t **rcodec) +static int snd_opti93x_create(snd_card_t *card, opti9xx_t *chip, + int dma1, int dma2, + opti93x_t **rcodec) { static snd_device_ops_t ops = { .dev_free = snd_opti93x_dev_free, @@ -1359,7 +1359,7 @@ static void snd_opti93x_pcm_free(snd_pcm_t *pcm) snd_pcm_lib_preallocate_free_for_all(pcm); } -int snd_opti93x_pcm(opti93x_t *codec, int device, snd_pcm_t **rpcm) +static int snd_opti93x_pcm(opti93x_t *codec, int device, snd_pcm_t **rpcm) { int error; snd_pcm_t *pcm; @@ -1603,7 +1603,7 @@ OPTi93X_DOUBLE("Capture Volume", 0, OPTi93X_MIXOUT_LEFT, OPTi93X_MIXOUT_RIGHT, 0 } }; -int snd_opti93x_mixer(opti93x_t *chip) +static int snd_opti93x_mixer(opti93x_t *chip) { snd_card_t *card; snd_kcontrol_new_t knew; diff --git a/sound/isa/sb/emu8000_patch.c b/sound/isa/sb/emu8000_patch.c index cea56e016..4afc4a1bc 100644 --- a/sound/isa/sb/emu8000_patch.c +++ b/sound/isa/sb/emu8000_patch.c @@ -183,10 +183,10 @@ snd_emu8000_sample_new(snd_emux_t *rec, snd_sf_sample_t *sp, } if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS) { - if (verify_area(VERIFY_READ, data, sp->v.size)) + if (!access_ok(VERIFY_READ, data, sp->v.size)) return -EFAULT; } else { - if (verify_area(VERIFY_READ, data, sp->v.size * 2)) + if (!access_ok(VERIFY_READ, data, sp->v.size * 2)) return -EFAULT; } diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index 920b5ce5b..3959ed694 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c @@ -487,7 +487,7 @@ static int upload_dma_data(struct soundscape *s, * the userspace pointer ... */ len = min(size, dma.bytes); - __copy_from_user(dma.area, data, len); + len -= __copy_from_user(dma.area, data, len); data += len; size -= len; @@ -571,8 +571,9 @@ static int sscape_upload_bootblock(struct soundscape *sscape, struct sscape_boot if (data < 0) { snd_printk(KERN_ERR "sscape: timeout reading firmware version\n"); ret = -EAGAIN; - } else { - __copy_to_user(&bb->version, &data, sizeof(bb->version)); + } + else if (__copy_to_user(&bb->version, &data, sizeof(bb->version))) { + ret = -EFAULT; } } @@ -591,7 +592,7 @@ static int sscape_upload_microcode(struct soundscape *sscape, { unsigned long flags; char __user *code; - int err, ret; + int err; /* * We are going to have to copy this data into a special @@ -601,12 +602,11 @@ static int sscape_upload_microcode(struct soundscape *sscape, * NOTE: This buffer is 64K long! That's WAY too big to * copy into a stack-temporary anyway. */ - if (get_user(code, &mc->code)) + if ( get_user(code, &mc->code) || + !access_ok(VERIFY_READ, code, SSCAPE_MICROCODE_SIZE) ) return -EFAULT; - if ((err = verify_area(VERIFY_READ, code, SSCAPE_MICROCODE_SIZE)) != 0) - return err; - if ((ret = upload_dma_data(sscape, code, SSCAPE_MICROCODE_SIZE)) == 0) { + if ((err = upload_dma_data(sscape, code, SSCAPE_MICROCODE_SIZE)) == 0) { snd_printk(KERN_INFO "sscape: MIDI firmware loaded\n"); } @@ -616,7 +616,7 @@ static int sscape_upload_microcode(struct soundscape *sscape, initialise_mpu401(sscape->mpu); - return ret; + return err; } /* @@ -673,14 +673,14 @@ static int sscape_hw_ioctl(snd_hwdep_t * hw, struct file *file, * DMA-able buffer before we can upload it. We shall therefore * just check that the data pointer is valid for now ... */ - if ((err = verify_area(VERIFY_READ, bb->code, sizeof(bb->code))) != 0) - return err; + if ( !access_ok(VERIFY_READ, bb->code, sizeof(bb->code)) ) + return -EFAULT; /* * Now check that we can write the firmware version number too... */ - if ((err = verify_area(VERIFY_WRITE, &bb->version, sizeof(bb->version))) != 0) - return err; + if ( !access_ok(VERIFY_WRITE, &bb->version, sizeof(bb->version)) ) + return -EFAULT; err = sscape_upload_bootblock(sscape, bb); } diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c index 3aa25a610..79b022070 100644 --- a/sound/isa/wavefront/wavefront.c +++ b/sound/isa/wavefront/wavefront.c @@ -279,7 +279,7 @@ static irqreturn_t snd_wavefront_ics2115_interrupt(int irq, return IRQ_HANDLED; } -snd_hwdep_t * __devinit +static snd_hwdep_t * __devinit snd_wavefront_new_synth (snd_card_t *card, int hw_dev, snd_wavefront_card_t *acard) @@ -305,7 +305,7 @@ snd_wavefront_new_synth (snd_card_t *card, return wavefront_synth; } -snd_hwdep_t * __devinit +static snd_hwdep_t * __devinit snd_wavefront_new_fx (snd_card_t *card, int hw_dev, snd_wavefront_card_t *acard, @@ -332,7 +332,7 @@ snd_wavefront_new_fx (snd_card_t *card, static snd_wavefront_mpu_id internal_id = internal_mpu; static snd_wavefront_mpu_id external_id = external_mpu; -snd_rawmidi_t * __devinit +static snd_rawmidi_t * __devinit snd_wavefront_new_midi (snd_card_t *card, int midi_dev, snd_wavefront_card_t *acard, diff --git a/sound/isa/wavefront/wavefront_fx.c b/sound/isa/wavefront/wavefront_fx.c index 2d42c694f..0e13623f6 100644 --- a/sound/isa/wavefront/wavefront_fx.c +++ b/sound/isa/wavefront/wavefront_fx.c @@ -537,8 +537,7 @@ snd_wavefront_fx_ioctl (snd_hwdep_t *sdev, struct file *file, r.data[1], /* addr */ r.data[2], /* cnt */ pd); - if (page_data) - kfree(page_data); + kfree(page_data); break; default: diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c index 1d9ee967b..0c3c95100 100644 --- a/sound/isa/wavefront/wavefront_synth.c +++ b/sound/isa/wavefront/wavefront_synth.c @@ -32,58 +32,58 @@ #include <sound/snd_wavefront.h> #include <sound/initval.h> -int wf_raw = 0; /* we normally check for "raw state" to firmware - loading. if non-zero, 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 = 0; /* we normally check for "raw state" to firmware + loading. if non-zero, then during driver loading, the + state of the board is ignored, and we reset the + board and load the firmware anyway. + */ -int fx_raw = 1; /* if this is zero, we'll leave the FX processor in - whatever state it is when the driver is loaded. - The default is to download the microprogram and - associated coefficients to set it up for "default" - operation, whatever that means. - */ - -int debug_default = 0; /* you can set this to control debugging - during driver loading. it takes any combination - of the WF_DEBUG_* flags defined in - wavefront.h - */ +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. + The default is to download the microprogram and + associated coefficients to set it up for "default" + operation, whatever that means. + */ + +static int debug_default = 0; /* you can set this to control debugging + during driver loading. it takes any combination + of the WF_DEBUG_* flags defined in + wavefront.h + */ /* XXX this needs to be made firmware and hardware version dependent */ -char *ospath = "/etc/sound/wavefront.os"; /* where to find a processed - version of the WaveFront OS - */ - -int wait_usecs = 150; /* This magic number seems to give pretty optimal - throughput based on my limited experimentation. - If you want to play around with it and find a better - value, be my guest. Remember, the idea is to - get a number that causes us to just busy wait - for as many WaveFront commands as possible, without - coming up with a number so large that we hog the - whole CPU. - - Specifically, with this number, out of about 134,000 - status waits, only about 250 result in a sleep. - */ - -int sleep_interval = 100; /* HZ/sleep_interval seconds per sleep */ -int sleep_tries = 50; /* number of times we'll try to sleep */ - -int reset_time = 2; /* hundreths of a second we wait after a HW - reset for the expected interrupt. - */ - -int ramcheck_time = 20; /* time in seconds to wait while ROM code - checks on-board RAM. - */ - -int osrun_time = 10; /* time in seconds we wait for the OS to - start running. - */ +static char *ospath = "/etc/sound/wavefront.os"; /* where to find a processed + version of the WaveFront OS + */ + +static int wait_usecs = 150; /* This magic number seems to give pretty optimal + throughput based on my limited experimentation. + If you want to play around with it and find a better + value, be my guest. Remember, the idea is to + get a number that causes us to just busy wait + for as many WaveFront commands as possible, without + coming up with a number so large that we hog the + whole CPU. + + Specifically, with this number, out of about 134,000 + status waits, only about 250 result in a sleep. + */ + +static int sleep_interval = 100; /* HZ/sleep_interval seconds per sleep */ +static int sleep_tries = 50; /* number of times we'll try to sleep */ + +static int reset_time = 2; /* hundreths of a second we wait after a HW + reset for the expected interrupt. + */ + +static int ramcheck_time = 20; /* time in seconds to wait while ROM code + checks on-board RAM. + */ + +static int osrun_time = 10; /* time in seconds we wait for the OS to + start running. + */ module_param(wf_raw, int, 0444); MODULE_PARM_DESC(wf_raw, "if non-zero, assume that we need to boot the OS"); module_param(fx_raw, int, 0444); @@ -1201,7 +1201,11 @@ wavefront_send_multisample (snd_wavefront_t *dev, wavefront_patch_info *header) { int i; int num_samples; - unsigned char msample_hdr[WF_MSAMPLE_BYTES]; + unsigned char *msample_hdr; + + msample_hdr = kmalloc(sizeof(WF_MSAMPLE_BYTES), GFP_KERNEL); + if (! msample_hdr) + return -ENOMEM; munge_int32 (header->number, &msample_hdr[0], 2); @@ -1234,11 +1238,13 @@ wavefront_send_multisample (snd_wavefront_t *dev, wavefront_patch_info *header) (unsigned char *) (long) ((num_samples*2)+3), msample_hdr)) { snd_printk ("download of multisample failed.\n"); + kfree(msample_hdr); return -(EIO); } dev->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_MULTISAMPLE); + kfree(msample_hdr); return (0); } @@ -1356,78 +1362,103 @@ wavefront_find_free_patch (snd_wavefront_t *dev) static int wavefront_load_patch (snd_wavefront_t *dev, const char __user *addr) - { - wavefront_patch_info header; + wavefront_patch_info *header; + int err; - if (copy_from_user (&header, addr, sizeof(wavefront_patch_info) - + header = kmalloc(sizeof(*header), GFP_KERNEL); + if (! header) + return -ENOMEM; + + if (copy_from_user (header, addr, sizeof(wavefront_patch_info) - sizeof(wavefront_any))) { snd_printk ("bad address for load patch.\n"); - return -(EFAULT); + err = -EFAULT; + goto __error; } DPRINT (WF_DEBUG_LOAD_PATCH, "download " "Sample type: %d " "Sample number: %d " "Sample size: %d\n", - header.subkey, - header.number, - header.size); + header->subkey, + header->number, + header->size); - switch (header.subkey) { + switch (header->subkey) { case WF_ST_SAMPLE: /* sample or sample_header, based on patch->size */ - if (copy_from_user (&header.hdr.s, header.hdrptr, - sizeof (wavefront_sample))) - return -EFAULT; + if (copy_from_user (&header->hdr.s, header->hdrptr, + sizeof (wavefront_sample))) { + err = -EFAULT; + break; + } - return wavefront_send_sample (dev, &header, header.dataptr, 0); + err = wavefront_send_sample (dev, header, header->dataptr, 0); + break; case WF_ST_MULTISAMPLE: - if (copy_from_user (&header.hdr.s, header.hdrptr, - sizeof (wavefront_multisample))) - return -EFAULT; - - return wavefront_send_multisample (dev, &header); + if (copy_from_user (&header->hdr.s, header->hdrptr, + sizeof (wavefront_multisample))) { + err = -EFAULT; + break; + } + err = wavefront_send_multisample (dev, header); + break; case WF_ST_ALIAS: - if (copy_from_user (&header.hdr.a, header.hdrptr, - sizeof (wavefront_alias))) - return -EFAULT; + if (copy_from_user (&header->hdr.a, header->hdrptr, + sizeof (wavefront_alias))) { + err = -EFAULT; + break; + } - return wavefront_send_alias (dev, &header); + err = wavefront_send_alias (dev, header); + break; case WF_ST_DRUM: - if (copy_from_user (&header.hdr.d, header.hdrptr, - sizeof (wavefront_drum))) - return -EFAULT; + if (copy_from_user (&header->hdr.d, header->hdrptr, + sizeof (wavefront_drum))) { + err = -EFAULT; + break; + } - return wavefront_send_drum (dev, &header); + err = wavefront_send_drum (dev, header); + break; case WF_ST_PATCH: - if (copy_from_user (&header.hdr.p, header.hdrptr, - sizeof (wavefront_patch))) - return -EFAULT; - - return wavefront_send_patch (dev, &header); + if (copy_from_user (&header->hdr.p, header->hdrptr, + sizeof (wavefront_patch))) { + err = -EFAULT; + break; + } + + err = wavefront_send_patch (dev, header); + break; case WF_ST_PROGRAM: - if (copy_from_user (&header.hdr.pr, header.hdrptr, - sizeof (wavefront_program))) - return -EFAULT; + if (copy_from_user (&header->hdr.pr, header->hdrptr, + sizeof (wavefront_program))) { + err = -EFAULT; + break; + } - return wavefront_send_program (dev, &header); + err = wavefront_send_program (dev, header); + break; default: snd_printk ("unknown patch type %d.\n", - header.subkey); - return -(EINVAL); + header->subkey); + err = -EINVAL; + break; } - return 0; + __error: + kfree(header); + return err; } /*********************************************************************** @@ -1620,8 +1651,9 @@ snd_wavefront_synth_ioctl (snd_hwdep_t *hw, struct file *file, snd_card_t *card; snd_wavefront_t *dev; snd_wavefront_card_t *acard; - wavefront_control wc; + wavefront_control *wc; void __user *argp = (void __user *)arg; + int err; card = (snd_card_t *) hw->card; @@ -1640,14 +1672,19 @@ snd_wavefront_synth_ioctl (snd_hwdep_t *hw, struct file *file, break; case WFCTL_WFCMD: - if (copy_from_user (&wc, argp, sizeof (wc))) - return -EFAULT; - if (wavefront_synth_control (acard, &wc) < 0) { - return -EIO; - } - if (copy_to_user (argp, &wc, sizeof (wc))) - return -EFAULT; - break; + wc = kmalloc(sizeof(*wc), GFP_KERNEL); + if (! wc) + return -ENOMEM; + if (copy_from_user (wc, argp, sizeof (*wc))) + err = -EFAULT; + else if (wavefront_synth_control (acard, wc) < 0) + err = -EIO; + else if (copy_to_user (argp, wc, sizeof (*wc))) + err = -EFAULT; + else + err = 0; + kfree(wc); + return err; default: return -EINVAL; @@ -1709,7 +1746,7 @@ snd_wavefront_internal_interrupt (snd_wavefront_card_t *card) 7 Unused */ -int __init +static int __init snd_wavefront_interrupt_bits (int irq) { @@ -1751,6 +1788,7 @@ wavefront_should_cause_interrupt (snd_wavefront_t *dev, outb (val,port); spin_unlock_irq(&dev->irq_lock); while (1) { + set_current_state(TASK_INTERRUPTIBLE); if ((timeout = schedule_timeout(timeout)) == 0) return; if (dev->irq_ok) @@ -1922,7 +1960,7 @@ wavefront_download_firmware (snd_wavefront_t *dev, char *path) { unsigned char section[WF_SECTION_MAX]; - char section_length; /* yes, just a char; max value is WF_SECTION_MAX */ + signed char section_length; /* yes, just a char; max value is WF_SECTION_MAX */ int section_cnt_downloaded = 0; int fd; int c; @@ -1942,7 +1980,7 @@ wavefront_download_firmware (snd_wavefront_t *dev, char *path) fs = get_fs(); set_fs (get_ds()); - if ((fd = sys_open (path, 0, 0)) < 0) { + if ((fd = sys_open ((char __user *) path, 0, 0)) < 0) { snd_printk ("Unable to load \"%s\".\n", path); return 1; @@ -1951,7 +1989,7 @@ wavefront_download_firmware (snd_wavefront_t *dev, char *path) while (1) { int x; - if ((x = sys_read (fd, §ion_length, sizeof (section_length))) != + if ((x = sys_read (fd, (char __user *) §ion_length, sizeof (section_length))) != sizeof (section_length)) { snd_printk ("firmware read error.\n"); goto failure; @@ -1967,7 +2005,7 @@ wavefront_download_firmware (snd_wavefront_t *dev, char *path) goto failure; } - if (sys_read (fd, section, section_length) != section_length) { + if (sys_read (fd, (char __user *) section, section_length) != section_length) { snd_printk ("firmware section " "read error.\n"); goto failure; diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig index 46022a534..e537bd66a 100644 --- a/sound/oss/Kconfig +++ b/sound/oss/Kconfig @@ -100,9 +100,19 @@ config SOUND_CS4281 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 + help + The BCM91250A has a Crystal CS4297a on synchronous serial + port B (in addition to the DB-9 serial port). Say Y or M + here to enable the sound chip instead of the UART. Also + note that CONFIG_KGDB should not be enabled at the same + time, since it also attempts to use this UART port. + config SOUND_ES1370 tristate "Ensoniq AudioPCI (ES1370)" - depends on SOUND_PRIME!=n && SOUND && PCI && SOUND_GAMEPORT + depends on SOUND_PRIME!=n && SOUND && 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 @@ -115,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!=n && SOUND && 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 @@ -128,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!=n && SOUND && 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 @@ -169,7 +179,7 @@ config SOUND_HARMONY config SOUND_SONICVIBES tristate "S3 SonicVibes" - depends on SOUND_PRIME!=n && SOUND && SOUND_GAMEPORT + depends on SOUND_PRIME!=n && SOUND 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 @@ -194,6 +204,10 @@ config SOUND_HAL2 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 + config SOUND_VRC5477 tristate "NEC Vrc5477 AC97 sound" depends on SOUND_PRIME!=n && DDB5477 && SOUND @@ -202,9 +216,17 @@ config SOUND_VRC5477 integrated, multi-function controller chip for MIPS CPUs. Works with the AC97 codec. +config SOUND_AU1000 + tristate "Au1000 Sound" + depends on SOUND_PRIME!=n && (SOC_AU1000 || SOC_AU1100 || SOC_AU1500) && SOUND + +config SOUND_AU1550_AC97 + tristate "Au1550 AC97 Sound" + depends on SOUND_PRIME!=n && SOC_AU1550 && SOUND + 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!=n && SOUND ---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 @@ -423,7 +445,7 @@ config MSNDPIN_MPU_IRQ depends on MSNDPIN_NONPNP default "0" help - Iinterrupt request number for the Kurzweil daughterboard + Interrupt request number for the Kurzweil daughterboard synthesizer on MultiSound Pinnacle and Fiji sound cards. config MSNDPIN_IDE_IO0 @@ -534,7 +556,7 @@ config SOUND_AD1816 config SOUND_AD1889 tristate "AD1889 based cards (AD1819 codec) (EXPERIMENTAL)" - depends on EXPERIMENTAL && SOUND_OSS + depends on EXPERIMENTAL && SOUND_OSS && PCI help Say M here if you have a sound card based on the Analog Devices AD1889 chip. @@ -717,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 @@ -1081,8 +1103,8 @@ config SOUND_RME96XX depends on SOUND_PRIME!=n && PCI help Say Y or M if you have a Hammerfall or Hammerfall light - multichannel card from RME. If you want to acess advanced - features of the card, read Documentation/sound/oss/rme96xx. + multichannel card from RME. If you want to access advanced + features of the card, read <file:Documentation/sound/oss/rme96xx>. config SOUND_AD1980 tristate "AD1980 front/back switch plugin" diff --git a/sound/oss/Makefile b/sound/oss/Makefile index 226b395bb..db9afb61d 100644 --- a/sound/oss/Makefile +++ b/sound/oss/Makefile @@ -64,6 +64,8 @@ endif obj-$(CONFIG_SOUND_ES1370) += es1370.o obj-$(CONFIG_SOUND_ES1371) += es1371.o ac97_codec.o obj-$(CONFIG_SOUND_VRC5477) += nec_vrc5477.o ac97_codec.o +obj-$(CONFIG_SOUND_AU1000) += au1000.o ac97_codec.o +obj-$(CONFIG_SOUND_AU1550_AC97) += au1550_ac97.o ac97_codec.o obj-$(CONFIG_SOUND_ESSSOLO1) += esssolo1.o obj-$(CONFIG_SOUND_FUSION) += cs46xx.o ac97_codec.o obj-$(CONFIG_SOUND_MAESTRO) += maestro.o @@ -71,6 +73,7 @@ obj-$(CONFIG_SOUND_MAESTRO3) += maestro3.o ac97_codec.o obj-$(CONFIG_SOUND_TRIDENT) += trident.o ac97_codec.o obj-$(CONFIG_SOUND_HARMONY) += harmony.o obj-$(CONFIG_SOUND_EMU10K1) += ac97_codec.o +obj-$(CONFIG_SOUND_BCM_CS4297A) += swarm_cs4297a.o obj-$(CONFIG_SOUND_RME96XX) += rme96xx.o obj-$(CONFIG_SOUND_BT878) += btaudio.o obj-$(CONFIG_SOUND_ALI5455) += ali5455.o ac97_codec.o diff --git a/sound/oss/ac97.c b/sound/oss/ac97.c index d79ff7754..3ba6d91e8 100644 --- a/sound/oss/ac97.c +++ b/sound/oss/ac97.c @@ -133,7 +133,7 @@ ac97_reset (struct ac97_hwint *dev) /* Return the contents of register REG; use the cache if the value in it is valid. Returns a negative error code on failure. */ -int +static int ac97_get_register (struct ac97_hwint *dev, u8 reg) { if (reg > 127 || (reg & 1)) @@ -226,7 +226,7 @@ ac97_scale_from_oss_val (int value, int maxval, int is_stereo, int inv) } } -int +static int ac97_set_mixer (struct ac97_hwint *dev, int oss_channel, u16 oss_value) { int scaled_value; @@ -262,7 +262,7 @@ ac97_set_mixer (struct ac97_hwint *dev, int oss_channel, u16 oss_value) return result; } -int +static int ac97_get_mixer_scaled (struct ac97_hwint *dev, int oss_channel) { struct ac97_chn_desc *channel = ac97_find_chndesc (dev, oss_channel); @@ -292,7 +292,7 @@ ac97_get_mixer_scaled (struct ac97_hwint *dev, int oss_channel) channel->is_inverted); } -int +static int ac97_get_recmask (struct ac97_hwint *dev) { int recReg = ac97_get_register (dev, AC97_RECORD_SELECT); @@ -309,7 +309,7 @@ ac97_get_recmask (struct ac97_hwint *dev) } } -int +static int ac97_set_recmask (struct ac97_hwint *dev, int oss_recmask) { int x; @@ -439,10 +439,7 @@ ac97_mixer_ioctl (struct ac97_hwint *dev, unsigned int cmd, void __user *arg) EXPORT_SYMBOL(ac97_init); EXPORT_SYMBOL(ac97_set_values); -EXPORT_SYMBOL(ac97_set_mixer); -EXPORT_SYMBOL(ac97_get_register); EXPORT_SYMBOL(ac97_put_register); -EXPORT_SYMBOL(ac97_get_mixer_scaled); EXPORT_SYMBOL(ac97_mixer_ioctl); EXPORT_SYMBOL(ac97_reset); MODULE_LICENSE("GPL"); diff --git a/sound/oss/ac97.h b/sound/oss/ac97.h index 3353c84b5..77d454ea3 100644 --- a/sound/oss/ac97.h +++ b/sound/oss/ac97.h @@ -184,26 +184,10 @@ extern int ac97_init (struct ac97_hwint *dev); extern int ac97_set_values (struct ac97_hwint *dev, struct ac97_mixer_value_list *value_list); -/* Sets one mixer channel OSS_CHANNEL to the scaled value OSS_VALUE. - Returns the resulting (rescaled) value, or a negative value - representing an error code. - - Stereo channels have two values in OSS_VALUE (the left value is in the - lower 8 bits, the right value is in the upper 8 bits). */ -extern int ac97_set_mixer (struct ac97_hwint *dev, int oss_channel, - u16 oss_value); - -/* Return the contents of the specified AC97 register REG; it uses the - last-written value if it is available. */ -extern int ac97_get_register (struct ac97_hwint *dev, u8 reg); - /* Writes the specified VALUE to the AC97 register REG in the mixer. Takes care of setting the last-written cache as well. */ extern int ac97_put_register (struct ac97_hwint *dev, u8 reg, u16 value); -/* Returns the last OSS value written to the OSS_CHANNEL mixer channel. */ -extern int ac97_get_mixer_scaled (struct ac97_hwint *dev, int oss_channel); - /* Default ioctl. */ extern int ac97_mixer_ioctl (struct ac97_hwint *dev, unsigned int cmd, void __user * arg); diff --git a/sound/oss/ac97_codec.c b/sound/oss/ac97_codec.c index c883411da..3ecef4689 100644 --- a/sound/oss/ac97_codec.c +++ b/sound/oss/ac97_codec.c @@ -52,6 +52,7 @@ #include <linux/errno.h> #include <linux/bitops.h> #include <linux/delay.h> +#include <linux/pci.h> #include <linux/ac97_codec.h> #include <asm/uaccess.h> @@ -70,6 +71,7 @@ static int wolfson_init03(struct ac97_codec * codec); static int wolfson_init04(struct ac97_codec * codec); static int wolfson_init05(struct ac97_codec * codec); static int wolfson_init11(struct ac97_codec * codec); +static int wolfson_init13(struct ac97_codec * codec); static int tritech_init(struct ac97_codec * codec); static int tritech_maestro_init(struct ac97_codec * codec); static int sigmatel_9708_init(struct ac97_codec *codec); @@ -106,6 +108,7 @@ static struct ac97_ops wolfson_ops03 = { wolfson_init03, NULL, NULL }; static struct ac97_ops wolfson_ops04 = { wolfson_init04, NULL, NULL }; static struct ac97_ops wolfson_ops05 = { wolfson_init05, NULL, NULL }; static struct ac97_ops wolfson_ops11 = { wolfson_init11, NULL, NULL }; +static struct ac97_ops wolfson_ops13 = { wolfson_init13, NULL, NULL }; static struct ac97_ops tritech_ops = { tritech_init, NULL, NULL }; static struct ac97_ops tritech_m_ops = { tritech_maestro_init, NULL, NULL }; static struct ac97_ops sigmatel_9708_ops = { sigmatel_9708_init, NULL, NULL }; @@ -128,6 +131,9 @@ static const struct { {0x41445348, "Analog Devices AD1881A", &null_ops}, {0x41445360, "Analog Devices AD1885", &default_ops}, {0x41445361, "Analog Devices AD1886", &ad1886_ops}, + {0x41445370, "Analog Devices AD1981", &null_ops}, + {0x41445372, "Analog Devices AD1981A", &null_ops}, + {0x41445374, "Analog Devices AD1981B", &null_ops}, {0x41445460, "Analog Devices AD1885", &default_ops}, {0x41445461, "Analog Devices AD1886", &ad1886_ops}, {0x414B4D00, "Asahi Kasei AK4540", &null_ops}, @@ -149,6 +155,7 @@ static const struct { {0x43525931, "Cirrus Logic CS4299 rev A", &crystal_digital_ops}, {0x43525933, "Cirrus Logic CS4299 rev C", &crystal_digital_ops}, {0x43525934, "Cirrus Logic CS4299 rev D", &crystal_digital_ops}, + {0x43585430, "CXT48", &default_ops, AC97_DELUDED_MODEM }, {0x43585442, "CXT66", &default_ops, AC97_DELUDED_MODEM }, {0x44543031, "Diamond Technology DT0893", &default_ops}, {0x45838308, "ESS Allegro ES1988", &null_ops}, @@ -167,12 +174,14 @@ static const struct { {0x574D4C05, "Wolfson WM9705/WM9710", &wolfson_ops05}, {0x574D4C09, "Wolfson WM9709", &null_ops}, {0x574D4C12, "Wolfson WM9711/9712", &wolfson_ops11}, + {0x574D4C13, "Wolfson WM9713", &wolfson_ops13, AC97_DEFAULT_POWER_OFF}, {0x83847600, "SigmaTel STAC????", &null_ops}, {0x83847604, "SigmaTel STAC9701/3/4/5", &null_ops}, {0x83847605, "SigmaTel STAC9704", &null_ops}, {0x83847608, "SigmaTel STAC9708", &sigmatel_9708_ops}, {0x83847609, "SigmaTel STAC9721/23", &sigmatel_9721_ops}, {0x83847644, "SigmaTel STAC9744/45", &sigmatel_9744_ops}, + {0x83847652, "SigmaTel STAC9752/53", &default_ops}, {0x83847656, "SigmaTel STAC9756/57", &sigmatel_9744_ops}, {0x83847666, "SigmaTel STAC9750T", &sigmatel_9744_ops}, {0x83847684, "SigmaTel STAC9783/84?", &null_ops}, @@ -793,6 +802,9 @@ EXPORT_SYMBOL(ac97_release_codec); * Currently codec_wait is used to wait for AC97 codec * reset to complete. * + * Some codecs will power down when a register reset is + * performed. We now check for such codecs. + * * Returns 1 (true) on success, or 0 (false) on failure. */ @@ -806,34 +818,17 @@ int ac97_probe_codec(struct ac97_codec *codec) struct list_head *l; struct ac97_driver *d; - /* probing AC97 codec, AC97 2.0 says that bit 15 of register 0x00 (reset) should - * be read zero. - * - * FIXME: is the following comment outdated? -jgarzik - * Probing of AC97 in this way is not reliable, it is not even SAFE !! - */ - codec->codec_write(codec, AC97_RESET, 0L); - - /* also according to spec, we wait for codec-ready state */ + /* wait for codec-ready state */ if (codec->codec_wait) codec->codec_wait(codec); else udelay(10); - if ((audio = codec->codec_read(codec, AC97_RESET)) & 0x8000) { - printk(KERN_ERR "ac97_codec: %s ac97 codec not present\n", - (codec->id & 0x2) ? (codec->id&1 ? "4th" : "Tertiary") - : (codec->id&1 ? "Secondary": "Primary")); - return 0; - } - - /* probe for Modem Codec */ - codec->modem = ac97_check_modem(codec); - codec->name = NULL; - codec->codec_ops = &default_ops; - + /* will the codec power down if register reset ? */ id1 = codec->codec_read(codec, AC97_VENDOR_ID1); id2 = codec->codec_read(codec, AC97_VENDOR_ID2); + codec->name = NULL; + codec->codec_ops = &null_ops; for (i = 0; i < ARRAY_SIZE(ac97_codec_ids); i++) { if (ac97_codec_ids[i].id == ((id1 << 16) | id2)) { codec->type = ac97_codec_ids[i].id; @@ -845,9 +840,34 @@ int ac97_probe_codec(struct ac97_codec *codec) } codec->model = (id1 << 16) | id2; + if ((codec->flags & AC97_DEFAULT_POWER_OFF) == 0) { + /* reset codec and wait for the ready bit before we continue */ + codec->codec_write(codec, AC97_RESET, 0L); + if (codec->codec_wait) + codec->codec_wait(codec); + else + udelay(10); + } + + /* probing AC97 codec, AC97 2.0 says that bit 15 of register 0x00 (reset) should + * be read zero. + * + * FIXME: is the following comment outdated? -jgarzik + * Probing of AC97 in this way is not reliable, it is not even SAFE !! + */ + if ((audio = codec->codec_read(codec, AC97_RESET)) & 0x8000) { + printk(KERN_ERR "ac97_codec: %s ac97 codec not present\n", + (codec->id & 0x2) ? (codec->id&1 ? "4th" : "Tertiary") + : (codec->id&1 ? "Secondary": "Primary")); + return 0; + } + /* probe for Modem Codec */ + codec->modem = ac97_check_modem(codec); + + /* enable SPDIF */ f = codec->codec_read(codec, AC97_EXTENDED_STATUS); - if(f & 4) + if((codec->codec_ops == &null_ops) && (f & 4)) codec->codec_ops = &default_digital_ops; /* A device which thinks its a modem but isnt */ @@ -916,11 +936,6 @@ static int ac97_init_mixer(struct ac97_codec *codec) codec->recmask_io = ac97_recmask_io; codec->mixer_ioctl = ac97_mixer_ioctl; - /* codec specific initialization for 4-6 channel output or secondary codec stuff */ - if (codec->codec_ops->init != NULL) { - codec->codec_ops->init(codec); - } - /* initialize mixer channel volumes */ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { struct mixer_defaults *md = &mixer_defaults[i]; @@ -931,6 +946,11 @@ static int ac97_init_mixer(struct ac97_codec *codec) ac97_set_mixer(codec, md->mixer, md->value); } + /* codec specific initialization for 4-6 channel output or secondary codec stuff */ + if (codec->codec_ops->init != NULL) { + codec->codec_ops->init(codec); + } + /* * Volume is MUTE only on this device. We have to initialise * it but its useless beyond that. @@ -1086,6 +1106,19 @@ static int wolfson_init11(struct ac97_codec * codec) return 0; } +/* WM9713 */ +static int wolfson_init13(struct ac97_codec * codec) +{ + codec->codec_write(codec, AC97_RECORD_GAIN, 0x00a0); + codec->codec_write(codec, AC97_POWER_CONTROL, 0x0000); + codec->codec_write(codec, AC97_EXTENDED_MODEM_ID, 0xDA00); + codec->codec_write(codec, AC97_EXTEND_MODEM_STAT, 0x3810); + codec->codec_write(codec, AC97_PHONE_VOL, 0x0808); + codec->codec_write(codec, AC97_PCBEEP_VOL, 0x0808); + + return 0; +} + static int tritech_init(struct ac97_codec * codec) { codec->codec_write(codec, 0x26, 0x0300); @@ -1453,5 +1486,92 @@ void ac97_unregister_driver(struct ac97_driver *driver) } EXPORT_SYMBOL_GPL(ac97_unregister_driver); + +static int swap_headphone(int remove_master) +{ + struct list_head *l; + struct ac97_codec *c; + if (remove_master) { + down(&codec_sem); + list_for_each(l, &codecs) + { + c = list_entry(l, struct ac97_codec, list); + if (supported_mixer(c, SOUND_MIXER_PHONEOUT)) + c->supported_mixers &= ~SOUND_MASK_PHONEOUT; + } + up(&codec_sem); + } else + ac97_hw[SOUND_MIXER_PHONEOUT].offset = AC97_MASTER_VOL_STEREO; + + /* Scale values already match */ + ac97_hw[SOUND_MIXER_VOLUME].offset = AC97_MASTER_VOL_MONO; + return 0; +} + +static int apply_quirk(int quirk) +{ + switch (quirk) { + case AC97_TUNE_NONE: + return 0; + case AC97_TUNE_HP_ONLY: + return swap_headphone(1); + case AC97_TUNE_SWAP_HP: + return swap_headphone(0); + case AC97_TUNE_SWAP_SURROUND: + return -ENOSYS; /* not yet implemented */ + case AC97_TUNE_AD_SHARING: + return -ENOSYS; /* not yet implemented */ + case AC97_TUNE_ALC_JACK: + return -ENOSYS; /* not yet implemented */ + } + return -EINVAL; +} + +/** + * ac97_tune_hardware - tune up the hardware + * @pdev: pci_dev pointer + * @quirk: quirk list + * @override: explicit quirk value (overrides if not AC97_TUNE_DEFAULT) + * + * Do some workaround for each pci device, such as renaming of the + * headphone (true line-out) control as "Master". + * The quirk-list must be terminated with a zero-filled entry. + * + * Returns zero if successful, or a negative error code on failure. + */ + +int ac97_tune_hardware(struct pci_dev *pdev, struct ac97_quirk *quirk, int override) +{ + int result; + + if (!quirk) + return -EINVAL; + + if (override != AC97_TUNE_DEFAULT) { + result = apply_quirk(override); + if (result < 0) + printk(KERN_ERR "applying quirk type %d failed (%d)\n", override, result); + return result; + } + + for (; quirk->vendor; quirk++) { + if (quirk->vendor != pdev->subsystem_vendor) + continue; + if ((! quirk->mask && quirk->device == pdev->subsystem_device) || + quirk->device == (quirk->mask & pdev->subsystem_device)) { +#ifdef DEBUG + printk("ac97 quirk for %s (%04x:%04x)\n", quirk->name, ac97->subsystem_vendor, pdev->subsystem_device); +#endif + result = apply_quirk(quirk->type); + if (result < 0) + printk(KERN_ERR "applying quirk type %d for %s failed (%d)\n", quirk->type, quirk->name, result); + return result; + } + } + return 0; +} + +EXPORT_SYMBOL_GPL(ac97_tune_hardware); + MODULE_LICENSE("GPL"); diff --git a/sound/oss/aci.c b/sound/oss/aci.c index e686eaa4d..3928c2802 100644 --- a/sound/oss/aci.c +++ b/sound/oss/aci.c @@ -83,18 +83,18 @@ static struct semaphore aci_sem; #ifdef MODULE static int reset; -MODULE_PARM(reset,"i"); +module_param(reset, bool, 0); MODULE_PARM_DESC(reset,"When set to 1, reset aci mixer."); #else static int reset = 1; #endif static int ide=-1; -MODULE_PARM(ide,"i"); +module_param(ide, int, 0); MODULE_PARM_DESC(ide,"1 enable, 0 disable ide-port - untested" " default: do nothing"); static int wss=-1; -MODULE_PARM(wss,"i"); +module_param(wss, int, 0); MODULE_PARM_DESC(wss,"change between ACI/WSS-mixer; use 0 and 1 - untested" " default: do nothing; for PCM1-pro only"); diff --git a/sound/oss/ad1816.c b/sound/oss/ad1816.c index 442506444..22dae5d0f 100644 --- a/sound/oss/ad1816.c +++ b/sound/oss/ad1816.c @@ -1215,16 +1215,16 @@ static int __initdata dma2 = -1; /* use isapnp for configuration */ static int isapnp = 1; static int isapnpjump; -MODULE_PARM(isapnp, "i"); -MODULE_PARM(isapnpjump, "i"); +module_param(isapnp, bool, 0); +module_param(isapnpjump, int, 0); #endif -MODULE_PARM(io,"i"); -MODULE_PARM(irq,"i"); -MODULE_PARM(dma,"i"); -MODULE_PARM(dma2,"i"); -MODULE_PARM(ad1816_clockfreq,"i"); -MODULE_PARM(options,"i"); +module_param(io, int, 0); +module_param(irq, int, 0); +module_param(dma, int, 0); +module_param(dma2, int, 0); +module_param(ad1816_clockfreq, int, 0); +module_param(options, int, 0); #ifdef __ISAPNP__ static struct { @@ -1245,8 +1245,9 @@ static struct { MODULE_DEVICE_TABLE(isapnp, isapnp_ad1816_list); -void __init ad1816_config_pnp_card(struct pnp_card *card, unsigned short vendor, - unsigned short function) +static void __init ad1816_config_pnp_card(struct pnp_card *card, + unsigned short vendor, + unsigned short function) { struct address_info cfg; struct pnp_dev *card_dev = pnp_find_dev(card, vendor, function, NULL); @@ -1270,7 +1271,7 @@ void __init ad1816_config_pnp_card(struct pnp_card *card, unsigned short vendor, } } -void __init ad1816_config_pnp_cards(void) +static void __init ad1816_config_pnp_cards(void) { int nr_pnp_cfg; int i; diff --git a/sound/oss/ad1848.c b/sound/oss/ad1848.c index c78a5a11d..4384dac3f 100644 --- a/sound/oss/ad1848.c +++ b/sound/oss/ad1848.c @@ -123,9 +123,9 @@ ad1848_port_info; static struct address_info cfg; static int nr_ad1848_devs; -int deskpro_xl; -int deskpro_m; -int soundpro; +static int deskpro_xl; +static int deskpro_m; +static int soundpro; static volatile signed char irq2dev[17] = { -1, -1, -1, -1, -1, -1, -1, -1, @@ -2905,24 +2905,24 @@ static int __initdata dma = -1; static int __initdata dma2 = -1; static int __initdata type = 0; -MODULE_PARM(io, "i"); /* I/O for a raw AD1848 card */ -MODULE_PARM(irq, "i"); /* IRQ to use */ -MODULE_PARM(dma, "i"); /* First DMA channel */ -MODULE_PARM(dma2, "i"); /* Second DMA channel */ -MODULE_PARM(type, "i"); /* Card type */ -MODULE_PARM(deskpro_xl, "i"); /* Special magic for Deskpro XL boxen */ -MODULE_PARM(deskpro_m, "i"); /* Special magic for Deskpro M box */ -MODULE_PARM(soundpro, "i"); /* More special magic for SoundPro chips */ +module_param(io, int, 0); /* I/O for a raw AD1848 card */ +module_param(irq, int, 0); /* IRQ to use */ +module_param(dma, int, 0); /* First DMA channel */ +module_param(dma2, int, 0); /* Second DMA channel */ +module_param(type, int, 0); /* Card type */ +module_param(deskpro_xl, bool, 0); /* Special magic for Deskpro XL boxen */ +module_param(deskpro_m, bool, 0); /* Special magic for Deskpro M box */ +module_param(soundpro, bool, 0); /* More special magic for SoundPro chips */ #ifdef CONFIG_PNP -MODULE_PARM(isapnp, "i"); -MODULE_PARM(isapnpjump, "i"); -MODULE_PARM(reverse, "i"); +module_param(isapnp, int, 0); +module_param(isapnpjump, int, 0); +module_param(reverse, bool, 0); MODULE_PARM_DESC(isapnp, "When set to 0, Plug & Play support will be disabled"); MODULE_PARM_DESC(isapnpjump, "Jumps to a specific slot in the driver's PnP table. Use the source, Luke."); MODULE_PARM_DESC(reverse, "When set to 1, will reverse ISAPnP search order"); -struct pnp_dev *ad1848_dev = NULL; +static struct pnp_dev *ad1848_dev = NULL; /* Please add new entries at the end of the table */ static struct { diff --git a/sound/oss/ad1889.c b/sound/oss/ad1889.c index 607a07a59..b767c621f 100644 --- a/sound/oss/ad1889.c +++ b/sound/oss/ad1889.c @@ -82,20 +82,6 @@ static inline void ad1889_set_wav_rate(ad1889_dev_t *dev, int rate) ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0); } -static inline void ad1889_set_adc_rate(ad1889_dev_t *dev, int rate) -{ - struct ac97_codec *ac97_codec = dev->ac97_codec; - - DBG("Setting ADC rate to %d\n", rate); - dev->state[AD_ADC_STATE].dmabuf.rate = rate; - AD1889_WRITEW(dev, AD_DSRES, rate); - - /* Cycle the ADC to enable the new rate */ - ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0x0100); - WAIT_10MS(); - ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0); -} - static inline void ad1889_set_wav_fmt(ad1889_dev_t *dev, int fmt) { u16 tmp; @@ -308,8 +294,8 @@ static inline void ad1889_trigger_playback(ad1889_dev_t *dev) ad1889_start_wav(&dev->state[AD_WAV_STATE]); } -int ad1889_read_proc (char *page, char **start, off_t off, - int count, int *eof, void *data) +static int ad1889_read_proc (char *page, char **start, off_t off, + int count, int *eof, void *data) { char *out = page; int len, i; diff --git a/sound/oss/awe_wave.c b/sound/oss/awe_wave.c index c80d97c55..d2b9beda8 100644 --- a/sound/oss/awe_wave.c +++ b/sound/oss/awe_wave.c @@ -207,8 +207,8 @@ static awe_chan_info channels[AWE_MAX_CHANNELS]; #define AWE_DEFAULT_MEM_SIZE -1 /* autodetect */ #endif -int io = AWE_DEFAULT_BASE_ADDR; /* Emu8000 base address */ -int memsize = AWE_DEFAULT_MEM_SIZE; /* memory size in Kbytes */ +static int io = AWE_DEFAULT_BASE_ADDR; /* Emu8000 base address */ +static int memsize = AWE_DEFAULT_MEM_SIZE; /* memory size in Kbytes */ #ifdef CONFIG_PNP static int isapnp = -1; #else @@ -219,11 +219,11 @@ MODULE_AUTHOR("Takashi Iwai <iwai@ww.uni-erlangen.de>"); MODULE_DESCRIPTION("SB AWE32/64 WaveTable driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(io, "i"); +module_param(io, int, 0); MODULE_PARM_DESC(io, "base i/o port of Emu8000"); -MODULE_PARM(memsize, "i"); +module_param(memsize, int, 0); MODULE_PARM_DESC(memsize, "onboard DRAM size in Kbytes"); -MODULE_PARM(isapnp, "i"); +module_param(isapnp, bool, 0); MODULE_PARM_DESC(isapnp, "use ISAPnP detection"); /* DRAM start offset */ @@ -6113,12 +6113,12 @@ awe_detect(void) return 0; } -int __init attach_awe(void) +static int __init attach_awe(void) { return awe_detect() ? 0 : -ENODEV; } -void __exit unload_awe(void) +static void __exit unload_awe(void) { pnp_unregister_driver(&awe_pnp_driver); awe_dettach_device(); diff --git a/sound/oss/cmpci.c b/sound/oss/cmpci.c index 16ff7f094..34720e66d 100644 --- a/sound/oss/cmpci.c +++ b/sound/oss/cmpci.c @@ -426,7 +426,7 @@ struct cm_state { struct address_info mpu_data; #endif #ifdef CONFIG_SOUND_CMPCI_JOYSTICK - struct gameport gameport; + struct gameport *gameport; #endif int chip_version; @@ -468,28 +468,28 @@ struct cm_state { static LIST_HEAD(devs); -static int mpuio = 0; -static int fmio = 0; -static int joystick = 0; -static int spdif_inverse = 0; -static int spdif_loop = 0; -static int spdif_out = 0; -static int use_line_as_rear = 0; -static int use_line_as_bass = 0; -static int use_mic_as_bass = 0; -static int mic_boost = 0; -static int hw_copy = 0; -MODULE_PARM(mpuio, "i"); -MODULE_PARM(fmio, "i"); -MODULE_PARM(joystick, "i"); -MODULE_PARM(spdif_inverse, "i"); -MODULE_PARM(spdif_loop, "i"); -MODULE_PARM(spdif_out, "i"); -MODULE_PARM(use_line_as_rear, "i"); -MODULE_PARM(use_line_as_bass, "i"); -MODULE_PARM(use_mic_as_bass, "i"); -MODULE_PARM(mic_boost, "i"); -MODULE_PARM(hw_copy, "i"); +static int mpuio; +static int fmio; +static int joystick; +static int spdif_inverse; +static int spdif_loop; +static int spdif_out; +static int use_line_as_rear; +static int use_line_as_bass; +static int use_mic_as_bass; +static int mic_boost; +static int hw_copy; +module_param(mpuio, int, 0); +module_param(fmio, int, 0); +module_param(joystick, bool, 0); +module_param(spdif_inverse, bool, 0); +module_param(spdif_loop, bool, 0); +module_param(spdif_out, bool, 0); +module_param(use_line_as_rear, bool, 0); +module_param(use_line_as_bass, bool, 0); +module_param(use_mic_as_bass, bool, 0); +module_param(mic_boost, bool, 0); +module_param(hw_copy, bool, 0); MODULE_PARM_DESC(mpuio, "(0x330, 0x320, 0x310, 0x300) Base of MPU-401, 0 to disable"); MODULE_PARM_DESC(fmio, "(0x388, 0x3C8, 0x3E0) Base of OPL3, 0 to disable"); MODULE_PARM_DESC(joystick, "(1/0) Enable joystick interface, still need joystick driver"); @@ -1162,15 +1162,6 @@ static inline void enable_dac_unlocked(struct cm_state *s) enable_adc(s); } -static inline void enable_dac(struct cm_state *s) -{ - unsigned long flags; - - spin_lock_irqsave(&s->lock, flags); - enable_dac_unlocked(s); - spin_unlock_irqrestore(&s->lock, flags); -} - static inline void stop_adc_unlocked(struct cm_state *s) { if (s->enable & ENADC) { @@ -2934,7 +2925,7 @@ static /*const*/ struct file_operations cm_audio_fops = { static struct initvol { int mixch; int vol; -} initvol[] __initdata = { +} initvol[] __devinitdata = { { SOUND_MIXER_WRITE_CD, 0x4f4f }, { SOUND_MIXER_WRITE_LINE, 0x4f4f }, { SOUND_MIXER_WRITE_MIC, 0x4f4f }, @@ -2993,6 +2984,51 @@ static int query_chip(struct cm_state *s) return ChipVersion; } +#ifdef CONFIG_SOUND_CMPCI_JOYSTICK +static int __devinit cm_create_gameport(struct cm_state *s, int io_port) +{ + struct gameport *gp; + + if (!request_region(io_port, CM_EXTENT_GAME, "cmpci GAME")) { + printk(KERN_ERR "cmpci: gameport io ports 0x%#x in use\n", io_port); + return -EBUSY; + } + + if (!(s->gameport = gp = gameport_allocate_port())) { + printk(KERN_ERR "cmpci: can not allocate memory for gameport\n"); + release_region(io_port, CM_EXTENT_GAME); + return -ENOMEM; + } + + gameport_set_name(gp, "C-Media GP"); + gameport_set_phys(gp, "pci%s/gameport0", pci_name(s->dev)); + gp->dev.parent = &s->dev->dev; + gp->io = io_port; + + /* enable joystick */ + maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x02); + + gameport_register_port(gp); + + return 0; +} + +static void __devexit cm_free_gameport(struct cm_state *s) +{ + if (s->gameport) { + int gpio = s->gameport->io; + + gameport_unregister_port(s->gameport); + s->gameport = NULL; + maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x02, 0); + release_region(gpio, CM_EXTENT_GAME); + } +} +#else +static inline int cm_create_gameport(struct cm_state *s, int io_port) { return -ENOSYS; } +static inline void cm_free_gameport(struct cm_state *s) { } +#endif + #define echo_option(x)\ if (x) strcat(options, "" #x " ") @@ -3238,22 +3274,11 @@ static int __devinit cm_probe(struct pci_dev *pcidev, const struct pci_device_id } skip_mpu: #endif -#ifdef CONFIG_SOUND_CMPCI_JOYSTICK - /* enable joystick */ - if (joystick) { - s->gameport.io = 0x200; - if (!request_region(s->gameport.io, CM_EXTENT_GAME, "cmpci GAME")) { - printk(KERN_ERR "cmpci: gameport io ports in use\n"); - s->gameport.io = 0; - } else { - maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x02); - gameport_register_port(&s->gameport); - } - } else { - maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x02, 0); - s->gameport.io = 0; - } -#endif + /* disable joystick port */ + maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x02, 0); + if (joystick) + cm_create_gameport(s, 0x200); + /* store it in the driver field */ pci_set_drvdata(pcidev, s); /* put it into driver list */ @@ -3287,13 +3312,9 @@ static void __devexit cm_remove(struct pci_dev *dev) if (!s) return; -#ifdef CONFIG_SOUND_CMPCI_JOYSTICK - if (s->gameport.io) { - gameport_unregister_port(&s->gameport); - release_region(s->gameport.io, CM_EXTENT_GAME); - maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x02, 0); - } -#endif + + cm_free_gameport(s); + #ifdef CONFIG_SOUND_CMPCI_FM if (s->iosynth) { /* disable FM */ diff --git a/sound/oss/cs4232.h b/sound/oss/cs4232.h deleted file mode 100644 index a5a00292c..000000000 --- a/sound/oss/cs4232.h +++ /dev/null @@ -1,3 +0,0 @@ - -int probe_cs4232_mpu (struct address_info *hw_config); -void attach_cs4232_mpu (struct address_info *hw_config); diff --git a/sound/oss/dmasound/dac3550a.c b/sound/oss/dmasound/dac3550a.c index fadf33e59..533895eba 100644 --- a/sound/oss/dmasound/dac3550a.c +++ b/sound/oss/dmasound/dac3550a.c @@ -40,9 +40,6 @@ static int daca_attach_adapter(struct i2c_adapter *adapter); static int daca_detect_client(struct i2c_adapter *adapter, int address); static int daca_detach_client(struct i2c_client *client); -/* Unique ID allocation */ -static int daca_id; - struct i2c_driver daca_driver = { .owner = THIS_MODULE, .name = "DAC3550A driver V " DACA_VERSION, @@ -176,7 +173,6 @@ static int daca_detect_client(struct i2c_adapter *adapter, int address) new_client->driver = &daca_driver; new_client->flags = 0; strcpy(new_client->name, client_name); - new_client->id = daca_id++; /* racy... */ if (daca_init_client(new_client)) goto bail; diff --git a/sound/oss/dmasound/dmasound_awacs.c b/sound/oss/dmasound/dmasound_awacs.c index 89f52a7d4..5281b8898 100644 --- a/sound/oss/dmasound/dmasound_awacs.c +++ b/sound/oss/dmasound/dmasound_awacs.c @@ -2987,10 +2987,13 @@ printk("dmasound_pmac: Awacs/Screamer Codec Mfct: %d Rev %d\n", mfg, rev); set_hw_byteswap(io) ; /* figure out if the h/w can do it */ - /* get default volume from nvram - * vol = (~nvram_read_byte(0x1308) & 7) << 1; - */ +#ifdef CONFIG_NVRAM + /* get default volume from nvram */ vol = ((pmac_xpram_read( 8 ) & 7 ) << 1 ); +#else + vol = 0; +#endif + /* set up tracking values */ spk_vol = vol * 100 ; spk_vol /= 7 ; /* get set value to a percentage */ diff --git a/sound/oss/gus_wave.c b/sound/oss/gus_wave.c index 2cc924d7b..942d51865 100644 --- a/sound/oss/gus_wave.c +++ b/sound/oss/gus_wave.c @@ -94,7 +94,7 @@ static int recording_active; static int only_read_access; static int only_8_bits; -int iw_mode = 0; +static int iw_mode = 0; int gus_wave_volume = 60; int gus_pcm_volume = 80; int have_gus_max = 0; @@ -139,7 +139,7 @@ static int pcm_current_block; static unsigned long pcm_current_buf; static int pcm_current_count; static int pcm_current_intrflag; -spinlock_t gus_lock=SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(gus_lock); extern int *gus_osp; @@ -3126,8 +3126,7 @@ void __exit gus_wave_unload(struct address_info *hw_config) if (hw_config->slots[5] != -1) sound_unload_mixerdev(hw_config->slots[5]); - if(samples) - vfree(samples); + vfree(samples); samples=NULL; } /* called in interrupt context */ diff --git a/sound/oss/i810_audio.c b/sound/oss/i810_audio.c index 07f575d90..7e9f667cf 100644 --- a/sound/oss/i810_audio.c +++ b/sound/oss/i810_audio.c @@ -111,6 +111,7 @@ static int ftsodell; static int strict_clocking; static unsigned int clocking; static int spdif_locked; +static int ac97_quirk = AC97_TUNE_DEFAULT; //#define DEBUG //#define DEBUG2 @@ -481,6 +482,124 @@ struct i810_card { #define CIV_TO_LVI(card, port, off) \ I810_IOWRITEB(MODULOP2(GET_CIV((card), (port)) + (off), SG_LEN), (card), (port) + OFF_LVI) +static struct ac97_quirk ac97_quirks[] __devinitdata = { + { + .vendor = 0x0e11, + .device = 0x00b8, + .name = "Compaq Evo D510C", + .type = AC97_TUNE_HP_ONLY + }, + { + .vendor = 0x1028, + .device = 0x00d8, + .name = "Dell Precision 530", /* AD1885 */ + .type = AC97_TUNE_HP_ONLY + }, + { + .vendor = 0x1028, + .device = 0x0126, + .name = "Dell Optiplex GX260", /* AD1981A */ + .type = AC97_TUNE_HP_ONLY + }, + { + .vendor = 0x1028, + .device = 0x012d, + .name = "Dell Precision 450", /* AD1981B*/ + .type = AC97_TUNE_HP_ONLY + }, + { /* FIXME: which codec? */ + .vendor = 0x103c, + .device = 0x00c3, + .name = "Hewlett-Packard onboard", + .type = AC97_TUNE_HP_ONLY + }, + { + .vendor = 0x103c, + .device = 0x12f1, + .name = "HP xw8200", /* AD1981B*/ + .type = AC97_TUNE_HP_ONLY + }, + { + .vendor = 0x103c, + .device = 0x3008, + .name = "HP xw4200", /* AD1981B*/ + .type = AC97_TUNE_HP_ONLY + }, + { + .vendor = 0x10f1, + .device = 0x2665, + .name = "Fujitsu-Siemens Celsius", /* AD1981? */ + .type = AC97_TUNE_HP_ONLY + }, + { + .vendor = 0x10f1, + .device = 0x2885, + .name = "AMD64 Mobo", /* ALC650 */ + .type = AC97_TUNE_HP_ONLY + }, + { + .vendor = 0x110a, + .device = 0x0056, + .name = "Fujitsu-Siemens Scenic", /* AD1981? */ + .type = AC97_TUNE_HP_ONLY + }, + { + .vendor = 0x11d4, + .device = 0x5375, + .name = "ADI AD1985 (discrete)", + .type = AC97_TUNE_HP_ONLY + }, + { + .vendor = 0x1462, + .device = 0x5470, + .name = "MSI P4 ATX 645 Ultra", + .type = AC97_TUNE_HP_ONLY + }, + { + .vendor = 0x1734, + .device = 0x0088, + .name = "Fujitsu-Siemens D1522", /* AD1981 */ + .type = AC97_TUNE_HP_ONLY + }, + { + .vendor = 0x8086, + .device = 0x4856, + .name = "Intel D845WN (82801BA)", + .type = AC97_TUNE_SWAP_HP + }, + { + .vendor = 0x8086, + .device = 0x4d44, + .name = "Intel D850EMV2", /* AD1885 */ + .type = AC97_TUNE_HP_ONLY + }, + { + .vendor = 0x8086, + .device = 0x4d56, + .name = "Intel ICH/AD1885", + .type = AC97_TUNE_HP_ONLY + }, + { + .vendor = 0x1028, + .device = 0x012d, + .name = "Dell Precision 450", /* AD1981B*/ + .type = AC97_TUNE_HP_ONLY + }, + { + .vendor = 0x103c, + .device = 0x3008, + .name = "HP xw4200", /* AD1981B*/ + .type = AC97_TUNE_HP_ONLY + }, + { + .vendor = 0x103c, + .device = 0x12f1, + .name = "HP xw8200", /* AD1981B*/ + .type = AC97_TUNE_HP_ONLY + }, + { } /* terminator */ +}; + static struct i810_card *devs = NULL; static int i810_open_mixdev(struct inode *inode, struct file *file); @@ -1077,10 +1196,23 @@ static void __i810_update_lvi(struct i810_state *state, int rec) if (count < fragsize) return; + /* if we are currently stopped, then our CIV is actually set to our + * *last* sg segment and we are ready to wrap to the next. However, + * if we set our LVI to the last sg segment, then it won't wrap to + * the next sg segment, it won't even get a start. So, instead, when + * we are stopped, we set both the LVI value and also we increment + * the CIV value to the next sg segment to be played so that when + * we call start, things will operate properly. Since the CIV can't + * be written to directly for this purpose, we set the LVI to CIV + 1 + * temporarily. Once the engine has started we set the LVI to its + * final value. + */ if (!dmabuf->enable && dmabuf->ready) { if (!(dmabuf->trigger & trigger)) return; + CIV_TO_LVI(state->card, port, 1); + start(state); while (!(I810_IOREADB(state->card, port + OFF_CR) & ((1<<4) | (1<<2)))) ; @@ -3043,6 +3175,9 @@ static int __devinit i810_ac97_init(struct i810_card *card) card->ac97_codec[num_ac97] = codec; } + /* tune up the primary codec */ + ac97_tune_hardware(card->pci_dev, ac97_quirks, ac97_quirk); + /* pick the minimum of channels supported by ICHx or codec(s) */ card->channels = (card->channels > total_channels)?total_channels:card->channels; @@ -3335,7 +3470,7 @@ static void __devexit i810_remove(struct pci_dev *pci_dev) } #ifdef CONFIG_PM -static int i810_pm_suspend(struct pci_dev *dev, u32 pm_state) +static int i810_pm_suspend(struct pci_dev *dev, pm_message_t pm_state) { struct i810_card *card = pci_get_drvdata(dev); struct i810_state *state; @@ -3460,15 +3595,15 @@ static int i810_pm_resume(struct pci_dev *dev) } #endif /* CONFIG_PM */ -MODULE_AUTHOR(""); +MODULE_AUTHOR("The Linux kernel team"); MODULE_DESCRIPTION("Intel 810 audio support"); MODULE_LICENSE("GPL"); -MODULE_PARM(ftsodell, "i"); -MODULE_PARM(clocking, "i"); -MODULE_PARM(strict_clocking, "i"); -MODULE_PARM(spdif_locked, "i"); +module_param(ftsodell, int, 0444); +module_param(clocking, uint, 0444); +module_param(strict_clocking, int, 0444); +module_param(spdif_locked, int, 0444); -#define I810_MODULE_NAME "intel810_audio" +#define I810_MODULE_NAME "i810_audio" static struct pci_driver i810_pci_driver = { .name = I810_MODULE_NAME, diff --git a/sound/oss/maestro_tables.h b/sound/oss/maestro_tables.h deleted file mode 100644 index 1edf1850a..000000000 --- a/sound/oss/maestro_tables.h +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Set up data block for the ESS soundblaster emulation. This is like - * the example code from ftp.esstech.com.tw (104T31.ZIP) - */ - -u16 asp_block_0[]= { - 0x7980, 0x003a, 0x7980, 0x007d, 0xbe3a, 0x8b00, 0xbe3a, 0x8b00, - 0xbe3a, 0x8b00, 0xbe3a, 0x8b00, 0xbe3a, 0x8b00, 0xbe3a, 0x8b00, - 0x7980, 0x0be6, 0x7980, 0x0069, 0xbe3a, 0x8b00, 0x8048, 0x6945, - 0xb801, 0x9045, 0x6941, 0xe388, 0x0031, 0x6944, 0xba50, 0xe38c, - 0x0031, 0x8b88, 0x6942, 0x304a, 0xe308, 0x0028, 0x6949, 0x9042, - 0x0042, 0xafa0, 0x8000, 0xafa0, 0x8000, 0x8042, 0x6944, 0xb801, - 0x9044, 0x0048, 0xbe3a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0xbe41, 0xbf80, 0x0101, 0x8806, 0x8804, 0xb912, - 0x8807, 0xbc26, 0xbe40, 0xb92f, 0x9001, 0x9002, 0x003b, 0x0122, - 0x7a88, 0x0055, 0x003a, 0x013c, 0x7a88, 0x0055, 0x4902, 0xe100, - 0x0800, 0x0c02, 0xa000, 0x7980, 0x004e, 0xb908, 0x8809, 0xbec6, - 0x0067, 0x4a80, 0xe200, 0x0065, 0x4880, 0xe200, 0x0063, 0xb97f, - 0x6e80, 0x7980, 0x0066, 0x1089, 0x9088, 0xb900, 0x90a9, 0x8ba8, - 0xef00, 0x803d, 0x0003, 0x1007, 0x881f, 0x8b88, 0xbb0f, 0xada0, - 0x0810, 0x9003, 0x4903, 0xe200, 0x007b, 0x9002, 0x6a05, 0x6d04, - 0x9803, 0x9804, 0x9005, 0x003d, 0xbe3a, 0xaf06, 0x0000, 0x803d, - 0x8b88, 0x6906, 0x8810, 0xaf06, 0x0001, 0xbfb0, 0x00ff, 0xbaf5, - 0xe3cc, 0x009a, 0x5e06, 0x003f, 0xbf80, 0x0080, 0x4a06, 0xe200, - 0x0095, 0x6e80, 0x6d06, 0x7980, 0x009b, 0x9080, 0x0810, 0xba46, - 0x8810, 0x8b00, 0x1006, 0x9080, 0x003d, 0xbe3a, 0x1024, 0x2009, - 0x8810, 0x8b88, 0x8b00, 0x1089, 0xbfb0, 0x000e, 0xbe0a, 0x880d, - 0x903e, 0x1038, 0x2008, 0x8810, 0x1037, 0x2008, 0x8811, 0x5f3e, - 0x0000, 0x8b00, 0xf500, 0x5e80, 0xfffe, 0x1039, 0x2008, 0x8815, - 0x8b8d, 0x0231, 0x0333, 0x108a, 0x90ad, 0x1025, 0x200a, 0x8815, - 0x0605, 0xb91f, 0x8809, 0x4f16, 0x1080, 0xf600, 0xbfb0, - 0x0003, 0xbfb0, 0x0007, 0x9089, 0xbe47, 0xbe43, 0xbec6, - 0x00f6, 0x4f8b, 0x14a8, 0xe500, 0x6380, 0x8b89, 0x4e8a, - 0xbfe3, 0xe500, 0x2480, 0xbe46, 0x8b9d, 0xbfe7, 0xbfb0, - 0x00ff, 0x288c, 0x2026, 0x8814, 0xbe47, 0x8b00, 0x738f, - 0x54aa, 0xbe03, 0xbe0a, 0x2fa8, 0x988a, 0x8da9, 0xbe03, - 0x4d8e, 0xbfe1, 0xf500, 0x6180, 0x9880, 0x8ba9, 0xbe03, - 0x4c8e, 0xbfe1, 0xf500, 0x6180, 0x9880, 0x8ba9, 0xbe42, - 0x1039, 0x2008, 0x8815, 0x8b8d, 0x8b00, 0x8d8a, 0x7980, - 0x0bcf}; - -u16 asp_block_1[]={ - 0x0005, 0xb900, 0x9008, 0x9009, 0x900a, 0xbb3f, 0x90a0, - 0x001a, 0x011b, 0x021c, 0x0323, 0x1089, 0x9015, 0x108a, - 0x9016, 0x108b, 0x9017, 0x1088, 0x9018, 0x0137, 0x0524, - 0x8b8d, 0x4f16, 0xe200, 0x0827, 0x4f15, 0xe200, 0x0827, - 0x7a80, 0x08e6, 0x102c, 0xb802, 0x8813, 0x8b8b, 0xb900, - 0x90a0, 0x908d, 0x7980, 0x0833, 0x7a80, 0x0913, 0x7803, - 0x7a80, 0x0913, 0x102c, 0xb802, 0x8813, 0x8b8b, 0xb903, - 0x90a0, 0x908d, 0x7c02, 0x4f16, 0xe200, 0x0845, 0x4e15, - 0xe200, 0x0845, 0x7a80, 0x08e6, 0x102c, 0xb806, 0x8813, - 0x8b8b, 0xb901, 0x90a0, 0x908d, 0x7980, 0x0851, 0x7a80, - 0x0913, 0x7803, 0x7a80, 0x0913, 0x102c, 0xb806, 0x8813, - 0x8b8b, 0xb904, 0x90a0, 0x908d, 0x7c02, 0x4f16, 0xe200, - 0x0863, 0x4d15, 0xe200, 0x0863, 0x7a80, 0x08e6, 0x102c, - 0xb80a, 0x8813, 0x8b8b, 0xb902, 0x90a0, 0x908d, 0x7980, - 0x086f, 0x7a80, 0x0913, 0x7803, 0x7a80, 0x0913, 0x102c, - 0xb80a, 0x8813, 0x8b8b, 0xb905, 0x90a0, 0x908d, 0x7801, - 0x7a80, 0x0913, 0x7801, 0x7a80, 0x0913, 0x7801, 0x7a80, - 0x0913, 0x1024, 0xbf90, 0x0100, 0x8815, 0x4f16, 0xe200, - 0x088e, 0x4c15, 0xe200, 0x088e, 0x7a80, 0x08e6, 0x102c, - 0xb814, 0x8813, 0x8b8b, 0xbf80, 0x0100, 0x90a0, 0x908d, - 0x7980, 0x089b, 0x7a80, 0x0913, 0x7803, 0x7a80, 0x0913, - 0x102c, 0xb814, 0x8813, 0x8b8b, 0xbf80, 0x0103, 0x90a0, - 0x908d, 0x7c02, 0x4f16, 0xe200, 0x08ae, 0x4b15, 0xe200, - 0x08ae, 0x7a80, 0x08e6, 0x102c, 0xb818, 0x8813, 0x8b8b, - 0xbf80, 0x0101, 0x90a0, 0x908d, 0x7980, 0x08bb, 0x7a80, - 0x0913, 0x7803, 0x7a80, 0x0913, 0x102c, 0xb818, 0x8813, - 0x8b8b, 0xbf80, 0x0104, 0x90a0, 0x908d, 0x7c02, 0x4f16, - 0xe200, 0x08ce, 0x4a15, 0xe200, 0x08ce, 0x7a80, 0x08e6, - 0x102c, 0xb81c, 0x8813, 0x8b8b, 0xbf80, 0x0102, 0x90a0, - 0x908d, 0x7980, 0x08db, 0x7a80, 0x0913, 0x7803, 0x7a80, - 0x0913, 0x102c, 0xb81c, 0x8813, 0x8b8b, 0xbf80, 0x0105, - 0x90a0, 0x908d, 0x7801, 0x7a80, 0x0913, 0x7801, 0x7a80, - 0x0913, 0x7801, 0x7a80, 0x0913, 0x7980, 0x0920, 0x4f80, - 0x7803, 0xe100, 0x08fe, 0x4f89, 0xe100, 0x08f5, 0xb901, - 0x90a0, 0xb902, 0x90a0, 0x90a0, 0xb906, 0x90ad, 0xef00, - 0xb901, 0x90a0, 0xb906, 0x90a0, 0xb900, 0x90a0, 0xb906, - 0x90ad, 0xef00, 0x4f89, 0xe100, 0x090a, 0xb905, 0x90a0, - 0xb900, 0x90a0, 0xb902, 0x90a0, 0xb906, 0x90ad, 0xef00, - 0xb905, 0x90a0, 0xb900, 0x90a0, 0xb906, 0x90a0, 0xb904, - 0x90ad, 0xef00, 0x4f89, 0xe100, 0x091b, 0xb901, 0x90a0, - 0xb906, 0x90ad, 0xef00, 0xb905, 0x90a0, 0xb904, 0x90ad, - 0xef00, 0xb91f, 0x8809, 0x0034, 0x8b88, 0xbec6, 0x0932, - 0x1313, 0xbe1e, 0x1014, 0xbe1a, 0xbe01, 0xbfe8, 0xbe17, - 0x6a13, 0x6214, 0xbe14, 0x9813, 0x9014, 0x98a0, 0xbe47, - 0x5f0f, 0x002e, 0xe200, 0x093d, 0xbf80, 0xffd2, 0x900f, - 0x7980, 0x0940, 0x100f, 0xb801, 0x900f, 0x400f, 0x8b00, - 0xe500, 0xbe01, 0xbe09, 0x9010, 0xbe46, 0x5f11, 0x003f, - 0xe200, 0x094f, 0xb900, 0x9011, 0x7980, 0x0952, 0x1011, - 0xb801, 0x9011, 0x1001, 0xe388, 0x0bcf, 0x1021, 0x2009, - 0x8813, 0x8b8b, 0x8b00, 0x1080, 0xbfe6, 0x7810, 0x8b00, - 0x8b00, 0x2180, 0xbfb0, 0x0007, 0x4c11, 0x8b00, 0xe100, - 0x096c, 0x4b11, 0x8b00, 0xe600, 0xb900, 0x7980, 0x096d, - 0xbe0a, 0x4a11, 0x8b00, 0xe500, 0xbe01, 0x9012, 0x1037, - 0x2008, 0x8811, 0x102e, 0x2008, 0x8812, 0x4a89, 0xb901, - 0xe500, 0x9019, 0xe100, 0x09c9, 0xb900, 0x9019, 0x4a18, - 0xe200, 0x09c9, 0x5f0a, 0x0010, 0xe200, 0x098d, 0x4b18, - 0xb901, 0xe500, 0x9019, 0x7980, 0x09c9, 0x5f0a, 0x0013, - 0xe200, 0x0997, 0x4b18, 0xb901, 0xe500, 0x9019, 0x7980, - 0x09c9, 0x5f0a, 0x0011, 0xe200, 0x09a4, 0x4f18, 0xb905, - 0xe500, 0x9080, 0xb901, 0xe500, 0x9019, 0x7980, 0x09c9, - 0x5f0a, 0x0014, 0xe200, 0x09b1, 0x4c18, 0xb904, 0xe500, - 0x9080, 0xb901, 0xe500, 0x9019, 0x7980, 0x09c9, 0x5f0a, - 0x0012, 0xe200, 0x09be, 0x4d18, 0xb905, 0xe500, 0x9080, - 0xb901, 0xe500, 0x9019, 0x7980, 0x09c9, 0x5f0a, 0x0015, - 0xe200, 0x09c9, 0x4e18, 0xb904, 0xe500, 0x9080, 0xb901, - 0xe500, 0x9019, 0x8b8a, 0x4f19, 0xe200, 0x09d4, 0x4b80, - 0xe200, 0x09d6, 0x5d80, 0x0020, 0x7980, 0x09d9, 0x5d80, - 0x0010, 0x4a80, 0xe200, 0x0bca, 0x1001, 0xba01, 0x9001, - 0x1024, 0x2009, 0x8815, 0x8b89, 0x4d8d, 0xe200, 0x09f8, - 0x4f16, 0xe100, 0x09ed, 0x8b89, 0x1080, 0xbfc0, 0x000c, - 0x908c, 0x7980, 0x09f8, 0x4b89, 0x108d, 0xf600, 0xbfb0, - 0x0003, 0x4a89, 0x8b00, 0xf500, 0xbfc0, 0x0008, 0x908c, - 0x1022, 0x2009, 0x8811, 0x102e, 0x2008, 0x8812, 0x102f, - 0x2008, 0x8813, 0x1020, 0x200a, 0x8814, 0x101d, 0x200a, - 0x8815, 0x8b8a, 0x4f19, 0xe100, 0x0a11, 0x5e80, 0x0020, - 0x5d80, 0x0018, 0x7980, 0x0a3e, 0x4f80, 0xe200, 0x0a1e, - 0x8b8b, 0x108a, 0xbfa0, 0x7fc0, 0x8b00, 0xf704, 0x5c80, - 0x0003, 0x7980, 0x0a3e, 0x4e80, 0xe200, 0x0a36, 0x8b8c, - 0x178b, 0xbe01, 0xbfb7, 0x00f0, 0x308a, 0xe344, 0x0a3e, - 0x8b8d, 0x4a8a, 0x8b00, 0xe200, 0x0a32, 0x5c80, 0x0006, - 0x7980, 0x0a3e, 0x5c80, 0x000a, 0x7980, 0x0a3e, 0x4c80, - 0xe200, 0x0a3e, 0x4b80, 0x8b00, 0xf500, 0x5c80, 0x0019, - 0x4f80, 0xe200, 0x0a4d, 0x101f, 0x200a, 0x8816, 0x8b00, - 0x8b00, 0x8b8e, 0x1780, 0xbfb7, 0x00f0, 0x900b, 0x7980, - 0x0a64, 0x4e80, 0xe200, 0x0a5c, 0x101f, 0x200a, 0x8816, - 0x8b00, 0x8b00, 0x8b8e, 0x1b80, 0xbfbb, 0x000f, 0x900b, - 0x7980, 0x0a64, 0x4c80, 0xe200, 0x0a64, 0x8b8c, 0x1b80, - 0xbfbb, 0x000f, 0x900b, 0x8b89, 0x1880, 0xbfb8, 0x001c, - 0x4917, 0xe100, 0x0a6e, 0x4f80, 0x7980, 0x0a70, 0x4e80, - 0x8b00, 0xf500, 0xbf98, 0x0002, 0x8b8d, 0x4b89, 0x8b00, - 0xe600, 0xbfe1, 0x903e, 0xbe43, 0x6a0b, 0x613e, 0xbfe8, - 0x980c, 0xbe42, 0x7c10, 0x1080, 0xbfe5, 0xbe1e, 0x7810, - 0x1280, 0xbfb2, 0x001f, 0xbe11, 0x2027, 0x8811, 0x101e, - 0x200a, 0x8816, 0x8b00, 0x128e, 0x4980, 0xe100, 0x0a9b, - 0x4880, 0xe100, 0x0a98, 0xb900, 0x7980, 0x0a9f, 0xbe0a, - 0x7980, 0x0a9f, 0x4880, 0xe200, 0x0a9f, 0xbe09, 0xbe1e, - 0x158d, 0xbfb5, 0x003f, 0xbe11, 0x4889, 0xe200, 0x0aae, - 0xbe1e, 0x1010, 0x4818, 0x8b00, 0xe600, 0xbfe1, 0xbe11, - 0xbfe1, 0x8811, 0xbe1e, 0xb9ff, 0x8819, 0x8b00, 0x8b00, - 0xbf46, 0x8b00, 0xe600, 0xbe1f, 0xbe01, 0xbfb0, 0x00ff, - 0x202a, 0x8811, 0x8b00, 0x8b00, 0x108a, 0x900d, 0xb91f, - 0x8809, 0x0732, 0x730d, 0x4f80, 0xe200, 0x0ad8, 0x1028, - 0x200c, 0x8815, 0xbe43, 0x8b8b, 0x6a8d, 0xbec6, 0x0ad4, - 0x618b, 0x9880, 0x548f, 0x8dad, 0xbe42, 0x7980, 0x0b24, - 0x4e80, 0xe200, 0x0af9, 0x8b8c, 0x178b, 0xbe01, 0xbfb7, - 0x00f0, 0x903e, 0x1029, 0x200c, 0x8815, 0x108d, 0xbec6, - 0x0af6, 0x308b, 0xbe1e, 0x303e, 0x903f, 0x403f, 0xbe1f, - 0xe500, 0x103e, 0x9080, 0xbfe6, 0x202a, 0x8811, 0x8b00, - 0x1089, 0x548f, 0x8dad, 0x7980, 0x0b24, 0x4c8b, 0xe200, - 0x0b1b, 0x1029, 0x200c, 0x8815, 0xbf80, 0x007f, 0x903e, - 0x108d, 0xbec6, 0x0b14, 0x308b, 0xbe1e, 0x303e, 0x903f, - 0x403f, 0xbe1f, 0xe500, 0xb900, 0x9080, 0xbfe6, 0x202a, - 0x8811, 0x8b00, 0x1089, 0x548f, 0x8dad, 0x8b8a, 0xf500, - 0x5e80, 0xffdf, 0x7980, 0x0b24, 0x1089, 0xbfe6, 0x202a, - 0x8811, 0x8b00, 0x8b00, 0x548f, 0xbb1f, 0x8da0, 0x8b8f, - 0x0732, 0x1021, 0x2009, 0x8811, 0x8b89, 0x101d, 0x200a, - 0x8812, 0x1080, 0x7810, 0x8b00, 0xbe47, 0x288a, 0xbfb0, - 0x03ff, 0x4989, 0xe200, 0x0b3e, 0xbe1e, 0x1012, 0x4918, - 0x8b00, 0xe600, 0xbe0a, 0xbe11, 0x900e, 0xbe46, 0x108a, - 0xbfb0, 0x001c, 0xbfe1, 0x880d, 0x8b00, 0x6b0e, 0xbe0a, - 0x880c, 0x108c, 0xbfb0, 0x000f, 0x202d, 0x8814, 0x8b00, - 0x8b00, 0x5589, 0xbf03, 0x8c0e, 0xbf00, 0x1030, 0x2008, - 0x8811, 0xb91f, 0x8809, 0x108b, 0x0333, 0xbec6, 0x0b5f, - 0x200e, 0x90a0, 0x8b00, 0x8b89, 0x9080, 0x4a18, 0xe200, - 0x0b7a, 0x5f0a, 0x0011, 0xe200, 0x0b6c, 0x4f18, 0xe900, - 0x0b7c, 0x5f0a, 0x0014, 0xe200, 0x0b73, 0x4c18, 0xe900, - 0x0b9b, 0x5f0a, 0x0015, 0xe200, 0x0b7a, 0x4e18, 0xe900, - 0x0bb2, 0x7980, 0x009e, 0x0034, 0xb91f, 0x8809, 0x0333, - 0x8b8b, 0xbec6, 0x0b99, 0x1280, 0x6c80, 0xbfea, 0xbe1e, - 0x1580, 0x6c88, 0xbfec, 0xbe13, 0x903e, 0x6cab, 0x903f, - 0x4f3e, 0xb900, 0xf500, 0xbf80, 0x8000, 0x4f3f, 0xbf90, - 0x0d00, 0xf500, 0xbf90, 0x2700, 0x90a0, 0xef00, 0x0034, - 0xb91f, 0x8809, 0x0333, 0x8b88, 0xbec6, 0x0bb0, 0x1eab, - 0x6c80, 0xbfed, 0x903e, 0x4180, 0xb900, 0xf500, 0xbf80, - 0x8000, 0x4f3e, 0x8b00, 0xf500, 0xbf90, 0x4000, 0x90a8, - 0xef00, 0x0034, 0xb91f, 0x8809, 0x0333, 0x8b8b, 0xbec6, - 0x0bc8, 0x1280, 0x6c8b, 0xbfea, 0xbe1e, 0x1580, 0x6c80, - 0xbfec, 0xbe13, 0x903e, 0x4f3e, 0xbf80, 0x4000, 0xf500, - 0xbf90, 0x8000, 0x90a0, 0xef00, 0x0231, 0x8b8a, 0xb900, - 0xbb20, 0x90a0, 0x5f08, 0x0023, 0xe100, 0x0043, 0x1008, - 0xb801, 0x9008, 0x102b, 0x2008, 0x8812, 0x8b00, 0x8b00, - 0x1080, 0x900a, 0x102c, 0x2008, 0x8812, 0x8b00, 0x8b00, - 0x1080, 0x9009, 0x7980, 0x0952, 0x8148, 0x6946, 0xb801, - 0x9046, 0xb901, 0x9041, 0x6944, 0xba08, 0xe344, 0x0bfe, - 0x9044, 0x8b89, 0x0143, 0x694b, 0x881f, 0xbb0f, 0xada0, - 0x8143, 0x0811, 0x304a, 0xe308, 0x0bfe, 0x6949, 0x9043, - 0x0148, 0xbe3a -}; - -u16 asp_block_2[]={ - 0x0000, 0x0000, 0x0003, 0x0003, 0x0001, 0x0001, - 0x0004, 0x0004, 0x0002, 0x0002, 0x0005, 0x0005, - 0x0006, 0x0006, 0x0007, 0x0007, 0x0008, 0x0008, - 0x0100, 0x0100, 0x0103, 0x0103, 0x0101, 0x0101, - 0x0104, 0x0104, 0x0102, 0x0102, 0x0105, 0x0105, - 0x0106, 0x0106, 0x0107, 0x0107, 0x0108, 0x0108 -}; - -u16 asp_block_3[]={ - 0x0000, 0x0000, 0x0000, 0x1200, 0x1200, 0x1280, 0x0000, 0x05d0, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x1104, 0x1105, 0x1008, 0x1020, 0x1040, 0x1060, - 0x1080, 0x10a0, 0x10b0, 0x100d, 0x1010, 0x10e0, 0x2000, 0x2980, - 0x2b00, 0x2b40, 0x2a00, 0x2b90, 0x13dc, 0x2b80, 0x11bc, 0x134c, - 0x1370, 0x12e0, 0x1240, 0x1260, 0x12c0, 0x009e, 0x0045, 0x10bc, - 0x1394, 0x13b8, 0x11f6, 0x10f6, 0x11b0, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0815, 0x0956, 0x09df, 0x0be5, 0x0a19, 0x0a48, 0x0b37, - 0x0b5d, 0x0a8b, 0x0aae, 0x0ad2 }; - - -u16 asp_block_4[] = { - 0x0192, 0x04b6, 0x07d9, 0x0afb, 0x0e1c, 0x113a, 0x1455, 0x176e, - 0x1a83, 0x1d93, 0x209f, 0x23a7, 0x26a8, 0x29a4, 0x2c99, 0x2f87, - 0x326e, 0x354e, 0x3825, 0x3af3, 0x3db8, 0x4074, 0x4326, 0x45cd, - 0x486a, 0x4afb, 0x4d81, 0x4ffb, 0x5269, 0x54ca, 0x571e, 0x5964, - 0x5b9d, 0x5dc8, 0x5fe4, 0x61f1, 0x63ef, 0x65de, 0x67bd, 0x698c, - 0x6b4b, 0x6cf9, 0x6e97, 0x7023, 0x719e, 0x7308, 0x7460, 0x75a6, - 0x76d9, 0x77fb, 0x790a, 0x7a06, 0x7aef, 0x7bc6, 0x7c89, 0x7d3a, - 0x7dd6, 0x7e60, 0x7ed6, 0x7f38, 0x7f87, 0x7fc2, 0x7fea, 0x7ffe, - 0x7ffe, 0x7fea, 0x7fc2, 0x7f87, 0x7f38, 0x7ed6, 0x7e60, 0x7dd6, - 0x7d3a, 0x7c89, 0x7bc6, 0x7aef, 0x7a06, 0x790a, 0x77fb, 0x76d9, - 0x75a6, 0x7460, 0x7308, 0x719e, 0x7023, 0x6e97, 0x6cf9, 0x6b4b, - 0x698c, 0x67bd, 0x65de, 0x63ef, 0x61f1, 0x5fe4, 0x5dc8, 0x5b9d, - 0x5964, 0x571e, 0x54ca, 0x5269, 0x4ffb, 0x4d81, 0x4afb, 0x486a, - 0x45cd, 0x4326, 0x4074, 0x3db8, 0x3af3, 0x3825, 0x354e, 0x326e, - 0x2f87, 0x2c99, 0x29a4, 0x26a8, 0x23a7, 0x209f, 0x1d93, 0x1a83, - 0x176e, 0x1455, 0x113a, 0x0e1c, 0x0afb, 0x07d9, 0x04b6, 0x0192, - 0xfe6f, 0xfb4b, 0xf828, 0xf506, 0xf1e5, 0xeec7, 0xebac, 0xe893, - 0xe57e, 0xe26e, 0xdf62, 0xdc5a, 0xd959, 0xd65d, 0xd368, 0xd07a, - 0xcd93, 0xcab3, 0xc7dc, 0xc50e, 0xc249, 0xbf8d, 0xbcdb, 0xba34, - 0xb797, 0xb506, 0xb280, 0xb006, 0xad98, 0xab37, 0xa8e3, 0xa69d, - 0xa464, 0xa239, 0xa01d, 0x9e10, 0x9c12, 0x9a23, 0x9844, 0x9675, - 0x94b6, 0x9308, 0x916a, 0x8fde, 0x8e63, 0x8cf9, 0x8ba1, 0x8a5b, - 0x8928, 0x8806, 0x86f7, 0x85fb, 0x8512, 0x843b, 0x8378, 0x82c7, - 0x822b, 0x81a1, 0x812b, 0x80c9, 0x807a, 0x803f, 0x8017, 0x8003, - 0x8003, 0x8017, 0x803f, 0x807a, 0x80c9, 0x812b, 0x81a1, 0x822b, - 0x82c7, 0x8378, 0x843b, 0x8512, 0x85fb, 0x86f7, 0x8806, 0x8928, - 0x8a5b, 0x8ba1, 0x8cf9, 0x8e63, 0x8fde, 0x916a, 0x9308, 0x94b6, - 0x9675, 0x9844, 0x9a23, 0x9c12, 0x9e10, 0xa01d, 0xa239, 0xa464, - 0xa69d, 0xa8e3, 0xab37, 0xad98, 0xb006, 0xb280, 0xb506, 0xb797, - 0xba34, 0xbcdb, 0xbf8d, 0xc249, 0xc50e, 0xc7dc, 0xcab3, 0xcd93, - 0xd07a, 0xd368, 0xd65d, 0xd959, 0xdc5a, 0xdf62, 0xe26e, 0xe57e, - 0xe893, 0xebac, 0xeec7, 0xf1e5, 0xf506, 0xf828, 0xfb4b, 0xfe6f, - 0x7cc3, 0x725e, 0x68d5, 0x6017, 0x5813, 0x50b9, 0x49fb, 0x43cd, - 0x3e22, 0x38ef, 0x342b, 0x2fcc, 0x2bc9, 0x281c, 0x24be, 0x21a6, - 0x1ed1, 0x1c37, 0x19d5, 0x17a6, 0x15a5, 0x13ce, 0x121f, 0x1093, - 0x0f28, 0x0ddc, 0x0cab, 0x0b93, 0x0a92, 0x09a7, 0x08cf, 0x080a, - 0x0754, 0x06ae, 0x0615, 0x0589, 0x0509, 0x0494, 0x0428, 0x03c5, - 0x036a, 0x0317, 0x02cb, 0x0285, 0x0245, 0x020a, 0x01d4, 0x01a2, - 0x0175, 0x014b, 0x0125, 0x0102, 0x00e2, 0x00c5, 0x00aa, 0x0091, - 0x007b, 0x0066, 0x0053, 0x0041, 0x0031, 0x0022, 0x0015, 0x0009, - 0xfffe, 0xfff2, 0xffe5, 0xffd7, 0xffc8, 0xffb7, 0xffa5, 0xff91, - 0xff7b, 0xff64, 0xff4a, 0xff2e, 0xff0f, 0xfeee, 0xfec9, 0xfea1, - 0xfe76, 0xfe46, 0xfe13, 0xfdda, 0xfd9d, 0xfd5a, 0xfd11, 0xfcc1, - 0xfc6b, 0xfc0c, 0xfba5, 0xfb34, 0xfab9, 0xfa33, 0xf9a1, 0xf902, - 0xf854, 0xf797, 0xf6c8, 0xf5e7, 0xf4f1, 0xf3e5, 0xf2c1, 0xf183, - 0xf027, 0xeeac, 0xed0f, 0xeb4d, 0xe961, 0xe74a, 0xe501, 0xe284, - 0xdfcd, 0xdcd8, 0xd99d, 0xd618, 0xd242, 0xce12, 0xc982, 0xc487, - 0xbf1a, 0xb92e, 0xb2ba, 0xabaf, 0xa402, 0x9ba3, 0x9282, 0x888d, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0004, 0x0006, 0x0008, 0x000a, 0x000c, 0x000e, 0x0010, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0006, 0x000a, 0x000e, - 0x0010, 0x0014, 0x0016, 0x0018, 0x001a, 0x001c, 0x001e, 0x0020, - 0x0000, 0x0000, 0x0000, 0x000a, 0x0010, 0x0016, 0x001a, 0x001e, - 0x0020, 0x0024, 0x0026, 0x0028, 0x002a, 0x002c, 0x002e, 0x0030, - 0x0000, 0x0000, 0x0010, 0x001a, 0x0020, 0x0026, 0x002a, 0x002e, - 0x0030, 0x0034, 0x0036, 0x0038, 0x003a, 0x003c, 0x003e, 0x0040, - 0x0000, 0x0010, 0x0020, 0x002a, 0x0030, 0x0036, 0x003a, 0x003e, - 0x0040, 0x0044, 0x0046, 0x0048, 0x004a, 0x004c, 0x004e, 0x0050, - 0x0000, 0x0020, 0x0030, 0x003a, 0x0040, 0x0046, 0x004a, 0x004e, - 0x0050, 0x0054, 0x0056, 0x0058, 0x005a, 0x005c, 0x005e, 0x0060, - 0x0000, 0x0030, 0x0040, 0x004a, 0x0050, 0x0056, 0x005a, 0x005e, - 0x0060, 0x0064, 0x0066, 0x0068, 0x006a, 0x006c, 0x006e, 0x0070, - 0x0008, 0x0021, 0x0042, 0x0064, 0x0086, 0x00a8, 0x00cb, 0x00ee, - 0x0111, 0x0135, 0x0158, 0x017d, 0x01a1, 0x01c6, 0x01eb, 0x0211, - 0x0236, 0x025d, 0x0283, 0x02aa, 0x02d1, 0x02f9, 0x0321, 0x0349, - 0x0372, 0x039b, 0x03c4, 0x03ee, 0x0418, 0x0442, 0x046d, 0x0499, - 0x04c4, 0x04f0, 0x051d, 0x054a, 0x0577, 0x05a5, 0x05d3, 0x0601, - 0x0630, 0x0660, 0x0690, 0x06c0, 0x06f1, 0x0722, 0x0753, 0x0785, - 0x07b8, 0x07eb, 0x081e, 0x0852, 0x0886, 0x08bb, 0x08f0, 0x0926, - 0x095c, 0x0993, 0x09ca, 0x0a02, 0x0a3a, 0x0a73, 0x0aac, 0x0ae6, - 0x0b20, 0x0b5b, 0x0b96, 0x0bd2, 0x0c0e, 0x0c4b, 0x0c89, 0x0cc7, - 0x0d05, 0x0d44, 0x0d84, 0x0dc5, 0x0e05, 0x0e47, 0x0e89, 0x0ecc, - 0x0f0f, 0x0f53, 0x0f97, 0x0fdd, 0x1022, 0x1069, 0x10b0, 0x10f7, - 0x1140, 0x1189, 0x11d2, 0x121c, 0x1267, 0x12b3, 0x12ff, 0x134c, - 0x139a, 0x13e8, 0x1438, 0x1487, 0x14d8, 0x1529, 0x157b, 0x15ce, - 0x1621, 0x1676, 0x16cb, 0x1720, 0x1777, 0x17ce, 0x1826, 0x187f, - 0x18d9, 0x1934, 0x198f, 0x19eb, 0x1a48, 0x1aa6, 0x1b05, 0x1b64, - 0x1bc5, 0x1c26, 0x1c88, 0x1ceb, 0x1d4f, 0x1db4, 0x1e1a, 0x1e80, - 0x1ee8, 0x1f51, 0x1fba, 0x2025, 0x2090, 0x20fc, 0x216a, 0x21d8, - 0x2247, 0x22b8, 0x2329, 0x239b, 0x240f, 0x2483, 0x24f9, 0x256f, - 0x25e7, 0x2660, 0x26da, 0x2755, 0x27d1, 0x284e, 0x28cc, 0x294b, - 0x29cc, 0x2a4e, 0x2ad1, 0x2b55, 0x2bda, 0x2c61, 0x2ce8, 0x2d71, - 0x2dfb, 0x2e87, 0x2f13, 0x2fa1, 0x3031, 0x30c1, 0x3153, 0x31e6, - 0x327b, 0x3310, 0x33a8, 0x3440, 0x34da, 0x3575, 0x3612, 0x36b0, - 0x3750, 0x37f1, 0x3893, 0x3937, 0x39dc, 0x3a83, 0x3b2c, 0x3bd6, - 0x3c81, 0x3d2e, 0x3ddd, 0x3e8d, 0x3f3f, 0x3ff2, 0x40a7, 0x415d, - 0x4216, 0x42d0, 0x438b, 0x4448, 0x4507, 0x45c8, 0x468b, 0x474f, - 0x4815, 0x48dd, 0x49a6, 0x4a72, 0x4b3f, 0x4c0e, 0x4cdf, 0x4db2, - 0x4e87, 0x4f5d, 0x5036, 0x5111, 0x51ed, 0x52cc, 0x53ac, 0x548f, - 0x5573, 0x565a, 0x5743, 0x582e, 0x591b, 0x5a0a, 0x5afb, 0x5bef, - 0x5ce4, 0x5ddc, 0x5ed7, 0x5fd3, 0x60d2, 0x61d3, 0x62d6, 0x63dc, - 0x64e4, 0x65ee, 0x66fb, 0x680a, 0x691c, 0x6a30, 0x6b47, 0x6c60, - 0x6d7c, 0x6e9a, 0x6fbb, 0x70de, 0x7204, 0x732d, 0x7459, 0x7587, - 0x76b8, 0x77eb, 0x7922, 0x7a5b, 0x7b97, 0x7cd6, 0x7e18, 0x7f5d, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 0x0002, 0x0002, 0x0003, - 0x0003, 0x0004, 0x0004, 0x0005, 0x0006, 0x0008, 0x0009, 0x000a, - 0x000c, 0x0010, 0x0012, 0x0015, 0x0019, 0x0022, 0x0024, 0x002a, - 0x0031, 0x003e, 0x0049, 0x0055, 0x0062, 0x007c, 0x0092, 0x00a9, - 0x00c4, 0x00fc, 0x0125, 0x0152, 0x0187, 0x01f2, 0x024a, 0x02a4, - 0x030d, 0x03e3, 0x0492, 0x0547, 0x061b, 0x07c7, 0x0923, 0x0a8d, - 0x0c19, 0x0eb3, 0x1228, 0x14c1, 0x17fb, 0x1d17, 0x22f2, 0x2835, - 0x2dd4, 0x3cd0, 0x4cf5, 0x51cc, 0x7fff, 0x7fff, 0x7fff, 0x7fff, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0002, 0x0002, - 0x0002, 0x0003, 0x0004, 0x0005, 0x0005, 0x0007, 0x0008, 0x000a, - 0x000b, 0x000e, 0x0011, 0x0014, 0x0017, 0x001c, 0x0022, 0x0028, - 0x002e, 0x0039, 0x0045, 0x0050, 0x005c, 0x0073, 0x008a, 0x00a0, - 0x00b9, 0x00e7, 0x0114, 0x0141, 0x0172, 0x01ce, 0x0228, 0x0283, - 0x02e3, 0x039b, 0x0454, 0x0501, 0x05bf, 0x072a, 0x0899, 0x0a18, - 0x0b7e, 0x0e55, 0x10d3, 0x1404, 0x16c3, 0x16c3, 0x16c3, 0x16c3, - 0x0012, 0x0024, 0x0048, 0x006c, 0x0090, 0x00b4, 0x00d8, 0x00fc, - 0x0120, 0x0144, 0x0168, 0x0168, 0x01b0, 0x01b0, 0x021c, 0x021c, - 0x0000, 0x0003, 0x0008, 0x000b, 0x0001, 0x0004, 0x0009, 0x000c, - 0x0002, 0x0005, 0x000a, 0x000d, 0x0010, 0x0013, 0x0011, 0x0014, - 0x0012, 0x0015, 0x0100, 0x0103, 0x0108, 0x010b, 0x0101, 0x0104, - 0x0109, 0x010c, 0x0102, 0x0105, 0x010a, 0x010d, 0x0110, 0x0113, - 0x0111, 0x0114, 0x0112, 0x0115 }; diff --git a/sound/oss/maui.c b/sound/oss/maui.c index 0c0d53e87..05cf194ed 100644 --- a/sound/oss/maui.c +++ b/sound/oss/maui.c @@ -420,8 +420,8 @@ static struct address_info cfg; static int __initdata io = -1; static int __initdata irq = -1; -MODULE_PARM(io,"i"); -MODULE_PARM(irq,"i"); +module_param(io, int, 0); +module_param(irq, int, 0); /* * Install a Maui card. Needs mpu401 loaded already. diff --git a/sound/oss/midibuf.c b/sound/oss/midibuf.c index 615b5c8c7..b2676fa34 100644 --- a/sound/oss/midibuf.c +++ b/sound/oss/midibuf.c @@ -53,7 +53,7 @@ static void midi_poll(unsigned long dummy); static struct timer_list poll_timer = TIMER_INITIALIZER(midi_poll, 0, 0); static volatile int open_devs; -static spinlock_t lock=SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(lock); #define DATA_AVAIL(q) (q->len) #define SPACE_AVAIL(q) (MAX_QUEUE_SIZE - q->len) diff --git a/sound/oss/mpu401.c b/sound/oss/mpu401.c index 73c3ce32a..b66f53fa8 100644 --- a/sound/oss/mpu401.c +++ b/sound/oss/mpu401.c @@ -1770,8 +1770,8 @@ static struct address_info cfg; static int io = -1; static int irq = -1; -MODULE_PARM(irq, "i"); -MODULE_PARM(io, "i"); +module_param(irq, int, 0); +module_param(io, int, 0); static int __init init_mpu401(void) { diff --git a/sound/oss/nm256_audio.c b/sound/oss/nm256_audio.c index 228ce6a00..f9166e135 100644 --- a/sound/oss/nm256_audio.c +++ b/sound/oss/nm256_audio.c @@ -157,7 +157,7 @@ static int samplerates[9] = { * attempted. */ -int +static int nm256_setInfo (int dev, struct nm256_info *card) { int x; @@ -1047,7 +1047,7 @@ nm256_peek_for_sig (struct nm256_info *card) * VERSTR is a human-readable version string. */ -static int __init +static int __devinit nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr) { struct nm256_info *card; @@ -1673,17 +1673,17 @@ MODULE_DEVICE_TABLE(pci, nm256_pci_tbl); MODULE_LICENSE("GPL"); -struct pci_driver nm256_pci_driver = { +static struct pci_driver nm256_pci_driver = { .name = "nm256_audio", .id_table = nm256_pci_tbl, .probe = nm256_probe, .remove = nm256_remove, }; -MODULE_PARM (usecache, "i"); -MODULE_PARM (buffertop, "i"); -MODULE_PARM (nm256_debug, "i"); -MODULE_PARM (force_load, "i"); +module_param(usecache, bool, 0); +module_param(buffertop, int, 0); +module_param(nm256_debug, bool, 0644); +module_param(force_load, bool, 0); static int __init do_init_nm256(void) { diff --git a/sound/oss/opl3.c b/sound/oss/opl3.c index 9789c5ab2..a31734b78 100644 --- a/sound/oss/opl3.c +++ b/sound/oss/opl3.c @@ -1202,7 +1202,7 @@ static int me; static int io = -1; -MODULE_PARM(io, "i"); +module_param(io, int, 0); static int __init init_opl3 (void) { diff --git a/sound/oss/opl3sa2.c b/sound/oss/opl3sa2.c index 7d7a98173..2efbd8651 100644 --- a/sound/oss/opl3sa2.c +++ b/sound/oss/opl3sa2.c @@ -177,9 +177,6 @@ static int __initdata loopback = -1; static int __initdata isapnp = 1; static int __initdata multiple = 1; -/* PnP devices */ -struct pnp_dev* opl3sa2_dev[OPL3SA2_CARDS_MAX]; - /* Whether said devices have been activated */ static int opl3sa2_activated[OPL3SA2_CARDS_MAX]; #else @@ -192,35 +189,35 @@ MODULE_AUTHOR("Scott Murray <scott@spiteful.org>"); MODULE_LICENSE("GPL"); -MODULE_PARM(io, "i"); +module_param(io, int, 0); MODULE_PARM_DESC(io, "Set I/O base of OPL3-SA2 or SA3 card (usually 0x370. Address must be even and must be from 0x100 to 0xFFE)"); -MODULE_PARM(mss_io, "i"); +module_param(mss_io, int, 0); MODULE_PARM_DESC(mss_io, "Set MSS (audio) I/O base (0x530, 0xE80, or other. Address must end in 0 or 4 and must be from 0x530 to 0xF48)"); -MODULE_PARM(mpu_io, "i"); +module_param(mpu_io, int, 0); MODULE_PARM_DESC(mpu_io, "Set MIDI I/O base (0x330 or other. Address must be even and must be from 0x300 to 0x334)"); -MODULE_PARM(irq, "i"); -MODULE_PARM_DESC(mss_irq, "Set MSS (audio) IRQ (5, 7, 9, 10, 11, 12)"); +module_param(irq, int, 0); +MODULE_PARM_DESC(irq, "Set MSS (audio) IRQ (5, 7, 9, 10, 11, 12)"); -MODULE_PARM(dma, "i"); +module_param(dma, int, 0); MODULE_PARM_DESC(dma, "Set MSS (audio) first DMA channel (0, 1, 3)"); -MODULE_PARM(dma2, "i"); +module_param(dma2, int, 0); MODULE_PARM_DESC(dma2, "Set MSS (audio) second DMA channel (0, 1, 3)"); -MODULE_PARM(ymode, "i"); +module_param(ymode, int, 0); MODULE_PARM_DESC(ymode, "Set Yamaha 3D enhancement mode (0 = Desktop/Normal, 1 = Notebook PC (1), 2 = Notebook PC (2), 3 = Hi-Fi)"); -MODULE_PARM(loopback, "i"); +module_param(loopback, int, 0); MODULE_PARM_DESC(loopback, "Set A/D input source. Useful for echo cancellation (0 = Mic Rch (default), 1 = Mono output loopback)"); #ifdef CONFIG_PNP -MODULE_PARM(isapnp, "i"); +module_param(isapnp, bool, 0); MODULE_PARM_DESC(isapnp, "When set to 0, ISA PnP support will be disabled"); -MODULE_PARM(multiple, "i"); +module_param(multiple, bool, 0); MODULE_PARM_DESC(multiple, "When set to 0, will not search for multiple cards"); #endif @@ -714,7 +711,7 @@ static void __init attach_opl3sa2_mixer(struct address_info *hw_config, int card } -static void __init opl3sa2_clear_slots(struct address_info* hw_config) +static void opl3sa2_clear_slots(struct address_info* hw_config) { int i; @@ -775,7 +772,7 @@ static void __exit unload_opl3sa2(struct address_info* hw_config, int card) } #ifdef CONFIG_PNP -struct pnp_device_id pnp_opl3sa2_list[] = { +static struct pnp_device_id pnp_opl3sa2_list[] = { {.id = "YMH0021", .driver_data = 0}, {.id = ""} }; @@ -835,7 +832,7 @@ static struct pnp_driver opl3sa2_driver = { /* End of component functions */ #ifdef CONFIG_PM -static spinlock_t opl3sa2_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(opl3sa2_lock); /* Power Management support functions */ static int opl3sa2_suspend(struct pm_dev *pdev, unsigned int pm_mode) diff --git a/sound/oss/pss.c b/sound/oss/pss.c index af3f96ad0..3ed38765d 100644 --- a/sound/oss/pss.c +++ b/sound/oss/pss.c @@ -118,9 +118,9 @@ /* If compiled into kernel, it enable or disable pss mixer */ #ifdef CONFIG_PSS_MIXER -static unsigned char pss_mixer = 1; +static int pss_mixer = 1; #else -static unsigned char pss_mixer; +static int pss_mixer; #endif @@ -143,7 +143,7 @@ typedef struct pss_confdata { static pss_confdata pss_data; static pss_confdata *devc = &pss_data; -static spinlock_t lock=SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(lock); static int pss_initialized; static int nonstandard_microcode; @@ -649,7 +649,7 @@ static struct mixer_operations pss_mixer_operations = .ioctl = pss_mixer_ioctl }; -void disable_all_emulations(void) +static void disable_all_emulations(void) { outw(0x0000, REG(CONF_PSS)); /* 0x0400 enables joystick */ outw(0x0000, REG(CONF_WSS)); @@ -658,7 +658,7 @@ void disable_all_emulations(void) outw(0x0000, REG(CONF_CDROM)); } -void configure_nonsound_components(void) +static void configure_nonsound_components(void) { /* Configure Joystick port */ @@ -1149,33 +1149,33 @@ static int mss_irq __initdata = -1; static int mss_dma __initdata = -1; static int mpu_io __initdata = -1; static int mpu_irq __initdata = -1; -static int pss_no_sound __initdata = 0; /* Just configure non-sound components */ +static int pss_no_sound = 0; /* Just configure non-sound components */ static int pss_keep_settings = 1; /* Keep hardware settings at module exit */ static char *pss_firmware = "/etc/sound/pss_synth"; -MODULE_PARM(pss_io, "i"); +module_param(pss_io, int, 0); MODULE_PARM_DESC(pss_io, "Set i/o base of PSS card (probably 0x220 or 0x240)"); -MODULE_PARM(mss_io, "i"); +module_param(mss_io, int, 0); MODULE_PARM_DESC(mss_io, "Set WSS (audio) i/o base (0x530, 0x604, 0xE80, 0xF40, or other. Address must end in 0 or 4 and must be from 0x100 to 0xFF4)"); -MODULE_PARM(mss_irq, "i"); +module_param(mss_irq, int, 0); MODULE_PARM_DESC(mss_irq, "Set WSS (audio) IRQ (3, 5, 7, 9, 10, 11, 12)"); -MODULE_PARM(mss_dma, "i"); +module_param(mss_dma, int, 0); MODULE_PARM_DESC(mss_dma, "Set WSS (audio) DMA (0, 1, 3)"); -MODULE_PARM(mpu_io, "i"); +module_param(mpu_io, int, 0); MODULE_PARM_DESC(mpu_io, "Set MIDI i/o base (0x330 or other. Address must be on 4 location boundaries and must be from 0x100 to 0xFFC)"); -MODULE_PARM(mpu_irq, "i"); +module_param(mpu_irq, int, 0); MODULE_PARM_DESC(mpu_irq, "Set MIDI IRQ (3, 5, 7, 9, 10, 11, 12)"); -MODULE_PARM(pss_cdrom_port, "i"); +module_param(pss_cdrom_port, int, 0); MODULE_PARM_DESC(pss_cdrom_port, "Set the PSS CDROM port i/o base (0x340 or other)"); -MODULE_PARM(pss_enable_joystick, "i"); +module_param(pss_enable_joystick, bool, 0); MODULE_PARM_DESC(pss_enable_joystick, "Enables the PSS joystick port (1 to enable, 0 to disable)"); -MODULE_PARM(pss_no_sound, "i"); +module_param(pss_no_sound, bool, 0); MODULE_PARM_DESC(pss_no_sound, "Configure sound compoents (0 - no, 1 - yes)"); -MODULE_PARM(pss_keep_settings, "i"); +module_param(pss_keep_settings, bool, 0); MODULE_PARM_DESC(pss_keep_settings, "Keep hardware setting at driver unloading (0 - no, 1 - yes)"); -MODULE_PARM(pss_firmware, "s"); +module_param(pss_firmware, charp, 0); MODULE_PARM_DESC(pss_firmware, "Location of the firmware file (default - /etc/sound/pss_synth)"); -MODULE_PARM(pss_mixer, "b"); +module_param(pss_mixer, bool, 0); MODULE_PARM_DESC(pss_mixer, "Enable (1) or disable (0) PSS mixer (controlling of output volume, bass, treble, synth volume). The mixer is not available on all PSS cards."); MODULE_AUTHOR("Hannu Savolainen, Vladimir Michl"); MODULE_DESCRIPTION("Module for PSS sound cards (based on AD1848, ADSP-2115 and ESC614). This module includes control of output amplifier and synth volume of the Beethoven ADSP-16 card (this may work with other PSS cards)."); diff --git a/sound/oss/sb_card.c b/sound/oss/sb_card.c index 07191b3ae..680b82e15 100644 --- a/sound/oss/sb_card.c +++ b/sound/oss/sb_card.c @@ -26,9 +26,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/init.h> -#ifdef CONFIG_MCA -#include <linux/mca.h> -#endif /* CONFIG_MCA */ #include "sound_config.h" #include "sb_mixer.h" #include "sb.h" @@ -52,7 +49,7 @@ static int __initdata esstype = 0; /* ESS chip type */ static int __initdata acer = 0; /* Do acer notebook init? */ static int __initdata sm_games = 0; /* Logitech soundman games? */ -struct sb_card_config *legacy = NULL; +static struct sb_card_config *legacy = NULL; #ifdef CONFIG_PNP static int __initdata pnp = 1; @@ -289,6 +286,7 @@ static struct pnp_card_driver sb_pnp_driver = { .probe = sb_pnp_probe, .remove = sb_pnp_remove, }; +MODULE_DEVICE_TABLE(pnp_card, sb_pnp_card_table); #endif /* CONFIG_PNP */ static int __init sb_init(void) diff --git a/sound/oss/sequencer.c b/sound/oss/sequencer.c index 038bf7fd3..698614226 100644 --- a/sound/oss/sequencer.c +++ b/sound/oss/sequencer.c @@ -28,7 +28,7 @@ static int pending_timer = -1; /* For timer change operation */ extern unsigned long seq_time; static int obsolete_api_used; -static spinlock_t lock=SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(lock); /* * Local counts for number of synth and MIDI devices. These are initialized @@ -1091,7 +1091,7 @@ int sequencer_open(int dev, struct file *file) return 0; } -void seq_drain_midi_queues(void) +static void seq_drain_midi_queues(void) { int i, n; diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c index f25c75ec5..de91c90a0 100644 --- a/sound/oss/soundcard.c +++ b/sound/oss/soundcard.c @@ -329,7 +329,7 @@ static int sound_mixer_ioctl(int mixdev, unsigned int cmd, void __user *arg) static int sound_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - int err, len = 0, dtype; + int len = 0, dtype; int dev = iminor(inode); void __user *p = (void __user *)arg; @@ -341,11 +341,11 @@ static int sound_ioctl(struct inode *inode, struct file *file, if (len < 1 || len > 65536 || !p) return -EFAULT; if (_SIOC_DIR(cmd) & _SIOC_WRITE) - if ((err = verify_area(VERIFY_READ, p, len)) < 0) - return err; + if (!access_ok(VERIFY_READ, p, len)) + return -EFAULT; if (_SIOC_DIR(cmd) & _SIOC_READ) - if ((err = verify_area(VERIFY_WRITE, p, len)) < 0) - return err; + if (!access_ok(VERIFY_WRITE, p, len)) + return -EFAULT; } DEB(printk("sound_ioctl(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg)); if (cmd == OSS_GETVERSION) @@ -535,8 +535,8 @@ static const struct { static int dmabuf; static int dmabug; -MODULE_PARM(dmabuf, "i"); -MODULE_PARM(dmabug, "i"); +module_param(dmabuf, int, 0444); +module_param(dmabug, int, 0444); static int __init oss_init(void) { diff --git a/sound/oss/sscape.c b/sound/oss/sscape.c index 7c9b5d41b..50ca64629 100644 --- a/sound/oss/sscape.c +++ b/sound/oss/sscape.c @@ -1393,20 +1393,20 @@ static struct address_info cfg; static struct address_info cfg_mpu; static int __initdata spea = -1; -static int __initdata mss = 0; +static int mss = 0; static int __initdata dma = -1; static int __initdata irq = -1; static int __initdata io = -1; static int __initdata mpu_irq = -1; static int __initdata mpu_io = -1; -MODULE_PARM(dma, "i"); -MODULE_PARM(irq, "i"); -MODULE_PARM(io, "i"); -MODULE_PARM(spea, "i"); /* spea=0/1 set the old_hardware */ -MODULE_PARM(mpu_irq, "i"); -MODULE_PARM(mpu_io, "i"); -MODULE_PARM(mss, "i"); +module_param(dma, int, 0); +module_param(irq, int, 0); +module_param(io, int, 0); +module_param(spea, int, 0); /* spea=0/1 set the old_hardware */ +module_param(mpu_irq, int, 0); +module_param(mpu_io, int, 0); +module_param(mss, int, 0); static int __init init_sscape(void) { diff --git a/sound/oss/sys_timer.c b/sound/oss/sys_timer.c index 3b7fa02cb..6afe29b76 100644 --- a/sound/oss/sys_timer.c +++ b/sound/oss/sys_timer.c @@ -27,7 +27,7 @@ static volatile unsigned long next_event_time; static unsigned long prev_event_time; static void poll_def_tmr(unsigned long dummy); -static spinlock_t lock=SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(lock); static struct timer_list def_tmr = TIMER_INITIALIZER(poll_def_tmr, 0, 0); diff --git a/sound/oss/trident.c b/sound/oss/trident.c index 47b129f3a..47537f0a5 100644 --- a/sound/oss/trident.c +++ b/sound/oss/trident.c @@ -441,7 +441,7 @@ struct trident_card { struct timer_list timer; /* Game port support */ - struct gameport gameport; + struct gameport *gameport; }; enum dmabuf_mode { @@ -487,7 +487,7 @@ static struct trident_channel *ali_alloc_rec_pcm_channel(struct trident_card *ca static struct trident_channel *ali_alloc_pcm_channel(struct trident_card *card); static void ali_restore_regs(struct trident_card *card); static void ali_save_regs(struct trident_card *card); -static int trident_suspend(struct pci_dev *dev, u32 unused); +static int trident_suspend(struct pci_dev *dev, pm_message_t unused); static int trident_resume(struct pci_dev *dev); static void ali_free_pcm_channel(struct trident_card *card, unsigned int channel); static int ali_setup_multi_channels(struct trident_card *card, int chan_nums); @@ -3723,7 +3723,7 @@ ali_restore_regs(struct trident_card *card) } static int -trident_suspend(struct pci_dev *dev, u32 unused) +trident_suspend(struct pci_dev *dev, pm_message_t unused) { struct trident_card *card = pci_get_drvdata(dev); @@ -4014,7 +4014,8 @@ ali_free_other_states_resources(struct trident_state *state) } } -struct proc_dir_entry *res; +static struct proc_dir_entry *res; + static int ali_write_proc(struct file *file, const char __user *buffer, unsigned long count, void *data) { @@ -4256,21 +4257,21 @@ trident_ac97_init(struct trident_card *card) static unsigned char trident_game_read(struct gameport *gameport) { - struct trident_card *card = gameport->driver; + struct trident_card *card = gameport->port_data; return inb(TRID_REG(card, T4D_GAME_LEG)); } static void trident_game_trigger(struct gameport *gameport) { - struct trident_card *card = gameport->driver; + struct trident_card *card = gameport->port_data; outb(0xff, TRID_REG(card, T4D_GAME_LEG)); } static int trident_game_cooked_read(struct gameport *gameport, int *axes, int *buttons) { - struct trident_card *card = gameport->driver; + struct trident_card *card = gameport->port_data; int i; *buttons = (~inb(TRID_REG(card, T4D_GAME_LEG)) >> 4) & 0xf; @@ -4287,7 +4288,7 @@ trident_game_cooked_read(struct gameport *gameport, int *axes, int *buttons) static int trident_game_open(struct gameport *gameport, int mode) { - struct trident_card *card = gameport->driver; + struct trident_card *card = gameport->port_data; switch (mode) { case GAMEPORT_MODE_COOKED: @@ -4304,6 +4305,31 @@ trident_game_open(struct gameport *gameport, int mode) return 0; } +static int __devinit +trident_register_gameport(struct trident_card *card) +{ + struct gameport *gp; + + card->gameport = gp = gameport_allocate_port(); + if (!gp) { + printk(KERN_ERR "trident: can not allocate memory for gameport\n"); + return -ENOMEM; + } + + gameport_set_name(gp, "Trident 4DWave"); + gameport_set_phys(gp, "pci%s/gameport0", pci_name(card->pci_dev)); + gp->read = trident_game_read; + gp->trigger = trident_game_trigger; + gp->cooked_read = trident_game_cooked_read; + gp->open = trident_game_open; + gp->fuzz = 64; + gp->port_data = card; + + gameport_register_port(gp); + + return 0; +} + /* install the driver, we do not allocate hardware channel nor DMA buffer */ /* now, they are defered until "ACCESS" time (in prog_dmabuf called by */ /* open/read/write/ioctl/mmap) */ @@ -4367,13 +4393,6 @@ trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) card->banks[BANK_B].addresses = &bank_b_addrs; card->banks[BANK_B].bitmap = 0UL; - card->gameport.driver = card; - card->gameport.fuzz = 64; - card->gameport.read = trident_game_read; - card->gameport.trigger = trident_game_trigger; - card->gameport.cooked_read = trident_game_cooked_read; - card->gameport.open = trident_game_open; - init_MUTEX(&card->open_sem); spin_lock_init(&card->lock); init_timer(&card->timer); @@ -4507,7 +4526,7 @@ trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) trident_enable_loop_interrupts(card); /* Register gameport */ - gameport_register_port(&card->gameport); + trident_register_gameport(card); out: return rc; @@ -4550,7 +4569,8 @@ trident_remove(struct pci_dev *pci_dev) } /* Unregister gameport */ - gameport_unregister_port(&card->gameport); + if (card->gameport) + gameport_unregister_port(card->gameport); /* Kill interrupts, and SP/DIF */ trident_disable_loop_interrupts(card); diff --git a/sound/oss/via82cxxx_audio.c b/sound/oss/via82cxxx_audio.c index 58da28a9c..b387e1e52 100644 --- a/sound/oss/via82cxxx_audio.c +++ b/sound/oss/via82cxxx_audio.c @@ -62,11 +62,6 @@ } #endif -#if defined(CONFIG_PROC_FS) && \ - defined(CONFIG_SOUND_VIA82CXXX_PROCFS) -#define VIA_PROC_FS 1 -#endif - #define VIA_SUPPORT_MMAP 1 /* buggy, for now... */ #define MAX_CARDS 1 @@ -366,18 +361,6 @@ static void via_chan_clear (struct via_info *card, struct via_channel *chan); static void via_chan_pcm_fmt (struct via_channel *chan, int reset); static void via_chan_buffer_free (struct via_info *card, struct via_channel *chan); -#ifdef VIA_PROC_FS -static int via_init_proc (void); -static void via_cleanup_proc (void); -static int via_card_init_proc (struct via_info *card); -static void via_card_cleanup_proc (struct via_info *card); -#else -static inline int via_init_proc (void) { return 0; } -static inline void via_cleanup_proc (void) {} -static inline int via_card_init_proc (struct via_info *card) { return 0; } -static inline void via_card_cleanup_proc (struct via_info *card) {} -#endif - /**************************************************************** * @@ -2179,7 +2162,7 @@ static int via_mm_swapout (struct page *page, struct file *filp) #endif /* VM_RESERVED */ -struct vm_operations_struct via_mm_ops = { +static struct vm_operations_struct via_mm_ops = { .nopage = via_mm_nopage, #ifndef VM_RESERVED @@ -3483,22 +3466,13 @@ static int __devinit via_init_one (struct pci_dev *pdev, const struct pci_device goto err_out_have_mixer; } - /* - * per-card /proc info - */ - rc = via_card_init_proc (card); - if (rc) { - printk (KERN_ERR PFX "card-specific /proc init failed, aborting\n"); - goto err_out_have_dsp; - } - /* * init and turn on interrupts, as the last thing we do */ rc = via_interrupt_init (card); if (rc) { printk (KERN_ERR PFX "interrupt init failed, aborting\n"); - goto err_out_have_proc; + goto err_out_have_dsp; } printk (KERN_INFO PFX "board #%d at 0x%04lX, IRQ %d\n", @@ -3538,9 +3512,6 @@ static int __devinit via_init_one (struct pci_dev *pdev, const struct pci_device DPRINTK ("EXIT, returning 0\n"); return 0; -err_out_have_proc: - via_card_cleanup_proc (card); - err_out_have_dsp: via_dsp_cleanup (card); @@ -3582,7 +3553,6 @@ static void __devexit via_remove_one (struct pci_dev *pdev) #endif free_irq (card->pdev->irq, card); - via_card_cleanup_proc (card); via_dsp_cleanup (card); via_ac97_cleanup (card); @@ -3615,15 +3585,8 @@ static int __init init_via82cxxx_audio(void) DPRINTK ("ENTER\n"); - rc = via_init_proc (); - if (rc) { - DPRINTK ("EXIT, returning %d\n", rc); - return rc; - } - rc = pci_register_driver (&via_driver); if (rc) { - via_cleanup_proc (); DPRINTK ("EXIT, returning %d\n", rc); return rc; } @@ -3638,7 +3601,6 @@ static void __exit cleanup_via82cxxx_audio(void) DPRINTK ("ENTER\n"); pci_unregister_driver (&via_driver); - via_cleanup_proc (); DPRINTK ("EXIT\n"); } @@ -3651,181 +3613,3 @@ MODULE_AUTHOR("Jeff Garzik"); MODULE_DESCRIPTION("DSP audio and mixer driver for Via 82Cxxx audio devices"); MODULE_LICENSE("GPL"); - -#ifdef VIA_PROC_FS - -/**************************************************************** - * - * /proc/driver/via/info - * - * - */ - -static int via_info_read_proc (char *page, char **start, off_t off, - int count, int *eof, void *data) -{ -#define YN(val,bit) (((val) & (bit)) ? "yes" : "no") -#define ED(val,bit) (((val) & (bit)) ? "enable" : "disable") - - int len = 0; - u8 r40, r41, r42, r44; - struct via_info *card = data; - - DPRINTK ("ENTER\n"); - - assert (card != NULL); - - len += sprintf (page+len, VIA_CARD_NAME "\n\n"); - - pci_read_config_byte (card->pdev, 0x40, &r40); - pci_read_config_byte (card->pdev, 0x41, &r41); - pci_read_config_byte (card->pdev, 0x42, &r42); - pci_read_config_byte (card->pdev, 0x44, &r44); - - len += sprintf (page+len, - "Via 82Cxxx PCI registers:\n" - "\n" - "40 Codec Ready: %s\n" - " Codec Low-power: %s\n" - " Secondary Codec Ready: %s\n" - "\n" - "41 Interface Enable: %s\n" - " De-Assert Reset: %s\n" - " Force SYNC high: %s\n" - " Force SDO high: %s\n" - " Variable Sample Rate On-Demand Mode: %s\n" - " SGD Read Channel PCM Data Out: %s\n" - " FM Channel PCM Data Out: %s\n" - " SB PCM Data Out: %s\n" - "\n" - "42 Game port enabled: %s\n" - " SoundBlaster enabled: %s\n" - " FM enabled: %s\n" - " MIDI enabled: %s\n" - "\n" - "44 AC-Link Interface Access: %s\n" - " Secondary Codec Support: %s\n" - - "\n", - - YN (r40, VIA_CR40_AC97_READY), - YN (r40, VIA_CR40_AC97_LOW_POWER), - YN (r40, VIA_CR40_SECONDARY_READY), - - ED (r41, VIA_CR41_AC97_ENABLE), - YN (r41, (1 << 6)), - YN (r41, (1 << 5)), - YN (r41, (1 << 4)), - ED (r41, (1 << 3)), - ED (r41, (1 << 2)), - ED (r41, (1 << 1)), - ED (r41, (1 << 0)), - - YN (r42, VIA_CR42_GAME_ENABLE), - YN (r42, VIA_CR42_SB_ENABLE), - YN (r42, VIA_CR42_FM_ENABLE), - YN (r42, VIA_CR42_MIDI_ENABLE), - - YN (r44, VIA_CR44_AC_LINK_ACCESS), - YN (r44, VIA_CR44_SECOND_CODEC_SUPPORT) - - ); - - DPRINTK ("EXIT, returning %d\n", len); - return len; - -#undef YN -#undef ED -} - - -/**************************************************************** - * - * /proc/driver/via/... setup and cleanup - * - * - */ - -static int __init via_init_proc (void) -{ - DPRINTK ("ENTER\n"); - - if (!proc_mkdir ("driver/via", 0)) - return -EIO; - - DPRINTK ("EXIT, returning 0\n"); - return 0; -} - - -static void via_cleanup_proc (void) -{ - DPRINTK ("ENTER\n"); - - remove_proc_entry ("driver/via", NULL); - - DPRINTK ("EXIT\n"); -} - - -static int __devinit via_card_init_proc (struct via_info *card) -{ - char s[32]; - int rc; - - DPRINTK ("ENTER\n"); - - sprintf (s, "driver/via/%d", card->card_num); - if (!proc_mkdir (s, 0)) { - rc = -EIO; - goto err_out_none; - } - - sprintf (s, "driver/via/%d/info", card->card_num); - if (!create_proc_read_entry (s, 0, 0, via_info_read_proc, card)) { - rc = -EIO; - goto err_out_dir; - } - - sprintf (s, "driver/via/%d/ac97", card->card_num); - if (!create_proc_read_entry (s, 0, 0, ac97_read_proc, card->ac97)) { - rc = -EIO; - goto err_out_info; - } - - DPRINTK ("EXIT, returning 0\n"); - return 0; - -err_out_info: - sprintf (s, "driver/via/%d/info", card->card_num); - remove_proc_entry (s, NULL); - -err_out_dir: - sprintf (s, "driver/via/%d", card->card_num); - remove_proc_entry (s, NULL); - -err_out_none: - DPRINTK ("EXIT, returning %d\n", rc); - return rc; -} - - -static void via_card_cleanup_proc (struct via_info *card) -{ - char s[32]; - - DPRINTK ("ENTER\n"); - - sprintf (s, "driver/via/%d/ac97", card->card_num); - remove_proc_entry (s, NULL); - - sprintf (s, "driver/via/%d/info", card->card_num); - remove_proc_entry (s, NULL); - - sprintf (s, "driver/via/%d", card->card_num); - remove_proc_entry (s, NULL); - - DPRINTK ("EXIT\n"); -} - -#endif /* VIA_PROC_FS */ diff --git a/sound/oss/vwsnd.c b/sound/oss/vwsnd.c index ce519a9a9..265423054 100644 --- a/sound/oss/vwsnd.c +++ b/sound/oss/vwsnd.c @@ -256,7 +256,7 @@ static int __init li_create(lithium_t *lith, unsigned long baseaddr) { static void li_destroy(lithium_t *); - lith->lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&lith->lock); lith->page0 = ioremap_nocache(baseaddr + LI_PAGE0_OFFSET, PAGE_SIZE); lith->page1 = ioremap_nocache(baseaddr + LI_PAGE1_OFFSET, PAGE_SIZE); lith->page2 = ioremap_nocache(baseaddr + LI_PAGE2_OFFSET, PAGE_SIZE); @@ -3380,13 +3380,13 @@ static int __init attach_vwsnd(struct address_info *hw_config) init_MUTEX(&devc->io_sema); init_MUTEX(&devc->mix_sema); devc->open_mode = 0; - devc->rport.lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&devc->rport.lock); init_waitqueue_head(&devc->rport.queue); devc->rport.swstate = SW_OFF; devc->rport.hwstate = HW_STOPPED; devc->rport.flags = 0; devc->rport.swbuf = NULL; - devc->wport.lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&devc->wport.lock); init_waitqueue_head(&devc->wport.queue); devc->wport.swstate = SW_OFF; devc->wport.hwstate = HW_STOPPED; diff --git a/sound/oss/waveartist.c b/sound/oss/waveartist.c index 438e64ecb..99d04ad3c 100644 --- a/sound/oss/waveartist.c +++ b/sound/oss/waveartist.c @@ -146,7 +146,7 @@ typedef struct wavnc_port_info { static int nr_waveartist_devs; static wavnc_info adev_info[MAX_AUDIO_DEV]; -static spinlock_t waveartist_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(waveartist_lock); #ifndef CONFIG_ARCH_NETWINDER #define machine_is_netwinder() 0 diff --git a/sound/oss/wavfront.c b/sound/oss/wavfront.c index 4875565a0..cce1278dc 100644 --- a/sound/oss/wavfront.c +++ b/sound/oss/wavfront.c @@ -157,14 +157,14 @@ int wf_raw; /* we normally check for "raw state" to firmware board and load the firmware anyway. */ -int fx_raw = 1; /* if this is zero, we'll leave the FX processor in - whatever state it is when the driver is loaded. - The default is to download the microprogram and - associated coefficients to set it up for "default" - operation, whatever that means. - */ - -int debug_default; /* you can set this to control debugging +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. + The default is to download the microprogram and + associated coefficients to set it up for "default" + operation, whatever that means. + */ + +static int debug_default; /* you can set this to control debugging during driver loading. it takes any combination of the WF_DEBUG_* flags defined in wavefront.h @@ -172,44 +172,46 @@ int debug_default; /* you can set this to control debugging /* XXX this needs to be made firmware and hardware version dependent */ -char *ospath = "/etc/sound/wavefront.os"; /* where to find a processed - version of the WaveFront OS - */ +static char *ospath = "/etc/sound/wavefront.os"; /* where to find a processed + version of the WaveFront OS + */ -int wait_polls = 2000; /* This is a number of tries we poll the status register - before resorting to sleeping. WaveFront being an ISA - card each poll takes about 1.2us. So before going to - sleep we wait up to 2.4ms in a loop. - */ +static int wait_polls = 2000; /* This is a number of tries we poll the + status register before resorting to sleeping. + WaveFront being an ISA card each poll takes + about 1.2us. So before going to + sleep we wait up to 2.4ms in a loop. + */ -int sleep_length = HZ/100; /* This says how long we're going to sleep between polls. - 10ms sounds reasonable for fast response. - */ +static int sleep_length = HZ/100; /* This says how long we're going to + sleep between polls. + 10ms sounds reasonable for fast response. + */ -int sleep_tries = 50; /* Wait for status 0.5 seconds total. */ +static int sleep_tries = 50; /* Wait for status 0.5 seconds total. */ -int reset_time = 2; /* hundreths of a second we wait after a HW reset for +static int reset_time = 2; /* hundreths of a second we wait after a HW reset for the expected interrupt. */ -int ramcheck_time = 20; /* time in seconds to wait while ROM code - checks on-board RAM. - */ - -int osrun_time = 10; /* time in seconds we wait for the OS to - start running. - */ - -MODULE_PARM(wf_raw,"i"); -MODULE_PARM(fx_raw,"i"); -MODULE_PARM(debug_default,"i"); -MODULE_PARM(wait_polls,"i"); -MODULE_PARM(sleep_length,"i"); -MODULE_PARM(sleep_tries,"i"); -MODULE_PARM(ospath,"s"); -MODULE_PARM(reset_time,"i"); -MODULE_PARM(ramcheck_time,"i"); -MODULE_PARM(osrun_time,"i"); +static int ramcheck_time = 20; /* time in seconds to wait while ROM code + checks on-board RAM. + */ + +static int osrun_time = 10; /* time in seconds we wait for the OS to + start running. + */ + +module_param(wf_raw, int, 0); +module_param(fx_raw, int, 0); +module_param(debug_default, int, 0); +module_param(wait_polls, int, 0); +module_param(sleep_length, int, 0); +module_param(sleep_tries, int, 0); +module_param(ospath, charp, 0); +module_param(reset_time, int, 0); +module_param(ramcheck_time, int, 0); +module_param(osrun_time, int, 0); /***************************************************************************/ @@ -275,7 +277,7 @@ struct wf_config { wait_queue_head_t interrupt_sleeper; } dev; -static spinlock_t lock=SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(lock); static int detect_wffx(void); static int wffx_ioctl (wavefront_fx_info *); static int wffx_init (void); @@ -1516,45 +1518,56 @@ wavefront_load_gus_patch (int devno, int format, const char __user *addr, int offs, int count, int pmgr_flag) { struct patch_info guspatch; - wavefront_patch_info samp, pat, prog; + wavefront_patch_info *samp, *pat, *prog; wavefront_patch *patp; wavefront_sample *sampp; wavefront_program *progp; int i,base_note; long sizeof_patch; + int rc = -ENOMEM; + + samp = kmalloc(3 * sizeof(wavefront_patch_info), GFP_KERNEL); + if (!samp) + goto free_fail; + pat = samp + 1; + prog = pat + 1; /* Copy in the header of the GUS patch */ sizeof_patch = (long) &guspatch.data[0] - (long) &guspatch; if (copy_from_user(&((char *) &guspatch)[offs], - &(addr)[offs], sizeof_patch - offs)) - return -EFAULT; + &(addr)[offs], sizeof_patch - offs)) { + rc = -EFAULT; + goto free_fail; + } if ((i = wavefront_find_free_patch ()) == -1) { - return -EBUSY; + rc = -EBUSY; + goto free_fail; } - pat.number = i; - pat.subkey = WF_ST_PATCH; - patp = &pat.hdr.p; + pat->number = i; + pat->subkey = WF_ST_PATCH; + patp = &pat->hdr.p; if ((i = wavefront_find_free_sample ()) == -1) { - return -EBUSY; + rc = -EBUSY; + goto free_fail; } - samp.number = i; - samp.subkey = WF_ST_SAMPLE; - samp.size = guspatch.len; - sampp = &samp.hdr.s; + samp->number = i; + samp->subkey = WF_ST_SAMPLE; + samp->size = guspatch.len; + sampp = &samp->hdr.s; - prog.number = guspatch.instr_no; - progp = &prog.hdr.pr; + prog->number = guspatch.instr_no; + progp = &prog->hdr.pr; /* Setup the patch structure */ patp->amplitude_bias=guspatch.volume; patp->portamento=0; - patp->sample_number= samp.number & 0xff; - patp->sample_msb= samp.number>>8; + patp->sample_number= samp->number & 0xff; + patp->sample_msb= samp->number >> 8; patp->pitch_bend= /*12*/ 0; patp->mono=1; patp->retrigger=1; @@ -1587,7 +1600,7 @@ wavefront_load_gus_patch (int devno, int format, const char __user *addr, /* Program for this patch */ - progp->layer[0].patch_number= pat.number; /* XXX is this right ? */ + progp->layer[0].patch_number= pat->number; /* XXX is this right ? */ progp->layer[0].mute=1; progp->layer[0].pan_or_mod=1; progp->layer[0].pan=7; @@ -1635,11 +1648,11 @@ wavefront_load_gus_patch (int devno, int format, const char __user *addr, /* Now ship it down */ - wavefront_send_sample (&samp, + wavefront_send_sample (samp, (unsigned short __user *) &(addr)[sizeof_patch], (guspatch.mode & WAVE_UNSIGNED) ? 1:0); - wavefront_send_patch (&pat); - wavefront_send_program (&prog); + wavefront_send_patch (pat); + wavefront_send_program (prog); /* Now pan as best we can ... use the slave/internal MIDI device number if it exists (since it talks to the WaveFront), or the @@ -1651,8 +1664,11 @@ wavefront_load_gus_patch (int devno, int format, const char __user *addr, ((guspatch.panning << 4) > 127) ? 127 : (guspatch.panning << 4)); } + rc = 0; - return(0); +free_fail: + kfree(samp); + return rc; } static int @@ -2036,7 +2052,7 @@ wavefront_oss_ioctl (int devno, unsigned int cmd, void __user * arg) } } -int +static int wavefront_oss_load_patch (int devno, int format, const char __user *addr, int offs, int count, int pmgr_flag) { @@ -2165,7 +2181,7 @@ wavefrontintr(int irq, void *dev_id, struct pt_regs *dummy) 7 Unused */ -int +static int wavefront_interrupt_bits (int irq) { @@ -2193,7 +2209,7 @@ wavefront_interrupt_bits (int irq) return bits; } -void +static void wavefront_should_cause_interrupt (int val, int port, int timeout) { @@ -2895,16 +2911,6 @@ int __init detect_wffx (void) return 0; } -int __init attach_wffx (void) -{ - if ((dev.fx_mididev = sound_alloc_mididev ()) < 0) { - printk (KERN_WARNING LOGNAME "cannot install FX Midi driver\n"); - return -1; - } - - return 0; -} - void wffx_mute (int onoff) @@ -3490,8 +3496,8 @@ static int irq = -1; MODULE_AUTHOR ("Paul Barton-Davis <pbd@op.net>"); MODULE_DESCRIPTION ("Turtle Beach WaveFront Linux Driver"); MODULE_LICENSE("GPL"); -MODULE_PARM (io,"i"); -MODULE_PARM (irq,"i"); +module_param (io, int, 0); +module_param (irq, int, 0); static int __init init_wavfront (void) { diff --git a/sound/oss/wf_midi.c b/sound/oss/wf_midi.c index 3ced960e5..7b167b743 100644 --- a/sound/oss/wf_midi.c +++ b/sound/oss/wf_midi.c @@ -81,7 +81,7 @@ static struct wf_mpu_config *phys_dev = &devs[0]; static struct wf_mpu_config *virt_dev = &devs[1]; static void start_uart_mode (void); -static spinlock_t lock=SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(lock); #define OUTPUT_READY 0x40 #define INPUT_AVAIL 0x80 diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c index 3b9a8bd4f..d7a8f9f58 100644 --- a/sound/parisc/harmony.c +++ b/sound/parisc/harmony.c @@ -1,264 +1,88 @@ -/* - * Harmony chipset driver +/* Hewlett-Packard Harmony audio driver * - * This is a sound driver for ASP's and Lasi's Harmony sound chip - * and is unlikely to be used for anything other than on a HP PA-RISC. + * This is a driver for the Harmony audio chipset found + * on the LASI ASIC of various early HP PA-RISC workstations. * - * Harmony is found in HP 712s, 715/new and many other GSC based machines. - * On older 715 machines you'll find the technically identical chip - * called 'Vivace'. Both Harmony and Vivace are supported by this driver. + * Copyright (C) 2004, Kyle McMartin <kyle@{debian.org,parisc-linux.org}> * - * this ALSA driver is based on OSS driver by: - * Copyright 2000 (c) Linuxcare Canada, Alex deVries <alex@linuxcare.com> - * Copyright 2000-2002 (c) Helge Deller <deller@gmx.de> - * Copyright 2001 (c) Matthieu Delahaye <delahaym@esiee.fr> + * Based on the previous Harmony incarnations by, + * Copyright 2000 (c) Linuxcare Canada, Alex deVries + * Copyright 2000-2003 (c) Helge Deller + * Copyright 2001 (c) Matthieu Delahaye + * Copyright 2001 (c) Jean-Christophe Vaugeois + * Copyright 2003 (c) Laurent Canet + * Copyright 2004 (c) Stuart Brady * - * TODO: - * - use generic DMA interface and ioremap()/iounmap() - * - capture is still untested (and probaby non-working) - * - spin locks - * - implement non-consistent DMA pages - * - implement gain meter - * - module parameters - * - correct cleaning sequence - * - better error checking - * - try to have a better quality. - * - */ - -/* - * Harmony chipset 'modus operandi'. - * - This chipset is found in some HP 32bit workstations, like 712, or B132 class. - * most of controls are done through registers. Register are found at a fixed offset - * from the hard physical adress, given in struct dev by register_parisc_driver. + * 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. * - * Playback and recording use 4kb pages (dma or not, depending on the machine). + * 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. * - * Most of PCM playback & capture is done through interrupt. When harmony needs - * a new buffer to put recorded data or read played PCM, it sends an interrupt. - * Bits 2 and 10 of DSTATUS register are '1' when harmony needs respectively - * a new page for recording and playing. - * Interrupt are disabled/enabled by writing to bit 32 of DSTATUS. - * Adresses of next page to be played is put in PNXTADD register, next page - * to be recorded is put in RNXTADD. There is 2 read-only registers, PCURADD and - * RCURADD that provides adress of current page. - * - * Harmony has no way to control full duplex or half duplex mode. It means - * that we always need to provide adresses of playback and capture data, even - * when this is not needed. That's why we statically alloc one graveyard - * buffer (to put recorded data in play-only mode) and a silence buffer. - * - * Bitrate, number of channels and data format are controlled with - * the CNTL register. + * 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. * - * Mixer work is done through one register (GAINCTL). Only input gain, - * output attenuation and general attenuation control is provided. There is - * also controls for enabling/disabling internal speaker and line - * input. + * Notes: + * - graveyard and silence buffers last for lifetime of + * the driver. playback and capture buffers are allocated + * per _open()/_close(). + * + * TODO: * - * Buffers used by this driver are all DMA consistent. */ -#include <linux/delay.h> -#include <sound/driver.h> #include <linux/init.h> -#include <linux/interrupt.h> #include <linux/slab.h> #include <linux/time.h> #include <linux/wait.h> -#include <linux/moduleparam.h> +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/dma-mapping.h> + +#include <sound/driver.h> #include <sound/core.h> -#include <sound/control.h> #include <sound/pcm.h> +#include <sound/control.h> #include <sound/rawmidi.h> #include <sound/initval.h> #include <sound/info.h> -#include <asm/hardware.h> + #include <asm/io.h> +#include <asm/hardware.h> #include <asm/parisc-device.h> -MODULE_AUTHOR("Laurent Canet <canetl@esiee.fr>"); -MODULE_DESCRIPTION("ALSA Harmony sound driver"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{ALSA,Harmony soundcard}}"); - -#undef DEBUG -#ifdef DEBUG -# define DPRINTK printk -#else -# define DPRINTK(x,...) -#endif - -#define PFX "harmony: " - -#define MAX_PCM_DEVICES 1 -#define MAX_PCM_SUBSTREAMS 4 -#define MAX_MIDI_DEVICES 0 - -#define HARMONY_BUF_SIZE 4096 -#define MAX_BUFS 10 -#define MAX_BUFFER_SIZE (MAX_BUFS * HARMONY_BUF_SIZE) - -/* number of silence & graveyard buffers */ -#define GRAVEYARD_BUFS 3 -#define SILENCE_BUFS 3 - -#define HARMONY_CNTL_C 0x80000000 - -#define HARMONY_DSTATUS_PN 0x00000200 -#define HARMONY_DSTATUS_RN 0x00000002 -#define HARMONY_DSTATUS_IE 0x80000000 - -#define HARMONY_DF_16BIT_LINEAR 0x00000000 -#define HARMONY_DF_8BIT_ULAW 0x00000001 -#define HARMONY_DF_8BIT_ALAW 0x00000002 - -#define HARMONY_SS_MONO 0x00000000 -#define HARMONY_SS_STEREO 0x00000001 - -/* - * Channels Mask in mixer register - * try some "reasonable" default gain values - */ - -#define HARMONY_GAIN_TOTAL_SILENCE 0x00F00FFF - -/* the following should be enough (mixer is - * very sensible on harmony) - */ -#define HARMONY_GAIN_DEFAULT 0x0F2FF082 - - -/* useless since only one card is supported ATM */ -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; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for Harmony device."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for Harmony device."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable Harmony device."); - -/* Register offset (from base hpa) */ -#define REG_ID 0x00 -#define REG_RESET 0x04 -#define REG_CNTL 0x08 -#define REG_GAINCTL 0x0C -#define REG_PNXTADD 0x10 -#define REG_PCURADD 0x14 -#define REG_RNXTADD 0x18 -#define REG_RCURADD 0x1C -#define REG_DSTATUS 0x20 -#define REG_OV 0x24 -#define REG_PIO 0x28 -#define REG_DIAG 0x3C - -/* - * main harmony structure - */ - -typedef struct snd_card_harmony { - - /* spinlocks (To be done) */ - spinlock_t mixer_lock; - spinlock_t control_lock; - - /* parameters */ - int irq; - unsigned long hpa; - int id; - int rev; - - u32 current_gain; - int data_format; /* HARMONY_DF_xx_BIT_xxx */ - int sample_rate; /* HARMONY_SR_xx_KHZ */ - int stereo_select; /* HARMONY_SS_MONO or HARMONY_SS_STEREO */ - int format_initialized; - - unsigned long ply_buffer; - int ply_buf; - int ply_count; - int ply_size; - int ply_stopped; - int ply_total; - - unsigned long cap_buffer; - int cap_buf; - int cap_count; - int cap_size; - int cap_stopped; - int cap_total; - - struct parisc_device *pa_dev; - - struct snd_dma_device dma_dev; - - /* the graveyard buffer is used as recording buffer when playback, - * because harmony always want a buffer to put recorded data */ - struct snd_dma_buffer graveyard_dma; - int graveyard_count; - - /* same thing for silence buffer */ - struct snd_dma_buffer silence_dma; - int silence_count; - - /* alsa stuff */ - snd_card_t *card; - snd_pcm_t *pcm; - snd_pcm_substream_t *playback_substream; - snd_pcm_substream_t *capture_substream; - snd_info_entry_t *proc_entry; -} snd_card_harmony_t; - -static snd_card_t *snd_harmony_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; - -/* wait to be out of control mode */ -static inline void snd_harmony_wait_cntl(snd_card_harmony_t *harmony) -{ - int timeout = 5000; +#include "harmony.h" + +static struct parisc_device_id snd_harmony_devtable[] = { + /* bushmaster / flounder */ + { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007A }, + /* 712 / 715 */ + { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007B }, + /* pace */ + { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007E }, + /* outfield / coral II */ + { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007F }, + { 0, } +}; - while ( (gsc_readl(harmony->hpa+REG_CNTL) & HARMONY_CNTL_C) && --timeout) - { - /* Wait */ ; - } - if (timeout == 0) DPRINTK(KERN_DEBUG PFX "Error: wait cntl timeouted\n"); -} +MODULE_DEVICE_TABLE(parisc, snd_harmony_devtable); +#define NAME "harmony" +#define PFX NAME ": " -/* - * sample rate routines - */ -static unsigned int snd_card_harmony_rates[] = { - 5125, 6615, 8000, 9600, +static unsigned int snd_harmony_rates[] = { + 5512, 6615, 8000, 9600, 11025, 16000, 18900, 22050, 27428, 32000, 33075, 37800, 44100, 48000 }; -static snd_pcm_hw_constraint_list_t hw_constraint_rates = { - .count = ARRAY_SIZE(snd_card_harmony_rates), - .list = snd_card_harmony_rates, - .mask = 0, -}; - -#define HARMONY_SR_8KHZ 0x08 -#define HARMONY_SR_16KHZ 0x09 -#define HARMONY_SR_27KHZ 0x0A -#define HARMONY_SR_32KHZ 0x0B -#define HARMONY_SR_48KHZ 0x0E -#define HARMONY_SR_9KHZ 0x0F -#define HARMONY_SR_5KHZ 0x10 -#define HARMONY_SR_11KHZ 0x11 -#define HARMONY_SR_18KHZ 0x12 -#define HARMONY_SR_22KHZ 0x13 -#define HARMONY_SR_37KHZ 0x14 -#define HARMONY_SR_44KHZ 0x15 -#define HARMONY_SR_33KHZ 0x16 -#define HARMONY_SR_6KHZ 0x17 - -/* bits corresponding to the entries of snd_card_harmony_rates */ static unsigned int rate_bits[14] = { HARMONY_SR_5KHZ, HARMONY_SR_6KHZ, HARMONY_SR_8KHZ, HARMONY_SR_9KHZ, HARMONY_SR_11KHZ, HARMONY_SR_16KHZ, @@ -267,642 +91,627 @@ static unsigned int rate_bits[14] = { HARMONY_SR_44KHZ, HARMONY_SR_48KHZ }; -/* snd_card_harmony_rate_bits - * @rate: index of current data rate in list - * returns: harmony hex code for registers - */ -static unsigned int snd_card_harmony_rate_bits(int rate) +static snd_pcm_hw_constraint_list_t hw_constraint_rates = { + .count = ARRAY_SIZE(snd_harmony_rates), + .list = snd_harmony_rates, + .mask = 0, +}; + +inline unsigned long +harmony_read(harmony_t *h, unsigned r) { - unsigned int idx; - - for (idx = 0; idx < ARRAY_SIZE(snd_card_harmony_rates); idx++) - if (snd_card_harmony_rates[idx] == rate) - return rate_bits[idx]; - return HARMONY_SR_44KHZ; /* fallback */ + return __raw_readl(h->iobase + r); } -/* - * update controls (data format, sample rate, number of channels) - * according to value supplied in data structure - */ -void snd_harmony_update_control(snd_card_harmony_t *harmony) +inline void +harmony_write(harmony_t *h, unsigned r, unsigned long v) { - u32 default_cntl; - - /* Set CNTL */ - default_cntl = (HARMONY_CNTL_C | /* The C bit */ - (harmony->data_format << 6) | /* Set the data format */ - (harmony->stereo_select << 5) | /* Stereo select */ - (harmony->sample_rate)); /* Set sample rate */ - - /* initialize CNTL */ - snd_harmony_wait_cntl(harmony); - - gsc_writel(default_cntl, harmony->hpa+REG_CNTL); - + __raw_writel(v, h->iobase + r); } -/* - * interruption controls routines - */ +static void +harmony_wait_for_control(harmony_t *h) +{ + while (harmony_read(h, HARMONY_CNTL) & HARMONY_CNTL_C) ; +} -static void snd_harmony_disable_interrupts(snd_card_harmony_t *chip) +inline void +harmony_reset(harmony_t *h) { - snd_harmony_wait_cntl(chip); - gsc_writel(0, chip->hpa+REG_DSTATUS); + harmony_write(h, HARMONY_RESET, 1); + mdelay(50); + harmony_write(h, HARMONY_RESET, 0); } -static void snd_harmony_enable_interrupts(snd_card_harmony_t *chip) +static void +harmony_disable_interrupts(harmony_t *h) { - snd_harmony_wait_cntl(chip); - gsc_writel(HARMONY_DSTATUS_IE, chip->hpa+REG_DSTATUS); + u32 dstatus; + harmony_wait_for_control(h); + dstatus = harmony_read(h, HARMONY_DSTATUS); + dstatus &= ~HARMONY_DSTATUS_IE; + harmony_write(h, HARMONY_DSTATUS, dstatus); } -/* - * interruption routine: - * The interrupt routine must provide adresse of next physical pages - * used by harmony - */ -static int snd_card_harmony_interrupt(int irq, void *dev, struct pt_regs *regs) +static void +harmony_enable_interrupts(harmony_t *h) { - snd_card_harmony_t *harmony = (snd_card_harmony_t *)dev; - u32 dstatus = 0; - unsigned long hpa = harmony->hpa; - - /* Turn off interrupts */ - snd_harmony_disable_interrupts(harmony); - - /* wait for control to free */ - snd_harmony_wait_cntl(harmony); - - /* Read dstatus and pcuradd (the current address) */ - dstatus = gsc_readl(hpa+REG_DSTATUS); - - /* Check if this is a request to get the next play buffer */ + u32 dstatus; + harmony_wait_for_control(h); + dstatus = harmony_read(h, HARMONY_DSTATUS); + dstatus |= HARMONY_DSTATUS_IE; + harmony_write(h, HARMONY_DSTATUS, dstatus); +} + +static void +harmony_mute(harmony_t *h) +{ + unsigned long flags; + + spin_lock_irqsave(&h->mixer_lock, flags); + harmony_wait_for_control(h); + harmony_write(h, HARMONY_GAINCTL, HARMONY_GAIN_SILENCE); + spin_unlock_irqrestore(&h->mixer_lock, flags); +} + +static void +harmony_unmute(harmony_t *h) +{ + unsigned long flags; + + spin_lock_irqsave(&h->mixer_lock, flags); + harmony_wait_for_control(h); + harmony_write(h, HARMONY_GAINCTL, h->st.gain); + spin_unlock_irqrestore(&h->mixer_lock, flags); +} + +static void +harmony_set_control(harmony_t *h) +{ + u32 ctrl; + unsigned long flags; + + spin_lock_irqsave(&h->lock, flags); + + ctrl = (HARMONY_CNTL_C | + (h->st.format << 6) | + (h->st.stereo << 5) | + (h->st.rate)); + + harmony_wait_for_control(h); + harmony_write(h, HARMONY_CNTL, ctrl); + + spin_unlock_irqrestore(&h->lock, flags); +} + +static irqreturn_t +snd_harmony_interrupt(int irq, void *dev, struct pt_regs *regs) +{ + u32 dstatus; + harmony_t *h = dev; + + spin_lock(&h->lock); + harmony_disable_interrupts(h); + harmony_wait_for_control(h); + dstatus = harmony_read(h, HARMONY_DSTATUS); + spin_unlock(&h->lock); + if (dstatus & HARMONY_DSTATUS_PN) { - if (harmony->playback_substream) { - harmony->ply_buf += harmony->ply_count; - harmony->ply_buf %= harmony->ply_size; - - gsc_writel(harmony->ply_buffer + harmony->ply_buf, - hpa+REG_PNXTADD); - - snd_pcm_period_elapsed(harmony->playback_substream); - harmony->ply_total++; + if (h->psubs) { + spin_lock(&h->lock); + h->pbuf.buf += h->pbuf.count; /* PAGE_SIZE */ + h->pbuf.buf %= h->pbuf.size; /* MAX_BUFS*PAGE_SIZE */ + + harmony_write(h, HARMONY_PNXTADD, + h->pbuf.addr + h->pbuf.buf); + h->stats.play_intr++; + spin_unlock(&h->lock); + snd_pcm_period_elapsed(h->psubs); } else { - gsc_writel(harmony->silence_dma.addr + - (HARMONY_BUF_SIZE*harmony->silence_count), - hpa+REG_PNXTADD); - harmony->silence_count++; - harmony->silence_count %= SILENCE_BUFS; + spin_lock(&h->lock); + harmony_write(h, HARMONY_PNXTADD, h->sdma.addr); + h->stats.silence_intr++; + spin_unlock(&h->lock); } } - - /* Check if we're being asked to fill in a recording buffer */ + if (dstatus & HARMONY_DSTATUS_RN) { - if (harmony->capture_substream) { - harmony->cap_buf += harmony->cap_count; - harmony->cap_buf %= harmony->cap_size; - - gsc_writel(harmony->cap_buffer + harmony->cap_buf, - hpa+REG_RNXTADD); - - snd_pcm_period_elapsed(harmony->capture_substream); - harmony->cap_total++; + if (h->csubs) { + spin_lock(&h->lock); + h->cbuf.buf += h->cbuf.count; + h->cbuf.buf %= h->cbuf.size; + + harmony_write(h, HARMONY_RNXTADD, + h->cbuf.addr + h->cbuf.buf); + h->stats.rec_intr++; + spin_unlock(&h->lock); + snd_pcm_period_elapsed(h->csubs); } else { - /* graveyard buffer */ - gsc_writel(harmony->graveyard_dma.addr + - (HARMONY_BUF_SIZE*harmony->graveyard_count), - hpa+REG_RNXTADD); - harmony->graveyard_count++; - harmony->graveyard_count %= GRAVEYARD_BUFS; + spin_lock(&h->lock); + harmony_write(h, HARMONY_RNXTADD, h->gdma.addr); + h->stats.graveyard_intr++; + spin_unlock(&h->lock); } } - snd_harmony_enable_interrupts(harmony); + + spin_lock(&h->lock); + harmony_enable_interrupts(h); + spin_unlock(&h->lock); return IRQ_HANDLED; } -/* - * proc entry - * this proc file will give some debugging info - */ - -static void snd_harmony_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer) +static unsigned int +snd_harmony_rate_bits(int rate) { - snd_card_harmony_t *harmony = (snd_card_harmony_t *)entry->private_data; - - snd_iprintf(buffer, "LASI Harmony driver\nLaurent Canet <canetl@esiee.fr>\n\n"); - snd_iprintf(buffer, "IRQ %d, hpa %lx, id %d rev %d\n", - harmony->irq, harmony->hpa, - harmony->id, harmony->rev); - snd_iprintf(buffer, "Current gain %lx\n", (unsigned long) harmony->current_gain); - snd_iprintf(buffer, "\tsample rate=%d\n", harmony->sample_rate); - snd_iprintf(buffer, "\tstereo select=%d\n", harmony->stereo_select); - snd_iprintf(buffer, "\tbitperchan=%d\n\n", harmony->data_format); + unsigned int i; - snd_iprintf(buffer, "Play status:\n"); - snd_iprintf(buffer, "\tstopped %d\n", harmony->ply_stopped); - snd_iprintf(buffer, "\tbuffer %lx, count %d\n", harmony->ply_buffer, harmony->ply_count); - snd_iprintf(buffer, "\tbuf %d size %d\n\n", harmony->ply_buf, harmony->ply_size); - - snd_iprintf(buffer, "Capture status:\n"); - snd_iprintf(buffer, "\tstopped %d\n", harmony->cap_stopped); - snd_iprintf(buffer, "\tbuffer %lx, count %d\n", harmony->cap_buffer, harmony->cap_count); - snd_iprintf(buffer, "\tbuf %d, size %d\n\n", harmony->cap_buf, harmony->cap_size); + for (i = 0; i < ARRAY_SIZE(snd_harmony_rates); i++) + if (snd_harmony_rates[i] == rate) + return rate_bits[i]; - snd_iprintf(buffer, "Funny stats: total played=%d, recorded=%d\n\n", harmony->ply_total, harmony->cap_total); - - snd_iprintf(buffer, "Register:\n"); - snd_iprintf(buffer, "\tgainctl: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_GAINCTL)); - snd_iprintf(buffer, "\tcntl: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_CNTL)); - snd_iprintf(buffer, "\tid: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_ID)); - snd_iprintf(buffer, "\tpcuradd: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_PCURADD)); - snd_iprintf(buffer, "\trcuradd: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_RCURADD)); - snd_iprintf(buffer, "\tpnxtadd: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_PNXTADD)); - snd_iprintf(buffer, "\trnxtadd: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_RNXTADD)); - snd_iprintf(buffer, "\tdstatus: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_DSTATUS)); - snd_iprintf(buffer, "\tov: %lx\n\n", (unsigned long) gsc_readl(harmony->hpa+REG_OV)); - + return HARMONY_SR_44KHZ; } -static void __devinit snd_harmony_proc_init(snd_card_harmony_t *harmony) +static snd_pcm_hardware_t snd_harmony_playback = { - snd_info_entry_t *entry; - - if (! snd_card_proc_new(harmony->card, "harmony", &entry)) - snd_info_set_text_ops(entry, harmony, 2048, snd_harmony_proc_read); -} + .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_JOINT_DUPLEX | SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BLOCK_TRANSFER), + .formats = (SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_MU_LAW | + SNDRV_PCM_FMTBIT_A_LAW), + .rates = (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000 | + SNDRV_PCM_RATE_KNOT), + .rate_min = 5512, + .rate_max = 48000, + .channels_min = 1, + .channels_max = 2, + .buffer_bytes_max = MAX_BUF_SIZE, + .period_bytes_min = BUF_SIZE, + .period_bytes_max = BUF_SIZE, + .periods_min = 1, + .periods_max = MAX_BUFS, + .fifo_size = 0, +}; -/* - * PCM Stuff - */ +static snd_pcm_hardware_t snd_harmony_capture = +{ + .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_JOINT_DUPLEX | SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BLOCK_TRANSFER), + .formats = (SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_MU_LAW | + SNDRV_PCM_FMTBIT_A_LAW), + .rates = (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000 | + SNDRV_PCM_RATE_KNOT), + .rate_min = 5512, + .rate_max = 48000, + .channels_min = 1, + .channels_max = 2, + .buffer_bytes_max = MAX_BUF_SIZE, + .period_bytes_min = BUF_SIZE, + .period_bytes_max = BUF_SIZE, + .periods_min = 1, + .periods_max = MAX_BUFS, + .fifo_size = 0, +}; -static int snd_card_harmony_playback_ioctl(snd_pcm_substream_t * substream, - unsigned int cmd, - void *arg) +static int +snd_harmony_playback_trigger(snd_pcm_substream_t *ss, int cmd) { - return snd_pcm_lib_ioctl(substream, cmd, arg); -} + harmony_t *h = snd_pcm_substream_chip(ss); + unsigned long flags; -static int snd_card_harmony_capture_ioctl(snd_pcm_substream_t * substream, - unsigned int cmd, - void *arg) -{ - return snd_pcm_lib_ioctl(substream, cmd, arg); -} + if (h->st.capturing) + return -EBUSY; -static int snd_card_harmony_playback_trigger(snd_pcm_substream_t * substream, - int cmd) -{ - snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream); - + spin_lock_irqsave(&h->lock, flags); switch (cmd) { - case SNDRV_PCM_TRIGGER_STOP: - if (harmony->ply_stopped) - return -EBUSY; - harmony->ply_stopped = 1; - snd_harmony_disable_interrupts(harmony); - break; - case SNDRV_PCM_TRIGGER_START: - if (!harmony->ply_stopped) - return -EBUSY; - harmony->ply_stopped = 0; - /* write the location of the first buffer to play */ - gsc_writel(harmony->ply_buffer, harmony->hpa+REG_PNXTADD); - snd_harmony_enable_interrupts(harmony); - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_SUSPEND: - DPRINTK(KERN_INFO PFX "received unimplemented trigger: %d\n", cmd); - default: - return -EINVAL; + case SNDRV_PCM_TRIGGER_START: + h->st.playing = 1; + harmony_write(h, HARMONY_PNXTADD, h->pbuf.addr); + harmony_write(h, HARMONY_RNXTADD, h->gdma.addr); + harmony_unmute(h); + harmony_enable_interrupts(h); + break; + case SNDRV_PCM_TRIGGER_STOP: + h->st.playing = 0; + harmony_mute(h); + harmony_disable_interrupts(h); + break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + case SNDRV_PCM_TRIGGER_SUSPEND: + default: + spin_unlock_irqrestore(&h->lock, flags); + snd_BUG(); + return -EINVAL; } + spin_unlock_irqrestore(&h->lock, flags); + return 0; } -static int snd_card_harmony_capture_trigger(snd_pcm_substream_t * substream, - int cmd) +static int +snd_harmony_capture_trigger(snd_pcm_substream_t *ss, int cmd) { - snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_STOP: - if (harmony->cap_stopped) - return -EBUSY; - harmony->cap_stopped = 1; - snd_harmony_disable_interrupts(harmony); - break; - case SNDRV_PCM_TRIGGER_START: - if (!harmony->cap_stopped) - return -EBUSY; - harmony->cap_stopped = 0; - snd_harmony_enable_interrupts(harmony); - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_SUSPEND: - DPRINTK(KERN_INFO PFX "Received unimplemented trigger: %d\n", cmd); - default: - return -EINVAL; - } - return 0; + harmony_t *h = snd_pcm_substream_chip(ss); + unsigned long flags; + + if (h->st.playing) + return -EBUSY; + + spin_lock_irqsave(&h->lock, flags); + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + h->st.capturing = 1; + harmony_write(h, HARMONY_PNXTADD, h->sdma.addr); + harmony_write(h, HARMONY_RNXTADD, h->cbuf.addr); + harmony_unmute(h); + harmony_enable_interrupts(h); + break; + case SNDRV_PCM_TRIGGER_STOP: + h->st.capturing = 0; + harmony_mute(h); + harmony_disable_interrupts(h); + break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + case SNDRV_PCM_TRIGGER_SUSPEND: + default: + spin_unlock_irqrestore(&h->lock, flags); + snd_BUG(); + return -EINVAL; + } + spin_unlock_irqrestore(&h->lock, flags); + + return 0; } -/* set data format */ -static int snd_harmony_set_data_format(snd_card_harmony_t *harmony, int pcm_format) +static int +snd_harmony_set_data_format(harmony_t *h, int fmt, int force) { - int old_format = harmony->data_format; - int new_format = old_format; - switch (pcm_format) { + int o = h->st.format; + int n; + + switch(fmt) { case SNDRV_PCM_FORMAT_S16_BE: - new_format = HARMONY_DF_16BIT_LINEAR; + n = HARMONY_DF_16BIT_LINEAR; break; case SNDRV_PCM_FORMAT_A_LAW: - new_format = HARMONY_DF_8BIT_ALAW; + n = HARMONY_DF_8BIT_ALAW; break; case SNDRV_PCM_FORMAT_MU_LAW: - new_format = HARMONY_DF_8BIT_ULAW; + n = HARMONY_DF_8BIT_ULAW; break; + default: + n = HARMONY_DF_16BIT_LINEAR; + break; + } + + if (force || o != n) { + snd_pcm_format_set_silence(fmt, h->sdma.area, SILENCE_BUFSZ / + (snd_pcm_format_physical_width(fmt) + / 8)); } - /* re-initialize silence buffer if needed */ - if (old_format != new_format) - snd_pcm_format_set_silence(pcm_format, harmony->silence_dma.area, - (HARMONY_BUF_SIZE * SILENCE_BUFS * 8) / snd_pcm_format_width(pcm_format)); - return new_format; + return n; } -static int snd_card_harmony_playback_prepare(snd_pcm_substream_t * substream) +static int +snd_harmony_playback_prepare(snd_pcm_substream_t *ss) { - snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream); - snd_pcm_runtime_t *runtime = substream->runtime; + harmony_t *h = snd_pcm_substream_chip(ss); + snd_pcm_runtime_t *rt = ss->runtime; - harmony->ply_size = snd_pcm_lib_buffer_bytes(substream); - harmony->ply_count = snd_pcm_lib_period_bytes(substream); - harmony->ply_buf = 0; - harmony->ply_stopped = 1; + if (h->st.capturing) + return -EBUSY; - /* initialize given sample rate */ - harmony->sample_rate = snd_card_harmony_rate_bits(runtime->rate); - - /* data format */ - harmony->data_format = snd_harmony_set_data_format(harmony, runtime->format); + h->pbuf.size = snd_pcm_lib_buffer_bytes(ss); + h->pbuf.count = snd_pcm_lib_period_bytes(ss); + h->pbuf.buf = 0; + h->st.playing = 0; - /* number of channels */ - if (runtime->channels == 2) - harmony->stereo_select = HARMONY_SS_STEREO; - else - harmony->stereo_select = HARMONY_SS_MONO; - - DPRINTK(KERN_INFO PFX "Playback_prepare, sr=%d(%x), df=%x, ss=%x hpa=%lx\n", runtime->rate, - harmony->sample_rate, harmony->data_format, harmony->stereo_select, harmony->hpa); - snd_harmony_update_control(harmony); - harmony->format_initialized = 1; - harmony->ply_buffer = runtime->dma_addr; + h->st.rate = snd_harmony_rate_bits(rt->rate); + h->st.format = snd_harmony_set_data_format(h, rt->format, 0); - return 0; -} + if (rt->channels == 2) + h->st.stereo = HARMONY_SS_STEREO; + else + h->st.stereo = HARMONY_SS_MONO; -static int snd_card_harmony_capture_prepare(snd_pcm_substream_t * substream) -{ - snd_pcm_runtime_t *runtime = substream->runtime; - snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream); - - harmony->cap_size = snd_pcm_lib_buffer_bytes(substream); - harmony->cap_count = snd_pcm_lib_period_bytes(substream); - harmony->cap_count = 0; - harmony->cap_stopped = 1; + harmony_set_control(h); - /* initialize given sample rate */ - harmony->sample_rate = snd_card_harmony_rate_bits(runtime->rate); - - /* data format */ - harmony->data_format = snd_harmony_set_data_format(harmony, runtime->format); - - /* number of channels */ - if (runtime->channels == 1) - harmony->stereo_select = HARMONY_SS_MONO; - else if (runtime->channels == 2) - harmony->stereo_select = HARMONY_SS_STEREO; - - snd_harmony_update_control(harmony); - harmony->format_initialized = 1; - - harmony->cap_buffer = runtime->dma_addr; + h->pbuf.addr = rt->dma_addr; return 0; } -static snd_pcm_uframes_t snd_card_harmony_capture_pointer(snd_pcm_substream_t * substream) +static int +snd_harmony_capture_prepare(snd_pcm_substream_t *ss) { - snd_pcm_runtime_t *runtime = substream->runtime; - snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream); - unsigned long rcuradd; - int recorded; - - if (harmony->cap_stopped) return 0; - if (harmony->capture_substream == NULL) return 0; + harmony_t *h = snd_pcm_substream_chip(ss); + snd_pcm_runtime_t *rt = ss->runtime; - rcuradd = gsc_readl(harmony->hpa+REG_RCURADD); - recorded = (rcuradd - harmony->cap_buffer); - recorded %= harmony->cap_size; - - return bytes_to_frames(runtime, recorded); -} + if (h->st.playing) + return -EBUSY; -/* - */ + h->cbuf.size = snd_pcm_lib_buffer_bytes(ss); + h->cbuf.count = snd_pcm_lib_period_bytes(ss); + h->cbuf.buf = 0; + h->st.capturing = 0; + + h->st.rate = snd_harmony_rate_bits(rt->rate); + h->st.format = snd_harmony_set_data_format(h, rt->format, 0); + + if (rt->channels == 2) + h->st.stereo = HARMONY_SS_STEREO; + else + h->st.stereo = HARMONY_SS_MONO; + + harmony_set_control(h); -static snd_pcm_uframes_t snd_card_harmony_playback_pointer(snd_pcm_substream_t * substream) + h->cbuf.addr = rt->dma_addr; + + return 0; +} + +static snd_pcm_uframes_t +snd_harmony_playback_pointer(snd_pcm_substream_t *ss) { - snd_pcm_runtime_t *runtime = substream->runtime; - snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream); - int played; - long int pcuradd = gsc_readl(harmony->hpa+REG_PCURADD); - - if ((harmony->ply_stopped) || (harmony->playback_substream == NULL)) return 0; - if ((harmony->ply_buffer == 0) || (harmony->ply_size == 0)) return 0; - - played = (pcuradd - harmony->ply_buffer); - - printk(KERN_DEBUG PFX "Pointer is %lx-%lx = %d\n", pcuradd, harmony->ply_buffer, played); + snd_pcm_runtime_t *rt = ss->runtime; + harmony_t *h = snd_pcm_substream_chip(ss); + unsigned long pcuradd; + unsigned long played; + + if (!(h->st.playing) || (h->psubs == NULL)) + return 0; - if (pcuradd > harmony->ply_buffer + harmony->ply_size) return 0; + if ((h->pbuf.addr == 0) || (h->pbuf.size == 0)) + return 0; - return bytes_to_frames(runtime, played); + pcuradd = harmony_read(h, HARMONY_PCURADD); + played = pcuradd - h->pbuf.addr; + +#ifdef HARMONY_DEBUG + printk(KERN_DEBUG PFX "playback_pointer is 0x%lx-0x%lx = %d bytes\n", + pcuradd, h->pbuf.addr, played); +#endif + + if (pcuradd > h->pbuf.addr + h->pbuf.size) { + return 0; + } + + return bytes_to_frames(rt, played); } -static snd_pcm_hardware_t snd_card_harmony_playback = +static snd_pcm_uframes_t +snd_harmony_capture_pointer(snd_pcm_substream_t *ss) { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_JOINT_DUPLEX | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_BLOCK_TRANSFER), - .formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_BE | - SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_MU_LAW), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 5500, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = MAX_BUFFER_SIZE, - .period_bytes_min = HARMONY_BUF_SIZE, - .period_bytes_max = HARMONY_BUF_SIZE, - .periods_min = 1, - .periods_max = MAX_BUFS, - .fifo_size = 0, -}; + snd_pcm_runtime_t *rt = ss->runtime; + harmony_t *h = snd_pcm_substream_chip(ss); + unsigned long rcuradd; + unsigned long caught; -static snd_pcm_hardware_t snd_card_harmony_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_JOINT_DUPLEX | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_BLOCK_TRANSFER), - .formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_BE | - SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_MU_LAW), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 5500, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = MAX_BUFFER_SIZE, - .period_bytes_min = HARMONY_BUF_SIZE, - .period_bytes_max = HARMONY_BUF_SIZE, - .periods_min = 1, - .periods_max = MAX_BUFS, - .fifo_size = 0, -}; + if (!(h->st.capturing) || (h->csubs == NULL)) + return 0; -static int snd_card_harmony_playback_open(snd_pcm_substream_t * substream) + if ((h->cbuf.addr == 0) || (h->cbuf.size == 0)) + return 0; + + rcuradd = harmony_read(h, HARMONY_RCURADD); + caught = rcuradd - h->cbuf.addr; + +#ifdef HARMONY_DEBUG + printk(KERN_DEBUG PFX "capture_pointer is 0x%lx-0x%lx = %d bytes\n", + rcuradd, h->cbuf.addr, caught); +#endif + + if (rcuradd > h->cbuf.addr + h->cbuf.size) { + return 0; + } + + return bytes_to_frames(rt, caught); +} + +static int +snd_harmony_playback_open(snd_pcm_substream_t *ss) { - snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream); - snd_pcm_runtime_t *runtime = substream->runtime; + harmony_t *h = snd_pcm_substream_chip(ss); + snd_pcm_runtime_t *rt = ss->runtime; int err; - harmony->playback_substream = substream; - runtime->hw = snd_card_harmony_playback; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraint_rates); + h->psubs = ss; + rt->hw = snd_harmony_playback; + snd_pcm_hw_constraint_list(rt, 0, SNDRV_PCM_HW_PARAM_RATE, + &hw_constraint_rates); - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) + err = snd_pcm_hw_constraint_integer(rt, SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) return err; return 0; } -static int snd_card_harmony_capture_open(snd_pcm_substream_t * substream) +static int +snd_harmony_capture_open(snd_pcm_substream_t *ss) { - snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream); - snd_pcm_runtime_t *runtime = substream->runtime; - int err; - - harmony->capture_substream = substream; - runtime->hw = snd_card_harmony_capture; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraint_rates); - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) - return err; - return 0; + harmony_t *h = snd_pcm_substream_chip(ss); + snd_pcm_runtime_t *rt = ss->runtime; + int err; + + h->csubs = ss; + rt->hw = snd_harmony_capture; + snd_pcm_hw_constraint_list(rt, 0, SNDRV_PCM_HW_PARAM_RATE, + &hw_constraint_rates); + + err = snd_pcm_hw_constraint_integer(rt, SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) + return err; + return 0; } -static int snd_card_harmony_playback_close(snd_pcm_substream_t * substream) +static int +snd_harmony_playback_close(snd_pcm_substream_t *ss) { - snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream); - - harmony->playback_substream = NULL; - harmony->ply_size = 0; - harmony->ply_buf = 0; - harmony->ply_buffer = 0; - harmony->ply_count = 0; - harmony->ply_stopped = 1; - harmony->format_initialized = 0; - + harmony_t *h = snd_pcm_substream_chip(ss); + h->psubs = NULL; return 0; } -static int snd_card_harmony_capture_close(snd_pcm_substream_t * substream) +static int +snd_harmony_capture_close(snd_pcm_substream_t *ss) { - snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream); - - harmony->capture_substream = NULL; - harmony->cap_size = 0; - harmony->cap_buf = 0; - harmony->cap_buffer = 0; - harmony->cap_count = 0; - harmony->cap_stopped = 1; - harmony->format_initialized = 0; - - return 0; + harmony_t *h = snd_pcm_substream_chip(ss); + h->csubs = NULL; + return 0; } -static int snd_card_harmony_hw_params(snd_pcm_substream_t *substream, - snd_pcm_hw_params_t * hw_params) +static int +snd_harmony_hw_params(snd_pcm_substream_t *ss, + snd_pcm_hw_params_t *hw) { int err; - snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream); + harmony_t *h = snd_pcm_substream_chip(ss); + + err = snd_pcm_lib_malloc_pages(ss, params_buffer_bytes(hw)); + if (err > 0 && h->dma.type == SNDRV_DMA_TYPE_CONTINUOUS) + ss->runtime->dma_addr = __pa(ss->runtime->dma_area); - err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); - if (err > 0 && harmony->dma_dev.type == SNDRV_DMA_TYPE_CONTINUOUS) - substream->runtime->dma_addr = __pa(substream->runtime->dma_area); - DPRINTK(KERN_INFO PFX "HW Params returned %d, dma_addr %lx\n", err, - (unsigned long)substream->runtime->dma_addr); return err; } -static int snd_card_harmony_hw_free(snd_pcm_substream_t *substream) +static int +snd_harmony_hw_free(snd_pcm_substream_t *ss) { - snd_pcm_lib_free_pages(substream); - return 0; + return snd_pcm_lib_free_pages(ss); } -static snd_pcm_ops_t snd_card_harmony_playback_ops = { - .open = snd_card_harmony_playback_open, - .close = snd_card_harmony_playback_close, - .ioctl = snd_card_harmony_playback_ioctl, - .hw_params = snd_card_harmony_hw_params, - .hw_free = snd_card_harmony_hw_free, - .prepare = snd_card_harmony_playback_prepare, - .trigger = snd_card_harmony_playback_trigger, - .pointer = snd_card_harmony_playback_pointer, +static snd_pcm_ops_t snd_harmony_playback_ops = { + .open = snd_harmony_playback_open, + .close = snd_harmony_playback_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = snd_harmony_hw_params, + .hw_free = snd_harmony_hw_free, + .prepare = snd_harmony_playback_prepare, + .trigger = snd_harmony_playback_trigger, + .pointer = snd_harmony_playback_pointer, }; -static snd_pcm_ops_t snd_card_harmony_capture_ops = { - .open = snd_card_harmony_capture_open, - .close = snd_card_harmony_capture_close, - .ioctl = snd_card_harmony_capture_ioctl, - .hw_params = snd_card_harmony_hw_params, - .hw_free = snd_card_harmony_hw_free, - .prepare = snd_card_harmony_capture_prepare, - .trigger = snd_card_harmony_capture_trigger, - .pointer = snd_card_harmony_capture_pointer, +static snd_pcm_ops_t snd_harmony_capture_ops = { + .open = snd_harmony_capture_open, + .close = snd_harmony_capture_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = snd_harmony_hw_params, + .hw_free = snd_harmony_hw_free, + .prepare = snd_harmony_capture_prepare, + .trigger = snd_harmony_capture_trigger, + .pointer = snd_harmony_capture_pointer, }; -static int snd_card_harmony_pcm_init(snd_card_harmony_t *harmony) +static int +snd_harmony_pcm_init(harmony_t *h) { snd_pcm_t *pcm; int err; - /* Request that IRQ */ - if (request_irq(harmony->irq, snd_card_harmony_interrupt, 0 ,"harmony", harmony)) { - printk(KERN_ERR PFX "Error requesting irq %d.\n", harmony->irq); - return -EFAULT; - } + harmony_disable_interrupts(h); - snd_harmony_disable_interrupts(harmony); - - if ((err = snd_pcm_new(harmony->card, "Harmony", 0, 1, 1, &pcm)) < 0) + err = snd_pcm_new(h->card, "harmony", 0, 1, 1, &pcm); + if (err < 0) return err; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_harmony_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_harmony_capture_ops); - - pcm->private_data = harmony; + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, + &snd_harmony_playback_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, + &snd_harmony_capture_ops); + + pcm->private_data = h; pcm->info_flags = 0; - strcpy(pcm->name, "Harmony"); - harmony->pcm = pcm; + strcpy(pcm->name, "harmony"); + h->pcm = pcm; + + h->psubs = NULL; + h->csubs = NULL; /* initialize graveyard buffer */ - harmony->dma_dev.type = SNDRV_DMA_TYPE_DEV; - harmony->dma_dev.dev = &harmony->pa_dev->dev; - err = snd_dma_alloc_pages(harmony->dma_dev.type, - harmony->dma_dev.dev, - HARMONY_BUF_SIZE*GRAVEYARD_BUFS, - &harmony->graveyard_dma); - if (err == -ENOMEM) { - /* use continuous buffers */ - harmony->dma_dev.type = SNDRV_DMA_TYPE_CONTINUOUS; - harmony->dma_dev.dev = snd_dma_continuous_data(GFP_KERNEL); - err = snd_dma_alloc_pages(harmony->dma_dev.type, - harmony->dma_dev.dev, - HARMONY_BUF_SIZE*GRAVEYARD_BUFS, - &harmony->graveyard_dma); - } + h->dma.type = SNDRV_DMA_TYPE_DEV; + h->dma.dev = &h->dev->dev; + err = snd_dma_alloc_pages(h->dma.type, + h->dma.dev, + BUF_SIZE*GRAVEYARD_BUFS, + &h->gdma); if (err < 0) { - printk(KERN_ERR PFX "can't allocate graveyard buffer\n"); + printk(KERN_ERR PFX "cannot allocate graveyard buffer!\n"); return err; } - harmony->graveyard_count = 0; /* initialize silence buffers */ - err = snd_dma_alloc_pages(harmony->dma_dev.type, - harmony->dma_dev.dev, - HARMONY_BUF_SIZE*SILENCE_BUFS, - &harmony->silence_dma); + err = snd_dma_alloc_pages(h->dma.type, + h->dma.dev, + BUF_SIZE*SILENCE_BUFS, + &h->sdma); if (err < 0) { - printk(KERN_ERR PFX "can't allocate silence buffer\n"); + printk(KERN_ERR PFX "cannot allocate silence buffer!\n"); return err; } - harmony->silence_count = 0; - - if (harmony->dma_dev.type == SNDRV_DMA_TYPE_CONTINUOUS) { - harmony->graveyard_dma.addr = __pa(harmony->graveyard_dma.area); - harmony->silence_dma.addr = __pa(harmony->silence_dma.area); - } - harmony->ply_stopped = harmony->cap_stopped = 1; - - harmony->playback_substream = NULL; - harmony->capture_substream = NULL; - harmony->graveyard_count = 0; - - err = snd_pcm_lib_preallocate_pages_for_all(pcm, harmony->dma_dev.type, - harmony->dma_dev.dev, - MAX_BUFFER_SIZE, MAX_BUFFER_SIZE); + /* pre-allocate space for DMA */ + err = snd_pcm_lib_preallocate_pages_for_all(pcm, h->dma.type, + h->dma.dev, + MAX_BUF_SIZE, + MAX_BUF_SIZE); if (err < 0) { - printk(KERN_ERR PFX "buffer allocation error %d\n", err); - // return err; + printk(KERN_ERR PFX "buffer allocation error: %d\n", err); + return err; } + h->st.format = snd_harmony_set_data_format(h, + SNDRV_PCM_FORMAT_S16_BE, 1); + return 0; } -/* - * mixer routines - */ - -static void snd_harmony_set_new_gain(snd_card_harmony_t *harmony) +static void +snd_harmony_set_new_gain(harmony_t *h) { - DPRINTK(KERN_INFO PFX "Setting new gain %x at %lx\n", harmony->current_gain, harmony->hpa+REG_GAINCTL); - /* Wait until we're out of control mode */ - snd_harmony_wait_cntl(harmony); - - gsc_writel(harmony->current_gain, harmony->hpa+REG_GAINCTL); + harmony_wait_for_control(h); + harmony_write(h, HARMONY_GAINCTL, h->st.gain); } -#define HARMONY_VOLUME(xname, left_shift, right_shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_harmony_mixercontrol_info, \ - .get = snd_harmony_volume_get, .put = snd_harmony_volume_put, \ - .private_value = ((left_shift) | ((right_shift) << 8) | ((mask) << 16) | ((invert) << 24)) } - -static int snd_harmony_mixercontrol_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo) +static int +snd_harmony_mixercontrol_info(snd_kcontrol_t *kc, + snd_ctl_elem_info_t *uinfo) { - int mask = (kcontrol->private_value >> 16) & 0xff; - int left_shift = (kcontrol->private_value) & 0xff; - int right_shift = (kcontrol->private_value >> 8) & 0xff; + int mask = (kc->private_value >> 16) & 0xff; + int left_shift = (kc->private_value) & 0xff; + int right_shift = (kc->private_value >> 8) & 0xff; - uinfo->type = (mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER); - uinfo->count = (left_shift == right_shift) ? 1 : 2; + uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : + SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = left_shift == right_shift ? 1 : 2; uinfo->value.integer.min = 0; uinfo->value.integer.max = mask; + return 0; } - -static int snd_harmony_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) + +static int +snd_harmony_volume_get(snd_kcontrol_t *kc, + snd_ctl_elem_value_t *ucontrol) { - snd_card_harmony_t *harmony = snd_kcontrol_chip(kcontrol); - int shift_left = (kcontrol->private_value) & 0xff; - int shift_right = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - unsigned long flags; + harmony_t *h = snd_kcontrol_chip(kc); + int shift_left = (kc->private_value) & 0xff; + int shift_right = (kc->private_value >> 8) & 0xff; + int mask = (kc->private_value >> 16) & 0xff; + int invert = (kc->private_value >> 24) & 0xff; int left, right; + unsigned long flags; - spin_lock_irqsave(&harmony->mixer_lock, flags); - left = (harmony->current_gain >> shift_left) & mask; - right = (harmony->current_gain >> shift_right) & mask; + spin_lock_irqsave(&h->mixer_lock, flags); + + left = (h->st.gain >> shift_left) & mask; + right = (h->st.gain >> shift_right) & mask; if (invert) { left = mask - left; @@ -910,21 +719,24 @@ static int snd_harmony_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ } ucontrol->value.integer.value[0] = left; ucontrol->value.integer.value[1] = right; - spin_unlock_irqrestore(&harmony->mixer_lock, flags); + + spin_unlock_irqrestore(&h->mixer_lock, flags); return 0; } -static int snd_harmony_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int +snd_harmony_volume_put(snd_kcontrol_t *kc, + snd_ctl_elem_value_t *ucontrol) { - snd_card_harmony_t *harmony = snd_kcontrol_chip(kcontrol); - int shift_left = (kcontrol->private_value) & 0xff; - int shift_right = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - unsigned long flags; + harmony_t *h = snd_kcontrol_chip(kc); + int shift_left = (kc->private_value) & 0xff; + int shift_right = (kc->private_value >> 8) & 0xff; + int mask = (kc->private_value >> 16) & 0xff; + int invert = (kc->private_value >> 24) & 0xff; int left, right; - int old_gain = harmony->current_gain; + int old_gain = h->st.gain; + unsigned long flags; left = ucontrol->value.integer.value[0] & mask; right = ucontrol->value.integer.value[1] & mask; @@ -933,213 +745,249 @@ static int snd_harmony_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ right = mask - right; } - spin_lock_irqsave(&harmony->mixer_lock, flags); - harmony->current_gain = harmony->current_gain & ~( (mask << shift_right) | (mask << shift_left)); - harmony->current_gain = harmony->current_gain | ((left << shift_left) | (right << shift_right) ); - snd_harmony_set_new_gain(harmony); - spin_unlock_irqrestore(&harmony->mixer_lock, flags); + spin_lock_irqsave(&h->mixer_lock, flags); + + h->st.gain &= ~( (mask << shift_right) | (mask << shift_left) ); + h->st.gain |= ( (left << shift_left) | (right << shift_right) ); + snd_harmony_set_new_gain(h); + + spin_unlock_irqrestore(&h->mixer_lock, flags); - return (old_gain - harmony->current_gain); + return (old_gain - h->st.gain); } -#define HARMONY_CONTROLS (sizeof(snd_harmony_controls)/sizeof(snd_kcontrol_new_t)) +#define HARMONY_CONTROLS (sizeof(snd_harmony_controls)/ \ + sizeof(snd_kcontrol_new_t)) + +#define HARMONY_VOLUME(xname, left_shift, right_shift, mask, invert) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .info = snd_harmony_mixercontrol_info, \ + .get = snd_harmony_volume_get, .put = snd_harmony_volume_put, \ + .private_value = ((left_shift) | ((right_shift) << 8) | \ + ((mask) << 16) | ((invert) << 24)) } static snd_kcontrol_new_t snd_harmony_controls[] = { -HARMONY_VOLUME("PCM Capture Volume", 12, 16, 0x0f, 0), -HARMONY_VOLUME("Master Volume", 20, 20, 0x0f, 1), -HARMONY_VOLUME("PCM Playback Volume", 6, 0, 0x3f, 1), + HARMONY_VOLUME("Playback Volume", HARMONY_GAIN_LO_SHIFT, + HARMONY_GAIN_RO_SHIFT, HARMONY_GAIN_OUT, 1), + HARMONY_VOLUME("Capture Volume", HARMONY_GAIN_LI_SHIFT, + HARMONY_GAIN_RI_SHIFT, HARMONY_GAIN_IN, 0), }; -static void __init snd_harmony_reset_codec(snd_card_harmony_t *harmony) +static void __init +snd_harmony_mixer_reset(harmony_t *h) { - snd_harmony_wait_cntl(harmony); - gsc_writel(1, harmony->hpa+REG_RESET); - mdelay(50); /* wait 50 ms */ - gsc_writel(0, harmony->hpa+REG_RESET); + harmony_mute(h); + harmony_reset(h); + h->st.gain = HARMONY_GAIN_DEFAULT; + harmony_unmute(h); } -/* - * Mute all the output and reset Harmony. - */ - -static void __init snd_harmony_mixer_reset(snd_card_harmony_t *harmony) +static int __init +snd_harmony_mixer_init(harmony_t *h) { - harmony->current_gain = HARMONY_GAIN_TOTAL_SILENCE; - snd_harmony_set_new_gain(harmony); - snd_harmony_reset_codec(harmony); - harmony->current_gain = HARMONY_GAIN_DEFAULT; - snd_harmony_set_new_gain(harmony); -} - - -static int __init snd_card_harmony_mixer_init(snd_card_harmony_t *harmony) -{ - snd_card_t *card = harmony->card; + snd_card_t *card = h->card; int idx, err; - snd_assert(harmony != NULL, return -EINVAL); + snd_assert(h != NULL, return -EINVAL); strcpy(card->mixername, "Harmony Gain control interface"); for (idx = 0; idx < HARMONY_CONTROLS; idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_harmony_controls[idx], harmony))) < 0) + err = snd_ctl_add(card, + snd_ctl_new1(&snd_harmony_controls[idx], h)); + if (err < 0) return err; } - snd_harmony_mixer_reset(harmony); + snd_harmony_mixer_reset(h); return 0; } -static int snd_card_harmony_create(snd_card_t *card, struct parisc_device *pa_dev, snd_card_harmony_t *harmony) +static int +snd_harmony_free(harmony_t *h) { - u32 cntl; - - harmony->card = card; - - harmony->pa_dev = pa_dev; + if (h->gdma.addr) + snd_dma_free_pages(&h->gdma); + if (h->sdma.addr) + snd_dma_free_pages(&h->sdma); - /* Set the HPA of harmony */ - harmony->hpa = pa_dev->hpa; - - harmony->irq = pa_dev->irq; - if (!harmony->irq) { - printk(KERN_ERR PFX "no irq found\n"); - return -ENODEV; - } + if (h->irq >= 0) + free_irq(h->irq, h); - /* Grab the ID and revision from the device */ - harmony->id = (gsc_readl(harmony->hpa+REG_ID)&0x00ff0000) >> 16; - if ((harmony->id | 1) != 0x15) { - printk(KERN_WARNING PFX "wrong harmony id 0x%02x\n", harmony->id); - return -EBUSY; - } - cntl = gsc_readl(harmony->hpa+REG_CNTL); - harmony->rev = (cntl>>20) & 0xff; + if (h->iobase) + iounmap(h->iobase); - printk(KERN_INFO "Lasi Harmony Audio driver h/w id %i, rev. %i at 0x%lx, IRQ %i\n", harmony->id, harmony->rev, pa_dev->hpa, harmony->irq); - - /* Make sure the control bit isn't set, although I don't think it - ever is. */ - if (cntl & HARMONY_CNTL_C) { - printk(KERN_WARNING PFX "CNTL busy\n"); - harmony->hpa = 0; - return -EBUSY; + parisc_set_drvdata(h->dev, NULL); + + kfree(h); + return 0; +} + +static int +snd_harmony_dev_free(snd_device_t *dev) +{ + harmony_t *h = dev->device_data; + return snd_harmony_free(h); +} + +static int __devinit +snd_harmony_create(snd_card_t *card, + struct parisc_device *padev, + harmony_t **rchip) +{ + int err; + harmony_t *h; + static snd_device_ops_t ops = { + .dev_free = snd_harmony_dev_free, + }; + + *rchip = NULL; + + h = kmalloc(sizeof(*h), GFP_KERNEL); + if (h == NULL) + return -ENOMEM; + + memset(&h->st, 0, sizeof(h->st)); + memset(&h->stats, 0, sizeof(h->stats)); + memset(&h->pbuf, 0, sizeof(h->pbuf)); + memset(&h->cbuf, 0, sizeof(h->cbuf)); + + h->hpa = padev->hpa; + h->card = card; + h->dev = padev; + h->irq = padev->irq; + h->iobase = ioremap_nocache(padev->hpa, HARMONY_SIZE); + if (h->iobase == NULL) { + printk(KERN_ERR PFX "unable to remap hpa 0x%lx\n", + padev->hpa); + err = -EBUSY; + goto free_and_ret; } - + + err = request_irq(h->irq, snd_harmony_interrupt, 0, + "harmony", h); + if (err) { + printk(KERN_ERR PFX "could not obtain interrupt %d", + h->irq); + goto free_and_ret; + } + + spin_lock_init(&h->mixer_lock); + spin_lock_init(&h->lock); + + if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, + h, &ops)) < 0) { + goto free_and_ret; + } + + *rchip = h; + return 0; + +free_and_ret: + snd_harmony_free(h); + return err; } - -static int __init snd_card_harmony_probe(struct parisc_device *pa_dev) + +static int __devinit +snd_harmony_probe(struct parisc_device *padev) { + int err; static int dev; - snd_card_harmony_t *chip; snd_card_t *card; - int err; - - if (dev >= SNDRV_CARDS) + harmony_t *h; + static int index = SNDRV_DEFAULT_IDX1; + static char *id = SNDRV_DEFAULT_STR1; + + h = parisc_get_drvdata(padev); + if (h != NULL) { return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; } - - snd_harmony_cards[dev] = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(snd_card_harmony_t)); - card = snd_harmony_cards[dev]; - + + card = snd_card_new(index, id, THIS_MODULE, 0); if (card == NULL) return -ENOMEM; - chip = (struct snd_card_harmony *)card->private_data; - spin_lock_init(&chip->control_lock); - spin_lock_init(&chip->mixer_lock); - - if ((err = snd_card_harmony_create(card, pa_dev, chip)) < 0) { - printk(KERN_ERR PFX "Creation failed\n"); - snd_card_free(card); - return err; + + err = snd_harmony_create(card, padev, &h); + if (err < 0) { + goto free_and_ret; } - if ((err = snd_card_harmony_pcm_init(chip)) < 0) { - printk(KERN_ERR PFX "PCM Init failed\n"); - snd_card_free(card); - return err; + + err = snd_harmony_pcm_init(h); + if (err < 0) { + goto free_and_ret; } - if ((err = snd_card_harmony_mixer_init(chip)) < 0) { - printk(KERN_ERR PFX "Mixer init failed\n"); - snd_card_free(card); - return err; + + err = snd_harmony_mixer_init(h); + if (err < 0) { + goto free_and_ret; } - - snd_harmony_proc_init(chip); - - strcpy(card->driver, "Harmony"); - strcpy(card->shortname, "ALSA driver for LASI Harmony"); - sprintf(card->longname, "%s at h/w, id %i, rev. %i hpa 0x%lx, IRQ %i\n",card->shortname, chip->id, chip->rev, pa_dev->hpa, chip->irq); - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; + strcpy(card->driver, "harmony"); + strcpy(card->shortname, "Harmony"); + sprintf(card->longname, "%s at 0x%lx, irq %i", + card->shortname, h->hpa, h->irq); + + err = snd_card_register(card); + if (err < 0) { + goto free_and_ret; } - printk(KERN_DEBUG PFX "Successfully registered harmony pcm backend & mixer %d\n", dev); dev++; - return 0; -} + parisc_set_drvdata(padev, h); -static struct parisc_device_id snd_card_harmony_devicetbl[] = { - { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007A }, /* Bushmaster/Flounder */ - { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007B }, /* 712/715 Audio */ - { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007E }, /* Pace Audio */ - { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007F }, /* Outfield / Coral II */ - { 0, } -}; + return 0; -MODULE_DEVICE_TABLE(parisc, snd_card_harmony_devicetbl); +free_and_ret: + snd_card_free(card); + return err; +} -/* - * bloc device parisc. c'est une structure qui definit un device - * que l'on trouve sur parisc. - * On y trouve les differents numeros HVERSION correspondant au device - * en question (ce qui permet a l'inventory de l'identifier) et la fonction - * d'initialisation du chose - */ +static int __devexit +snd_harmony_remove(struct parisc_device *padev) +{ + harmony_t *h = parisc_get_drvdata(padev); + snd_card_free(h->card); + return 0; +} -static struct parisc_driver snd_card_harmony_driver = { - .name = "Lasi ALSA Harmony", - .id_table = snd_card_harmony_devicetbl, - .probe = snd_card_harmony_probe, +static struct parisc_driver snd_harmony_driver = { + .name = "harmony", + .id_table = snd_harmony_devtable, + .probe = snd_harmony_probe, + .remove = snd_harmony_remove, }; -static int __init alsa_card_harmony_init(void) +static int __init +alsa_harmony_init(void) { int err; - - if ((err = register_parisc_driver(&snd_card_harmony_driver)) < 0) { - printk(KERN_ERR "Harmony soundcard not found or device busy\n"); + + err = register_parisc_driver(&snd_harmony_driver); + if (err < 0) { + printk(KERN_ERR PFX "device not found\n"); return err; } return 0; } -static void __exit alsa_card_harmony_exit(void) +static void __exit +alsa_harmony_fini(void) { - int idx; - snd_card_harmony_t *harmony; + int err; + + err = unregister_parisc_driver(&snd_harmony_driver); + if (err < 0) { + printk(KERN_ERR PFX "failed to unregister\n"); + } - for (idx = 0; idx < SNDRV_CARDS; idx++) - { - if (snd_harmony_cards[idx] != NULL) - { - DPRINTK(KERN_INFO PFX "Freeing card %d\n", idx); - harmony = snd_harmony_cards[idx]->private_data; - free_irq(harmony->irq, harmony); - printk(KERN_INFO PFX "Card unloaded %d, irq=%d\n", idx, harmony->irq); - snd_card_free(snd_harmony_cards[idx]); - } - } - if (unregister_parisc_driver(&snd_card_harmony_driver) < 0) - printk(KERN_ERR PFX "Failed to unregister Harmony driver\n"); + return; } -module_init(alsa_card_harmony_init) -module_exit(alsa_card_harmony_exit) +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Kyle McMartin <kyle@parisc-linux.org>"); +MODULE_DESCRIPTION("Harmony sound driver"); + +module_init(alsa_harmony_init); +module_exit(alsa_harmony_fini); diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index 3248ed924..428efdbd7 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig @@ -54,7 +54,7 @@ config SND_AU8810 Supported features: Hardware Mixer, SRC, EQ and SPDIF output. 3D support code is in place, but not yet useable. For more info, - email the ALSA developer list, or mjander@users.sourceforge.net. + email the ALSA developer list, or <mjander@users.sourceforge.net>. To compile this driver as a module, choose M here: the module will be called snd-au8810. @@ -68,7 +68,7 @@ config SND_AU8820 Say Y here to include support for Aureal Vortex soundcards. Supported features: Hardware Mixer and SRC. For more info, email - the ALSA developer list, or mjander@users.sourceforge.net. + the ALSA developer list, or <mjander@users.sourceforge.net>. To compile this driver as a module, choose M here: the module will be called snd-au8820. @@ -83,7 +83,7 @@ config SND_AU8830 Supported features: Hardware Mixer, SRC, EQ and SPDIF output. 3D support code is in place, but not yet useable. For more info, - email the ALSA developer list, or mjander@users.sourceforge.net. + email the ALSA developer list, or <mjander@users.sourceforge.net>. To compile this driver as a module, choose M here: the module will be called snd-au8830. @@ -106,8 +106,9 @@ config SND_BT87X depends on SND select SND_PCM help - Say Y here to include support for recording audio from TV - cards based on Brooktree Bt878/Bt879 chips. + If you want to record audio from TV cards based on + Brooktree Bt878/Bt879 chips, say Y here and read + <file:Documentation/sound/alsa/Bt87x.txt>. To compile this driver as a module, choose M here: the module will be called snd-bt87x. @@ -171,6 +172,29 @@ config SND_EMU10K1 To compile this driver as a module, choose M here: the module will be called snd-emu10k1. +config SND_EMU10K1X + tristate "Emu10k1X (Dell OEM Version)" + depends on SND + select SND_AC97_CODEC + select SND_RAWMIDI + help + Say Y here to include support for the Dell OEM version of the + Sound Blaster Live!. + + To compile this driver as a module, choose M here: the module + will be called snd-emu10k1x. + +config SND_CA0106 + tristate "SB Audigy LS / Live 24bit" + depends on SND + select SND_AC97_CODEC + help + Say Y here to include support for the Sound Blaster Audigy LS + and Live 24bit. + + To compile this driver as a module, choose M here: the module + will be called snd-ca0106. + config SND_KORG1212 tristate "Korg 1212 IO" depends on SND @@ -469,6 +493,17 @@ config SND_VIA82XX To compile this driver as a module, choose M here: the module will be called snd-via82xx. +config SND_VIA82XX_MODEM + tristate "VIA 82C686A/B, 8233 based Modems" + depends on SND + select SND_AC97_CODEC + help + Say Y here to include support for the integrated MC97 modem on + motherboards with VIA chipsets. + + To compile this driver as a module, choose M here: the module + will be called snd-via82xx-modem. + config SND_VX222 tristate "Digigram VX222" depends on SND @@ -479,5 +514,15 @@ config SND_VX222 To compile this driver as a module, choose M here: the module will be called snd-vx222. -endmenu +config SND_HDA_INTEL + tristate "Intel HD Audio" + depends on SND + select SND_PCM + help + Say Y here to include support for Intel "High Definition + Audio" (Azalia) motherboard devices. + To compile this driver as a module, choose M here: the module + will be called snd-hda-intel. + +endmenu diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index b5c032036..0b024ec1f 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -56,6 +56,7 @@ typedef struct { const char *name; int (*patch)(ac97_t *ac97); int (*mpatch)(ac97_t *ac97); + unsigned int flags; } ac97_codec_id_t; static const ac97_codec_id_t snd_ac97_codec_id_vendors[] = { @@ -103,8 +104,9 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = { { 0x41445372, 0xffffffff, "AD1981A", patch_ad1981a, NULL }, { 0x41445374, 0xffffffff, "AD1981B", patch_ad1981b, NULL }, { 0x41445375, 0xffffffff, "AD1985", patch_ad1985, NULL }, -{ 0x414c4300, 0xffffff00, "ALC100/100P", NULL, NULL }, -{ 0x414c4710, 0xfffffff0, "ALC200/200P", NULL, NULL }, +{ 0x41445378, 0xffffffff, "AD1986", patch_ad1985, NULL }, +{ 0x414c4300, 0xffffff00, "ALC100,100P", NULL, NULL }, +{ 0x414c4710, 0xfffffff0, "ALC200,200P", NULL, NULL }, { 0x414c4721, 0xffffffff, "ALC650D", NULL, NULL }, /* already patched */ { 0x414c4722, 0xffffffff, "ALC650E", NULL, NULL }, /* already patched */ { 0x414c4723, 0xffffffff, "ALC650F", NULL, NULL }, /* already patched */ @@ -143,11 +145,11 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = { { 0x49434552, 0xffffffff, "VT1616i", patch_vt1616, NULL }, // VT1616 compatible (chipset integrated) { 0x49544520, 0xffffffff, "IT2226E", NULL, NULL }, { 0x49544561, 0xffffffff, "IT2646E", patch_it2646, NULL }, -{ 0x4e534300, 0xffffffff, "LM4540/43/45/46/48", NULL, NULL }, // only guess --jk +{ 0x4e534300, 0xffffffff, "LM4540,43,45,46,48", NULL, NULL }, // only guess --jk { 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", NULL, mpatch_si3036 }, { 0x54524102, 0xffffffff, "TR28022", NULL, NULL }, { 0x54524106, 0xffffffff, "TR28026", NULL, NULL }, { 0x54524108, 0xffffffff, "TR28028", patch_tritech_tr28028, NULL }, // added by xin jin [07/09/99] @@ -156,25 +158,26 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = { { 0x56494161, 0xffffffff, "VIA1612A", NULL, NULL }, // modified ICE1232 with S/PDIF { 0x57454301, 0xffffffff, "W83971D", NULL, NULL }, { 0x574d4c00, 0xffffffff, "WM9701A", NULL, NULL }, -{ 0x574d4C03, 0xffffffff, "WM9703/WM9707/WM9708/WM9717", patch_wolfson03, NULL}, -{ 0x574d4C04, 0xffffffff, "WM9704M/WM9704Q", patch_wolfson04, NULL}, -{ 0x574d4C05, 0xffffffff, "WM9705/WM9710", patch_wolfson05, NULL}, +{ 0x574d4C03, 0xffffffff, "WM9703,WM9707,WM9708,WM9717", patch_wolfson03, NULL}, +{ 0x574d4C04, 0xffffffff, "WM9704M,WM9704Q", patch_wolfson04, NULL}, +{ 0x574d4C05, 0xffffffff, "WM9705,WM9710", patch_wolfson05, NULL}, { 0x574d4C09, 0xffffffff, "WM9709", NULL, NULL}, -{ 0x574d4C12, 0xffffffff, "WM9711/WM9712", patch_wolfson11, NULL}, +{ 0x574d4C12, 0xffffffff, "WM9711,WM9712", patch_wolfson11, NULL}, +{ 0x574d4c13, 0xffffffff, "WM9713,WM9714", patch_wolfson13, NULL, AC97_DEFAULT_POWER_OFF}, { 0x594d4800, 0xffffffff, "YMF743", NULL, NULL }, { 0x594d4802, 0xffffffff, "YMF752", NULL, NULL }, { 0x594d4803, 0xffffffff, "YMF753", patch_yamaha_ymf753, NULL }, -{ 0x83847600, 0xffffffff, "STAC9700/83/84", patch_sigmatel_stac9700, NULL }, -{ 0x83847604, 0xffffffff, "STAC9701/3/4/5", NULL, NULL }, +{ 0x83847600, 0xffffffff, "STAC9700,83,84", patch_sigmatel_stac9700, NULL }, +{ 0x83847604, 0xffffffff, "STAC9701,3,4,5", NULL, NULL }, { 0x83847605, 0xffffffff, "STAC9704", NULL, NULL }, -{ 0x83847608, 0xffffffff, "STAC9708/11", patch_sigmatel_stac9708, NULL }, -{ 0x83847609, 0xffffffff, "STAC9721/23", patch_sigmatel_stac9721, NULL }, +{ 0x83847608, 0xffffffff, "STAC9708,11", patch_sigmatel_stac9708, NULL }, +{ 0x83847609, 0xffffffff, "STAC9721,23", patch_sigmatel_stac9721, NULL }, { 0x83847644, 0xffffffff, "STAC9744", patch_sigmatel_stac9744, NULL }, -{ 0x83847650, 0xffffffff, "STAC9750/51", NULL, NULL }, // patch? -{ 0x83847652, 0xffffffff, "STAC9752/53", NULL, NULL }, // patch? -{ 0x83847656, 0xffffffff, "STAC9756/57", patch_sigmatel_stac9756, NULL }, -{ 0x83847658, 0xffffffff, "STAC9758/59", patch_sigmatel_stac9758, NULL }, -{ 0x83847666, 0xffffffff, "STAC9766/67", NULL, NULL }, // patch? +{ 0x83847650, 0xffffffff, "STAC9750,51", NULL, NULL }, // patch? +{ 0x83847652, 0xffffffff, "STAC9752,53", NULL, NULL }, // patch? +{ 0x83847656, 0xffffffff, "STAC9756,57", patch_sigmatel_stac9756, NULL }, +{ 0x83847658, 0xffffffff, "STAC9758,59", patch_sigmatel_stac9758, NULL }, +{ 0x83847666, 0xffffffff, "STAC9766,67", NULL, NULL }, // patch? { 0, 0, NULL, NULL, NULL } }; @@ -332,11 +335,11 @@ void snd_ac97_write_cache(ac97_t *ac97, unsigned short reg, unsigned short value { if (!snd_ac97_valid_reg(ac97, reg)) return; - spin_lock(&ac97->reg_lock); + down(&ac97->reg_mutex); ac97->regs[reg] = value; - spin_unlock(&ac97->reg_lock); ac97->bus->ops->write(ac97, reg, value); set_bit(reg, ac97->reg_accessed); + up(&ac97->reg_mutex); } /** @@ -357,14 +360,13 @@ int snd_ac97_update(ac97_t *ac97, unsigned short reg, unsigned short value) if (!snd_ac97_valid_reg(ac97, reg)) return -EINVAL; - spin_lock(&ac97->reg_lock); + down(&ac97->reg_mutex); change = ac97->regs[reg] != value; if (change) { ac97->regs[reg] = value; - spin_unlock(&ac97->reg_lock); ac97->bus->ops->write(ac97, reg, value); - } else - spin_unlock(&ac97->reg_lock); + } + up(&ac97->reg_mutex); return change; } @@ -384,20 +386,29 @@ int snd_ac97_update(ac97_t *ac97, unsigned short reg, unsigned short value) int snd_ac97_update_bits(ac97_t *ac97, unsigned short reg, unsigned short mask, unsigned short value) { int change; - unsigned short old, new; if (!snd_ac97_valid_reg(ac97, reg)) return -EINVAL; - spin_lock(&ac97->reg_lock); + down(&ac97->reg_mutex); + change = snd_ac97_update_bits_nolock(ac97, reg, mask, value); + up(&ac97->reg_mutex); + return change; +} + +/* no lock version - see snd_ac97_updat_bits() */ +int snd_ac97_update_bits_nolock(ac97_t *ac97, unsigned short reg, + unsigned short mask, unsigned short value) +{ + int change; + unsigned short old, new; + old = snd_ac97_read_cache(ac97, reg); new = (old & ~mask) | value; change = old != new; if (change) { ac97->regs[reg] = new; - spin_unlock(&ac97->reg_lock); ac97->bus->ops->write(ac97, reg, new); - } else - spin_unlock(&ac97->reg_lock); + } return change; } @@ -406,15 +417,14 @@ static int snd_ac97_ad18xx_update_pcm_bits(ac97_t *ac97, int codec, unsigned sho int change; unsigned short old, new, cfg; - down(&ac97->mutex); - spin_lock(&ac97->reg_lock); + down(&ac97->page_mutex); old = ac97->spec.ad18xx.pcmreg[codec]; new = (old & ~mask) | value; - cfg = snd_ac97_read_cache(ac97, AC97_AD_SERIAL_CFG); change = old != new; if (change) { + down(&ac97->reg_mutex); + cfg = snd_ac97_read_cache(ac97, AC97_AD_SERIAL_CFG); ac97->spec.ad18xx.pcmreg[codec] = new; - spin_unlock(&ac97->reg_lock); /* select single codec */ ac97->bus->ops->write(ac97, AC97_AD_SERIAL_CFG, (cfg & ~0x7000) | @@ -424,249 +434,153 @@ static int snd_ac97_ad18xx_update_pcm_bits(ac97_t *ac97, int codec, unsigned sho /* select all codecs */ ac97->bus->ops->write(ac97, AC97_AD_SERIAL_CFG, cfg | 0x7000); - } else - spin_unlock(&ac97->reg_lock); - up(&ac97->mutex); + up(&ac97->reg_mutex); + } + up(&ac97->page_mutex); return change; } /* - * + * Controls */ -static int snd_ac97_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) +int snd_ac97_info_enum_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) { - static char *texts[8] = { - "Mic", "CD", "Video", "Aux", "Line", - "Mix", "Mix Mono", "Phone" - }; - + struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value; + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 2; - 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]); + uinfo->count = e->shift_l == e->shift_r ? 1 : 2; + uinfo->value.enumerated.items = e->mask; + + if (uinfo->value.enumerated.item > e->mask - 1) + uinfo->value.enumerated.item = e->mask - 1; + strcpy(uinfo->value.enumerated.name, e->texts[uinfo->value.enumerated.item]); return 0; } -static int snd_ac97_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +int snd_ac97_get_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { ac97_t *ac97 = snd_kcontrol_chip(kcontrol); + struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value; unsigned short val; - val = snd_ac97_read_cache(ac97, AC97_REC_SEL); - ucontrol->value.enumerated.item[0] = (val >> 8) & 7; - ucontrol->value.enumerated.item[1] = (val >> 0) & 7; + val = snd_ac97_read_cache(ac97, e->reg); + ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (e->mask - 1); + if (e->shift_l != e->shift_r) + ucontrol->value.enumerated.item[1] = (val >> e->shift_r) & (e->mask - 1); + return 0; } -static int snd_ac97_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +int snd_ac97_put_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { ac97_t *ac97 = snd_kcontrol_chip(kcontrol); + struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value; unsigned short val; + unsigned short mask; - if (ucontrol->value.enumerated.item[0] > 7 || - ucontrol->value.enumerated.item[1] > 7) + if (ucontrol->value.enumerated.item[0] > e->mask - 1) return -EINVAL; - val = (ucontrol->value.enumerated.item[0] << 8) | - (ucontrol->value.enumerated.item[1] << 0); - return snd_ac97_update(ac97, AC97_REC_SEL, val); -} - -#define AC97_ENUM_DOUBLE(xname, reg, shift, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_enum_double, \ - .get = snd_ac97_get_enum_double, .put = snd_ac97_put_enum_double, \ - .private_value = reg | (shift << 8) | (invert << 24) } - -static int snd_ac97_info_enum_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) -{ - static char *texts1[2] = { "pre 3D", "post 3D" }; - static char *texts2[2] = { "Mix", "Mic" }; - static char *texts3[2] = { "Mic1", "Mic2" }; - char **texts = NULL; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - - switch (reg) { - case AC97_GENERAL_PURPOSE: - switch (shift) { - case 15: texts = texts1; break; - case 9: texts = texts2; break; - case 8: texts = texts3; break; - } + val = ucontrol->value.enumerated.item[0] << e->shift_l; + mask = (e->mask - 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; } - 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; + return snd_ac97_update_bits(ac97, e->reg, mask, val); } -static int snd_ac97_get_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +/* save/restore ac97 v2.3 paging */ +static int snd_ac97_page_save(ac97_t *ac97, int reg, snd_kcontrol_t *kcontrol) { - ac97_t *ac97 = snd_kcontrol_chip(kcontrol); - unsigned short val; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - - val = (snd_ac97_read_cache(ac97, reg) >> shift) & 1; - if (invert) - val ^= 1; - ucontrol->value.enumerated.item[0] = val; - return 0; + int page_save = -1; + if ((kcontrol->private_value & (1<<25)) && + (ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23 && + (reg >= 0x60 && reg < 0x70)) { + unsigned short page = (kcontrol->private_value >> 26) & 0x0f; + down(&ac97->page_mutex); /* lock paging */ + page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK; + snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page); + } + return page_save; } -static int snd_ac97_put_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static void snd_ac97_page_restore(ac97_t *ac97, int page_save) { - ac97_t *ac97 = snd_kcontrol_chip(kcontrol); - unsigned short val; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - - if (ucontrol->value.enumerated.item[0] > 1) - return -EINVAL; - val = !!ucontrol->value.enumerated.item[0]; - if (invert) - val = !val; - return snd_ac97_update_bits(ac97, reg, 1 << shift, val << shift); + if (page_save >= 0) { + snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save); + up(&ac97->page_mutex); /* unlock paging */ + } } -int snd_ac97_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) +/* volume and switch controls */ +int snd_ac97_info_volsw(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) { int mask = (kcontrol->private_value >> 16) & 0xff; + int shift = (kcontrol->private_value >> 8) & 0x0f; + int rshift = (kcontrol->private_value >> 12) & 0x0f; uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; + uinfo->count = shift == rshift ? 1 : 2; uinfo->value.integer.min = 0; uinfo->value.integer.max = mask; return 0; } -int snd_ac97_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +int snd_ac97_get_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { ac97_t *ac97 = snd_kcontrol_chip(kcontrol); int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; + int shift = (kcontrol->private_value >> 8) & 0x0f; + int rshift = (kcontrol->private_value >> 12) & 0x0f; int mask = (kcontrol->private_value >> 16) & 0xff; int invert = (kcontrol->private_value >> 24) & 0x01; - + int page_save; + + page_save = snd_ac97_page_save(ac97, reg, kcontrol); ucontrol->value.integer.value[0] = (snd_ac97_read_cache(ac97, reg) >> shift) & mask; - if (invert) + if (shift != rshift) + ucontrol->value.integer.value[1] = (snd_ac97_read_cache(ac97, reg) >> rshift) & mask; + if (invert) { ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; + if (shift != rshift) + ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; + } + snd_ac97_page_restore(ac97, page_save); return 0; } -int snd_ac97_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +int snd_ac97_put_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { ac97_t *ac97 = snd_kcontrol_chip(kcontrol); int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; + int shift = (kcontrol->private_value >> 8) & 0x0f; + int rshift = (kcontrol->private_value >> 12) & 0x0f; int mask = (kcontrol->private_value >> 16) & 0xff; int invert = (kcontrol->private_value >> 24) & 0x01; - unsigned short val; + int err, page_save; + unsigned short val, val2, val_mask; + page_save = snd_ac97_page_save(ac97, reg, kcontrol); val = (ucontrol->value.integer.value[0] & mask); if (invert) val = mask - val; - return snd_ac97_update_bits(ac97, reg, mask << shift, val << shift); -} - -#define AC97_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .info = snd_ac97_info_double, \ - .get = snd_ac97_get_double, .put = snd_ac97_put_double, \ - .private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) | ((mask) << 16) | ((invert) << 24) } - -static int snd_ac97_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) -{ - int mask = (kcontrol->private_value >> 16) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_ac97_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) -{ - ac97_t *ac97 = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift_left = (kcontrol->private_value >> 8) & 0x0f; - int shift_right = (kcontrol->private_value >> 12) & 0x0f; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - - spin_lock(&ac97->reg_lock); - ucontrol->value.integer.value[0] = (snd_ac97_read_cache(ac97, reg) >> shift_left) & mask; - ucontrol->value.integer.value[1] = (snd_ac97_read_cache(ac97, reg) >> shift_right) & mask; - spin_unlock(&ac97->reg_lock); - 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; -} - -static int snd_ac97_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) -{ - ac97_t *ac97 = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift_left = (kcontrol->private_value >> 8) & 0x0f; - int shift_right = (kcontrol->private_value >> 12) & 0x0f; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - unsigned short val1, val2; - - val1 = ucontrol->value.integer.value[0] & mask; - val2 = ucontrol->value.integer.value[1] & mask; - if (invert) { - val1 = mask - val1; - val2 = mask - val2; - } - return snd_ac97_update_bits(ac97, reg, - (mask << shift_left) | (mask << shift_right), - (val1 << shift_left) | (val2 << shift_right)); -} - -int snd_ac97_getput_page(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol, - int (*func)(snd_kcontrol_t *, snd_ctl_elem_value_t *)) -{ - ac97_t *ac97 = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int err; - - if ((ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23 && - (reg >= 0x60 && reg < 0x70)) { - unsigned short page_save; - unsigned short page = (kcontrol->private_value >> 25) & 0x0f; - down(&ac97->mutex); /* lock paging */ - page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK; - snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page); - err = func(kcontrol, ucontrol); - snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save); - up(&ac97->mutex); /* unlock paging */ - } else - err = func(kcontrol, ucontrol); + val_mask = mask << shift; + val = val << shift; + if (shift != rshift) { + val2 = (ucontrol->value.integer.value[1] & mask); + if (invert) + val2 = mask - val2; + val_mask |= mask << rshift; + val |= val2 << rshift; + } + err = snd_ac97_update_bits(ac97, reg, val_mask, val); + snd_ac97_page_restore(ac97, page_save); return err; } -/* for rev2.3 paging */ -int snd_ac97_page_get_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - return snd_ac97_getput_page(kcontrol, ucontrol, snd_ac97_get_single); -} - -/* for rev2.3 paging */ -int snd_ac97_page_put_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - return snd_ac97_getput_page(kcontrol, ucontrol, snd_ac97_put_single); -} - static const snd_kcontrol_new_t snd_ac97_controls_master_mono[2] = { AC97_SINGLE("Master Mono Playback Switch", AC97_MASTER_MONO, 15, 1, 1), AC97_SINGLE("Master Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 1) @@ -682,25 +596,25 @@ AC97_SINGLE("PC Speaker Playback Switch", AC97_PC_BEEP, 15, 1, 1), AC97_SINGLE("PC Speaker Playback Volume", AC97_PC_BEEP, 1, 15, 1) }; -static const snd_kcontrol_new_t snd_ac97_controls_phone[2] = { -AC97_SINGLE("Phone Playback Switch", AC97_PHONE, 15, 1, 1), -AC97_SINGLE("Phone Playback Volume", AC97_PHONE, 0, 15, 1) -}; +static const snd_kcontrol_new_t snd_ac97_controls_mic_boost = + AC97_SINGLE("Mic Boost (+20dB)", AC97_MIC, 6, 1, 0); -static const snd_kcontrol_new_t snd_ac97_controls_mic[3] = { -AC97_SINGLE("Mic Playback Switch", AC97_MIC, 15, 1, 1), -AC97_SINGLE("Mic Playback Volume", AC97_MIC, 0, 15, 1), -AC97_SINGLE("Mic Boost (+20dB)", AC97_MIC, 6, 1, 0) -}; -static const snd_kcontrol_new_t snd_ac97_control_capture_src = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = snd_ac97_info_mux, - .get = snd_ac97_get_mux, - .put = snd_ac97_put_mux, +static const char* std_rec_sel[] = {"Mic", "CD", "Video", "Aux", "Line", "Mix", "Mix Mono", "Phone"}; +static const char* std_3d_path[] = {"pre 3D", "post 3D"}; +static const char* std_mix[] = {"Mix", "Mic"}; +static const char* std_mic[] = {"Mic1", "Mic2"}; + +static const struct ac97_enum std_enum[] = { +AC97_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 8, std_rec_sel), +AC97_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, std_3d_path), +AC97_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 9, 2, std_mix), +AC97_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 8, 2, std_mic), }; +static const snd_kcontrol_new_t snd_ac97_control_capture_src = +AC97_ENUM("Capture Source", std_enum[0]); + static const snd_kcontrol_new_t snd_ac97_control_capture_vol = AC97_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 15, 0); @@ -720,12 +634,12 @@ typedef enum { } ac97_general_index_t; static const snd_kcontrol_new_t snd_ac97_controls_general[7] = { -AC97_ENUM_DOUBLE("PCM Out Path & Mute", AC97_GENERAL_PURPOSE, 15, 0), +AC97_ENUM("PCM Out Path & Mute", std_enum[1]), AC97_SINGLE("Simulated Stereo Enhancement", AC97_GENERAL_PURPOSE, 14, 1, 0), AC97_SINGLE("3D Control - Switch", AC97_GENERAL_PURPOSE, 13, 1, 0), AC97_SINGLE("Loudness (bass boost)", AC97_GENERAL_PURPOSE, 12, 1, 0), -AC97_ENUM_DOUBLE("Mono Output Select", AC97_GENERAL_PURPOSE, 9, 0), -AC97_ENUM_DOUBLE("Mic Select", AC97_GENERAL_PURPOSE, 8, 0), +AC97_ENUM("Mono Output Select", std_enum[2]), +AC97_ENUM("Mic Select", std_enum[3]), AC97_SINGLE("ADC/DAC Loopback", AC97_GENERAL_PURPOSE, 7, 1, 0) }; @@ -793,12 +707,12 @@ static int snd_ac97_spdif_default_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_val { ac97_t *ac97 = snd_kcontrol_chip(kcontrol); - spin_lock(&ac97->reg_lock); + down(&ac97->reg_mutex); ucontrol->value.iec958.status[0] = ac97->spdif_status & 0xff; ucontrol->value.iec958.status[1] = (ac97->spdif_status >> 8) & 0xff; ucontrol->value.iec958.status[2] = (ac97->spdif_status >> 16) & 0xff; ucontrol->value.iec958.status[3] = (ac97->spdif_status >> 24) & 0xff; - spin_unlock(&ac97->reg_lock); + up(&ac97->reg_mutex); return 0; } @@ -809,7 +723,6 @@ static int snd_ac97_spdif_default_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val unsigned short val = 0; int change; - spin_lock(&ac97->reg_lock); new = val = ucontrol->value.iec958.status[0] & (IEC958_AES0_PROFESSIONAL|IEC958_AES0_NONAUDIO); if (ucontrol->value.iec958.status[0] & IEC958_AES0_PROFESSIONAL) { new |= ucontrol->value.iec958.status[0] & (IEC958_AES0_PRO_FS|IEC958_AES0_PRO_EMPHASIS_5015); @@ -838,9 +751,9 @@ static int snd_ac97_spdif_default_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val } } + down(&ac97->reg_mutex); change = ac97->spdif_status != new; ac97->spdif_status = new; - spin_unlock(&ac97->reg_lock); if (ac97->flags & AC97_CS_SPDIF) { int x = (val >> 12) & 0x03; @@ -849,23 +762,24 @@ static int snd_ac97_spdif_default_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val case 2: x = 0; break; // 48.0 default: x = 0; break; // illegal. } - change |= snd_ac97_update_bits(ac97, AC97_CSR_SPDIF, 0x3fff, ((val & 0xcfff) | (x << 12))); + change |= snd_ac97_update_bits_nolock(ac97, AC97_CSR_SPDIF, 0x3fff, ((val & 0xcfff) | (x << 12))); } else if (ac97->flags & AC97_CX_SPDIF) { int v; v = new & (IEC958_AES0_CON_EMPHASIS_5015|IEC958_AES0_CON_NOT_COPYRIGHT) ? 0 : AC97_CXR_COPYRGT; v |= new & IEC958_AES0_NONAUDIO ? AC97_CXR_SPDIF_AC3 : AC97_CXR_SPDIF_PCM; - change |= snd_ac97_update_bits(ac97, AC97_CXR_AUDIO_MISC, - AC97_CXR_SPDIF_MASK | AC97_CXR_COPYRGT, - v); + change |= snd_ac97_update_bits_nolock(ac97, AC97_CXR_AUDIO_MISC, + AC97_CXR_SPDIF_MASK | AC97_CXR_COPYRGT, + v); } else { unsigned short extst = snd_ac97_read_cache(ac97, AC97_EXTENDED_STATUS); - snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); /* turn off */ + snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); /* turn off */ - change |= snd_ac97_update_bits(ac97, AC97_SPDIF, 0x3fff, val); + change |= snd_ac97_update_bits_nolock(ac97, AC97_SPDIF, 0x3fff, val); if (extst & AC97_EA_SPDIF) { - snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); /* turn on again */ + snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); /* turn on again */ } } + up(&ac97->reg_mutex); return change; } @@ -878,26 +792,26 @@ static int snd_ac97_put_spsa(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uco int mask = (kcontrol->private_value >> 16) & 0xff; // int invert = (kcontrol->private_value >> 24) & 0xff; unsigned short value, old, new; + int change; value = (ucontrol->value.integer.value[0] & mask); + down(&ac97->reg_mutex); mask <<= shift; value <<= shift; - spin_lock(&ac97->reg_lock); old = snd_ac97_read_cache(ac97, reg); new = (old & ~mask) | value; - spin_unlock(&ac97->reg_lock); + change = old != new; - if (old != new) { - int change; + if (change) { unsigned short extst = snd_ac97_read_cache(ac97, AC97_EXTENDED_STATUS); - snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); /* turn off */ - change = snd_ac97_update_bits(ac97, reg, mask, value); + snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); /* turn off */ + change = snd_ac97_update_bits_nolock(ac97, reg, mask, value); if (extst & AC97_EA_SPDIF) - snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); /* turn on again */ - return change; + snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); /* turn on again */ } - return 0; + up(&ac97->reg_mutex); + return change; } const snd_kcontrol_new_t snd_ac97_controls_spdif[5] = { @@ -927,8 +841,8 @@ const snd_kcontrol_new_t snd_ac97_controls_spdif[5] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "AC97-SPSA", - .info = snd_ac97_info_single, - .get = snd_ac97_get_single, + .info = snd_ac97_info_volsw, + .get = snd_ac97_get_volsw, .put = snd_ac97_put_spsa, .private_value = AC97_SINGLE_VALUE(AC97_EXTENDED_STATUS, 4, 3, 0) }, @@ -1007,10 +921,10 @@ static int snd_ac97_ad18xx_pcm_get_volume(snd_kcontrol_t * kcontrol, snd_ctl_ele ac97_t *ac97 = snd_kcontrol_chip(kcontrol); int codec = kcontrol->private_value & 3; - spin_lock(&ac97->reg_lock); + down(&ac97->page_mutex); ucontrol->value.integer.value[0] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 0) & 31); ucontrol->value.integer.value[1] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 8) & 31); - spin_unlock(&ac97->reg_lock); + up(&ac97->page_mutex); return 0; } @@ -1055,8 +969,7 @@ static int snd_ac97_bus_free(ac97_bus_t *bus) { if (bus) { snd_ac97_bus_proc_done(bus); - if (bus->pcms) - kfree(bus->pcms); + kfree(bus->pcms); if (bus->private_free) bus->private_free(bus); kfree(bus); @@ -1148,6 +1061,26 @@ static int snd_ac97_try_volume_mix(ac97_t * ac97, int reg) return 1; /* success, useable */ } +static void check_volume_resolution(ac97_t *ac97, int reg, unsigned char *lo_max, unsigned char *hi_max) +{ + unsigned short cbit[3] = { 0x20, 0x10, 0x01 }; + unsigned char max[3] = { 63, 31, 15 }; + int i; + + *lo_max = *hi_max = 0; + for (i = 0 ; i < ARRAY_SIZE(cbit); i++) { + 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])) + *lo_max = max[i]; + if (! *hi_max && (val & (cbit[i] << 8))) + *hi_max = max[i]; + if (*lo_max && *hi_max) + break; + } +} + int snd_ac97_try_bit(ac97_t * ac97, int reg, int bit) { unsigned short mask, val, orig, res; @@ -1161,21 +1094,6 @@ int snd_ac97_try_bit(ac97_t * ac97, int reg, int bit) return res == val; } -static void snd_ac97_change_volume_params1(ac97_t * ac97, int reg, unsigned char *max) -{ - unsigned short val, val1; - - *max = 63; - val = 0x8000 | 0x0020; - snd_ac97_write(ac97, reg, val); - val1 = snd_ac97_read(ac97, reg); - if (val != val1) { - *max = 31; - } - /* reset volume to zero */ - snd_ac97_write_cache(ac97, reg, 0x8000); -} - /* check the volume resolution of center/lfe */ static void snd_ac97_change_volume_params2(ac97_t * ac97, int reg, int shift, unsigned char *max) { @@ -1192,34 +1110,6 @@ static void snd_ac97_change_volume_params2(ac97_t * ac97, int reg, int shift, un snd_ac97_write_cache(ac97, reg, 0x8080); } -/* check whether the volume resolution is 4 or 5 bits */ -static void snd_ac97_change_volume_params3(ac97_t * ac97, int reg, unsigned char *max) -{ - unsigned short val, val1; - - *max = 31; - val = 0x8000 | 0x0010; - snd_ac97_write(ac97, reg, val); - val1 = snd_ac97_read(ac97, reg); - if (val != val1) { - *max = 15; - } - /* reset volume to zero */ - snd_ac97_write_cache(ac97, reg, 0x8000); -} - -/* check whether the volume is mono or stereo */ -static int snd_ac97_is_stereo_vol(ac97_t *ac97, int reg) -{ - unsigned short val, val1, val2; - val = snd_ac97_read(ac97, reg); - val1 = val | 0x8000 | (0x01 << 8); - snd_ac97_write(ac97, reg, val1); - val2 = snd_ac97_read(ac97, reg); - snd_ac97_write(ac97, reg, val); /* restore */ - return val1 == val2; -} - static inline int printable(unsigned int x) { x &= 0xff; @@ -1243,25 +1133,25 @@ snd_kcontrol_t *snd_ac97_cnew(const snd_kcontrol_new_t *_template, ac97_t * ac97 /* * create mute switch(es) for normal stereo controls */ -static int snd_ac97_cmute_new(snd_card_t *card, char *name, int reg, ac97_t *ac97) +static int snd_ac97_cmute_new_stereo(snd_card_t *card, char *name, int reg, int check_stereo, ac97_t *ac97) { snd_kcontrol_t *kctl; - int stereo = 0; + int err; + unsigned short val, val1, mute_mask; if (! snd_ac97_valid_reg(ac97, reg)) return 0; - if (ac97->flags & AC97_STEREO_MUTES) { + mute_mask = 0x8000; + val = snd_ac97_read(ac97, reg); + if (check_stereo || (ac97->flags & AC97_STEREO_MUTES)) { /* check whether both mute bits work */ - unsigned short val, val1; - val = snd_ac97_read(ac97, reg); val1 = val | 0x8080; snd_ac97_write(ac97, reg, val1); if (val1 == snd_ac97_read(ac97, reg)) - stereo = 1; - snd_ac97_write(ac97, reg, val); + mute_mask = 0x8080; } - if (stereo) { + if (mute_mask == 0x8080) { snd_kcontrol_new_t tmp = AC97_DOUBLE(name, reg, 15, 7, 1, 1); tmp.index = ac97->num; kctl = snd_ctl_new1(&tmp, ac97); @@ -1270,53 +1160,73 @@ static int snd_ac97_cmute_new(snd_card_t *card, char *name, int reg, ac97_t *ac9 tmp.index = ac97->num; kctl = snd_ctl_new1(&tmp, ac97); } - return snd_ctl_add(card, kctl); + err = snd_ctl_add(card, kctl); + if (err < 0) + return err; + /* mute as default */ + snd_ac97_write_cache(ac97, reg, val | mute_mask); + return 0; } /* - * create volumes for normal stereo controls + * create a volume for normal stereo/mono controls */ -static int snd_ac97_cvol_new(snd_card_t *card, char *name, int reg, unsigned int max, ac97_t *ac97) +static int snd_ac97_cvol_new(snd_card_t *card, char *name, int reg, unsigned int lo_max, + unsigned int hi_max, ac97_t *ac97) { int err; - snd_kcontrol_new_t tmp = AC97_DOUBLE(name, reg, 8, 0, (unsigned int)max, 1); - tmp.index = ac97->num; + snd_kcontrol_t *kctl; if (! snd_ac97_valid_reg(ac97, reg)) return 0; - if ((err = snd_ctl_add(card, snd_ctl_new1(&tmp, ac97))) < 0) + if (hi_max) { + /* invert */ + snd_kcontrol_new_t tmp = AC97_DOUBLE(name, reg, 8, 0, lo_max, 1); + tmp.index = ac97->num; + kctl = snd_ctl_new1(&tmp, ac97); + } else { + /* invert */ + snd_kcontrol_new_t tmp = AC97_SINGLE(name, reg, 0, lo_max, 1); + tmp.index = ac97->num; + kctl = snd_ctl_new1(&tmp, ac97); + } + err = snd_ctl_add(card, kctl); + if (err < 0) return err; snd_ac97_write_cache(ac97, reg, - ((ac97->flags & AC97_STEREO_MUTES) ? 0x8080 : 0x8000) | - (unsigned short)max | ((unsigned short)max << 8)); + (snd_ac97_read(ac97, reg) & 0x8080) | + lo_max | (hi_max << 8)); return 0; } /* - * create mute-switch and volumes for normal stereo controls + * create a mute-switch and a volume for normal stereo/mono controls */ -static int snd_ac97_cmix_new(snd_card_t *card, const char *pfx, int reg, int check_res, ac97_t *ac97) +static int snd_ac97_cmix_new_stereo(snd_card_t *card, const char *pfx, int reg, int check_stereo, ac97_t *ac97) { int err; char name[44]; - unsigned char max; + unsigned char lo_max, hi_max; if (! snd_ac97_valid_reg(ac97, reg)) return 0; - sprintf(name, "%s Switch", pfx); - if ((err = snd_ac97_cmute_new(card, name, reg, ac97)) < 0) - return err; - sprintf(name, "%s Volume", pfx); - if (check_res) - snd_ac97_change_volume_params1(ac97, reg, &max); - else - max = 31; /* 5bit */ - if ((err = snd_ac97_cvol_new(card, name, reg, max, ac97)) < 0) - return err; + if (snd_ac97_try_bit(ac97, reg, 15)) { + sprintf(name, "%s Switch", pfx); + if ((err = snd_ac97_cmute_new_stereo(card, name, reg, check_stereo, ac97)) < 0) + return err; + } + check_volume_resolution(ac97, reg, &lo_max, &hi_max); + if (lo_max) { + sprintf(name, "%s Volume", pfx); + if ((err = snd_ac97_cvol_new(card, name, reg, lo_max, hi_max, ac97)) < 0) + return err; + } return 0; } +#define snd_ac97_cmix_new(card, pfx, reg, ac97) snd_ac97_cmix_new_stereo(card, pfx, reg, 0, ac97) +#define snd_ac97_cmute_new(card, name, reg, ac97) snd_ac97_cmute_new_stereo(card, name, reg, 0, ac97) static unsigned int snd_ac97_determine_spdif_rates(ac97_t *ac97); @@ -1331,7 +1241,11 @@ static int snd_ac97_mixer_build(ac97_t * ac97) /* build master controls */ /* AD claims to remove this control from AD1887, although spec v2.2 does not allow this */ if (snd_ac97_try_volume_mix(ac97, AC97_MASTER)) { - if ((err = snd_ac97_cmix_new(card, "Master Playback", AC97_MASTER, 1, ac97)) < 0) + if (ac97->flags & AC97_HAS_NO_MASTER_VOL) + err = snd_ac97_cmute_new(card, "Master Playback Switch", AC97_MASTER, ac97); + else + err = snd_ac97_cmix_new(card, "Master Playback", AC97_MASTER, ac97); + if (err < 0) return err; } @@ -1363,32 +1277,21 @@ static int snd_ac97_mixer_build(ac97_t * ac97) /* build surround controls */ if (snd_ac97_try_volume_mix(ac97, AC97_SURROUND_MASTER)) { - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_surround[0], ac97))) < 0) - return err; - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_surround[1], ac97))) < 0) + /* Surround Master (0x38) is with stereo mutes */ + if ((err = snd_ac97_cmix_new_stereo(card, "Surround Playback", AC97_SURROUND_MASTER, 1, ac97)) < 0) return err; - snd_ac97_change_volume_params2(ac97, AC97_SURROUND_MASTER, 0, &max); - kctl->private_value &= ~(0xff << 16); - kctl->private_value |= (int)max << 16; - snd_ac97_write_cache(ac97, AC97_SURROUND_MASTER, 0x8080 | max | (max << 8)); } /* build headphone controls */ if (snd_ac97_try_volume_mix(ac97, AC97_HEADPHONE)) { - if ((err = snd_ac97_cmix_new(card, "Headphone Playback", AC97_HEADPHONE, 1, ac97)) < 0) + if ((err = snd_ac97_cmix_new(card, "Headphone Playback", AC97_HEADPHONE, ac97)) < 0) return err; } /* build master mono controls */ if (snd_ac97_try_volume_mix(ac97, AC97_MASTER_MONO)) { - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_master_mono[0], ac97))) < 0) - return err; - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_master_mono[1], ac97))) < 0) + if ((err = snd_ac97_cmix_new(card, "Master Mono Playback", AC97_MASTER_MONO, ac97)) < 0) return err; - snd_ac97_change_volume_params1(ac97, AC97_MASTER_MONO, &max); - kctl->private_value &= ~(0xff << 16); - kctl->private_value |= (int)max << 16; - snd_ac97_write_cache(ac97, AC97_MASTER_MONO, 0x8000 | max); } /* build master tone controls */ @@ -1405,8 +1308,9 @@ static int snd_ac97_mixer_build(ac97_t * ac97) } /* build PC Speaker controls */ - if ((ac97->flags & AC97_HAS_PC_BEEP) || - snd_ac97_try_volume_mix(ac97, AC97_PC_BEEP)) { + if (!(ac97->flags & AC97_HAS_NO_PC_BEEP) && + ((ac97->flags & AC97_HAS_PC_BEEP) || + snd_ac97_try_volume_mix(ac97, AC97_PC_BEEP))) { for (idx = 0; idx < 2; idx++) if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_pc_beep[idx], ac97))) < 0) return err; @@ -1415,57 +1319,46 @@ static int snd_ac97_mixer_build(ac97_t * ac97) } /* build Phone controls */ - if (snd_ac97_try_volume_mix(ac97, AC97_PHONE)) { - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_phone[0], ac97))) < 0) - return err; - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_phone[1], ac97))) < 0) - return err; - snd_ac97_change_volume_params3(ac97, AC97_PHONE, &max); - kctl->private_value &= ~(0xff << 16); - kctl->private_value |= (int)max << 16; - snd_ac97_write_cache(ac97, AC97_PHONE, 0x8000 | max); + if (!(ac97->flags & AC97_HAS_NO_PHONE)) { + if (snd_ac97_try_volume_mix(ac97, AC97_PHONE)) { + if ((err = snd_ac97_cmix_new(card, "Phone Playback", AC97_PHONE, ac97)) < 0) + return err; + } } /* build MIC controls */ - snd_ac97_change_volume_params3(ac97, AC97_MIC, &max); - if (snd_ac97_is_stereo_vol(ac97, AC97_MIC)) { - /* build stereo mic */ - if ((err = snd_ac97_cmute_new(card, "Mic Playback Switch", AC97_MIC, ac97)) < 0) - return err; - if ((err = snd_ac97_cvol_new(card, "Mic Playback Volume", AC97_MIC, max, ac97)) < 0) + if (snd_ac97_try_volume_mix(ac97, AC97_MIC)) { + if ((err = snd_ac97_cmix_new(card, "Mic Playback", AC97_MIC, ac97)) < 0) return err; - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_mic[2], ac97))) < 0) + if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_mic_boost, ac97))) < 0) return err; - } else { - /* build mono mic */ - for (idx = 0; idx < 3; idx++) { - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_mic[idx], ac97))) < 0) - return err; - if (idx == 1) { // volume - kctl->private_value &= ~(0xff << 16); - kctl->private_value |= (int)max << 16; - } - } - snd_ac97_write_cache(ac97, AC97_MIC, 0x8000 | max); } /* build Line controls */ - if ((err = snd_ac97_cmix_new(card, "Line Playback", AC97_LINE, 0, ac97)) < 0) - return err; + if (snd_ac97_try_volume_mix(ac97, AC97_LINE)) { + if ((err = snd_ac97_cmix_new(card, "Line Playback", AC97_LINE, ac97)) < 0) + return err; + } /* build CD controls */ - if ((err = snd_ac97_cmix_new(card, "CD Playback", AC97_CD, 0, ac97)) < 0) - return err; + if (!(ac97->flags & AC97_HAS_NO_CD)) { + if (snd_ac97_try_volume_mix(ac97, AC97_CD)) { + if ((err = snd_ac97_cmix_new(card, "CD Playback", AC97_CD, ac97)) < 0) + return err; + } + } /* build Video controls */ - if (snd_ac97_try_volume_mix(ac97, AC97_VIDEO)) { - if ((err = snd_ac97_cmix_new(card, "Video Playback", AC97_VIDEO, 0, ac97)) < 0) - return err; + if (!(ac97->flags & AC97_HAS_NO_VIDEO)) { + if (snd_ac97_try_volume_mix(ac97, AC97_VIDEO)) { + if ((err = snd_ac97_cmix_new(card, "Video Playback", AC97_VIDEO, ac97)) < 0) + return err; + } } /* build Aux controls */ if (snd_ac97_try_volume_mix(ac97, AC97_AUX)) { - if ((err = snd_ac97_cmix_new(card, "Aux Playback", AC97_AUX, 0, ac97)) < 0) + if ((err = snd_ac97_cmix_new(card, "Aux Playback", AC97_AUX, ac97)) < 0) return err; } @@ -1497,29 +1390,27 @@ static int snd_ac97_mixer_build(ac97_t * ac97) } snd_ac97_write_cache(ac97, AC97_PCM, init_val); } else { - if ((err = snd_ac97_cmute_new(card, "PCM Playback Switch", AC97_PCM, ac97)) < 0) + if (ac97->flags & AC97_HAS_NO_PCM_VOL) + err = snd_ac97_cmute_new(card, "PCM Playback Switch", AC97_PCM, ac97); + else + err = snd_ac97_cmix_new(card, "PCM Playback", AC97_PCM, ac97); + if (err < 0) return err; - /* FIXME: C-Media chips have no PCM volume!! */ - if (ac97->id == AC97_ID_CM9739) - snd_ac97_write_cache(ac97, AC97_PCM, 0x9f1f); - else { - if ((err = snd_ac97_cvol_new(card, "PCM Playback Volume", AC97_PCM, 31, ac97)) < 0) - return err; - } } /* build Capture controls */ - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_src, ac97))) < 0) - return err; - if (snd_ac97_try_bit(ac97, AC97_REC_GAIN, 15)) { - if ((err = snd_ac97_cmute_new(card, "Capture Switch", AC97_REC_GAIN, ac97)) < 0) + if (!(ac97->flags & AC97_HAS_NO_REC_GAIN)) { + if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_src, ac97))) < 0) return err; + if (snd_ac97_try_bit(ac97, AC97_REC_GAIN, 15)) { + if ((err = snd_ac97_cmute_new(card, "Capture Switch", AC97_REC_GAIN, ac97)) < 0) + return err; + } + if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_vol, ac97))) < 0) + return err; + snd_ac97_write_cache(ac97, AC97_REC_SEL, 0x0000); + snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x0000); } - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_vol, ac97))) < 0) - return err; - snd_ac97_write_cache(ac97, AC97_REC_SEL, 0x0000); - snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x0000); - /* build MIC Capture controls */ if (snd_ac97_try_volume_mix(ac97, AC97_REC_GAIN_MIC)) { for (idx = 0; idx < 2; idx++) @@ -1573,7 +1464,7 @@ static int snd_ac97_mixer_build(ac97_t * ac97) snd_ac97_update_bits(ac97, AC97_GENERAL_PURPOSE, ~AC97_GP_DRSS_MASK, 0x0000); /* build 3D controls */ - if (ac97->build_ops && ac97->build_ops->build_3d) { + if (ac97->build_ops->build_3d) { ac97->build_ops->build_3d(ac97); } else { if (snd_ac97_try_volume_mix(ac97, AC97_3D_CONTROL)) { @@ -1595,15 +1486,15 @@ static int snd_ac97_mixer_build(ac97_t * ac97) } /* build S/PDIF controls */ - if (ac97->ext_id & AC97_EI_SPDIF) { - if (ac97->build_ops && ac97->build_ops->build_spdif) { + if ((ac97->ext_id & AC97_EI_SPDIF) && !(ac97->scaps & AC97_SCAP_NO_SPDIF)) { + if (ac97->build_ops->build_spdif) { if ((err = ac97->build_ops->build_spdif(ac97)) < 0) return err; } else { for (idx = 0; idx < 5; idx++) if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_spdif[idx], ac97))) < 0) return err; - if (ac97->build_ops && ac97->build_ops->build_post_spdif) { + if (ac97->build_ops->build_post_spdif) { if ((err = ac97->build_ops->build_post_spdif(ac97)) < 0) return err; } @@ -1616,7 +1507,7 @@ static int snd_ac97_mixer_build(ac97_t * ac97) } /* build chip specific controls */ - if (ac97->build_ops && ac97->build_ops->build_specific) + if (ac97->build_ops->build_specific) if ((err = ac97->build_ops->build_specific(ac97)) < 0) return err; @@ -1661,7 +1552,17 @@ static int snd_ac97_test_rate(ac97_t *ac97, int reg, int shadow_reg, int rate) static void snd_ac97_determine_rates(ac97_t *ac97, int reg, int shadow_reg, unsigned int *r_result) { unsigned int result = 0; + unsigned short saved; + if (ac97->bus->no_vra) { + *r_result = SNDRV_PCM_RATE_48000; + if ((ac97->flags & AC97_DOUBLE_RATE) && + reg == AC97_PCM_FRONT_DAC_RATE) + *r_result |= SNDRV_PCM_RATE_96000; + return; + } + + saved = snd_ac97_read(ac97, reg); if ((ac97->ext_id & AC97_EI_DRA) && reg == AC97_PCM_FRONT_DAC_RATE) snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_DRA, 0); @@ -1700,6 +1601,10 @@ static void snd_ac97_determine_rates(ac97_t *ac97, int reg, int shadow_reg, unsi snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_DRA, 0); } + /* restore the default value */ + snd_ac97_write_cache(ac97, reg, saved); + if (shadow_reg) + snd_ac97_write_cache(ac97, shadow_reg, saved); *r_result = result; } @@ -1723,6 +1628,18 @@ static unsigned int snd_ac97_determine_spdif_rates(ac97_t *ac97) return result; } +/* look for the codec id table matching with the given id */ +static const ac97_codec_id_t *look_for_codec_id(const ac97_codec_id_t *table, + unsigned int id) +{ + const ac97_codec_id_t *pid; + + for (pid = table; pid->id; pid++) + if (pid->id == (id & pid->mask)) + return pid; + return NULL; +} + void snd_ac97_get_name(ac97_t *ac97, unsigned int id, char *name, int modem) { const ac97_codec_id_t *pid; @@ -1731,35 +1648,30 @@ void snd_ac97_get_name(ac97_t *ac97, unsigned int id, char *name, int modem) printable(id >> 24), printable(id >> 16), printable(id >> 8)); - for (pid = snd_ac97_codec_id_vendors; pid->id; pid++) - if (pid->id == (id & pid->mask)) { - strcpy(name, pid->name); - if (ac97) { - if (!modem && pid->patch) - pid->patch(ac97); - else if (modem && pid->mpatch) - pid->mpatch(ac97); - } - goto __vendor_ok; - } - return; + pid = look_for_codec_id(snd_ac97_codec_id_vendors, id); + if (! pid) + return; - __vendor_ok: - for (pid = snd_ac97_codec_ids; pid->id; pid++) - if (pid->id == (id & pid->mask)) { - strcat(name, " "); - strcat(name, pid->name); - if (pid->mask != 0xffffffff) - sprintf(name + strlen(name), " rev %d", id & ~pid->mask); - if (ac97) { - if (!modem && pid->patch) - pid->patch(ac97); - else if (modem && pid->mpatch) - pid->mpatch(ac97); - } - return; + strcpy(name, pid->name); + if (ac97 && pid->patch) { + if ((modem && (pid->flags & AC97_MODEM_PATCH)) || + (! modem && ! (pid->flags & AC97_MODEM_PATCH))) + pid->patch(ac97); + } + + pid = look_for_codec_id(snd_ac97_codec_ids, id); + if (pid) { + strcat(name, " "); + strcat(name, pid->name); + if (pid->mask != 0xffffffff) + sprintf(name + strlen(name), " rev %d", id & ~pid->mask); + if (ac97 && pid->patch) { + if ((modem && (pid->flags & AC97_MODEM_PATCH)) || + (! modem && ! (pid->flags & AC97_MODEM_PATCH))) + pid->patch(ac97); } - sprintf(name + strlen(name), " id %x", id & 0xff); + } else + sprintf(name + strlen(name), " id %x", id & 0xff); } /** @@ -1863,7 +1775,7 @@ int snd_ac97_bus(snd_card_t *card, int num, ac97_bus_ops_t *ops, bus->clock = 48000; spin_lock_init(&bus->bus_lock); snd_ac97_bus_proc_init(bus); - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, bus, &dev_ops)) < 0) { + if ((err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops)) < 0) { snd_ac97_bus_free(bus); return err; } @@ -1871,6 +1783,9 @@ int snd_ac97_bus(snd_card_t *card, int num, ac97_bus_ops_t *ops, return 0; } +/* build_ops to do nothing */ +static struct snd_ac97_build_ops null_build_ops; + /** * snd_ac97_mixer - create an Codec97 component * @bus: the AC97 bus which codec is attached to @@ -1898,6 +1813,7 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97) char name[64]; unsigned long end_time; unsigned int reg; + const ac97_codec_id_t *pid; static snd_device_ops_t ops = { .dev_free = snd_ac97_dev_free, }; @@ -1936,8 +1852,8 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97) ac97->limited_regs = template->limited_regs; memcpy(ac97->reg_accessed, template->reg_accessed, sizeof(ac97->reg_accessed)); bus->codec[ac97->num] = ac97; - spin_lock_init(&ac97->reg_lock); - init_MUTEX(&ac97->mutex); + init_MUTEX(&ac97->reg_mutex); + init_MUTEX(&ac97->page_mutex); if (ac97->pci) { pci_read_config_word(ac97->pci, PCI_SUBSYSTEM_VENDOR_ID, &ac97->subsystem_vendor); @@ -1948,6 +1864,14 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97) goto __access_ok; } + ac97->id = snd_ac97_read(ac97, AC97_VENDOR_ID1) << 16; + ac97->id |= snd_ac97_read(ac97, AC97_VENDOR_ID2); + if (ac97->id && ac97->id != (unsigned int)-1) { + pid = look_for_codec_id(snd_ac97_codec_ids, ac97->id); + if (pid && (pid->flags & AC97_DEFAULT_POWER_OFF)) + goto __access_ok; + } + snd_ac97_write(ac97, AC97_RESET, 0); /* reset to defaults */ if (bus->ops->wait) bus->ops->wait(ac97); @@ -1968,11 +1892,15 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97) __access_ok: ac97->id = snd_ac97_read(ac97, AC97_VENDOR_ID1) << 16; ac97->id |= snd_ac97_read(ac97, AC97_VENDOR_ID2); - if (ac97->id == 0x00000000 || ac97->id == 0xffffffff) { + if (! (ac97->scaps & AC97_SCAP_DETECT_BY_VENDOR) && + (ac97->id == 0x00000000 || ac97->id == 0xffffffff)) { snd_printk(KERN_ERR "AC'97 %d access is not valid [0x%x], removing mixer.\n", ac97->num, ac97->id); snd_ac97_free(ac97); return -EIO; } + pid = look_for_codec_id(snd_ac97_codec_ids, ac97->id); + if (pid) + ac97->flags |= pid->flags; /* test for AC'97 */ if (!(ac97->scaps & AC97_SCAP_SKIP_AUDIO) && !(ac97->scaps & AC97_SCAP_AUDIO)) { @@ -2011,10 +1939,12 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97) if (ac97_is_audio(ac97)) { /* nothing should be in powerdown mode */ snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0); - snd_ac97_write_cache(ac97, AC97_RESET, 0); /* reset to defaults */ - udelay(100); + if (! (ac97->flags & AC97_DEFAULT_POWER_OFF)) { + snd_ac97_write_cache(ac97, AC97_RESET, 0); /* reset to defaults */ + udelay(100); + snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0); + } /* nothing should be in powerdown mode */ - snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0); snd_ac97_write_cache(ac97, AC97_GENERAL_PURPOSE, 0); end_time = jiffies + (HZ / 10); do { @@ -2064,9 +1994,11 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97) ac97->addr = (ac97->ext_id & AC97_EI_ADDR_MASK) >> AC97_EI_ADDR_SHIFT; else ac97->addr = (ac97->ext_mid & AC97_MEI_ADDR_MASK) >> AC97_MEI_ADDR_SHIFT; - if (ac97->ext_id & 0x0189) { /* L/R, MIC, SDAC, LDAC VRA support */ + if (ac97->ext_id & 0x01c9) { /* L/R, MIC, SDAC, LDAC VRA support */ reg = snd_ac97_read(ac97, AC97_EXTENDED_STATUS); - reg |= ac97->ext_id & 0x0189; + reg |= ac97->ext_id & 0x01c0; /* LDAC/SDAC/CDAC */ + if (! bus->no_vra) + reg |= ac97->ext_id & 0x0009; /* VRA/VRM */ snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, reg); } if ((ac97->ext_id & AC97_EI_DRA) && bus->dra) { @@ -2107,7 +2039,11 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97) bus->ops->init(ac97); snd_ac97_get_name(ac97, ac97->id, name, !ac97_is_audio(ac97)); snd_ac97_get_name(NULL, ac97->id, name, !ac97_is_audio(ac97)); // ac97->id might be changed in the special setup code + if (! ac97->build_ops) + ac97->build_ops = &null_build_ops; + if (ac97_is_audio(ac97)) { + char comp[16]; if (card->mixername[0] == '\0') { strcpy(card->mixername, name); } else { @@ -2116,7 +2052,8 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97) strcat(card->mixername, name); } } - if ((err = snd_component_add(card, "AC97a")) < 0) { + sprintf(comp, "AC97a:%08x", ac97->id); + if ((err = snd_component_add(card, comp)) < 0) { snd_ac97_free(ac97); return err; } @@ -2126,6 +2063,7 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97) } } if (ac97_is_modem(ac97)) { + char comp[16]; if (card->mixername[0] == '\0') { strcpy(card->mixername, name); } else { @@ -2134,7 +2072,8 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97) strcat(card->mixername, name); } } - if ((err = snd_component_add(card, "AC97m")) < 0) { + sprintf(comp, "AC97m:%08x", ac97->id); + if ((err = snd_component_add(card, comp)) < 0) { snd_ac97_free(ac97); return err; } @@ -2153,7 +2092,7 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97) snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, reg); } snd_ac97_proc_init(ac97); - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ac97, &ops)) < 0) { + if ((err = snd_device_new(card, SNDRV_DEV_CODEC, ac97, &ops)) < 0) { snd_ac97_free(ac97); return err; } @@ -2210,9 +2149,51 @@ static void snd_ac97_powerdown(ac97_t *ac97) */ void snd_ac97_suspend(ac97_t *ac97) { + if (ac97->build_ops->suspend) + ac97->build_ops->suspend(ac97); snd_ac97_powerdown(ac97); } +/* + * restore ac97 status + */ +void snd_ac97_restore_status(ac97_t *ac97) +{ + int i; + + for (i = 2; i < 0x7c ; i += 2) { + if (i == AC97_POWERDOWN || i == AC97_EXTENDED_ID) + continue; + /* restore only accessible registers + * some chip (e.g. nm256) may hang up when unsupported registers + * are accessed..! + */ + if (test_bit(i, ac97->reg_accessed)) { + snd_ac97_write(ac97, i, ac97->regs[i]); + snd_ac97_read(ac97, i); + } + } +} + +/* + * restore IEC958 status + */ +void snd_ac97_restore_iec958(ac97_t *ac97) +{ + if (ac97->ext_id & AC97_EI_SPDIF) { + if (ac97->regs[AC97_EXTENDED_STATUS] & AC97_EA_SPDIF) { + /* reset spdif status */ + snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); + snd_ac97_write(ac97, AC97_EXTENDED_STATUS, ac97->regs[AC97_EXTENDED_STATUS]); + if (ac97->flags & AC97_CS_SPDIF) + snd_ac97_write(ac97, AC97_CSR_SPDIF, ac97->regs[AC97_CSR_SPDIF]); + else + snd_ac97_write(ac97, AC97_SPDIF, ac97->regs[AC97_SPDIF]); + snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); /* turn on again */ + } + } +} + /** * snd_ac97_resume - General resume function for AC97 codec * @ac97: the ac97 instance @@ -2222,7 +2203,7 @@ void snd_ac97_suspend(ac97_t *ac97) */ void snd_ac97_resume(ac97_t *ac97) { - int i, is_ad18xx, codec; + int i; if (ac97->bus->ops->reset) { ac97->bus->ops->reset(ac97); @@ -2230,9 +2211,11 @@ void snd_ac97_resume(ac97_t *ac97) } snd_ac97_write(ac97, AC97_POWERDOWN, 0); - snd_ac97_write(ac97, AC97_RESET, 0); - udelay(100); - snd_ac97_write(ac97, AC97_POWERDOWN, 0); + if (! (ac97->flags & AC97_DEFAULT_POWER_OFF)) { + snd_ac97_write(ac97, AC97_RESET, 0); + udelay(100); + snd_ac97_write(ac97, AC97_POWERDOWN, 0); + } snd_ac97_write(ac97, AC97_GENERAL_PURPOSE, 0); snd_ac97_write(ac97, AC97_POWERDOWN, ac97->regs[AC97_POWERDOWN]); @@ -2264,72 +2247,18 @@ __reset_ready: if (ac97->bus->ops->init) ac97->bus->ops->init(ac97); - is_ad18xx = (ac97->flags & AC97_AD_MULTI); - if (is_ad18xx) { - /* restore the AD18xx codec configurations */ - for (codec = 0; codec < 3; codec++) { - if (! ac97->spec.ad18xx.id[codec]) - continue; - /* select single codec */ - snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, - ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]); - ac97->bus->ops->write(ac97, AC97_AD_CODEC_CFG, ac97->spec.ad18xx.codec_cfg[codec]); - } - /* select all codecs */ - snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000); - } - - /* restore ac97 status */ - for (i = 2; i < 0x7c ; i += 2) { - if (i == AC97_POWERDOWN || i == AC97_EXTENDED_ID) - continue; - /* restore only accessible registers - * some chip (e.g. nm256) may hang up when unsupported registers - * are accessed..! - */ - if (test_bit(i, ac97->reg_accessed)) { - if (is_ad18xx) { - /* handle multi codecs for AD18xx */ - if (i == AC97_PCM) { - for (codec = 0; codec < 3; codec++) { - if (! ac97->spec.ad18xx.id[codec]) - continue; - /* select single codec */ - snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, - ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]); - /* update PCM bits */ - ac97->bus->ops->write(ac97, AC97_PCM, ac97->spec.ad18xx.pcmreg[codec]); - } - /* select all codecs */ - snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000); - continue; - } else if (i == AC97_AD_TEST || - i == AC97_AD_CODEC_CFG || - i == AC97_AD_SERIAL_CFG) - continue; /* ignore */ - } - snd_ac97_write(ac97, i, ac97->regs[i]); - snd_ac97_read(ac97, i); - } - } - - if (ac97->ext_id & AC97_EI_SPDIF) { - if (ac97->regs[AC97_EXTENDED_STATUS] & AC97_EA_SPDIF) { - /* reset spdif status */ - snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); - snd_ac97_write(ac97, AC97_EXTENDED_STATUS, ac97->regs[AC97_EXTENDED_STATUS]); - if (ac97->flags & AC97_CS_SPDIF) - snd_ac97_write(ac97, AC97_CSR_SPDIF, ac97->regs[AC97_CSR_SPDIF]); - else - snd_ac97_write(ac97, AC97_SPDIF, ac97->regs[AC97_SPDIF]); - snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); /* turn on again */ - } + if (ac97->build_ops->resume) + ac97->build_ops->resume(ac97); + else { + snd_ac97_restore_status(ac97); + snd_ac97_restore_iec958(ac97); } } #endif /* + * Hardware tuning */ static void set_ctl_name(char *dst, const char *src, const char *suffix) { @@ -2339,6 +2268,7 @@ static void set_ctl_name(char *dst, const char *src, const char *suffix) strcpy(dst, src); } +/* remove the control with the given name and optional suffix */ int snd_ac97_remove_ctl(ac97_t *ac97, const char *name, const char *suffix) { snd_ctl_elem_id_t id; @@ -2357,6 +2287,7 @@ static snd_kcontrol_t *ctl_find(ac97_t *ac97, const char *name, const char *suff return snd_ctl_find_id(ac97->bus->card, &sid); } +/* rename the control with the given name and optional suffix */ int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst, const char *suffix) { snd_kcontrol_t *kctl = ctl_find(ac97, src, suffix); @@ -2374,6 +2305,7 @@ void snd_ac97_rename_vol_ctl(ac97_t *ac97, const char *src, const char *dst) snd_ac97_rename_ctl(ac97, src, dst, "Volume"); } +/* swap controls */ int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2, const char *suffix) { snd_kcontrol_t *kctl1, *kctl2; @@ -2387,20 +2319,59 @@ int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2, const char * return -ENOENT; } -static int swap_headphone(ac97_t *ac97, int remove_master) +#if 1 +/* bind hp and master controls instead of using only hp control */ +static int bind_hp_volsw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + int err = snd_ac97_put_volsw(kcontrol, ucontrol); + if (err > 0) { + unsigned long priv_saved = kcontrol->private_value; + kcontrol->private_value = (kcontrol->private_value & ~0xff) | AC97_HEADPHONE; + snd_ac97_put_volsw(kcontrol, ucontrol); + kcontrol->private_value = priv_saved; + } + return err; +} + +/* ac97 tune: bind Master and Headphone controls */ +static int tune_hp_only(ac97_t *ac97) +{ + snd_kcontrol_t *msw = ctl_find(ac97, "Master Playback Switch", NULL); + snd_kcontrol_t *mvol = ctl_find(ac97, "Master Playback Volume", NULL); + if (! msw || ! mvol) + return -ENOENT; + msw->put = bind_hp_volsw_put; + mvol->put = bind_hp_volsw_put; + snd_ac97_remove_ctl(ac97, "Headphone Playback", "Switch"); + snd_ac97_remove_ctl(ac97, "Headphone Playback", "Volume"); + return 0; +} + +#else +/* ac97 tune: use Headphone control as master */ +static int tune_hp_only(ac97_t *ac97) { if (ctl_find(ac97, "Headphone Playback Switch", NULL) == NULL) return -ENOENT; - if (remove_master) { - snd_ac97_remove_ctl(ac97, "Master Playback", "Switch"); - snd_ac97_remove_ctl(ac97, "Master Playback", "Volume"); - } else - snd_ac97_rename_vol_ctl(ac97, "Master Playback", "Line-Out Playback"); + snd_ac97_remove_ctl(ac97, "Master Playback", "Switch"); + snd_ac97_remove_ctl(ac97, "Master Playback", "Volume"); snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback"); return 0; } +#endif -static int swap_surround(ac97_t *ac97) +/* ac97 tune: swap Headphone and Master controls */ +static int tune_swap_hp(ac97_t *ac97) +{ + if (ctl_find(ac97, "Headphone Playback Switch", NULL) == NULL) + return -ENOENT; + snd_ac97_rename_vol_ctl(ac97, "Master Playback", "Line-Out Playback"); + snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback"); + return 0; +} + +/* ac97 tune: swap Surround and Master controls */ +static int tune_swap_surround(ac97_t *ac97) { if (snd_ac97_swap_ctl(ac97, "Master Playback", "Surround Playback", "Switch") || snd_ac97_swap_ctl(ac97, "Master Playback", "Surround Playback", "Volume")) @@ -2408,6 +2379,7 @@ static int swap_surround(ac97_t *ac97) return 0; } +/* ac97 tune: set up mic sharing for AD codecs */ static int tune_ad_sharing(ac97_t *ac97) { unsigned short scfg; @@ -2424,6 +2396,7 @@ static int tune_ad_sharing(ac97_t *ac97) static const snd_kcontrol_new_t snd_ac97_alc_jack_detect = AC97_SINGLE("Jack Detect", AC97_ALC650_CLOCK, 5, 1, 0); +/* ac97 tune: set up ALC jack-select */ static int tune_alc_jack(ac97_t *ac97) { if ((ac97->id & 0xffffff00) != 0x414c4700) { @@ -2435,6 +2408,7 @@ static int tune_alc_jack(ac97_t *ac97) return snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&snd_ac97_alc_jack_detect, ac97)); } +/* ac97 tune: inversed EAPD bit */ static int tune_inv_eapd(ac97_t *ac97) { snd_kcontrol_t *kctl = ctl_find(ac97, "External Amplifier", NULL); @@ -2444,24 +2418,79 @@ static int tune_inv_eapd(ac97_t *ac97) return 0; } -static int apply_quirk(ac97_t *ac97, int quirk) +static int master_mute_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + int err = snd_ac97_put_volsw(kcontrol, ucontrol); + if (err > 0) { + ac97_t *ac97 = snd_kcontrol_chip(kcontrol); + int shift = (kcontrol->private_value >> 8) & 0x0f; + int rshift = (kcontrol->private_value >> 12) & 0x0f; + unsigned short mask; + if (shift != rshift) + mask = 0x8080; + else + mask = 0x8000; + snd_ac97_update_bits(ac97, AC97_POWERDOWN, 0x8000, + (ac97->regs[AC97_MASTER] & mask) == mask ? + 0x8000 : 0); + } + return err; +} + +/* ac97 tune: EAPD controls mute LED bound with the master mute */ +static int tune_mute_led(ac97_t *ac97) +{ + snd_kcontrol_t *msw = ctl_find(ac97, "Master Playback Switch", NULL); + if (! msw) + return -ENOENT; + msw->put = master_mute_sw_put; + snd_ac97_remove_ctl(ac97, "External Amplifier", NULL); + snd_ac97_update_bits(ac97, AC97_POWERDOWN, 0x8000, 0x8000); /* mute LED on */ + return 0; +} + +struct quirk_table { + const char *name; + int (*func)(ac97_t *); +}; + +static struct quirk_table applicable_quirks[] = { + { "none", NULL }, + { "hp_only", tune_hp_only }, + { "swap_hp", tune_swap_hp }, + { "swap_surround", tune_swap_surround }, + { "ad_sharing", tune_ad_sharing }, + { "alc_jack", tune_alc_jack }, + { "inv_eapd", tune_inv_eapd }, + { "mute_led", tune_mute_led }, +}; + +/* apply the quirk with the given type */ +static int apply_quirk(ac97_t *ac97, int type) { - switch (quirk) { - case AC97_TUNE_NONE: + if (type <= 0) return 0; - case AC97_TUNE_HP_ONLY: - return swap_headphone(ac97, 1); - case AC97_TUNE_SWAP_HP: - return swap_headphone(ac97, 0); - case AC97_TUNE_SWAP_SURROUND: - return swap_surround(ac97); - case AC97_TUNE_AD_SHARING: - return tune_ad_sharing(ac97); - case AC97_TUNE_ALC_JACK: - return tune_alc_jack(ac97); - case AC97_TUNE_INV_EAPD: - return tune_inv_eapd(ac97); + else if (type >= ARRAY_SIZE(applicable_quirks)) + return -EINVAL; + if (applicable_quirks[type].func) + return applicable_quirks[type].func(ac97); + return 0; +} + +/* apply the quirk with the given name */ +static int apply_quirk_str(ac97_t *ac97, const char *typestr) +{ + int i; + struct quirk_table *q; + + for (i = 0; i < ARRAY_SIZE(applicable_quirks); i++) { + q = &applicable_quirks[i]; + if (q->name && ! strcmp(typestr, q->name)) + return apply_quirk(ac97, i); } + /* for compatibility, accept the numbers, too */ + if (*typestr >= '0' && *typestr <= '9') + return apply_quirk(ac97, (int)simple_strtoul(typestr, NULL, 10)); return -EINVAL; } @@ -2469,7 +2498,7 @@ static int apply_quirk(ac97_t *ac97, int quirk) * snd_ac97_tune_hardware - tune up the hardware * @ac97: the ac97 instance * @quirk: quirk list - * @override: explicit quirk value (overrides the list if not AC97_TUNE_DEFAULT) + * @override: explicit quirk value (overrides the list if non-NULL) * * Do some workaround for each pci device, such as renaming of the * headphone (true line-out) control as "Master". @@ -2478,16 +2507,17 @@ static int apply_quirk(ac97_t *ac97, int quirk) * Returns zero if successful, or a negative error code on failure. */ -int snd_ac97_tune_hardware(ac97_t *ac97, struct ac97_quirk *quirk, int override) +int snd_ac97_tune_hardware(ac97_t *ac97, struct ac97_quirk *quirk, const char *override) { int result; snd_assert(quirk, return -EINVAL); - if (override != AC97_TUNE_DEFAULT) { - result = apply_quirk(ac97, override); + /* quirk overriden? */ + if (override && strcmp(override, "-1") && strcmp(override, "default")) { + result = apply_quirk_str(ac97, override); if (result < 0) - snd_printk(KERN_ERR "applying quirk type %d failed (%d)\n", override, result); + snd_printk(KERN_ERR "applying quirk type %s failed (%d)\n", override, result); return result; } diff --git a/sound/pci/ac97/ac97_local.h b/sound/pci/ac97/ac97_local.h index 21b58d759..536a4d479 100644 --- a/sound/pci/ac97/ac97_local.h +++ b/sound/pci/ac97/ac97_local.h @@ -22,16 +22,29 @@ * */ -#define AC97_SINGLE_VALUE(reg,shift,mask,invert) ((reg) | ((shift) << 8) | ((mask) << 16) | ((invert) << 24)) -#define AC97_PAGE_SINGLE_VALUE(reg,shift,mask,invert,page) ((reg) | ((shift) << 8) | ((mask) << 16) | ((invert) << 24) | ((page) << 25)) +#define AC97_SINGLE_VALUE(reg,shift,mask,invert) ((reg) | ((shift) << 8) | ((shift) << 12) | ((mask) << 16) | ((invert) << 24)) +#define AC97_PAGE_SINGLE_VALUE(reg,shift,mask,invert,page) (AC97_SINGLE_VALUE(reg,shift,mask,invert) | (1<<25) | ((page) << 26)) #define AC97_SINGLE(xname, reg, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_single, \ - .get = snd_ac97_get_single, .put = snd_ac97_put_single, \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_volsw, \ + .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \ .private_value = AC97_SINGLE_VALUE(reg, shift, mask, invert) } #define AC97_PAGE_SINGLE(xname, reg, shift, mask, invert, page) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_single, \ - .get = snd_ac97_page_get_single, .put = snd_ac97_page_put_single, \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_volsw, \ + .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \ .private_value = AC97_PAGE_SINGLE_VALUE(reg, shift, mask, invert, page) } +#define AC97_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .info = snd_ac97_info_volsw, \ + .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \ + .private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) | ((mask) << 16) | ((invert) << 24) } +#define AC97_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts) \ +{ .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ + .mask = xmask, .texts = xtexts } +#define AC97_ENUM_SINGLE(xreg, xshift, xmask, xtexts) \ + AC97_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xtexts) +#define AC97_ENUM(xname, xenum) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_enum_double, \ + .get = snd_ac97_get_enum_double, .put = snd_ac97_put_enum_double, \ + .private_value = (unsigned long)&xenum } /* ac97_codec.c */ extern const char *snd_ac97_stereo_enhancements[]; @@ -39,16 +52,22 @@ extern const snd_kcontrol_new_t snd_ac97_controls_3d[]; extern const snd_kcontrol_new_t snd_ac97_controls_spdif[]; snd_kcontrol_t *snd_ac97_cnew(const snd_kcontrol_new_t *_template, ac97_t * ac97); void snd_ac97_get_name(ac97_t *ac97, unsigned int id, char *name, int modem); -int snd_ac97_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo); -int snd_ac97_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol); -int snd_ac97_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol); -int snd_ac97_page_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol); -int snd_ac97_page_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol); +int snd_ac97_info_volsw(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo); +int snd_ac97_get_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol); +int snd_ac97_put_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol); int snd_ac97_try_bit(ac97_t * ac97, int reg, int bit); int snd_ac97_remove_ctl(ac97_t *ac97, const char *name, const char *suffix); int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst, const char *suffix); int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2, const char *suffix); void snd_ac97_rename_vol_ctl(ac97_t *ac97, const char *src, const char *dst); +void snd_ac97_restore_status(ac97_t *ac97); +void snd_ac97_restore_iec958(ac97_t *ac97); +int snd_ac97_info_enum_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo); +int snd_ac97_get_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol); +int snd_ac97_put_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol); + +int snd_ac97_update_bits_nolock(ac97_t *ac97, unsigned short reg, + unsigned short mask, unsigned short value); /* ac97_proc.c */ #ifdef CONFIG_PROC_FS diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 3b0b8d683..13c34a5d8 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -55,12 +55,12 @@ static int ac97_update_bits_page(ac97_t *ac97, unsigned short reg, unsigned shor unsigned short page_save; int ret; - down(&ac97->mutex); + down(&ac97->page_mutex); page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK; snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page); ret = snd_ac97_update_bits(ac97, reg, mask, value); snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save); - up(&ac97->mutex); /* unlock paging */ + up(&ac97->page_mutex); /* unlock paging */ return ret; } @@ -305,6 +305,136 @@ int patch_wolfson11(ac97_t * ac97) return 0; } +static const char* wm9713_mic_mixer[] = {"Stereo", "Mic1", "Mic2", "Mute"}; +static const char* wm9713_rec_mux[] = {"Stereo", "Left", "Right", "Mute"}; +static const char* wm9713_rec_src_l[] = {"Mic1", "Mic2", "Line L", "Mono In", "HP Mix L", "Spk Mix", "Mono Mix", "Zh"}; +static const char* wm9713_rec_src_r[] = {"Mic1", "Mic2", "Line R", "Mono In", "HP Mix R", "Spk Mix", "Mono Mix", "Zh"}; + +static const struct ac97_enum wm9713_enum[] = { +AC97_ENUM_SINGLE(AC97_LINE, 3, 4, wm9713_mic_mixer), +AC97_ENUM_SINGLE(AC97_VIDEO, 14, 4, wm9713_rec_mux), +AC97_ENUM_SINGLE(AC97_VIDEO, 9, 4, wm9713_rec_mux), +AC97_ENUM_SINGLE(AC97_VIDEO, 3, 8, wm9713_rec_src_l), +AC97_ENUM_SINGLE(AC97_VIDEO, 0, 8, wm9713_rec_src_r), +}; + +static const snd_kcontrol_new_t wm13_snd_ac97_controls_line_in[] = { +AC97_DOUBLE("Line In Volume", AC97_PC_BEEP, 8, 0, 31, 1), +AC97_SINGLE("Line In to Headphone Mute", AC97_PC_BEEP, 15, 1, 1), +AC97_SINGLE("Line In to Speaker Mute", AC97_PC_BEEP, 14, 1, 1), +AC97_SINGLE("Line In to Mono Mute", AC97_PC_BEEP, 13, 1, 1), +}; + +static const snd_kcontrol_new_t wm13_snd_ac97_controls_dac[] = { +AC97_DOUBLE("DAC Volume", AC97_PHONE, 8, 0, 31, 1), +AC97_SINGLE("DAC to Headphone Mute", AC97_PHONE, 15, 1, 1), +AC97_SINGLE("DAC to Speaker Mute", AC97_PHONE, 14, 1, 1), +AC97_SINGLE("DAC to Mono Mute", AC97_PHONE, 13, 1, 1), +}; + +static const snd_kcontrol_new_t wm13_snd_ac97_controls_mic[] = { +AC97_SINGLE("MICA Volume", AC97_MIC, 8, 31, 1), +AC97_SINGLE("MICB Volume", AC97_MIC, 0, 31, 1), +AC97_SINGLE("MICA to Mono Mute", AC97_LINE, 7, 1, 1), +AC97_SINGLE("MICB to Mono Mute", AC97_LINE, 6, 1, 1), +AC97_SINGLE("MIC Boost (+20dB)", AC97_LINE, 5, 1, 1), +AC97_ENUM("MIC Headphone Routing", wm9713_enum[0]), +AC97_SINGLE("MIC Headphone Mixer Volume", AC97_LINE, 0, 7, 1) +}; + +static const snd_kcontrol_new_t wm13_snd_ac97_controls_adc[] = { +AC97_SINGLE("ADC Mute", AC97_CD, 15, 1, 1), +AC97_DOUBLE("Gain Step Size (1.5dB/0.75dB)", AC97_CD, 14, 6, 1, 1), +AC97_DOUBLE("ADC Volume",AC97_CD, 8, 0, 15, 0), +AC97_SINGLE("ADC Zero Cross", AC97_CD, 7, 1, 1), +}; + +static const snd_kcontrol_new_t wm13_snd_ac97_controls_recsel[] = { +AC97_ENUM("Record to Headphone Path", wm9713_enum[1]), +AC97_SINGLE("Record to Headphone Volume", AC97_VIDEO, 11, 7, 0), +AC97_ENUM("Record to Mono Path", wm9713_enum[2]), +AC97_SINGLE("Record to Mono Boost (+20dB)", AC97_VIDEO, 8, 1, 0), +AC97_SINGLE("Record ADC Boost (+20dB)", AC97_VIDEO, 6, 1, 0), +AC97_ENUM("Record Select Left", wm9713_enum[3]), +AC97_ENUM("Record Select Right", wm9713_enum[4]), +}; + +static int patch_wolfson_wm9713_specific(ac97_t * ac97) +{ + int err, i; + + for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_line_in); i++) { + if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_line_in[i], ac97))) < 0) + return err; + } + snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x0808); + + for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_dac); i++) { + if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_dac[i], ac97))) < 0) + return err; + } + snd_ac97_write_cache(ac97, AC97_PHONE, 0x0808); + + for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_mic); i++) { + if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_mic[i], ac97))) < 0) + return err; + } + snd_ac97_write_cache(ac97, AC97_MIC, 0x0808); + snd_ac97_write_cache(ac97, AC97_LINE, 0x00da); + + for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_adc); i++) { + if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_adc[i], ac97))) < 0) + return err; + } + snd_ac97_write_cache(ac97, AC97_CD, 0x0808); + + for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_recsel); i++) { + if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_recsel[i], ac97))) < 0) + return err; + } + snd_ac97_write_cache(ac97, AC97_VIDEO, 0xd612); + snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x1ba0); + + return 0; +} + +#ifdef CONFIG_PM +static void patch_wolfson_wm9713_suspend (ac97_t * ac97) +{ + snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xfeff); + snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xffff); +} + +static void patch_wolfson_wm9713_resume (ac97_t * ac97) +{ + snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xda00); + snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0x3810); + snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0x0); +} +#endif + +static struct snd_ac97_build_ops patch_wolfson_wm9713_ops = { + .build_specific = patch_wolfson_wm9713_specific, +#ifdef CONFIG_PM + .suspend = patch_wolfson_wm9713_suspend, + .resume = patch_wolfson_wm9713_resume +#endif +}; + +int patch_wolfson13(ac97_t * ac97) +{ + ac97->build_ops = &patch_wolfson_wm9713_ops; + + ac97->flags |= AC97_HAS_NO_REC_GAIN | AC97_STEREO_MUTES | AC97_HAS_NO_PHONE | + AC97_HAS_NO_PC_BEEP | AC97_HAS_NO_VIDEO | AC97_HAS_NO_CD; + + snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xda00); + snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0x3810); + snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0x0); + + return 0; +} + /* * Tritech codec */ @@ -392,9 +522,36 @@ int patch_sigmatel_stac9700(ac97_t * ac97) return 0; } +static int snd_ac97_stac9708_put_bias(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + ac97_t *ac97 = snd_kcontrol_chip(kcontrol); + int err; + + down(&ac97->page_mutex); + snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0xabba); + err = snd_ac97_update_bits(ac97, AC97_SIGMATEL_BIAS2, 0x0010, + (ucontrol->value.integer.value[0] & 1) << 4); + snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0); + up(&ac97->page_mutex); + return err; +} + +static const snd_kcontrol_new_t snd_ac97_stac9708_bias_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Sigmatel Output Bias Switch", + .info = snd_ac97_info_volsw, + .get = snd_ac97_get_volsw, + .put = snd_ac97_stac9708_put_bias, + .private_value = AC97_SINGLE_VALUE(AC97_SIGMATEL_BIAS2, 4, 1, 0), +}; + static int patch_sigmatel_stac9708_specific(ac97_t *ac97) { + int err; + snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Sigmatel Surround Playback"); + if ((err = patch_build_controls(ac97, &snd_ac97_stac9708_bias_control, 1)) < 0) + return err; return patch_sigmatel_stac97xx_specific(ac97); } @@ -775,6 +932,71 @@ int patch_conexant(ac97_t * ac97) /* * Analog Device AD18xx, AD19xx codecs */ +#ifdef CONFIG_PM +static void ad18xx_resume(ac97_t *ac97) +{ + static unsigned short setup_regs[] = { + AC97_AD_MISC, AC97_AD_SERIAL_CFG, AC97_AD_JACK_SPDIF, + }; + int i, codec; + + for (i = 0; i < (int)ARRAY_SIZE(setup_regs); i++) { + unsigned short reg = setup_regs[i]; + if (test_bit(reg, ac97->reg_accessed)) { + snd_ac97_write(ac97, reg, ac97->regs[reg]); + snd_ac97_read(ac97, reg); + } + } + + if (! (ac97->flags & AC97_AD_MULTI)) + /* normal restore */ + snd_ac97_restore_status(ac97); + else { + /* restore the AD18xx codec configurations */ + for (codec = 0; codec < 3; codec++) { + if (! ac97->spec.ad18xx.id[codec]) + continue; + /* select single codec */ + snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, + ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]); + ac97->bus->ops->write(ac97, AC97_AD_CODEC_CFG, ac97->spec.ad18xx.codec_cfg[codec]); + } + /* select all codecs */ + snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000); + + /* restore status */ + for (i = 2; i < 0x7c ; i += 2) { + if (i == AC97_POWERDOWN || i == AC97_EXTENDED_ID) + continue; + if (test_bit(i, ac97->reg_accessed)) { + /* handle multi codecs for AD18xx */ + if (i == AC97_PCM) { + for (codec = 0; codec < 3; codec++) { + if (! ac97->spec.ad18xx.id[codec]) + continue; + /* select single codec */ + snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, + ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]); + /* update PCM bits */ + ac97->bus->ops->write(ac97, AC97_PCM, ac97->spec.ad18xx.pcmreg[codec]); + } + /* select all codecs */ + snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000); + continue; + } else if (i == AC97_AD_TEST || + i == AC97_AD_CODEC_CFG || + i == AC97_AD_SERIAL_CFG) + continue; /* ignore */ + } + snd_ac97_write(ac97, i, ac97->regs[i]); + snd_ac97_read(ac97, i); + } + } + + snd_ac97_restore_iec958(ac97); +} +#endif + int patch_ad1819(ac97_t * ac97) { unsigned short scfg; @@ -843,6 +1065,12 @@ static void patch_ad1881_chained(ac97_t * ac97, int unchained_idx, int cidx1, in } } +static struct snd_ac97_build_ops patch_ad1881_build_ops = { +#ifdef CONFIG_PM + .resume = ad18xx_resume +#endif +}; + int patch_ad1881(ac97_t * ac97) { static const char cfg_idxs[3][2] = { @@ -897,6 +1125,7 @@ int patch_ad1881(ac97_t * ac97) ac97->id &= 0xffff0000; ac97->id |= ac97->spec.ad18xx.id[0]; } + ac97->build_ops = &patch_ad1881_build_ops; return 0; } @@ -919,7 +1148,10 @@ static int patch_ad1885_specific(ac97_t * ac97) } static struct snd_ac97_build_ops patch_ad1885_build_ops = { - .build_specific = &patch_ad1885_specific + .build_specific = &patch_ad1885_specific, +#ifdef CONFIG_PM + .resume = ad18xx_resume +#endif }; int patch_ad1885(ac97_t * ac97) @@ -1026,16 +1258,32 @@ static int patch_ad1981a_specific(ac97_t * ac97) static struct snd_ac97_build_ops patch_ad1981a_build_ops = { .build_post_spdif = patch_ad198x_post_spdif, - .build_specific = patch_ad1981a_specific + .build_specific = patch_ad1981a_specific, +#ifdef CONFIG_PM + .resume = ad18xx_resume +#endif }; +static void check_ad1981_hp_jack_sense(ac97_t *ac97) +{ + u32 subid = ((u32)ac97->subsystem_vendor << 16) | ac97->subsystem_device; + switch (subid) { + case 0x103c0890: /* HP nc6000 */ + case 0x103c006d: /* HP nx9105 */ + case 0x17340088: /* FSC Scenic-W */ + /* enable headphone jack sense */ + snd_ac97_update_bits(ac97, AC97_AD_JACK_SPDIF, 1<<11, 1<<11); + break; + } +} + int patch_ad1981a(ac97_t *ac97) { patch_ad1881(ac97); ac97->build_ops = &patch_ad1981a_build_ops; snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD198X_MSPLT, AC97_AD198X_MSPLT); ac97->flags |= AC97_STEREO_MUTES; - snd_ac97_update_bits(ac97, AC97_AD_JACK_SPDIF, 1<<11, 1<<11); /* HP jack sense */ + check_ad1981_hp_jack_sense(ac97); return 0; } @@ -1054,7 +1302,10 @@ static int patch_ad1981b_specific(ac97_t *ac97) static struct snd_ac97_build_ops patch_ad1981b_build_ops = { .build_post_spdif = patch_ad198x_post_spdif, - .build_specific = patch_ad1981b_specific + .build_specific = patch_ad1981b_specific, +#ifdef CONFIG_PM + .resume = ad18xx_resume +#endif }; int patch_ad1981b(ac97_t *ac97) @@ -1063,7 +1314,7 @@ int patch_ad1981b(ac97_t *ac97) ac97->build_ops = &patch_ad1981b_build_ops; snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD198X_MSPLT, AC97_AD198X_MSPLT); ac97->flags |= AC97_STEREO_MUTES; - snd_ac97_update_bits(ac97, AC97_AD_JACK_SPDIF, 1<<11, 1<<11); /* HP jack sense */ + check_ad1981_hp_jack_sense(ac97); return 0; } @@ -1169,7 +1420,10 @@ static int patch_ad1888_specific(ac97_t *ac97) static struct snd_ac97_build_ops patch_ad1888_build_ops = { .build_post_spdif = patch_ad198x_post_spdif, - .build_specific = patch_ad1888_specific + .build_specific = patch_ad1888_specific, +#ifdef CONFIG_PM + .resume = ad18xx_resume +#endif }; int patch_ad1888(ac97_t * ac97) @@ -1203,7 +1457,10 @@ static int patch_ad1980_specific(ac97_t *ac97) static struct snd_ac97_build_ops patch_ad1980_build_ops = { .build_post_spdif = patch_ad198x_post_spdif, - .build_specific = patch_ad1980_specific + .build_specific = patch_ad1980_specific, +#ifdef CONFIG_PM + .resume = ad18xx_resume +#endif }; int patch_ad1980(ac97_t * ac97) @@ -1229,7 +1486,10 @@ static int patch_ad1985_specific(ac97_t *ac97) static struct snd_ac97_build_ops patch_ad1985_build_ops = { .build_post_spdif = patch_ad198x_post_spdif, - .build_specific = patch_ad1985_specific + .build_specific = patch_ad1985_specific, +#ifdef CONFIG_PM + .resume = ad18xx_resume +#endif }; int patch_ad1985(ac97_t * ac97) @@ -1313,7 +1573,7 @@ static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Mic As Center/LFE", - .info = snd_ac97_info_single, + .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 */ @@ -1323,7 +1583,8 @@ static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = { static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc650[] = { AC97_SINGLE("IEC958 Capture Switch", AC97_ALC650_MULTICH, 11, 1, 0), AC97_SINGLE("Analog to IEC958 Output", AC97_ALC650_MULTICH, 12, 1, 0), - AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0), + /* disable this controls since it doesn't work as expected */ + /* AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0), */ }; static int patch_alc650_specific(ac97_t * ac97) @@ -1424,7 +1685,7 @@ static const snd_kcontrol_new_t snd_ac97_controls_alc655[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Mic As Center/LFE", - .info = snd_ac97_info_single, + .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 */ @@ -1467,13 +1728,14 @@ static int alc655_iec958_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_ ac97_t *ac97 = snd_kcontrol_chip(kcontrol); return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 3 << 12, - (unsigned short)ucontrol->value.enumerated.item[0], + (unsigned short)ucontrol->value.enumerated.item[0] << 12, 0); } static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc655[] = { AC97_PAGE_SINGLE("IEC958 Capture Switch", AC97_ALC650_MULTICH, 11, 1, 0, 0), - AC97_PAGE_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 14, 1, 0, 0), + /* disable this controls since it doesn't work as expected */ + /* AC97_PAGE_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 14, 1, 0, 0), */ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "IEC958 Playback Route", @@ -1513,7 +1775,10 @@ int patch_alc655(ac97_t * ac97) /* adjust default values */ val = snd_ac97_read(ac97, 0x7a); /* misc control */ - val |= (1 << 1); /* spdif input pin */ + if (ac97->id == 0x414c4780) /* ALC658 */ + val &= ~(1 << 1); /* Pin 47 is spdif input pin */ + else /* ALC655 */ + val |= (1 << 1); /* Pin 47 is spdif input pin */ val &= ~(1 << 12); /* vref enable */ snd_ac97_write_cache(ac97, 0x7a, val); /* set default: spdif-in enabled, @@ -1576,7 +1841,7 @@ static const snd_kcontrol_new_t snd_ac97_controls_alc850[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Line-In As Surround", - .info = snd_ac97_info_single, + .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 */ @@ -1584,7 +1849,7 @@ static const snd_kcontrol_new_t snd_ac97_controls_alc850[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Mic As Center/LFE", - .info = snd_ac97_info_single, + .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 */ @@ -1663,6 +1928,11 @@ static struct snd_ac97_build_ops patch_cm9738_ops = { int patch_cm9738(ac97_t * ac97) { ac97->build_ops = &patch_cm9738_ops; + /* FIXME: can anyone confirm below? */ + /* CM9738 has no PCM volume although the register reacts */ + ac97->flags |= AC97_HAS_NO_PCM_VOL; + snd_ac97_write_cache(ac97, AC97_PCM, 0x8000); + return 0; } @@ -1739,7 +2009,7 @@ static const snd_kcontrol_new_t snd_ac97_cm9739_controls[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Mic As Center/LFE", - .info = snd_ac97_info_single, + .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 */ @@ -1767,6 +2037,11 @@ int patch_cm9739(ac97_t * ac97) ac97->build_ops = &patch_cm9739_ops; + /* CM9739/A has no Master and PCM volume although the register reacts */ + ac97->flags |= AC97_HAS_NO_MASTER_VOL | AC97_HAS_NO_PCM_VOL; + snd_ac97_write_cache(ac97, AC97_MASTER, 0x8000); + snd_ac97_write_cache(ac97, AC97_PCM, 0x8000); + /* check spdif */ val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS); if (val & AC97_EA_SPCV) { @@ -1785,8 +2060,12 @@ int patch_cm9739(ac97_t * ac97) /* bit 12: disable center/lfe (swithable) */ /* bit 10: disable surround/line (switchable) */ /* bit 9: mix 2 surround off */ + /* bit 4: undocumented; 0 mutes the CM9739A, which defaults to 1 */ + /* bit 3: undocumented; surround? */ /* bit 0: dB */ - val = (1 << 13); + val = snd_ac97_read(ac97, AC97_CM9739_MULTI_CHAN) & (1 << 4); + val |= (1 << 3); + val |= (1 << 13); if (! (ac97->ext_id & AC97_EI_SPDIF)) val |= (1 << 14); snd_ac97_write_cache(ac97, AC97_CM9739_MULTI_CHAN, val); @@ -1794,6 +2073,15 @@ int patch_cm9739(ac97_t * ac97) /* FIXME: set up GPIO */ snd_ac97_write_cache(ac97, 0x70, 0x0100); snd_ac97_write_cache(ac97, 0x72, 0x0020); + /* Special exception for ASUS W1000/CMI9739. It does not have an SPDIF in. */ + if (ac97->pci && + ac97->subsystem_vendor == 0x1043 && + ac97->subsystem_device == 0x1843) { + snd_ac97_write_cache(ac97, AC97_CM9739_SPDIF_CTRL, + snd_ac97_read(ac97, AC97_CM9739_SPDIF_CTRL) & ~0x01); + snd_ac97_write_cache(ac97, AC97_CM9739_MULTI_CHAN, + snd_ac97_read(ac97, AC97_CM9739_MULTI_CHAN) | (1 << 14)); + } return 0; } @@ -1849,7 +2137,7 @@ 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_single, + .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 */ @@ -1857,7 +2145,7 @@ static const snd_kcontrol_new_t snd_ac97_cm9761_controls[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Mic As Center/LFE", - .info = snd_ac97_info_single, + .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 */ @@ -1878,6 +2166,14 @@ int patch_cm9761(ac97_t *ac97) { unsigned short val; + /* CM9761 has no PCM volume although the register reacts */ + /* Master volume seems to have _some_ influence on the analog + * input sounds + */ + ac97->flags |= /*AC97_HAS_NO_MASTER_VOL |*/ AC97_HAS_NO_PCM_VOL; + snd_ac97_write_cache(ac97, AC97_MASTER, 0x8808); + snd_ac97_write_cache(ac97, AC97_PCM, 0x8808); + ac97->spec.dev_flags = 0; /* 1 = model 82 revision B */ if (ac97->id == AC97_ID_CM9761_82) { unsigned short tmp; @@ -1896,7 +2192,8 @@ int patch_cm9761(ac97_t *ac97) ac97->ext_id |= AC97_EI_SPDIF; /* to be sure: we overwrite the ext status bits */ snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, 0x05c0); - snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0209); + /* Don't set 0x0200 here. This results in the silent analog output */ + snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0009); ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */ /* set-up multi channel */ @@ -1921,8 +2218,10 @@ int patch_cm9761(ac97_t *ac97) val = 0x0214; else val = 0x321c; - snd_ac97_write_cache(ac97, AC97_CM9761_MULTI_CHAN, val); #endif + val = snd_ac97_read(ac97, AC97_CM9761_MULTI_CHAN); + val |= (1 << 4); /* front on */ + snd_ac97_write_cache(ac97, AC97_CM9761_MULTI_CHAN, val); /* FIXME: set up GPIO */ snd_ac97_write_cache(ac97, 0x70, 0x0100); diff --git a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c index 466977e3f..dd289b951 100644 --- a/sound/pci/ac97/ac97_pcm.c +++ b/sound/pci/ac97/ac97_pcm.c @@ -206,14 +206,12 @@ static int set_spdif_rate(ac97_t *ac97, unsigned short rate) mask = AC97_SC_SPSR_MASK; } - spin_lock(&ac97->reg_lock); + down(&ac97->reg_mutex); old = snd_ac97_read(ac97, reg) & mask; - spin_unlock(&ac97->reg_lock); if (old != bits) { - snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); - snd_ac97_update_bits(ac97, reg, mask, bits); + snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); + snd_ac97_update_bits_nolock(ac97, reg, mask, bits); /* update the internal spdif bits */ - spin_lock(&ac97->reg_lock); sbits = ac97->spdif_status; if (sbits & IEC958_AES0_PROFESSIONAL) { sbits &= ~IEC958_AES0_PRO_FS; @@ -231,9 +229,9 @@ static int set_spdif_rate(ac97_t *ac97, unsigned short rate) } } ac97->spdif_status = sbits; - spin_unlock(&ac97->reg_lock); } - snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); + snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); + up(&ac97->reg_mutex); return 0; } @@ -555,7 +553,7 @@ int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate, { ac97_bus_t *bus; int i, cidx, r, ok_flag; - unsigned int reg_ok = 0; + unsigned int reg_ok[4] = {0,0,0,0}; unsigned char reg; int err = 0; @@ -604,14 +602,14 @@ int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate, snd_printk(KERN_ERR "invalid AC97 slot %i?\n", i); continue; } - if (reg_ok & (1 << (reg - AC97_PCM_FRONT_DAC_RATE))) + if (reg_ok[cidx] & (1 << (reg - AC97_PCM_FRONT_DAC_RATE))) continue; //printk(KERN_DEBUG "setting ac97 reg 0x%x to rate %d\n", reg, rate); err = snd_ac97_set_rate(pcm->r[r].codec[cidx], reg, rate); if (err < 0) snd_printk(KERN_ERR "error in snd_ac97_set_rate: cidx=%d, reg=0x%x, rate=%d, err=%d\n", cidx, reg, rate, err); else - reg_ok |= (1 << (reg - AC97_PCM_FRONT_DAC_RATE)); + reg_ok[cidx] |= (1 << (reg - AC97_PCM_FRONT_DAC_RATE)); } } } diff --git a/sound/pci/ac97/ac97_proc.c b/sound/pci/ac97/ac97_proc.c index 377e38ad1..a040b2666 100644 --- a/sound/pci/ac97/ac97_proc.c +++ b/sound/pci/ac97/ac97_proc.c @@ -296,7 +296,7 @@ static void snd_ac97_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buff { ac97_t *ac97 = entry->private_data; - down(&ac97->mutex); + down(&ac97->page_mutex); if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86 int idx; for (idx = 0; idx < 3; idx++) @@ -322,7 +322,7 @@ static void snd_ac97_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buff } else { snd_ac97_proc_read_main(ac97, buffer, 0); } - up(&ac97->mutex); + up(&ac97->page_mutex); } #ifdef CONFIG_SND_DEBUG @@ -332,7 +332,7 @@ static void snd_ac97_proc_regs_write(snd_info_entry_t *entry, snd_info_buffer_t ac97_t *ac97 = entry->private_data; char line[64]; unsigned int reg, val; - down(&ac97->mutex); + down(&ac97->page_mutex); while (!snd_info_get_line(buffer, line, sizeof(line))) { if (sscanf(line, "%x %x", ®, &val) != 2) continue; @@ -340,7 +340,7 @@ static void snd_ac97_proc_regs_write(snd_info_entry_t *entry, snd_info_buffer_t if (reg < 0x80 && (reg & 1) == 0 && val <= 0xffff) snd_ac97_write_cache(ac97, reg, val); } - up(&ac97->mutex); + up(&ac97->page_mutex); } #endif @@ -359,7 +359,7 @@ static void snd_ac97_proc_regs_read(snd_info_entry_t *entry, { ac97_t *ac97 = entry->private_data; - down(&ac97->mutex); + down(&ac97->page_mutex); if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86 int idx; @@ -375,7 +375,7 @@ static void snd_ac97_proc_regs_read(snd_info_entry_t *entry, } else { snd_ac97_proc_regs_read_main(ac97, buffer, 0); } - up(&ac97->mutex); + up(&ac97->page_mutex); } void snd_ac97_proc_init(ac97_t * ac97) diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index f186ac709..984d5d4ba 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -188,7 +188,7 @@ typedef struct snd_ali_channel_control { struct snd_ali_stru_voice { unsigned int number; - int use: 1, + unsigned int use: 1, pcm: 1, midi: 1, mode: 1, @@ -199,7 +199,7 @@ struct snd_ali_stru_voice { snd_pcm_substream_t *substream; snd_ali_voice_t *extra; - int running: 1; + unsigned int running: 1; int eso; /* final ESO value for channel */ int count; /* runtime->period_size */ @@ -1894,7 +1894,7 @@ static int __devinit snd_ali_mixer(ali_t * codec) } #ifdef CONFIG_PM -static int ali_suspend(snd_card_t *card, unsigned int state) +static int ali_suspend(snd_card_t *card, pm_message_t state) { ali_t *chip = card->pm_private_data; ali_image_t *im; @@ -1933,11 +1933,10 @@ static int ali_suspend(snd_card_t *card, unsigned int state) spin_unlock_irq(&chip->reg_lock); pci_disable_device(chip->pci); - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } -static int ali_resume(snd_card_t *card, unsigned int state) +static int ali_resume(snd_card_t *card) { ali_t *chip = card->pm_private_data; ali_image_t *im; @@ -1971,7 +1970,6 @@ static int ali_resume(snd_card_t *card, unsigned int state) spin_unlock_irq(&chip->reg_lock); snd_ac97_resume(chip->ac97); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; } @@ -1989,8 +1987,7 @@ static int snd_ali_free(ali_t * codec) pci_release_regions(codec->pci); pci_disable_device(codec->pci); #ifdef CONFIG_PM - if (codec->image) - kfree(codec->image); + kfree(codec->image); #endif kfree(codec); return 0; diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index 7be0f0d6d..f1a5f5723 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c @@ -104,8 +104,7 @@ typedef struct { struct pci_dev *pci; unsigned long gcr; #ifdef SUPPORT_JOYSTICK - struct gameport gameport; - struct resource *res_joystick; + struct gameport *gameport; #endif } snd_card_als4000_t; @@ -566,21 +565,80 @@ static void __devinit snd_als4000_configure(sb_t *chip) spin_unlock_irq(&chip->reg_lock); } +#ifdef SUPPORT_JOYSTICK +static int __devinit snd_als4000_create_gameport(snd_card_als4000_t *acard, int dev) +{ + struct gameport *gp; + struct resource *r; + int io_port; + + if (joystick_port[dev] == 0) + return -ENODEV; + + if (joystick_port[dev] == 1) { /* auto-detect */ + for (io_port = 0x200; io_port <= 0x218; io_port += 8) { + r = request_region(io_port, 8, "ALS4000 gameport"); + if (r) + break; + } + } else { + io_port = joystick_port[dev]; + r = request_region(io_port, 8, "ALS4000 gameport"); + } + + if (!r) { + printk(KERN_WARNING "als4000: cannot reserve joystick ports\n"); + return -EBUSY; + } + + acard->gameport = gp = gameport_allocate_port(); + if (!gp) { + printk(KERN_ERR "als4000: cannot allocate memory for gameport\n"); + release_resource(r); + kfree_nocheck(r); + return -ENOMEM; + } + + gameport_set_name(gp, "ALS4000 Gameport"); + gameport_set_phys(gp, "pci%s/gameport0", pci_name(acard->pci)); + gameport_set_dev_parent(gp, &acard->pci->dev); + gp->io = io_port; + gameport_set_port_data(gp, r); + + /* Enable legacy joystick port */ + snd_als4000_set_addr(acard->gcr, 0, 0, 0, 1); + + gameport_register_port(acard->gameport); + + return 0; +} + +static void snd_als4000_free_gameport(snd_card_als4000_t *acard) +{ + if (acard->gameport) { + struct resource *r = gameport_get_port_data(acard->gameport); + + gameport_unregister_port(acard->gameport); + acard->gameport = NULL; + + snd_als4000_set_addr(acard->gcr, 0, 0, 0, 0); /* disable joystick */ + release_resource(r); + kfree_nocheck(r); + } +} +#else +static inline int snd_als4000_create_gameport(snd_card_als4000_t *acard, int dev) { return -ENOSYS; } +static inline void snd_als4000_free_gameport(snd_card_als4000_t *acard) { } +#endif + static void snd_card_als4000_free( snd_card_t *card ) { snd_card_als4000_t * acard = (snd_card_als4000_t *)card->private_data; + /* make sure that interrupts are disabled */ snd_als4000_gcr_write_addr( acard->gcr, 0x8c, 0); /* free resources */ -#ifdef SUPPORT_JOYSTICK - if (acard->res_joystick) { - if (acard->gameport.io) - gameport_unregister_port(&acard->gameport); - snd_als4000_set_addr(acard->gcr, 0, 0, 0, 0); /* disable joystick */ - release_resource(acard->res_joystick); - kfree_nocheck(acard->res_joystick); - } -#endif + snd_als4000_free_gameport(acard); pci_release_regions(acard->pci); pci_disable_device(acard->pci); } @@ -596,7 +654,6 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci, opl3_t *opl3; unsigned short word; int err; - int joystick = 0; if (dev >= SNDRV_CARDS) return -ENODEV; @@ -640,26 +697,9 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci, acard->gcr = gcr; card->private_free = snd_card_als4000_free; - /* disable all legacy ISA stuff except for joystick */ -#ifdef SUPPORT_JOYSTICK - if (joystick_port[dev] == 1) { - /* auto-detect */ - long p; - for (p = 0x200; p <= 0x218; p += 8) { - if ((acard->res_joystick = request_region(p, 8, "ALS4000 gameport")) != NULL) { - joystick_port[dev] = p; - break; - } - } - } else if (joystick_port[dev] > 0) - acard->res_joystick = request_region(joystick_port[dev], 8, "ALS4000 gameport"); - if (acard->res_joystick) - joystick = joystick_port[dev]; - else - joystick = 0; -#endif - snd_als4000_set_addr(gcr, 0, 0, 0, joystick); - + /* disable all legacy ISA stuff */ + snd_als4000_set_addr(acard->gcr, 0, 0, 0, 0); + if ((err = snd_sbdsp_create(card, gcr + 0x10, pci->irq, @@ -711,12 +751,7 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci, } } -#ifdef SUPPORT_JOYSTICK - if (acard->res_joystick) { - acard->gameport.io = joystick; - gameport_register_port(&acard->gameport); - } -#endif + snd_als4000_create_gameport(acard, dev); if ((err = snd_card_register(card)) < 0) { snd_card_free(card); diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 36010940e..6b04c0acc 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -43,6 +43,7 @@ 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 */ static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 48000}; +static char *ac97_quirk[SNDRV_CARDS]; static int spdif_aclink[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; module_param_array(index, int, NULL, 0444); @@ -53,6 +54,8 @@ module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable audio part of ATI IXP controller."); module_param_array(ac97_clock, int, NULL, 0444); 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(spdif_aclink, bool, NULL, 0444); MODULE_PARM_DESC(spdif_aclink, "S/PDIF over AC-link."); @@ -247,6 +250,7 @@ struct snd_atiixp_dma { int running; int pcm_open_flag; int ac97_pcm_type; /* index # of ac97_pcm to access, -1 = not used */ + unsigned int saved_curptr; }; /* @@ -264,7 +268,6 @@ struct snd_atiixp { ac97_t *ac97[NUM_ATI_CODECS]; spinlock_t reg_lock; - spinlock_t ac97_lock; atiixp_dma_t dmas[NUM_ATI_DMAS]; struct ac97_pcm *pcms[NUM_ATI_PCMS]; @@ -476,20 +479,14 @@ static void snd_atiixp_codec_write(atiixp_t *chip, unsigned short codec, unsigne static unsigned short snd_atiixp_ac97_read(ac97_t *ac97, unsigned short reg) { atiixp_t *chip = ac97->private_data; - unsigned short data; - spin_lock(&chip->ac97_lock); - data = snd_atiixp_codec_read(chip, ac97->num, reg); - spin_unlock(&chip->ac97_lock); - return data; + return snd_atiixp_codec_read(chip, ac97->num, reg); } static void snd_atiixp_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val) { atiixp_t *chip = ac97->private_data; - spin_lock(&chip->ac97_lock); snd_atiixp_codec_write(chip, ac97->num, reg, val); - spin_unlock(&chip->ac97_lock); } /* @@ -637,21 +634,20 @@ static snd_pcm_uframes_t snd_atiixp_pcm_pointer(snd_pcm_substream_t *substream) snd_pcm_runtime_t *runtime = substream->runtime; atiixp_dma_t *dma = (atiixp_dma_t *)runtime->private_data; unsigned int curptr; + int timeout = 1000; - spin_lock(&chip->reg_lock); - curptr = readl(chip->remap_addr + dma->ops->dt_cur); - if (curptr < dma->buf_addr) { - snd_printdd("curptr = %x, base = %x\n", curptr, dma->buf_addr); - curptr = 0; - } else { + while (timeout--) { + curptr = readl(chip->remap_addr + dma->ops->dt_cur); + if (curptr < dma->buf_addr) + continue; curptr -= dma->buf_addr; - if (curptr >= dma->buf_bytes) { - snd_printdd("curptr = %x, size = %x\n", curptr, dma->buf_bytes); - curptr = 0; - } + if (curptr >= dma->buf_bytes) + continue; + return bytes_to_frames(runtime, curptr); } - spin_unlock(&chip->reg_lock); - return bytes_to_frames(runtime, curptr); + snd_printd("atiixp: invalid DMA pointer read 0x%x (buf=%x)\n", + readl(chip->remap_addr + dma->ops->dt_cur), dma->buf_addr); + return 0; } /* @@ -1336,7 +1332,17 @@ static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id, struct pt_regs *r * ac97 mixer section */ -static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock) +static struct ac97_quirk ac97_quirks[] __devinitdata = { + { + .vendor = 0x103c, + .device = 0x006b, + .name = "HP Pavilion ZV5030US", + .type = AC97_TUNE_MUTE_LED + }, + { } /* terminator */ +}; + +static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock, const char *quirk_override) { ac97_bus_t *pbus; ac97_template_t ac97; @@ -1370,6 +1376,8 @@ static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock) ac97.pci = chip->pci; ac97.num = i; ac97.scaps = AC97_SCAP_SKIP_MODEM; + if (! chip->spdif_over_aclink) + ac97.scaps |= AC97_SCAP_NO_SPDIF; if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) { chip->ac97[i] = NULL; /* to be sure */ snd_printdd("atiixp: codec %d not available for audio\n", i); @@ -1383,7 +1391,7 @@ static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock) return -ENODEV; } - /* snd_ac97_tune_hardware(chip->ac97, ac97_quirks); */ + snd_ac97_tune_hardware(chip->ac97[0], ac97_quirks, quirk_override); return 0; } @@ -1393,14 +1401,18 @@ static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock) /* * power management */ -static int snd_atiixp_suspend(snd_card_t *card, unsigned int state) +static int snd_atiixp_suspend(snd_card_t *card, pm_message_t state) { atiixp_t *chip = card->pm_private_data; int i; for (i = 0; i < NUM_ATI_PCMDEVS; i++) - if (chip->pcmdevs[i]) + if (chip->pcmdevs[i]) { + atiixp_dma_t *dma = &chip->dmas[i]; + if (dma->substream && dma->running) + dma->saved_curptr = readl(chip->remap_addr + dma->ops->dt_cur); snd_pcm_suspend_all(chip->pcmdevs[i]); + } for (i = 0; i < NUM_ATI_CODECS; i++) if (chip->ac97[i]) snd_ac97_suspend(chip->ac97[i]); @@ -1409,11 +1421,10 @@ static int snd_atiixp_suspend(snd_card_t *card, unsigned int state) pci_set_power_state(chip->pci, 3); pci_disable_device(chip->pci); - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } -static int snd_atiixp_resume(snd_card_t *card, unsigned int state) +static int snd_atiixp_resume(snd_card_t *card) { atiixp_t *chip = card->pm_private_data; int i; @@ -1429,7 +1440,17 @@ static int snd_atiixp_resume(snd_card_t *card, unsigned int state) if (chip->ac97[i]) snd_ac97_resume(chip->ac97[i]); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); + for (i = 0; i < NUM_ATI_PCMDEVS; i++) + if (chip->pcmdevs[i]) { + atiixp_dma_t *dma = &chip->dmas[i]; + if (dma->substream && dma->running) { + dma->ops->enable_dma(chip, 1); + writel((u32)dma->desc_buf.addr | ATI_REG_LINKPTR_EN, + chip->remap_addr + dma->ops->llp_offset); + writel(dma->saved_curptr, chip->remap_addr + dma->ops->dt_cur); + } + } + return 0; } #endif /* CONFIG_PM */ @@ -1508,7 +1529,6 @@ static int __devinit snd_atiixp_create(snd_card_t *card, } spin_lock_init(&chip->reg_lock); - spin_lock_init(&chip->ac97_lock); init_MUTEX(&chip->open_mutex); chip->card = card; chip->pci = pci; @@ -1579,7 +1599,7 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci, chip->spdif_over_aclink = spdif_aclink[dev]; - if ((err = snd_atiixp_mixer_new(chip, ac97_clock[dev])) < 0) + if ((err = snd_atiixp_mixer_new(chip, ac97_clock[dev], ac97_quirk[dev])) < 0) goto __error; if ((err = snd_atiixp_pcm_new(chip)) < 0) diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c index 611ee42eb..889b4a1a5 100644 --- a/sound/pci/au88x0/au88x0.c +++ b/sound/pci/au88x0/au88x0.c @@ -4,7 +4,7 @@ * * This driver is the result of the OpenVortex Project from Savannah * (savannah.nongnu.org/projects/openvortex). I would like to thank - * the developers of OpenVortex, Jeff Muizelar and Kester Maddock, from + * the developers of OpenVortex, Jeff Muizelaar and Kester Maddock, from * whom i got plenty of help, and their codebase was invaluable. * Thanks to the ALSA developers, they helped a lot working out * the ALSA part. @@ -170,9 +170,8 @@ snd_vortex_create(snd_card_t * card, struct pci_dev *pci, vortex_t ** rchip) if ((err = pci_request_regions(pci, CARD_NAME_SHORT)) != 0) goto regions_out; - chip->mmio = - ioremap_nocache(pci_resource_start(pci, 0), - pci_resource_len(pci, 0)); + chip->mmio = ioremap_nocache(pci_resource_start(pci, 0), + pci_resource_len(pci, 0)); if (!chip->mmio) { printk(KERN_ERR "MMIO area remap failed.\n"); err = -ENOMEM; @@ -187,10 +186,9 @@ snd_vortex_create(snd_card_t * card, struct pci_dev *pci, vortex_t ** rchip) goto core_out; } - if ((err = - request_irq(pci->irq, vortex_interrupt, - SA_INTERRUPT | SA_SHIRQ, CARD_NAME_SHORT, - (void *)chip)) != 0) { + if ((err = request_irq(pci->irq, vortex_interrupt, + SA_INTERRUPT | SA_SHIRQ, CARD_NAME_SHORT, + chip)) != 0) { printk(KERN_ERR "cannot grab irq\n"); goto irq_out; } @@ -214,7 +212,6 @@ snd_vortex_create(snd_card_t * card, struct pci_dev *pci, vortex_t ** rchip) irq_out: vortex_core_shutdown(chip); core_out: - //FIXME: the type of chip->mmio might need to be changed?? iounmap(chip->mmio); ioremap_out: pci_release_regions(chip->pci_dev); @@ -293,10 +290,9 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) snd_card_free(card); return err; } - if ((err = vortex_gameport_register(chip)) < 0) { - snd_card_free(card); - return err; - } + + vortex_gameport_register(chip); + #if 0 if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_VORTEX_SYNTH, sizeof(snd_vortex_synth_arg_t), &wave) < 0 diff --git a/sound/pci/au88x0/au88x0.h b/sound/pci/au88x0/au88x0.h index a300bfdab..ee1ede197 100644 --- a/sound/pci/au88x0/au88x0.h +++ b/sound/pci/au88x0/au88x0.h @@ -80,7 +80,8 @@ #define VORTEX_RESOURCE_LAST 0x00000005 /* Check for SDAC bit in "Extended audio ID" AC97 register */ -#define VORTEX_IS_QUAD(x) ((x->codec == NULL) ? 0 : (x->codec->ext_id&0x80)) +//#define VORTEX_IS_QUAD(x) (((x)->codec == NULL) ? 0 : ((x)->codec->ext_id&0x80)) +#define VORTEX_IS_QUAD(x) ((x)->isquad) /* Check if chip has bug. */ #define IS_BAD_CHIP(x) (\ (x->rev == 0xfe && x->device == PCI_DEVICE_ID_AUREAL_VORTEX_2) || \ @@ -164,6 +165,8 @@ struct snd_vortex { int xt_mode; /* 1: speakers, 0:headphones. */ #endif + int isquad; /* cache of extended ID codec flag. */ + /* Gameport stuff. */ struct gameport *gameport; @@ -208,6 +211,7 @@ static void vortex_adbdma_startfifo(vortex_t * vortex, int adbdma); static void vortex_adbdma_pausefifo(vortex_t * vortex, int adbdma); static void vortex_adbdma_resumefifo(vortex_t * vortex, int adbdma); static int inline vortex_adbdma_getlinearpos(vortex_t * vortex, int adbdma); +static void vortex_adbdma_resetup(vortex_t *vortex, int adbdma); #ifndef CHIP_AU8810 static void vortex_wtdma_startfifo(vortex_t * vortex, int wtdma); @@ -268,7 +272,7 @@ static void vortex_Vort3D_InitializeSource(a3dsrc_t * a, int en); /* Driver stuff. */ static int __devinit vortex_gameport_register(vortex_t * card); -static int __devexit vortex_gameport_unregister(vortex_t * card); +static void vortex_gameport_unregister(vortex_t * card); #ifndef CHIP_AU8820 static int __devinit vortex_eq_init(vortex_t * vortex); static int __devexit vortex_eq_free(vortex_t * vortex); diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c index bdf7ce8ce..f0eda4bbb 100644 --- a/sound/pci/au88x0/au88x0_core.c +++ b/sound/pci/au88x0/au88x0_core.c @@ -21,7 +21,7 @@ These functions are mainly the result of translations made from the original disassembly of the au88x0 binary drivers, written by Aureal before they went down. - Many thanks to the Jeff Muizelar, Kester Maddock, and whoever + Many thanks to the Jeff Muizelaar, Kester Maddock, and whoever contributed to the OpenVortex project. The author of this file, put the few available pieces together and translated the rest of the riddle (Mix, Src and connection stuff). @@ -1223,6 +1223,33 @@ static int vortex_adbdma_bufshift(vortex_t * vortex, int adbdma) return delta; } + +static void vortex_adbdma_resetup(vortex_t *vortex, int adbdma) { + stream_t *dma = &vortex->dma_adb[adbdma]; + int p, pp, i; + + /* refresh hw page table */ + for (i=0 ; i < 4 && i < dma->nr_periods; i++) { + /* p: audio buffer page index */ + p = dma->period_virt + i; + if (p >= dma->nr_periods) + p -= dma->nr_periods; + /* pp: hardware DMA page index. */ + pp = dma->period_real + i; + if (dma->nr_periods < 4) { + if (pp >= dma->nr_periods) + pp -= dma->nr_periods; + } + else { + if (pp >= 4) + pp -= 4; + } + hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFBASE+(((adbdma << 2)+pp) << 2), snd_sgbuf_get_addr(dma->sgbuf, dma->period_bytes * p)); + /* Force write thru cache. */ + hwread(vortex->mmio, VORTEX_ADBDMA_BUFBASE + (((adbdma << 2)+pp) << 2)); + } +} + static int inline vortex_adbdma_getlinearpos(vortex_t * vortex, int adbdma) { stream_t *dma = &vortex->dma_adb[adbdma]; @@ -2453,33 +2480,34 @@ static void vortex_codec_init(vortex_t * vortex) int i; for (i = 0; i < 32; i++) { - hwwrite(vortex->mmio, (VORTEX_CODEC_CHN + (i << 2)), 0); - udelay(2000); + /* the windows driver writes -i, so we write -i */ + hwwrite(vortex->mmio, (VORTEX_CODEC_CHN + (i << 2)), -i); + msleep(2); } if (0) { hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x8068); - udelay(1000); + msleep(1); hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x00e8); - udelay(1000); + msleep(1); } else { hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x00a8); - udelay(2000); + msleep(2); hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x80a8); - udelay(2000); + msleep(2); hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x80e8); - udelay(2000); + msleep(2); hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x80a8); - udelay(2000); + msleep(2); hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x00a8); - udelay(2000); + msleep(2); hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x00e8); } for (i = 0; i < 32; i++) { - hwwrite(vortex->mmio, (VORTEX_CODEC_CHN + (i << 2)), 0); - udelay(5000); + hwwrite(vortex->mmio, (VORTEX_CODEC_CHN + (i << 2)), -i); + msleep(5); } hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0xe8); - udelay(1000); + msleep(1); /* Enable codec channels 0 and 1. */ hwwrite(vortex->mmio, VORTEX_CODEC_EN, hwread(vortex->mmio, VORTEX_CODEC_EN) | EN_CODEC); @@ -2634,10 +2662,10 @@ static int vortex_core_init(vortex_t * vortex) printk(KERN_INFO "Vortex: init.... "); /* Hardware Init. */ hwwrite(vortex->mmio, VORTEX_CTRL, 0xffffffff); - udelay(5000); + msleep(5); hwwrite(vortex->mmio, VORTEX_CTRL, hwread(vortex->mmio, VORTEX_CTRL) & 0xffdfffff); - udelay(5000); + msleep(5); /* Reset IRQ flags */ hwwrite(vortex->mmio, VORTEX_IRQ_SOURCE, 0xffffffff); hwread(vortex->mmio, VORTEX_IRQ_STAT); @@ -2704,7 +2732,7 @@ static int vortex_core_shutdown(vortex_t * vortex) hwwrite(vortex->mmio, VORTEX_IRQ_CTRL, 0); hwwrite(vortex->mmio, VORTEX_CTRL, 0); - udelay(5000); + msleep(5); hwwrite(vortex->mmio, VORTEX_IRQ_SOURCE, 0xffff); printk(KERN_INFO "done.\n"); diff --git a/sound/pci/au88x0/au88x0_eq.c b/sound/pci/au88x0/au88x0_eq.c index 9045a4bf1..53b47a42c 100644 --- a/sound/pci/au88x0/au88x0_eq.c +++ b/sound/pci/au88x0/au88x0_eq.c @@ -45,6 +45,8 @@ #define VORTEX_EQ_SOURCE (VORTEX_EQ_BASE + 0x430) #define VORTEX_EQ_CTRL (VORTEX_EQ_BASE + 0x440) +#define VORTEX_BAND_COEFF_SIZE 0x30 + /* CEqHw.s */ static void vortex_EqHw_SetTimeConsts(vortex_t * vortex, u16 gain, u16 level) { @@ -52,10 +54,10 @@ static void vortex_EqHw_SetTimeConsts(vortex_t * vortex, u16 gain, u16 level) hwwrite(vortex->mmio, 0x2b3c8, level); } -static inline short sign_invert(short a) +static inline u16 sign_invert(u16 a) { /* -(-32768) -> -32768 so we do -(-32768) -> 32767 to make the result positive */ - if (a == -32768) + if (a == (u16)-32768) return 32767; else return -a; @@ -71,13 +73,13 @@ static void vortex_EqHw_SetLeftCoefs(vortex_t * vortex, u16 coefs[]) hwwrite(vortex->mmio, 0x2b004 + n * 0x30, coefs[i + 1]); if (eqhw->this08 == 0) { - hwwrite(vortex->mmio, 0x2b008 + n * 0x30, coefs[i + 2] & 0xffff); - hwwrite(vortex->mmio, 0x2b00c + n * 0x30, coefs[i + 3] & 0xffff); - hwwrite(vortex->mmio, 0x2b010 + n * 0x30, coefs[i + 4] & 0xffff); + hwwrite(vortex->mmio, 0x2b008 + n * 0x30, coefs[i + 2]); + hwwrite(vortex->mmio, 0x2b00c + n * 0x30, coefs[i + 3]); + hwwrite(vortex->mmio, 0x2b010 + n * 0x30, coefs[i + 4]); } else { - hwwrite(vortex->mmio, 0x2b008 + n * 0x30, sign_invert(coefs[2 + i]) & 0xffff); - hwwrite(vortex->mmio, 0x2b00c + n * 0x30, sign_invert(coefs[3 + i]) & 0xffff); - hwwrite(vortex->mmio, 0x2b010 + n * 0x30, sign_invert(coefs[4 + i]) & 0xffff); + hwwrite(vortex->mmio, 0x2b008 + n * 0x30, sign_invert(coefs[2 + i])); + hwwrite(vortex->mmio, 0x2b00c + n * 0x30, sign_invert(coefs[3 + i])); + hwwrite(vortex->mmio, 0x2b010 + n * 0x30, sign_invert(coefs[4 + i])); } i += 5; } @@ -93,13 +95,13 @@ static void vortex_EqHw_SetRightCoefs(vortex_t * vortex, u16 coefs[]) hwwrite(vortex->mmio, 0x2b1e4 + n * 0x30, coefs[1 + i]); if (eqhw->this08 == 0) { - hwwrite(vortex->mmio, 0x2b1e8 + n * 0x30, coefs[2 + i] & 0xffff); - hwwrite(vortex->mmio, 0x2b1ec + n * 0x30, coefs[3 + i] & 0xffff); - hwwrite(vortex->mmio, 0x2b1f0 + n * 0x30, coefs[4 + i] & 0xffff); + hwwrite(vortex->mmio, 0x2b1e8 + n * 0x30, coefs[2 + i]); + hwwrite(vortex->mmio, 0x2b1ec + n * 0x30, coefs[3 + i]); + hwwrite(vortex->mmio, 0x2b1f0 + n * 0x30, coefs[4 + i]); } else { - hwwrite(vortex->mmio, 0x2b1e8 + n * 0x30, sign_invert(coefs[2 + i]) & 0xffff); - hwwrite(vortex->mmio, 0x2b1ec + n * 0x30, sign_invert(coefs[3 + i]) & 0xffff); - hwwrite(vortex->mmio, 0x2b1f0 + n * 0x30, sign_invert(coefs[4 + i]) & 0xffff); + hwwrite(vortex->mmio, 0x2b1e8 + n * 0x30, sign_invert(coefs[2 + i])); + hwwrite(vortex->mmio, 0x2b1ec + n * 0x30, sign_invert(coefs[3 + i])); + hwwrite(vortex->mmio, 0x2b1f0 + n * 0x30, sign_invert(coefs[4 + i])); } i += 5; } @@ -176,8 +178,8 @@ static void vortex_EqHw_SetBypassGain(vortex_t * vortex, u16 a, u16 b) hwwrite(vortex->mmio, 0x2b3d4, a); hwwrite(vortex->mmio, 0x2b3ec, b); } else { - hwwrite(vortex->mmio, 0x2b3d4, sign_invert(a) & 0xffff); - hwwrite(vortex->mmio, 0x2b3ec, sign_invert(b) & 0xffff); + hwwrite(vortex->mmio, 0x2b3d4, sign_invert(a)); + hwwrite(vortex->mmio, 0x2b3ec, sign_invert(b)); } } @@ -319,25 +321,27 @@ static void vortex_EqHw_GetRightGainsCurrent(vortex_t * vortex, u16 a[]) #endif /* EQ band levels settings */ -static void vortex_EqHw_SetLevels(vortex_t * vortex, u16 a[]) +static void vortex_EqHw_SetLevels(vortex_t * vortex, u16 peaks[]) { eqhw_t *eqhw = &(vortex->eq.this04); - int ebx; + int i; - for (ebx = 0; ebx < eqhw->this04; ebx++) { - hwwrite(vortex->mmio, 0x2b024 + ebx * 0x30, a[ebx]); + /* set left peaks */ + for (i = 0; i < eqhw->this04; i++) { + hwwrite(vortex->mmio, 0x2b024 + i * VORTEX_BAND_COEFF_SIZE, peaks[i]); } - hwwrite(vortex->mmio, 0x2b3cc, a[eqhw->this04]); - hwwrite(vortex->mmio, 0x2b3d8, a[eqhw->this04 + 1]); + hwwrite(vortex->mmio, 0x2b3cc, peaks[eqhw->this04]); + hwwrite(vortex->mmio, 0x2b3d8, peaks[eqhw->this04 + 1]); - for (ebx = 0; ebx < eqhw->this04; ebx++) { - hwwrite(vortex->mmio, 0x2b204 + ebx * 0x30, - a[ebx + (eqhw->this04 + 2)]); + /* set right peaks */ + for (i = 0; i < eqhw->this04; i++) { + hwwrite(vortex->mmio, 0x2b204 + i * VORTEX_BAND_COEFF_SIZE, + peaks[i + (eqhw->this04 + 2)]); } - hwwrite(vortex->mmio, 0x2b3e4, a[2 + (eqhw->this04 * 2)]); - hwwrite(vortex->mmio, 0x2b3f0, a[3 + (eqhw->this04 * 2)]); + hwwrite(vortex->mmio, 0x2b3e4, peaks[2 + (eqhw->this04 * 2)]); + hwwrite(vortex->mmio, 0x2b3f0, peaks[3 + (eqhw->this04 * 2)]); } #if 0 diff --git a/sound/pci/au88x0/au88x0_game.c b/sound/pci/au88x0/au88x0_game.c index d47bff1eb..a07d1deba 100644 --- a/sound/pci/au88x0/au88x0_game.c +++ b/sound/pci/au88x0/au88x0_game.c @@ -44,20 +44,20 @@ static unsigned char vortex_game_read(struct gameport *gameport) { - vortex_t *vortex = gameport->driver; + vortex_t *vortex = gameport_get_port_data(gameport); return hwread(vortex->mmio, VORTEX_GAME_LEGACY); } static void vortex_game_trigger(struct gameport *gameport) { - vortex_t *vortex = gameport->driver; + vortex_t *vortex = gameport_get_port_data(gameport); hwwrite(vortex->mmio, VORTEX_GAME_LEGACY, 0xff); } static int vortex_game_cooked_read(struct gameport *gameport, int *axes, int *buttons) { - vortex_t *vortex = gameport->driver; + vortex_t *vortex = gameport_get_port_data(gameport); int i; *buttons = (~hwread(vortex->mmio, VORTEX_GAME_LEGACY) >> 4) & 0xf; @@ -73,7 +73,7 @@ vortex_game_cooked_read(struct gameport *gameport, int *axes, int *buttons) static int vortex_game_open(struct gameport *gameport, int mode) { - vortex_t *vortex = gameport->driver; + vortex_t *vortex = gameport_get_port_data(gameport); switch (mode) { case GAMEPORT_MODE_COOKED: @@ -94,40 +94,42 @@ static int vortex_game_open(struct gameport *gameport, int mode) return 0; } -static int vortex_gameport_register(vortex_t * vortex) +static int __devinit vortex_gameport_register(vortex_t * vortex) { - if ((vortex->gameport = kcalloc(1, sizeof(struct gameport), GFP_KERNEL)) == NULL) { - return -1; + struct gameport *gp; + + vortex->gameport = gp = gameport_allocate_port(); + if (!gp) { + printk(KERN_ERR "vortex: cannot allocate memory for gameport\n"); + return -ENOMEM; }; - - vortex->gameport->driver = vortex; - vortex->gameport->fuzz = 64; - vortex->gameport->read = vortex_game_read; - vortex->gameport->trigger = vortex_game_trigger; - vortex->gameport->cooked_read = vortex_game_cooked_read; - vortex->gameport->open = vortex_game_open; + gameport_set_name(gp, "AU88x0 Gameport"); + gameport_set_phys(gp, "pci%s/gameport0", pci_name(vortex->pci_dev)); + gameport_set_dev_parent(gp, &vortex->pci_dev->dev); + + gp->read = vortex_game_read; + gp->trigger = vortex_game_trigger; + gp->cooked_read = vortex_game_cooked_read; + gp->open = vortex_game_open; + + gameport_set_port_data(gp, vortex); + gp->fuzz = 64; - gameport_register_port((struct gameport *)vortex->gameport); + gameport_register_port(gp); -/* printk(KERN_INFO "gameport%d: %s at speed %d kHz\n", - vortex->gameport->number, vortex->pci_dev->name, vortex->gameport->speed); -*/ return 0; } -static int vortex_gameport_unregister(vortex_t * vortex) +static void vortex_gameport_unregister(vortex_t * vortex) { - if (vortex->gameport != NULL) { + if (vortex->gameport) { gameport_unregister_port(vortex->gameport); - kfree(vortex->gameport); + vortex->gameport = NULL; } - return 0; } #else - -static inline int vortex_gameport_register(vortex_t * vortex) { return 0; } -static inline int vortex_gameport_unregister(vortex_t * vortex) { return 0; } - +static inline int vortex_gameport_register(vortex_t * vortex) { return -ENOSYS; } +static inline void vortex_gameport_unregister(vortex_t * vortex) { } #endif diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c index f624b7726..04dcefd8b 100644 --- a/sound/pci/au88x0/au88x0_pcm.c +++ b/sound/pci/au88x0/au88x0_pcm.c @@ -20,7 +20,7 @@ * Supports ADB and WT DMA. Unfortunately, WT channels do not run yet. * It remains stuck,and DMA transfers do not happen. */ - +#include <sound/asoundef.h> #include <sound/driver.h> #include <linux/time.h> #include <sound/core.h> @@ -320,8 +320,10 @@ static int snd_vortex_pcm_trigger(snd_pcm_substream_t * substream, int cmd) // do something to start the PCM engine //printk(KERN_INFO "vortex: start %d\n", dma); stream->fifo_enabled = 1; - if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) + if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) { + vortex_adbdma_resetup(chip, dma); vortex_adbdma_startfifo(chip, dma); + } #ifndef CHIP_AU8810 else { printk(KERN_INFO "vortex: wt start %d\n", dma); @@ -429,61 +431,77 @@ static char *vortex_pcm_name[VORTEX_PCM_LAST] = { }; /* SPDIF kcontrol */ -static int -snd_vortex_spdif_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo) -{ - static char *texts[] = { "32000", "44100", "48000" }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; +static int snd_vortex_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; 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_vortex_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) -{ - vortex_t *vortex = snd_kcontrol_chip(kcontrol); - if (vortex->spdif_sr == 32000) - ucontrol->value.enumerated.item[0] = 0; - if (vortex->spdif_sr == 44100) - ucontrol->value.enumerated.item[0] = 1; - if (vortex->spdif_sr == 48000) - ucontrol->value.enumerated.item[0] = 2; +static int snd_vortex_spdif_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +{ + ucontrol->value.iec958.status[0] = 0xff; + ucontrol->value.iec958.status[1] = 0xff; + ucontrol->value.iec958.status[2] = 0xff; + ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS; return 0; } -static int -snd_vortex_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) + +static int snd_vortex_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { vortex_t *vortex = snd_kcontrol_chip(kcontrol); - static unsigned int sr[3] = { 32000, 44100, 48000 }; + ucontrol->value.iec958.status[0] = 0x00; + ucontrol->value.iec958.status[1] = IEC958_AES1_CON_ORIGINAL|IEC958_AES1_CON_DIGDIGCONV_ID; + ucontrol->value.iec958.status[2] = 0x00; + switch (vortex->spdif_sr) { + case 32000: ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_32000; break; + case 44100: ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_44100; break; + case 48000: ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_48000; break; + } + return 0; +} - //printk("vortex: spdif sr = %d\n", ucontrol->value.enumerated.item[0]); - vortex->spdif_sr = sr[ucontrol->value.enumerated.item[0] % 3]; - vortex_spdif_init(vortex, - sr[ucontrol->value.enumerated.item[0] % 3], 1); +static int snd_vortex_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +{ + vortex_t *vortex = snd_kcontrol_chip(kcontrol); + int spdif_sr = 48000; + switch (ucontrol->value.iec958.status[3] & IEC958_AES3_CON_FS) { + case IEC958_AES3_CON_FS_32000: spdif_sr = 32000; break; + case IEC958_AES3_CON_FS_44100: spdif_sr = 44100; break; + case IEC958_AES3_CON_FS_48000: spdif_sr = 48000; break; + } + if (spdif_sr == vortex->spdif_sr) + return 0; + vortex->spdif_sr = spdif_sr; + vortex_spdif_init(vortex, vortex->spdif_sr, 1); return 1; } -static snd_kcontrol_new_t vortex_spdif_kcontrol __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "SPDIF SR", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = 0, - .info = snd_vortex_spdif_info, - .get = snd_vortex_spdif_get, - .put = snd_vortex_spdif_put + +/* spdif controls */ +static snd_kcontrol_new_t snd_vortex_mixer_spdif[] __devinitdata = { + { + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), + .info = snd_vortex_spdif_info, + .get = snd_vortex_spdif_get, + .put = snd_vortex_spdif_put, + }, + { + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK), + .info = snd_vortex_spdif_info, + .get = snd_vortex_spdif_mask_get + }, }; /* create a pcm device */ static int __devinit snd_vortex_new_pcm(vortex_t * chip, int idx, int nr) { snd_pcm_t *pcm; + snd_kcontrol_t *kctl; + int i; int err, nr_capt; if ((chip == 0) || (idx < 0) || (idx > VORTEX_PCM_LAST)) @@ -518,13 +536,13 @@ static int __devinit snd_vortex_new_pcm(vortex_t * chip, int idx, int nr) 0x10000, 0x10000); if (VORTEX_PCM_TYPE(pcm) == VORTEX_PCM_SPDIF) { - snd_kcontrol_t *kcontrol; - - if ((kcontrol = - snd_ctl_new1(&vortex_spdif_kcontrol, chip)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(chip->card, kcontrol)) < 0) - return err; + for (i = 0; i < ARRAY_SIZE(snd_vortex_mixer_spdif); i++) { + kctl = snd_ctl_new1(&snd_vortex_mixer_spdif[i], chip); + if (!kctl) + return -ENOMEM; + if ((err = snd_ctl_add(chip->card, kctl)) < 0) + return err; + } } return 0; } diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index b26a7180a..b8ae53412 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -160,19 +160,19 @@ MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}"); #endif 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 */ -#ifdef SUPPORT_JOYSTICK -static int joystick[SNDRV_CARDS]; -#endif - module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for AZF3328 soundcard."); + +static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for AZF3328 soundcard."); + +static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable AZF3328 soundcard."); + #ifdef SUPPORT_JOYSTICK +static int joystick[SNDRV_CARDS]; module_param_array(joystick, bool, NULL, 0444); MODULE_PARM_DESC(joystick, "Enable joystick for AZF3328 soundcard."); #endif @@ -189,8 +189,7 @@ struct _snd_azf3328 { unsigned long mixer_port; #ifdef SUPPORT_JOYSTICK - struct gameport gameport; - struct resource *res_joystick; + struct gameport *gameport; #endif struct pci_dev *pci; @@ -214,17 +213,17 @@ static struct pci_device_id snd_azf3328_ids[] = { MODULE_DEVICE_TABLE(pci, snd_azf3328_ids); -void snd_azf3328_io2_write(azf3328_t *chip, int reg, unsigned char value) +static inline void snd_azf3328_io2_write(azf3328_t *chip, int reg, unsigned char value) { outb(value, chip->io2_port + reg); } -unsigned char snd_azf3328_io2_read(azf3328_t *chip, int reg) +static inline unsigned char snd_azf3328_io2_read(azf3328_t *chip, int reg) { return inb(chip->io2_port + reg); } -void snd_azf3328_mixer_write(azf3328_t *chip, int reg, unsigned long value, int type) +static void snd_azf3328_mixer_write(azf3328_t *chip, int reg, unsigned long value, int type) { switch(type) { case WORD_VALUE: @@ -239,26 +238,7 @@ void snd_azf3328_mixer_write(azf3328_t *chip, int reg, unsigned long value, int } } -unsigned long snd_azf3328_mixer_read(azf3328_t *chip, int reg, int type) -{ - unsigned long res = 0; - - switch(type) { - case WORD_VALUE: - res = (unsigned long)inw(chip->mixer_port + reg); - break; - case DWORD_VALUE: - res = (unsigned long)inl(chip->mixer_port + reg); - break; - case BYTE_VALUE: - res = (unsigned long)inb(chip->mixer_port + reg); - break; - } - - return res; -} - -void snd_azf3328_mixer_set_mute(azf3328_t *chip, int reg, int do_mute) +static void snd_azf3328_mixer_set_mute(azf3328_t *chip, int reg, int do_mute) { unsigned char oldval; @@ -272,7 +252,7 @@ void snd_azf3328_mixer_set_mute(azf3328_t *chip, int reg, int do_mute) outb(oldval, chip->mixer_port + reg + 1); } -void snd_azf3328_mixer_write_volume_gradually(azf3328_t *chip, int reg, unsigned char dst_vol_left, unsigned char dst_vol_right, int chan_sel, int delay) +static void snd_azf3328_mixer_write_volume_gradually(azf3328_t *chip, int reg, unsigned char dst_vol_left, unsigned char dst_vol_right, int chan_sel, int delay) { unsigned char curr_vol_left = 0, curr_vol_right = 0; int left_done = 0, right_done = 0; @@ -1241,6 +1221,63 @@ static int __devinit snd_azf3328_pcm(azf3328_t *chip, int device) /******************************************************************/ +#ifdef SUPPORT_JOYSTICK +static int __devinit snd_azf3328_config_joystick(azf3328_t *chip, int dev) +{ + struct gameport *gp; + struct resource *r; + + if (!joystick[dev]) + return -ENODEV; + + if (!(r = request_region(0x200, 8, "AZF3328 gameport"))) { + printk(KERN_WARNING "azt3328: cannot reserve joystick ports\n"); + return -EBUSY; + } + + chip->gameport = gp = gameport_allocate_port(); + if (!gp) { + printk(KERN_ERR "azt3328: cannot allocate memory for gameport\n"); + release_resource(r); + kfree_nocheck(r); + return -ENOMEM; + } + + gameport_set_name(gp, "AZF3328 Gameport"); + gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci)); + gameport_set_dev_parent(gp, &chip->pci->dev); + gp->io = 0x200; + gameport_set_port_data(gp, r); + + snd_azf3328_io2_write(chip, IDX_IO2_LEGACY_ADDR, + snd_azf3328_io2_read(chip, IDX_IO2_LEGACY_ADDR) | LEGACY_JOY); + + gameport_register_port(chip->gameport); + + return 0; +} + +static void snd_azf3328_free_joystick(azf3328_t *chip) +{ + if (chip->gameport) { + struct resource *r = gameport_get_port_data(chip->gameport); + + gameport_unregister_port(chip->gameport); + chip->gameport = NULL; + /* disable gameport */ + snd_azf3328_io2_write(chip, IDX_IO2_LEGACY_ADDR, + snd_azf3328_io2_read(chip, IDX_IO2_LEGACY_ADDR) & ~LEGACY_JOY); + release_resource(r); + kfree_nocheck(r); + } +} +#else +static inline int snd_azf3328_config_joystick(azf3328_t *chip, int dev) { return -ENOSYS; } +static inline void snd_azf3328_free_joystick(azf3328_t *chip) { } +#endif + +/******************************************************************/ + static int snd_azf3328_free(azf3328_t *chip) { if (chip->irq < 0) @@ -1255,16 +1292,7 @@ static int snd_azf3328_free(azf3328_t *chip) synchronize_irq(chip->irq); __end_hw: -#ifdef SUPPORT_JOYSTICK - if (chip->res_joystick) { - gameport_unregister_port(&chip->gameport); - /* disable gameport */ - snd_azf3328_io2_write(chip, IDX_IO2_LEGACY_ADDR, - snd_azf3328_io2_read(chip, IDX_IO2_LEGACY_ADDR) & ~LEGACY_JOY); - release_resource(chip->res_joystick); - kfree_nocheck(chip->res_joystick); - } -#endif + snd_azf3328_free_joystick(chip); if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); pci_release_regions(chip->pci); @@ -1392,28 +1420,6 @@ static int __devinit snd_azf3328_create(snd_card_t * card, return 0; } -#ifdef SUPPORT_JOYSTICK -static void __devinit snd_azf3328_config_joystick(azf3328_t *chip, int joystick) -{ - unsigned char val; - - if (joystick == 1) { - if ((chip->res_joystick = request_region(0x200, 8, "AZF3328 gameport")) != NULL) - chip->gameport.io = 0x200; - } - - val = inb(chip->io2_port + IDX_IO2_LEGACY_ADDR); - if (chip->res_joystick) - val |= LEGACY_JOY; - else - val &= ~LEGACY_JOY; - - outb(val, chip->io2_port + IDX_IO2_LEGACY_ADDR); - if (chip->res_joystick) - gameport_register_port(&chip->gameport); -} -#endif - static int __devinit snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { @@ -1484,9 +1490,9 @@ static int __devinit snd_azf3328_probe(struct pci_dev *pci, "azt3328: Feel free to contact hw7oshyuv3001@sneakemail.com for bug reports etc.!\n"); #endif -#ifdef SUPPORT_JOYSTICK - snd_azf3328_config_joystick(chip, joystick[dev]); -#endif + if (snd_azf3328_config_joystick(chip, dev) < 0) + snd_azf3328_io2_write(chip, IDX_IO2_LEGACY_ADDR, + snd_azf3328_io2_read(chip, IDX_IO2_LEGACY_ADDR) & ~LEGACY_JOY); pci_set_drvdata(pci, card); dev++; diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 83b7546ee..89a7ffe5e 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c @@ -41,10 +41,11 @@ MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Brooktree,Bt878}," "{Brooktree,Bt879}}"); -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ +static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the first card */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ static int digital_rate[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; /* digital input rate */ +static int load_all; /* allow to load the non-whitelisted cards */ module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for Bt87x soundcard"); @@ -54,6 +55,8 @@ module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable Bt87x soundcard"); module_param_array(digital_rate, int, NULL, 0444); MODULE_PARM_DESC(digital_rate, "Digital input rate for Bt87x soundcard"); +module_param(load_all, bool, 0444); +MODULE_PARM_DESC(load_all, "Allow to load the non-whitelisted cards"); #ifndef PCI_VENDOR_ID_BROOKTREE @@ -159,7 +162,7 @@ struct snd_bt87x { snd_card_t *card; struct pci_dev *pci; - void *mmio; + void __iomem *mmio; int irq; int dig_rate; @@ -173,7 +176,11 @@ struct snd_bt87x { unsigned int lines; u32 reg_control; + u32 interrupt_mask; + int current_line; + + int pci_parity_errors; }; enum { DEVICE_DIGITAL, DEVICE_ANALOG }; @@ -246,33 +253,53 @@ static void snd_bt87x_free_risc(bt87x_t *chip) } } +static void snd_bt87x_pci_error(bt87x_t *chip, unsigned int status) +{ + u16 pci_status; + + pci_read_config_word(chip->pci, PCI_STATUS, &pci_status); + pci_status &= PCI_STATUS_PARITY | PCI_STATUS_SIG_TARGET_ABORT | + PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_REC_MASTER_ABORT | + PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY; + pci_write_config_word(chip->pci, PCI_STATUS, pci_status); + if (pci_status != PCI_STATUS_DETECTED_PARITY) + snd_printk(KERN_ERR "Aieee - PCI error! status %#08x, PCI status %#04x\n", + status & ERROR_INTERRUPTS, pci_status); + else { + snd_printk(KERN_ERR "Aieee - PCI parity error detected!\n"); + /* error 'handling' similar to aic7xxx_pci.c: */ + chip->pci_parity_errors++; + if (chip->pci_parity_errors > 20) { + snd_printk(KERN_ERR "Too many PCI parity errors observed.\n"); + snd_printk(KERN_ERR "Some device on this bus is generating bad parity.\n"); + snd_printk(KERN_ERR "This is an error *observed by*, not *generated by*, this card.\n"); + snd_printk(KERN_ERR "PCI parity error checking has been disabled.\n"); + chip->interrupt_mask &= ~(INT_PPERR | INT_RIPERR); + snd_bt87x_writel(chip, REG_INT_MASK, chip->interrupt_mask); + } + } +} + static irqreturn_t snd_bt87x_interrupt(int irq, void *dev_id, struct pt_regs *regs) { bt87x_t *chip = dev_id; - unsigned int status; + unsigned int status, irq_status; status = snd_bt87x_readl(chip, REG_INT_STAT); - if (!(status & MY_INTERRUPTS)) + irq_status = status & chip->interrupt_mask; + if (!irq_status) return IRQ_NONE; - snd_bt87x_writel(chip, REG_INT_STAT, status & MY_INTERRUPTS); + snd_bt87x_writel(chip, REG_INT_STAT, irq_status); - if (status & ERROR_INTERRUPTS) { - if (status & (INT_FBUS | INT_FTRGT)) + if (irq_status & ERROR_INTERRUPTS) { + if (irq_status & (INT_FBUS | INT_FTRGT)) snd_printk(KERN_WARNING "FIFO overrun, status %#08x\n", status); - if (status & INT_OCERR) + if (irq_status & INT_OCERR) snd_printk(KERN_ERR "internal RISC error, status %#08x\n", status); - if (status & (INT_PPERR | INT_RIPERR | INT_PABORT)) { - u16 pci_status; - pci_read_config_word(chip->pci, PCI_STATUS, &pci_status); - pci_write_config_word(chip->pci, PCI_STATUS, pci_status & - (PCI_STATUS_PARITY | PCI_STATUS_SIG_TARGET_ABORT | - PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY)); - snd_printk(KERN_ERR "Aieee - PCI error! status %#08x, PCI status %#04x\n", - status, pci_status); - } + if (irq_status & (INT_PPERR | INT_RIPERR | INT_PABORT)) + snd_bt87x_pci_error(chip, irq_status); } - if ((status & INT_RISCI) && (chip->reg_control & CTL_ACAP_EN)) { + if ((irq_status & INT_RISCI) && (chip->reg_control & CTL_ACAP_EN)) { int current_block, irq_block; /* assume that exactly one line has been recorded */ @@ -458,7 +485,7 @@ static int snd_bt87x_start(bt87x_t *chip) snd_bt87x_writel(chip, REG_RISC_STRT_ADD, chip->dma_risc.addr); snd_bt87x_writel(chip, REG_PACKET_LEN, chip->line_bytes | (chip->lines << 16)); - snd_bt87x_writel(chip, REG_INT_MASK, MY_INTERRUPTS); + snd_bt87x_writel(chip, REG_INT_MASK, chip->interrupt_mask); snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); spin_unlock(&chip->reg_lock); return 0; @@ -717,6 +744,7 @@ static int __devinit snd_bt87x_create(snd_card_t *card, } chip->reg_control = CTL_DA_ES2 | CTL_PKTP_16 | (15 << CTL_DA_SDR_SHIFT); + chip->interrupt_mask = MY_INTERRUPTS; snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); snd_bt87x_writel(chip, REG_INT_MASK, 0); snd_bt87x_writel(chip, REG_INT_STAT, MY_INTERRUPTS); @@ -741,13 +769,73 @@ static int __devinit snd_bt87x_create(snd_card_t *card, return 0; } +#define BT_DEVICE(chip, subvend, subdev, rate) \ + { .vendor = PCI_VENDOR_ID_BROOKTREE, \ + .device = PCI_DEVICE_ID_BROOKTREE_##chip, \ + .subvendor = subvend, .subdevice = subdev, \ + .driver_data = rate } + +/* driver_data is the default digital_rate value for that device */ +static struct pci_device_id snd_bt87x_ids[] = { + BT_DEVICE(878, 0x0070, 0x13eb, 32000), /* Hauppauge WinTV series */ + BT_DEVICE(879, 0x0070, 0x13eb, 32000), /* Hauppauge WinTV series */ + BT_DEVICE(878, 0x0070, 0xff01, 44100), /* Viewcast Osprey 200 */ + { } +}; +MODULE_DEVICE_TABLE(pci, snd_bt87x_ids); + +/* cards known not to have audio + * (DVB cards use the audio function to transfer MPEG data) */ +static struct { + unsigned short subvendor, subdevice; +} blacklist[] __devinitdata = { + {0x0071, 0x0101}, /* Nebula Electronics DigiTV */ + {0x11bd, 0x0026}, /* Pinnacle PCTV SAT CI */ + {0x1461, 0x0761}, /* AVermedia AverTV DVB-T */ + {0x1461, 0x0771}, /* AVermedia DVB-T 771 */ + {0x1822, 0x0001}, /* Twinhan VisionPlus DVB-T */ + {0x18ac, 0xdb10}, /* DVICO FusionHDTV DVB-T Lite */ + {0x270f, 0xfc00}, /* Chaintech Digitop DST-1000 DVB-S */ +}; + +/* return the rate of the card, or a negative value if it's blacklisted */ +static int __devinit snd_bt87x_detect_card(struct pci_dev *pci) +{ + int i; + const struct pci_device_id *supported; + + supported = pci_match_device(snd_bt87x_ids, pci); + if (supported) + return supported->driver_data; + + for (i = 0; i < ARRAY_SIZE(blacklist); ++i) + if (blacklist[i].subvendor == pci->subsystem_vendor && + blacklist[i].subdevice == pci->subsystem_device) { + snd_printdd(KERN_INFO "card %#04x:%#04x has no audio\n", + pci->subsystem_vendor, pci->subsystem_device); + return -EBUSY; + } + + snd_printk(KERN_INFO "unknown card %#04x:%#04x, using default rate 32000\n", + pci->subsystem_vendor, pci->subsystem_device); + snd_printk(KERN_DEBUG "please mail id, board name, and, " + "if it works, the correct digital_rate option to " + "<alsa-devel@lists.sf.net>\n"); + return 32000; /* default rate */ +} + static int __devinit snd_bt87x_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { static int dev; snd_card_t *card; bt87x_t *chip; - int err; + int err, rate; + + rate = pci_id->driver_data; + if (! rate) + if ((rate = snd_bt87x_detect_card(pci)) <= 0) + return -ENODEV; if (dev >= SNDRV_CARDS) return -ENODEV; @@ -767,7 +855,7 @@ static int __devinit snd_bt87x_probe(struct pci_dev *pci, if (digital_rate[dev] > 0) chip->dig_rate = digital_rate[dev]; else - chip->dig_rate = (int)pci_id->driver_data; + chip->dig_rate = rate; err = snd_bt87x_pcm(chip, DEVICE_DIGITAL, "Bt87x Digital"); if (err < 0) @@ -811,22 +899,13 @@ static void __devexit snd_bt87x_remove(struct pci_dev *pci) pci_set_drvdata(pci, NULL); } -#define BT_DEVICE(chip, subvend, subdev, rate) \ - { .vendor = PCI_VENDOR_ID_BROOKTREE, \ - .device = PCI_DEVICE_ID_BROOKTREE_##chip, \ - .subvendor = subvend, .subdevice = subdev, \ - .driver_data = rate } - -/* driver_data is the default digital_rate value for that device */ -static struct pci_device_id snd_bt87x_ids[] = { - BT_DEVICE(878, 0x0070, 0xff01, 44100), /* Osprey 200 */ - - /* default entries for 32kHz and generic Bt87x cards */ - BT_DEVICE(878, PCI_ANY_ID, PCI_ANY_ID, 32000), - BT_DEVICE(879, PCI_ANY_ID, PCI_ANY_ID, 32000), +/* default entries for all Bt87x cards - it's not exported */ +/* driver_data is set to 0 to call detection */ +static struct pci_device_id snd_bt87x_default_ids[] = { + BT_DEVICE(878, PCI_ANY_ID, PCI_ANY_ID, 0), + BT_DEVICE(879, PCI_ANY_ID, PCI_ANY_ID, 0), { } }; -MODULE_DEVICE_TABLE(pci, snd_bt87x_ids); static struct pci_driver driver = { .name = "Bt87x", @@ -837,6 +916,8 @@ static struct pci_driver driver = { static int __init alsa_card_bt87x_init(void) { + if (load_all) + driver.id_table = snd_bt87x_default_ids; return pci_module_init(&driver); } diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 17fbed0f0..113208fbd 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -156,6 +156,8 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); #define CM_CHIP_MASK2 0xff000000 #define CM_CHIP_039 0x04000000 #define CM_CHIP_039_6CH 0x01000000 +#define CM_CHIP_055 0x08000000 +#define CM_CHIP_8768 0x20000000 #define CM_TDMA_INT_EN 0x00040000 #define CM_CH1_INT_EN 0x00020000 #define CM_CH0_INT_EN 0x00010000 @@ -328,6 +330,13 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); #define CM_REG_CH0_FRAME2 0x84 #define CM_REG_CH1_FRAME1 0x88 /* 0-15: count of samples at bus master; buffer size */ #define CM_REG_CH1_FRAME2 0x8C /* 16-31: count of samples at codec; fragment size */ +#define CM_REG_MISC_CTRL_8768 0x92 /* reg. name the same as 0x18 */ +#define CM_CHB3D8C 0x20 /* 7.1 channels support */ +#define CM_SPD32FMT 0x10 /* SPDIF/IN 32k */ +#define CM_ADC2SPDIF 0x08 /* ADC output to SPDIF/OUT */ +#define CM_SHAREADC 0x04 /* DAC in ADC as Center/LFE */ +#define CM_REALTCMP 0x02 /* monitor the CMPL/CMPR of ADC */ +#define CM_INVLRCK 0x01 /* invert ZVPORT's LRCK */ /* * size of i/o region @@ -458,7 +467,7 @@ struct snd_stru_cmipci { int opened[2]; /* open mode */ struct semaphore open_mutex; - int mixer_insensitive: 1; + unsigned int mixer_insensitive: 1; snd_kcontrol_t *mixer_res_ctl[CM_SAVED_MIXERS]; int mixer_res_status[CM_SAVED_MIXERS]; @@ -471,8 +480,7 @@ struct snd_stru_cmipci { snd_rawmidi_t *rmidi; #ifdef SUPPORT_JOYSTICK - struct gameport gameport; - struct resource *res_joystick; + struct gameport *gameport; #endif spinlock_t reg_lock; @@ -674,7 +682,7 @@ static int snd_cmipci_hw_free(snd_pcm_substream_t * substream) /* */ -static unsigned int hw_channels[] = {1, 2, 4, 5, 6}; +static unsigned int hw_channels[] = {1, 2, 4, 5, 6, 8}; static snd_pcm_hw_constraint_list_t hw_constraints_channels_4 = { .count = 3, .list = hw_channels, @@ -685,6 +693,11 @@ static snd_pcm_hw_constraint_list_t hw_constraints_channels_6 = { .list = hw_channels, .mask = 0, }; +static snd_pcm_hw_constraint_list_t hw_constraints_channels_8 = { + .count = 6, + .list = hw_channels, + .mask = 0, +}; static int set_dac_channels(cmipci_t *cm, cmipci_pcm_t *rec, int channels) { @@ -704,13 +717,20 @@ static int set_dac_channels(cmipci_t *cm, cmipci_pcm_t *rec, int channels) snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D5C); snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_CHB3D); } - if (channels == 6) { + if (channels >= 6) { snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C); snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_ENCENTER); } else { snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C); snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_ENCENTER); } + if (cm->chip_version == 68) { + if (channels == 8) { + snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL_8768, CM_CHB3D8C); + } else { + snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL_8768, CM_CHB3D8C); + } + } spin_unlock_irq(&cm->reg_lock); } else { @@ -1504,6 +1524,7 @@ static int snd_cmipci_playback_open(snd_pcm_substream_t *substream) if ((err = open_device_check(cm, CM_OPEN_PLAYBACK, substream)) < 0) return err; runtime->hw = snd_cmipci_playback; + runtime->hw.channels_max = cm->max_channels; snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); cm->dig_pcm_status = cm->dig_status; return 0; @@ -1518,6 +1539,10 @@ static int snd_cmipci_capture_open(snd_pcm_substream_t *substream) if ((err = open_device_check(cm, CM_OPEN_CAPTURE, substream)) < 0) return err; runtime->hw = snd_cmipci_capture; + if (cm->chip_version == 68) { // 8768 only supports 44k/48k recording + runtime->hw.rate_min = 41000; + runtime->hw.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000; + } snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); return 0; } @@ -1537,8 +1562,10 @@ static int snd_cmipci_playback2_open(snd_pcm_substream_t *substream) runtime->hw.channels_max = cm->max_channels; if (cm->max_channels == 4) snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels_4); - else + else if (cm->max_channels == 6) snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels_6); + else if (cm->max_channels == 8) + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels_8); } snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); } @@ -2108,8 +2135,8 @@ typedef struct snd_cmipci_switch_args { int reg; /* register index */ unsigned int mask; /* mask bits */ unsigned int mask_on; /* mask bits to turn on */ - int is_byte: 1; /* byte access? */ - int ac3_sensitive: 1; /* access forbidden during non-audio operation? */ + unsigned int is_byte: 1; /* byte access? */ + unsigned int ac3_sensitive: 1; /* access forbidden during non-audio operation? */ } snd_cmipci_switch_args_t; static int snd_cmipci_uswitch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) @@ -2346,6 +2373,11 @@ static int __devinit snd_cmipci_mixer_new(cmipci_t *cm, int pcm_spdif_device) spin_unlock_irq(&cm->reg_lock); for (idx = 0; idx < ARRAY_SIZE(snd_cmipci_mixers); idx++) { + if (cm->chip_version == 68) { // 8768 has no PCM volume + if (!strcmp(snd_cmipci_mixers[idx].name, + "PCM Playback Volume")) + continue; + } if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cmipci_mixers[idx], cm))) < 0) return err; } @@ -2496,32 +2528,98 @@ static void __devinit query_chip(cmipci_t *cm) } } else { /* check reg 0Ch, bit 26 */ - if (detect & CM_CHIP_039) { + if (detect & CM_CHIP_8768) { + cm->chip_version = 68; + cm->max_channels = 8; + cm->can_ac3_hw = 1; + cm->has_dual_dac = 1; + cm->can_multi_ch = 1; + } else if (detect & CM_CHIP_055) { + cm->chip_version = 55; + cm->max_channels = 6; + cm->can_ac3_hw = 1; + cm->has_dual_dac = 1; + cm->can_multi_ch = 1; + } else if (detect & CM_CHIP_039) { cm->chip_version = 39; - if (detect & CM_CHIP_039_6CH) - cm->max_channels = 6; + if (detect & CM_CHIP_039_6CH) /* 4 or 6 channels */ + cm->max_channels = 6; else cm->max_channels = 4; cm->can_ac3_hw = 1; cm->has_dual_dac = 1; cm->can_multi_ch = 1; } else { - cm->chip_version = 55; /* 4 or 6 channels */ - cm->max_channels = 6; - cm->can_ac3_hw = 1; - cm->has_dual_dac = 1; - cm->can_multi_ch = 1; + printk(KERN_ERR "chip %x version not supported\n", detect); } } +} - /* added -MCx suffix for chip supporting multi-channels */ - if (cm->can_multi_ch) - sprintf(cm->card->driver + strlen(cm->card->driver), - "-MC%d", cm->max_channels); - else if (cm->can_ac3_sw) - strcpy(cm->card->driver + strlen(cm->card->driver), "-SWIEC"); +#ifdef SUPPORT_JOYSTICK +static int __devinit snd_cmipci_create_gameport(cmipci_t *cm, int dev) +{ + static int ports[] = { 0x201, 0x200, 0 }; /* FIXME: majority is 0x201? */ + struct gameport *gp; + struct resource *r = NULL; + int i, io_port = 0; + + if (joystick_port[dev] == 0) + return -ENODEV; + + if (joystick_port[dev] == 1) { /* auto-detect */ + for (i = 0; ports[i]; i++) { + io_port = ports[i]; + r = request_region(io_port, 1, "CMIPCI gameport"); + if (r) + break; + } + } else { + io_port = joystick_port[dev]; + r = request_region(io_port, 1, "CMIPCI gameport"); + } + + if (!r) { + printk(KERN_WARNING "cmipci: cannot reserve joystick ports\n"); + return -EBUSY; + } + + cm->gameport = gp = gameport_allocate_port(); + if (!gp) { + printk(KERN_ERR "cmipci: cannot allocate memory for gameport\n"); + release_resource(r); + kfree_nocheck(r); + return -ENOMEM; + } + gameport_set_name(gp, "C-Media Gameport"); + gameport_set_phys(gp, "pci%s/gameport0", pci_name(cm->pci)); + gameport_set_dev_parent(gp, &cm->pci->dev); + gp->io = io_port; + gameport_set_port_data(gp, r); + + snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN); + + gameport_register_port(cm->gameport); + + return 0; } +static void snd_cmipci_free_gameport(cmipci_t *cm) +{ + if (cm->gameport) { + struct resource *r = gameport_get_port_data(cm->gameport); + + gameport_unregister_port(cm->gameport); + cm->gameport = NULL; + + snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN); + release_resource(r); + kfree_nocheck(r); + } +} +#else +static inline int snd_cmipci_create_gameport(cmipci_t *cm, int dev) { return -ENOSYS; } +static inline void snd_cmipci_free_gameport(cmipci_t *cm) { } +#endif static int snd_cmipci_free(cmipci_t *cm) { @@ -2541,14 +2639,8 @@ static int snd_cmipci_free(cmipci_t *cm) free_irq(cm->irq, (void *)cm); } -#ifdef SUPPORT_JOYSTICK - if (cm->res_joystick) { - gameport_unregister_port(&cm->gameport); - snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN); - release_resource(cm->res_joystick); - kfree_nocheck(cm->res_joystick); - } -#endif + + snd_cmipci_free_gameport(cm); pci_release_regions(cm->pci); pci_disable_device(cm->pci); kfree(cm); @@ -2623,7 +2715,15 @@ static int __devinit snd_cmipci_create(snd_card_t *card, struct pci_dev *pci, cm->max_channels = 2; cm->do_soft_ac3 = soft_ac3[dev]; - query_chip(cm); + if (pci->device != PCI_DEVICE_ID_CMEDIA_CM8338A && + pci->device != PCI_DEVICE_ID_CMEDIA_CM8338B) + query_chip(cm); + /* added -MCx suffix for chip supporting multi-channels */ + if (cm->can_multi_ch) + sprintf(cm->card->driver + strlen(cm->card->driver), + "-MC%d", cm->max_channels); + else if (cm->can_ac3_sw) + strcpy(cm->card->driver + strlen(cm->card->driver), "-SWIEC"); cm->dig_status = SNDRV_PCM_DEFAULT_CON_SPDIF; cm->dig_pcm_status = SNDRV_PCM_DEFAULT_CON_SPDIF; @@ -2757,31 +2857,9 @@ static int __devinit snd_cmipci_create(snd_card_t *card, struct pci_dev *pci, snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_SPDIF48K|CM_SPDF_AC97); #endif /* USE_VAR48KRATE */ -#ifdef SUPPORT_JOYSTICK - if (joystick_port[dev] > 0) { - if (joystick_port[dev] == 1) { /* auto-detect */ - static int ports[] = { 0x201, 0x200, 0 }; /* FIXME: majority is 0x201? */ - int i; - for (i = 0; ports[i]; i++) { - joystick_port[dev] = ports[i]; - cm->res_joystick = request_region(ports[i], 1, "CMIPCI gameport"); - if (cm->res_joystick) - break; - } - } else { - cm->res_joystick = request_region(joystick_port[dev], 1, "CMIPCI gameport"); - } - } - if (cm->res_joystick) { - cm->gameport.io = joystick_port[dev]; - snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN); - gameport_register_port(&cm->gameport); - } else { - if (joystick_port[dev] > 0) - printk(KERN_WARNING "cmipci: cannot reserve joystick ports\n"); + if (snd_cmipci_create_gameport(cm, dev) < 0) snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN); - } -#endif + snd_card_set_dev(card, &pci->dev); *rcmipci = cm; diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index bf4f1180c..d7e06b3ca 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -495,7 +495,7 @@ struct snd_cs4281 { unsigned int midcr; unsigned int uartm; - struct snd_cs4281_gameport *gameport; + struct gameport *gameport; #ifdef CONFIG_PM u32 suspend_regs[SUSPEND_REGISTERS]; @@ -1238,38 +1238,29 @@ static void __devinit snd_cs4281_proc_init(cs4281_t * chip) #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) -typedef struct snd_cs4281_gameport { - struct gameport info; - cs4281_t *chip; -} cs4281_gameport_t; - static void snd_cs4281_gameport_trigger(struct gameport *gameport) { - cs4281_gameport_t *gp = (cs4281_gameport_t *)gameport; - cs4281_t *chip; - snd_assert(gp, return); - chip = gp->chip; + cs4281_t *chip = gameport_get_port_data(gameport); + + snd_assert(chip, return); snd_cs4281_pokeBA0(chip, BA0_JSPT, 0xff); } static unsigned char snd_cs4281_gameport_read(struct gameport *gameport) { - cs4281_gameport_t *gp = (cs4281_gameport_t *)gameport; - cs4281_t *chip; - snd_assert(gp, return 0); - chip = gp->chip; + cs4281_t *chip = gameport_get_port_data(gameport); + + snd_assert(chip, return 0); return snd_cs4281_peekBA0(chip, BA0_JSPT); } #ifdef COOKED_MODE static int snd_cs4281_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons) { - cs4281_gameport_t *gp = (cs4281_gameport_t *)gameport; - cs4281_t *chip; + cs4281_t *chip = gameport_get_port_data(gameport); unsigned js1, js2, jst; - snd_assert(gp, return 0); - chip = gp->chip; + snd_assert(chip, return 0); js1 = snd_cs4281_peekBA0(chip, BA0_JSC1); js2 = snd_cs4281_peekBA0(chip, BA0_JSC2); @@ -1282,10 +1273,12 @@ static int snd_cs4281_gameport_cooked_read(struct gameport *gameport, int *axes, axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF; axes[3] = ((js2 & JSC2_X2V_MASK) >> JSC2_X2V_SHIFT) & 0xFFFF; - for(jst=0;jst<4;++jst) - if(axes[jst]==0xFFFF) axes[jst] = -1; + for (jst = 0; jst < 4; ++jst) + if (axes[jst] == 0xFFFF) axes[jst] = -1; return 0; } +#else +#define snd_cs4281_gameport_cooked_read NULL #endif static int snd_cs4281_gameport_open(struct gameport *gameport, int mode) @@ -1303,31 +1296,43 @@ static int snd_cs4281_gameport_open(struct gameport *gameport, int mode) return 0; } -static void __devinit snd_cs4281_gameport(cs4281_t *chip) +static int __devinit snd_cs4281_create_gameport(cs4281_t *chip) { - cs4281_gameport_t *gp; - gp = kmalloc(sizeof(*gp), GFP_KERNEL); - if (! gp) { - snd_printk(KERN_ERR "cannot allocate gameport area\n"); - return; + struct gameport *gp; + + chip->gameport = gp = gameport_allocate_port(); + if (!gp) { + printk(KERN_ERR "cs4281: cannot allocate memory for gameport\n"); + return -ENOMEM; } - memset(gp, 0, sizeof(*gp)); - gp->info.open = snd_cs4281_gameport_open; - gp->info.read = snd_cs4281_gameport_read; - gp->info.trigger = snd_cs4281_gameport_trigger; -#ifdef COOKED_MODE - gp->info.cooked_read = snd_cs4281_gameport_cooked_read; -#endif - gp->chip = chip; - chip->gameport = gp; + + gameport_set_name(gp, "CS4281 Gameport"); + gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci)); + gameport_set_dev_parent(gp, &chip->pci->dev); + gp->open = snd_cs4281_gameport_open; + gp->read = snd_cs4281_gameport_read; + gp->trigger = snd_cs4281_gameport_trigger; + gp->cooked_read = snd_cs4281_gameport_cooked_read; + gameport_set_port_data(gp, chip); snd_cs4281_pokeBA0(chip, BA0_JSIO, 0xFF); // ? snd_cs4281_pokeBA0(chip, BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW); - gameport_register_port(&gp->info); + + gameport_register_port(gp); + + return 0; } +static void snd_cs4281_free_gameport(cs4281_t *chip) +{ + if (chip->gameport) { + gameport_unregister_port(chip->gameport); + chip->gameport = NULL; + } +} #else -#define snd_cs4281_gameport(chip) /*NOP*/ +static inline int snd_cs4281_create_gameport(cs4281_t *chip) { return -ENOSYS; } +static inline void snd_cs4281_free_gameport(cs4281_t *chip) { } #endif /* CONFIG_GAMEPORT || (MODULE && CONFIG_GAMEPORT_MODULE) */ @@ -1337,12 +1342,8 @@ static void __devinit snd_cs4281_gameport(cs4281_t *chip) static int snd_cs4281_free(cs4281_t *chip) { -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) - if (chip->gameport) { - gameport_unregister_port(&chip->gameport->info); - kfree(chip->gameport); - } -#endif + snd_cs4281_free_gameport(chip); + if (chip->irq >= 0) synchronize_irq(chip->irq); @@ -1376,8 +1377,8 @@ static int snd_cs4281_dev_free(snd_device_t *device) static int snd_cs4281_chip_init(cs4281_t *chip); /* defined below */ #ifdef CONFIG_PM -static int cs4281_suspend(snd_card_t *card, unsigned int state); -static int cs4281_resume(snd_card_t *card, unsigned int state); +static int cs4281_suspend(snd_card_t *card, pm_message_t state); +static int cs4281_resume(snd_card_t *card); #endif static int __devinit snd_cs4281_create(snd_card_t * card, @@ -1893,9 +1894,7 @@ static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *r c = snd_cs4281_peekBA0(chip, BA0_MIDRP); if ((chip->midcr & BA0_MIDCR_RIE) == 0) continue; - spin_unlock(&chip->reg_lock); snd_rawmidi_receive(chip->midi_input, &c, 1); - spin_lock(&chip->reg_lock); } while ((snd_cs4281_peekBA0(chip, BA0_MIDSR) & BA0_MIDSR_TBF) == 0) { if ((chip->midcr & BA0_MIDCR_TIE) == 0) @@ -1990,7 +1989,7 @@ static int __devinit snd_cs4281_probe(struct pci_dev *pci, snd_card_free(card); return err; } - snd_cs4281_gameport(chip); + snd_cs4281_create_gameport(chip); strcpy(card->driver, "CS4281"); strcpy(card->shortname, "Cirrus Logic CS4281"); sprintf(card->longname, "%s at 0x%lx, irq %d", @@ -2037,7 +2036,7 @@ static int saved_regs[SUSPEND_REGISTERS] = { #define CLKCR1_CKRA 0x00010000L -static int cs4281_suspend(snd_card_t *card, unsigned int state) +static int cs4281_suspend(snd_card_t *card, pm_message_t state) { cs4281_t *chip = card->pm_private_data; u32 ulCLK; @@ -2079,11 +2078,10 @@ static int cs4281_suspend(snd_card_t *card, unsigned int state) snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK); pci_disable_device(chip->pci); - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } -static int cs4281_resume(snd_card_t *card, unsigned int state) +static int cs4281_resume(snd_card_t *card) { cs4281_t *chip = card->pm_private_data; unsigned int i; @@ -2112,7 +2110,6 @@ static int cs4281_resume(snd_card_t *card, unsigned int state) ulCLK &= ~CLKCR1_CKRA; snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; } #endif /* CONFIG_PM */ diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index c3312e169..5f2ffb7ef 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -68,6 +68,20 @@ static void amp_voyetra(cs46xx_t *chip, int change); +#ifdef CONFIG_SND_CS46XX_NEW_DSP +static snd_pcm_ops_t snd_cs46xx_playback_rear_ops; +static snd_pcm_ops_t snd_cs46xx_playback_indirect_rear_ops; +static snd_pcm_ops_t snd_cs46xx_playback_clfe_ops; +static snd_pcm_ops_t snd_cs46xx_playback_indirect_clfe_ops; +static snd_pcm_ops_t snd_cs46xx_playback_iec958_ops; +static snd_pcm_ops_t snd_cs46xx_playback_indirect_iec958_ops; +#endif + +static snd_pcm_ops_t snd_cs46xx_playback_ops; +static snd_pcm_ops_t snd_cs46xx_playback_indirect_ops; +static snd_pcm_ops_t snd_cs46xx_capture_ops; +static snd_pcm_ops_t snd_cs46xx_capture_indirect_ops; + static unsigned short snd_cs46xx_codec_read(cs46xx_t *chip, unsigned short reg, int codec_index) @@ -99,7 +113,7 @@ static unsigned short snd_cs46xx_codec_read(cs46xx_t *chip, if ((tmp & ACCTL_VFRM) == 0) { snd_printk(KERN_WARNING "cs46xx: ACCTL_VFRM not set 0x%x\n",tmp); snd_cs46xx_pokeBA0(chip, BA0_ACCTL, (tmp & (~ACCTL_ESYN)) | ACCTL_VFRM ); - mdelay(50); + msleep(50); tmp = snd_cs46xx_peekBA0(chip, BA0_ACCTL + offset); snd_cs46xx_pokeBA0(chip, BA0_ACCTL, tmp | ACCTL_ESYN | ACCTL_VFRM ); @@ -1203,9 +1217,7 @@ static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id, struct pt_regs *r c = snd_cs46xx_peekBA0(chip, BA0_MIDRP); if ((chip->midcr & MIDCR_RIE) == 0) continue; - spin_unlock(&chip->reg_lock); snd_rawmidi_receive(chip->midi_input, &c, 1); - spin_lock(&chip->reg_lock); } while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_TBF) == 0) { if ((chip->midcr & MIDCR_TIE) == 0) @@ -1446,7 +1458,7 @@ static int snd_cs46xx_capture_close(snd_pcm_substream_t * substream) } #ifdef CONFIG_SND_CS46XX_NEW_DSP -snd_pcm_ops_t snd_cs46xx_playback_rear_ops = { +static snd_pcm_ops_t snd_cs46xx_playback_rear_ops = { .open = snd_cs46xx_playback_open_rear, .close = snd_cs46xx_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1457,7 +1469,7 @@ snd_pcm_ops_t snd_cs46xx_playback_rear_ops = { .pointer = snd_cs46xx_playback_direct_pointer, }; -snd_pcm_ops_t snd_cs46xx_playback_indirect_rear_ops = { +static snd_pcm_ops_t snd_cs46xx_playback_indirect_rear_ops = { .open = snd_cs46xx_playback_open_rear, .close = snd_cs46xx_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1469,7 +1481,7 @@ snd_pcm_ops_t snd_cs46xx_playback_indirect_rear_ops = { .ack = snd_cs46xx_playback_transfer, }; -snd_pcm_ops_t snd_cs46xx_playback_clfe_ops = { +static snd_pcm_ops_t snd_cs46xx_playback_clfe_ops = { .open = snd_cs46xx_playback_open_clfe, .close = snd_cs46xx_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1480,7 +1492,7 @@ snd_pcm_ops_t snd_cs46xx_playback_clfe_ops = { .pointer = snd_cs46xx_playback_direct_pointer, }; -snd_pcm_ops_t snd_cs46xx_playback_indirect_clfe_ops = { +static snd_pcm_ops_t snd_cs46xx_playback_indirect_clfe_ops = { .open = snd_cs46xx_playback_open_clfe, .close = snd_cs46xx_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1492,7 +1504,7 @@ snd_pcm_ops_t snd_cs46xx_playback_indirect_clfe_ops = { .ack = snd_cs46xx_playback_transfer, }; -snd_pcm_ops_t snd_cs46xx_playback_iec958_ops = { +static snd_pcm_ops_t snd_cs46xx_playback_iec958_ops = { .open = snd_cs46xx_playback_open_iec958, .close = snd_cs46xx_playback_close_iec958, .ioctl = snd_pcm_lib_ioctl, @@ -1503,7 +1515,7 @@ snd_pcm_ops_t snd_cs46xx_playback_iec958_ops = { .pointer = snd_cs46xx_playback_direct_pointer, }; -snd_pcm_ops_t snd_cs46xx_playback_indirect_iec958_ops = { +static snd_pcm_ops_t snd_cs46xx_playback_indirect_iec958_ops = { .open = snd_cs46xx_playback_open_iec958, .close = snd_cs46xx_playback_close_iec958, .ioctl = snd_pcm_lib_ioctl, @@ -1517,7 +1529,7 @@ snd_pcm_ops_t snd_cs46xx_playback_indirect_iec958_ops = { #endif -snd_pcm_ops_t snd_cs46xx_playback_ops = { +static snd_pcm_ops_t snd_cs46xx_playback_ops = { .open = snd_cs46xx_playback_open, .close = snd_cs46xx_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1528,7 +1540,7 @@ snd_pcm_ops_t snd_cs46xx_playback_ops = { .pointer = snd_cs46xx_playback_direct_pointer, }; -snd_pcm_ops_t snd_cs46xx_playback_indirect_ops = { +static snd_pcm_ops_t snd_cs46xx_playback_indirect_ops = { .open = snd_cs46xx_playback_open, .close = snd_cs46xx_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1540,7 +1552,7 @@ snd_pcm_ops_t snd_cs46xx_playback_indirect_ops = { .ack = snd_cs46xx_playback_transfer, }; -snd_pcm_ops_t snd_cs46xx_capture_ops = { +static snd_pcm_ops_t snd_cs46xx_capture_ops = { .open = snd_cs46xx_capture_open, .close = snd_cs46xx_capture_close, .ioctl = snd_pcm_lib_ioctl, @@ -1551,7 +1563,7 @@ snd_pcm_ops_t snd_cs46xx_capture_ops = { .pointer = snd_cs46xx_capture_direct_pointer, }; -snd_pcm_ops_t snd_cs46xx_capture_indirect_ops = { +static snd_pcm_ops_t snd_cs46xx_capture_indirect_ops = { .open = snd_cs46xx_capture_open, .close = snd_cs46xx_capture_close, .ioctl = snd_pcm_lib_ioctl, @@ -2304,6 +2316,36 @@ static snd_kcontrol_new_t snd_cs46xx_controls[] __devinitdata = { #endif }; +#ifdef CONFIG_SND_CS46XX_NEW_DSP +/* set primary cs4294 codec into Extended Audio Mode */ +static int snd_cs46xx_front_dup_get(snd_kcontrol_t *kcontrol, + snd_ctl_elem_value_t *ucontrol) +{ + cs46xx_t *chip = snd_kcontrol_chip(kcontrol); + unsigned short val; + val = snd_ac97_read(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX], AC97_CSR_ACMODE); + ucontrol->value.integer.value[0] = (val & 0x200) ? 0 : 1; + return 0; +} + +static int snd_cs46xx_front_dup_put(snd_kcontrol_t *kcontrol, + snd_ctl_elem_value_t *ucontrol) +{ + cs46xx_t *chip = snd_kcontrol_chip(kcontrol); + return snd_ac97_update_bits(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX], + AC97_CSR_ACMODE, 0x200, + ucontrol->value.integer.value[0] ? 0 : 0x200); +} + +static snd_kcontrol_new_t snd_cs46xx_front_dup_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Duplicate Front", + .info = snd_mixer_boolean_info, + .get = snd_cs46xx_front_dup_get, + .put = snd_cs46xx_front_dup_put, +}; +#endif + #ifdef CONFIG_SND_CS46XX_NEW_DSP /* Only available on the Hercules Game Theater XP soundcard */ static snd_kcontrol_new_t snd_hercules_controls[] __devinitdata = { @@ -2451,10 +2493,11 @@ int __devinit snd_cs46xx_mixer(cs46xx_t *chip) if (chip->nr_ac97_codecs == 1) { unsigned int id2 = chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]->id & 0xffff; if (id2 == 0x592b || id2 == 0x592d) { - /* set primary cs4294 codec into Extended Audio Mode */ - snd_printdd("setting EAM bit on cs4294 CODEC\n"); - snd_cs46xx_codec_write(chip, AC97_CSR_ACMODE, 0x200, - CS46XX_PRIMARY_CODEC_INDEX); + err = snd_ctl_add(card, snd_ctl_new1(&snd_cs46xx_front_dup_ctl, chip)); + if (err < 0) + return err; + snd_ac97_write_cache(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX], + AC97_CSR_ACMODE, 0x200); } } /* do soundcard specific mixer setup */ @@ -2645,37 +2688,28 @@ int __devinit snd_cs46xx_midi(cs46xx_t *chip, int device, snd_rawmidi_t **rrawmi #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) -typedef struct snd_cs46xx_gameport { - struct gameport info; - cs46xx_t *chip; -} cs46xx_gameport_t; - static void snd_cs46xx_gameport_trigger(struct gameport *gameport) { - cs46xx_gameport_t *gp = (cs46xx_gameport_t *)gameport; - cs46xx_t *chip; - snd_assert(gp, return); - chip = gp->chip; + cs46xx_t *chip = gameport_get_port_data(gameport); + + snd_assert(chip, return); snd_cs46xx_pokeBA0(chip, BA0_JSPT, 0xFF); //outb(gameport->io, 0xFF); } static unsigned char snd_cs46xx_gameport_read(struct gameport *gameport) { - cs46xx_gameport_t *gp = (cs46xx_gameport_t *)gameport; - cs46xx_t *chip; - snd_assert(gp, return 0); - chip = gp->chip; + cs46xx_t *chip = gameport_get_port_data(gameport); + + snd_assert(chip, return 0); return snd_cs46xx_peekBA0(chip, BA0_JSPT); //inb(gameport->io); } static int snd_cs46xx_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons) { - cs46xx_gameport_t *gp = (cs46xx_gameport_t *)gameport; - cs46xx_t *chip; + cs46xx_t *chip = gameport_get_port_data(gameport); unsigned js1, js2, jst; - - snd_assert(gp, return 0); - chip = gp->chip; + + snd_assert(chip, return 0); js1 = snd_cs46xx_peekBA0(chip, BA0_JSC1); js2 = snd_cs46xx_peekBA0(chip, BA0_JSC2); @@ -2706,33 +2740,44 @@ static int snd_cs46xx_gameport_open(struct gameport *gameport, int mode) return 0; } -void __devinit snd_cs46xx_gameport(cs46xx_t *chip) +int __devinit snd_cs46xx_gameport(cs46xx_t *chip) { - cs46xx_gameport_t *gp; - gp = kmalloc(sizeof(*gp), GFP_KERNEL); - if (! gp) { - snd_printk("cannot allocate gameport area\n"); - return; + struct gameport *gp; + + chip->gameport = gp = gameport_allocate_port(); + if (!gp) { + printk(KERN_ERR "cs46xx: cannot allocate memory for gameport\n"); + return -ENOMEM; } - memset(gp, 0, sizeof(*gp)); - gp->info.open = snd_cs46xx_gameport_open; - gp->info.read = snd_cs46xx_gameport_read; - gp->info.trigger = snd_cs46xx_gameport_trigger; - gp->info.cooked_read = snd_cs46xx_gameport_cooked_read; - gp->chip = chip; - chip->gameport = gp; + + gameport_set_name(gp, "CS46xx Gameport"); + gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci)); + gameport_set_dev_parent(gp, &chip->pci->dev); + gameport_set_port_data(gp, chip); + + gp->open = snd_cs46xx_gameport_open; + gp->read = snd_cs46xx_gameport_read; + gp->trigger = snd_cs46xx_gameport_trigger; + gp->cooked_read = snd_cs46xx_gameport_cooked_read; snd_cs46xx_pokeBA0(chip, BA0_JSIO, 0xFF); // ? snd_cs46xx_pokeBA0(chip, BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW); - gameport_register_port(&gp->info); -} -#else + gameport_register_port(gp); -void __devinit snd_cs46xx_gameport(cs46xx_t *chip) -{ + return 0; } +static inline void snd_cs46xx_remove_gameport(cs46xx_t *chip) +{ + if (chip->gameport) { + gameport_unregister_port(chip->gameport); + chip->gameport = NULL; + } +} +#else +int __devinit snd_cs46xx_gameport(cs46xx_t *chip) { return -ENOSYS; } +static inline void snd_cs46xx_remove_gameport(cs46xx_t *chip) { } #endif /* CONFIG_GAMEPORT */ /* @@ -2848,12 +2893,7 @@ static int snd_cs46xx_free(cs46xx_t *chip) if (chip->active_ctrl) chip->active_ctrl(chip, 1); -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) - if (chip->gameport) { - gameport_unregister_port(&chip->gameport->info); - kfree(chip->gameport); - } -#endif + snd_cs46xx_remove_gameport(chip); if (chip->amplifier_ctrl) chip->amplifier_ctrl(chip, -chip->amplifier); /* force to off */ @@ -3659,7 +3699,7 @@ static struct cs_card_type __devinitdata cards[] = { * APM support */ #ifdef CONFIG_PM -static int snd_cs46xx_suspend(snd_card_t *card, unsigned int state) +static int snd_cs46xx_suspend(snd_card_t *card, pm_message_t state) { cs46xx_t *chip = card->pm_private_data; int amp_saved; @@ -3680,11 +3720,10 @@ static int snd_cs46xx_suspend(snd_card_t *card, unsigned int state) chip->active_ctrl(chip, -chip->amplifier); chip->amplifier = amp_saved; /* restore the status */ pci_disable_device(chip->pci); - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } -static int snd_cs46xx_resume(snd_card_t *card, unsigned int state) +static int snd_cs46xx_resume(snd_card_t *card) { cs46xx_t *chip = card->pm_private_data; int amp_saved; @@ -3717,7 +3756,6 @@ static int snd_cs46xx_resume(snd_card_t *card, unsigned int state) else chip->active_ctrl(chip, -1); /* disable CLKRUN */ chip->amplifier = amp_saved; - snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; } #endif /* CONFIG_PM */ diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c index acd0db847..92849e134 100644 --- a/sound/pci/cs46xx/dsp_spos_scb_lib.c +++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c @@ -342,7 +342,7 @@ _dsp_create_generic_scb (cs46xx_t *chip,char * name, u32 * scb_data,u32 dest, return scb; } -dsp_scb_descriptor_t * +static dsp_scb_descriptor_t * cs46xx_dsp_create_generic_scb (cs46xx_t *chip,char * name, u32 * scb_data,u32 dest, char * task_entry_name, dsp_scb_descriptor_t * parent_scb, @@ -481,7 +481,7 @@ cs46xx_dsp_create_codec_in_scb(cs46xx_t * chip,char * codec_name, } -dsp_scb_descriptor_t * +static dsp_scb_descriptor_t * cs46xx_dsp_create_pcm_reader_scb(cs46xx_t * chip,char * scb_name, u16 sample_buffer_addr,u32 dest, int virtual_channel, u32 playback_hw_addr, @@ -687,6 +687,7 @@ cs46xx_dsp_create_src_task_scb(cs46xx_t * chip,char * scb_name, return scb; } +#if 0 /* not used */ dsp_scb_descriptor_t * cs46xx_dsp_create_filter_scb(cs46xx_t * chip,char * scb_name, u16 buffer_addr,u32 dest, @@ -735,6 +736,7 @@ cs46xx_dsp_create_filter_scb(cs46xx_t * chip,char * scb_name, return scb; } +#endif /* not used */ dsp_scb_descriptor_t * cs46xx_dsp_create_mix_only_scb(cs46xx_t * chip,char * scb_name, @@ -874,7 +876,7 @@ cs46xx_dsp_create_vari_decimate_scb(cs46xx_t * chip,char * scb_name, } -dsp_scb_descriptor_t * +static dsp_scb_descriptor_t * cs46xx_dsp_create_pcm_serial_input_scb(cs46xx_t * chip,char * scb_name,u32 dest, dsp_scb_descriptor_t * input_scb, dsp_scb_descriptor_t * parent_scb, @@ -917,7 +919,7 @@ cs46xx_dsp_create_pcm_serial_input_scb(cs46xx_t * chip,char * scb_name,u32 dest, } -dsp_scb_descriptor_t * +static dsp_scb_descriptor_t * cs46xx_dsp_create_asynch_fg_tx_scb(cs46xx_t * chip,char * scb_name,u32 dest, u16 hfg_scb_address, u16 asynch_buffer_address, @@ -1013,6 +1015,7 @@ cs46xx_dsp_create_asynch_fg_rx_scb(cs46xx_t * chip,char * scb_name,u32 dest, } +#if 0 /* not used */ dsp_scb_descriptor_t * cs46xx_dsp_create_output_snoop_scb(cs46xx_t * chip,char * scb_name,u32 dest, u16 snoop_buffer_address, @@ -1052,6 +1055,7 @@ cs46xx_dsp_create_output_snoop_scb(cs46xx_t * chip,char * scb_name,u32 dest, scb_child_type); return scb; } +#endif /* not used */ dsp_scb_descriptor_t * diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 2f22d03a9..6446afe19 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c @@ -2,6 +2,9 @@ * The driver for the EMU10K1 (SB Live!) based soundcards * Copyright (c) by Jaroslav Kysela <perex@suse.cz> * + * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk> + * Added support for Audigy 2 Value. + * * * 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,6 +20,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * */ #include <sound/driver.h> @@ -68,12 +72,27 @@ MODULE_PARM_DESC(max_buffer_size, "Maximum sample buffer size in MB."); module_param_array(enable_ir, bool, NULL, 0444); MODULE_PARM_DESC(enable_ir, "Enable IR."); +/* + * Class 0401: 1102:0008 (rev 00) Subsystem: 1102:1001 -> Audigy2 Value Model:SB0400 + */ static struct pci_device_id snd_emu10k1_ids[] = { { 0x1102, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* EMU10K1 */ { 0x1102, 0x0004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, /* Audigy */ + { 0x1102, 0x0008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, /* Audigy 2 Value SB0400 */ { 0, } }; +/* + * Audigy 2 Value notes: + * A_IOCFG Input (GPIO) + * 0x400 = Front analog jack plugged in. (Green socket) + * 0x1000 = Read analog jack plugged in. (Black socket) + * 0x2000 = Center/LFE analog jack plugged in. (Orange socket) + * A_IOCFG Output (GPIO) + * 0x60 = Sound out of front Left. + * Win sets it to 0xXX61 + */ + MODULE_DEVICE_TABLE(pci, snd_emu10k1_ids); static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci, @@ -119,11 +138,35 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci, if ((err = snd_emu10k1_pcm_efx(emu, 2, NULL)) < 0) { snd_card_free(card); return err; - } + } + /* This stores the periods table. */ + if (emu->audigy && emu->revision == 4) { /* P16V */ + if(snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 1024, &emu->p16v_buffer) < 0) { + snd_p16v_free(emu); + return -ENOMEM; + } + } + if ((err = snd_emu10k1_mixer(emu)) < 0) { snd_card_free(card); return err; } + + if ((err = snd_emu10k1_timer(emu, 0)) < 0) { + snd_card_free(card); + return err; + } + + if ((err = snd_emu10k1_pcm_multi(emu, 3, NULL)) < 0) { + snd_card_free(card); + return err; + } + if (emu->audigy && emu->revision == 4) { /* P16V */ + if ((err = snd_p16v_pcm(emu, 4, NULL)) < 0) { + snd_card_free(card); + return err; + } + } if (emu->audigy) { if ((err = snd_emu10k1_audigy_midi(emu)) < 0) { snd_card_free(card); @@ -155,20 +198,11 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci, } #endif - if (emu->audigy && (emu->revision == 4) ) { - strcpy(card->driver, "Audigy2"); - strcpy(card->shortname, "Sound Blaster Audigy2"); - } else if (emu->audigy) { - strcpy(card->driver, "Audigy"); - strcpy(card->shortname, "Sound Blaster Audigy"); - } else if (emu->APS) { - strcpy(card->driver, "E-mu APS"); - strcpy(card->shortname, "E-mu APS"); - } else { - strcpy(card->driver, "EMU10K1"); - strcpy(card->shortname, "Sound Blaster Live!"); - } - sprintf(card->longname, "%s (rev.%d) at 0x%lx, irq %i", card->shortname, emu->revision, emu->port, emu->irq); + strcpy(card->driver, emu->card_capabilities->driver); + strcpy(card->shortname, emu->card_capabilities->name); + snprintf(card->longname, sizeof(card->longname), + "%s (rev.%d, serial:0x%x) at 0x%lx, irq %i", + card->shortname, emu->revision, emu->serial, emu->port, emu->irq); if ((err = snd_card_register(card)) < 0) { snd_card_free(card); diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 45f3ceda5..c3c96f9f2 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -3,6 +3,10 @@ * Creative Labs, Inc. * Routines for control of EMU10K1 chips * + * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk> + * Added support for Audigy 2 Value. + * + * * BUGS: * -- * @@ -35,6 +39,7 @@ #include <sound/core.h> #include <sound/emu10k1.h> +#include "p16v.h" #if 0 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Creative Labs, Inc."); @@ -174,16 +179,48 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir) tmp &= 0xfffff1ff; tmp |= (0x2<<9); snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp); + + /* Setup SRCSel (Enable Spdif,I2S SRCMulti) */ + snd_emu10k1_ptr20_write(emu, SRCSel, 0, 0x14); + /* Setup SRCMulti Input Audio Enable */ + /* Use 0xFFFFFFFF to enable P16V sounds. */ + snd_emu10k1_ptr20_write(emu, SRCMULTI_ENABLE, 0, 0xFFFFFFFF); + + /* Enabled Phased (8-channel) P16V playback */ + outl(0x0201, emu->port + HCFG2); + /* Set playback routing. */ + snd_emu10k1_ptr_write(emu, CAPTURE_P16V_SOURCE, 0, 78e4); + } + if (emu->audigy && (emu->serial == 0x10011102) ) { /* audigy2 Value */ + /* Hacks for Alice3 to work independent of haP16V driver */ + u32 tmp; + + snd_printk(KERN_ERR "Audigy2 value:Special config.\n"); + //Setup SRCMulti_I2S SamplingRate + tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); + tmp &= 0xfffff1ff; + tmp |= (0x2<<9); + snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp); /* Setup SRCSel (Enable Spdif,I2S SRCMulti) */ outl(0x600000, emu->port + 0x20); outl(0x14, emu->port + 0x24); /* Setup SRCMulti Input Audio Enable */ - outl(0x6E0000, emu->port + 0x20); - outl(0xFF00FF00, emu->port + 0x24); + outl(0x7b0000, emu->port + 0x20); + outl(0xFF000000, emu->port + 0x24); + + /* Setup SPDIF Out Audio Enable */ + /* The Audigy 2 Value has a separate SPDIF out, + * so no need for a mixer switch + */ + outl(0x7a0000, emu->port + 0x20); + outl(0xFF000000, emu->port + 0x24); + tmp = inl(emu->port + A_IOCFG) & ~0x8; /* Clear bit 3 */ + outl(tmp, emu->port + A_IOCFG); } + /* * Clear page with silence & setup all pointers to this page */ @@ -267,6 +304,9 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir) * This has to be done after init ALice3 I2SOut beyond 48KHz. * So, sequence is important. */ outl(inl(emu->port + A_IOCFG) | 0x0040, emu->port + A_IOCFG); + } else if (emu->serial == 0x10011102) { /* audigy2 value */ + /* Unmute Analog now. */ + outl(inl(emu->port + A_IOCFG) | 0x0060, emu->port + A_IOCFG); } else { /* Disable routing from AC97 line out to Front speakers */ outl(inl(emu->port + A_IOCFG) | 0x0080, emu->port + A_IOCFG); @@ -553,15 +593,15 @@ static int snd_emu10k1_free(emu10k1_t *emu) snd_dma_free_pages(&emu->silent_page); if (emu->ptb_pages.area) snd_dma_free_pages(&emu->ptb_pages); - if (emu->page_ptr_table) - vfree(emu->page_ptr_table); - if (emu->page_addr_table) - vfree(emu->page_addr_table); + vfree(emu->page_ptr_table); + vfree(emu->page_addr_table); if (emu->irq >= 0) free_irq(emu->irq, (void *)emu); if (emu->port) pci_release_regions(emu->pci); pci_disable_device(emu->pci); + if (emu->audigy && emu->revision == 4) /* P16V */ + snd_p16v_free(emu); kfree(emu); return 0; } @@ -572,6 +612,85 @@ 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]", + .emu10k2_chip = 1, + .ca0108_chip = 1, + .spk71 = 1} , + {.vendor = 0x1102, .device = 0x0008, + .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]", + .emu10k2_chip = 1, + .ca0108_chip = 1} , + {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102, + .driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]", + .emu10k2_chip = 1, + .ca0102_chip = 1, + .ca0151_chip = 1, + .spk71 = 1, + .spdif_bug = 1, + .ac97_chip = 1} , + {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20021102, + .driver = "Audigy2", .name = "Audigy 2 ZS [SB0350]", + .emu10k2_chip = 1, + .ca0102_chip = 1, + .ca0151_chip = 1, + .spk71 = 1, + .spdif_bug = 1, + .ac97_chip = 1} , + {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20011102, + .driver = "Audigy2", .name = "Audigy 2 ZS [2001]", + .emu10k2_chip = 1, + .ca0102_chip = 1, + .ca0151_chip = 1, + .spk71 = 1, + .spdif_bug = 1, + .ac97_chip = 1} , + {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10071102, + .driver = "Audigy2", .name = "Audigy 2 [SB0240]", + .emu10k2_chip = 1, + .ca0102_chip = 1, + .ca0151_chip = 1, + .spk71 = 1, + .spdif_bug = 1, + .ac97_chip = 1} , + {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102, + .driver = "Audigy2", .name = "Audigy 2 EX [1005]", + .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]", + .emu10k2_chip = 1, + .ca0102_chip = 1, + .ca0151_chip = 1, + .spk71 = 1, + .spdif_bug = 1, + .ac97_chip = 1} , + {.vendor = 0x1102, .device = 0x0004, + .driver = "Audigy", .name = "Audigy 1 or 2 [Unknown]", + .emu10k2_chip = 1, + .ca0102_chip = 1, + .spdif_bug = 1} , + {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x40011102, + .driver = "EMU10K1", .name = "E-mu APS [4001]", + .emu10k1_chip = 1, + .ecard = 1} , + {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80641102, + .driver = "EMU10K1", .name = "SB Live 5.1", + .emu10k1_chip = 1, + .ac97_chip = 1} , + {.vendor = 0x1102, .device = 0x0002, + .driver = "EMU10K1", .name = "SB Live [Unknown]", + .emu10k1_chip = 1, + .ac97_chip = 1} , + { } /* terminator */ +}; + int __devinit snd_emu10k1_create(snd_card_t * card, struct pci_dev * pci, unsigned short extin_mask, @@ -583,15 +702,14 @@ int __devinit snd_emu10k1_create(snd_card_t * card, emu10k1_t *emu; int err; int is_audigy; + unsigned char revision; + const emu_chip_details_t *c; static snd_device_ops_t ops = { .dev_free = snd_emu10k1_dev_free, }; *remu = NULL; - // is_audigy = (int)pci->driver_data; - is_audigy = (pci->device == 0x0004); - /* enable PCI device */ if ((err = pci_enable_device(pci)) < 0) return err; @@ -601,15 +719,6 @@ int __devinit snd_emu10k1_create(snd_card_t * card, pci_disable_device(pci); return -ENOMEM; } - /* set the DMA transfer mask */ - emu->dma_mask = is_audigy ? AUDIGY_DMA_MASK : EMU10K1_DMA_MASK; - if (pci_set_dma_mask(pci, emu->dma_mask) < 0 || - pci_set_consistent_dma_mask(pci, emu->dma_mask) < 0) { - snd_printk(KERN_ERR "architecture does not support PCI busmaster DMA with mask 0x%lx\n", emu->dma_mask); - kfree(emu); - pci_disable_device(pci); - return -ENXIO; - } emu->card = card; spin_lock_init(&emu->reg_lock); spin_lock_init(&emu->emu_lock); @@ -624,8 +733,43 @@ int __devinit snd_emu10k1_create(snd_card_t * card, emu->irq = -1; emu->synth = NULL; emu->get_synth_voice = NULL; + /* read revision & serial */ + pci_read_config_byte(pci, PCI_REVISION_ID, &revision); + 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); - emu->audigy = is_audigy; + 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->vendor == 0) { + snd_printk(KERN_ERR "emu10k1: Card not recognised\n"); + kfree(emu); + pci_disable_device(pci); + return -ENOENT; + } + emu->card_capabilities = c; + if (c->subsystem != 0) + snd_printdd("Sound card name=%s\n", c->name); + 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); + + is_audigy = emu->audigy = c->emu10k2_chip; + + /* set the DMA transfer mask */ + emu->dma_mask = is_audigy ? AUDIGY_DMA_MASK : EMU10K1_DMA_MASK; + if (pci_set_dma_mask(pci, emu->dma_mask) < 0 || + pci_set_consistent_dma_mask(pci, emu->dma_mask) < 0) { + snd_printk(KERN_ERR "architecture does not support PCI busmaster DMA with mask 0x%lx\n", emu->dma_mask); + kfree(emu); + pci_disable_device(pci); + return -ENXIO; + } if (is_audigy) emu->gpr_base = A_FXGPREGBASE; else @@ -671,30 +815,15 @@ int __devinit snd_emu10k1_create(snd_card_t * card, emu->memhdr->block_extra_size = sizeof(emu10k1_memblk_t) - sizeof(snd_util_memblk_t); pci_set_master(pci); - /* read revision & serial */ - pci_read_config_byte(pci, PCI_REVISION_ID, (char *)&emu->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; - if (emu->serial == 0x40011102) { + + if (c->ecard) { emu->card_type = EMU10K1_CARD_EMUAPS; emu->APS = 1; - emu->no_ac97 = 1; /* APS has no AC97 chip */ - } - else if (emu->revision == 4 && emu->serial == 0x10051102) { - /* Audigy 2 EX has apparently no effective AC97 controls - * (for both input and output), so we skip the AC97 detections - */ - snd_printdd(KERN_INFO "Audigy2 EX is detected. skipping ac97.\n"); - emu->no_ac97 = 1; - } - - if (emu->revision == 4 && emu->model == 0x2002) { - /* Audigy 2 ZS */ - snd_printdd(KERN_INFO "Audigy2 ZS is detected. setting 7.1 mode.\n"); - emu->spk71 = 1; } + if (! c->ac97_chip) + emu->no_ac97 = 1; + emu->spk71 = c->spk71; emu->fx8010.fxbus_mask = 0x303f; if (extin_mask == 0) diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index cc651b087..b9fa2e887 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c @@ -437,7 +437,7 @@ int snd_emu10k1_fx8010_register_irq_handler(emu10k1_t *emu, } int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu, - snd_emu10k1_fx8010_irq_t *irq) + snd_emu10k1_fx8010_irq_t *irq) { snd_emu10k1_fx8010_irq_t *tmp; unsigned long flags; @@ -468,10 +468,13 @@ int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu, static void snd_emu10k1_write_op(emu10k1_fx8010_code_t *icode, unsigned int *ptr, u32 op, u32 r, u32 a, u32 x, u32 y) { + u_int32_t *code; snd_assert(*ptr < 512, return); + code = (u_int32_t *)icode->code + (*ptr) * 2; set_bit(*ptr, icode->code_valid); - icode->code[*ptr ][0] = ((x & 0x3ff) << 10) | (y & 0x3ff); - icode->code[(*ptr)++][1] = ((op & 0x0f) << 20) | ((r & 0x3ff) << 10) | (a & 0x3ff); + code[0] = ((x & 0x3ff) << 10) | (y & 0x3ff); + code[1] = ((op & 0x0f) << 20) | ((r & 0x3ff) << 10) | (a & 0x3ff); + (*ptr)++; } #define OP(icode, ptr, op, r, a, x, y) \ @@ -480,16 +483,19 @@ static void snd_emu10k1_write_op(emu10k1_fx8010_code_t *icode, unsigned int *ptr static void snd_emu10k1_audigy_write_op(emu10k1_fx8010_code_t *icode, unsigned int *ptr, u32 op, u32 r, u32 a, u32 x, u32 y) { + u_int32_t *code; snd_assert(*ptr < 1024, return); + code = (u_int32_t *)icode->code + (*ptr) * 2; set_bit(*ptr, icode->code_valid); - icode->code[*ptr ][0] = ((x & 0x7ff) << 12) | (y & 0x7ff); - icode->code[(*ptr)++][1] = ((op & 0x0f) << 24) | ((r & 0x7ff) << 12) | (a & 0x7ff); + code[0] = ((x & 0x7ff) << 12) | (y & 0x7ff); + code[1] = ((op & 0x0f) << 24) | ((r & 0x7ff) << 12) | (a & 0x7ff); + (*ptr)++; } #define A_OP(icode, ptr, op, r, a, x, y) \ snd_emu10k1_audigy_write_op(icode, ptr, op, r, a, x, y) -void snd_emu10k1_efx_write(emu10k1_t *emu, unsigned int pc, unsigned int data) +static void snd_emu10k1_efx_write(emu10k1_t *emu, unsigned int pc, unsigned int data) { pc += emu->audigy ? A_MICROCODEBASE : MICROCODEBASE; snd_emu10k1_ptr_write(emu, pc, 0, data); @@ -501,83 +507,108 @@ unsigned int snd_emu10k1_efx_read(emu10k1_t *emu, unsigned int pc) return snd_emu10k1_ptr_read(emu, pc, 0); } -static void snd_emu10k1_gpr_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode) +static int snd_emu10k1_gpr_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode) { int gpr; + u32 val; for (gpr = 0; gpr < (emu->audigy ? 0x200 : 0x100); gpr++) { if (!test_bit(gpr, icode->gpr_valid)) continue; - snd_emu10k1_ptr_write(emu, emu->gpr_base + gpr, 0, icode->gpr_map[gpr]); + if (get_user(val, &icode->gpr_map[gpr])) + return -EFAULT; + snd_emu10k1_ptr_write(emu, emu->gpr_base + gpr, 0, val); } + return 0; } -static void snd_emu10k1_gpr_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode) +static int snd_emu10k1_gpr_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode) { int gpr; + u32 val; for (gpr = 0; gpr < (emu->audigy ? 0x200 : 0x100); gpr++) { set_bit(gpr, icode->gpr_valid); - icode->gpr_map[gpr] = snd_emu10k1_ptr_read(emu, emu->gpr_base + gpr, 0); + val = snd_emu10k1_ptr_read(emu, emu->gpr_base + gpr, 0); + if (put_user(val, &icode->gpr_map[gpr])) + return -EFAULT; } + return 0; } -static void snd_emu10k1_tram_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode) +static int snd_emu10k1_tram_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode) { int tram; + u32 addr, val; for (tram = 0; tram < (emu->audigy ? 0x100 : 0xa0); tram++) { if (!test_bit(tram, icode->tram_valid)) continue; - snd_emu10k1_ptr_write(emu, TANKMEMDATAREGBASE + tram, 0, icode->tram_data_map[tram]); - if (!emu->audigy) - snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + tram, 0, icode->tram_addr_map[tram]); - else { - snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + tram, 0, icode->tram_addr_map[tram] << 12); - snd_emu10k1_ptr_write(emu, A_TANKMEMCTLREGBASE + tram, 0, icode->tram_addr_map[tram] >> 20); + if (get_user(val, &icode->tram_data_map[tram]) || + get_user(addr, &icode->tram_addr_map[tram])) + return -EFAULT; + snd_emu10k1_ptr_write(emu, TANKMEMDATAREGBASE + tram, 0, val); + if (!emu->audigy) { + snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + tram, 0, addr); + } else { + snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + tram, 0, addr << 12); + snd_emu10k1_ptr_write(emu, A_TANKMEMCTLREGBASE + tram, 0, addr >> 20); } } + return 0; } -static void snd_emu10k1_tram_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode) +static int snd_emu10k1_tram_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode) { int tram; + u32 val, addr; memset(icode->tram_valid, 0, sizeof(icode->tram_valid)); for (tram = 0; tram < (emu->audigy ? 0x100 : 0xa0); tram++) { set_bit(tram, icode->tram_valid); - icode->tram_data_map[tram] = snd_emu10k1_ptr_read(emu, TANKMEMDATAREGBASE + tram, 0); - if (!emu->audigy) - icode->tram_addr_map[tram] = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + tram, 0); - else { - icode->tram_addr_map[tram] = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + tram, 0) >> 12; - icode->tram_addr_map[tram] |= snd_emu10k1_ptr_read(emu, A_TANKMEMCTLREGBASE + tram, 0) << 20; + val = snd_emu10k1_ptr_read(emu, TANKMEMDATAREGBASE + tram, 0); + if (!emu->audigy) { + addr = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + tram, 0); + } else { + addr = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + tram, 0) >> 12; + addr |= snd_emu10k1_ptr_read(emu, A_TANKMEMCTLREGBASE + tram, 0) << 20; } + if (put_user(val, &icode->tram_data_map[tram]) || + put_user(addr, &icode->tram_addr_map[tram])) + return -EFAULT; } + return 0; } -static void snd_emu10k1_code_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode) +static int snd_emu10k1_code_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode) { - u32 pc; + u32 pc, lo, hi; - for (pc = 0; pc < (emu->audigy ? 1024 : 512); pc++) { - if (!test_bit(pc, icode->code_valid)) + for (pc = 0; pc < (emu->audigy ? 2*1024 : 2*512); pc += 2) { + if (!test_bit(pc / 2, icode->code_valid)) continue; - snd_emu10k1_efx_write(emu, pc * 2, icode->code[pc][0]); - snd_emu10k1_efx_write(emu, pc * 2 + 1, icode->code[pc][1]); + if (get_user(lo, &icode->code[pc + 0]) || + get_user(hi, &icode->code[pc + 1])) + return -EFAULT; + snd_emu10k1_efx_write(emu, pc + 0, lo); + snd_emu10k1_efx_write(emu, pc + 1, hi); } + return 0; } -static void snd_emu10k1_code_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode) +static int snd_emu10k1_code_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode) { u32 pc; memset(icode->code_valid, 0, sizeof(icode->code_valid)); - for (pc = 0; pc < (emu->audigy ? 1024 : 512); pc++) { - set_bit(pc, icode->code_valid); - icode->code[pc][0] = snd_emu10k1_efx_read(emu, pc * 2); - icode->code[pc][1] = snd_emu10k1_efx_read(emu, pc * 2 + 1); + for (pc = 0; pc < (emu->audigy ? 2*1024 : 2*512); pc += 2) { + set_bit(pc / 2, icode->code_valid); + if (put_user(snd_emu10k1_efx_read(emu, pc + 0), &icode->code[pc + 0])) + return -EFAULT; + if (put_user(snd_emu10k1_efx_read(emu, pc + 1), &icode->code[pc + 1])) + return -EFAULT; } + return 0; } static snd_emu10k1_fx8010_ctl_t *snd_emu10k1_look_for_ctl(emu10k1_t *emu, snd_ctl_elem_id_t *id) @@ -603,7 +634,8 @@ static int snd_emu10k1_verify_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *ic snd_ctl_elem_id_t __user *_id; snd_ctl_elem_id_t id; emu10k1_fx8010_control_gpr_t __user *_gctl; - emu10k1_fx8010_control_gpr_t gctl; + emu10k1_fx8010_control_gpr_t *gctl; + int err; for (i = 0, _id = icode->gpr_del_controls; i < icode->gpr_del_control_count; i++, _id++) { @@ -612,29 +644,42 @@ static int snd_emu10k1_verify_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *ic if (snd_emu10k1_look_for_ctl(emu, &id) == NULL) return -ENOENT; } + gctl = kmalloc(sizeof(*gctl), GFP_KERNEL); + if (! gctl) + return -ENOMEM; + err = 0; for (i = 0, _gctl = icode->gpr_add_controls; i < icode->gpr_add_control_count; i++, _gctl++) { - if (copy_from_user(&gctl, _gctl, sizeof(gctl))) - return -EFAULT; - if (snd_emu10k1_look_for_ctl(emu, &gctl.id)) + if (copy_from_user(gctl, _gctl, sizeof(*gctl))) { + err = -EFAULT; + goto __error; + } + if (snd_emu10k1_look_for_ctl(emu, &gctl->id)) continue; down_read(&emu->card->controls_rwsem); - if (snd_ctl_find_id(emu->card, &gctl.id) != NULL) { + if (snd_ctl_find_id(emu->card, &gctl->id) != NULL) { up_read(&emu->card->controls_rwsem); - return -EEXIST; + err = -EEXIST; + goto __error; } up_read(&emu->card->controls_rwsem); - if (gctl.id.iface != SNDRV_CTL_ELEM_IFACE_MIXER && - gctl.id.iface != SNDRV_CTL_ELEM_IFACE_PCM) - return -EINVAL; + if (gctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER && + gctl->id.iface != SNDRV_CTL_ELEM_IFACE_PCM) { + err = -EINVAL; + goto __error; + } } for (i = 0, _gctl = icode->gpr_list_controls; i < icode->gpr_list_control_count; i++, _gctl++) { /* FIXME: we need to check the WRITE access */ - if (copy_from_user(&gctl, _gctl, sizeof(gctl))) - return -EFAULT; + if (copy_from_user(gctl, _gctl, sizeof(*gctl))) { + err = -EFAULT; + goto __error; + } } - return 0; + __error: + kfree(gctl); + return err; } static void snd_emu10k1_ctl_private_free(snd_kcontrol_t *kctl) @@ -647,74 +692,88 @@ static void snd_emu10k1_ctl_private_free(snd_kcontrol_t *kctl) kfree(ctl); } -static void snd_emu10k1_add_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode) +static int snd_emu10k1_add_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode) { unsigned int i, j; emu10k1_fx8010_control_gpr_t __user *_gctl; - emu10k1_fx8010_control_gpr_t gctl; - snd_emu10k1_fx8010_ctl_t *ctl, nctl; + emu10k1_fx8010_control_gpr_t *gctl; + snd_emu10k1_fx8010_ctl_t *ctl, *nctl; snd_kcontrol_new_t knew; snd_kcontrol_t *kctl; snd_ctl_elem_value_t *val; + int err = 0; val = (snd_ctl_elem_value_t *)kmalloc(sizeof(*val), GFP_KERNEL); - if (!val) - return; + gctl = kmalloc(sizeof(*gctl), GFP_KERNEL); + nctl = kmalloc(sizeof(*nctl), GFP_KERNEL); + if (!val || !gctl || !nctl) { + err = -ENOMEM; + goto __error; + } + for (i = 0, _gctl = icode->gpr_add_controls; i < icode->gpr_add_control_count; i++, _gctl++) { - if (copy_from_user(&gctl, _gctl, sizeof(gctl))) - break; - snd_runtime_check(gctl.id.iface == SNDRV_CTL_ELEM_IFACE_MIXER || - gctl.id.iface == SNDRV_CTL_ELEM_IFACE_PCM, continue); - snd_runtime_check(gctl.id.name[0] != '\0', continue); - ctl = snd_emu10k1_look_for_ctl(emu, &gctl.id); + if (copy_from_user(gctl, _gctl, sizeof(*gctl))) { + err = -EFAULT; + goto __error; + } + snd_runtime_check(gctl->id.iface == SNDRV_CTL_ELEM_IFACE_MIXER || + gctl->id.iface == SNDRV_CTL_ELEM_IFACE_PCM, err = -EINVAL; goto __error); + snd_runtime_check(gctl->id.name[0] != '\0', err = -EINVAL; goto __error); + ctl = snd_emu10k1_look_for_ctl(emu, &gctl->id); memset(&knew, 0, sizeof(knew)); - knew.iface = gctl.id.iface; - knew.name = gctl.id.name; - knew.index = gctl.id.index; - knew.device = gctl.id.device; - knew.subdevice = gctl.id.subdevice; + knew.iface = gctl->id.iface; + knew.name = gctl->id.name; + knew.index = gctl->id.index; + knew.device = gctl->id.device; + knew.subdevice = gctl->id.subdevice; knew.info = snd_emu10k1_gpr_ctl_info; knew.get = snd_emu10k1_gpr_ctl_get; knew.put = snd_emu10k1_gpr_ctl_put; - memset(&nctl, 0, sizeof(nctl)); - nctl.vcount = gctl.vcount; - nctl.count = gctl.count; + memset(nctl, 0, sizeof(*nctl)); + nctl->vcount = gctl->vcount; + nctl->count = gctl->count; for (j = 0; j < 32; j++) { - nctl.gpr[j] = gctl.gpr[j]; - nctl.value[j] = ~gctl.value[j]; /* inverted, we want to write new value in gpr_ctl_put() */ - val->value.integer.value[j] = gctl.value[j]; + nctl->gpr[j] = gctl->gpr[j]; + nctl->value[j] = ~gctl->value[j]; /* inverted, we want to write new value in gpr_ctl_put() */ + val->value.integer.value[j] = gctl->value[j]; } - nctl.min = gctl.min; - nctl.max = gctl.max; - nctl.translation = gctl.translation; + nctl->min = gctl->min; + nctl->max = gctl->max; + nctl->translation = gctl->translation; if (ctl == NULL) { ctl = (snd_emu10k1_fx8010_ctl_t *)kmalloc(sizeof(*ctl), GFP_KERNEL); - if (ctl == NULL) - continue; + if (ctl == NULL) { + err = -ENOMEM; + goto __error; + } knew.private_value = (unsigned long)ctl; - memcpy(ctl, &nctl, sizeof(nctl)); - if (snd_ctl_add(emu->card, kctl = snd_ctl_new1(&knew, emu)) < 0) { + *ctl = *nctl; + if ((err = snd_ctl_add(emu->card, kctl = snd_ctl_new1(&knew, emu))) < 0) { kfree(ctl); - continue; + goto __error; } kctl->private_free = snd_emu10k1_ctl_private_free; ctl->kcontrol = kctl; list_add_tail(&ctl->list, &emu->fx8010.gpr_ctl); } else { /* overwrite */ - nctl.list = ctl->list; - nctl.kcontrol = ctl->kcontrol; - memcpy(ctl, &nctl, sizeof(nctl)); + nctl->list = ctl->list; + nctl->kcontrol = ctl->kcontrol; + *ctl = *nctl; snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO, &ctl->kcontrol->id); } snd_emu10k1_gpr_ctl_put(ctl->kcontrol, val); } + __error: + kfree(nctl); + kfree(gctl); kfree(val); + return err; } -static void snd_emu10k1_del_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode) +static int snd_emu10k1_del_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode) { unsigned int i; snd_ctl_elem_id_t id; @@ -724,53 +783,61 @@ static void snd_emu10k1_del_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icod for (i = 0, _id = icode->gpr_del_controls; i < icode->gpr_del_control_count; i++, _id++) { - snd_runtime_check(copy_from_user(&id, _id, sizeof(id)) == 0, continue); + snd_runtime_check(copy_from_user(&id, _id, sizeof(id)) == 0, return -EFAULT); down_write(&card->controls_rwsem); ctl = snd_emu10k1_look_for_ctl(emu, &id); if (ctl) snd_ctl_remove(card, ctl->kcontrol); up_write(&card->controls_rwsem); } + return 0; } static int snd_emu10k1_list_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode) { unsigned int i = 0, j; unsigned int total = 0; - emu10k1_fx8010_control_gpr_t gctl; + emu10k1_fx8010_control_gpr_t *gctl; emu10k1_fx8010_control_gpr_t __user *_gctl; snd_emu10k1_fx8010_ctl_t *ctl; snd_ctl_elem_id_t *id; struct list_head *list; + gctl = kmalloc(sizeof(*gctl), GFP_KERNEL); + if (! gctl) + return -ENOMEM; + _gctl = icode->gpr_list_controls; list_for_each(list, &emu->fx8010.gpr_ctl) { ctl = emu10k1_gpr_ctl(list); total++; if (_gctl && i < icode->gpr_list_control_count) { - memset(&gctl, 0, sizeof(gctl)); + memset(gctl, 0, sizeof(*gctl)); id = &ctl->kcontrol->id; - gctl.id.iface = id->iface; - strlcpy(gctl.id.name, id->name, sizeof(gctl.id.name)); - gctl.id.index = id->index; - gctl.id.device = id->device; - gctl.id.subdevice = id->subdevice; - gctl.vcount = ctl->vcount; - gctl.count = ctl->count; + gctl->id.iface = id->iface; + strlcpy(gctl->id.name, id->name, sizeof(gctl->id.name)); + gctl->id.index = id->index; + gctl->id.device = id->device; + gctl->id.subdevice = id->subdevice; + gctl->vcount = ctl->vcount; + gctl->count = ctl->count; for (j = 0; j < 32; j++) { - gctl.gpr[j] = ctl->gpr[j]; - gctl.value[j] = ctl->value[j]; + gctl->gpr[j] = ctl->gpr[j]; + gctl->value[j] = ctl->value[j]; } - gctl.min = ctl->min; - gctl.max = ctl->max; - gctl.translation = ctl->translation; - if (copy_to_user(_gctl, &gctl, sizeof(gctl))) + gctl->min = ctl->min; + gctl->max = ctl->max; + gctl->translation = ctl->translation; + if (copy_to_user(_gctl, gctl, sizeof(*gctl))) { + kfree(gctl); return -EFAULT; + } _gctl++; i++; } } icode->gpr_list_control_total = total; + kfree(gctl); return 0; } @@ -789,11 +856,12 @@ static int snd_emu10k1_icode_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode) else snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg | EMU10K1_DBG_SINGLE_STEP); /* ok, do the main job */ - snd_emu10k1_del_controls(emu, icode); - snd_emu10k1_gpr_poke(emu, icode); - snd_emu10k1_tram_poke(emu, icode); - snd_emu10k1_code_poke(emu, icode); - snd_emu10k1_add_controls(emu, icode); + if ((err = snd_emu10k1_del_controls(emu, icode)) < 0 || + (err = snd_emu10k1_gpr_poke(emu, icode)) < 0 || + (err = snd_emu10k1_tram_poke(emu, icode)) < 0 || + (err = snd_emu10k1_code_poke(emu, icode)) < 0 || + (err = snd_emu10k1_add_controls(emu, icode)) < 0) + goto __error; /* start FX processor when the DSP code is updated */ if (emu->audigy) snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg); @@ -811,10 +879,13 @@ static int snd_emu10k1_icode_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode) down(&emu->fx8010.lock); strlcpy(icode->name, emu->fx8010.name, sizeof(icode->name)); /* ok, do the main job */ - snd_emu10k1_gpr_peek(emu, icode); - snd_emu10k1_tram_peek(emu, icode); - snd_emu10k1_code_peek(emu, icode); - err = snd_emu10k1_list_controls(emu, icode); + err = snd_emu10k1_gpr_peek(emu, icode); + if (err >= 0) + err = snd_emu10k1_tram_peek(emu, icode); + if (err >= 0) + err = snd_emu10k1_code_peek(emu, icode); + if (err >= 0) + err = snd_emu10k1_list_controls(emu, icode); up(&emu->fx8010.lock); return err; } @@ -957,19 +1028,25 @@ static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu) const int stereo_mix = capture + 2; const int tmp = 0x88; u32 ptr; - emu10k1_fx8010_code_t *icode; - emu10k1_fx8010_control_gpr_t *controls, *ctl; + emu10k1_fx8010_code_t *icode = NULL; + emu10k1_fx8010_control_gpr_t *controls = NULL, *ctl; + u32 *gpr_map; mm_segment_t seg; spin_lock_init(&emu->fx8010.irq_lock); INIT_LIST_HEAD(&emu->fx8010.gpr_ctl); - if ((icode = kcalloc(1, sizeof(*icode), GFP_KERNEL)) == NULL) - return -ENOMEM; - if ((controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, sizeof(*controls), GFP_KERNEL)) == NULL) { - kfree(icode); - return -ENOMEM; + if ((icode = kcalloc(1, sizeof(*icode), GFP_KERNEL)) == NULL || + (icode->gpr_map = (u_int32_t __user *)kcalloc(512 + 256 + 256 + 2 * 1024, sizeof(u_int32_t), GFP_KERNEL)) == NULL || + (controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, sizeof(*controls), GFP_KERNEL)) == NULL) { + err = -ENOMEM; + goto __err; } + gpr_map = (u32 *)icode->gpr_map; + + icode->tram_data_map = icode->gpr_map + 512; + icode->tram_addr_map = icode->tram_data_map + 256; + icode->code = icode->tram_addr_map + 256; /* clear free GPRs */ for (i = 0; i < 512; i++) @@ -1026,10 +1103,10 @@ static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu) snd_emu10k1_init_stereo_control(&controls[nctl++], "Wave Playback Volume", gpr, 100); gpr += 2; - /* Music Playback */ + /* Synth Playback */ A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+0), A_GPR(stereo_mix+0), A_GPR(gpr), A_FXBUS(FXBUS_MIDI_LEFT)); A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+1), A_GPR(stereo_mix+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT)); - snd_emu10k1_init_stereo_control(&controls[nctl++], "Music Playback Volume", gpr, 100); + snd_emu10k1_init_stereo_control(&controls[nctl++], "Synth Playback Volume", gpr, 100); gpr += 2; /* Wave (PCM) Capture */ @@ -1038,10 +1115,10 @@ static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu) snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Capture Volume", gpr, 0); gpr += 2; - /* Music Capture */ + /* Synth Capture */ A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_FXBUS(FXBUS_MIDI_LEFT)); A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT)); - snd_emu10k1_init_stereo_control(&controls[nctl++], "Music Capture Volume", gpr, 0); + snd_emu10k1_init_stereo_control(&controls[nctl++], "Synth Capture Volume", gpr, 0); gpr += 2; /* @@ -1292,8 +1369,9 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) /* A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); */ /* IEC958 Optical Raw Playback Switch */ - icode->gpr_map[gpr++] = 0x1008; - icode->gpr_map[gpr++] = 0xffff0000; + gpr_map[gpr++] = 0; + gpr_map[gpr++] = 0x1008; + gpr_map[gpr++] = 0xffff0000; for (z = 0; z < 2; z++) { A_OP(icode, &ptr, iMAC0, A_GPR(tmp + 2), A_FXBUS(FXBUS_PT_LEFT + z), A_C_00000000, A_C_00000000); A_OP(icode, &ptr, iSKIP, A_GPR_COND, A_GPR_COND, A_GPR(gpr - 2), A_C_00000001); @@ -1302,7 +1380,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) A_SWITCH(icode, &ptr, tmp + 0, tmp + 2, gpr + z); A_SWITCH_NEG(icode, &ptr, tmp + 1, gpr + z); A_SWITCH(icode, &ptr, tmp + 1, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, tmp + 1); - A_OP(icode, &ptr, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L + z), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000); + if ((z==1) && (emu->card_capabilities->spdif_bug)) { + /* Due to a SPDIF output bug on some Audigy cards, this code delays the Right channel by 1 sample */ + snd_printk("Installing spdif_bug patch: %s\n", emu->card_capabilities->name); + A_OP(icode, &ptr, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L + z), A_GPR(gpr - 3), A_C_00000000, A_C_00000000); + A_OP(icode, &ptr, iACC3, A_GPR(gpr - 3), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000); + } else { + A_OP(icode, &ptr, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L + z), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000); + } } snd_emu10k1_init_stereo_onoff_control(controls + nctl++, "IEC958 Optical Raw Playback Switch", gpr, 0); gpr += 2; @@ -1312,9 +1397,18 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) A_PUT_OUTPUT(A_EXTOUT_LFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS); /* ADC buffer */ +#ifdef EMU10K1_CAPTURE_DIGITAL_OUT + A_PUT_STEREO_OUTPUT(A_EXTOUT_ADC_CAP_L, A_EXTOUT_ADC_CAP_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); +#else A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_L, capture); A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_R, capture+1); +#endif + /* EFX capture - capture the 16 EXTINs */ + for (z = 0; z < 16; z++) { + A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_EXTIN(z)); + } + /* * ok, set up done.. */ @@ -1330,13 +1424,16 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) seg = snd_enter_user(); icode->gpr_add_control_count = nctl; - icode->gpr_add_controls = controls; + icode->gpr_add_controls = (emu10k1_fx8010_control_gpr_t __user *)controls; err = snd_emu10k1_icode_poke(emu, icode); snd_leave_user(seg); __err: kfree(controls); - kfree(icode); + if (icode != NULL) { + kfree((void *)icode->gpr_map); + kfree(icode); + } return err; } @@ -1398,8 +1495,9 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu) int err, i, z, gpr, tmp, playback, capture; u32 ptr; emu10k1_fx8010_code_t *icode; - emu10k1_fx8010_pcm_t *ipcm; - emu10k1_fx8010_control_gpr_t *controls, *ctl; + emu10k1_fx8010_pcm_t *ipcm = NULL; + emu10k1_fx8010_control_gpr_t *controls = NULL, *ctl; + u32 *gpr_map; mm_segment_t seg; spin_lock_init(&emu->fx8010.irq_lock); @@ -1407,15 +1505,17 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu) if ((icode = kcalloc(1, sizeof(*icode), GFP_KERNEL)) == NULL) return -ENOMEM; - if ((controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, sizeof(emu10k1_fx8010_control_gpr_t), GFP_KERNEL)) == NULL) { - kfree(icode); - return -ENOMEM; - } - if ((ipcm = kcalloc(1, sizeof(*ipcm), GFP_KERNEL)) == NULL) { - kfree(controls); - kfree(icode); - return -ENOMEM; + if ((icode->gpr_map = (u_int32_t __user *)kcalloc(256 + 160 + 160 + 2 * 512, sizeof(u_int32_t), GFP_KERNEL)) == NULL || + (controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, sizeof(emu10k1_fx8010_control_gpr_t), GFP_KERNEL)) == NULL || + (ipcm = kcalloc(1, sizeof(*ipcm), GFP_KERNEL)) == NULL) { + err = -ENOMEM; + goto __err; } + gpr_map = (u32 *)icode->gpr_map; + + icode->tram_data_map = icode->gpr_map + 256; + icode->tram_addr_map = icode->tram_data_map + 160; + icode->code = icode->tram_addr_map + 160; /* clear free GPRs */ for (i = 0; i < 256; i++) @@ -1466,19 +1566,19 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu) ipcm->etram[0] = 0; ipcm->etram[1] = 1; - icode->gpr_map[gpr + 0] = 0xfffff000; - icode->gpr_map[gpr + 1] = 0xffff0000; - icode->gpr_map[gpr + 2] = 0x70000000; - icode->gpr_map[gpr + 3] = 0x00000007; - icode->gpr_map[gpr + 4] = 0x001f << 11; - icode->gpr_map[gpr + 5] = 0x001c << 11; - icode->gpr_map[gpr + 6] = (0x22 - 0x01) - 1; /* skip at 01 to 22 */ - icode->gpr_map[gpr + 7] = (0x22 - 0x06) - 1; /* skip at 06 to 22 */ - icode->gpr_map[gpr + 8] = 0x2000000 + (2<<11); - icode->gpr_map[gpr + 9] = 0x4000000 + (2<<11); - icode->gpr_map[gpr + 10] = 1<<11; - icode->gpr_map[gpr + 11] = (0x24 - 0x0a) - 1; /* skip at 0a to 24 */ - icode->gpr_map[gpr + 12] = 0; + gpr_map[gpr + 0] = 0xfffff000; + gpr_map[gpr + 1] = 0xffff0000; + gpr_map[gpr + 2] = 0x70000000; + gpr_map[gpr + 3] = 0x00000007; + gpr_map[gpr + 4] = 0x001f << 11; + gpr_map[gpr + 5] = 0x001c << 11; + gpr_map[gpr + 6] = (0x22 - 0x01) - 1; /* skip at 01 to 22 */ + gpr_map[gpr + 7] = (0x22 - 0x06) - 1; /* skip at 06 to 22 */ + gpr_map[gpr + 8] = 0x2000000 + (2<<11); + gpr_map[gpr + 9] = 0x4000000 + (2<<11); + gpr_map[gpr + 10] = 1<<11; + gpr_map[gpr + 11] = (0x24 - 0x0a) - 1; /* skip at 0a to 24 */ + gpr_map[gpr + 12] = 0; /* if the trigger flag is not set, skip */ /* 00: */ OP(icode, &ptr, iMAC0, C_00000000, GPR(ipcm->gpr_trigger), C_00000000, C_00000000); @@ -1559,19 +1659,19 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu) snd_emu10k1_init_stereo_onoff_control(controls + i++, "Wave Capture Switch", gpr + 2, 0); gpr += 4; - /* Music Playback Volume */ + /* Synth Playback Volume */ for (z = 0; z < 2; z++) VOLUME_ADD(icode, &ptr, playback + z, 2 + z, gpr + z); - snd_emu10k1_init_stereo_control(controls + i++, "Music Playback Volume", gpr, 100); + snd_emu10k1_init_stereo_control(controls + i++, "Synth Playback Volume", gpr, 100); gpr += 2; - /* Music Capture Volume + Switch */ + /* Synth Capture Volume + Switch */ for (z = 0; z < 2; z++) { SWITCH(icode, &ptr, tmp + 0, 2 + z, gpr + 2 + z); VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z); } - snd_emu10k1_init_stereo_control(controls + i++, "Music Capture Volume", gpr, 0); - snd_emu10k1_init_stereo_onoff_control(controls + i++, "Music Capture Switch", gpr + 2, 0); + snd_emu10k1_init_stereo_control(controls + i++, "Synth Capture Volume", gpr, 0); + snd_emu10k1_init_stereo_onoff_control(controls + i++, "Synth Capture Switch", gpr + 2, 0); gpr += 4; /* Surround Digital Playback Volume (renamed later without Digital) */ @@ -1881,6 +1981,24 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu) if (emu->fx8010.extout_mask & (1<<EXTOUT_MIC_CAP)) 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 (gpr > tmp) { snd_BUG(); err = -EIO; @@ -1900,7 +2018,7 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu) goto __err; seg = snd_enter_user(); icode->gpr_add_control_count = i; - icode->gpr_add_controls = controls; + icode->gpr_add_controls = (emu10k1_fx8010_control_gpr_t __user *)controls; err = snd_emu10k1_icode_poke(emu, icode); snd_leave_user(seg); if (err >= 0) @@ -1908,7 +2026,10 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu) __err: kfree(ipcm); kfree(controls); - kfree(icode); + if (icode != NULL) { + kfree((void *)icode->gpr_map); + kfree(icode); + } return err; } @@ -1959,7 +2080,7 @@ int snd_emu10k1_fx8010_tram_setup(emu10k1_t *emu, u32 size) } size = 0x2000 << size_reg; } - if (emu->fx8010.etram_pages.bytes == size) + if ((emu->fx8010.etram_pages.bytes / 2) == size) return 0; spin_lock_irq(&emu->emu_lock); outl(HCFG_LOCKTANKCACHE_MASK | inl(emu->port + HCFG), emu->port + HCFG); @@ -2009,7 +2130,7 @@ static int snd_emu10k1_fx8010_info(emu10k1_t *emu, emu10k1_fx8010_info_t *info) 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; + info->external_tram_size = emu->fx8010.etram_pages.bytes / 2; fxbus = fxbuses; extin = emu->audigy ? audigy_ins : creative_ins; extout = emu->audigy ? audigy_outs : creative_outs; diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c index f73ac0ef6..044663d31 100644 --- a/sound/pci/emu10k1/emumixer.c +++ b/sound/pci/emu10k1/emumixer.c @@ -3,6 +3,7 @@ * Takashi Iwai <tiwai@suse.de> * Creative Labs, Inc. * Routines for control of EMU10K1 chips / mixer routines + * Multichannel PCM support Copyright (c) Lee Revell <rlrevell@joe-job.com> * * BUGS: * -- @@ -54,7 +55,7 @@ static int snd_emu10k1_spdif_get(snd_kcontrol_t * kcontrol, ucontrol->value.iec958.status[2] = (emu->spdif_bits[idx] >> 16) & 0xff; ucontrol->value.iec958.status[3] = (emu->spdif_bits[idx] >> 24) & 0xff; spin_unlock_irqrestore(&emu->reg_lock, flags); - return 0; + return 0; } static int snd_emu10k1_spdif_get_mask(snd_kcontrol_t * kcontrol, @@ -64,9 +65,94 @@ static int snd_emu10k1_spdif_get_mask(snd_kcontrol_t * kcontrol, ucontrol->value.iec958.status[1] = 0xff; ucontrol->value.iec958.status[2] = 0xff; ucontrol->value.iec958.status[3] = 0xff; - return 0; + return 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"}; + + 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_audigy_spdif_output_rate_get(snd_kcontrol_t * kcontrol, + snd_ctl_elem_value_t * ucontrol) +{ + emu10k1_t *emu = snd_kcontrol_chip(kcontrol); + unsigned int tmp; + unsigned long flags; + + + spin_lock_irqsave(&emu->reg_lock, flags); + tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); + switch (tmp & A_SPDIF_RATE_MASK) { + case A_SPDIF_44100: + ucontrol->value.enumerated.item[0] = 0; + break; + case A_SPDIF_48000: + ucontrol->value.enumerated.item[0] = 1; + break; + case A_SPDIF_96000: + ucontrol->value.enumerated.item[0] = 2; + break; + default: + ucontrol->value.enumerated.item[0] = 1; + } + spin_unlock_irqrestore(&emu->reg_lock, flags); + return 0; +} + +static int snd_audigy_spdif_output_rate_put(snd_kcontrol_t * kcontrol, + snd_ctl_elem_value_t * ucontrol) +{ + emu10k1_t *emu = snd_kcontrol_chip(kcontrol); + int change; + unsigned int reg, val, tmp; + unsigned long flags; + + switch(ucontrol->value.enumerated.item[0]) { + case 0: + val = A_SPDIF_44100; + break; + case 1: + val = A_SPDIF_48000; + break; + case 2: + val = A_SPDIF_96000; + break; + default: + val = A_SPDIF_48000; + break; + } + + + spin_lock_irqsave(&emu->reg_lock, flags); + reg = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); + tmp = reg & ~A_SPDIF_RATE_MASK; + tmp |= val; + if ((change = (tmp != reg))) + snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp); + spin_unlock_irqrestore(&emu->reg_lock, flags); + return change; +} + +static snd_kcontrol_new_t snd_audigy_spdif_output_rate = +{ + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Audigy SPDIF Output Sample Rate", + .count = 1, + .info = snd_audigy_spdif_output_rate_info, + .get = snd_audigy_spdif_output_rate_get, + .put = snd_audigy_spdif_output_rate_put +}; + static int snd_emu10k1_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { @@ -87,27 +173,27 @@ static int snd_emu10k1_spdif_put(snd_kcontrol_t * kcontrol, emu->spdif_bits[idx] = val; } spin_unlock_irqrestore(&emu->reg_lock, flags); - return change; + return change; } static snd_kcontrol_new_t snd_emu10k1_spdif_mask_control = { .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), .count = 4, - .info = snd_emu10k1_spdif_info, - .get = snd_emu10k1_spdif_get_mask + .info = snd_emu10k1_spdif_info, + .get = snd_emu10k1_spdif_get_mask }; static snd_kcontrol_new_t snd_emu10k1_spdif_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), .count = 4, - .info = snd_emu10k1_spdif_info, - .get = snd_emu10k1_spdif_get, - .put = snd_emu10k1_spdif_put + .info = snd_emu10k1_spdif_info, + .get = snd_emu10k1_spdif_get, + .put = snd_emu10k1_spdif_put }; @@ -139,6 +225,8 @@ static void update_emu10k1_send_volume(emu10k1_t *emu, int voice, unsigned char } } +/* PCM stream controls */ + static int snd_emu10k1_send_routing_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) { emu10k1_t *emu = snd_kcontrol_chip(kcontrol); @@ -165,7 +253,7 @@ static int snd_emu10k1_send_routing_get(snd_kcontrol_t * kcontrol, ucontrol->value.integer.value[(voice * num_efx) + idx] = mix->send_routing[voice][idx] & mask; spin_unlock_irqrestore(&emu->reg_lock, flags); - return 0; + return 0; } static int snd_emu10k1_send_routing_put(snd_kcontrol_t * kcontrol, @@ -199,18 +287,18 @@ static int snd_emu10k1_send_routing_put(snd_kcontrol_t * kcontrol, } } spin_unlock_irqrestore(&emu->reg_lock, flags); - return change; + return change; } static snd_kcontrol_new_t snd_emu10k1_send_routing_control = { .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "EMU10K1 PCM Send Routing", + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "EMU10K1 PCM Send Routing", .count = 32, - .info = snd_emu10k1_send_routing_info, - .get = snd_emu10k1_send_routing_get, - .put = snd_emu10k1_send_routing_put + .info = snd_emu10k1_send_routing_info, + .get = snd_emu10k1_send_routing_get, + .put = snd_emu10k1_send_routing_put }; static int snd_emu10k1_send_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) @@ -236,7 +324,7 @@ static int snd_emu10k1_send_volume_get(snd_kcontrol_t * kcontrol, for (idx = 0; idx < 3*num_efx; idx++) ucontrol->value.integer.value[idx] = mix->send_volume[idx/num_efx][idx%num_efx]; spin_unlock_irqrestore(&emu->reg_lock, flags); - return 0; + return 0; } static int snd_emu10k1_send_volume_put(snd_kcontrol_t * kcontrol, @@ -268,18 +356,18 @@ static int snd_emu10k1_send_volume_put(snd_kcontrol_t * kcontrol, } } spin_unlock_irqrestore(&emu->reg_lock, flags); - return change; + return change; } static snd_kcontrol_new_t snd_emu10k1_send_volume_control = { .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "EMU10K1 PCM Send Volume", + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "EMU10K1 PCM Send Volume", .count = 32, - .info = snd_emu10k1_send_volume_info, - .get = snd_emu10k1_send_volume_get, - .put = snd_emu10k1_send_volume_put + .info = snd_emu10k1_send_volume_info, + .get = snd_emu10k1_send_volume_get, + .put = snd_emu10k1_send_volume_put }; static int snd_emu10k1_attn_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) @@ -303,7 +391,7 @@ static int snd_emu10k1_attn_get(snd_kcontrol_t * kcontrol, for (idx = 0; idx < 3; idx++) ucontrol->value.integer.value[idx] = mix->attn[idx]; spin_unlock_irqrestore(&emu->reg_lock, flags); - return 0; + return 0; } static int snd_emu10k1_attn_put(snd_kcontrol_t * kcontrol, @@ -331,18 +419,212 @@ static int snd_emu10k1_attn_put(snd_kcontrol_t * kcontrol, } } spin_unlock_irqrestore(&emu->reg_lock, flags); - return change; + return change; } static snd_kcontrol_new_t snd_emu10k1_attn_control = { .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "EMU10K1 PCM Volume", + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "EMU10K1 PCM Volume", .count = 32, - .info = snd_emu10k1_attn_info, - .get = snd_emu10k1_attn_get, - .put = snd_emu10k1_attn_put + .info = snd_emu10k1_attn_info, + .get = snd_emu10k1_attn_get, + .put = snd_emu10k1_attn_put +}; + +/* Mutichannel PCM stream controls */ + +static int snd_emu10k1_efx_send_routing_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) +{ + emu10k1_t *emu = snd_kcontrol_chip(kcontrol); + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = emu->audigy ? 8 : 4; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f; + return 0; +} + +static int snd_emu10k1_efx_send_routing_get(snd_kcontrol_t * kcontrol, + snd_ctl_elem_value_t * ucontrol) +{ + unsigned long flags; + emu10k1_t *emu = snd_kcontrol_chip(kcontrol); + emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; + int idx; + int num_efx = emu->audigy ? 8 : 4; + int mask = emu->audigy ? 0x3f : 0x0f; + + spin_lock_irqsave(&emu->reg_lock, flags); + for (idx = 0; idx < num_efx; idx++) + ucontrol->value.integer.value[idx] = + mix->send_routing[0][idx] & mask; + spin_unlock_irqrestore(&emu->reg_lock, flags); + return 0; +} + +static int snd_emu10k1_efx_send_routing_put(snd_kcontrol_t * kcontrol, + snd_ctl_elem_value_t * ucontrol) +{ + unsigned long flags; + emu10k1_t *emu = snd_kcontrol_chip(kcontrol); + int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[ch]; + int change = 0, idx, val; + int num_efx = emu->audigy ? 8 : 4; + int mask = emu->audigy ? 0x3f : 0x0f; + + spin_lock_irqsave(&emu->reg_lock, flags); + for (idx = 0; idx < num_efx; idx++) { + val = ucontrol->value.integer.value[idx] & mask; + if (mix->send_routing[0][idx] != val) { + mix->send_routing[0][idx] = val; + change = 1; + } + } + + if (change && mix->epcm) { + if (mix->epcm->voices[ch]) { + update_emu10k1_fxrt(emu, mix->epcm->voices[ch]->number, + &mix->send_routing[0][0]); + } + } + spin_unlock_irqrestore(&emu->reg_lock, flags); + return change; +} + +static snd_kcontrol_new_t snd_emu10k1_efx_send_routing_control = +{ + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "Multichannel PCM Send Routing", + .count = 16, + .info = snd_emu10k1_efx_send_routing_info, + .get = snd_emu10k1_efx_send_routing_get, + .put = snd_emu10k1_efx_send_routing_put +}; + +static int snd_emu10k1_efx_send_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) +{ + emu10k1_t *emu = snd_kcontrol_chip(kcontrol); + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = emu->audigy ? 8 : 4; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 255; + return 0; +} + +static int snd_emu10k1_efx_send_volume_get(snd_kcontrol_t * kcontrol, + snd_ctl_elem_value_t * ucontrol) +{ + unsigned long flags; + emu10k1_t *emu = snd_kcontrol_chip(kcontrol); + emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; + int idx; + int num_efx = emu->audigy ? 8 : 4; + + spin_lock_irqsave(&emu->reg_lock, flags); + for (idx = 0; idx < num_efx; idx++) + ucontrol->value.integer.value[idx] = mix->send_volume[0][idx]; + spin_unlock_irqrestore(&emu->reg_lock, flags); + return 0; +} + +static int snd_emu10k1_efx_send_volume_put(snd_kcontrol_t * kcontrol, + snd_ctl_elem_value_t * ucontrol) +{ + unsigned long flags; + emu10k1_t *emu = snd_kcontrol_chip(kcontrol); + int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[ch]; + int change = 0, idx, val; + int num_efx = emu->audigy ? 8 : 4; + + spin_lock_irqsave(&emu->reg_lock, flags); + for (idx = 0; idx < num_efx; idx++) { + val = ucontrol->value.integer.value[idx] & 255; + if (mix->send_volume[0][idx] != val) { + mix->send_volume[0][idx] = val; + change = 1; + } + } + if (change && mix->epcm) { + if (mix->epcm->voices[ch]) { + update_emu10k1_send_volume(emu, mix->epcm->voices[ch]->number, + &mix->send_volume[0][0]); + } + } + spin_unlock_irqrestore(&emu->reg_lock, flags); + return change; +} + + +static snd_kcontrol_new_t snd_emu10k1_efx_send_volume_control = +{ + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "Multichannel PCM Send Volume", + .count = 16, + .info = snd_emu10k1_efx_send_volume_info, + .get = snd_emu10k1_efx_send_volume_get, + .put = snd_emu10k1_efx_send_volume_put +}; + +static int snd_emu10k1_efx_attn_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; + uinfo->value.integer.max = 0xffff; + return 0; +} + +static int snd_emu10k1_efx_attn_get(snd_kcontrol_t * kcontrol, + snd_ctl_elem_value_t * ucontrol) +{ + emu10k1_t *emu = snd_kcontrol_chip(kcontrol); + emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; + unsigned long flags; + + spin_lock_irqsave(&emu->reg_lock, flags); + ucontrol->value.integer.value[0] = mix->attn[0]; + spin_unlock_irqrestore(&emu->reg_lock, flags); + return 0; +} + +static int snd_emu10k1_efx_attn_put(snd_kcontrol_t * kcontrol, + snd_ctl_elem_value_t * ucontrol) +{ + unsigned long flags; + emu10k1_t *emu = snd_kcontrol_chip(kcontrol); + int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[ch]; + int change = 0, val; + + spin_lock_irqsave(&emu->reg_lock, flags); + val = ucontrol->value.integer.value[0] & 0xffff; + if (mix->attn[0] != val) { + mix->attn[0] = val; + change = 1; + } + if (change && mix->epcm) { + if (mix->epcm->voices[ch]) { + snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[ch]->number, mix->attn[0]); + } + } + spin_unlock_irqrestore(&emu->reg_lock, flags); + return change; +} + +static snd_kcontrol_new_t snd_emu10k1_efx_attn_control = +{ + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "Multichannel PCM Volume", + .count = 16, + .info = snd_emu10k1_efx_attn_info, + .get = snd_emu10k1_efx_attn_get, + .put = snd_emu10k1_efx_attn_put }; static int snd_emu10k1_shared_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) @@ -363,7 +645,7 @@ static int snd_emu10k1_shared_spdif_get(snd_kcontrol_t * kcontrol, ucontrol->value.integer.value[0] = inl(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0; else ucontrol->value.integer.value[0] = inl(emu->port + HCFG) & HCFG_GPOUT0 ? 1 : 0; - return 0; + return 0; } static int snd_emu10k1_shared_spdif_put(snd_kcontrol_t * kcontrol, @@ -394,7 +676,7 @@ static int snd_emu10k1_shared_spdif_put(snd_kcontrol_t * kcontrol, outl(reg | val, emu->port + HCFG); } spin_unlock_irqrestore(&emu->reg_lock, flags); - return change; + return change; } static snd_kcontrol_new_t snd_emu10k1_shared_spdif __devinitdata = @@ -519,10 +801,12 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu) if ((err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus)) < 0) return err; + pbus->no_vra = 1; /* we don't need VRA */ memset(&ac97, 0, sizeof(ac97)); ac97.private_data = emu; ac97.private_free = snd_emu10k1_mixer_free_ac97; + ac97.scaps = AC97_SCAP_NO_SPDIF; if ((err = snd_ac97_mixer(pbus, &ac97, &emu->ac97)) < 0) return err; if (emu->audigy) { @@ -577,7 +861,22 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu) if ((err = snd_ctl_add(card, kctl))) return err; - /* intiailize the routing and volume table for each pcm playback stream */ + if ((kctl = emu->ctl_efx_send_routing = snd_ctl_new1(&snd_emu10k1_efx_send_routing_control, emu)) == NULL) + return -ENOMEM; + if ((err = snd_ctl_add(card, kctl))) + return err; + + if ((kctl = emu->ctl_efx_send_volume = snd_ctl_new1(&snd_emu10k1_efx_send_volume_control, emu)) == NULL) + return -ENOMEM; + if ((err = snd_ctl_add(card, kctl))) + return err; + + if ((kctl = emu->ctl_efx_attn = snd_ctl_new1(&snd_emu10k1_efx_attn_control, emu)) == NULL) + return -ENOMEM; + if ((err = snd_ctl_add(card, kctl))) + return err; + + /* initialize the routing and volume table for each pcm playback stream */ for (pcm = 0; pcm < 32; pcm++) { emu10k1_pcm_mixer_t *mix; int v; @@ -597,17 +896,34 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu) mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff; } + /* initialize the routing and volume table for the multichannel playback stream */ + for (pcm = 0; pcm < NUM_EFX_PLAYBACK; pcm++) { + emu10k1_pcm_mixer_t *mix; + int v; + + mix = &emu->efx_pcm_mixer[pcm]; + mix->epcm = NULL; + + mix->send_routing[0][0] = pcm; + mix->send_routing[0][1] = (pcm == 0) ? 1 : 0; + for (v = 0; v < 2; v++) + mix->send_routing[0][2+v] = 13+v; + if (emu->audigy) + for (v = 0; v < 4; v++) + mix->send_routing[0][4+v] = 60+v; + + memset(&mix->send_volume, 0, sizeof(mix->send_volume)); + mix->send_volume[0][0] = 255; + + mix->attn[0] = 0xffff; + } + if (! emu->APS) { /* FIXME: APS has these controls? */ /* sb live! and audigy */ if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL) 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 ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu)) == NULL) return -ENOMEM; if ((err = snd_ctl_add(card, kctl))) @@ -619,6 +935,10 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu) return -ENOMEM; if ((err = snd_ctl_add(card, kctl))) return err; + 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) { /* sb live! */ if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL) @@ -626,6 +946,10 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu) if ((err = snd_ctl_add(card, kctl))) return err; } - + if (emu->audigy && emu->revision == 4) { /* P16V */ + if ((err = snd_p16v_mixer(emu))) + return err; + } + return 0; } diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 89c5d834f..f910399db 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -430,7 +430,7 @@ struct _snd_ensoniq { #endif #ifdef SUPPORT_JOYSTICK - struct gameport gameport; + struct gameport *gameport; #endif }; @@ -573,24 +573,18 @@ static void snd_es1370_codec_write(ak4531_t *ak4531, unsigned short reg, unsigned short val) { ensoniq_t *ensoniq = ak4531->private_data; - unsigned long flags; unsigned long end_time = jiffies + HZ / 10; #if 0 printk("CODEC WRITE: reg = 0x%x, val = 0x%x (0x%x), creg = 0x%x\n", reg, val, ES_1370_CODEC_WRITE(reg, val), ES_REG(ensoniq, 1370_CODEC)); #endif do { - spin_lock_irqsave(&ensoniq->reg_lock, flags); if (!(inl(ES_REG(ensoniq, STATUS)) & ES_1370_CSTAT)) { outw(ES_1370_CODEC_WRITE(reg, val), ES_REG(ensoniq, 1370_CODEC)); - spin_unlock_irqrestore(&ensoniq->reg_lock, flags); return; } - spin_unlock_irqrestore(&ensoniq->reg_lock, flags); -#if 0 set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); -#endif } while (time_after(end_time, jiffies)); snd_printk("codec write timeout, status = 0x%x\n", inl(ES_REG(ensoniq, STATUS))); } @@ -603,11 +597,10 @@ static void snd_es1371_codec_write(ac97_t *ac97, unsigned short reg, unsigned short val) { ensoniq_t *ensoniq = ac97->private_data; - unsigned long flags; unsigned int t, x; + down(&ensoniq->src_mutex); for (t = 0; t < POLL_COUNT; t++) { - spin_lock_irqsave(&ensoniq->reg_lock, flags); if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP)) { /* save the current state for latter */ x = snd_es1371_wait_src_ready(ensoniq); @@ -629,11 +622,11 @@ static void snd_es1371_codec_write(ac97_t *ac97, /* restore SRC reg */ snd_es1371_wait_src_ready(ensoniq); outl(x, ES_REG(ensoniq, 1371_SMPRATE)); - spin_unlock_irqrestore(&ensoniq->reg_lock, flags); + up(&ensoniq->src_mutex); return; } - spin_unlock_irqrestore(&ensoniq->reg_lock, flags); } + up(&ensoniq->src_mutex); snd_printk("codec write timeout at 0x%lx [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC))); } @@ -641,12 +634,11 @@ static unsigned short snd_es1371_codec_read(ac97_t *ac97, unsigned short reg) { ensoniq_t *ensoniq = ac97->private_data; - unsigned long flags; unsigned int t, x, fail = 0; __again: + down(&ensoniq->src_mutex); for (t = 0; t < POLL_COUNT; t++) { - spin_lock_irqsave(&ensoniq->reg_lock, flags); if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP)) { /* save the current state for latter */ x = snd_es1371_wait_src_ready(ensoniq); @@ -676,19 +668,19 @@ static unsigned short snd_es1371_codec_read(ac97_t *ac97, /* now wait for the stinkin' data (RDY) */ for (t = 0; t < POLL_COUNT; t++) { if ((x = inl(ES_REG(ensoniq, 1371_CODEC))) & ES_1371_CODEC_RDY) { - spin_unlock_irqrestore(&ensoniq->reg_lock, flags); + up(&ensoniq->src_mutex); return ES_1371_CODEC_READ(x); } } - spin_unlock_irqrestore(&ensoniq->reg_lock, flags); + up(&ensoniq->src_mutex); if (++fail > 10) { snd_printk("codec read timeout (final) at 0x%lx, reg = 0x%x [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), reg, inl(ES_REG(ensoniq, 1371_CODEC))); return 0; } goto __again; } - spin_unlock_irqrestore(&ensoniq->reg_lock, flags); } + up(&ensoniq->src_mutex); snd_printk("es1371: codec read timeout at 0x%lx [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC))); return 0; } @@ -1742,43 +1734,99 @@ static int __devinit snd_ensoniq_1370_mixer(ensoniq_t * ensoniq) #endif /* CHIP1370 */ #ifdef SUPPORT_JOYSTICK -static int snd_ensoniq_joystick(ensoniq_t *ensoniq, long port) -{ + #ifdef CHIP1371 - if (port == 1) { /* auto-detect */ - for (port = 0x200; port <= 0x218; port += 8) - if (request_region(port, 8, "ens137x: gameport")) +static int __devinit snd_ensoniq_get_joystick_port(int dev) +{ + switch (joystick_port[dev]) { + case 0: /* disabled */ + case 1: /* auto-detect */ + case 0x200: + case 0x208: + case 0x210: + case 0x218: + return joystick_port[dev]; + + default: + printk(KERN_ERR "ens1371: invalid joystick port %#x", joystick_port[dev]); + return 0; + } +} +#else +static inline int snd_ensoniq_get_joystick_port(int dev) +{ + return joystick[dev] ? 0x200 : 0; +} +#endif + +static int __devinit snd_ensoniq_create_gameport(ensoniq_t *ensoniq, int dev) +{ + struct gameport *gp; + int io_port; + + io_port = snd_ensoniq_get_joystick_port(dev); + + switch (io_port) { + case 0: + return -ENOSYS; + + case 1: /* auto_detect */ + for (io_port = 0x200; io_port <= 0x218; io_port += 8) + if (request_region(io_port, 8, "ens137x: gameport")) break; - if (port > 0x218) { - snd_printk("no gameport available\n"); + if (io_port > 0x218) { + printk(KERN_WARNING "ens137x: no gameport ports available\n"); return -EBUSY; } - } else -#endif - { - if (!request_region(port, 8, "ens137x: gameport")) { - snd_printk("gameport io port 0x%03x in use", ensoniq->gameport.io); + break; + + default: + if (!request_region(io_port, 8, "ens137x: gameport")) { + printk(KERN_WARNING "ens137x: gameport io port 0x%#x in use\n", io_port); return -EBUSY; } + break; } - ensoniq->gameport.io = port; + + ensoniq->gameport = gp = gameport_allocate_port(); + if (!gp) { + printk(KERN_ERR "ens137x: cannot allocate memory for gameport\n"); + release_region(io_port, 8); + return -ENOMEM; + } + + gameport_set_name(gp, "ES137x"); + gameport_set_phys(gp, "pci%s/gameport0", pci_name(ensoniq->pci)); + gameport_set_dev_parent(gp, &ensoniq->pci->dev); + gp->io = io_port; + ensoniq->ctrl |= ES_JYSTK_EN; #ifdef CHIP1371 ensoniq->ctrl &= ~ES_1371_JOY_ASELM; - ensoniq->ctrl |= ES_1371_JOY_ASEL((ensoniq->gameport.io - 0x200) / 8); + ensoniq->ctrl |= ES_1371_JOY_ASEL((io_port - 0x200) / 8); #endif outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); - gameport_register_port(&ensoniq->gameport); + + gameport_register_port(ensoniq->gameport); + return 0; } -static void snd_ensoniq_joystick_free(ensoniq_t *ensoniq) +static void snd_ensoniq_free_gameport(ensoniq_t *ensoniq) { - gameport_unregister_port(&ensoniq->gameport); - ensoniq->ctrl &= ~ES_JYSTK_EN; - outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); - release_region(ensoniq->gameport.io, 8); + if (ensoniq->gameport) { + int port = ensoniq->gameport->io; + + gameport_unregister_port(ensoniq->gameport); + ensoniq->gameport = NULL; + ensoniq->ctrl &= ~ES_JYSTK_EN; + outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); + release_region(port, 8); + } } +#else +static inline int snd_ensoniq_create_gameport(ensoniq_t *ensoniq, long port) { return -ENOSYS; } +static inline void snd_ensoniq_free_gameport(ensoniq_t *ensoniq) { } #endif /* SUPPORT_JOYSTICK */ /* @@ -1818,10 +1866,7 @@ static void __devinit snd_ensoniq_proc_init(ensoniq_t * ensoniq) static int snd_ensoniq_free(ensoniq_t *ensoniq) { -#ifdef SUPPORT_JOYSTICK - if (ensoniq->ctrl & ES_JYSTK_EN) - snd_ensoniq_joystick_free(ensoniq); -#endif + snd_ensoniq_free_gameport(ensoniq); if (ensoniq->irq < 0) goto __hw_end; #ifdef CHIP1370 @@ -2051,9 +2096,7 @@ static void snd_ensoniq_midi_interrupt(ensoniq_t * ensoniq) if ((status & mask) == 0) break; byte = inb(ES_REG(ensoniq, UART_DATA)); - spin_unlock(&ensoniq->reg_lock); snd_rawmidi_receive(ensoniq->midi_input, &byte, 1); - spin_lock(&ensoniq->reg_lock); } spin_unlock(&ensoniq->reg_lock); @@ -2321,22 +2364,9 @@ static int __devinit snd_audiopci_probe(struct pci_dev *pci, snd_card_free(card); return err; } -#ifdef SUPPORT_JOYSTICK -#ifdef CHIP1371 - switch (joystick_port[dev]) { - case 1: /* auto-detect */ - case 0x200: - case 0x208: - case 0x210: - case 0x218: - snd_ensoniq_joystick(ensoniq, joystick_port[dev]); - break; - } -#else - if (joystick[dev]) - snd_ensoniq_joystick(ensoniq, 0x200); -#endif -#endif /* SUPPORT_JOYSTICK */ + + snd_ensoniq_create_gameport(ensoniq, dev); + strcpy(card->driver, DRIVER_NAME); strcpy(card->shortname, "Ensoniq AudioPCI"); diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 4ef94409b..b4ca8adf3 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c @@ -72,6 +72,10 @@ MODULE_SUPPORTED_DEVICE("{{ESS,ES1938}," "{ESS,ES1969}," "{TerraTec,128i PCI}}"); +#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) +#define SUPPORT_JOYSTICK 1 +#endif + #ifndef PCI_VENDOR_ID_ESS #define PCI_VENDOR_ID_ESS 0x125d #endif @@ -237,8 +241,8 @@ struct _snd_es1938 { spinlock_t mixer_lock; snd_info_entry_t *proc_entry; -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) - struct gameport gameport; +#ifdef SUPPORT_JOYSTICK + struct gameport *gameport; #endif #ifdef CONFIG_PM unsigned char saved_regs[SAVED_REG_SIZE]; @@ -1381,7 +1385,7 @@ static unsigned char saved_regs[SAVED_REG_SIZE+1] = { }; -static int es1938_suspend(snd_card_t *card, unsigned int state) +static int es1938_suspend(snd_card_t *card, pm_message_t state) { es1938_t *chip = card->pm_private_data; unsigned char *s, *d; @@ -1395,11 +1399,10 @@ static int es1938_suspend(snd_card_t *card, unsigned int state) outb(0x00, SLIO_REG(chip, IRQCONTROL)); /* disable irqs */ pci_disable_device(chip->pci); - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } -static int es1938_resume(snd_card_t *card, unsigned int state) +static int es1938_resume(snd_card_t *card) { es1938_t *chip = card->pm_private_data; unsigned char *s, *d; @@ -1415,21 +1418,52 @@ static int es1938_resume(snd_card_t *card, unsigned int state) snd_es1938_write(chip, *s, *d); } - snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; } #endif /* CONFIG_PM */ +#ifdef SUPPORT_JOYSTICK +static int __devinit snd_es1938_create_gameport(es1938_t *chip) +{ + struct gameport *gp; + + chip->gameport = gp = gameport_allocate_port(); + if (!gp) { + printk(KERN_ERR "es1938: cannot allocate memory for gameport\n"); + return -ENOMEM; + } + + gameport_set_name(gp, "ES1938"); + gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci)); + gameport_set_dev_parent(gp, &chip->pci->dev); + gp->io = chip->game_port; + + gameport_register_port(gp); + + return 0; +} + +static void snd_es1938_free_gameport(es1938_t *chip) +{ + if (chip->gameport) { + gameport_unregister_port(chip->gameport); + chip->gameport = NULL; + } +} +#else +static inline int snd_es1938_create_gameport(es1938_t *chip) { return -ENOSYS; } +static inline void snd_es1938_free_gameport(es1938_t *chip) { } +#endif /* SUPPORT_JOYSTICK */ + static int snd_es1938_free(es1938_t *chip) { /* disable irqs */ outb(0x00, SLIO_REG(chip, IRQCONTROL)); - /*if (chip->rmidi) - snd_es1938_mixer_bits(chip, ESSSB_IREG_MPU401CONTROL, 0x40, 0);*/ -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) - if (chip->gameport.io) - gameport_unregister_port(&chip->gameport); -#endif + if (chip->rmidi) + snd_es1938_mixer_bits(chip, ESSSB_IREG_MPU401CONTROL, 0x40, 0); + + snd_es1938_free_gameport(chip); + if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); pci_release_regions(chip->pci); @@ -1576,6 +1610,9 @@ static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id, struct pt_regs *r /* MPU401 */ if (status & 0x80) { + // the following line is evil! It switches off MIDI interrupt handling after the first interrupt received. + // replacing the last 0 by 0x40 works for ESS-Solo1, but just doing nothing works as well! + // andreas@flying-snail.de // snd_es1938_mixer_bits(chip, ESSSB_IREG_MPU401CONTROL, 0x40, 0); /* ack? */ if (chip->rmidi) { handled = 1; @@ -1690,13 +1727,13 @@ static int __devinit snd_es1938_probe(struct pci_dev *pci, if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, chip->mpu_port, 1, chip->irq, 0, &chip->rmidi) < 0) { printk(KERN_ERR "es1938: unable to initialize MPU-401\n"); - } /*else - snd_es1938_mixer_bits(chip, ESSSB_IREG_MPU401CONTROL, 0x40, 0x40);*/ + } else { + // this line is vital for MIDI interrupt handling on ess-solo1 + // andreas@flying-snail.de + snd_es1938_mixer_bits(chip, ESSSB_IREG_MPU401CONTROL, 0x40, 0x40); + } -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) - chip->gameport.io = chip->game_port; - gameport_register_port(&chip->gameport); -#endif + snd_es1938_create_gameport(chip); if ((err = snd_card_register(card)) < 0) { snd_card_free(card); diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index d374f9b57..faf63ff19 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -586,6 +586,7 @@ struct snd_es1968 { spinlock_t reg_lock; spinlock_t ac97_lock; struct tasklet_struct hwvol_tq; + unsigned int in_suspend; /* Maestro Stuff */ u16 maestro_map[32]; @@ -605,8 +606,7 @@ struct snd_es1968 { #endif #ifdef SUPPORT_JOYSTICK - struct gameport gameport; - struct resource *res_joystick; + struct gameport *gameport; #endif }; @@ -1938,6 +1938,9 @@ static void es1968_update_hw_volume(unsigned long private_data) outb(0x88, chip->io_port + 0x1e); outb(0x88, chip->io_port + 0x1f); + if (chip->in_suspend) + return; + if (! chip->master_switch || ! chip->master_volume) return; @@ -2037,6 +2040,7 @@ snd_es1968_mixer(es1968_t *chip) if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0) return err; + pbus->no_vra = 1; /* ES1968 doesn't need VRA */ memset(&ac97, 0, sizeof(ac97)); ac97.private_data = chip; @@ -2403,25 +2407,26 @@ static void snd_es1968_start_irq(es1968_t *chip) /* * PM support */ -static int es1968_suspend(snd_card_t *card, unsigned int state) +static int es1968_suspend(snd_card_t *card, pm_message_t state) { es1968_t *chip = card->pm_private_data; if (! chip->do_pm) return 0; + chip->in_suspend = 1; snd_pcm_suspend_all(chip->pcm); snd_ac97_suspend(chip->ac97); snd_es1968_bob_stop(chip); snd_es1968_set_acpi(chip, ACPI_D3); pci_disable_device(chip->pci); - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } -static int es1968_resume(snd_card_t *card, unsigned int state) +static int es1968_resume(snd_card_t *card) { es1968_t *chip = card->pm_private_data; + struct list_head *p; if (! chip->do_pm) return 0; @@ -2442,15 +2447,81 @@ static int es1968_resume(snd_card_t *card, unsigned int state) /* restore ac97 state */ snd_ac97_resume(chip->ac97); + list_for_each(p, &chip->substream_list) { + esschan_t *es = list_entry(p, esschan_t, list); + switch (es->mode) { + case ESM_MODE_PLAY: + snd_es1968_playback_setup(chip, es, es->substream->runtime); + break; + case ESM_MODE_CAPTURE: + snd_es1968_capture_setup(chip, es, es->substream->runtime); + break; + } + } + /* start timer again */ if (chip->bobclient) snd_es1968_bob_start(chip); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); + chip->in_suspend = 0; return 0; } #endif /* CONFIG_PM */ +#ifdef SUPPORT_JOYSTICK +#define JOYSTICK_ADDR 0x200 +static int __devinit snd_es1968_create_gameport(es1968_t *chip, int dev) +{ + struct gameport *gp; + struct resource *r; + u16 val; + + if (!joystick[dev]) + return -ENODEV; + + r = request_region(JOYSTICK_ADDR, 8, "ES1968 gameport"); + if (!r) + return -EBUSY; + + chip->gameport = gp = gameport_allocate_port(); + if (!gp) { + printk(KERN_ERR "es1968: cannot allocate memory for gameport\n"); + release_resource(r); + kfree_nocheck(r); + return -ENOMEM; + } + + pci_read_config_word(chip->pci, ESM_LEGACY_AUDIO_CONTROL, &val); + pci_write_config_word(chip->pci, ESM_LEGACY_AUDIO_CONTROL, val | 0x04); + + gameport_set_name(gp, "ES1968 Gameport"); + gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci)); + gameport_set_dev_parent(gp, &chip->pci->dev); + gp->io = JOYSTICK_ADDR; + gameport_set_port_data(gp, r); + + gameport_register_port(gp); + + return 0; +} + +static void snd_es1968_free_gameport(es1968_t *chip) +{ + if (chip->gameport) { + struct resource *r = gameport_get_port_data(chip->gameport); + + gameport_unregister_port(chip->gameport); + chip->gameport = NULL; + + release_resource(r); + kfree_nocheck(r); + } +} +#else +static inline int snd_es1968_create_gameport(es1968_t *chip, int dev) { return -ENOSYS; } +static inline void snd_es1968_free_gameport(es1968_t *chip) { } +#endif + static int snd_es1968_free(es1968_t *chip) { if (chip->io_port) { @@ -2461,13 +2532,7 @@ static int snd_es1968_free(es1968_t *chip) if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); -#ifdef SUPPORT_JOYSTICK - if (chip->res_joystick) { - gameport_unregister_port(&chip->gameport); - release_resource(chip->res_joystick); - kfree_nocheck(chip->res_joystick); - } -#endif + snd_es1968_free_gameport(chip); snd_es1968_set_acpi(chip, ACPI_D3); chip->master_switch = NULL; chip->master_volume = NULL; @@ -2694,17 +2759,7 @@ static int __devinit snd_es1968_probe(struct pci_dev *pci, } } -#ifdef SUPPORT_JOYSTICK -#define JOYSTICK_ADDR 0x200 - if (joystick[dev] && - (chip->res_joystick = request_region(JOYSTICK_ADDR, 8, "ES1968 gameport")) != NULL) { - u16 val; - pci_read_config_word(pci, ESM_LEGACY_AUDIO_CONTROL, &val); - pci_write_config_word(pci, ESM_LEGACY_AUDIO_CONTROL, val | 0x04); - chip->gameport.io = JOYSTICK_ADDR; - gameport_register_port(&chip->gameport); - } -#endif + snd_es1968_create_gameport(chip, dev); snd_es1968_start_irq(chip); diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index b67761b84..08e7c5a29 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -64,7 +64,7 @@ module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for the FM801 soundcard."); module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable FM801 soundcard."); -module_param_array(tea575x_tuner, bool, NULL, 0444); +module_param_array(tea575x_tuner, int, NULL, 0444); MODULE_PARM_DESC(tea575x_tuner, "Enable TEA575x tuner."); /* diff --git a/sound/pci/ice1712/Makefile b/sound/pci/ice1712/Makefile index 8b5e37cf8..7837cef88 100644 --- a/sound/pci/ice1712/Makefile +++ b/sound/pci/ice1712/Makefile @@ -5,7 +5,7 @@ snd-ice17xx-ak4xxx-objs := ak4xxx.o snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o -snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o +snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o juli.o phase.o # Toplevel Module Dependency obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c index 77a8e278f..4405d96cb 100644 --- a/sound/pci/ice1712/aureon.c +++ b/sound/pci/ice1712/aureon.c @@ -27,18 +27,10 @@ * both controls in the future, once if wm codecs are reused in * many boards. * - * - writing over SPI is implemented but reading is not yet. - * the SPDIF-in channel status, etc. can be read from CS chip. - * * - DAC digital volumes are not implemented in the mixer. * if they show better response than DAC analog volumes, we can use them * instead. * - * - Aureon boards are equipped with AC97 codec, too. it's used to do - * the analog mixing but not easily controllable (it's not connected - * directly from envy24ht chip). so let's leave it as it is. - * - * * Lowlevel functions for AudioTrak Prodigy 7.1 (and possibly 192) cards * Copyright (c) 2003 Dimitromanolakis Apostolos <apostol@cs.utoronto.ca> * @@ -53,10 +45,6 @@ * we have no digital output, no capture, pretty bad clicks and poops * on mixer switch and other coll stuff. * - * - Prodigy boards are equipped with AC97 STAC9744 chip , too. it's used to do - * the analog mixing but not easily controllable (it's not connected - * directly from envy24ht chip). so let's leave it as it is. - * */ #include <sound/driver.h> @@ -89,6 +77,14 @@ #define WM_OUT_MUX2 0x1e /* output MUX */ #define WM_RESET 0x1f /* software reset */ +/* CS8415A registers */ +#define CS8415_CTRL1 0x01 +#define CS8415_CTRL2 0x02 +#define CS8415_QSUB 0x14 +#define CS8415_RATIO 0x1E +#define CS8415_C_BUFFER 0x20 +#define CS8415_ID 0x7F + static void aureon_ac97_write(ice1712_t *ice, unsigned short reg, unsigned short val) { unsigned int tmp; @@ -325,47 +321,109 @@ static int aureon_ac97_micboost_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_valu static void aureon_spi_write(ice1712_t *ice, unsigned int cs, unsigned int data, int bits) { unsigned int tmp; - unsigned int cscs; int i; tmp = snd_ice1712_gpio_read(ice); - if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71) - cscs = PRODIGY_CS8415_CS; - else - cscs = AUREON_CS8415_CS; - - snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_WM_DATA|AUREON_WM_CLK| - AUREON_WM_CS|cscs)); + snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_SPI_MOSI|AUREON_SPI_CLK| + AUREON_WM_CS|AUREON_CS8415_CS)); tmp |= AUREON_WM_RW; tmp &= ~cs; snd_ice1712_gpio_write(ice, tmp); udelay(1); for (i = bits - 1; i >= 0; i--) { - tmp &= ~AUREON_WM_CLK; + tmp &= ~AUREON_SPI_CLK; snd_ice1712_gpio_write(ice, tmp); udelay(1); if (data & (1 << i)) - tmp |= AUREON_WM_DATA; + tmp |= AUREON_SPI_MOSI; else - tmp &= ~AUREON_WM_DATA; + tmp &= ~AUREON_SPI_MOSI; snd_ice1712_gpio_write(ice, tmp); udelay(1); - tmp |= AUREON_WM_CLK; + tmp |= AUREON_SPI_CLK; snd_ice1712_gpio_write(ice, tmp); udelay(1); } - tmp &= ~AUREON_WM_CLK; + tmp &= ~AUREON_SPI_CLK; tmp |= cs; snd_ice1712_gpio_write(ice, tmp); udelay(1); - tmp |= AUREON_WM_CLK; + tmp |= AUREON_SPI_CLK; + snd_ice1712_gpio_write(ice, tmp); + udelay(1); +} + +/* + * Read data in SPI mode + */ +static void aureon_spi_read(ice1712_t *ice, unsigned int cs, unsigned int data, int bits, unsigned char *buffer, int size) { + int i, j; + unsigned int tmp; + + tmp = (snd_ice1712_gpio_read(ice) & ~AUREON_SPI_CLK) | AUREON_CS8415_CS|AUREON_WM_CS; + snd_ice1712_gpio_write(ice, tmp); + tmp &= ~cs; snd_ice1712_gpio_write(ice, tmp); udelay(1); + + for (i=bits-1; i>=0; i--) { + if (data & (1 << i)) + tmp |= AUREON_SPI_MOSI; + else + tmp &= ~AUREON_SPI_MOSI; + snd_ice1712_gpio_write(ice, tmp); + udelay(1); + + tmp |= AUREON_SPI_CLK; + snd_ice1712_gpio_write(ice, tmp); + udelay(1); + + tmp &= ~AUREON_SPI_CLK; + snd_ice1712_gpio_write(ice, tmp); + udelay(1); + } + + for (j=0; j<size; j++) { + unsigned char outdata = 0; + for (i=7; i>=0; i--) { + tmp = snd_ice1712_gpio_read(ice); + outdata <<= 1; + outdata |= (tmp & AUREON_SPI_MISO) ? 1 : 0; + udelay(1); + + tmp |= AUREON_SPI_CLK; + snd_ice1712_gpio_write(ice, tmp); + udelay(1); + + tmp &= ~AUREON_SPI_CLK; + snd_ice1712_gpio_write(ice, tmp); + udelay(1); + } + buffer[j] = outdata; + } + + tmp |= cs; + snd_ice1712_gpio_write(ice, tmp); +} + +static unsigned char aureon_cs8415_get(ice1712_t *ice, int reg) { + unsigned char val; + aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16); + aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, &val, 1); + return val; +} + +static void aureon_cs8415_read(ice1712_t *ice, int reg, unsigned char *buffer, int size) { + aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16); + aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, buffer, size); +} + +static void aureon_cs8415_put(ice1712_t *ice, int reg, unsigned char val) { + aureon_spi_write(ice, AUREON_CS8415_CS, 0x200000 | (reg << 8) | val, 24); } - /* * get the current register value of WM codec @@ -845,12 +903,32 @@ static int wm_adc_mux_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) "Mic", //AIN4 "AC97" //AIN5 }; + static char *universe_texts[] = { + "Aux1", //AIN1 + "CD", //AIN2 + "Phono", //AIN3 + "Line", //AIN4 + "Aux2", //AIN5 + "Mic", //AIN6 + "Aux3", //AIN7 + "AC97" //AIN8 + }; + ice1712_t *ice = snd_kcontrol_chip(kcontrol); + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 2; - uinfo->value.enumerated.items = 5; - 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]); + if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) { + uinfo->value.enumerated.items = 8; + if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) + uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; + strcpy(uinfo->value.enumerated.name, universe_texts[uinfo->value.enumerated.item]); + } + else { + uinfo->value.enumerated.items = 5; + 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; } @@ -885,6 +963,154 @@ static int wm_adc_mux_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucont return 0; } +/* + * CS8415 Input mux + */ +static int aureon_cs8415_mux_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) +{ + ice1712_t *ice = snd_kcontrol_chip(kcontrol); + static char *aureon_texts[] = { + "CD", //RXP0 + "Optical" //RXP1 + }; + static char *prodigy_texts[] = { + "CD", + "Coax" + }; + 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; + if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71) + strcpy(uinfo->value.enumerated.name, prodigy_texts[uinfo->value.enumerated.item]); + else + strcpy(uinfo->value.enumerated.name, aureon_texts[uinfo->value.enumerated.item]); + return 0; +} + +static int aureon_cs8415_mux_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + ice1712_t *ice = snd_kcontrol_chip(kcontrol); + + //snd_ice1712_save_gpio_status(ice); + //val = aureon_cs8415_get(ice, CS8415_CTRL2); + ucontrol->value.integer.value[0] = ice->spec.aureon.cs8415_mux; + //snd_ice1712_restore_gpio_status(ice); + return 0; +} + +static int aureon_cs8415_mux_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + ice1712_t *ice = snd_kcontrol_chip(kcontrol); + unsigned short oval, nval; + int change; + + snd_ice1712_save_gpio_status(ice); + oval = aureon_cs8415_get(ice, CS8415_CTRL2); + nval = oval & ~0x07; + nval |= ucontrol->value.integer.value[0] & 7; + change = (oval != nval); + if (change) + aureon_cs8415_put(ice, CS8415_CTRL2, nval); + snd_ice1712_restore_gpio_status(ice); + ice->spec.aureon.cs8415_mux = ucontrol->value.integer.value[0]; + return change; +} + +static int aureon_cs8415_rate_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; + uinfo->value.integer.max = 192000; + return 0; +} + +static int aureon_cs8415_rate_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + ice1712_t *ice = snd_kcontrol_chip(kcontrol); + unsigned char ratio; + ratio = aureon_cs8415_get(ice, CS8415_RATIO); + ucontrol->value.integer.value[0] = (int)((unsigned int)ratio * 750); + return 0; +} + +/* + * CS8415A Mute + */ +static int aureon_cs8415_mute_info (snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 1; + return 0; +} + +static int aureon_cs8415_mute_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + ice1712_t *ice = snd_kcontrol_chip(kcontrol); + snd_ice1712_save_gpio_status(ice); + ucontrol->value.integer.value[0] = (aureon_cs8415_get(ice, CS8415_CTRL1) & 0x20) ? 0 : 1; + snd_ice1712_restore_gpio_status(ice); + return 0; +} + +static int aureon_cs8415_mute_put (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + ice1712_t *ice = snd_kcontrol_chip(kcontrol); + unsigned char oval, nval; + int change; + snd_ice1712_save_gpio_status(ice); + oval = aureon_cs8415_get(ice, CS8415_CTRL1); + if (ucontrol->value.integer.value[0]) + nval = oval & ~0x20; + else + nval = oval | 0x20; + if ((change = (oval != nval))) + aureon_cs8415_put(ice, CS8415_CTRL1, nval); + snd_ice1712_restore_gpio_status(ice); + return change; +} + +/* + * CS8415A Q-Sub info + */ +static int aureon_cs8415_qsub_info (snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) { + uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; + uinfo->count = 10; + return 0; +} + +static int aureon_cs8415_qsub_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { + ice1712_t *ice = snd_kcontrol_chip(kcontrol); + + snd_ice1712_save_gpio_status(ice); + aureon_cs8415_read(ice, CS8415_QSUB, ucontrol->value.bytes.data, 10); + snd_ice1712_restore_gpio_status(ice); + + return 0; +} + +static int aureon_cs8415_spdif_info (snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) { + uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; + uinfo->count = 1; + return 0; +} + +static int aureon_cs8415_mask_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { + memset(ucontrol->value.iec958.status, 0xFF, 24); + return 0; +} + +static int aureon_cs8415_spdif_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { + ice1712_t *ice = snd_kcontrol_chip(kcontrol); + + snd_ice1712_save_gpio_status(ice); + aureon_cs8415_read(ice, CS8415_C_BUFFER, ucontrol->value.iec958.status, 24); + snd_ice1712_restore_gpio_status(ice); + return 0; +} + /* * Headphone Amplifier */ @@ -1142,7 +1368,7 @@ static snd_kcontrol_new_t wm_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Headphone Amplifier Switch", + .name = "External Amplifier", .info = aureon_hpamp_info, .get = aureon_hpamp_get, .put = aureon_hpamp_put @@ -1160,7 +1386,7 @@ static snd_kcontrol_new_t wm_controls[] __devinitdata = { .info = aureon_oversampling_info, .get = aureon_oversampling_get, .put = aureon_oversampling_put - }, + } }; static snd_kcontrol_new_t ac97_controls[] __devinitdata = { @@ -1246,12 +1472,165 @@ static snd_kcontrol_new_t ac97_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mic Boost", + .name = "Mic Boost (+20dB)", + .info = aureon_ac97_micboost_info, + .get = aureon_ac97_micboost_get, + .put = aureon_ac97_micboost_put + } +}; + +static snd_kcontrol_new_t universe_ac97_controls[] __devinitdata = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "AC97 Playback Switch", + .info = aureon_ac97_mmute_info, + .get = aureon_ac97_mmute_get, + .put = aureon_ac97_mmute_put, + .private_value = AC97_MASTER + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "AC97 Playback Volume", + .info = aureon_ac97_vol_info, + .get = aureon_ac97_vol_get, + .put = aureon_ac97_vol_put, + .private_value = AC97_MASTER|AUREON_AC97_STEREO + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "CD Playback Switch", + .info = aureon_ac97_mute_info, + .get = aureon_ac97_mute_get, + .put = aureon_ac97_mute_put, + .private_value = AC97_AUX + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "CD Playback Volume", + .info = aureon_ac97_vol_info, + .get = aureon_ac97_vol_get, + .put = aureon_ac97_vol_put, + .private_value = AC97_AUX|AUREON_AC97_STEREO + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Phono Playback Switch", + .info = aureon_ac97_mute_info, + .get = aureon_ac97_mute_get, + .put = aureon_ac97_mute_put, + .private_value = AC97_CD, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Phono Playback Volume", + .info = aureon_ac97_vol_info, + .get = aureon_ac97_vol_get, + .put = aureon_ac97_vol_put, + .private_value = AC97_CD|AUREON_AC97_STEREO + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Line Playback Switch", + .info = aureon_ac97_mute_info, + .get = aureon_ac97_mute_get, + .put = aureon_ac97_mute_put, + .private_value = AC97_LINE + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Line Playback Volume", + .info = aureon_ac97_vol_info, + .get = aureon_ac97_vol_get, + .put = aureon_ac97_vol_put, + .private_value = AC97_LINE|AUREON_AC97_STEREO + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Mic Playback Switch", + .info = aureon_ac97_mute_info, + .get = aureon_ac97_mute_get, + .put = aureon_ac97_mute_put, + .private_value = AC97_MIC + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Mic Playback Volume", + .info = aureon_ac97_vol_info, + .get = aureon_ac97_vol_get, + .put = aureon_ac97_vol_put, + .private_value = AC97_MIC + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Mic Boost (+20dB)", .info = aureon_ac97_micboost_info, .get = aureon_ac97_micboost_get, .put = aureon_ac97_micboost_put + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Aux Playback Switch", + .info = aureon_ac97_mute_info, + .get = aureon_ac97_mute_get, + .put = aureon_ac97_mute_put, + .private_value = AC97_VIDEO, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Aux Playback Volume", + .info = aureon_ac97_vol_info, + .get = aureon_ac97_vol_get, + .put = aureon_ac97_vol_put, + .private_value = AC97_VIDEO|AUREON_AC97_STEREO } }; + + +static snd_kcontrol_new_t cs8415_controls[] __devinitdata = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), + .info = aureon_cs8415_mute_info, + .get = aureon_cs8415_mute_get, + .put = aureon_cs8415_mute_put + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Source", + .info = aureon_cs8415_mux_info, + .get = aureon_cs8415_mux_get, + .put = aureon_cs8415_mux_put, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = SNDRV_CTL_NAME_IEC958("Q-subcode ",CAPTURE,DEFAULT), + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .info = aureon_cs8415_qsub_info, + .get = aureon_cs8415_qsub_get, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK), + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .info = aureon_cs8415_spdif_info, + .get = aureon_cs8415_mask_get + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT), + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .info = aureon_cs8415_spdif_info, + .get = aureon_cs8415_spdif_get + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Rate", + .access =SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .info = aureon_cs8415_rate_info, + .get = aureon_cs8415_rate_get + } +}; + static int __devinit aureon_add_controls(ice1712_t *ice) { @@ -1273,10 +1652,40 @@ static int __devinit aureon_add_controls(ice1712_t *ice) return err; } - for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) { - err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice)); - if (err < 0) - return err; + if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) { + for (i = 0; i < ARRAY_SIZE(universe_ac97_controls); i++) { + err = snd_ctl_add(ice->card, snd_ctl_new1(&universe_ac97_controls[i], ice)); + if (err < 0) + return err; + } + } + else { + for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) { + err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice)); + if (err < 0) + return err; + } + } + + { + unsigned char id; + snd_ice1712_save_gpio_status(ice); + id = aureon_cs8415_get(ice, CS8415_ID); + if (id != 0x41) + snd_printk("No CS8415 chip. Skipping CS8415 controls.\n"); + else if ((id & 0x0F) != 0x01) + snd_printk("Detected unsupported CS8415 rev. (%c)\n", (char)((id & 0x0F) + 'A' - 1)); + else { + for (i = 0; i< ARRAY_SIZE(cs8415_controls); i++) { + snd_kcontrol_t *kctl; + err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice))); + if (err < 0) + return err; + if (i > 1) + kctl->id.device = ice->pcm->device; + } + } + snd_ice1712_restore_gpio_status(ice); } return 0; @@ -1290,9 +1699,9 @@ static int __devinit aureon_init(ice1712_t *ice) { static unsigned short wm_inits_aureon[] = { /* These come first to reduce init pop noise */ - 0x1b, 0x005, /* ADC Mux (AC'97 source) */ - 0x1c, 0x00B, /* Out Mux1 (VOUT1 = ADC+AUX, VOUT2 = ADC) */ - 0x1d, 0x009, /* Out Mux2 (VOUT2 = ADC, VOUT3 = ADC) */ + 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 */ @@ -1375,7 +1784,6 @@ static int __devinit aureon_init(ice1712_t *ice) }; unsigned int tmp; unsigned short *p; - unsigned int cscs; int err, i; if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) { @@ -1396,23 +1804,17 @@ static int __devinit aureon_init(ice1712_t *ice) if ((err = aureon_ac97_init(ice)) != 0) return err; - if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71) - cscs = PRODIGY_CS8415_CS; - else - cscs = AUREON_CS8415_CS; - 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, ~(AUREON_WM_RESET|AUREON_WM_CS| - cscs|AUREON_HP_SEL)); + snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL)); tmp = snd_ice1712_gpio_read(ice); tmp &= ~AUREON_WM_RESET; snd_ice1712_gpio_write(ice, tmp); udelay(1); - tmp |= AUREON_WM_CS | cscs; + tmp |= AUREON_WM_CS | AUREON_CS8415_CS; snd_ice1712_gpio_write(ice, tmp); udelay(1); tmp |= AUREON_WM_RESET; @@ -1429,8 +1831,8 @@ static int __devinit aureon_init(ice1712_t *ice) /* initialize CS8415A codec */ for (p = cs_inits; *p != (unsigned short)-1; p++) - aureon_spi_write(ice, cscs, - *p | 0x200000, 24); + aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24); + ice->spec.aureon.cs8415_mux = 1; aureon_set_headphone_amp(ice, 1); @@ -1525,12 +1927,12 @@ struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = { { .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE, .name = "Terratec Aureon 7.1-Universe", - /* model not needed - identical with 7.1-Space */ + .model = "universe", .chip_init = aureon_init, .build_controls = aureon_add_controls, .eeprom_size = sizeof(aureon71_eeprom), .eeprom_data = aureon71_eeprom, - .driver = "Aureon71", + .driver = "Aureon71Universe", }, { .subvendor = VT1724_SUBDEVICE_PRODIGY71, diff --git a/sound/pci/ice1712/aureon.h b/sound/pci/ice1712/aureon.h index b98001973..95d515f36 100644 --- a/sound/pci/ice1712/aureon.h +++ b/sound/pci/ice1712/aureon.h @@ -38,10 +38,10 @@ extern struct snd_ice1712_card_info snd_vt1724_aureon_cards[]; /* GPIO bits */ #define AUREON_CS8415_CS (1 << 22) -#define AUREON_CS8415_CDTO (1 << 21) +#define AUREON_SPI_MISO (1 << 21) #define AUREON_WM_RESET (1 << 20) -#define AUREON_WM_CLK (1 << 19) -#define AUREON_WM_DATA (1 << 18) +#define AUREON_SPI_CLK (1 << 19) +#define AUREON_SPI_MOSI (1 << 18) #define AUREON_WM_RW (1 << 17) #define AUREON_AC97_RESET (1 << 16) #define AUREON_DIGITAL_SEL1 (1 << 15) @@ -53,8 +53,4 @@ extern struct snd_ice1712_card_info snd_vt1724_aureon_cards[]; #define AUREON_AC97_DATA_HIGH (1 << 8) #define AUREON_AC97_DATA_MASK 0xFF -/* Prodigy has different pin assignment for chip select */ -#define PRODIGY_CS8415_CS (1 << 23) -#define PRODIGY_CS8415_CDTO (1 << 22) - #endif /* __SOUND_AUREON_H */ diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c index 7708adc45..eb20f73be 100644 --- a/sound/pci/ice1712/delta.c +++ b/sound/pci/ice1712/delta.c @@ -530,6 +530,9 @@ static int __devinit snd_ice1712_delta_init(ice1712_t *ice) ice->num_total_dacs = 8; ice->num_total_adcs = 8; break; + case ICE1712_SUBDEVICE_DELTADIO2496: + ice->num_total_dacs = 4; /* two AK4324 codecs */ + break; case ICE1712_SUBDEVICE_VX442: ice->num_total_dacs = 4; ice->num_total_adcs = 4; diff --git a/sound/pci/ice1712/envy24ht.h b/sound/pci/ice1712/envy24ht.h index 375e5fb00..f7878020e 100644 --- a/sound/pci/ice1712/envy24ht.h +++ b/sound/pci/ice1712/envy24ht.h @@ -106,7 +106,7 @@ enum { #define VT1724_REG_I2C_BYTE_ADDR 0x11 /* byte */ #define VT1724_REG_I2C_DATA 0x12 /* byte */ #define VT1724_REG_I2C_CTRL 0x13 /* byte */ -#define VT1724_I2C_EEPROM 0x80 /* EEPROM exists */ +#define VT1724_I2C_EEPROM 0x80 /* 1 = EEPROM exists */ #define VT1724_I2C_BUSY 0x01 /* busy bit */ #define VT1724_REG_GPIO_DATA 0x14 /* word */ diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index fddd9e0e5..79fba6be3 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -1014,21 +1014,9 @@ static int snd_ice1712_pro_trigger(snd_pcm_substream_t *substream, static void snd_ice1712_set_pro_rate(ice1712_t *ice, unsigned int rate, int force) { unsigned long flags; - unsigned char val; + unsigned char val, old; unsigned int i; - spin_lock_irqsave(&ice->reg_lock, flags); - if (inb(ICEMT(ice, PLAYBACK_CONTROL)) & (ICE1712_CAPTURE_START_SHADOW| - ICE1712_PLAYBACK_PAUSE| - ICE1712_PLAYBACK_START)) { - spin_unlock_irqrestore(&ice->reg_lock, flags); - return; - } - if (!force && is_pro_rate_locked(ice)) { - spin_unlock_irqrestore(&ice->reg_lock, flags); - return; - } - switch (rate) { case 8000: val = 6; break; case 9600: val = 3; break; @@ -1049,8 +1037,22 @@ static void snd_ice1712_set_pro_rate(ice1712_t *ice, unsigned int rate, int forc rate = 48000; break; } - outb(val, ICEMT(ice, RATE)); + spin_lock_irqsave(&ice->reg_lock, flags); + if (inb(ICEMT(ice, PLAYBACK_CONTROL)) & (ICE1712_CAPTURE_START_SHADOW| + ICE1712_PLAYBACK_PAUSE| + ICE1712_PLAYBACK_START)) { + __out: + spin_unlock_irqrestore(&ice->reg_lock, flags); + return; + } + if (!force && is_pro_rate_locked(ice)) + goto __out; + + old = inb(ICEMT(ice, RATE)); + if (!force && old == val) + goto __out; + outb(val, ICEMT(ice, RATE)); spin_unlock_irqrestore(&ice->reg_lock, flags); if (ice->gpio.set_pro_rate) @@ -2405,6 +2407,7 @@ static int __devinit snd_ice1712_chip_init(ice1712_t *ice) udelay(200); snd_ice1712_write(ice, ICE1712_IREG_CONSUMER_POWERDOWN, 0); } + snd_ice1712_set_pro_rate(ice, 48000, 1); return 0; } @@ -2545,6 +2548,7 @@ static int __devinit snd_ice1712_create(snd_card_t * card, ice->cs8427_timeout = cs8427_timeout; spin_lock_init(&ice->reg_lock); init_MUTEX(&ice->gpio_mutex); + init_MUTEX(&ice->i2c_mutex); init_MUTEX(&ice->open_mutex); ice->gpio.set_mask = snd_ice1712_set_gpio_mask; ice->gpio.set_dir = snd_ice1712_set_gpio_dir; diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h index b5110fe77..8bb1c58c2 100644 --- a/sound/pci/ice1712/ice1712.h +++ b/sound/pci/ice1712/ice1712.h @@ -27,6 +27,7 @@ #include <sound/rawmidi.h> #include <sound/i2c.h> #include <sound/ak4xxx-adda.h> +#include <sound/ak4114.h> #include <sound/pcm.h> @@ -335,11 +336,13 @@ struct _snd_ice1712 { struct semaphore open_mutex; snd_pcm_substream_t *pcm_reserved[4]; + snd_pcm_hw_constraint_list_t *hw_rates; /* card-specific rate constraints */ unsigned int akm_codecs; akm4xxx_t *akm; struct snd_ice1712_spdif spdif; + struct semaphore i2c_mutex; /* I2C mutex for ICE1724 registers */ snd_i2c_bus_t *i2c; /* I2C bus */ snd_i2c_device_t *cs8427; /* CS8427 I2C device */ unsigned int cs8427_timeout; /* CS8427 reset timeout in HZ/100 */ @@ -355,16 +358,18 @@ struct _snd_ice1712 { unsigned int (*get_data)(ice1712_t *ice); /* misc operators - move to another place? */ void (*set_pro_rate)(ice1712_t *ice, unsigned int rate); + void (*i2s_mclk_changed)(ice1712_t *ice); } gpio; struct semaphore gpio_mutex; /* other board-specific data */ union { - /* additional i2c devices for EWS boards*/ + /* additional i2c devices for EWS boards */ snd_i2c_device_t *i2cdevs[3]; /* AC97 register cache for Aureon */ struct aureon_spec { unsigned short stac9744[64]; + unsigned int cs8415_mux; unsigned short master[2]; unsigned short vol[8]; } aureon; @@ -374,6 +379,10 @@ struct _snd_ice1712 { unsigned int config; unsigned short boxconfig[4]; } hoontech; + struct { + ak4114_t *ak4114; + unsigned int analog: 1; + } juli; } spec; }; @@ -476,7 +485,7 @@ struct snd_ice1712_card_info { char *driver; int (*chip_init)(ice1712_t *); int (*build_controls)(ice1712_t *); - int no_mpu401: 1; + unsigned int no_mpu401: 1; unsigned int eeprom_size; unsigned char *eeprom_data; }; diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 91c961dd4..95500f06f 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -47,6 +47,8 @@ #include "vt1720_mobo.h" #include "pontis.h" #include "prodigy192.h" +#include "juli.h" +#include "phase.h" MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); @@ -59,6 +61,8 @@ MODULE_SUPPORTED_DEVICE("{" VT1720_MOBO_DEVICE_DESC PONTIS_DEVICE_DESC PRODIGY192_DEVICE_DESC + JULI_DEVICE_DESC + PHASE_DEVICE_DESC "{VIA,VT1720}," "{VIA,VT1724}," "{ICEnsemble,Generic ICE1724}," @@ -401,23 +405,11 @@ static void snd_vt1724_set_pro_rate(ice1712_t *ice, unsigned int rate, int force { unsigned long flags; unsigned char val, old; - unsigned int i; + unsigned int i, mclk_change; if (rate > get_max_rate(ice)) return; - spin_lock_irqsave(&ice->reg_lock, flags); - if ((inb(ICEMT1724(ice, DMA_CONTROL)) & DMA_STARTS) || - (inb(ICEMT1724(ice, DMA_PAUSE)) & DMA_PAUSES)) { - /* running? we cannot change the rate now... */ - spin_unlock_irqrestore(&ice->reg_lock, flags); - return; - } - if (!force && is_pro_rate_locked(ice)) { - spin_unlock_irqrestore(&ice->reg_lock, flags); - return; - } - switch (rate) { case 8000: val = 6; break; case 9600: val = 3; break; @@ -439,8 +431,21 @@ static void snd_vt1724_set_pro_rate(ice1712_t *ice, unsigned int rate, int force val = 0; break; } + + spin_lock_irqsave(&ice->reg_lock, flags); + if ((inb(ICEMT1724(ice, DMA_CONTROL)) & DMA_STARTS) || + (inb(ICEMT1724(ice, DMA_PAUSE)) & DMA_PAUSES)) { + /* running? we cannot change the rate now... */ + spin_unlock_irqrestore(&ice->reg_lock, flags); + return; + } + if (!force && is_pro_rate_locked(ice)) { + spin_unlock_irqrestore(&ice->reg_lock, flags); + return; + } + old = inb(ICEMT1724(ice, RATE)); - if (old != val) + if (force || old != val) outb(val, ICEMT1724(ice, RATE)); else if (rate == ice->cur_rate) { spin_unlock_irqrestore(&ice->reg_lock, flags); @@ -450,6 +455,7 @@ static void snd_vt1724_set_pro_rate(ice1712_t *ice, unsigned int rate, int force ice->cur_rate = rate; /* check MT02 */ + mclk_change = 0; if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) { val = old = inb(ICEMT1724(ice, I2S_FORMAT)); if (rate > 96000) @@ -458,25 +464,23 @@ static void snd_vt1724_set_pro_rate(ice1712_t *ice, unsigned int rate, int force val &= ~VT1724_MT_I2S_MCLK_128X; /* 256x MCLK */ if (val != old) { outb(val, ICEMT1724(ice, I2S_FORMAT)); - if (ice->eeprom.subvendor == VT1724_SUBDEVICE_REVOLUTION71) { - /* FIXME: is this revo only? */ - /* assert PRST# to converters; MT05 bit 7 */ - outb(inb(ICEMT1724(ice, AC97_CMD)) | 0x80, ICEMT1724(ice, AC97_CMD)); - spin_unlock_irqrestore(&ice->reg_lock, flags); - mdelay(5); - spin_lock_irqsave(&ice->reg_lock, flags); - /* deassert PRST# */ - outb(inb(ICEMT1724(ice, AC97_CMD)) & ~0x80, ICEMT1724(ice, AC97_CMD)); - } + mclk_change = 1; } } spin_unlock_irqrestore(&ice->reg_lock, flags); + if (mclk_change && ice->gpio.i2s_mclk_changed) + ice->gpio.i2s_mclk_changed(ice); + if (ice->gpio.set_pro_rate) + ice->gpio.set_pro_rate(ice, rate); + /* set up codecs */ for (i = 0; i < ice->akm_codecs; i++) { if (ice->akm[i].ops.set_rate_val) ice->akm[i].ops.set_rate_val(&ice->akm[i], rate); } + if (ice->spdif.ops.setup_rate) + ice->spdif.ops.setup_rate(ice, rate); } static int snd_vt1724_pcm_hw_params(snd_pcm_substream_t * substream, @@ -714,6 +718,13 @@ static snd_pcm_hardware_t snd_vt1724_2ch_stereo = static int set_rate_constraints(ice1712_t *ice, snd_pcm_substream_t *substream) { snd_pcm_runtime_t *runtime = substream->runtime; + if (ice->hw_rates) { + /* hardware specific */ + runtime->hw.rate_min = ice->hw_rates->list[0]; + runtime->hw.rate_max = ice->hw_rates->list[ice->hw_rates->count - 1]; + runtime->hw.rates = SNDRV_PCM_RATE_KNOT; + return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, ice->hw_rates); + } if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) { /* I2S */ /* VT1720 doesn't support more than 96kHz */ @@ -1814,7 +1825,7 @@ static snd_kcontrol_new_t snd_vt1724_mixer_pro_analog_route __devinitdata = { static snd_kcontrol_new_t snd_vt1724_mixer_pro_spdif_route __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "IEC958 Playback Route", + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route", .info = snd_vt1724_pro_route_info, .get = snd_vt1724_pro_route_spdif_get, .put = snd_vt1724_pro_route_spdif_put, @@ -1866,6 +1877,8 @@ static struct snd_ice1712_card_info *card_tables[] __devinitdata = { snd_vt1720_mobo_cards, snd_vt1720_pontis_cards, snd_vt1724_prodigy192_cards, + snd_vt1724_juli_cards, + snd_vt1724_phase_cards, NULL, }; @@ -1878,23 +1891,34 @@ static void wait_i2c_busy(ice1712_t *ice) int t = 0x10000; while ((inb(ICEREG1724(ice, I2C_CTRL)) & VT1724_I2C_BUSY) && t--) ; + if (t == -1) + printk(KERN_ERR "ice1724: i2c busy timeout\n"); } unsigned char snd_vt1724_read_i2c(ice1712_t *ice, unsigned char dev, unsigned char addr) { + unsigned char val; + + down(&ice->i2c_mutex); outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR)); outb(dev & ~VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR)); wait_i2c_busy(ice); - return inb(ICEREG1724(ice, I2C_DATA)); + val = inb(ICEREG1724(ice, I2C_DATA)); + up(&ice->i2c_mutex); + //printk("i2c_read: [0x%x,0x%x] = 0x%x\n", dev, addr, val); + return val; } void snd_vt1724_write_i2c(ice1712_t *ice, unsigned char dev, unsigned char addr, unsigned char data) { + down(&ice->i2c_mutex); wait_i2c_busy(ice); + //printk("i2c_write: [0x%x,0x%x] = 0x%x\n", dev, addr, data); outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR)); outb(data, ICEREG1724(ice, I2C_DATA)); outb(dev | VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR)); wait_i2c_busy(ice); + up(&ice->i2c_mutex); } static int __devinit snd_vt1724_read_eeprom(ice1712_t *ice, const char *modelname) @@ -1906,7 +1930,8 @@ static int __devinit snd_vt1724_read_eeprom(ice1712_t *ice, const char *modelnam if (! modelname || ! *modelname) { ice->eeprom.subvendor = 0; if ((inb(ICEREG1724(ice, I2C_CTRL)) & VT1724_I2C_EEPROM) != 0) - ice->eeprom.subvendor = (snd_vt1724_read_i2c(ice, dev, 0x00) << 0) | + ice->eeprom.subvendor = + (snd_vt1724_read_i2c(ice, dev, 0x00) << 0) | (snd_vt1724_read_i2c(ice, dev, 0x01) << 8) | (snd_vt1724_read_i2c(ice, dev, 0x02) << 16) | (snd_vt1724_read_i2c(ice, dev, 0x03) << 24); @@ -2114,6 +2139,7 @@ static int __devinit snd_vt1724_create(snd_card_t * card, spin_lock_init(&ice->reg_lock); init_MUTEX(&ice->gpio_mutex); init_MUTEX(&ice->open_mutex); + init_MUTEX(&ice->i2c_mutex); ice->gpio.set_mask = snd_vt1724_set_gpio_mask; ice->gpio.set_dir = snd_vt1724_set_gpio_dir; ice->gpio.set_data = snd_vt1724_set_gpio_data; diff --git a/sound/pci/ice1712/revo.c b/sound/pci/ice1712/revo.c index 82db619b2..d48d42524 100644 --- a/sound/pci/ice1712/revo.c +++ b/sound/pci/ice1712/revo.c @@ -33,6 +33,15 @@ #include "envy24ht.h" #include "revo.h" +static void revo_i2s_mclk_changed(ice1712_t *ice) +{ + /* assert PRST# to converters; MT05 bit 7 */ + outb(inb(ICEMT1724(ice, AC97_CMD)) | 0x80, ICEMT1724(ice, AC97_CMD)); + mdelay(5); + /* deassert PRST# */ + outb(inb(ICEMT1724(ice, AC97_CMD)) & ~0x80, ICEMT1724(ice, AC97_CMD)); +} + /* * change the rate of envy24HT, AK4355 and AK4381 */ @@ -119,6 +128,17 @@ static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = { .mask_flags = 0, }; +static unsigned int rates[] = { + 32000, 44100, 48000, 64000, 88200, 96000, + 176400, 192000, +}; + +static snd_pcm_hw_constraint_list_t revo_rates = { + .count = ARRAY_SIZE(rates), + .list = rates, + .mask = 0, +}; + static int __devinit revo_init(ice1712_t *ice) { akm4xxx_t *ak; @@ -135,6 +155,8 @@ static int __devinit revo_init(ice1712_t *ice) return -EINVAL; } + ice->gpio.i2s_mclk_changed = revo_i2s_mclk_changed; + /* second stage of initialization, analog parts and others */ ak = ice->akm = kcalloc(2, sizeof(akm4xxx_t), GFP_KERNEL); if (! ak) @@ -151,6 +173,8 @@ static int __devinit revo_init(ice1712_t *ice) break; } + ice->hw_rates = &revo_rates; /* AK codecs don't support lower than 32k */ + return 0; } diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index d8af0046c..75c065ee6 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -55,6 +55,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH}," "{Intel,ICH6}," "{Intel,ICH7}," "{Intel,6300ESB}," + "{Intel,ESB2}," "{Intel,MX440}," "{SiS,SI7012}," "{NVidia,nForce Audio}," @@ -67,7 +68,7 @@ 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 */ static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; -static int ac97_quirk[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = AC97_TUNE_DEFAULT}; +static char *ac97_quirk[SNDRV_CARDS]; static int buggy_irq[SNDRV_CARDS]; static int xbox[SNDRV_CARDS]; @@ -83,7 +84,7 @@ module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable Intel i8x0 soundcard."); module_param_array(ac97_clock, int, NULL, 0444); MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = auto-detect)."); -module_param_array(ac97_quirk, int, NULL, 0444); +module_param_array(ac97_quirk, charp, NULL, 0444); MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware."); module_param_array(buggy_irq, bool, NULL, 0444); MODULE_PARM_DESC(buggy_irq, "Enable workaround for buggy interrupts on some motherboards."); @@ -118,12 +119,15 @@ MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 c #ifndef PCI_DEVICE_ID_INTEL_ESB_5 #define PCI_DEVICE_ID_INTEL_ESB_5 0x25a6 #endif -#ifndef PCI_DEVICE_ID_INTEL_ICH6_3 -#define PCI_DEVICE_ID_INTEL_ICH6_3 0x266e +#ifndef PCI_DEVICE_ID_INTEL_ICH6_18 +#define PCI_DEVICE_ID_INTEL_ICH6_18 0x266e #endif #ifndef PCI_DEVICE_ID_INTEL_ICH7_20 #define PCI_DEVICE_ID_INTEL_ICH7_20 0x27de #endif +#ifndef PCI_DEVICE_ID_INTEL_ESB2_14 +#define PCI_DEVICE_ID_INTEL_ESB2_14 0x2698 +#endif #ifndef PCI_DEVICE_ID_SI_7012 #define PCI_DEVICE_ID_SI_7012 0x7012 #endif @@ -426,7 +430,6 @@ struct _snd_intel8x0 { unsigned int ac97_sdin[3]; spinlock_t reg_lock; - spinlock_t ac97_lock; u32 bdbars_count; struct snd_dma_buffer bdbars; @@ -444,6 +447,7 @@ static struct pci_device_id snd_intel8x0_ids[] = { { 0x8086, 0x25a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL_ICH4 }, /* ESB */ { 0x8086, 0x266e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL_ICH4 }, /* ICH6 */ { 0x8086, 0x27de, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL_ICH4 }, /* ICH7 */ + { 0x8086, 0x2698, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL_ICH4 }, /* ESB2 */ { 0x8086, 0x7195, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 440MX */ { 0x1039, 0x7012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_SIS }, /* SI7012 */ { 0x10de, 0x01b1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* NFORCE */ @@ -595,13 +599,11 @@ static void snd_intel8x0_codec_write(ac97_t *ac97, { intel8x0_t *chip = ac97->private_data; - spin_lock(&chip->ac97_lock); if (snd_intel8x0_codec_semaphore(chip, ac97->num) < 0) { if (! chip->in_ac97_init) snd_printk("codec_write %d: semaphore is not ready for register 0x%x\n", ac97->num, reg); } iaputword(chip, reg + ac97->num * 0x80, val); - spin_unlock(&chip->ac97_lock); } static unsigned short snd_intel8x0_codec_read(ac97_t *ac97, @@ -611,7 +613,6 @@ static unsigned short snd_intel8x0_codec_read(ac97_t *ac97, unsigned short res; unsigned int tmp; - spin_lock(&chip->ac97_lock); if (snd_intel8x0_codec_semaphore(chip, ac97->num) < 0) { if (! chip->in_ac97_init) snd_printk("codec_read %d: semaphore is not ready for register 0x%x\n", ac97->num, reg); @@ -626,7 +627,6 @@ static unsigned short snd_intel8x0_codec_read(ac97_t *ac97, res = 0xffff; } } - spin_unlock(&chip->ac97_lock); return res; } @@ -634,7 +634,6 @@ static void snd_intel8x0_codec_read_test(intel8x0_t *chip, unsigned int codec) { unsigned int tmp; - spin_lock(&chip->ac97_lock); if (snd_intel8x0_codec_semaphore(chip, codec) >= 0) { iagetword(chip, codec * 0x80); if ((tmp = igetdword(chip, ICHREG(GLOB_STA))) & ICH_RCS) { @@ -642,7 +641,6 @@ static void snd_intel8x0_codec_read_test(intel8x0_t *chip, unsigned int codec) iputdword(chip, ICHREG(GLOB_STA), tmp & ~(ICH_SRI|ICH_PRI|ICH_TRI|ICH_GSCI)); } } - spin_unlock(&chip->ac97_lock); } /* @@ -675,7 +673,6 @@ static unsigned short snd_intel8x0_ali_codec_read(ac97_t *ac97, unsigned short r intel8x0_t *chip = ac97->private_data; unsigned short data = 0xffff; - spin_lock(&chip->ac97_lock); if (snd_intel8x0_ali_codec_semaphore(chip)) goto __err; reg |= ALI_CPR_ADDR_READ; @@ -686,7 +683,6 @@ static unsigned short snd_intel8x0_ali_codec_read(ac97_t *ac97, unsigned short r goto __err; data = igetword(chip, ICHREG(ALI_SPR)); __err: - spin_unlock(&chip->ac97_lock); return data; } @@ -694,17 +690,13 @@ static void snd_intel8x0_ali_codec_write(ac97_t *ac97, unsigned short reg, unsig { intel8x0_t *chip = ac97->private_data; - spin_lock(&chip->ac97_lock); - if (snd_intel8x0_ali_codec_semaphore(chip)) { - spin_unlock(&chip->ac97_lock); + if (snd_intel8x0_ali_codec_semaphore(chip)) return; - } iputword(chip, ICHREG(ALI_CPR), val); if (ac97->num) reg |= ALI_CPR_ADDR_SECONDARY; iputword(chip, ICHREG(ALI_CPR_ADDR), reg); snd_intel8x0_ali_codec_ready(chip, ALI_CSPSR_WRITE_OK); - spin_unlock(&chip->ac97_lock); } @@ -948,7 +940,6 @@ static int snd_intel8x0_hw_params(snd_pcm_substream_t * substream, intel8x0_t *chip = snd_pcm_substream_chip(substream); ichdev_t *ichdev = get_ichdev(substream); snd_pcm_runtime_t *runtime = substream->runtime; - size_t size = params_buffer_bytes(hw_params); int dbl = params_rate(hw_params) > 48000; int err; @@ -1073,7 +1064,7 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(snd_pcm_substream_t * substrea intel8x0_t *chip = snd_pcm_substream_chip(substream); ichdev_t *ichdev = get_ichdev(substream); size_t ptr1, ptr; - int civ, timeout = 10; + int civ, timeout = 100; unsigned int position; spin_lock(&chip->reg_lock); @@ -1081,8 +1072,10 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(snd_pcm_substream_t * substrea civ = igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV); ptr1 = igetword(chip, ichdev->reg_offset + ichdev->roff_picb); position = ichdev->position; - if (ptr1 == 0) - udelay(1); + if (ptr1 == 0) { + udelay(10); + continue; + } if (civ == igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV) && ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb)) break; @@ -1743,6 +1736,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { .name = "Compaq Evo D510C", .type = AC97_TUNE_HP_ONLY }, + { + .vendor = 0x0e11, + .device = 0x0860, + .name = "HP/Compaq nx7010", + .type = AC97_TUNE_MUTE_LED + }, { .vendor = 0x1014, .device = 0x1f00, @@ -1767,6 +1766,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { .name = "Dell Optiplex GX260", /* AD1981A */ .type = AC97_TUNE_HP_ONLY }, + { + .vendor = 0x1028, + .device = 0x012c, + .name = "Dell Precision 650", /* AD1981A */ + .type = AC97_TUNE_HP_ONLY + }, { .vendor = 0x1028, .device = 0x012d, @@ -1779,10 +1784,40 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { .name = "Dell", /* which model? AD1981B*/ .type = AC97_TUNE_HP_ONLY }, + { + .vendor = 0x1028, + .device = 0x0163, + .name = "Dell Unknown", /* STAC9750/51 */ + .type = AC97_TUNE_HP_ONLY + }, + { + .vendor = 0x103c, + .device = 0x006d, + .name = "HP zv5000", + .type = AC97_TUNE_MUTE_LED /*AD1981B*/ + }, { /* FIXME: which codec? */ .vendor = 0x103c, .device = 0x00c3, - .name = "Hewlett-Packard onboard", + .name = "HP xw6000", + .type = AC97_TUNE_HP_ONLY + }, + { + .vendor = 0x103c, + .device = 0x088c, + .name = "HP nc8000", + .type = AC97_TUNE_MUTE_LED + }, + { + .vendor = 0x103c, + .device = 0x0890, + .name = "HP nc6000", + .type = AC97_TUNE_MUTE_LED + }, + { + .vendor = 0x103c, + .device = 0x129d, + .name = "HP xw8000", .type = AC97_TUNE_HP_ONLY }, { @@ -1791,6 +1826,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { .name = "HP xw8200", /* AD1981B*/ .type = AC97_TUNE_HP_ONLY }, + { + .vendor = 0x103c, + .device = 0x12f2, + .name = "HP xw6200", + .type = AC97_TUNE_HP_ONLY + }, { .vendor = 0x103c, .device = 0x3008, @@ -1815,6 +1856,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { .name = "Fujitsu-Siemens E4010", .type = AC97_TUNE_HP_ONLY }, + { + .vendor = 0x10cf, + .device = 0x1253, + .name = "Fujitsu S6210", /* STAC9750/51 */ + .type = AC97_TUNE_HP_ONLY + }, { .vendor = 0x10f1, .device = 0x2665, @@ -1927,7 +1974,7 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { { } /* terminator */ }; -static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock, int ac97_quirk) +static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock, const char *quirk_override) { ac97_bus_t *pbus; ac97_template_t ac97; @@ -2008,7 +2055,8 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock, int ac /* FIXME: my test board doesn't work well with VRA... */ if (chip->device_type == DEVICE_ALI) pbus->no_vra = 1; - pbus->dra = 1; + else + pbus->dra = 1; chip->ac97_bus = pbus; ac97.pci = chip->pci; @@ -2023,7 +2071,7 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock, int ac } } /* tune up the primary codec */ - snd_ac97_tune_hardware(chip->ac97[0], ac97_quirks, ac97_quirk); + snd_ac97_tune_hardware(chip->ac97[0], ac97_quirks, quirk_override); /* enable separate SDINs for ICH4 */ if (chip->device_type == DEVICE_INTEL_ICH4) pbus->isdin = 1; @@ -2316,7 +2364,7 @@ static int snd_intel8x0_free(intel8x0_t *chip) /* * power management */ -static int intel8x0_suspend(snd_card_t *card, unsigned int state) +static int intel8x0_suspend(snd_card_t *card, pm_message_t state) { intel8x0_t *chip = card->pm_private_data; int i; @@ -2338,11 +2386,10 @@ static int intel8x0_suspend(snd_card_t *card, unsigned int state) if (chip->ac97[i]) snd_ac97_suspend(chip->ac97[i]); pci_disable_device(chip->pci); - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } -static int intel8x0_resume(snd_card_t *card, unsigned int state) +static int intel8x0_resume(snd_card_t *card) { intel8x0_t *chip = card->pm_private_data; int i; @@ -2371,7 +2418,6 @@ static int intel8x0_resume(snd_card_t *card, unsigned int state) } } - snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; } #endif /* CONFIG_PM */ @@ -2560,7 +2606,6 @@ static int __devinit snd_intel8x0_create(snd_card_t * card, return -ENOMEM; } spin_lock_init(&chip->reg_lock); - spin_lock_init(&chip->ac97_lock); chip->device_type = device_type; chip->card = card; chip->pci = pci; @@ -2712,8 +2757,9 @@ static struct shortname_table { { PCI_DEVICE_ID_INTEL_ICH4, "Intel 82801DB-ICH4" }, { PCI_DEVICE_ID_INTEL_ICH5, "Intel ICH5" }, { PCI_DEVICE_ID_INTEL_ESB_5, "Intel 6300ESB" }, - { PCI_DEVICE_ID_INTEL_ICH6_3, "Intel ICH6" }, + { PCI_DEVICE_ID_INTEL_ICH6_18, "Intel ICH6" }, { PCI_DEVICE_ID_INTEL_ICH7_20, "Intel ICH7" }, + { PCI_DEVICE_ID_INTEL_ESB2_14, "Intel ESB2" }, { PCI_DEVICE_ID_SI_7012, "SiS SI7012" }, { PCI_DEVICE_ID_NVIDIA_MCP_AUDIO, "NVidia nForce" }, { PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO, "NVidia nForce2" }, @@ -2821,11 +2867,7 @@ static struct pci_driver driver = { static int __init alsa_card_intel8x0_init(void) { - int err; - - if ((err = pci_module_init(&driver)) < 0) - return err; - return 0; + return pci_module_init(&driver); } static void __exit alsa_card_intel8x0_exit(void) diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index e97b41452..67da096d6 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -35,6 +35,7 @@ #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>"); @@ -46,6 +47,8 @@ MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH}," "{Intel,82801CA-ICH3}," "{Intel,82801DB-ICH4}," "{Intel,ICH5}," + "{Intel,ICH6}," + "{Intel,ICH7}," "{Intel,MX440}," "{SiS,7013}," "{NVidia,NForce Modem}," @@ -54,7 +57,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH}," "{NVidia,NForce3 Modem}," "{AMD,AMD768}}"); -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ +static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the first card */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; @@ -93,6 +96,12 @@ MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = auto-detect)."); #ifndef PCI_DEVICE_ID_INTEL_ICH5_6 #define PCI_DEVICE_ID_INTEL_ICH5_6 0x24d6 #endif +#ifndef PCI_DEVICE_ID_INTEL_ICH6_6 +#define PCI_DEVICE_ID_INTEL_ICH6_6 0x266d +#endif +#ifndef PCI_DEVICE_ID_INTEL_ICH7_6 +#define PCI_DEVICE_ID_INTEL_ICH7_6 0x27dd +#endif #ifndef PCI_DEVICE_ID_SI_7013 #define PCI_DEVICE_ID_SI_7013 0x7013 #endif @@ -247,13 +256,12 @@ struct _snd_intel8x0m { snd_pcm_t *pcm[2]; ichdev_t ichd[2]; - int in_ac97_init: 1; + unsigned int in_ac97_init: 1; ac97_bus_t *ac97_bus; ac97_t *ac97; spinlock_t reg_lock; - spinlock_t ac97_lock; struct snd_dma_buffer bdbars; u32 bdbars_count; @@ -269,6 +277,8 @@ static struct pci_device_id snd_intel8x0m_ids[] = { { 0x8086, 0x2486, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* ICH3 */ { 0x8086, 0x24c6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* ICH4 */ { 0x8086, 0x24d6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* ICH5 */ + { 0x8086, 0x266d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* ICH6 */ + { 0x8086, 0x27dd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* ICH7 */ { 0x8086, 0x7196, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 440MX */ { 0x1022, 0x7446, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* AMD768 */ { 0x1039, 0x7013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_SIS }, /* SI7013 */ @@ -282,9 +292,60 @@ 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 */ @@ -411,13 +472,11 @@ static void snd_intel8x0_codec_write(ac97_t *ac97, { intel8x0_t *chip = ac97->private_data; - spin_lock(&chip->ac97_lock); if (snd_intel8x0m_codec_semaphore(chip, ac97->num) < 0) { if (! chip->in_ac97_init) snd_printk("codec_write %d: semaphore is not ready for register 0x%x\n", ac97->num, reg); } iaputword(chip, reg + ac97->num * 0x80, val); - spin_unlock(&chip->ac97_lock); } static unsigned short snd_intel8x0_codec_read(ac97_t *ac97, @@ -427,7 +486,6 @@ static unsigned short snd_intel8x0_codec_read(ac97_t *ac97, unsigned short res; unsigned int tmp; - spin_lock(&chip->ac97_lock); if (snd_intel8x0m_codec_semaphore(chip, ac97->num) < 0) { if (! chip->in_ac97_init) snd_printk("codec_read %d: semaphore is not ready for register 0x%x\n", ac97->num, reg); @@ -442,7 +500,6 @@ static unsigned short snd_intel8x0_codec_read(ac97_t *ac97, res = 0xffff; } } - spin_unlock(&chip->ac97_lock); return res; } @@ -643,17 +700,12 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(snd_pcm_substream_t * substrea static int snd_intel8x0m_pcm_trigger(snd_pcm_substream_t *substream, int cmd) { - ichdev_t *ichdev = get_ichdev(substream); /* hook off/on on start/stop */ - /* TODO: move it to ac97 controls */ + /* Moved this to mixer control */ switch (cmd) { case SNDRV_PCM_TRIGGER_START: - snd_ac97_update_bits(ichdev->ac97, AC97_GPIO_STATUS, - AC97_GPIO_LINE1_OH, AC97_GPIO_LINE1_OH); break; case SNDRV_PCM_TRIGGER_STOP: - snd_ac97_update_bits(ichdev->ac97, AC97_GPIO_STATUS, - AC97_GPIO_LINE1_OH, ~AC97_GPIO_LINE1_OH); break; default: return -EINVAL; @@ -895,6 +947,7 @@ 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, @@ -926,10 +979,14 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock) return err; } chip->ac97 = x97; - if(ac97_is_modem(x97) && !chip->ichd[ICHD_MDMIN].ac97 ) { + if(ac97_is_modem(x97) && !chip->ichd[ICHD_MDMIN].ac97) { 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; @@ -1083,7 +1140,7 @@ static int snd_intel8x0_free(intel8x0_t *chip) /* * power management */ -static int intel8x0m_suspend(snd_card_t *card, unsigned int state) +static int intel8x0m_suspend(snd_card_t *card, pm_message_t state) { intel8x0_t *chip = card->pm_private_data; int i; @@ -1093,11 +1150,10 @@ static int intel8x0m_suspend(snd_card_t *card, unsigned int state) if (chip->ac97) snd_ac97_suspend(chip->ac97); pci_disable_device(chip->pci); - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } -static int intel8x0m_resume(snd_card_t *card, unsigned int state) +static int intel8x0m_resume(snd_card_t *card) { intel8x0_t *chip = card->pm_private_data; pci_enable_device(chip->pci); @@ -1106,7 +1162,6 @@ static int intel8x0m_resume(snd_card_t *card, unsigned int state) if (chip->ac97) snd_ac97_resume(chip->ac97); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; } #endif /* CONFIG_PM */ @@ -1179,7 +1234,6 @@ static int __devinit snd_intel8x0m_create(snd_card_t * card, return -ENOMEM; } spin_lock_init(&chip->reg_lock); - spin_lock_init(&chip->ac97_lock); chip->device_type = device_type; chip->card = card; chip->pci = pci; @@ -1306,6 +1360,8 @@ static struct shortname_table { { PCI_DEVICE_ID_INTEL_ICH3_6, "Intel 82801CA-ICH3" }, { PCI_DEVICE_ID_INTEL_ICH4_6, "Intel 82801DB-ICH4" }, { PCI_DEVICE_ID_INTEL_ICH5_6, "Intel ICH5" }, + { PCI_DEVICE_ID_INTEL_ICH6_6, "Intel ICH6" }, + { PCI_DEVICE_ID_INTEL_ICH7_6, "Intel ICH7" }, { 0x7446, "AMD AMD768" }, { PCI_DEVICE_ID_SI_7013, "SiS SI7013" }, { PCI_DEVICE_ID_NVIDIA_MCP_MODEM, "NVidia nForce" }, diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 21367171f..bb1de2008 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c @@ -51,7 +51,7 @@ //#define K1212_LARGEALLOC 1 // ---------------------------------------------------------------------------- -// the following enum defines the valid states of the Korg 1212 I/O card. +// Valid states of the Korg 1212 I/O card. // ---------------------------------------------------------------------------- typedef enum { K1212_STATE_NONEXISTENT, // there is no card here @@ -85,6 +85,8 @@ typedef enum { K1212_DB_ConfigureMiscMemory = 6, // tells card where other buffers are. K1212_DB_TriggerFromAdat = 7, // tells card to trigger from Adat at a specific // timecode value. + K1212_DB_DMAERROR = 0x80, // DMA Error - the PCI bus is congestioned. + K1212_DB_CARDSTOPPED = 0x81, // Card has stopped by user request. K1212_DB_RebootCard = 0xA0, // instructs the card to reboot. K1212_DB_BootFromDSPPage4 = 0xA4, // instructs the card to boot from the DSP microcode // on page 4 (local page to card). @@ -93,11 +95,9 @@ typedef enum { K1212_DB_StartDSPDownload = 0xAF // tells the card to download its DSP firmware. } korg1212_dbcnst_t; -#define K1212_ISRCODE_DMAERROR 0x80 -#define K1212_ISRCODE_CARDSTOPPED 0x81 // ---------------------------------------------------------------------------- -// The following enumeration defines return codes for DeviceIoControl() calls +// The following enumeration defines return codes // to the Korg 1212 I/O driver. // ---------------------------------------------------------------------------- typedef enum { @@ -116,11 +116,6 @@ typedef enum { K1212_CMDRET_NoAckFromCard, // the card never acknowledged a command K1212_CMDRET_BadParams, // bad parameters were provided by the caller - // -------------------------------------------------------------- - // the following return errors are specific to the wave device - // driver interface. These will not be encountered by users of - // the 32 bit DIOC interface (a.k.a. custom or native API). - // -------------------------------------------------------------- K1212_CMDRET_BadDevice, // the specified wave device was out of range K1212_CMDRET_BadFormat // the specified wave format is unsupported } snd_korg1212rc; @@ -400,9 +395,14 @@ struct _snd_korg1212 { u16 leftADCInSens; // ADC left channel input sensitivity u16 rightADCInSens; // ADC right channel input sensitivity - int opencnt; // Open/Close count - int setcnt; // SetupForPlay count - int playcnt; // TriggerPlay count + int opencnt; // Open/Close count + int setcnt; // SetupForPlay count + int playcnt; // TriggerPlay count + int errorcnt; // Error Count + unsigned long totalerrorcnt; // Total Error Count + + int dsp_is_loaded; + int dsp_stop_is_processed; }; @@ -472,7 +472,8 @@ static char* channelName[] = { "SPDIF-R", }; -u16 ClockSourceSelector[] = {0x8000, // selects source as ADAT at 44.1 kHz +static u16 ClockSourceSelector[] = + {0x8000, // selects source as ADAT at 44.1 kHz 0x0000, // selects source as ADAT at 48 kHz 0x8001, // selects source as S/PDIF at 44.1 kHz 0x0001, // selects source as S/PDIF at 48 kHz @@ -609,7 +610,7 @@ static snd_korg1212rc snd_korg1212_Send1212Command(korg1212_t *korg1212, korg121 static void snd_korg1212_SendStop(korg1212_t *korg1212) { if (! korg1212->stop_pending_cnt) { - writel(0xffffffff, &korg1212->sharedBufferPtr->cardCommand); + korg1212->sharedBufferPtr->cardCommand = 0xffffffff; /* program the timer */ korg1212->stop_pending_cnt = HZ; korg1212->timer.expires = jiffies + 1; @@ -621,9 +622,10 @@ static void snd_korg1212_SendStopAndWait(korg1212_t *korg1212) { unsigned long flags; spin_lock_irqsave(&korg1212->lock, flags); + korg1212->dsp_stop_is_processed = 0; snd_korg1212_SendStop(korg1212); spin_unlock_irqrestore(&korg1212->lock, flags); - sleep_on_timeout(&korg1212->wait, (HZ * 3) / 2); + wait_event_timeout(korg1212->wait, korg1212->dsp_stop_is_processed, (HZ * 3) / 2); } /* timer callback for checking the ack of stop request */ @@ -632,9 +634,10 @@ static void snd_korg1212_timer_func(unsigned long data) korg1212_t *korg1212 = (korg1212_t *) data; spin_lock(&korg1212->lock); - if (readl(&korg1212->sharedBufferPtr->cardCommand) == 0) { + if (korg1212->sharedBufferPtr->cardCommand == 0) { /* ack'ed */ korg1212->stop_pending_cnt = 0; + korg1212->dsp_stop_is_processed = 1; wake_up(&korg1212->wait); #if K1212_DEBUG_LEVEL > 1 K1212_DEBUG_PRINTK("K1212_DEBUG: Stop ack'ed [%s]\n", stateName[korg1212->cardState]); @@ -646,7 +649,8 @@ static void snd_korg1212_timer_func(unsigned long data) add_timer(&korg1212->timer); } else { snd_printd("korg1212_timer_func timeout\n"); - writel(0, &korg1212->sharedBufferPtr->cardCommand); + korg1212->sharedBufferPtr->cardCommand = 0; + korg1212->dsp_stop_is_processed = 1; wake_up(&korg1212->wait); #if K1212_DEBUG_LEVEL > 0 K1212_DEBUG_PRINTK("K1212_DEBUG: Stop timeout [%s]\n", stateName[korg1212->cardState]); @@ -849,15 +853,12 @@ static int snd_korg1212_SetMonitorMode(korg1212_t *korg1212, MonitorModeSelector static inline int snd_korg1212_use_is_exclusive(korg1212_t *korg1212) { - unsigned long flags; int ret = 1; - spin_lock_irqsave(&korg1212->lock, flags); if ((korg1212->playback_pid != korg1212->capture_pid) && (korg1212->playback_pid >= 0) && (korg1212->capture_pid >= 0)) { ret = 0; } - spin_unlock_irqrestore(&korg1212->lock, flags); return ret; } @@ -1178,18 +1179,23 @@ static irqreturn_t snd_korg1212_interrupt(int irq, void *dev_id, struct pt_regs #if K1212_DEBUG_LEVEL > 0 K1212_DEBUG_PRINTK("K1212_DEBUG: IRQ DNLD count - %ld, %x, [%s].\n", korg1212->irqcount, doorbellValue, stateName[korg1212->cardState]); #endif - if (korg1212->cardState == K1212_STATE_DSP_IN_PROCESS) + if (korg1212->cardState == K1212_STATE_DSP_IN_PROCESS) { + korg1212->dsp_is_loaded = 1; wake_up(&korg1212->wait); + } break; // ------------------------------------------------------------------------ // an error occurred - stop the card // ------------------------------------------------------------------------ - case K1212_ISRCODE_DMAERROR: + case K1212_DB_DMAERROR: #if K1212_DEBUG_LEVEL > 1 K1212_DEBUG_PRINTK("K1212_DEBUG: IRQ DMAE count - %ld, %x, [%s].\n", korg1212->irqcount, doorbellValue, stateName[korg1212->cardState]); #endif - writel(0, &korg1212->sharedBufferPtr->cardCommand); + snd_printk(KERN_ERR "korg1212: DMA Error\n"); + korg1212->errorcnt++; + korg1212->totalerrorcnt++; + korg1212->sharedBufferPtr->cardCommand = 0; snd_korg1212_setCardState(korg1212, K1212_STATE_ERRORSTOP); break; @@ -1197,11 +1203,11 @@ static irqreturn_t snd_korg1212_interrupt(int irq, void *dev_id, struct pt_regs // the card has stopped by our request. Clear the command word and signal // the semaphore in case someone is waiting for this. // ------------------------------------------------------------------------ - case K1212_ISRCODE_CARDSTOPPED: + case K1212_DB_CARDSTOPPED: #if K1212_DEBUG_LEVEL > 1 K1212_DEBUG_PRINTK("K1212_DEBUG: IRQ CSTP count - %ld, %x, [%s].\n", korg1212->irqcount, doorbellValue, stateName[korg1212->cardState]); #endif - writel(0, &korg1212->sharedBufferPtr->cardCommand); + korg1212->sharedBufferPtr->cardCommand = 0; break; default: @@ -1266,7 +1272,9 @@ static int snd_korg1212_downloadDSPCode(korg1212_t *korg1212) if (rc) K1212_DEBUG_PRINTK("K1212_DEBUG: Start DSP Download RC = %d [%s]\n", rc, stateName[korg1212->cardState]); #endif - if (! sleep_on_timeout(&korg1212->wait, HZ * CARD_BOOT_TIMEOUT)) + korg1212->dsp_is_loaded = 0; + wait_event_timeout(korg1212->wait, korg1212->dsp_is_loaded, HZ * CARD_BOOT_TIMEOUT); + if (! korg1212->dsp_is_loaded ) return -EBUSY; /* timeout */ snd_korg1212_OnDSPDownloadComplete(korg1212); @@ -1438,6 +1446,7 @@ static int snd_korg1212_playback_open(snd_pcm_substream_t *substream) korg1212->playback_pid = current->pid; korg1212->periodsize = K1212_PERIODS; korg1212->channels = K1212_CHANNELS; + korg1212->errorcnt = 0; spin_unlock_irqrestore(&korg1212->lock, flags); @@ -1456,7 +1465,7 @@ static int snd_korg1212_capture_open(snd_pcm_substream_t *substream) K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_capture_open [%s]\n", stateName[korg1212->cardState]); #endif - snd_pcm_set_sync(substream); // ??? + snd_pcm_set_sync(substream); snd_korg1212_OpenCard(korg1212); @@ -1613,7 +1622,7 @@ static int snd_korg1212_prepare(snd_pcm_substream_t *substream) spin_unlock_irq(&korg1212->lock); return -EAGAIN; /* - writel(0, &korg1212->sharedBufferPtr->cardCommand); + korg1212->sharedBufferPtr->cardCommand = 0; del_timer(&korg1212->timer); korg1212->stop_pending_cnt = 0; */ @@ -2117,6 +2126,7 @@ static void snd_korg1212_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *b snd_iprintf(buffer, "Idle mon. State: %d\n", korg1212->idleMonitorOn); snd_iprintf(buffer, "Cmd retry count: %d\n", korg1212->cmdRetryCount); snd_iprintf(buffer, " Irq count: %ld\n", korg1212->irqcount); + snd_iprintf(buffer, " Error count: %ld\n", korg1212->totalerrorcnt); } static void __devinit snd_korg1212_proc_init(korg1212_t *korg1212) @@ -2234,6 +2244,7 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci, korg1212->opencnt = 0; korg1212->playcnt = 0; korg1212->setcnt = 0; + korg1212->totalerrorcnt = 0; korg1212->playback_pid = -1; korg1212->capture_pid = -1; snd_korg1212_setCardState(korg1212, K1212_STATE_UNINITIALIZED); @@ -2272,7 +2283,7 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci, #endif if ((korg1212->iobase = ioremap(korg1212->iomem, iomem_size)) == NULL) { - snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", korg1212->iomem, + snd_printk(KERN_ERR "korg1212: unable to remap memory region 0x%lx-0x%lx\n", korg1212->iomem, korg1212->iomem + iomem_size - 1); snd_korg1212_free(korg1212); return -EBUSY; @@ -2283,7 +2294,7 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci, "korg1212", (void *) korg1212); if (err) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + snd_printk(KERN_ERR "korg1212: unable to grab IRQ %d\n", pci->irq); snd_korg1212_free(korg1212); return -EBUSY; } @@ -2331,7 +2342,7 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci, if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), sizeof(KorgSharedBuffer), &korg1212->dma_shared) < 0) { - snd_printk(KERN_ERR "can not allocate shared buffer memory (%Zd bytes)\n", sizeof(KorgSharedBuffer)); + snd_printk(KERN_ERR "korg1212: can not allocate shared buffer memory (%Zd bytes)\n", sizeof(KorgSharedBuffer)); snd_korg1212_free(korg1212); return -ENOMEM; } @@ -2348,7 +2359,7 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci, if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), korg1212->DataBufsSize, &korg1212->dma_play) < 0) { - snd_printk(KERN_ERR "can not allocate play data buffer memory (%d bytes)\n", korg1212->DataBufsSize); + snd_printk(KERN_ERR "korg1212: can not allocate play data buffer memory (%d bytes)\n", korg1212->DataBufsSize); snd_korg1212_free(korg1212); return -ENOMEM; } @@ -2362,7 +2373,7 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci, if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), korg1212->DataBufsSize, &korg1212->dma_rec) < 0) { - snd_printk(KERN_ERR "can not allocate record data buffer memory (%d bytes)\n", korg1212->DataBufsSize); + snd_printk(KERN_ERR "korg1212: can not allocate record data buffer memory (%d bytes)\n", korg1212->DataBufsSize); snd_korg1212_free(korg1212); return -ENOMEM; } @@ -2394,7 +2405,7 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci, if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), korg1212->dspCodeSize, &korg1212->dma_dsp) < 0) { - snd_printk(KERN_ERR "can not allocate dsp code memory (%d bytes)\n", korg1212->dspCodeSize); + snd_printk(KERN_ERR "korg1212: can not allocate dsp code memory (%d bytes)\n", korg1212->dspCodeSize); snd_korg1212_free(korg1212); return -ENOMEM; } @@ -2423,11 +2434,12 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci, if (snd_korg1212_downloadDSPCode(korg1212)) return -EBUSY; - printk(KERN_INFO "dspMemPhy = %08x U[%08x]\n" - "PlayDataPhy = %08x L[%08x]\n" - "RecDataPhy = %08x L[%08x]\n" - "VolumeTablePhy = %08x L[%08x]\n" - "RoutingTablePhy = %08x L[%08x]\n" + snd_printk(KERN_ERR + "korg1212: dspMemPhy = %08x U[%08x], " + "PlayDataPhy = %08x L[%08x]\n" + "korg1212: RecDataPhy = %08x L[%08x], " + "VolumeTablePhy = %08x L[%08x]\n" + "korg1212: RoutingTablePhy = %08x L[%08x], " "AdatTimeCodePhy = %08x L[%08x]\n", (int)korg1212->dma_dsp.addr, UpperWordSwap(korg1212->dma_dsp.addr), korg1212->PlayDataPhy, LowerWordSwap(korg1212->PlayDataPhy), diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 01a8a51e4..2cf33083d 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -820,7 +820,7 @@ struct snd_m3 { unsigned long iobase; int irq; - int allegro_flag : 1; + unsigned int allegro_flag : 1; ac97_t *ac97; @@ -957,6 +957,13 @@ static struct m3_quirk m3_quirk_list[] = { .device = 0x80f1, .amp_gpio = 0x03, }, + /* LEGEND ZhaoYang 3100CF */ + { + .name = "LEGEND ZhaoYang 3100CF", + .vendor = 0x1509, + .device = 0x1740, + .amp_gpio = 0x03, + }, /* END */ { NULL } }; @@ -1835,34 +1842,24 @@ static unsigned short snd_m3_ac97_read(ac97_t *ac97, unsigned short reg) { m3_t *chip = ac97->private_data; - unsigned short ret = 0; - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); if (snd_m3_ac97_wait(chip)) - goto __error; - snd_m3_outb(chip, 0x80 | (reg & 0x7f), 0x30); + return 0xffff; + snd_m3_outb(chip, 0x80 | (reg & 0x7f), CODEC_COMMAND); if (snd_m3_ac97_wait(chip)) - goto __error; - ret = snd_m3_inw(chip, 0x32); -__error: - spin_unlock_irqrestore(&chip->reg_lock, flags); - return ret; + return 0xffff; + return snd_m3_inw(chip, CODEC_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; - spin_lock_irqsave(&chip->reg_lock, flags); if (snd_m3_ac97_wait(chip)) - goto __error; - snd_m3_outw(chip, val, 0x32); - snd_m3_outb(chip, reg & 0x7f, 0x30); -__error: - spin_unlock_irqrestore(&chip->reg_lock, flags); + return; + snd_m3_outw(chip, val, CODEC_DATA); + snd_m3_outb(chip, reg & 0x7f, CODEC_COMMAND); } @@ -2374,8 +2371,7 @@ static int snd_m3_free(m3_t *chip) } #ifdef CONFIG_PM - if (chip->suspend_mem) - vfree(chip->suspend_mem); + vfree(chip->suspend_mem); #endif if (chip->irq >= 0) { @@ -2396,7 +2392,7 @@ static int snd_m3_free(m3_t *chip) * APM support */ #ifdef CONFIG_PM -static int m3_suspend(snd_card_t *card, unsigned int state) +static int m3_suspend(snd_card_t *card, pm_message_t state) { m3_t *chip = card->pm_private_data; int i, index; @@ -2425,11 +2421,10 @@ static int m3_suspend(snd_card_t *card, unsigned int state) snd_m3_outw(chip, 0xffff, 0x56); pci_disable_device(chip->pci); - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } -static int m3_resume(snd_card_t *card, unsigned int state) +static int m3_resume(snd_card_t *card) { m3_t *chip = card->pm_private_data; int i, index; @@ -2468,7 +2463,6 @@ static int m3_resume(snd_card_t *card, unsigned int state) snd_m3_enable_ints(chip); snd_m3_amp_enable(chip, 1); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; } #endif /* CONFIG_PM */ diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index 32a728ffb..65bb0f47a 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -526,11 +526,11 @@ static int mixart_set_format(mixart_stream_t *stream, snd_pcm_format_t format) stream_param.sample_type = ST_INTEGER_24BE; stream_param.sample_size = 24; break; - case SNDRV_PCM_FMTBIT_FLOAT_LE: + case SNDRV_PCM_FORMAT_FLOAT_LE: stream_param.sample_type = ST_FLOATING_POINT_32LE; stream_param.sample_size = 32; break; - case SNDRV_PCM_FMTBIT_FLOAT_BE: + case SNDRV_PCM_FORMAT_FLOAT_BE: stream_param.sample_type = ST_FLOATING_POINT_32BE; stream_param.sample_size = 32; break; @@ -1019,13 +1019,6 @@ static int __devinit snd_mixart_create(mixart_mgr_t *mgr, snd_card_t *card, int return err; } - if (idx == 0) { - /* create a DSP loader only on first cardX*/ - err = snd_mixart_hwdep_new(mgr); - if (err < 0) - return err; - } - snd_card_set_dev(card, &mgr->pci->dev); return 0; @@ -1069,7 +1062,7 @@ static int snd_mixart_free(mixart_mgr_t *mgr) free_irq(mgr->irq, (void *)mgr); /* reset board if some firmware was loaded */ - if(mgr->hwdep->dsp_loaded) { + if(mgr->dsp_loaded) { snd_mixart_reset_board(mgr); snd_printdd("reset miXart !\n"); } @@ -1210,7 +1203,7 @@ static void snd_mixart_proc_read(snd_info_entry_t *entry, snd_iprintf(buffer, "Digigram miXart (alsa card %d)\n\n", chip->chip_idx); /* stats available when embedded OS is running */ - if (chip->mgr->hwdep->dsp_loaded & ( 1 << MIXART_MOTHERBOARD_ELF_INDEX)) { + if (chip->mgr->dsp_loaded & ( 1 << MIXART_MOTHERBOARD_ELF_INDEX)) { snd_iprintf(buffer, "- hardware -\n"); switch (chip->mgr->board_type ) { case MIXART_DAUGHTER_TYPE_NONE : snd_iprintf(buffer, "\tmiXart8 (no daughter board)\n\n"); break; @@ -1359,7 +1352,7 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci, idx = index[dev]; else idx = index[dev] + i; - snprintf(tmpid, sizeof(tmpid), "%s-%d", id[dev], i); + snprintf(tmpid, sizeof(tmpid), "%s-%d", id[dev] ? id[dev] : "MIXART", i); card = snd_card_new(idx, tmpid, THIS_MODULE, 0); if (! card) { @@ -1388,7 +1381,7 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci, } } - /* init firmware status (mgr->hwdep->dsp_loaded reset in hwdep_new) */ + /* init firmware status (mgr->dsp_loaded reset in hwdep_new) */ mgr->board_type = MIXART_DAUGHTER_TYPE_NONE; /* create array of streaminfo */ @@ -1411,6 +1404,13 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci, /* init bufferinfo_array */ memset(mgr->bufferinfo.area, 0, size); + /* set up firmware */ + err = snd_mixart_setup_firmware(mgr); + if (err < 0) { + snd_mixart_free(mgr); + return err; + } + pci_set_drvdata(pci, mgr); dev++; return 0; diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index 4d9cdb4ad..356fbeac6 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c @@ -1130,7 +1130,7 @@ snd_nm256_ac97_read(ac97_t *ac97, unsigned short reg) return 0; res = snd_nm256_readw(chip, chip->mixer_base + reg); /* Magic delay. Bleah yucky. */ - udelay(1000); + msleep(1); return res; } @@ -1151,7 +1151,7 @@ snd_nm256_ac97_write(ac97_t *ac97, /* Wait for the write to take, too. */ while (tries-- > 0) { snd_nm256_writew(chip, base + reg, val); - udelay(1000); /* a little delay here seems better.. */ + msleep(1); /* a little delay here seems better.. */ if (snd_nm256_ac97_ready(chip)) return; } @@ -1267,7 +1267,7 @@ snd_nm256_peek_for_sig(nm256_t *chip) * APM event handler, so the card is properly reinitialized after a power * event. */ -static int nm256_suspend(snd_card_t *card, unsigned int state) +static int nm256_suspend(snd_card_t *card, pm_message_t state) { nm256_t *chip = card->pm_private_data; @@ -1275,11 +1275,10 @@ static int nm256_suspend(snd_card_t *card, unsigned int state) snd_ac97_suspend(chip->ac97); chip->coeffs_current = 0; pci_disable_device(chip->pci); - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } -static int nm256_resume(snd_card_t *card, unsigned int state) +static int nm256_resume(snd_card_t *card) { nm256_t *chip = card->pm_private_data; @@ -1290,7 +1289,6 @@ static int nm256_resume(snd_card_t *card, unsigned int state) /* restore ac97 */ snd_ac97_resume(chip->ac97); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; } #endif /* CONFIG_PM */ diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index 2c131766a..b96acd5a5 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c @@ -1183,15 +1183,14 @@ static int snd_rme32_playback_fd_ack(snd_pcm_substream_t *substream) { rme32_t *rme32 = snd_pcm_substream_chip(substream); snd_pcm_indirect_t *rec, *cprec; - unsigned long flags; rec = &rme32->playback_pcm; cprec = &rme32->capture_pcm; - spin_lock_irqsave(&rme32->lock, flags); + spin_lock(&rme32->lock); rec->hw_queue_size = RME32_BUFFER_SIZE; if (rme32->running & (1 << SNDRV_PCM_STREAM_CAPTURE)) rec->hw_queue_size -= cprec->hw_ready; - spin_unlock_irqrestore(&rme32->lock, flags); + spin_unlock(&rme32->lock); snd_pcm_indirect_playback_transfer(substream, rec, snd_rme32_pb_trans_copy); return 0; @@ -1916,21 +1915,21 @@ static snd_kcontrol_new_t snd_rme32_controls[] = { .private_value = IEC958_AES0_PROFESSIONAL | IEC958_AES0_PRO_EMPHASIS }, { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Input Connector", .info = snd_rme32_info_inputtype_control, .get = snd_rme32_get_inputtype_control, .put = snd_rme32_put_inputtype_control }, { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Loopback Input", .info = snd_rme32_info_loopback_control, .get = snd_rme32_get_loopback_control, .put = snd_rme32_put_loopback_control }, { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Sample Clock Source", .info = snd_rme32_info_clockmode_control, .get = snd_rme32_get_clockmode_control, diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 8ab9ba8cb..8e2666841 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c @@ -2285,35 +2285,35 @@ static snd_kcontrol_new_t snd_rme96_controls[] = { IEC958_AES0_PRO_EMPHASIS }, { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Input Connector", .info = snd_rme96_info_inputtype_control, .get = snd_rme96_get_inputtype_control, .put = snd_rme96_put_inputtype_control }, { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Loopback Input", .info = snd_rme96_info_loopback_control, .get = snd_rme96_get_loopback_control, .put = snd_rme96_put_loopback_control }, { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Sample Clock Source", .info = snd_rme96_info_clockmode_control, .get = snd_rme96_get_clockmode_control, .put = snd_rme96_put_clockmode_control }, { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Monitor Tracks", .info = snd_rme96_info_montracks_control, .get = snd_rme96_get_montracks_control, .put = snd_rme96_put_montracks_control }, { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Attenuation", .info = snd_rme96_info_attenuation_control, .get = snd_rme96_get_attenuation_control, diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 05665b08b..12efbf0fa 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -27,6 +27,7 @@ #include <linux/interrupt.h> #include <linux/slab.h> #include <linux/pci.h> +#include <linux/firmware.h> #include <linux/moduleparam.h> #include <sound/core.h> @@ -46,8 +47,6 @@ 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 */ -static int precise_ptr[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; /* Enable precise pointer */ -static int line_outs_monitor[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0}; /* Send all inputs/playback to line outs */ module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for RME Hammerfall DSP interface."); @@ -55,10 +54,6 @@ module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for RME Hammerfall DSP interface."); module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable/disable specific Hammerfall DSP soundcards."); -module_param_array(precise_ptr, bool, NULL, 0444); -MODULE_PARM_DESC(precise_ptr, "Enable precise pointer (doesn't work reliably)."); -module_param_array(line_outs_monitor, bool, NULL, 0444); -MODULE_PARM_DESC(line_outs_monitor, "Send all input and playback streams to line outs by default."); MODULE_AUTHOR("Paul Davis <paul@linuxaudiosystems.com>, Marcus Andersson, Thomas Charbonnel <thomas@undata.org>"); MODULE_DESCRIPTION("RME Hammerfall DSP"); MODULE_LICENSE("GPL"); @@ -399,6 +394,13 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," #define HDSP_DMA_AREA_BYTES ((HDSP_MAX_CHANNELS+1) * HDSP_CHANNEL_BUFFER_BYTES) #define HDSP_DMA_AREA_KILOBYTES (HDSP_DMA_AREA_BYTES/1024) +/* use hotplug firmeare loader? */ +#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) +#ifndef HDSP_USE_HWDEP_LOADER +#define HDSP_FW_LOADER +#endif +#endif + typedef struct _hdsp hdsp_t; typedef struct _hdsp_midi hdsp_midi_t; typedef struct _hdsp_9632_meters hdsp_9632_meters_t; @@ -437,6 +439,7 @@ struct _hdsp { snd_pcm_substream_t *playback_substream; hdsp_midi_t midi[2]; struct tasklet_struct midi_tasklet; + int use_midi_tasklet; int precise_ptr; u32 control_register; /* cached value */ u32 control2_register; /* cached value */ @@ -464,7 +467,6 @@ struct _hdsp { pid_t capture_pid; pid_t playback_pid; int running; - int passthru; /* non-zero if doing pass-thru */ int system_sample_rate; char *channel_map; int dev; @@ -585,8 +587,8 @@ static struct pci_device_id snd_hdsp_ids[] = { MODULE_DEVICE_TABLE(pci, snd_hdsp_ids); /* prototypes */ -static int __devinit snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp); -static int __devinit snd_hdsp_create_pcm(snd_card_t *card, hdsp_t *hdsp); +static int snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp); +static int snd_hdsp_create_pcm(snd_card_t *card, hdsp_t *hdsp); static int snd_hdsp_enable_io (hdsp_t *hdsp); static void snd_hdsp_initialize_midi_flush (hdsp_t *hdsp); static void snd_hdsp_initialize_channels (hdsp_t *hdsp); @@ -651,13 +653,13 @@ static int snd_hdsp_load_firmware_from_cache(hdsp_t *hdsp) { if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { - snd_printk ("loading firmware\n"); + snd_printk ("Hammerfall-DSP: loading firmware\n"); hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_PROGRAM); hdsp_write (hdsp, HDSP_fifoData, 0); if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) { - snd_printk ("timeout waiting for download preparation\n"); + snd_printk ("Hammerfall-DSP: timeout waiting for download preparation\n"); return -EIO; } @@ -666,7 +668,7 @@ static int snd_hdsp_load_firmware_from_cache(hdsp_t *hdsp) { for (i = 0; i < 24413; ++i) { hdsp_write(hdsp, HDSP_fifoData, hdsp->firmware_cache[i]); if (hdsp_fifo_wait (hdsp, 127, HDSP_LONG_WAIT)) { - snd_printk ("timeout during firmware loading\n"); + snd_printk ("Hammerfall-DSP: timeout during firmware loading\n"); return -EIO; } } @@ -679,7 +681,7 @@ static int snd_hdsp_load_firmware_from_cache(hdsp_t *hdsp) { } if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) { - snd_printk ("timeout at end of firmware loading\n"); + snd_printk ("Hammerfall-DSP: timeout at end of firmware loading\n"); return -EIO; } @@ -689,11 +691,11 @@ static int snd_hdsp_load_firmware_from_cache(hdsp_t *hdsp) { hdsp->control2_register = 0; #endif hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register); - snd_printk ("finished firmware loading\n"); + snd_printk ("Hammerfall-DSP: finished firmware loading\n"); } if (hdsp->state & HDSP_InitializationComplete) { - snd_printk("firmware loaded from cache, restoring defaults\n"); + snd_printk("Hammerfall-DSP: firmware loaded from cache, restoring defaults\n"); spin_lock_irqsave(&hdsp->lock, flags); snd_hdsp_set_defaults(hdsp); spin_unlock_irqrestore(&hdsp->lock, flags); @@ -706,16 +708,6 @@ static int snd_hdsp_load_firmware_from_cache(hdsp_t *hdsp) { static int hdsp_get_iobox_version (hdsp_t *hdsp) { - int err; - - if (hdsp_check_for_iobox (hdsp)) { - return -EIO; - } - - if ((err = snd_hdsp_enable_io(hdsp)) < 0) { - return err; - } - if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { hdsp_write (hdsp, HDSP_control2Reg, HDSP_PROGRAM); @@ -751,7 +743,7 @@ static int hdsp_check_for_firmware (hdsp_t *hdsp) { if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0; if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { - snd_printk("firmware not present.\n"); + snd_printk("Hammerfall-DSP: firmware not present.\n"); hdsp->state &= ~HDSP_FirmwareLoaded; return -EIO; } @@ -779,7 +771,7 @@ static int hdsp_fifo_wait(hdsp_t *hdsp, int count, int timeout) udelay (100); } - snd_printk ("wait for FIFO status <= %d failed after %d iterations\n", + snd_printk ("Hammerfall-DSP: wait for FIFO status <= %d failed after %d iterations\n", count, timeout); return -1; } @@ -801,7 +793,7 @@ static int hdsp_write_gain(hdsp_t *hdsp, unsigned int addr, unsigned short data) if (hdsp->io_type == H9652 || hdsp->io_type == H9632) { - /* from martin björnsen: + /* from martin bjornsen: "You can only write dwords to the mixer memory which contain two @@ -914,7 +906,7 @@ static int hdsp_spdif_sample_rate(hdsp_t *hdsp) default: break; } - snd_printk ("unknown spdif frequency status; bits = 0x%x, status = 0x%x\n", rate_bits, status); + snd_printk ("Hammerfall-DSP: unknown spdif frequency status; bits = 0x%x, status = 0x%x\n", rate_bits, status); return 0; } @@ -1000,7 +992,7 @@ static int hdsp_set_rate(hdsp_t *hdsp, int rate, int called_internally) if (!(hdsp->control_register & HDSP_ClockModeMaster)) { if (called_internally) { /* request from ctl or card initialization */ - snd_printk("device is not running as a clock master: cannot set sample rate.\n"); + snd_printk("Hammerfall-DSP: device is not running as a clock master: cannot set sample rate.\n"); return -1; } else { /* hw_param request while in AutoSync mode */ @@ -1008,11 +1000,11 @@ static int hdsp_set_rate(hdsp_t *hdsp, int rate, int called_internally) int spdif_freq = hdsp_spdif_sample_rate(hdsp); if ((spdif_freq == external_freq*2) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) { - snd_printk("Detected ADAT in double speed mode\n"); + snd_printk("Hammerfall-DSP: Detected ADAT in double speed mode\n"); } else if (hdsp->io_type == H9632 && (spdif_freq == external_freq*4) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) { - snd_printk("Detected ADAT in quad speed mode\n"); + snd_printk("Hammerfall-DSP: Detected ADAT in quad speed mode\n"); } else if (rate != external_freq) { - snd_printk("No AutoSync source for requested rate\n"); + snd_printk("Hammerfall-DSP: No AutoSync source for requested rate\n"); return -1; } } @@ -1094,7 +1086,7 @@ static int hdsp_set_rate(hdsp_t *hdsp, int rate, int called_internally) } if (reject_if_open && (hdsp->capture_pid >= 0 || hdsp->playback_pid >= 0)) { - snd_printk ("cannot change speed mode (capture PID = %d, playback PID = %d)\n", + snd_printk ("Hammerfall-DSP: cannot change speed mode (capture PID = %d, playback PID = %d)\n", hdsp->capture_pid, hdsp->playback_pid); return -EBUSY; @@ -1135,68 +1127,6 @@ static int hdsp_set_rate(hdsp_t *hdsp, int rate, int called_internally) return 0; } -static void hdsp_set_thru(hdsp_t *hdsp, int channel, int enable) -{ - - hdsp->passthru = 0; - - if (channel < 0) { - - int i; - - /* set thru for all channels */ - - if (enable) { - for (i = 0; i < hdsp->max_channels; i++) { - hdsp_write_gain (hdsp, hdsp_input_to_output_key(hdsp,i,i), UNITY_GAIN); - } - } else { - for (i = 0; i < hdsp->max_channels; i++) { - hdsp_write_gain (hdsp, hdsp_input_to_output_key(hdsp,i,i), MINUS_INFINITY_GAIN); - } - } - - } else { - int mapped_channel; - - snd_assert(channel < hdsp->max_channels, return); - - mapped_channel = hdsp->channel_map[channel]; - - snd_assert(mapped_channel > -1, return); - - if (enable) { - hdsp_write_gain (hdsp, hdsp_input_to_output_key(hdsp,mapped_channel,mapped_channel), UNITY_GAIN); - } else { - hdsp_write_gain (hdsp, hdsp_input_to_output_key(hdsp,mapped_channel,mapped_channel), MINUS_INFINITY_GAIN); - } - } -} - -static int hdsp_set_passthru(hdsp_t *hdsp, int onoff) -{ - if (onoff) { - hdsp_set_thru(hdsp, -1, 1); - hdsp_reset_hw_pointer(hdsp); - hdsp_silence_playback(hdsp); - - /* we don't want interrupts, so do a - custom version of hdsp_start_audio(). - */ - - hdsp->control_register |= (HDSP_Start|HDSP_AudioInterruptEnable|hdsp_encode_latency(7)); - - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - hdsp->passthru = 1; - } else { - hdsp_set_thru(hdsp, -1, 0); - hdsp_stop_audio(hdsp); - hdsp->passthru = 0; - } - - return 0; -} - /*---------------------------------------------------------------------------- MIDI ----------------------------------------------------------------------------*/ @@ -1337,6 +1267,7 @@ static void snd_hdsp_midi_input_trigger(snd_rawmidi_substream_t * substream, int } } else { hdsp->control_register &= ~ie; + tasklet_kill(&hdsp->midi_tasklet); } hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); @@ -1444,14 +1375,14 @@ static int snd_hdsp_midi_output_close(snd_rawmidi_substream_t * substream) return 0; } -snd_rawmidi_ops_t snd_hdsp_midi_output = +static snd_rawmidi_ops_t snd_hdsp_midi_output = { .open = snd_hdsp_midi_output_open, .close = snd_hdsp_midi_output_close, .trigger = snd_hdsp_midi_output_trigger, }; -snd_rawmidi_ops_t snd_hdsp_midi_input = +static snd_rawmidi_ops_t snd_hdsp_midi_input = { .open = snd_hdsp_midi_input_open, .close = snd_hdsp_midi_input_close, @@ -2729,20 +2660,36 @@ static int snd_hdsp_get_autosync_ref(snd_kcontrol_t * kcontrol, snd_ctl_elem_val { hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); - ucontrol->value.enumerated.item[0] = hdsp_pref_sync_ref(hdsp); + ucontrol->value.enumerated.item[0] = hdsp_autosync_ref(hdsp); return 0; } -#define HDSP_PASSTHRU(xname, xindex) \ +#define HDSP_LINE_OUT(xname, xindex) \ { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ .name = xname, \ .index = xindex, \ - .info = snd_hdsp_info_passthru, \ - .put = snd_hdsp_put_passthru, \ - .get = snd_hdsp_get_passthru \ + .info = snd_hdsp_info_line_out, \ + .get = snd_hdsp_get_line_out, \ + .put = snd_hdsp_put_line_out \ +} + +static int hdsp_line_out(hdsp_t *hdsp) +{ + return (hdsp->control_register & HDSP_LineOut) ? 1 : 0; } -static int snd_hdsp_info_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo) +static int hdsp_set_line_output(hdsp_t *hdsp, int out) +{ + if (out) { + hdsp->control_register |= HDSP_LineOut; + } else { + hdsp->control_register &= ~HDSP_LineOut; + } + hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); + return 0; +} + +static int snd_hdsp_info_line_out(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; uinfo->count = 1; @@ -2751,61 +2698,106 @@ static int snd_hdsp_info_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t return 0; } -static int snd_hdsp_get_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_hdsp_get_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); - + spin_lock_irq(&hdsp->lock); - ucontrol->value.integer.value[0] = hdsp->passthru; + ucontrol->value.integer.value[0] = hdsp_line_out(hdsp); spin_unlock_irq(&hdsp->lock); return 0; } -static int snd_hdsp_put_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_hdsp_put_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); int change; unsigned int val; - int err = 0; - + if (!snd_hdsp_use_is_exclusive(hdsp)) return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; spin_lock_irq(&hdsp->lock); - change = (ucontrol->value.integer.value[0] != hdsp->passthru); - if (change) - err = hdsp_set_passthru(hdsp, val); + change = (int)val != hdsp_line_out(hdsp); + hdsp_set_line_output(hdsp, val); spin_unlock_irq(&hdsp->lock); - return err ? err : change; + return change; } -#define HDSP_LINE_OUT(xname, xindex) \ +#define HDSP_PRECISE_POINTER(xname, xindex) \ { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ .name = xname, \ .index = xindex, \ - .info = snd_hdsp_info_line_out, \ - .get = snd_hdsp_get_line_out, \ - .put = snd_hdsp_put_line_out \ + .info = snd_hdsp_info_precise_pointer, \ + .get = snd_hdsp_get_precise_pointer, \ + .put = snd_hdsp_put_precise_pointer \ } -static int hdsp_line_out(hdsp_t *hdsp) +static int hdsp_set_precise_pointer(hdsp_t *hdsp, int precise) { - return (hdsp->control_register & HDSP_LineOut) ? 1 : 0; + if (precise) { + hdsp->precise_ptr = 1; + } else { + hdsp->precise_ptr = 0; + } + return 0; } -static int hdsp_set_line_output(hdsp_t *hdsp, int out) +static int snd_hdsp_info_precise_pointer(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) { - if (out) { - hdsp->control_register |= HDSP_LineOut; + 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_hdsp_get_precise_pointer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +{ + hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); + + spin_lock_irq(&hdsp->lock); + ucontrol->value.integer.value[0] = hdsp->precise_ptr; + spin_unlock_irq(&hdsp->lock); + return 0; +} + +static int snd_hdsp_put_precise_pointer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +{ + hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); + int change; + unsigned int val; + + if (!snd_hdsp_use_is_exclusive(hdsp)) + return -EBUSY; + val = ucontrol->value.integer.value[0] & 1; + spin_lock_irq(&hdsp->lock); + change = (int)val != hdsp->precise_ptr; + hdsp_set_precise_pointer(hdsp, val); + spin_unlock_irq(&hdsp->lock); + return change; +} + +#define HDSP_USE_MIDI_TASKLET(xname, xindex) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ + .name = xname, \ + .index = xindex, \ + .info = snd_hdsp_info_use_midi_tasklet, \ + .get = snd_hdsp_get_use_midi_tasklet, \ + .put = snd_hdsp_put_use_midi_tasklet \ +} + +static int hdsp_set_use_midi_tasklet(hdsp_t *hdsp, int use_tasklet) +{ + if (use_tasklet) { + hdsp->use_midi_tasklet = 1; } else { - hdsp->control_register &= ~HDSP_LineOut; + hdsp->use_midi_tasklet = 0; } - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); return 0; } -static int snd_hdsp_info_line_out(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) +static int snd_hdsp_info_use_midi_tasklet(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; uinfo->count = 1; @@ -2814,17 +2806,17 @@ static int snd_hdsp_info_line_out(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t return 0; } -static int snd_hdsp_get_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_hdsp_get_use_midi_tasklet(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); spin_lock_irq(&hdsp->lock); - ucontrol->value.integer.value[0] = hdsp_line_out(hdsp); + ucontrol->value.integer.value[0] = hdsp->use_midi_tasklet; spin_unlock_irq(&hdsp->lock); return 0; } -static int snd_hdsp_put_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_hdsp_put_use_midi_tasklet(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); int change; @@ -2834,8 +2826,8 @@ static int snd_hdsp_put_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t return -EBUSY; val = ucontrol->value.integer.value[0] & 1; spin_lock_irq(&hdsp->lock); - change = (int)val != hdsp_line_out(hdsp); - hdsp_set_line_output(hdsp, val); + change = (int)val != hdsp->use_midi_tasklet; + hdsp_set_use_midi_tasklet(hdsp, val); spin_unlock_irq(&hdsp->lock); return change; } @@ -3131,14 +3123,15 @@ HDSP_AUTOSYNC_SAMPLE_RATE("External Rate", 0), HDSP_WC_SYNC_CHECK("Word Clock Lock Status", 0), HDSP_SPDIF_SYNC_CHECK("SPDIF Lock Status", 0), HDSP_ADATSYNC_SYNC_CHECK("ADAT Sync Lock Status", 0), -HDSP_PASSTHRU("Passthru", 0), HDSP_LINE_OUT("Line Out", 0), +HDSP_PRECISE_POINTER("Precise Pointer", 0), +HDSP_USE_MIDI_TASKLET("Use Midi Tasklet", 0), }; static snd_kcontrol_new_t snd_hdsp_96xx_aeb = HDSP_AEB("Analog Extension Board", 0); static snd_kcontrol_new_t snd_hdsp_adat_sync_check = HDSP_ADAT_SYNC_CHECK; -int snd_hdsp_create_controls(snd_card_t *card, hdsp_t *hdsp) +static int snd_hdsp_create_controls(snd_card_t *card, hdsp_t *hdsp) { unsigned int idx; int err; @@ -3232,11 +3225,11 @@ snd_hdsp_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer) snd_iprintf(buffer, "Status register: 0x%x\n", status); snd_iprintf(buffer, "Status2 register: 0x%x\n", status2); snd_iprintf(buffer, "FIFO status: %d\n", hdsp_read(hdsp, HDSP_fifoStatus) & 0xff); - snd_iprintf(buffer, "MIDI1 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut0)); snd_iprintf(buffer, "MIDI1 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn0)); snd_iprintf(buffer, "MIDI2 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut1)); snd_iprintf(buffer, "MIDI2 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn1)); + snd_iprintf(buffer, "Use Midi Tasklet: %s\n", hdsp->use_midi_tasklet ? "on" : "off"); snd_iprintf(buffer, "\n"); @@ -3244,7 +3237,7 @@ snd_hdsp_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer) snd_iprintf(buffer, "Buffer Size (Latency): %d samples (2 periods of %lu bytes)\n", x, (unsigned long) hdsp->period_bytes); snd_iprintf(buffer, "Hardware pointer (frames): %ld\n", hdsp_hw_pointer(hdsp)); - snd_iprintf(buffer, "Passthru: %s\n", hdsp->passthru ? "yes" : "no"); + snd_iprintf(buffer, "Precise pointer: %s\n", hdsp->precise_ptr ? "on" : "off"); snd_iprintf(buffer, "Line out: %s\n", (hdsp->control_register & HDSP_LineOut) ? "on" : "off"); snd_iprintf(buffer, "Firmware version: %d\n", (status2&HDSP_version0)|(status2&HDSP_version1)<<1|(status2&HDSP_version2)<<2); @@ -3604,40 +3597,6 @@ static int snd_hdsp_set_defaults(hdsp_t *hdsp) } } - if ((hdsp->io_type != H9652) && line_outs_monitor[hdsp->dev]) { - - int lineouts_base; - - snd_printk ("sending all inputs and playback streams to line outs.\n"); - - /* route all inputs to the line outs for easy monitoring. send - odd numbered channels to right, even to left. - */ - if (hdsp->io_type == H9632) { - /* this is the phones/analog output */ - lineouts_base = 10; - } else { - lineouts_base = 26; - } - - for (i = 0; i < hdsp->max_channels; i++) { - if (i & 1) { - if (hdsp_write_gain (hdsp, hdsp_input_to_output_key (hdsp, i, lineouts_base), UNITY_GAIN) || - hdsp_write_gain (hdsp, hdsp_playback_to_output_key (hdsp, i, lineouts_base), UNITY_GAIN)) { - return -EIO; - } - } else { - if (hdsp_write_gain (hdsp, hdsp_input_to_output_key (hdsp, i, lineouts_base+1), UNITY_GAIN) || - hdsp_write_gain (hdsp, hdsp_playback_to_output_key (hdsp, i, lineouts_base+1), UNITY_GAIN)) { - - return -EIO; - } - } - } - } - - hdsp->passthru = 0; - /* H9632 specific defaults */ if (hdsp->io_type == H9632) { hdsp->control_register |= (HDSP_DAGainPlus4dBu | HDSP_ADGainPlus4dBu | HDSP_PhoneGain0dB); @@ -3652,7 +3611,7 @@ static int snd_hdsp_set_defaults(hdsp_t *hdsp) return 0; } -void hdsp_midi_tasklet(unsigned long arg) +static void hdsp_midi_tasklet(unsigned long arg) { hdsp_t *hdsp = (hdsp_t *)arg; @@ -3701,21 +3660,29 @@ static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id, struct pt_regs *reg } if (midi0 && midi0status) { - /* we disable interrupts for this input until processing is done */ - hdsp->control_register &= ~HDSP_Midi0InterruptEnable; - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - hdsp->midi[0].pending = 1; - schedule = 1; + if (hdsp->use_midi_tasklet) { + /* we disable interrupts for this input until processing is done */ + hdsp->control_register &= ~HDSP_Midi0InterruptEnable; + hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); + hdsp->midi[0].pending = 1; + schedule = 1; + } else { + snd_hdsp_midi_input_read (&hdsp->midi[0]); + } } - if (midi1 && midi1status) { - /* we disable interrupts for this input until processing is done */ - hdsp->control_register &= ~HDSP_Midi1InterruptEnable; - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - hdsp->midi[1].pending = 1; - schedule = 1; + if (hdsp->io_type != Multiface && hdsp->io_type != H9632 && midi1 && midi1status) { + if (hdsp->use_midi_tasklet) { + /* we disable interrupts for this input until processing is done */ + hdsp->control_register &= ~HDSP_Midi1InterruptEnable; + hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); + hdsp->midi[1].pending = 1; + schedule = 1; + } else { + snd_hdsp_midi_input_read (&hdsp->midi[1]); + } } - if (schedule) - tasklet_hi_schedule(&hdsp->midi_tasklet); + if (hdsp->use_midi_tasklet && schedule) + tasklet_hi_schedule(&hdsp->midi_tasklet); return IRQ_HANDLED; } @@ -3830,10 +3797,10 @@ static int snd_hdsp_hw_params(snd_pcm_substream_t *substream, if (hdsp_check_for_firmware(hdsp)) { if (hdsp->state & HDSP_FirmwareCached) { if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { - snd_printk("Firmware loading from cache failed, please upload manually.\n"); + snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n"); } } else { - snd_printk("No firmware loaded nor cached, please upload firmware.\n"); + snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n"); } return -EIO; } @@ -3949,10 +3916,10 @@ static int snd_hdsp_trigger(snd_pcm_substream_t *substream, int cmd) if (hdsp_check_for_firmware(hdsp)) { if (hdsp->state & HDSP_FirmwareCached) { if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { - snd_printk("Firmware loading from cache failed, please upload manually.\n"); + snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n"); } } else { - snd_printk("No firmware loaded nor cached, please upload firmware.\n"); + snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n"); } return -EIO; } @@ -4027,10 +3994,10 @@ static int snd_hdsp_prepare(snd_pcm_substream_t *substream) if (hdsp_check_for_firmware(hdsp)) { if (hdsp->state & HDSP_FirmwareCached) { if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { - snd_printk("Firmware loading from cache failed, please upload manually.\n"); + snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n"); } } else { - snd_printk("No firmware loaded nor cached, please upload firmware.\n"); + snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n"); } return -EIO; } @@ -4049,7 +4016,11 @@ static snd_pcm_hardware_t snd_hdsp_playback_subinfo = SNDRV_PCM_INFO_NONINTERLEAVED | SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE), +#ifdef SNDRV_BIG_ENDIAN + .formats = SNDRV_PCM_FMTBIT_S32_BE, +#else .formats = SNDRV_PCM_FMTBIT_S32_LE, +#endif .rates = (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | @@ -4074,7 +4045,11 @@ static snd_pcm_hardware_t snd_hdsp_capture_subinfo = SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_NONINTERLEAVED | SNDRV_PCM_INFO_SYNC_START), +#ifdef SNDRV_BIG_ENDIAN + .formats = SNDRV_PCM_FMTBIT_S32_BE, +#else .formats = SNDRV_PCM_FMTBIT_S32_LE, +#endif .rates = (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | @@ -4282,10 +4257,10 @@ static int snd_hdsp_playback_open(snd_pcm_substream_t *substream) if (hdsp_check_for_firmware(hdsp)) { if (hdsp->state & HDSP_FirmwareCached) { if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { - snd_printk("Firmware loading from cache failed, please upload manually.\n"); + snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n"); } } else { - snd_printk("No firmware loaded nor cached, please upload firmware.\n"); + snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n"); } return -EIO; } @@ -4298,11 +4273,6 @@ static int snd_hdsp_playback_open(snd_pcm_substream_t *substream) runtime->dma_area = hdsp->playback_buffer; runtime->dma_bytes = HDSP_DMA_AREA_BYTES; - if (hdsp->capture_substream == NULL) { - hdsp_stop_audio(hdsp); - hdsp_set_thru(hdsp, -1, 0); - } - hdsp->playback_pid = current->pid; hdsp->playback_substream = substream; @@ -4365,10 +4335,10 @@ static int snd_hdsp_capture_open(snd_pcm_substream_t *substream) if (hdsp_check_for_firmware(hdsp)) { if (hdsp->state & HDSP_FirmwareCached) { if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { - snd_printk("Firmware loading from cache failed, please upload manually.\n"); + snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n"); } } else { - snd_printk("No firmware loaded nor cached, please upload firmware.\n"); + snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n"); } return -EIO; } @@ -4381,11 +4351,6 @@ static int snd_hdsp_capture_open(snd_pcm_substream_t *substream) runtime->dma_area = hdsp->capture_buffer; runtime->dma_bytes = HDSP_DMA_AREA_BYTES; - if (hdsp->playback_substream == NULL) { - hdsp_stop_audio(hdsp); - hdsp_set_thru(hdsp, -1, 0); - } - hdsp->capture_pid = current->pid; hdsp->capture_substream = substream; @@ -4545,12 +4510,12 @@ static int hdsp_get_peak(hdsp_t *hdsp, hdsp_peak_rms_t __user *peak_rms) } for (i = 0; i < 26; ++i) { if (copy_u64_le(&peak_rms->playback_rms[i], - hdsp->iobase + HDSP_playbackRmsLevel + i * 8, - hdsp->iobase + HDSP_playbackRmsLevel + i * 8 + 4)) + hdsp->iobase + HDSP_playbackRmsLevel + i * 8 + 4, + hdsp->iobase + HDSP_playbackRmsLevel + i * 8)) return -EFAULT; if (copy_u64_le(&peak_rms->input_rms[i], - hdsp->iobase + HDSP_inputRmsLevel + i * 8, - hdsp->iobase + HDSP_inputRmsLevel + i * 8 + 4)) + hdsp->iobase + HDSP_inputRmsLevel + i * 8 + 4, + hdsp->iobase + HDSP_inputRmsLevel + i * 8)) return -EFAULT; } return 0; @@ -4566,7 +4531,7 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int hdsp_peak_rms_t __user *peak_rms = (hdsp_peak_rms_t __user *)arg; if (!(hdsp->state & HDSP_FirmwareLoaded)) { - snd_printk(KERN_ERR "firmware needs to be uploaded to the card.\n"); + snd_printk(KERN_ERR "Hammerfall-DSP: firmware needs to be uploaded to the card.\n"); return -EINVAL; } @@ -4585,7 +4550,7 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int int i; if (!(hdsp->state & HDSP_FirmwareLoaded)) { - snd_printk("Firmware needs to be uploaded to the card.\n"); + snd_printk("Hammerfall-DSP: Firmware needs to be uploaded to the card.\n"); return -EINVAL; } spin_lock_irqsave(&hdsp->lock, flags); @@ -4610,7 +4575,6 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int info.clock_source = (unsigned char)hdsp_clock_source(hdsp); info.autosync_ref = (unsigned char)hdsp_autosync_ref(hdsp); info.line_out = (unsigned char)hdsp_line_out(hdsp); - info.passthru = (unsigned char)hdsp->passthru; if (hdsp->io_type == H9632) { info.da_gain = (unsigned char)hdsp_da_gain(hdsp); info.ad_gain = (unsigned char)hdsp_ad_gain(hdsp); @@ -4662,7 +4626,10 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int /* SNDRV_HDSP_IOCTL_GET_VERSION must have been called */ if (hdsp->io_type == Undefined) return -EINVAL; - snd_printk("initializing firmware upload\n"); + if (hdsp->state & (HDSP_FirmwareCached | HDSP_FirmwareLoaded)) + return -EBUSY; + + snd_printk("Hammerfall-DSP: initializing firmware upload\n"); firmware = (hdsp_firmware_t __user *)argp; if (get_user(firmware_data, &firmware->firmware_data)) { @@ -4684,12 +4651,15 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int } if (!(hdsp->state & HDSP_InitializationComplete)) { - snd_hdsp_initialize_channels(hdsp); - + if ((err = snd_hdsp_enable_io(hdsp)) < 0) { + return err; + } + + snd_hdsp_initialize_channels(hdsp); snd_hdsp_initialize_midi_flush(hdsp); if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) { - snd_printk("error creating alsa devices\n"); + snd_printk("Hammerfall-DSP: error creating alsa devices\n"); return err; } } @@ -4750,8 +4720,7 @@ static int __devinit snd_hdsp_create_hwdep(snd_card_t *card, return 0; } -static int __devinit snd_hdsp_create_pcm(snd_card_t *card, - hdsp_t *hdsp) +static int snd_hdsp_create_pcm(snd_card_t *card, hdsp_t *hdsp) { snd_pcm_t *pcm; int err; @@ -4782,6 +4751,7 @@ static int snd_hdsp_enable_io (hdsp_t *hdsp) int i; if (hdsp_fifo_wait (hdsp, 0, 100)) { + snd_printk("Hammerfall-DSP: enable_io fifo_wait failed\n"); return -EIO; } @@ -4842,29 +4812,30 @@ static void snd_hdsp_initialize_midi_flush (hdsp_t *hdsp) snd_hdsp_flush_midi_input (hdsp, 1); } -static int __devinit snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp) +static int snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp) { int err; if ((err = snd_hdsp_create_pcm(card, hdsp)) < 0) { - snd_printk("Error creating pcm interface\n"); + snd_printk("Hammerfall-DSP: Error creating pcm interface\n"); return err; } if ((err = snd_hdsp_create_midi(card, hdsp, 0)) < 0) { - snd_printk("Error creating first midi interface\n"); + snd_printk("Hammerfall-DSP: Error creating first midi interface\n"); return err; } - - if ((err = snd_hdsp_create_midi(card, hdsp, 1)) < 0) { - snd_printk("Error creating second midi interface\n"); - return err; + if (hdsp->io_type == Digiface || hdsp->io_type == H9652) { + if ((err = snd_hdsp_create_midi(card, hdsp, 1)) < 0) { + snd_printk("Hammerfall-DSP: Error creating second midi interface\n"); + return err; + } } if ((err = snd_hdsp_create_controls(card, hdsp)) < 0) { - snd_printk("Error creating ctl interface\n"); + snd_printk("Hammerfall-DSP: Error creating ctl interface\n"); return err; } @@ -4877,7 +4848,7 @@ static int __devinit snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp hdsp->playback_substream = NULL; if ((err = snd_hdsp_set_defaults(hdsp)) < 0) { - snd_printk("Error setting default values\n"); + snd_printk("Hammerfall-DSP: Error setting default values\n"); return err; } @@ -4886,7 +4857,7 @@ static int __devinit snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp hdsp->port, hdsp->irq); if ((err = snd_card_register(card)) < 0) { - snd_printk("error registering card\n"); + snd_printk("Hammerfall-DSP: error registering card\n"); return err; } hdsp->state |= HDSP_InitializationComplete; @@ -4895,9 +4866,94 @@ static int __devinit snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp return 0; } +#ifdef HDSP_FW_LOADER +/* load firmware via hotplug fw loader */ +static int __devinit hdsp_request_fw_loader(hdsp_t *hdsp) +{ + const char *fwfile; + const struct firmware *fw; + int err; + + if (hdsp->io_type == H9652 || hdsp->io_type == H9632) + return 0; + if (hdsp->io_type == Undefined) { + if ((err = hdsp_get_iobox_version(hdsp)) < 0) + return err; + if (hdsp->io_type == H9652 || hdsp->io_type == H9632) + return 0; + } + + /* caution: max length of firmware filename is 30! */ + switch (hdsp->io_type) { + case Multiface: + if (hdsp->firmware_rev == 0xa) + fwfile = "multiface_firmware.bin"; + else + fwfile = "multiface_firmware_rev11.bin"; + break; + case Digiface: + if (hdsp->firmware_rev == 0xa) + fwfile = "digiface_firmware.bin"; + else + fwfile = "digiface_firmware_rev11.bin"; + break; + default: + snd_printk(KERN_ERR "Hammerfall-DSP: invalid io_type %d\n", hdsp->io_type); + return -EINVAL; + } + + if (request_firmware(&fw, fwfile, &hdsp->pci->dev)) { + snd_printk(KERN_ERR "Hammerfall-DSP: cannot load firmware %s\n", fwfile); + return -ENOENT; + } + if (fw->size < sizeof(hdsp->firmware_cache)) { + snd_printk(KERN_ERR "Hammerfall-DSP: too short firmware size %d (expected %d)\n", + (int)fw->size, (int)sizeof(hdsp->firmware_cache)); + 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; + + if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0) + return err; + + if (!(hdsp->state & HDSP_InitializationComplete)) { + if ((err = snd_hdsp_enable_io(hdsp)) < 0) { + return err; + } + + if ((err = snd_hdsp_create_hwdep(hdsp->card, hdsp)) < 0) { + snd_printk("Hammerfall-DSP: error creating hwdep device\n"); + return err; + } + snd_hdsp_initialize_channels(hdsp); + snd_hdsp_initialize_midi_flush(hdsp); + if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) { + snd_printk("Hammerfall-DSP: error creating alsa devices\n"); + return err; + } + } + return 0; +} +#endif + static int __devinit snd_hdsp_create(snd_card_t *card, - hdsp_t *hdsp, - int precise_ptr) + hdsp_t *hdsp) { struct pci_dev *pci = hdsp->pci; int err; @@ -4912,6 +4968,8 @@ static int __devinit snd_hdsp_create(snd_card_t *card, hdsp->midi[1].input = NULL; hdsp->midi[0].output = NULL; hdsp->midi[1].output = NULL; + hdsp->midi[0].pending = 0; + hdsp->midi[1].pending = 0; spin_lock_init(&hdsp->midi[0].lock); spin_lock_init(&hdsp->midi[1].lock); hdsp->iobase = NULL; @@ -4927,6 +4985,7 @@ static int __devinit snd_hdsp_create(snd_card_t *card, tasklet_init(&hdsp->midi_tasklet, hdsp_midi_tasklet, (unsigned long)hdsp); pci_read_config_word(hdsp->pci, PCI_CLASS_REVISION, &hdsp->firmware_rev); + hdsp->firmware_rev &= 0xff; /* From Martin Bjoernsen : "It is important that the card's latency timer register in @@ -4940,27 +4999,17 @@ static int __devinit snd_hdsp_create(snd_card_t *card, strcpy(card->driver, "H-DSP"); strcpy(card->mixername, "Xilinx FPGA"); - switch (hdsp->firmware_rev & 0xff) { - case 0xa: - case 0xb: - case 0x32: + if (hdsp->firmware_rev < 0xa) { + return -ENODEV; + } else if (hdsp->firmware_rev < 0x64) { hdsp->card_name = "RME Hammerfall DSP"; - break; - - case 0x64: - case 0x65: - case 0x68: + } else if (hdsp->firmware_rev < 0x96) { hdsp->card_name = "RME HDSP 9652"; is_9652 = 1; - break; - case 0x96: - case 0x97: + } else { hdsp->card_name = "RME HDSP 9632"; hdsp->max_channels = 16; - is_9632 = 1; - break; - default: - return -ENODEV; + is_9632 = 1; } if ((err = pci_enable_device(pci)) < 0) { @@ -4973,51 +5022,65 @@ static int __devinit snd_hdsp_create(snd_card_t *card, return err; hdsp->port = pci_resource_start(pci, 0); if ((hdsp->iobase = ioremap_nocache(hdsp->port, HDSP_IO_EXTENT)) == NULL) { - snd_printk("unable to remap region 0x%lx-0x%lx\n", hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1); + snd_printk("Hammerfall-DSP: unable to remap region 0x%lx-0x%lx\n", hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1); return -EBUSY; } if (request_irq(pci->irq, snd_hdsp_interrupt, SA_INTERRUPT|SA_SHIRQ, "hdsp", (void *)hdsp)) { - snd_printk("unable to use IRQ %d\n", pci->irq); + snd_printk("Hammerfall-DSP: unable to use IRQ %d\n", pci->irq); return -EBUSY; } hdsp->irq = pci->irq; - hdsp->precise_ptr = precise_ptr; + hdsp->precise_ptr = 1; + hdsp->use_midi_tasklet = 1; if ((err = snd_hdsp_initialize_memory(hdsp)) < 0) { return err; } - if (!is_9652 && !is_9632 && hdsp_check_for_iobox (hdsp)) { - /* no iobox connected, we defer initialization */ - snd_printk("card initialization pending : waiting for firmware\n"); - if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) { - return err; + if (!is_9652 && !is_9632) { + /* we wait 2 seconds to let freshly inserted cardbus cards do their hardware init */ + if ((1000 / HZ) < 2000) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((2000 * HZ + 999) / 1000); + } else { + mdelay(2000); + } + + if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { +#ifdef HDSP_FW_LOADER + if ((err = hdsp_request_fw_loader(hdsp)) < 0) { + /* we don't fail as this can happen + if userspace is not ready for + firmware upload + */ + snd_printk("Hammerfall-DSP: couldn't get firmware from userspace. try using hdsploader\n"); + } else { + /* init is complete, we return */ + return 0; + } +#endif + /* no iobox connected, we defer initialization */ + snd_printk("Hammerfall-DSP: card initialization pending : waiting for firmware\n"); + if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) { + return err; + } + return 0; + } else { + snd_printk("Hammerfall-DSP: Firmware already present, initializing card.\n"); + if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) { + hdsp->io_type = Multiface; + } else { + hdsp->io_type = Digiface; + } } - return 0; } if ((err = snd_hdsp_enable_io(hdsp)) != 0) { return err; } - if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { - snd_printk("card initialization pending : waiting for firmware\n"); - if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) { - return err; - } - return 0; - } - - snd_printk("Firmware already loaded, initializing card.\n"); - - if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) { - hdsp->io_type = Multiface; - } else { - hdsp->io_type = Digiface; - } - if (is_9652) { hdsp->io_type = H9652; } @@ -5046,6 +5109,7 @@ static int snd_hdsp_free(hdsp_t *hdsp) { if (hdsp->port) { /* stop the audio, and cancel all interrupts */ + tasklet_kill(&hdsp->midi_tasklet); hdsp->control_register &= ~(HDSP_Start|HDSP_AudioInterruptEnable|HDSP_Midi0InterruptEnable|HDSP_Midi1InterruptEnable); hdsp_write (hdsp, HDSP_controlRegister, hdsp->control_register); } @@ -5097,7 +5161,7 @@ static int __devinit snd_hdsp_probe(struct pci_dev *pci, hdsp->pci = pci; snd_card_set_dev(card, &pci->dev); - if ((err = snd_hdsp_create(card, hdsp, precise_ptr[dev])) < 0) { + if ((err = snd_hdsp_create(card, hdsp)) < 0) { snd_card_free(card); return err; } diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index 420779931..69cd81eaa 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c @@ -1584,7 +1584,7 @@ RME9652_ADAT_SYNC("ADAT3 Sync Check", 0, 2); static snd_kcontrol_new_t snd_rme9652_adat1_input = RME9652_ADAT1_IN("ADAT1 Input Source", 0); -int snd_rme9652_create_controls(snd_card_t *card, rme9652_t *rme9652) +static int snd_rme9652_create_controls(snd_card_t *card, rme9652_t *rme9652) { unsigned int idx; int err; diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index baa9c2e04..cfd2c5fd6 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -46,6 +46,10 @@ MODULE_DESCRIPTION("S3 SonicVibes PCI"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{S3,SonicVibes PCI}}"); +#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) +#define SUPPORT_JOYSTICK 1 +#endif + #ifndef PCI_VENDOR_ID_S3 #define PCI_VENDOR_ID_S3 0x5333 #endif @@ -242,8 +246,8 @@ struct _snd_sonicvibes { snd_kcontrol_t *master_mute; snd_kcontrol_t *master_volume; -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) - struct gameport gameport; +#ifdef SUPPORT_JOYSTICK + struct gameport *gameport; #endif }; @@ -357,8 +361,8 @@ static unsigned char snd_sonicvibes_in(sonicvibes_t * sonic, unsigned char reg) return value; } -#ifdef CONFIG_SND_DEBUG -void snd_sonicvibes_debug(sonicvibes_t * sonic) +#if 0 +static void snd_sonicvibes_debug(sonicvibes_t * sonic) { printk("SV REGS: INDEX = 0x%02x ", inb(SV_REG(sonic, INDEX))); printk(" STATUS = 0x%02x\n", inb(SV_REG(sonic, STATUS))); @@ -1163,15 +1167,47 @@ static void __devinit snd_sonicvibes_proc_init(sonicvibes_t * sonic) */ +#ifdef SUPPORT_JOYSTICK static snd_kcontrol_new_t snd_sonicvibes_game_control __devinitdata = SONICVIBES_SINGLE("Joystick Speed", 0, SV_IREG_GAME_PORT, 1, 15, 0); -static int snd_sonicvibes_free(sonicvibes_t *sonic) +static int __devinit snd_sonicvibes_create_gameport(sonicvibes_t *sonic) { -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) - if (sonic->gameport.io) - gameport_unregister_port(&sonic->gameport); + struct gameport *gp; + + sonic->gameport = gp = gameport_allocate_port(); + if (!gp) { + printk(KERN_ERR "sonicvibes: cannot allocate memory for gameport\n"); + return -ENOMEM; + } + + gameport_set_name(gp, "SonicVibes Gameport"); + gameport_set_phys(gp, "pci%s/gameport0", pci_name(sonic->pci)); + gameport_set_dev_parent(gp, &sonic->pci->dev); + gp->io = sonic->game_port; + + gameport_register_port(gp); + + snd_ctl_add(sonic->card, snd_ctl_new1(&snd_sonicvibes_game_control, sonic)); + + return 0; +} + +static void snd_sonicvibes_free_gameport(sonicvibes_t *sonic) +{ + if (sonic->gameport) { + gameport_unregister_port(sonic->gameport); + sonic->gameport = NULL; + } +} +#else +static inline int snd_sonicvibes_create_gameport(sonicvibes_t *sonic) { return -ENOSYS; } +static inline void snd_sonicvibes_free_gameport(sonicvibes_t *sonic) { } #endif + +static int snd_sonicvibes_free(sonicvibes_t *sonic) +{ + snd_sonicvibes_free_gameport(sonic); pci_write_config_dword(sonic->pci, 0x40, sonic->dmaa_port); pci_write_config_dword(sonic->pci, 0x48, sonic->dmac_port); if (sonic->irq >= 0) @@ -1332,7 +1368,6 @@ static int __devinit snd_sonicvibes_create(snd_card_t * card, snd_sonicvibes_debug(sonic); #endif sonic->revision = snd_sonicvibes_in(sonic, SV_IREG_REVISION); - snd_ctl_add(card, snd_ctl_new1(&snd_sonicvibes_game_control, sonic)); if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, sonic, &ops)) < 0) { snd_sonicvibes_free(sonic); @@ -1459,10 +1494,8 @@ static int __devinit snd_sonic_probe(struct pci_dev *pci, snd_card_free(card); return err; } -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) - sonic->gameport.io = sonic->game_port; - gameport_register_port(&sonic->gameport); -#endif + + snd_sonicvibes_create_gameport(sonic); if ((err = snd_card_register(card)) < 0) { snd_card_free(card); diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c index 8304190f8..ad58e08d6 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c @@ -157,7 +157,7 @@ static int __devinit snd_trident_probe(struct pci_dev *pci, } #endif - snd_trident_gameport(trident); + snd_trident_create_gameport(trident); if ((err = snd_card_register(card)) < 0) { snd_card_free(card); diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 8c02d4770..ccd5ca2ba 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c @@ -48,11 +48,14 @@ static int snd_trident_pcm_mixer_build(trident_t *trident, snd_trident_voice_t * static int snd_trident_pcm_mixer_free(trident_t *trident, snd_trident_voice_t * voice, snd_pcm_substream_t *substream); static irqreturn_t snd_trident_interrupt(int irq, void *dev_id, struct pt_regs *regs); #ifdef CONFIG_PM -static int snd_trident_suspend(snd_card_t *card, unsigned int state); -static int snd_trident_resume(snd_card_t *card, unsigned int state); +static int snd_trident_suspend(snd_card_t *card, pm_message_t state); +static int snd_trident_resume(snd_card_t *card); #endif static int snd_trident_sis_reset(trident_t *trident); +static void snd_trident_clear_voices(trident_t * trident, unsigned short v_min, unsigned short v_max); +static int snd_trident_free(trident_t *trident); + /* * common I/O routines */ @@ -632,7 +635,7 @@ static void snd_trident_write_cvol_reg(trident_t * trident, snd_trident_voice_t Returns: Delta value. ---------------------------------------------------------------------------*/ -unsigned int snd_trident_convert_rate(unsigned int rate) +static unsigned int snd_trident_convert_rate(unsigned int rate) { unsigned int delta; @@ -692,7 +695,7 @@ static unsigned int snd_trident_convert_adc_rate(unsigned int rate) Returns: Delta value. ---------------------------------------------------------------------------*/ -unsigned int snd_trident_spurious_threshold(unsigned int rate, unsigned int period_size) +static unsigned int snd_trident_spurious_threshold(unsigned int rate, unsigned int period_size) { unsigned int res = (rate * period_size) / 48000; if (res < 64) @@ -713,7 +716,7 @@ unsigned int snd_trident_spurious_threshold(unsigned int rate, unsigned int peri Returns: Control value. ---------------------------------------------------------------------------*/ -unsigned int snd_trident_control_mode(snd_pcm_substream_t *substream) +static unsigned int snd_trident_control_mode(snd_pcm_substream_t *substream) { unsigned int CTRL; snd_pcm_runtime_t *runtime = substream->runtime; @@ -770,8 +773,8 @@ static int snd_trident_ioctl(snd_pcm_substream_t * substream, ---------------------------------------------------------------------------*/ -int snd_trident_allocate_pcm_mem(snd_pcm_substream_t * substream, - snd_pcm_hw_params_t * hw_params) +static int snd_trident_allocate_pcm_mem(snd_pcm_substream_t * substream, + snd_pcm_hw_params_t * hw_params) { trident_t *trident = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; @@ -804,8 +807,8 @@ int snd_trident_allocate_pcm_mem(snd_pcm_substream_t * substream, ---------------------------------------------------------------------------*/ -int snd_trident_allocate_evoice(snd_pcm_substream_t * substream, - snd_pcm_hw_params_t * hw_params) +static int snd_trident_allocate_evoice(snd_pcm_substream_t * substream, + snd_pcm_hw_params_t * hw_params) { trident_t *trident = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; @@ -3107,37 +3110,28 @@ static int __devinit snd_trident_mixer(trident_t * trident, int pcm_spdif_device #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) -typedef struct snd_trident_gameport { - struct gameport info; - trident_t *chip; -} trident_gameport_t; - static unsigned char snd_trident_gameport_read(struct gameport *gameport) { - trident_gameport_t *gp = (trident_gameport_t *)gameport; - trident_t *chip; - snd_assert(gp, return 0); - chip = gp->chip; + trident_t *chip = gameport_get_port_data(gameport); + + snd_assert(chip, return 0); return inb(TRID_REG(chip, GAMEPORT_LEGACY)); } static void snd_trident_gameport_trigger(struct gameport *gameport) { - trident_gameport_t *gp = (trident_gameport_t *)gameport; - trident_t *chip; - snd_assert(gp, return); - chip = gp->chip; + trident_t *chip = gameport_get_port_data(gameport); + + snd_assert(chip, return); outb(0xff, TRID_REG(chip, GAMEPORT_LEGACY)); } static int snd_trident_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons) { - trident_gameport_t *gp = (trident_gameport_t *)gameport; - trident_t *chip; + trident_t *chip = gameport_get_port_data(gameport); int i; - snd_assert(gp, return 0); - chip = gp->chip; + snd_assert(chip, return 0); *buttons = (~inb(TRID_REG(chip, GAMEPORT_LEGACY)) >> 4) & 0xf; @@ -3151,10 +3145,9 @@ static int snd_trident_gameport_cooked_read(struct gameport *gameport, int *axes static int snd_trident_gameport_open(struct gameport *gameport, int mode) { - trident_gameport_t *gp = (trident_gameport_t *)gameport; - trident_t *chip; - snd_assert(gp, return -1); - chip = gp->chip; + trident_t *chip = gameport_get_port_data(gameport); + + snd_assert(chip, return 0); switch (mode) { case GAMEPORT_MODE_COOKED: @@ -3170,30 +3163,42 @@ static int snd_trident_gameport_open(struct gameport *gameport, int mode) } } -void __devinit snd_trident_gameport(trident_t *chip) +int __devinit snd_trident_create_gameport(trident_t *chip) { - trident_gameport_t *gp; - gp = kmalloc(sizeof(*gp), GFP_KERNEL); - if (! gp) { - snd_printk("cannot allocate gameport area\n"); - return; + struct gameport *gp; + + chip->gameport = gp = gameport_allocate_port(); + if (!gp) { + printk(KERN_ERR "trident: cannot allocate memory for gameport\n"); + return -ENOMEM; } - memset(gp, 0, sizeof(*gp)); - gp->chip = chip; - gp->info.fuzz = 64; - gp->info.read = snd_trident_gameport_read; - gp->info.trigger = snd_trident_gameport_trigger; - gp->info.cooked_read = snd_trident_gameport_cooked_read; - gp->info.open = snd_trident_gameport_open; - chip->gameport = gp; - gameport_register_port(&gp->info); + gameport_set_name(gp, "Trident 4DWave"); + gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci)); + gameport_set_dev_parent(gp, &chip->pci->dev); + + gameport_set_port_data(gp, chip); + gp->fuzz = 64; + gp->read = snd_trident_gameport_read; + gp->trigger = snd_trident_gameport_trigger; + gp->cooked_read = snd_trident_gameport_cooked_read; + gp->open = snd_trident_gameport_open; + + gameport_register_port(gp); + + return 0; } -#else -void __devinit snd_trident_gameport(trident_t *chip) +static inline void snd_trident_free_gameport(trident_t *chip) { + if (chip->gameport) { + gameport_unregister_port(chip->gameport); + chip->gameport = NULL; + } } +#else +int __devinit snd_trident_create_gameport(trident_t *chip) { return -ENOSYS; } +static inline void snd_trident_free_gameport(trident_t *chip) { } #endif /* CONFIG_GAMEPORT */ /* @@ -3656,14 +3661,9 @@ int __devinit snd_trident_create(snd_card_t * card, ---------------------------------------------------------------------------*/ -int snd_trident_free(trident_t *trident) +static int snd_trident_free(trident_t *trident) { -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) - if (trident->gameport) { - gameport_unregister_port(&trident->gameport->info); - kfree(trident->gameport); - } -#endif + snd_trident_free_gameport(trident); snd_trident_disable_eso(trident); // Disable S/PDIF out if (trident->device == TRIDENT_DEVICE_ID_NX) @@ -3677,8 +3677,7 @@ int snd_trident_free(trident_t *trident) snd_util_memhdr_free(trident->tlb.memhdr); if (trident->tlb.silent_page.area) snd_dma_free_pages(&trident->tlb.silent_page); - if (trident->tlb.shadow_entries) - vfree(trident->tlb.shadow_entries); + vfree(trident->tlb.shadow_entries); snd_dma_free_pages(&trident->tlb.buffer); } if (trident->irq >= 0) @@ -3805,9 +3804,9 @@ static irqreturn_t snd_trident_interrupt(int irq, void *dev_id, struct pt_regs * } /*--------------------------------------------------------------------------- - snd_trident_attach_synthesizer, snd_trident_detach_synthesizer + snd_trident_attach_synthesizer - Description: Attach/detach synthesizer hooks + Description: Attach synthesizer hooks Paramters: trident - device specific private data for 4DWave card @@ -3826,17 +3825,6 @@ int snd_trident_attach_synthesizer(trident_t *trident) return 0; } -int snd_trident_detach_synthesizer(trident_t *trident) -{ -#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) - if (trident->seq_dev) { - snd_device_free(trident->card, trident->seq_dev); - trident->seq_dev = NULL; - } -#endif - return 0; -} - snd_trident_voice_t *snd_trident_alloc_voice(trident_t * trident, int type, int client, int port) { snd_trident_voice_t *pvoice; @@ -3909,7 +3897,7 @@ void snd_trident_free_voice(trident_t * trident, snd_trident_voice_t *voice) private_free(voice); } -void snd_trident_clear_voices(trident_t * trident, unsigned short v_min, unsigned short v_max) +static void snd_trident_clear_voices(trident_t * trident, unsigned short v_min, unsigned short v_max) { unsigned int i, val, mask[2] = { 0, 0 }; @@ -3930,7 +3918,7 @@ void snd_trident_clear_voices(trident_t * trident, unsigned short v_min, unsigne } #ifdef CONFIG_PM -static int snd_trident_suspend(snd_card_t *card, unsigned int state) +static int snd_trident_suspend(snd_card_t *card, pm_message_t state) { trident_t *trident = card->pm_private_data; @@ -3953,11 +3941,10 @@ static int snd_trident_suspend(snd_card_t *card, unsigned int state) break; } pci_disable_device(trident->pci); - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } -static int snd_trident_resume(snd_card_t *card, unsigned int state) +static int snd_trident_resume(snd_card_t *card) { trident_t *trident = card->pm_private_data; @@ -3988,7 +3975,6 @@ static int snd_trident_resume(snd_card_t *card, unsigned int state) snd_trident_enable_eso(trident); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); trident->in_suspend = 0; return 0; } @@ -3999,9 +3985,7 @@ EXPORT_SYMBOL(snd_trident_free_voice); EXPORT_SYMBOL(snd_trident_start_voice); EXPORT_SYMBOL(snd_trident_stop_voice); EXPORT_SYMBOL(snd_trident_write_voice_regs); -EXPORT_SYMBOL(snd_trident_clear_voices); /* trident_memory.c symbols */ EXPORT_SYMBOL(snd_trident_synth_alloc); EXPORT_SYMBOL(snd_trident_synth_free); -EXPORT_SYMBOL(snd_trident_synth_bzero); EXPORT_SYMBOL(snd_trident_synth_copy_from_user); diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 1344c7a58..9b4d74d49 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -81,7 +81,7 @@ static long mpu_port[SNDRV_CARDS]; static int joystick[SNDRV_CARDS]; #endif static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 48000}; -static int ac97_quirk[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = AC97_TUNE_DEFAULT}; +static char *ac97_quirk[SNDRV_CARDS]; static int dxs_support[SNDRV_CARDS]; module_param_array(index, int, NULL, 0444); @@ -98,7 +98,7 @@ MODULE_PARM_DESC(joystick, "Enable joystick. (VT82C686x only)"); #endif module_param_array(ac97_clock, int, NULL, 0444); MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz)."); -module_param_array(ac97_quirk, int, NULL, 0444); +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)"); @@ -332,6 +332,7 @@ struct via_dev { struct snd_via_sg_table *idx_table; /* for recovery from the unexpected pointer */ unsigned int lastpos; + unsigned int fragsize; unsigned int bufsize; unsigned int bufsize2; }; @@ -366,7 +367,7 @@ struct _snd_via82xx { unsigned int mpu_port_saved; #endif - unsigned char playback_volume[4][2]; /* for VIA8233/C/8235; default = 0 */ + unsigned char playback_volume[2]; /* for VIA8233/C/8235; default = 0 */ unsigned int intr_mask; /* SGD_SHADOW mask to check interrupts */ @@ -390,12 +391,10 @@ struct _snd_via82xx { unsigned int ac97_secondary; /* secondary AC'97 codec is present */ spinlock_t reg_lock; - spinlock_t ac97_lock; snd_info_entry_t *proc_entry; #ifdef SUPPORT_JOYSTICK - struct gameport gameport; - struct resource *res_joystick; + struct gameport *gameport; #endif }; @@ -478,6 +477,7 @@ static int build_via_table(viadev_t *dev, snd_pcm_substream_t *substream, dev->tbl_entries = idx; dev->bufsize = periods * fragsize; dev->bufsize2 = dev->bufsize / 2; + dev->fragsize = fragsize; return 0; } @@ -562,10 +562,8 @@ static void snd_via82xx_codec_write(ac97_t *ac97, xval <<= VIA_REG_AC97_CODEC_ID_SHIFT; xval |= reg << VIA_REG_AC97_CMD_SHIFT; xval |= val << VIA_REG_AC97_DATA_SHIFT; - spin_lock(&chip->ac97_lock); snd_via82xx_codec_xwrite(chip, xval); snd_via82xx_codec_ready(chip, ac97->num); - spin_unlock(&chip->ac97_lock); } static unsigned short snd_via82xx_codec_read(ac97_t *ac97, unsigned short reg) @@ -578,10 +576,8 @@ static unsigned short snd_via82xx_codec_read(ac97_t *ac97, unsigned short reg) xval |= ac97->num ? VIA_REG_AC97_SECONDARY_VALID : VIA_REG_AC97_PRIMARY_VALID; xval |= VIA_REG_AC97_READ; xval |= (reg & 0x7f) << VIA_REG_AC97_CMD_SHIFT; - spin_lock(&chip->ac97_lock); while (1) { if (again++ > 3) { - spin_unlock(&chip->ac97_lock); snd_printk(KERN_ERR "codec_read: codec %i is not valid [0x%x]\n", ac97->num, snd_via82xx_codec_xread(chip)); return 0xffff; } @@ -593,7 +589,6 @@ static unsigned short snd_via82xx_codec_read(ac97_t *ac97, unsigned short reg) break; } } - spin_unlock(&chip->ac97_lock); return val & 0xffff; } @@ -706,29 +701,34 @@ static int snd_via82xx_pcm_trigger(snd_pcm_substream_t * substream, int cmd) static inline unsigned int calc_linear_pos(viadev_t *viadev, unsigned int idx, unsigned int count) { - unsigned int size, res; + unsigned int size, base, res; size = viadev->idx_table[idx].size; - res = viadev->idx_table[idx].offset + size - count; + base = viadev->idx_table[idx].offset; + res = base + size - count; /* check the validity of the calculated position */ if (size < count) { snd_printd(KERN_ERR "invalid via82xx_cur_ptr (size = %d, count = %d)\n", (int)size, (int)count); res = viadev->lastpos; - } else if (check_invalid_pos(viadev, res)) { + } else { + if (! count) { + /* Some mobos report count = 0 on the DMA boundary, + * i.e. count = size indeed. + * Let's check whether this step is above the expected size. + */ + int delta = res - viadev->lastpos; + if (delta < 0) + delta += viadev->bufsize; + if ((unsigned int)delta > viadev->fragsize) + res = base; + } + if (check_invalid_pos(viadev, res)) { #ifdef POINTER_DEBUG - printk("fail: idx = %i/%i, lastpos = 0x%x, bufsize2 = 0x%x, offsize = 0x%x, size = 0x%x, count = 0x%x\n", idx, viadev->tbl_entries, viadev->lastpos, viadev->bufsize2, viadev->idx_table[idx].offset, viadev->idx_table[idx].size, count); + printk(KERN_DEBUG "fail: idx = %i/%i, lastpos = 0x%x, bufsize2 = 0x%x, offsize = 0x%x, size = 0x%x, count = 0x%x\n", idx, viadev->tbl_entries, viadev->lastpos, viadev->bufsize2, viadev->idx_table[idx].offset, viadev->idx_table[idx].size, count); #endif - if (count && size < count) { - snd_printd(KERN_ERR "invalid via82xx_cur_ptr, using last valid pointer\n"); - res = viadev->lastpos; - } else { - if (! count) - /* bogus count 0 on the DMA boundary? */ - res = viadev->idx_table[idx].offset; - else - /* count register returns full size when end of buffer is reached */ - res = viadev->idx_table[idx].offset + size; + /* count register returns full size when end of buffer is reached */ + res = base + size; if (check_invalid_pos(viadev, res)) { snd_printd(KERN_ERR "invalid via82xx_cur_ptr (2), using last valid pointer\n"); res = viadev->lastpos; @@ -778,12 +778,20 @@ static snd_pcm_uframes_t snd_via8233_pcm_pointer(snd_pcm_substream_t *substream) via82xx_t *chip = snd_pcm_substream_chip(substream); viadev_t *viadev = (viadev_t *)substream->runtime->private_data; unsigned int idx, count, res; + int timeout = 5000; snd_assert(viadev->tbl_entries, return 0); if (!(inb(VIADEV_REG(viadev, OFFSET_STATUS)) & VIA_REG_STAT_ACTIVE)) return 0; spin_lock(&chip->reg_lock); - count = inl(VIADEV_REG(viadev, OFFSET_CURR_COUNT)); + do { + count = inl(VIADEV_REG(viadev, OFFSET_CURR_COUNT)); + /* some mobos read 0 count */ + if ((count & 0xffffff) || ! viadev->running) + break; + } while (--timeout); + if (! timeout) + snd_printd(KERN_ERR "zero position is read\n"); idx = count >> 24; if (idx >= viadev->tbl_entries) { #ifdef POINTER_DEBUG @@ -933,8 +941,8 @@ static int snd_via8233_playback_prepare(snd_pcm_substream_t *substream) snd_assert((rbits & ~0xfffff) == 0, return -EINVAL); snd_via82xx_channel_reset(chip, viadev); snd_via82xx_set_table_ptr(chip, viadev); - outb(chip->playback_volume[viadev->reg_offset / 0x10][0], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_L)); - outb(chip->playback_volume[viadev->reg_offset / 0x10][1], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_R)); + outb(chip->playback_volume[0], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_L)); + outb(chip->playback_volume[1], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_R)); outl((runtime->format == SNDRV_PCM_FORMAT_S16_LE ? VIA8233_REG_TYPE_16BIT : 0) | /* format */ (runtime->channels > 1 ? VIA8233_REG_TYPE_STEREO : 0) | /* stereo */ rbits | /* rate */ @@ -1488,17 +1496,15 @@ static int snd_via8233_dxs_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_in static int snd_via8233_dxs_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { via82xx_t *chip = snd_kcontrol_chip(kcontrol); - unsigned int idx = snd_ctl_get_ioff(kcontrol, &ucontrol->id); - ucontrol->value.integer.value[0] = VIA_DXS_MAX_VOLUME - chip->playback_volume[idx][0]; - ucontrol->value.integer.value[1] = VIA_DXS_MAX_VOLUME - chip->playback_volume[idx][1]; + ucontrol->value.integer.value[0] = VIA_DXS_MAX_VOLUME - chip->playback_volume[0]; + ucontrol->value.integer.value[1] = VIA_DXS_MAX_VOLUME - chip->playback_volume[1]; return 0; } static int snd_via8233_dxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { via82xx_t *chip = snd_kcontrol_chip(kcontrol); - unsigned int idx = snd_ctl_get_ioff(kcontrol, &ucontrol->id); - unsigned long port = chip->port + 0x10 * idx; + unsigned int idx; unsigned char val; int i, change = 0; @@ -1507,19 +1513,21 @@ static int snd_via8233_dxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val if (val > VIA_DXS_MAX_VOLUME) val = VIA_DXS_MAX_VOLUME; val = VIA_DXS_MAX_VOLUME - val; - change |= val != chip->playback_volume[idx][i]; - if (change) { - chip->playback_volume[idx][i] = val; - outb(val, port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i); + if (val != chip->playback_volume[i]) { + change = 1; + chip->playback_volume[i] = val; + for (idx = 0; idx < 4; idx++) { + unsigned long port = chip->port + 0x10 * idx; + outb(val, port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i); + } } } return change; } static snd_kcontrol_new_t snd_via8233_dxs_volume_control __devinitdata = { - .name = "VIA DXS Playback Volume", + .name = "PCM Playback Volume", .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .count = 4, .info = snd_via8233_dxs_volume_info, .get = snd_via8233_dxs_volume_get, .put = snd_via8233_dxs_volume_put, @@ -1593,7 +1601,7 @@ static struct ac97_quirk ac97_quirks[] = { { } /* terminator */ }; -static int __devinit snd_via82xx_mixer_new(via82xx_t *chip, int ac97_quirk) +static int __devinit snd_via82xx_mixer_new(via82xx_t *chip, const char *quirk_override) { ac97_template_t ac97; int err; @@ -1616,7 +1624,7 @@ static int __devinit snd_via82xx_mixer_new(via82xx_t *chip, int ac97_quirk) if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0) return err; - snd_ac97_tune_hardware(chip->ac97, ac97_quirks, ac97_quirk); + snd_ac97_tune_hardware(chip->ac97, ac97_quirks, quirk_override); if (chip->chip_type != TYPE_VIA686) { /* use slot 10/11 */ @@ -1626,11 +1634,70 @@ static int __devinit snd_via82xx_mixer_new(via82xx_t *chip, int ac97_quirk) return 0; } +#ifdef SUPPORT_JOYSTICK +#define JOYSTICK_ADDR 0x200 +static int __devinit snd_via686_create_gameport(via82xx_t *chip, int dev, unsigned char *legacy) +{ + struct gameport *gp; + struct resource *r; + + if (!joystick[dev]) + return -ENODEV; + + r = request_region(JOYSTICK_ADDR, 8, "VIA686 gameport"); + if (!r) { + printk(KERN_WARNING "via82xx: cannot reserve joystick port 0x%#x\n", JOYSTICK_ADDR); + return -EBUSY; + } + + chip->gameport = gp = gameport_allocate_port(); + if (!gp) { + printk(KERN_ERR "via82xx: cannot allocate memory for gameport\n"); + release_resource(r); + kfree_nocheck(r); + return -ENOMEM; + } + + gameport_set_name(gp, "VIA686 Gameport"); + gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci)); + gameport_set_dev_parent(gp, &chip->pci->dev); + gp->io = JOYSTICK_ADDR; + gameport_set_port_data(gp, r); + + /* Enable legacy joystick port */ + *legacy |= VIA_FUNC_ENABLE_GAME; + pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, *legacy); + + gameport_register_port(chip->gameport); + + return 0; +} + +static void snd_via686_free_gameport(via82xx_t *chip) +{ + if (chip->gameport) { + struct resource *r = gameport_get_port_data(chip->gameport); + + gameport_unregister_port(chip->gameport); + chip->gameport = NULL; + release_resource(r); + kfree_nocheck(r); + } +} +#else +static inline int snd_via686_create_gameport(via82xx_t *chip, int dev, unsigned char *legacy) +{ + return -ENOSYS; +} +static inline void snd_via686_free_gameport(via82xx_t *chip) { } +#endif + + /* * */ -static int snd_via8233_init_misc(via82xx_t *chip, int dev) +static int __devinit snd_via8233_init_misc(via82xx_t *chip, int dev) { int i, err, caps; unsigned char val; @@ -1648,9 +1715,18 @@ static int snd_via8233_init_misc(via82xx_t *chip, int dev) return err; } if (chip->chip_type != TYPE_VIA8233A) { - err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs_volume_control, chip)); - if (err < 0) - return err; + /* when no h/w PCM volume control is found, use DXS volume control + * as the PCM vol control + */ + snd_ctl_elem_id_t sid; + memset(&sid, 0, sizeof(sid)); + strcpy(sid.name, "PCM Playback Volume"); + sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; + if (! snd_ctl_find_id(chip->card, &sid)) { + err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs_volume_control, chip)); + if (err < 0) + return err; + } } /* select spdif data slot 10/11 */ @@ -1662,7 +1738,7 @@ static int snd_via8233_init_misc(via82xx_t *chip, int dev) return 0; } -static int snd_via686_init_misc(via82xx_t *chip, int dev) +static int __devinit snd_via686_init_misc(via82xx_t *chip, int dev) { unsigned char legacy, legacy_cfg; int rev_h = 0; @@ -1709,15 +1785,6 @@ static int snd_via686_init_misc(via82xx_t *chip, int dev) mpu_port[dev] = 0; } -#ifdef SUPPORT_JOYSTICK -#define JOYSTICK_ADDR 0x200 - if (joystick[dev] && - (chip->res_joystick = request_region(JOYSTICK_ADDR, 8, "VIA686 gameport")) != NULL) { - legacy |= VIA_FUNC_ENABLE_GAME; - chip->gameport.io = JOYSTICK_ADDR; - } -#endif - pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, legacy); pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, legacy_cfg); if (chip->mpu_res) { @@ -1732,10 +1799,7 @@ static int snd_via686_init_misc(via82xx_t *chip, int dev) pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, legacy); } -#ifdef SUPPORT_JOYSTICK - if (chip->res_joystick) - gameport_register_port(&chip->gameport); -#endif + snd_via686_create_gameport(chip, dev, &legacy); #ifdef CONFIG_PM chip->legacy_saved = legacy; @@ -1772,16 +1836,12 @@ 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) { - ac97_t ac97; unsigned int val; int max_count; unsigned char pval; - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = chip; - #if 0 /* broken on K7M? */ if (chip->chip_type == TYPE_VIA686) /* disable all legacy ports */ @@ -1833,11 +1893,6 @@ static int __devinit snd_via82xx_chip_init(via82xx_t *chip) if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) snd_printk("AC'97 codec is not ready [0x%x]\n", val); - /* and then reset codec.. */ - snd_via82xx_codec_ready(chip, 0); - snd_via82xx_codec_write(&ac97, AC97_RESET, 0x0000); - snd_via82xx_codec_read(&ac97, 0); - #if 0 /* FIXME: we don't support the second codec yet so skip the detection now.. */ snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | VIA_REG_AC97_SECONDARY_VALID | @@ -1879,6 +1934,15 @@ static int __devinit snd_via82xx_chip_init(via82xx_t *chip) } } + if (chip->chip_type != TYPE_VIA8233A) { + int i, idx; + for (idx = 0; idx < 4; idx++) { + unsigned long port = chip->port + 0x10 * idx; + for (i = 0; i < 2; i++) + outb(chip->playback_volume[i], port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i); + } + } + return 0; } @@ -1886,7 +1950,7 @@ static int __devinit snd_via82xx_chip_init(via82xx_t *chip) /* * power management */ -static int snd_via82xx_suspend(snd_card_t *card, unsigned int state) +static int snd_via82xx_suspend(snd_card_t *card, pm_message_t state) { via82xx_t *chip = card->pm_private_data; int i; @@ -1908,14 +1972,13 @@ static int snd_via82xx_suspend(snd_card_t *card, unsigned int state) pci_set_power_state(chip->pci, 3); pci_disable_device(chip->pci); - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } -static int snd_via82xx_resume(snd_card_t *card, unsigned int state) +static int snd_via82xx_resume(snd_card_t *card) { via82xx_t *chip = card->pm_private_data; - int idx, i; + int i; pci_enable_device(chip->pci); pci_set_power_state(chip->pci, 0); @@ -1931,11 +1994,6 @@ static int snd_via82xx_resume(snd_card_t *card, unsigned int state) pci_write_config_byte(chip->pci, VIA8233_SPDIF_CTRL, chip->spdif_ctrl_saved); outb(chip->capture_src_saved[0], chip->port + VIA_REG_CAPTURE_CHANNEL); outb(chip->capture_src_saved[1], chip->port + VIA_REG_CAPTURE_CHANNEL + 0x10); - for (idx = 0; idx < 4; idx++) { - unsigned long port = chip->port + 0x10 * idx; - for (i = 0; i < 2; i++) - outb(chip->playback_volume[idx][i], port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i); - } } snd_ac97_resume(chip->ac97); @@ -1943,7 +2001,6 @@ static int snd_via82xx_resume(snd_card_t *card, unsigned int state) for (i = 0; i < chip->num_devs; i++) snd_via82xx_channel_reset(chip, &chip->devs[i]); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; } #endif /* CONFIG_PM */ @@ -1966,14 +2023,9 @@ static int snd_via82xx_free(via82xx_t *chip) kfree_nocheck(chip->mpu_res); } pci_release_regions(chip->pci); + if (chip->chip_type == TYPE_VIA686) { -#ifdef SUPPORT_JOYSTICK - if (chip->res_joystick) { - gameport_unregister_port(&chip->gameport); - release_resource(chip->res_joystick); - kfree_nocheck(chip->res_joystick); - } -#endif + snd_via686_free_gameport(chip); pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, chip->old_legacy); pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, chip->old_legacy_cfg); } @@ -2013,7 +2065,6 @@ static int __devinit snd_via82xx_create(snd_card_t * card, chip->revision = revision; spin_lock_init(&chip->reg_lock); - spin_lock_init(&chip->ac97_lock); spin_lock_init(&chip->rates[0].lock); spin_lock_init(&chip->rates[1].lock); chip->card = card; @@ -2106,11 +2157,15 @@ static int __devinit check_dxs_list(struct pci_dev *pci) { .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 = 0x147b, .device = 0x1401, .action = VIA_DXS_ENABLE }, /* ABIT KD7(-RAID) */ - { .vendor = 0x14ff, .device = 0x0403, .action = VIA_DXS_ENABLE }, /* Twinhead mobo */ { .vendor = 0x1462, .device = 0x3800, .action = VIA_DXS_ENABLE }, /* MSI KT266 */ - { .vendor = 0x1462, .device = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */ { .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 */ @@ -2118,7 +2173,6 @@ static int __devinit check_dxs_list(struct pci_dev *pci) { .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 */ - { .vendor = 0x147b, .device = 0x1415, .action = VIA_DXS_NO_VRA }, /* Abit AV8 */ { } /* terminator */ }; struct dxs_whitelist *w; diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c index 75e53b509..4ffbb2565 100644 --- a/sound/pci/vx222/vx222.c +++ b/sound/pci/vx222/vx222.c @@ -225,7 +225,11 @@ static int __devinit snd_vx222_probe(struct pci_dev *pci, snd_printdd("%s at 0x%lx & 0x%lx, irq %i\n", card->shortname, vx->port[0], vx->port[1], vx->core.irq); - if ((err = snd_vx_hwdep_new(&vx->core)) < 0) { +#ifdef SND_VX_FW_LOADER + vx->core.dev = &pci->dev; +#endif + + if ((err = snd_vx_setup_firmware(&vx->core)) < 0) { snd_card_free(card); return err; } @@ -251,6 +255,7 @@ static struct pci_driver driver = { .id_table = snd_vx222_ids, .probe = snd_vx222_probe, .remove = __devexit_p(snd_vx222_remove), + SND_PCI_PM_CALLBACKS }; static int __init alsa_card_vx222_init(void) diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index a4afa4b69..9f3ef22df 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c @@ -79,6 +79,97 @@ static struct pci_device_id snd_ymfpci_ids[] = { MODULE_DEVICE_TABLE(pci, snd_ymfpci_ids); +#ifdef SUPPORT_JOYSTICK +static int __devinit snd_ymfpci_create_gameport(ymfpci_t *chip, int dev, + int legacy_ctrl, int legacy_ctrl2) +{ + struct gameport *gp; + struct resource *r = NULL; + int io_port = joystick_port[dev]; + + if (!io_port) + return -ENODEV; + + if (chip->pci->device >= 0x0010) { /* YMF 744/754 */ + + if (io_port == 1) { + /* auto-detect */ + if (!(io_port = pci_resource_start(chip->pci, 2))) + return -ENODEV; + } + } else { + if (io_port == 1) { + /* auto-detect */ + for (io_port = 0x201; io_port <= 0x205; io_port++) { + if (io_port == 0x203) + continue; + if ((r = request_region(io_port, 1, "YMFPCI gameport")) != NULL) + break; + } + if (!r) { + printk(KERN_ERR "ymfpci: no gameport ports available\n"); + return -EBUSY; + } + } + switch (io_port) { + case 0x201: legacy_ctrl2 |= 0 << 6; break; + case 0x202: legacy_ctrl2 |= 1 << 6; break; + case 0x204: legacy_ctrl2 |= 2 << 6; break; + case 0x205: legacy_ctrl2 |= 3 << 6; break; + default: + printk(KERN_ERR "ymfpci: invalid joystick port %#x", io_port); + return -EINVAL; + } + } + + if (!r && !(r = request_region(io_port, 1, "YMFPCI gameport"))) { + printk(KERN_ERR "ymfpci: joystick port %#x is in use.\n", io_port); + return -EBUSY; + } + + chip->gameport = gp = gameport_allocate_port(); + if (!gp) { + printk(KERN_ERR "ymfpci: cannot allocate memory for gameport\n"); + release_resource(r); + kfree_nocheck(r); + return -ENOMEM; + } + + + gameport_set_name(gp, "Yamaha YMF Gameport"); + gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci)); + gameport_set_dev_parent(gp, &chip->pci->dev); + gp->io = io_port; + gameport_set_port_data(gp, r); + + if (chip->pci->device >= 0x0010) /* YMF 744/754 */ + pci_write_config_word(chip->pci, PCIR_DSXG_JOYBASE, io_port); + + pci_write_config_word(chip->pci, PCIR_DSXG_LEGACY, legacy_ctrl | YMFPCI_LEGACY_JPEN); + pci_write_config_word(chip->pci, PCIR_DSXG_ELEGACY, legacy_ctrl2); + + gameport_register_port(chip->gameport); + + return 0; +} + +void snd_ymfpci_free_gameport(ymfpci_t *chip) +{ + if (chip->gameport) { + struct resource *r = gameport_get_port_data(chip->gameport); + + gameport_unregister_port(chip->gameport); + chip->gameport = NULL; + + release_resource(r); + kfree_nocheck(r); + } +} +#else +static inline int snd_ymfpci_create_gameport(ymfpci_t *chip, int dev, int l, int l2) { return -ENOSYS; } +void snd_ymfpci_free_gameport(ymfpci_t *chip) { } +#endif /* SUPPORT_JOYSTICK */ + static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { @@ -86,9 +177,6 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci, snd_card_t *card; struct resource *fm_res = NULL; struct resource *mpu_res = NULL; -#ifdef SUPPORT_JOYSTICK - struct resource *joystick_res = NULL; -#endif ymfpci_t *chip; opl3_t *opl3; char *str; @@ -138,17 +226,6 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci, legacy_ctrl |= YMFPCI_LEGACY_MEN; pci_write_config_word(pci, PCIR_DSXG_MPU401BASE, mpu_port[dev]); } -#ifdef SUPPORT_JOYSTICK - if (joystick_port[dev] == 1) { - /* auto-detect */ - joystick_port[dev] = pci_resource_start(pci, 2); - } - if (joystick_port[dev] > 0 && - (joystick_res = request_region(joystick_port[dev], 1, "YMFPCI gameport")) != NULL) { - legacy_ctrl |= YMFPCI_LEGACY_JPEN; - pci_write_config_word(pci, PCIR_DSXG_JOYBASE, joystick_port[dev]); - } -#endif } else { switch (fm_port[dev]) { case 0x388: legacy_ctrl2 |= 0; break; @@ -178,34 +255,6 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci, legacy_ctrl2 &= ~YMFPCI_LEGACY2_MPUIO; mpu_port[dev] = 0; } -#ifdef SUPPORT_JOYSTICK - if (joystick_port[dev] == 1) { - /* auto-detect */ - long p; - for (p = 0x201; p <= 0x205; p++) { - if (p == 0x203) continue; - if ((joystick_res = request_region(p, 1, "YMFPCI gameport")) != NULL) - break; - } - if (joystick_res) - joystick_port[dev] = p; - } - switch (joystick_port[dev]) { - case 0x201: legacy_ctrl2 |= 0 << 6; break; - case 0x202: legacy_ctrl2 |= 1 << 6; break; - case 0x204: legacy_ctrl2 |= 2 << 6; break; - case 0x205: legacy_ctrl2 |= 3 << 6; break; - default: joystick_port[dev] = 0; break; - } - if (! joystick_res && joystick_port[dev] > 0) - joystick_res = request_region(joystick_port[dev], 1, "YMFPCI gameport"); - if (joystick_res) { - legacy_ctrl |= YMFPCI_LEGACY_JPEN; - } else { - legacy_ctrl2 &= ~YMFPCI_LEGACY2_JSIO; - joystick_port[dev] = 0; - } -#endif } if (mpu_res) { legacy_ctrl |= YMFPCI_LEGACY_MIEN; @@ -226,19 +275,10 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci, release_resource(fm_res); kfree_nocheck(fm_res); } -#ifdef SUPPORT_JOYSTICK - if (joystick_res) { - release_resource(joystick_res); - kfree_nocheck(joystick_res); - } -#endif return err; } chip->fm_res = fm_res; chip->mpu_res = mpu_res; -#ifdef SUPPORT_JOYSTICK - chip->joystick_res = joystick_res; -#endif strcpy(card->driver, str); sprintf(card->shortname, "Yamaha DS-XG (%s)", str); sprintf(card->longname, "%s at 0x%lx, irq %i", @@ -292,12 +332,8 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci, return err; } } -#ifdef SUPPORT_JOYSTICK - if (chip->joystick_res) { - chip->gameport.io = joystick_port[dev]; - gameport_register_port(&chip->gameport); - } -#endif + + snd_ymfpci_create_gameport(chip, dev, legacy_ctrl, legacy_ctrl2); if ((err = snd_card_register(card)) < 0) { snd_card_free(card); diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index dd307b8bd..05f162976 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -258,7 +258,7 @@ static int voice_alloc(ymfpci_t *chip, ymfpci_voice_type_t type, int pair, ymfpc return -ENOMEM; } -int snd_ymfpci_voice_alloc(ymfpci_t *chip, ymfpci_voice_type_t type, int pair, ymfpci_voice_t **rvoice) +static int snd_ymfpci_voice_alloc(ymfpci_t *chip, ymfpci_voice_type_t type, int pair, ymfpci_voice_t **rvoice) { unsigned long flags; int result; @@ -278,7 +278,7 @@ int snd_ymfpci_voice_alloc(ymfpci_t *chip, ymfpci_voice_type_t type, int pair, y return result; } -int snd_ymfpci_voice_free(ymfpci_t *chip, ymfpci_voice_t *pvoice) +static int snd_ymfpci_voice_free(ymfpci_t *chip, ymfpci_voice_t *pvoice) { unsigned long flags; @@ -831,8 +831,7 @@ static void snd_ymfpci_pcm_free_substream(snd_pcm_runtime_t *runtime) { ymfpci_pcm_t *ypcm = runtime->private_data; - if (ypcm) - kfree(ypcm); + kfree(ypcm); } static int snd_ymfpci_playback_open_1(snd_pcm_substream_t * substream) @@ -1714,6 +1713,7 @@ int __devinit snd_ymfpci_mixer(ymfpci_t *chip, int rear_switch) if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus)) < 0) return err; chip->ac97_bus->private_free = snd_ymfpci_mixer_free_ac97_bus; + chip->ac97_bus->no_vra = 1; /* YMFPCI doesn't need VRA */ memset(&ac97, 0, sizeof(ac97)); ac97.private_data = chip; @@ -1721,6 +1721,10 @@ int __devinit snd_ymfpci_mixer(ymfpci_t *chip, int rear_switch) if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0) return err; + /* to be sure */ + snd_ac97_update_bits(chip->ac97, AC97_EXTENDED_STATUS, + AC97_EA_VRA|AC97_EA_VRM, 0); + for (idx = 0; idx < ARRAY_SIZE(snd_ymfpci_controls); idx++) { if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_ymfpci_controls[idx], chip))) < 0) return err; @@ -2065,8 +2069,7 @@ static int snd_ymfpci_free(ymfpci_t *chip) #endif #ifdef CONFIG_PM - if (chip->saved_regs) - vfree(chip->saved_regs); + vfree(chip->saved_regs); #endif if (chip->mpu_res) { release_resource(chip->mpu_res); @@ -2076,14 +2079,7 @@ static int snd_ymfpci_free(ymfpci_t *chip) release_resource(chip->fm_res); kfree_nocheck(chip->fm_res); } -#ifdef SUPPORT_JOYSTICK - if (chip->joystick_res) { - if (chip->gameport.io) - gameport_unregister_port(&chip->gameport); - release_resource(chip->joystick_res); - kfree_nocheck(chip->joystick_res); - } -#endif + snd_ymfpci_free_gameport(chip); if (chip->reg_area_virt) iounmap(chip->reg_area_virt); if (chip->work_ptr.area) @@ -2139,7 +2135,7 @@ static int saved_regs_index[] = { }; #define YDSXGR_NUM_SAVED_REGS ARRAY_SIZE(saved_regs_index) -static int snd_ymfpci_suspend(snd_card_t *card, unsigned int state) +static int snd_ymfpci_suspend(snd_card_t *card, pm_message_t state) { ymfpci_t *chip = card->pm_private_data; unsigned int i; @@ -2155,11 +2151,10 @@ static int snd_ymfpci_suspend(snd_card_t *card, unsigned int state) snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0); snd_ymfpci_disable_dsp(chip); pci_disable_device(chip->pci); - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } -static int snd_ymfpci_resume(snd_card_t *card, unsigned int state) +static int snd_ymfpci_resume(snd_card_t *card) { ymfpci_t *chip = card->pm_private_data; unsigned int i; @@ -2183,7 +2178,6 @@ static int snd_ymfpci_resume(snd_card_t *card, unsigned int state) chip->active_bank = snd_ymfpci_readl(chip, YDSXGR_CTRLSELECT); spin_unlock_irq(&chip->reg_lock); } - snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; } #endif /* CONFIG_PM */ diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index 0434acf1f..f72c81cc9 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c @@ -42,8 +42,6 @@ MODULE_SUPPORTED_DEVICE("{{Sound Core," CARD_NAME "}}"); 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 switches */ -static unsigned int irq_mask = 0xffff; -static int irq_list[4] = { -1 }; module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); @@ -51,11 +49,6 @@ module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); -module_param(irq_mask, int, 0444); -MODULE_PARM_DESC(irq_mask, "IRQ bitmask for " CARD_NAME " soundcard."); -module_param_array(irq_list, int, NULL, 0444); -MODULE_PARM_DESC(irq_list, "List of Available interrupts for " CARD_NAME " soundcard."); - /* */ @@ -164,12 +157,7 @@ static dev_link_t *snd_pdacf_attach(void) link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT | IRQ_FORCED_PULSE; // link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; - link->irq.IRQInfo1 = IRQ_INFO2_VALID /* | IRQ_LEVEL_ID */; - if (irq_list[0] == -1) - link->irq.IRQInfo2 = irq_mask; - else - for (i = 0; i < 4; i++) - link->irq.IRQInfo2 |= 1 << irq_list[i]; + link->irq.IRQInfo1 = 0 /* | IRQ_LEVEL_ID */; link->irq.Handler = pdacf_interrupt; link->irq.Instance = pdacf; link->conf.Attributes = CONF_ENABLE_IRQ; @@ -183,7 +171,6 @@ static dev_link_t *snd_pdacf_attach(void) /* Register with Card Services */ client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL #ifdef CONFIG_PM @@ -273,15 +260,6 @@ static void snd_pdacf_detach(dev_link_t *link) snd_card_free_in_thread(chip->card); } -/* - * snd_pdacf_detach_all - detach all instances linked to the hw - */ -static void snd_pdacf_detach_all(void) -{ - while (dev_list != NULL) - snd_pdacf_detach(dev_list); -} - /* * configuration callback */ @@ -294,12 +272,17 @@ static void pdacf_config(dev_link_t *link) client_handle_t handle = link->handle; pdacf_t *pdacf = link->priv; tuple_t tuple; - cisparse_t parse; + cisparse_t *parse = NULL; config_info_t conf; u_short buf[32]; int last_fn, last_ret; snd_printdd(KERN_DEBUG "pdacf_config called\n"); + parse = kmalloc(sizeof(*parse), GFP_KERNEL); + if (! parse) { + snd_printk(KERN_ERR "pdacf_config: cannot allocate\n"); + return; + } tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; tuple.TupleData = (cisdata_t *)buf; @@ -308,9 +291,10 @@ static void pdacf_config(dev_link_t *link) tuple.DesiredTuple = CISTPL_CONFIG; 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; + CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, parse)); + link->conf.ConfigBase = parse->config.base; link->conf.ConfigIndex = 0x5; + kfree(parse); CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); link->conf.Vcc = conf.Vcc; @@ -364,7 +348,7 @@ static int pdacf_event(event_t event, int priority, event_callback_args_t *args) link->state |= DEV_SUSPEND; if (chip) { snd_printdd(KERN_DEBUG "snd_pdacf_suspend calling\n"); - snd_pdacf_suspend(chip->card, 0); + snd_pdacf_suspend(chip->card, PMSG_SUSPEND); } /* Fall through... */ case CS_EVENT_RESET_PHYSICAL: @@ -383,7 +367,7 @@ static int pdacf_event(event_t event, int priority, event_callback_args_t *args) pcmcia_request_configuration(link->handle, &link->conf); if (chip) { snd_printdd(KERN_DEBUG "calling snd_pdacf_resume\n"); - snd_pdacf_resume(chip->card, 0); + snd_pdacf_resume(chip->card); } } snd_printdd(KERN_DEBUG "resume done!\n"); @@ -413,7 +397,7 @@ static int __init init_pdacf(void) static void __exit exit_pdacf(void) { pcmcia_unregister_driver(&pdacf_cs_driver); - snd_pdacf_detach_all(); + BUG_ON(dev_list != NULL); } module_init(init_pdacf); diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.h b/sound/pcmcia/pdaudiocf/pdaudiocf.h index 440a92c66..c7a962825 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.h +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.h @@ -130,14 +130,12 @@ static inline unsigned short pdacf_reg_read(pdacf_t *chip, unsigned char reg) return inw(chip->port + reg); } -unsigned char pdacf_ak4117_read(void *private_data, unsigned char reg); -void pdacf_ak4117_write(void *private_data, unsigned char reg, unsigned char val); pdacf_t *snd_pdacf_create(snd_card_t *card); int snd_pdacf_ak4117_create(pdacf_t *pdacf); void snd_pdacf_powerdown(pdacf_t *chip); #ifdef CONFIG_PM -int snd_pdacf_suspend(snd_card_t *card, unsigned int state); -int snd_pdacf_resume(snd_card_t *card, unsigned int state); +int snd_pdacf_suspend(snd_card_t *card, pm_message_t state); +int snd_pdacf_resume(snd_card_t *card); #endif int snd_pdacf_pcm_new(pdacf_t *chip); irqreturn_t pdacf_interrupt(int irq, void *dev, struct pt_regs *regs); diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c index 9e194fb07..a2132e376 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c @@ -28,7 +28,7 @@ /* * */ -unsigned char pdacf_ak4117_read(void *private_data, unsigned char reg) +static unsigned char pdacf_ak4117_read(void *private_data, unsigned char reg) { pdacf_t *chip = private_data; unsigned long timeout; @@ -60,7 +60,7 @@ unsigned char pdacf_ak4117_read(void *private_data, unsigned char reg) return res; } -void pdacf_ak4117_write(void *private_data, unsigned char reg, unsigned char val) +static void pdacf_ak4117_write(void *private_data, unsigned char reg, unsigned char val) { pdacf_t *chip = private_data; unsigned long timeout; @@ -255,7 +255,7 @@ void snd_pdacf_powerdown(pdacf_t *chip) #ifdef CONFIG_PM -int snd_pdacf_suspend(snd_card_t *card, unsigned int state) +int snd_pdacf_suspend(snd_card_t *card, pm_message_t state) { pdacf_t *chip = card->pm_private_data; u16 val; @@ -267,7 +267,6 @@ int snd_pdacf_suspend(snd_card_t *card, unsigned int state) outw(val, chip->port + PDAUDIOCF_REG_IER); chip->chip_status |= PDAUDIOCF_STAT_IS_SUSPENDED; /* ignore interrupts from now */ snd_pdacf_powerdown(chip); - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } @@ -276,7 +275,7 @@ static inline int check_signal(pdacf_t *chip) return (chip->ak4117->rcs0 & AK4117_UNLCK) == 0; } -int snd_pdacf_resume(snd_card_t *card, unsigned int state) +int snd_pdacf_resume(snd_card_t *card) { pdacf_t *chip = card->pm_private_data; int timeout = 40; @@ -287,7 +286,6 @@ int snd_pdacf_resume(snd_card_t *card, unsigned int state) (snd_ak4117_external_rate(chip->ak4117) <= 0 || !check_signal(chip))) mdelay(1); chip->chip_status &= ~PDAUDIOCF_STAT_IS_SUSPENDED; - snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; } #endif diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c index 63aebb2b0..fce2ad04f 100644 --- a/sound/pcmcia/vx/vxpocket.c +++ b/sound/pcmcia/vx/vxpocket.c @@ -55,8 +55,6 @@ MODULE_SUPPORTED_DEVICE("{{Digigram," CARD_NAME "}}"); 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 switches */ -static unsigned int irq_mask = 0xffff; -static int irq_list[4] = { -1 }; static int ibl[SNDRV_CARDS]; module_param_array(index, int, NULL, 0444); @@ -65,10 +63,6 @@ module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); -module_param(irq_mask, int, 0444); -MODULE_PARM_DESC(irq_mask, "IRQ bitmask for " CARD_NAME " soundcard."); -module_param_array(irq_list, int, NULL, 0444); -MODULE_PARM_DESC(irq_list, "List of Available interrupts for " CARD_NAME " soundcard."); module_param_array(ibl, int, NULL, 0444); MODULE_PARM_DESC(ibl, "Capture IBL size for " CARD_NAME " soundcard."); @@ -123,8 +117,6 @@ static struct snd_vxp_entry hw_entry = { .index_table = index, .id_table = id, .enable_table = enable, - .irq_mask_p = &irq_mask, - .irq_list = irq_list, .ibl = ibl, /* h/w config */ @@ -165,7 +157,7 @@ static int __init init_vxpocket(void) static void __exit exit_vxpocket(void) { pcmcia_unregister_driver(&vxp_cs_driver); - snd_vxpocket_detach_all(&hw_entry); + BUG_ON(hw_entry.dev_list != NULL); } module_init(init_vxpocket); diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c index c4904895d..df073a05b 100644 --- a/sound/ppc/keywest.c +++ b/sound/ppc/keywest.c @@ -76,8 +76,6 @@ static int keywest_attach_adapter(struct i2c_adapter *adapter) new_client->flags = 0; strcpy(i2c_device_name(new_client), keywest_ctx->name); - - new_client->id = keywest_ctx->id++; /* Automatically unique */ keywest_ctx->client = new_client; /* Tell the i2c layer a new client has arrived */ diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index 326fc9d77..080ef3928 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c @@ -27,21 +27,20 @@ #include <linux/delay.h> #include <linux/slab.h> #include <linux/interrupt.h> +#include <linux/pci.h> +#include <linux/dma-mapping.h> #include <sound/core.h> #include "pmac.h" #include <sound/pcm_params.h> -#ifdef CONFIG_PPC_HAS_FEATURE_CALLS #include <asm/pmac_feature.h> -#else -#include <asm/feature.h> -#endif +#include <asm/pci-bridge.h> #if defined(CONFIG_PM) && defined(CONFIG_PMAC_PBOOK) static int snd_pmac_register_sleep_notifier(pmac_t *chip); static int snd_pmac_unregister_sleep_notifier(pmac_t *chip); -static int snd_pmac_suspend(snd_card_t *card, unsigned int state); -static int snd_pmac_resume(snd_card_t *card, unsigned int state); +static int snd_pmac_suspend(snd_card_t *card, pm_message_t state); +static int snd_pmac_resume(snd_card_t *card); #endif @@ -57,22 +56,29 @@ static int tumbler_freqs[1] = { /* * allocate DBDMA command arrays */ -static int snd_pmac_dbdma_alloc(pmac_dbdma_t *rec, int size) +static int snd_pmac_dbdma_alloc(pmac_t *chip, pmac_dbdma_t *rec, int size) { - rec->space = kmalloc(sizeof(struct dbdma_cmd) * (size + 1), GFP_KERNEL); + unsigned int rsize = sizeof(struct dbdma_cmd) * (size + 1); + + rec->space = dma_alloc_coherent(&chip->pdev->dev, rsize, + &rec->dma_base, GFP_KERNEL); if (rec->space == NULL) return -ENOMEM; rec->size = size; - memset(rec->space, 0, sizeof(struct dbdma_cmd) * (size + 1)); + memset(rec->space, 0, rsize); rec->cmds = (void __iomem *)DBDMA_ALIGN(rec->space); - rec->addr = virt_to_bus(rec->cmds); + rec->addr = rec->dma_base + (unsigned long)((char *)rec->cmds - (char *)rec->space); + return 0; } -static void snd_pmac_dbdma_free(pmac_dbdma_t *rec) +static void snd_pmac_dbdma_free(pmac_t *chip, pmac_dbdma_t *rec) { - if (rec && rec->space) - kfree(rec->space); + if (rec) { + unsigned int rsize = sizeof(struct dbdma_cmd) * (rec->size + 1); + + dma_free_coherent(&chip->pdev->dev, rsize, rec->space, rec->dma_base); + } } @@ -237,7 +243,7 @@ static int snd_pmac_pcm_prepare(pmac_t *chip, pmac_stream_t *rec, snd_pcm_substr /* continuous DMA memory type doesn't provide the physical address, * so we need to resolve the address here... */ - offset = virt_to_bus(runtime->dma_area); + offset = runtime->dma_addr; for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++) { st_le32(&cp->phy_addr, offset); st_le16(&cp->req_count, rec->period_size); @@ -664,8 +670,8 @@ int __init snd_pmac_pcm_new(pmac_t *chip) chip->capture.cur_freqs = chip->freqs_ok; /* preallocate 64k buffer */ - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, + &chip->pdev->dev, 64 * 1024, 64 * 1024); return 0; @@ -757,28 +763,10 @@ snd_pmac_ctrl_intr(int irq, void *devid, struct pt_regs *regs) /* * a wrapper to feature call for compatibility */ -#if defined(CONFIG_PM) && defined(CONFIG_PMAC_PBOOK) static void snd_pmac_sound_feature(pmac_t *chip, int enable) { -#ifdef CONFIG_PPC_HAS_FEATURE_CALLS ppc_md.feature_call(PMAC_FTR_SOUND_CHIP_ENABLE, chip->node, 0, enable); -#else - if (chip->is_pbook_G3) { - pmu_suspend(); - feature_clear(chip->node, FEATURE_Sound_power); - feature_clear(chip->node, FEATURE_Sound_CLK_enable); - big_mdelay(1000); /* XXX */ - pmu_resume(); - } - if (chip->is_pbook_3400) { - feature_set(chip->node, FEATURE_IOBUS_enable); - udelay(10); - } -#endif } -#else /* CONFIG_PM && CONFIG_PMAC_PBOOK */ -#define snd_pmac_sound_feature(chip,enable) /**/ -#endif /* CONFIG_PM && CONFIG_PMAC_PBOOK */ /* * release resources @@ -786,8 +774,6 @@ static void snd_pmac_sound_feature(pmac_t *chip, int enable) static int snd_pmac_free(pmac_t *chip) { - int i; - /* stop sounds */ if (chip->initialized) { snd_pmac_dbdma_reset(chip); @@ -813,9 +799,9 @@ static int snd_pmac_free(pmac_t *chip) free_irq(chip->tx_irq, (void*)chip); if (chip->rx_irq >= 0) free_irq(chip->rx_irq, (void*)chip); - snd_pmac_dbdma_free(&chip->playback.cmd); - snd_pmac_dbdma_free(&chip->capture.cmd); - snd_pmac_dbdma_free(&chip->extra_dma); + snd_pmac_dbdma_free(chip, &chip->playback.cmd); + snd_pmac_dbdma_free(chip, &chip->capture.cmd); + snd_pmac_dbdma_free(chip, &chip->extra_dma); if (chip->macio_base) iounmap(chip->macio_base); if (chip->latch_base) @@ -826,12 +812,23 @@ static int snd_pmac_free(pmac_t *chip) iounmap(chip->playback.dma); if (chip->capture.dma) iounmap(chip->capture.dma); +#ifndef CONFIG_PPC64 if (chip->node) { + int i; + for (i = 0; i < 3; i++) { - if (chip->of_requested & (1 << i)) - release_OF_resource(chip->node, i); + if (chip->of_requested & (1 << i)) { + if (chip->is_k2) + release_OF_resource(chip->node->parent, + i); + else + release_OF_resource(chip->node, i); + } } } +#endif /* CONFIG_PPC64 */ + if (chip->pdev) + pci_dev_put(chip->pdev); kfree(chip); return 0; } @@ -879,8 +876,11 @@ 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; + + u32 layout_id = 0; if (_machine != _MACH_Pmac) return -ENODEV; @@ -906,29 +906,43 @@ 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) + if (! chip->node) { chip->node = find_devices("i2s-a"); + if (chip->node && chip->node->parent && + chip->node->parent->parent) { + if (device_is_compatible(chip->node->parent->parent, + "K2-Keylargo")) + chip->is_k2 = 1; + } + } 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); if (prop && *prop < 16) chip->subframe = *prop; + prop = (unsigned int *) get_property(sound, "layout-id", NULL); + if (prop) + layout_id = *prop; /* This should be verified on older screamers */ if (device_is_compatible(sound, "screamer")) { chip->model = PMAC_SCREAMER; @@ -961,25 +975,65 @@ static int __init snd_pmac_detect(pmac_t *chip) chip->freq_table = tumbler_freqs; chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */ } - if (device_is_compatible(sound, "AOAKeylargo")) { - /* Seems to support the stock AWACS frequencies, but has - a snapper mixer */ - chip->model = PMAC_SNAPPER; - // chip->can_byte_swap = 0; /* FIXME: check this */ - chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */ + if (device_is_compatible(sound, "AOAKeylargo") || + device_is_compatible(sound, "AOAbase") || + device_is_compatible(sound, "AOAK2")) { + /* For now, only support very basic TAS3004 based machines with + * single frequency until proper i2s control is implemented + */ + switch(layout_id) { + case 0x48: + case 0x46: + case 0x33: + case 0x29: + case 0x24: + chip->num_freqs = ARRAY_SIZE(tumbler_freqs); + chip->model = PMAC_SNAPPER; + chip->can_byte_swap = 0; /* FIXME: check this */ + chip->control_mask = MASK_IEPC | 0x11;/* disable IEE */ + break; + case 0x3a: + chip->num_freqs = ARRAY_SIZE(tumbler_freqs); + chip->model = PMAC_TOONIE; + chip->can_byte_swap = 0; /* FIXME: check this */ + chip->control_mask = MASK_IEPC | 0x11;/* disable IEE */ + break; + } } prop = (unsigned int *)get_property(sound, "device-id", NULL); if (prop) chip->device_id = *prop; chip->has_iic = (find_devices("perch") != NULL); + /* We need the PCI device for DMA allocations, let's use a crude method + * for now ... + */ + macio = macio_find(chip->node, macio_unknown); + if (macio == NULL) + printk(KERN_WARNING "snd-powermac: can't locate macio !\n"); + else { + struct pci_dev *pdev = NULL; + + for_each_pci_dev(pdev) { + struct device_node *np = pci_device_to_OF_node(pdev); + if (np && np == macio->of_node) { + chip->pdev = pdev; + break; + } + } + } + if (chip->pdev == NULL) + printk(KERN_WARNING "snd-powermac: can't locate macio PCI" + " device !\n"); + detect_byte_swap(chip); /* look for a property saying what sample rates 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; @@ -1006,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; @@ -1015,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; @@ -1077,8 +1133,10 @@ int __init snd_pmac_add_automute(pmac_t *chip) int err; chip->auto_mute = 1; err = snd_ctl_add(chip->card, snd_ctl_new1(&auto_mute_controls[0], chip)); - if (err < 0) + if (err < 0) { + printk(KERN_ERR "snd-powermac: Failed to add automute control\n"); return err; + } chip->hp_detect_ctl = snd_ctl_new1(&auto_mute_controls[1], chip); return snd_ctl_add(chip->card, chip->hp_detect_ctl); } @@ -1092,6 +1150,7 @@ int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return) pmac_t *chip; struct device_node *np; int i, err; + unsigned long ctrl_addr, txdma_addr, rxdma_addr; static snd_device_ops_t ops = { .dev_free = snd_pmac_dev_free, }; @@ -1113,32 +1172,59 @@ int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return) if ((err = snd_pmac_detect(chip)) < 0) goto __error; - if (snd_pmac_dbdma_alloc(&chip->playback.cmd, PMAC_MAX_FRAGS + 1) < 0 || - snd_pmac_dbdma_alloc(&chip->capture.cmd, PMAC_MAX_FRAGS + 1) < 0 || - snd_pmac_dbdma_alloc(&chip->extra_dma, 2) < 0) { + if (snd_pmac_dbdma_alloc(chip, &chip->playback.cmd, PMAC_MAX_FRAGS + 1) < 0 || + snd_pmac_dbdma_alloc(chip, &chip->capture.cmd, PMAC_MAX_FRAGS + 1) < 0 || + snd_pmac_dbdma_alloc(chip, &chip->extra_dma, 2) < 0) { err = -ENOMEM; goto __error; } np = chip->node; - if (np->n_addrs < 3 || np->n_intrs < 3) { - err = -ENODEV; - goto __error; - } + if (chip->is_k2) { + if (np->parent->n_addrs < 2 || np->n_intrs < 3) { + err = -ENODEV; + goto __error; + } + for (i = 0; i < 2; i++) { +#ifndef CONFIG_PPC64 + static char *name[2] = { "- Control", "- DMA" }; + if (! request_OF_resource(np->parent, i, name[i])) { + snd_printk(KERN_ERR "pmac: can't request resource %d!\n", i); + err = -ENODEV; + goto __error; + } + chip->of_requested |= (1 << i); +#endif /* CONFIG_PPC64 */ + ctrl_addr = np->parent->addrs[0].address; + txdma_addr = np->parent->addrs[1].address; + rxdma_addr = txdma_addr + 0x100; + } - for (i = 0; i < 3; i++) { - static char *name[3] = { NULL, "- Tx DMA", "- Rx DMA" }; - if (! request_OF_resource(np, i, name[i])) { - snd_printk(KERN_ERR "pmac: can't request resource %d!\n", i); + } else { + if (np->n_addrs < 3 || np->n_intrs < 3) { err = -ENODEV; goto __error; } - chip->of_requested |= (1 << i); + + for (i = 0; i < 3; i++) { +#ifndef CONFIG_PPC64 + static char *name[3] = { "- Control", "- Tx DMA", "- Rx DMA" }; + if (! request_OF_resource(np, i, name[i])) { + snd_printk(KERN_ERR "pmac: can't request resource %d!\n", i); + err = -ENODEV; + goto __error; + } + chip->of_requested |= (1 << i); +#endif /* CONFIG_PPC64 */ + ctrl_addr = np->addrs[0].address; + txdma_addr = np->addrs[1].address; + rxdma_addr = np->addrs[2].address; + } } - chip->awacs = ioremap(np->addrs[0].address, 0x1000); - chip->playback.dma = ioremap(np->addrs[1].address, 0x100); - chip->capture.dma = ioremap(np->addrs[2].address, 0x100); + chip->awacs = ioremap(ctrl_addr, 0x1000); + chip->playback.dma = ioremap(txdma_addr, 0x100); + chip->capture.dma = ioremap(rxdma_addr, 0x100); if (chip->model <= PMAC_BURGUNDY) { if (request_irq(np->intrs[0].line, snd_pmac_ctrl_intr, 0, "PMac", (void*)chip)) { @@ -1166,7 +1252,8 @@ int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return) snd_pmac_sound_feature(chip, 1); /* reset */ - out_le32(&chip->awacs->control, 0x11); + if (chip->model == PMAC_AWACS) + out_le32(&chip->awacs->control, 0x11); /* Powerbooks have odd ways of enabling inputs such as an expansion-bay CD or sound from an internal modem @@ -1218,6 +1305,8 @@ int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return) return 0; __error: + if (chip->pdev) + pci_dev_put(chip->pdev); snd_pmac_free(chip); return err; } @@ -1233,7 +1322,7 @@ int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return) * Save state when going to sleep, restore it afterwards. */ -static int snd_pmac_suspend(snd_card_t *card, unsigned int state) +static int snd_pmac_suspend(snd_card_t *card, pm_message_t state) { pmac_t *chip = card->pm_private_data; unsigned long flags; @@ -1251,11 +1340,10 @@ static int snd_pmac_suspend(snd_card_t *card, unsigned int state) if (chip->rx_irq >= 0) disable_irq(chip->rx_irq); snd_pmac_sound_feature(chip, 0); - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } -static int snd_pmac_resume(snd_card_t *card, unsigned int state) +static int snd_pmac_resume(snd_card_t *card) { pmac_t *chip = card->pm_private_data; @@ -1278,7 +1366,6 @@ static int snd_pmac_resume(snd_card_t *card, unsigned int state) if (chip->rx_irq >= 0) enable_irq(chip->rx_irq); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; } @@ -1296,10 +1383,10 @@ static int snd_pmac_sleep_notify(struct pmu_sleep_notifier *self, int when) switch (when) { case PBOOK_SLEEP_NOW: - snd_pmac_suspend(chip->card, 0); + snd_pmac_suspend(chip->card, PMSG_SUSPEND); break; case PBOOK_WAKE: - snd_pmac_resume(chip->card, 0); + snd_pmac_resume(chip->card); break; } return PBOOK_SLEEP_OK; diff --git a/sound/ppc/pmac.h b/sound/ppc/pmac.h index a699b0121..0a84c05f7 100644 --- a/sound/ppc/pmac.h +++ b/sound/ppc/pmac.h @@ -60,7 +60,8 @@ typedef struct snd_pmac_dbdma pmac_dbdma_t; * DBDMA space */ struct snd_pmac_dbdma { - unsigned long addr; + dma_addr_t dma_base; + dma_addr_t addr; struct dbdma_cmd __iomem *cmds; void *space; int size; @@ -93,7 +94,8 @@ struct snd_pmac_stream { */ enum snd_pmac_model { - PMAC_AWACS, PMAC_SCREAMER, PMAC_BURGUNDY, PMAC_DACA, PMAC_TUMBLER, PMAC_SNAPPER + PMAC_AWACS, PMAC_SCREAMER, PMAC_BURGUNDY, PMAC_DACA, PMAC_TUMBLER, + PMAC_SNAPPER, PMAC_TOONIE }; struct snd_pmac { @@ -101,6 +103,7 @@ struct snd_pmac { /* h/w info */ struct device_node *node; + struct pci_dev *pdev; unsigned int revision; unsigned int manufacturer; unsigned int subframe; @@ -110,6 +113,7 @@ struct snd_pmac { unsigned int has_iic : 1; unsigned int is_pbook_3400 : 1; unsigned int is_pbook_G3 : 1; + unsigned int is_k2 : 1; unsigned int can_byte_swap : 1; unsigned int can_duplex : 1; @@ -157,6 +161,7 @@ struct snd_pmac { snd_kcontrol_t *speaker_sw_ctl; snd_kcontrol_t *drc_sw_ctl; /* only used for tumbler -ReneR */ snd_kcontrol_t *hp_detect_ctl; + snd_kcontrol_t *lineout_sw_ctl; /* lowlevel callbacks */ void (*set_format)(pmac_t *chip); @@ -187,6 +192,7 @@ int snd_pmac_burgundy_init(pmac_t *chip); int snd_pmac_daca_init(pmac_t *chip); int snd_pmac_tumbler_init(pmac_t *chip); int snd_pmac_tumbler_post_init(void); +int snd_pmac_toonie_init(pmac_t *chip); /* i2c functions */ typedef struct snd_pmac_keywest { diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c index 8f1953a8e..231f6432e 100644 --- a/sound/ppc/powermac.c +++ b/sound/ppc/powermac.c @@ -95,6 +95,13 @@ static int __init snd_pmac_probe(void) if ( snd_pmac_tumbler_init(chip) < 0 || snd_pmac_tumbler_post_init() < 0) goto __error; break; + case PMAC_TOONIE: + strcpy(card->driver, "PMac Toonie"); + strcpy(card->shortname, "PowerMac Toonie"); + strcpy(card->longname, card->shortname); + if ((err = snd_pmac_toonie_init(chip)) < 0) + goto __error; + break; case PMAC_AWACS: case PMAC_SCREAMER: name_ext = chip->model == PMAC_SCREAMER ? "Screamer" : "AWACS"; diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index 7d10385f0..9332237cb 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c @@ -35,12 +35,19 @@ #include <sound/core.h> #include <asm/io.h> #include <asm/irq.h> -#ifdef CONFIG_PPC_HAS_FEATURE_CALLS +#include <asm/machdep.h> #include <asm/pmac_feature.h> -#endif #include "pmac.h" #include "tumbler_volume.h" +#undef DEBUG + +#ifdef DEBUG +#define DBG(fmt...) printk(fmt) +#else +#define DBG(fmt...) +#endif + /* i2c address for tumbler */ #define TAS_I2C_ADDR 0x34 @@ -76,28 +83,35 @@ enum { }; typedef struct pmac_gpio { -#ifdef CONFIG_PPC_HAS_FEATURE_CALLS unsigned int addr; -#else - void __iomem *addr; -#endif - int active_state; + u8 active_val; + u8 inactive_val; + u8 active_state; } pmac_gpio_t; typedef struct pmac_tumbler_t { pmac_keywest_t i2c; pmac_gpio_t audio_reset; pmac_gpio_t amp_mute; + pmac_gpio_t line_mute; + pmac_gpio_t line_detect; pmac_gpio_t hp_mute; pmac_gpio_t hp_detect; int headphone_irq; + int lineout_irq; + unsigned int save_master_vol[2]; unsigned int master_vol[2]; + unsigned int save_master_switch[2]; unsigned int master_switch[2]; unsigned int mono_vol[VOL_IDX_LAST_MONO]; unsigned int mix_vol[VOL_IDX_LAST_MIX][2]; /* stereo volumes for tas3004 */ int drc_range; int drc_enable; int capture_source; + int anded_reset; + int auto_mute_notify; + int reset_on_sleep; + u8 acs; } pmac_tumbler_t; @@ -113,6 +127,7 @@ static int send_init_client(pmac_keywest_t *i2c, unsigned int *regs) regs[0], regs[1]); if (err >= 0) break; + DBG("(W) i2c error %d\n", err); mdelay(10); } while (count--); if (err < 0) @@ -130,6 +145,7 @@ static int tumbler_init_client(pmac_keywest_t *i2c) TAS_REG_MCS, (1<<6)|(2<<4)|(2<<2)|0, 0, /* terminator */ }; + DBG("(I) tumbler init client\n"); return send_init_client(i2c, regs); } @@ -144,36 +160,38 @@ static int snapper_init_client(pmac_keywest_t *i2c) TAS_REG_ACS, 0, 0, /* terminator */ }; + DBG("(I) snapper init client\n"); return send_init_client(i2c, regs); } /* * gpio access */ -#ifdef CONFIG_PPC_HAS_FEATURE_CALLS #define do_gpio_write(gp, val) \ pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, (gp)->addr, val) #define do_gpio_read(gp) \ pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, (gp)->addr, 0) #define tumbler_gpio_free(gp) /* NOP */ -#else -#define do_gpio_write(gp, val) writeb(val, (gp)->addr) -#define do_gpio_read(gp) readb((gp)->addr) -static inline void tumbler_gpio_free(pmac_gpio_t *gp) -{ - if (gp->addr) { - iounmap(gp->addr); - gp->addr = NULL; - } -} -#endif /* CONFIG_PPC_HAS_FEATURE_CALLS */ static void write_audio_gpio(pmac_gpio_t *gp, int active) { if (! gp->addr) return; - active = active ? gp->active_state : !gp->active_state; - do_gpio_write(gp, active ? 0x05 : 0x04); + active = active ? gp->active_val : gp->inactive_val; + do_gpio_write(gp, active); + DBG("(I) gpio %x write %d\n", gp->addr, active); +} + +static int check_audio_gpio(pmac_gpio_t *gp) +{ + int ret; + + if (! gp->addr) + return 0; + + ret = do_gpio_read(gp); + + return (ret & 0xd) == (gp->active_val & 0xd); } static int read_audio_gpio(pmac_gpio_t *gp) @@ -652,10 +670,11 @@ static int snapper_put_mix(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucont /* - * mute switches + * mute switches. FIXME: Turn that into software mute when both outputs are muted + * to avoid codec reset on ibook M7 */ -enum { TUMBLER_MUTE_HP, TUMBLER_MUTE_AMP }; +enum { TUMBLER_MUTE_HP, TUMBLER_MUTE_AMP, TUMBLER_MUTE_LINE }; static int tumbler_get_mute_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { @@ -664,8 +683,19 @@ static int tumbler_get_mute_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_ pmac_gpio_t *gp; if (! (mix = chip->mixer_data)) return -ENODEV; - gp = (kcontrol->private_value == TUMBLER_MUTE_HP) ? &mix->hp_mute : &mix->amp_mute; - ucontrol->value.integer.value[0] = ! read_audio_gpio(gp); + switch(kcontrol->private_value) { + case TUMBLER_MUTE_HP: + gp = &mix->hp_mute; break; + case TUMBLER_MUTE_AMP: + gp = &mix->amp_mute; break; + case TUMBLER_MUTE_LINE: + gp = &mix->line_mute; break; + default: + gp = NULL; + } + if (gp == NULL) + return -EINVAL; + ucontrol->value.integer.value[0] = !check_audio_gpio(gp); return 0; } @@ -681,8 +711,19 @@ static int tumbler_put_mute_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_ #endif if (! (mix = chip->mixer_data)) return -ENODEV; - gp = (kcontrol->private_value == TUMBLER_MUTE_HP) ? &mix->hp_mute : &mix->amp_mute; - val = ! read_audio_gpio(gp); + switch(kcontrol->private_value) { + case TUMBLER_MUTE_HP: + gp = &mix->hp_mute; break; + case TUMBLER_MUTE_AMP: + gp = &mix->amp_mute; break; + case TUMBLER_MUTE_LINE: + gp = &mix->line_mute; break; + default: + gp = NULL; + } + if (gp == NULL) + return -EINVAL; + val = ! check_audio_gpio(gp); if (val != ucontrol->value.integer.value[0]) { write_audio_gpio(gp, ! ucontrol->value.integer.value[0]); return 1; @@ -694,8 +735,11 @@ static int snapper_set_capture_source(pmac_tumbler_t *mix) { if (! mix->i2c.client) return -ENODEV; - return i2c_smbus_write_byte_data(mix->i2c.client, TAS_REG_ACS, - mix->capture_source ? 2 : 0); + if (mix->capture_source) + mix->acs = mix->acs |= 2; + else + mix->acs &= ~2; + return i2c_smbus_write_byte_data(mix->i2c.client, TAS_REG_ACS, mix->acs); } static int snapper_info_capture_source(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) @@ -822,6 +866,14 @@ static snd_kcontrol_new_t tumbler_speaker_sw __initdata = { .put = tumbler_put_mute_switch, .private_value = TUMBLER_MUTE_AMP, }; +static snd_kcontrol_new_t tumbler_lineout_sw __initdata = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Line Out Playback Switch", + .info = snd_pmac_boolean_mono_info, + .get = tumbler_get_mute_switch, + .put = tumbler_put_mute_switch, + .private_value = TUMBLER_MUTE_LINE, +}; static snd_kcontrol_new_t tumbler_drc_sw __initdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "DRC Switch", @@ -838,31 +890,84 @@ static snd_kcontrol_new_t tumbler_drc_sw __initdata = { static int tumbler_detect_headphone(pmac_t *chip) { pmac_tumbler_t *mix = chip->mixer_data; - return read_audio_gpio(&mix->hp_detect); + int detect = 0; + + if (mix->hp_detect.addr) + detect |= read_audio_gpio(&mix->hp_detect); + return detect; +} + +static int tumbler_detect_lineout(pmac_t *chip) +{ + pmac_tumbler_t *mix = chip->mixer_data; + int detect = 0; + + if (mix->line_detect.addr) + detect |= read_audio_gpio(&mix->line_detect); + return detect; } static void check_mute(pmac_t *chip, pmac_gpio_t *gp, int val, int do_notify, snd_kcontrol_t *sw) { - //pmac_tumbler_t *mix = chip->mixer_data; - if (val != read_audio_gpio(gp)) { + if (check_audio_gpio(gp) != val) { write_audio_gpio(gp, val); if (do_notify) - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &sw->id); + snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, + &sw->id); } } static struct work_struct device_change; -static void -device_change_handler(void *self) +static void device_change_handler(void *self) { pmac_t *chip = (pmac_t*) self; pmac_tumbler_t *mix; + int headphone, lineout; if (!chip) return; mix = chip->mixer_data; + snd_assert(mix, return); + + headphone = tumbler_detect_headphone(chip); + lineout = tumbler_detect_lineout(chip); + + DBG("headphone: %d, lineout: %d\n", headphone, lineout); + + if (headphone || lineout) { + /* unmute headphone/lineout & mute speaker */ + if (headphone) + check_mute(chip, &mix->hp_mute, 0, mix->auto_mute_notify, + chip->master_sw_ctl); + if (lineout && mix->line_mute.addr != 0) + check_mute(chip, &mix->line_mute, 0, mix->auto_mute_notify, + chip->lineout_sw_ctl); + if (mix->anded_reset) + big_mdelay(10); + check_mute(chip, &mix->amp_mute, 1, mix->auto_mute_notify, + chip->speaker_sw_ctl); + mix->drc_enable = 0; + } else { + /* unmute speaker, mute others */ + check_mute(chip, &mix->amp_mute, 0, mix->auto_mute_notify, + chip->speaker_sw_ctl); + if (mix->anded_reset) + big_mdelay(10); + check_mute(chip, &mix->hp_mute, 1, mix->auto_mute_notify, + chip->master_sw_ctl); + if (mix->line_mute.addr != 0) + check_mute(chip, &mix->line_mute, 1, mix->auto_mute_notify, + chip->lineout_sw_ctl); + mix->drc_enable = 1; + } + if (mix->auto_mute_notify) { + snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, + &chip->hp_detect_ctl->id); + snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, + &chip->drc_sw_ctl->id); + } /* first set the DRC so the speaker do not explode -ReneR */ if (chip->model == PMAC_TUMBLER) @@ -877,31 +982,11 @@ device_change_handler(void *self) static void tumbler_update_automute(pmac_t *chip, int do_notify) { if (chip->auto_mute) { - pmac_tumbler_t *mix = chip->mixer_data; + pmac_tumbler_t *mix; + mix = chip->mixer_data; snd_assert(mix, return); - if (tumbler_detect_headphone(chip)) { - /* mute speaker */ - check_mute(chip, &mix->amp_mute, 1, do_notify, chip->speaker_sw_ctl); - check_mute(chip, &mix->hp_mute, 0, do_notify, chip->master_sw_ctl); - mix->drc_enable = 0; - - } else { - /* unmute speaker */ - check_mute(chip, &mix->amp_mute, 0, do_notify, chip->speaker_sw_ctl); - check_mute(chip, &mix->hp_mute, 1, do_notify, chip->master_sw_ctl); - mix->drc_enable = 1; - } - if (do_notify) { - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->hp_detect_ctl->id); - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->drc_sw_ctl->id); - } - - /* finally we need to schedule an update of the mixer values - (master and DRC are enough for now) -ReneR */ + mix->auto_mute_notify = do_notify; schedule_work(&device_change); - } } #endif /* PMAC_SUPPORT_AUTOMUTE */ @@ -950,37 +1035,67 @@ static struct device_node *find_compatible_audio_device(const char *name) } /* find an audio device and get its address */ -static unsigned long tumbler_find_device(const char *device, pmac_gpio_t *gp, int is_compatible) +static long tumbler_find_device(const char *device, const char *platform, pmac_gpio_t *gp, int is_compatible) { struct device_node *node; - u32 *base; + u32 *base, addr; if (is_compatible) node = find_compatible_audio_device(device); else node = find_audio_device(device); if (! node) { + DBG("(W) cannot find audio device %s !\n", device); snd_printdd("cannot find device %s\n", device); return -ENODEV; } base = (u32 *)get_property(node, "AAPL,address", NULL); if (! base) { - snd_printd("cannot find address for device %s\n", device); - return -ENODEV; - } + base = (u32 *)get_property(node, "reg", NULL); + if (!base) { + DBG("(E) cannot find address for device %s !\n", device); + snd_printd("cannot find address for device %s\n", device); + return -ENODEV; + } + addr = *base; + if (addr < 0x50) + addr += 0x50; + } else + addr = *base; -#ifdef CONFIG_PPC_HAS_FEATURE_CALLS - gp->addr = (*base) & 0x0000ffff; -#else - gp->addr = ioremap((unsigned long)(*base), 1); -#endif + gp->addr = addr & 0x0000ffff; + /* Try to find the active state, default to 0 ! */ base = (u32 *)get_property(node, "audio-gpio-active-state", NULL); - if (base) + if (base) { gp->active_state = *base; - else - gp->active_state = 1; + gp->active_val = (*base) ? 0x5 : 0x4; + gp->inactive_val = (*base) ? 0x4 : 0x5; + } else { + u32 *prop = NULL; + gp->active_state = 0; + gp->active_val = 0x4; + gp->inactive_val = 0x5; + /* Here are some crude hacks to extract the GPIO polarity and + * open collector informations out of the do-platform script + * as we don't yet have an interpreter for these things + */ + if (platform) + prop = (u32 *)get_property(node, platform, NULL); + if (prop) { + if (prop[3] == 0x9 && prop[4] == 0x9) { + gp->active_val = 0xd; + gp->inactive_val = 0xc; + } + if (prop[3] == 0x1 && prop[4] == 0x1) { + gp->active_val = 0x5; + gp->inactive_val = 0x4; + } + } + } + DBG("(I) GPIO device %s found, offset: %x, active state: %d !\n", + device, gp->addr, gp->active_state); return (node->n_intrs > 0) ? node->intrs[0].line : 0; } @@ -990,15 +1105,60 @@ static void tumbler_reset_audio(pmac_t *chip) { pmac_tumbler_t *mix = chip->mixer_data; - write_audio_gpio(&mix->audio_reset, 0); - big_mdelay(200); - write_audio_gpio(&mix->audio_reset, 1); - big_mdelay(100); - write_audio_gpio(&mix->audio_reset, 0); - big_mdelay(100); + if (mix->anded_reset) { + DBG("(I) codec anded reset !\n"); + write_audio_gpio(&mix->hp_mute, 0); + write_audio_gpio(&mix->amp_mute, 0); + big_mdelay(200); + write_audio_gpio(&mix->hp_mute, 1); + write_audio_gpio(&mix->amp_mute, 1); + big_mdelay(100); + write_audio_gpio(&mix->hp_mute, 0); + write_audio_gpio(&mix->amp_mute, 0); + big_mdelay(100); + } else { + DBG("(I) codec normal reset !\n"); + + write_audio_gpio(&mix->audio_reset, 0); + big_mdelay(200); + write_audio_gpio(&mix->audio_reset, 1); + big_mdelay(100); + write_audio_gpio(&mix->audio_reset, 0); + big_mdelay(100); + } } #ifdef CONFIG_PMAC_PBOOK +/* suspend mixer */ +static void tumbler_suspend(pmac_t *chip) +{ + pmac_tumbler_t *mix = chip->mixer_data; + + if (mix->headphone_irq >= 0) + disable_irq(mix->headphone_irq); + if (mix->lineout_irq >= 0) + disable_irq(mix->lineout_irq); + mix->save_master_switch[0] = mix->master_switch[0]; + mix->save_master_switch[1] = mix->master_switch[1]; + mix->save_master_vol[0] = mix->master_vol[0]; + mix->save_master_vol[1] = mix->master_vol[1]; + mix->master_switch[0] = mix->master_switch[1] = 0; + tumbler_set_master_volume(mix); + if (!mix->anded_reset) { + write_audio_gpio(&mix->amp_mute, 1); + write_audio_gpio(&mix->hp_mute, 1); + } + if (chip->model == PMAC_SNAPPER) { + mix->acs |= 1; + i2c_smbus_write_byte_data(mix->i2c.client, TAS_REG_ACS, mix->acs); + } + if (mix->anded_reset) { + write_audio_gpio(&mix->amp_mute, 1); + write_audio_gpio(&mix->hp_mute, 1); + } else + write_audio_gpio(&mix->audio_reset, 1); +} + /* resume mixer */ static void tumbler_resume(pmac_t *chip) { @@ -1006,6 +1166,11 @@ static void tumbler_resume(pmac_t *chip) snd_assert(mix, return); + mix->acs &= ~1; + mix->master_switch[0] = mix->save_master_switch[0]; + mix->master_switch[1] = mix->save_master_switch[1]; + mix->master_vol[0] = mix->save_master_vol[0]; + mix->master_vol[1] = mix->save_master_vol[1]; tumbler_reset_audio(chip); if (mix->i2c.client && mix->i2c.init_client) { if (mix->i2c.init_client(&mix->i2c) < 0) @@ -1029,36 +1194,61 @@ static void tumbler_resume(pmac_t *chip) tumbler_set_master_volume(mix); if (chip->update_automute) chip->update_automute(chip, 0); + if (mix->headphone_irq >= 0) + enable_irq(mix->headphone_irq); + if (mix->lineout_irq >= 0) + enable_irq(mix->lineout_irq); } #endif /* initialize tumbler */ static int __init tumbler_init(pmac_t *chip) { - int irq, err; + int irq; pmac_tumbler_t *mix = chip->mixer_data; snd_assert(mix, return -EINVAL); - tumbler_find_device("audio-hw-reset", &mix->audio_reset, 0); - tumbler_find_device("amp-mute", &mix->amp_mute, 0); - tumbler_find_device("headphone-mute", &mix->hp_mute, 0); - irq = tumbler_find_device("headphone-detect", &mix->hp_detect, 0); + if (tumbler_find_device("audio-hw-reset", + "platform-do-hw-reset", + &mix->audio_reset, 0) < 0) + tumbler_find_device("hw-reset", + "platform-do-hw-reset", + &mix->audio_reset, 1); + if (tumbler_find_device("amp-mute", + "platform-do-amp-mute", + &mix->amp_mute, 0) < 0) + tumbler_find_device("amp-mute", + "platform-do-amp-mute", + &mix->amp_mute, 1); + if (tumbler_find_device("headphone-mute", + "platform-do-headphone-mute", + &mix->hp_mute, 0) < 0) + tumbler_find_device("headphone-mute", + "platform-do-headphone-mute", + &mix->hp_mute, 1); + if (tumbler_find_device("line-output-mute", + "platform-do-lineout-mute", + &mix->line_mute, 0) < 0) + tumbler_find_device("line-output-mute", + "platform-do-lineout-mute", + &mix->line_mute, 1); + irq = tumbler_find_device("headphone-detect", + NULL, &mix->hp_detect, 0); + if (irq < 0) + irq = tumbler_find_device("headphone-detect", + NULL, &mix->hp_detect, 1); if (irq < 0) - irq = tumbler_find_device("keywest-gpio15", &mix->hp_detect, 1); + irq = tumbler_find_device("keywest-gpio15", + NULL, &mix->hp_detect, 1); + mix->headphone_irq = irq; + irq = tumbler_find_device("line-output-detect", + NULL, &mix->line_detect, 0); + if (irq < 0) + irq = tumbler_find_device("line-output-detect", + NULL, &mix->line_detect, 1); + mix->lineout_irq = irq; tumbler_reset_audio(chip); - - /* activate headphone status interrupts */ - if (irq >= 0) { - unsigned char val; - if ((err = request_irq(irq, headphone_intr, 0, - "Tumbler Headphone Detection", chip)) < 0) - return err; - /* activate headphone status interrupts */ - val = do_gpio_read(&mix->hp_detect); - do_gpio_write(&mix->hp_detect, val | 0x80); - } - mix->headphone_irq = irq; return 0; } @@ -1071,6 +1261,8 @@ static void tumbler_cleanup(pmac_t *chip) if (mix->headphone_irq >= 0) free_irq(mix->headphone_irq, chip); + if (mix->lineout_irq >= 0) + free_irq(mix->lineout_irq, chip); tumbler_gpio_free(&mix->audio_reset); tumbler_gpio_free(&mix->amp_mute); tumbler_gpio_free(&mix->hp_mute); @@ -1086,7 +1278,7 @@ int __init snd_pmac_tumbler_init(pmac_t *chip) int i, err; pmac_tumbler_t *mix; u32 *paddr; - struct device_node *tas_node; + struct device_node *tas_node, *np; char *chipname; #ifdef CONFIG_KMOD @@ -1102,21 +1294,38 @@ int __init snd_pmac_tumbler_init(pmac_t *chip) chip->mixer_data = mix; chip->mixer_free = tumbler_cleanup; - + mix->anded_reset = 0; + mix->reset_on_sleep = 1; + + for (np = chip->node->child; np; np = np->sibling) { + if (!strcmp(np->name, "sound")) { + if (get_property(np, "has-anded-reset", NULL)) + mix->anded_reset = 1; + if (get_property(np, "layout-id", NULL)) + mix->reset_on_sleep = 0; + break; + } + } if ((err = tumbler_init(chip)) < 0) return err; /* set up TAS */ tas_node = find_devices("deq"); + if (tas_node == NULL) + tas_node = find_devices("codec"); if (tas_node == NULL) return -ENODEV; paddr = (u32 *)get_property(tas_node, "i2c-address", NULL); + if (paddr == NULL) + paddr = (u32 *)get_property(tas_node, "reg", NULL); if (paddr) mix->i2c.addr = (*paddr) >> 1; else mix->i2c.addr = TAS_I2C_ADDR; + DBG("(I) TAS i2c address is: %x\n", mix->i2c.addr); + if (chip->model == PMAC_TUMBLER) { mix->i2c.init_client = tumbler_init_client; mix->i2c.name = "TAS3001c"; @@ -1152,23 +1361,49 @@ int __init snd_pmac_tumbler_init(pmac_t *chip) chip->speaker_sw_ctl = snd_ctl_new1(&tumbler_speaker_sw, chip); if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0) return err; + if (mix->line_mute.addr != 0) { + chip->lineout_sw_ctl = snd_ctl_new1(&tumbler_lineout_sw, chip); + if ((err = snd_ctl_add(chip->card, chip->lineout_sw_ctl)) < 0) + return err; + } chip->drc_sw_ctl = snd_ctl_new1(&tumbler_drc_sw, chip); if ((err = snd_ctl_add(chip->card, chip->drc_sw_ctl)) < 0) return err; - #ifdef CONFIG_PMAC_PBOOK + chip->suspend = tumbler_suspend; chip->resume = tumbler_resume; #endif INIT_WORK(&device_change, device_change_handler, (void *)chip); #ifdef PMAC_SUPPORT_AUTOMUTE - if (mix->headphone_irq >=0 && (err = snd_pmac_add_automute(chip)) < 0) + if ((mix->headphone_irq >=0 || mix->lineout_irq >= 0) + && (err = snd_pmac_add_automute(chip)) < 0) return err; chip->detect_headphone = tumbler_detect_headphone; chip->update_automute = tumbler_update_automute; tumbler_update_automute(chip, 0); /* update the status only */ + + /* activate headphone status interrupts */ + if (mix->headphone_irq >= 0) { + unsigned char val; + if ((err = request_irq(mix->headphone_irq, headphone_intr, 0, + "Sound Headphone Detection", chip)) < 0) + return 0; + /* activate headphone status interrupts */ + val = do_gpio_read(&mix->hp_detect); + do_gpio_write(&mix->hp_detect, val | 0x80); + } + if (mix->lineout_irq >= 0) { + unsigned char val; + if ((err = request_irq(mix->lineout_irq, headphone_intr, 0, + "Sound Lineout Detection", chip)) < 0) + return 0; + /* activate headphone status interrupts */ + val = do_gpio_read(&mix->line_detect); + do_gpio_write(&mix->line_detect, val | 0x80); + } #endif return 0; diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index 696543c4d..36f9fe4d7 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -390,7 +390,7 @@ static void __cs4231_writeb(cs4231_t *cp, u8 val, void __iomem *reg_addr) * Basic I/O functions */ -void snd_cs4231_outm(cs4231_t *chip, unsigned char reg, +static void snd_cs4231_outm(cs4231_t *chip, unsigned char reg, unsigned char mask, unsigned char value) { int timeout; @@ -473,9 +473,9 @@ static unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg) return ret; } -#ifdef CONFIG_SND_DEBUG +#if 0 -void snd_cs4231_debug(cs4231_t *chip) +static void snd_cs4231_debug(cs4231_t *chip) { printk("CS4231 REGS: INDEX = 0x%02x ", __cs4231_readb(chip, CS4231P(chip, REGSEL))); @@ -560,7 +560,6 @@ static void snd_cs4231_mce_down(cs4231_t *chip) { unsigned long flags; int timeout; - signed long time; spin_lock_irqsave(&chip->lock, flags); snd_cs4231_busy_wait(chip); @@ -594,29 +593,29 @@ static void snd_cs4231_mce_down(cs4231_t *chip) #if 0 printk("(2) timeout = %i, jiffies = %li\n", timeout, jiffies); #endif - time = HZ / 4; + /* in 10ms increments, check condition, up to 250ms */ + timeout = 25; while (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) { spin_unlock_irqrestore(&chip->lock, flags); - if (time <= 0) { + if (--timeout < 0) { snd_printk("mce_down - auto calibration time out (2)\n"); return; } - set_current_state(TASK_INTERRUPTIBLE); - time = schedule_timeout(time); + msleep(10); spin_lock_irqsave(&chip->lock, flags); } #if 0 printk("(3) jiffies = %li\n", jiffies); #endif - time = HZ / 10; + /* in 10ms increments, check condition, up to 100ms */ + timeout = 10; while (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) { spin_unlock_irqrestore(&chip->lock, flags); - if (time <= 0) { + if (--timeout < 0) { snd_printk("mce_down - auto calibration time out (3)\n"); return; } - set_current_state(TASK_INTERRUPTIBLE); - time = schedule_timeout(time); + msleep(10); spin_lock_irqsave(&chip->lock, flags); } spin_unlock_irqrestore(&chip->lock, flags); diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 18efa78b2..aae66144d 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -1141,7 +1141,7 @@ static int init_usb_pitch(struct usb_device *dev, int iface, data[0] = 1; if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, - PITCH_CONTROL << 8, ep, data, 1, HZ)) < 0) { + PITCH_CONTROL << 8, ep, data, 1, 1000)) < 0) { snd_printk(KERN_ERR "%d:%d:%d: cannot set enable PITCH\n", dev->devnum, iface, ep); return err; @@ -1167,14 +1167,14 @@ static int init_usb_sample_rate(struct usb_device *dev, int iface, data[2] = rate >> 16; if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, - SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) { + SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) { snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep 0x%x\n", dev->devnum, iface, fmt->altsetting, rate, ep); return err; } if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN, - SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) { + SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) { snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep 0x%x\n", dev->devnum, iface, fmt->altsetting, ep); return 0; /* some devices don't support reading */ @@ -1606,62 +1606,65 @@ static int hw_rule_format(snd_pcm_hw_params_t *params, return changed; } +#define MAX_MASK 64 + /* * check whether the registered audio formats need special hw-constraints */ static int check_hw_params_convention(snd_usb_substream_t *subs) { int i; - u32 channels[64]; - u32 rates[64]; + u32 *channels; + u32 *rates; u32 cmaster, rmaster; u32 rate_min = 0, rate_max = 0; struct list_head *p; + int err = 1; - memset(channels, 0, sizeof(channels)); - memset(rates, 0, sizeof(rates)); + channels = kcalloc(MAX_MASK, sizeof(u32), GFP_KERNEL); + rates = kcalloc(MAX_MASK, sizeof(u32), GFP_KERNEL); list_for_each(p, &subs->fmt_list) { struct audioformat *f; f = list_entry(p, struct audioformat, list); /* unconventional channels? */ if (f->channels > 32) - return 1; + goto __out; /* continuous rate min/max matches? */ if (f->rates & SNDRV_PCM_RATE_CONTINUOUS) { if (rate_min && f->rate_min != rate_min) - return 1; + goto __out; if (rate_max && f->rate_max != rate_max) - return 1; + goto __out; rate_min = f->rate_min; rate_max = f->rate_max; } /* combination of continuous rates and fixed rates? */ if (rates[f->format] & SNDRV_PCM_RATE_CONTINUOUS) { if (f->rates != rates[f->format]) - return 1; + goto __out; } if (f->rates & SNDRV_PCM_RATE_CONTINUOUS) { if (rates[f->format] && rates[f->format] != f->rates) - return 1; + goto __out; } channels[f->format] |= (1 << f->channels); rates[f->format] |= f->rates; } /* check whether channels and rates match for all formats */ cmaster = rmaster = 0; - for (i = 0; i < 64; i++) { + for (i = 0; i < MAX_MASK; i++) { if (cmaster != channels[i] && cmaster && channels[i]) - return 1; + goto __out; if (rmaster != rates[i] && rmaster && rates[i]) - return 1; + goto __out; if (channels[i]) cmaster = channels[i]; if (rates[i]) rmaster = rates[i]; } /* check whether channels match for all distinct rates */ - memset(channels, 0, sizeof(channels)); + memset(channels, 0, MAX_MASK * sizeof(u32)); list_for_each(p, &subs->fmt_list) { struct audioformat *f; f = list_entry(p, struct audioformat, list); @@ -1675,11 +1678,16 @@ static int check_hw_params_convention(snd_usb_substream_t *subs) cmaster = 0; for (i = 0; i < 32; i++) { if (cmaster != channels[i] && cmaster && channels[i]) - return 1; + goto __out; if (channels[i]) cmaster = channels[i]; } - return 0; + err = 0; + + __out: + kfree(channels); + kfree(rates); + return err; } @@ -2066,8 +2074,7 @@ static void free_substream(snd_usb_substream_t *subs) return; /* not initialized */ list_for_each_safe(p, n, &subs->fmt_list) { struct audioformat *fp = list_entry(p, struct audioformat, list); - if (fp->rate_table) - kfree(fp->rate_table); + kfree(fp->rate_table); kfree(fp); } } @@ -2179,13 +2186,13 @@ static int add_audio_endpoint(snd_usb_audio_t *chip, int stream, struct audiofor static int is_big_endian_format(struct usb_device *dev, struct audioformat *fp) { /* M-Audio */ - if (dev->descriptor.idVendor == 0x0763) { + if (le16_to_cpu(dev->descriptor.idVendor) == 0x0763) { /* Quattro: captured data only */ - if (dev->descriptor.idProduct == 0x2001 && + if (le16_to_cpu(dev->descriptor.idProduct) == 0x2001 && fp->endpoint & USB_DIR_IN) return 1; /* Audiophile USB */ - if (dev->descriptor.idProduct == 0x2003) + if (le16_to_cpu(dev->descriptor.idProduct) == 0x2003) return 1; } return 0; @@ -2249,7 +2256,8 @@ static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat break; case USB_AUDIO_FORMAT_PCM8: /* Dallas DS4201 workaround */ - if (dev->descriptor.idVendor == 0x04fa && dev->descriptor.idProduct == 0x4201) + if (le16_to_cpu(dev->descriptor.idVendor) == 0x04fa && + le16_to_cpu(dev->descriptor.idProduct) == 0x4201) pcm_format = SNDRV_PCM_FORMAT_S8; else pcm_format = SNDRV_PCM_FORMAT_U8; @@ -2417,7 +2425,8 @@ static int parse_audio_format(struct usb_device *dev, struct audioformat *fp, /* extigy apparently supports sample rates other than 48k * but not in ordinary way. so we enable only 48k atm. */ - if (dev->descriptor.idVendor == 0x041e && dev->descriptor.idProduct == 0x3000) { + if (le16_to_cpu(dev->descriptor.idVendor) == 0x041e && + le16_to_cpu(dev->descriptor.idProduct) == 0x3000) { if (fmt[3] == USB_FORMAT_TYPE_I && stream == SNDRV_PCM_STREAM_PLAYBACK && fp->rates != SNDRV_PCM_RATE_48000) @@ -2451,7 +2460,7 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no) (altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIO_STREAMING && altsd->bInterfaceSubClass != USB_SUBCLASS_VENDOR_SPEC) || altsd->bNumEndpoints < 1 || - get_endpoint(alts, 0)->wMaxPacketSize == 0) + le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == 0) continue; /* must be isochronous */ if ((get_endpoint(alts, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != @@ -2514,14 +2523,14 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no) fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; /* FIXME: decode wMaxPacketSize of high bandwith endpoints */ - fp->maxpacksize = get_endpoint(alts, 0)->wMaxPacketSize; + fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); fp->attributes = csep[3]; /* some quirks for attributes here */ /* workaround for AudioTrak Optoplay */ - if (dev->descriptor.idVendor == 0x0a92 && - dev->descriptor.idProduct == 0x0053) { + if (le16_to_cpu(dev->descriptor.idVendor) == 0x0a92 && + le16_to_cpu(dev->descriptor.idProduct) == 0x0053) { /* Optoplay sets the sample rate attribute although * it seems not supporting it in fact. */ @@ -2529,8 +2538,8 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no) } /* workaround for M-Audio Audiophile USB */ - if (dev->descriptor.idVendor == 0x0763 && - dev->descriptor.idProduct == 0x2003) { + if (le16_to_cpu(dev->descriptor.idVendor) == 0x0763 && + le16_to_cpu(dev->descriptor.idProduct) == 0x2003) { /* doesn't set the sample rate attribute, but supports it */ fp->attributes |= EP_CS_ATTR_SAMPLE_RATE; } @@ -2539,11 +2548,11 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no) * plantronics headset and Griffin iMic have set adaptive-in * although it's really not... */ - if ((dev->descriptor.idVendor == 0x047f && - dev->descriptor.idProduct == 0x0ca1) || + 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) */ - (dev->descriptor.idVendor == 0x077d && - dev->descriptor.idProduct == 0x07af)) { + (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; @@ -2553,8 +2562,7 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no) /* ok, let's parse further... */ if (parse_audio_format(dev, fp, format, fmt, stream) < 0) { - if (fp->rate_table) - kfree(fp->rate_table); + kfree(fp->rate_table); kfree(fp); continue; } @@ -2562,8 +2570,7 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no) snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint 0x%x\n", dev->devnum, iface_no, i, fp->endpoint); err = add_audio_endpoint(chip, stream, fp); if (err < 0) { - if (fp->rate_table) - kfree(fp->rate_table); + kfree(fp->rate_table); kfree(fp); return err; } @@ -2696,15 +2703,13 @@ static int create_fixed_stream_quirk(snd_usb_audio_t *chip, err = add_audio_endpoint(chip, stream, fp); if (err < 0) { kfree(fp); - if (rate_table) - kfree(rate_table); + kfree(rate_table); return err; } if (fp->iface != get_iface_desc(&iface->altsetting[0])->bInterfaceNumber || fp->altset_idx >= iface->num_altsetting) { kfree(fp); - if (rate_table) - kfree(rate_table); + kfree(rate_table); return -EINVAL; } alts = &iface->altsetting[fp->altset_idx]; @@ -2791,7 +2796,7 @@ static int create_ua700_ua25_quirk(snd_usb_audio_t *chip, .type = QUIRK_MIDI_FIXED_ENDPOINT, .data = &ua25_ep }; - if (chip->dev->descriptor.idProduct == 0x002b) + if (le16_to_cpu(chip->dev->descriptor.idProduct) == 0x002b) return snd_usb_create_midi_interface(chip, iface, &ua700_quirk); else @@ -2810,7 +2815,7 @@ static int create_ua700_ua25_quirk(snd_usb_audio_t *chip, fp->iface = altsd->bInterfaceNumber; fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; - fp->maxpacksize = get_endpoint(alts, 0)->wMaxPacketSize; + fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); switch (fp->maxpacksize) { case 0x120: @@ -2876,7 +2881,7 @@ static int create_ua1000_quirk(snd_usb_audio_t *chip, struct usb_interface *ifac fp->iface = altsd->bInterfaceNumber; fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; - fp->maxpacksize = get_endpoint(alts, 0)->wMaxPacketSize; + fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); fp->rate_max = fp->rate_min = combine_triple(&alts->extra[8]); stream = (fp->endpoint & USB_DIR_IN) @@ -2934,12 +2939,12 @@ static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interfac struct usb_host_config *config = dev->actconfig; int err; - if (get_cfg_desc(config)->wTotalLength == EXTIGY_FIRMWARE_SIZE_OLD || - get_cfg_desc(config)->wTotalLength == EXTIGY_FIRMWARE_SIZE_NEW) { + if (le16_to_cpu(get_cfg_desc(config)->wTotalLength) == EXTIGY_FIRMWARE_SIZE_OLD || + le16_to_cpu(get_cfg_desc(config)->wTotalLength) == EXTIGY_FIRMWARE_SIZE_NEW) { snd_printdd("sending Extigy boot sequence...\n"); /* Send message to force it to reconnect with full interface. */ err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev,0), - 0x10, 0x43, 0x0001, 0x000a, NULL, 0, HZ); + 0x10, 0x43, 0x0001, 0x000a, NULL, 0, 1000); if (err < 0) snd_printdd("error sending boot message: %d\n", err); err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, sizeof(dev->descriptor)); @@ -2947,7 +2952,8 @@ static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interfac if (err < 0) snd_printdd("error usb_get_descriptor: %d\n", err); err = usb_reset_configuration(dev); if (err < 0) snd_printdd("error usb_reset_configuration: %d\n", err); - snd_printdd("extigy_boot: new boot length = %d\n", get_cfg_desc(config)->wTotalLength); + snd_printdd("extigy_boot: new boot length = %d\n", + le16_to_cpu(get_cfg_desc(config)->wTotalLength)); return -ENODEV; /* quit this anyway */ } return 0; @@ -2970,6 +2976,9 @@ static int snd_usb_create_quirk(snd_usb_audio_t *chip, case QUIRK_MIDI_FIXED_ENDPOINT: case QUIRK_MIDI_YAMAHA: case QUIRK_MIDI_MIDIMAN: + case QUIRK_MIDI_NOVATION: + case QUIRK_MIDI_MOTU: + case QUIRK_MIDI_EMAGIC: return snd_usb_create_midi_interface(chip, iface, quirk); case QUIRK_COMPOSITE: return create_composite_quirk(chip, iface, quirk); @@ -2982,6 +2991,8 @@ static int snd_usb_create_quirk(snd_usb_audio_t *chip, return create_ua700_ua25_quirk(chip, iface); case QUIRK_AUDIO_EDIROL_UA1000: return create_ua1000_quirk(chip, iface); + case QUIRK_IGNORE_INTERFACE: + return 0; default: snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type); return -ENXIO; @@ -3003,7 +3014,9 @@ 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", chip->dev->descriptor.idVendor, chip->dev->descriptor.idProduct); + snd_iprintf(buffer, "%04x:%04x\n", + le16_to_cpu(chip->dev->descriptor.idVendor), + le16_to_cpu(chip->dev->descriptor.idProduct)); } static void snd_usb_audio_create_proc(snd_usb_audio_t *chip) @@ -3084,7 +3097,8 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, strcpy(card->driver, "USB-Audio"); sprintf(component, "USB%04x:%04x", - dev->descriptor.idVendor, dev->descriptor.idProduct); + le16_to_cpu(dev->descriptor.idVendor), + le16_to_cpu(dev->descriptor.idProduct)); snd_component_add(card, component); /* retrieve the device string as shortname */ @@ -3096,7 +3110,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", - dev->descriptor.idVendor, dev->descriptor.idProduct); + le16_to_cpu(dev->descriptor.idVendor), + le16_to_cpu(dev->descriptor.idProduct)); } } @@ -3163,7 +3178,8 @@ static void *snd_usb_audio_probe(struct usb_device *dev, /* SB Extigy needs special boot-up sequence */ /* if more models come, this will go to the quirk list. */ - if (dev->descriptor.idVendor == 0x041e && dev->descriptor.idProduct == 0x3000) { + if (le16_to_cpu(dev->descriptor.idVendor) == 0x041e && + le16_to_cpu(dev->descriptor.idProduct) == 0x3000) { if (snd_usb_extigy_boot_quirk(dev, intf) < 0) goto __err_val; config = dev->actconfig; @@ -3197,8 +3213,8 @@ 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] == dev->descriptor.idVendor) && - (pid[i] == -1 || pid[i] == dev->descriptor.idProduct)) { + (vid[i] == -1 || vid[i] == le16_to_cpu(dev->descriptor.idVendor)) && + (pid[i] == -1 || pid[i] == le16_to_cpu(dev->descriptor.idProduct))) { if (snd_usb_audio_create(dev, i, quirk, &chip) < 0) { goto __error; } @@ -3273,7 +3289,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr) } usb_chip[chip->index] = NULL; up(®ister_mutex); - snd_card_free_in_thread(card); + snd_card_free(card); } else { up(®ister_mutex); } diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 5da9e5ee7..eecbf19fc 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -157,6 +157,10 @@ struct snd_usb_audio { #define QUIRK_MIDI_STANDARD_INTERFACE 6 #define QUIRK_AUDIO_EDIROL_UA700_UA25 7 #define QUIRK_AUDIO_EDIROL_UA1000 8 +#define QUIRK_IGNORE_INTERFACE 9 +#define QUIRK_MIDI_NOVATION 10 +#define QUIRK_MIDI_MOTU 11 +#define QUIRK_MIDI_EMAGIC 12 typedef struct snd_usb_audio_quirk snd_usb_audio_quirk_t; typedef struct snd_usb_midi_endpoint_info snd_usb_midi_endpoint_info_t; @@ -171,7 +175,10 @@ struct snd_usb_audio_quirk { /* data for QUIRK_MIDI_FIXED_ENDPOINT */ struct snd_usb_midi_endpoint_info { - int8_t out_ep, in_ep; /* ep number, 0 autodetect */ + int8_t out_ep; /* ep number, 0 autodetect */ + uint8_t out_interval; /* interval for interrupt endpoints */ + int8_t in_ep; + uint8_t in_interval; uint16_t out_cables; /* bitmask */ uint16_t in_cables; /* bitmask */ }; @@ -190,6 +197,13 @@ struct snd_usb_midi_endpoint_info { /* for QUIRK_AUDIO_EDIROL_UA700_UA25/UA1000, data is NULL */ +/* for QUIRK_IGNORE_INTERFACE, data is NULL */ + +/* for QUIRK_MIDI_NOVATION and _MOTU, data is NULL */ + +/* for QUIRK_MIDI_EMAGIC, data points to a snd_usb_midi_endpoint_info + * structure (out_cables and in_cables only) */ + /* */ diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index 1d0aa0332..5f1906915 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c @@ -305,7 +305,7 @@ static int get_ctl_value(usb_mixer_elem_info_t *cval, int request, int validx, i request, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, validx, cval->ctrlif | (cval->id << 8), - buf, val_len, HZ / 10) >= 0) { + buf, val_len, 100) >= 0) { *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); return 0; } @@ -343,7 +343,7 @@ static int set_ctl_value(usb_mixer_elem_info_t *cval, int request, int validx, i request, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, validx, cval->ctrlif | (cval->id << 8), - buf, val_len, HZ / 10) >= 0) + 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]); return -EINVAL; @@ -374,7 +374,7 @@ static int parse_audio_unit(mixer_build_t *state, int unitid); static int check_matrix_bitmap(unsigned char *bmap, int ich, int och, int num_outs) { int idx = ich * num_outs + och; - return bmap[-(idx >> 3)] & (0x80 >> (idx & 7)); + return bmap[idx >> 3] & (0x80 >> (idx & 7)); } @@ -573,7 +573,7 @@ static struct usb_feature_control_info audio_feature_info[] = { static void usb_mixer_elem_free(snd_kcontrol_t *kctl) { if (kctl->private_data) { - kfree((void *)kctl->private_data); + kfree(kctl->private_data); kctl->private_data = NULL; } } @@ -931,14 +931,14 @@ static int parse_audio_feature_unit(mixer_build_t *state, int unitid, unsigned c */ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc, - int in_ch, int unitid) + int in_pin, int in_ch, int unitid, + usb_audio_term_t *iterm) { usb_mixer_elem_info_t *cval; - unsigned int num_ins = desc[4]; - unsigned int num_outs = desc[5 + num_ins]; + unsigned int input_pins = desc[4]; + unsigned int num_outs = desc[5 + input_pins]; unsigned int i, len; snd_kcontrol_t *kctl; - usb_audio_term_t iterm; if (check_ignored_ctl(state, unitid, 0)) return; @@ -947,16 +947,13 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc, if (! cval) return; - if (check_input_term(state, desc[5 + in_ch], &iterm) < 0) - return; - cval->chip = state->chip; cval->ctrlif = state->ctrlif; cval->id = unitid; cval->control = in_ch + 1; /* based on 1 */ cval->val_type = USB_MIXER_S16; for (i = 0; i < num_outs; i++) { - if (check_matrix_bitmap(desc + 9 + num_ins, in_ch, i, num_outs)) { + if (check_matrix_bitmap(desc + 9 + input_pins, in_ch, i, num_outs)) { cval->cmask |= (1 << i); cval->channels++; } @@ -975,9 +972,9 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc, len = check_mapped_name(state, unitid, 0, kctl->id.name, sizeof(kctl->id.name)); if (! len) - len = get_term_name(state, &iterm, kctl->id.name, sizeof(kctl->id.name), 0); + len = get_term_name(state, iterm, kctl->id.name, sizeof(kctl->id.name), 0); if (! len) - len = sprintf(kctl->id.name, "Mixer Source %d", in_ch); + len = sprintf(kctl->id.name, "Mixer Source %d", in_ch + 1); strlcat(kctl->id.name + len, " Volume", sizeof(kctl->id.name)); snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n", @@ -991,17 +988,44 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc, */ static int parse_audio_mixer_unit(mixer_build_t *state, int unitid, unsigned char *desc) { - int num_ins, num_outs; - int i, err; - if (desc[0] < 12 || ! (num_ins = desc[4]) || ! (num_outs = desc[5 + num_ins])) + usb_audio_term_t iterm; + int input_pins, num_ins, num_outs; + int pin, ich, err; + + if (desc[0] < 11 || ! (input_pins = desc[4]) || ! (num_outs = desc[5 + input_pins])) { + snd_printk(KERN_ERR "invalid MIXER UNIT descriptor %d\n", unitid); return -EINVAL; + } + /* no bmControls field (e.g. Maya44) -> ignore */ + if (desc[0] <= 10 + input_pins) { + snd_printdd(KERN_INFO "MU %d has no bmControls field\n", unitid); + return 0; + } - for (i = 0; i < num_ins; i++) { - err = parse_audio_unit(state, desc[5 + i]); + num_ins = 0; + ich = 0; + for (pin = 0; pin < input_pins; pin++) { + err = parse_audio_unit(state, desc[5 + pin]); + if (err < 0) + return err; + err = check_input_term(state, desc[5 + pin], &iterm); if (err < 0) return err; - if (check_matrix_bitmap(desc + 9 + num_ins, i, 0, num_outs)) - build_mixer_unit_ctl(state, desc, i, unitid); + num_ins += iterm.channels; + for (; ich < num_ins; ++ich) { + int och, ich_has_controls = 0; + + for (och = 0; och < num_outs; ++och) { + if (check_matrix_bitmap(desc + 9 + input_pins, + ich, och, num_outs)) { + ich_has_controls = 1; + break; + } + } + if (ich_has_controls) + build_mixer_unit_ctl(state, desc, pin, ich, + unitid, &iterm); + } } return 0; } @@ -1490,12 +1514,12 @@ int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif) state.buffer = hostif->extra; state.buflen = hostif->extralen; state.ctrlif = ctrlif; - state.vendor = dev->idVendor; - state.product = dev->idProduct; + 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 == dev->idVendor && map->product == dev->idProduct) { + if (map->vendor == state.vendor && map->product == state.product) { state.map = map->map; chip->ignore_ctl_error = map->ignore_ctl_error; break; diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h index e79721ce1..88bbd944d 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h @@ -72,6 +72,8 @@ YAMAHA_DEVICE(0x1007, "MOTIF8"), YAMAHA_DEVICE(0x1008, "UX96"), YAMAHA_DEVICE(0x1009, "UX16"), YAMAHA_INTERFACE(0x100a, 3, "EOS BX"), +YAMAHA_DEVICE(0x100c, "UC-MX"), +YAMAHA_DEVICE(0x100d, "UC-KX"), YAMAHA_DEVICE(0x100e, "S08"), YAMAHA_DEVICE(0x100f, "CLP-150"), YAMAHA_DEVICE(0x1010, "CLP-170"), @@ -86,6 +88,7 @@ YAMAHA_DEVICE(0x1019, "CVP-208"), YAMAHA_DEVICE(0x101a, "CVP-210"), YAMAHA_DEVICE(0x101b, "PSR-1100"), YAMAHA_DEVICE(0x101c, "PSR-2100"), +YAMAHA_DEVICE(0x101d, "CLP-175"), YAMAHA_DEVICE(0x101e, "PSR-K1"), YAMAHA_DEVICE(0x1020, "EZ-250i"), YAMAHA_DEVICE(0x1021, "MOTIF ES 6"), @@ -125,9 +128,12 @@ YAMAHA_DEVICE(0x5005, "ACU16-C"), YAMAHA_DEVICE(0x5006, "NHB32-C"), YAMAHA_DEVICE(0x5007, "DM1000"), YAMAHA_DEVICE(0x5008, "01V96"), +YAMAHA_DEVICE(0x5009, "SPX2000"), YAMAHA_DEVICE(0x500a, "PM5D"), YAMAHA_DEVICE(0x500b, "DME64N"), YAMAHA_DEVICE(0x500c, "DME24N"), +YAMAHA_DEVICE(0x500d, NULL), +YAMAHA_DEVICE(0x500e, NULL), YAMAHA_DEVICE(0x7000, "DTX"), YAMAHA_DEVICE(0x7010, "UB99"), #undef YAMAHA_DEVICE @@ -628,6 +634,19 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, +{ + USB_DEVICE(0x0582, 0x0042), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Roland", + .product_name = "RS-70", + .ifnum = 0, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x0001, + .in_cables = 0x0001 + } + } +}, { USB_DEVICE(0x0582, 0x0044), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { @@ -684,19 +703,6 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, -{ - USB_DEVICE(0x0582, 0x0065), - .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { - .vendor_name = "EDIROL", - .product_name = "PCR-1", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const snd_usb_midi_endpoint_info_t) { - .out_cables = 0x0001, - .in_cables = 0x0003 - } - } -}, { /* * This quirk is for the "Advanced Driver" mode. If off, the UA-3FX @@ -732,6 +738,45 @@ YAMAHA_DEVICE(0x7010, "UB99"), .type = QUIRK_MIDI_STANDARD_INTERFACE } }, +{ + USB_DEVICE(0x0582, 0x0065), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "EDIROL", + .product_name = "PCR-1", + .ifnum = 0, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x0001, + .in_cables = 0x0003 + } + } +}, +{ + USB_DEVICE_VENDOR_SPEC(0x0582, 0x006a), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Roland", + .product_name = "SP-606", + .ifnum = 3, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x0001, + .in_cables = 0x0001 + } + } +}, +{ + USB_DEVICE(0x0582, 0x006d), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Roland", + .product_name = "FANTOM-X", + .ifnum = 0, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x0001, + .in_cables = 0x0001 + } + } +}, { /* * This quirk is for the "Advanced" modes of the Edirol UA-25. * If the switch is not in an advanced setting, the UA-25 has @@ -763,6 +808,19 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, +{ + USB_DEVICE(0x0582, 0x0075), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "BOSS", + .product_name = "DR-880", + .ifnum = 0, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x0001, + .in_cables = 0x0001 + } + } +}, /* Midiman/M-Audio devices */ { @@ -875,6 +933,22 @@ YAMAHA_DEVICE(0x7010, "UB99"), * Ignore them. The other interfaces can do 24 bits, * but captured samples are big-endian (see usbaudio.c). */ + { + .ifnum = 0, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = 1, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = 2, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = 3, + .type = QUIRK_IGNORE_INTERFACE + }, { .ifnum = 4, .type = QUIRK_AUDIO_STANDARD_INTERFACE @@ -883,6 +957,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), .ifnum = 5, .type = QUIRK_AUDIO_STANDARD_INTERFACE }, + { + .ifnum = 6, + .type = QUIRK_IGNORE_INTERFACE + }, { .ifnum = 7, .type = QUIRK_AUDIO_STANDARD_INTERFACE @@ -936,27 +1014,81 @@ YAMAHA_DEVICE(0x7010, "UB99"), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "M-Audio", .product_name = "OmniStudio", - .ifnum = 9, - .type = QUIRK_MIDI_MIDIMAN, - .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_IGNORE_INTERFACE + }, + { + .ifnum = 3, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = 4, + .type = QUIRK_AUDIO_STANDARD_INTERFACE + }, + { + .ifnum = 5, + .type = QUIRK_AUDIO_STANDARD_INTERFACE + }, + { + .ifnum = 6, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = 7, + .type = QUIRK_AUDIO_STANDARD_INTERFACE + }, + { + .ifnum = 8, + .type = QUIRK_AUDIO_STANDARD_INTERFACE + }, + { + .ifnum = 9, + .type = QUIRK_MIDI_MIDIMAN, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x0001, + .in_cables = 0x0001 + } + }, + { + .ifnum = -1 + } } } }, /* Mark of the Unicorn devices */ { - /* thanks to Woodley Packard <sweaglesw@thibs.menloschool.org> */ + /* thanks to Robert A. Lerche <ral 'at' msbit.com> */ USB_DEVICE(0x07fd, 0x0001), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "MOTU", .product_name = "Fastlane", - .ifnum = 1, - .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_MIDI_MOTU + }, + { + .ifnum = 1, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = -1 + } } } }, @@ -972,6 +1104,47 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, +/* Emagic devices */ +{ + USB_DEVICE(0x086a, 0x0001), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Emagic", + /* .product_name = "Unitor8", */ + .ifnum = 2, + .type = QUIRK_MIDI_EMAGIC, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x80ff, + .in_cables = 0x80ff + } + } +}, +{ + USB_DEVICE(0x086a, 0x0002), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Emagic", + /* .product_name = "AMT8", */ + .ifnum = 2, + .type = QUIRK_MIDI_EMAGIC, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x80ff, + .in_cables = 0x80ff + } + } +}, +{ + USB_DEVICE(0x086a, 0x0003), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Emagic", + /* .product_name = "MT4", */ + .ifnum = 2, + .type = QUIRK_MIDI_EMAGIC, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x800f, + .in_cables = 0x8003 + } + } +}, + { USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0013), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { @@ -982,6 +1155,35 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, +/* Novation EMS devices */ +{ + USB_DEVICE_VENDOR_SPEC(0x1235, 0x0001), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Novation", + .product_name = "ReMOTE Audio/XStation", + .ifnum = 4, + .type = QUIRK_MIDI_NOVATION + } +}, +{ + USB_DEVICE_VENDOR_SPEC(0x1235, 0x0002), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Novation", + .product_name = "Speedio", + .ifnum = 3, + .type = QUIRK_MIDI_NOVATION + } +}, +{ + USB_DEVICE_VENDOR_SPEC(0x1235, 0x4661), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Novation", + .product_name = "ReMOTE25", + .ifnum = 0, + .type = QUIRK_MIDI_NOVATION + } +}, + { /* * Some USB MIDI devices don't have an audio control interface, diff --git a/usr/initramfs_list b/usr/initramfs_list deleted file mode 100644 index 53efa2eed..000000000 --- a/usr/initramfs_list +++ /dev/null @@ -1,5 +0,0 @@ -# This is a very simple initramfs - -dir /dev 0755 0 0 -nod /dev/console 0600 0 0 c 5 1 -dir /root 0700 0 0 -- 2.47.0