From aea3fab536c540958b654389b5c9c11db00730f7 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:35:07 -0500 Subject: [PATCH] Import 2.3.99pre10-1 --- CREDITS | 2 +- Documentation/Configure.help | 8 + Documentation/DocBook/Makefile | 6 + Documentation/usb/ov511.txt | 6 +- Makefile | 12 +- arch/i386/config.in | 13 +- arch/i386/kernel/entry.S | 5 + arch/i386/kernel/process.c | 90 +++++ arch/i386/kernel/ptrace.c | 13 +- arch/i386/kernel/setup.c | 19 +- arch/i386/kernel/signal.c | 6 +- arch/i386/kernel/traps.c | 22 +- arch/sparc/kernel/Makefile | 2 +- arch/sparc64/defconfig | 7 + arch/sparc64/kernel/Makefile | 6 +- arch/sparc64/kernel/ioctl32.c | 570 +++++++++++++++++++++++++++- arch/sparc64/kernel/sparc64_ksyms.c | 6 +- arch/sparc64/mm/modutil.c | 4 +- drivers/char/Config.in | 1 + drivers/char/videodev.c | 190 +++++++++- drivers/ide/Config.in | 3 +- drivers/ide/Makefile | 2 +- drivers/ide/hd.c | 3 + drivers/ide/ide-features.c | 8 +- drivers/ide/ide-geometry.c | 4 +- drivers/ide/ide-probe.c | 10 +- drivers/ide/ide-tape.c | 8 +- drivers/ide/ide.c | 16 +- drivers/ide/piix.c | 18 +- drivers/ide/via82cxxx.c | 9 +- drivers/sound/es1370.c | 14 +- drivers/sound/es1371.c | 129 +++++-- drivers/sound/esssolo1.c | 31 +- drivers/sound/sonicvibes.c | 25 +- drivers/usb/audio.c | 165 ++++++-- drivers/usb/ibmcam.c | 78 ++-- drivers/usb/ov511.c | 422 +++++++++++--------- fs/nfs/flushd.c | 3 +- fs/nfs/inode.c | 2 + fs/nfs/write.c | 28 +- fs/nfsd/nfscache.c | 7 +- fs/partitions/msdos.c | 16 +- fs/super.c | 16 +- fs/ufs/super.c | 32 +- include/asm-alpha/ide.h | 2 +- include/asm-i386/ide.h | 2 +- include/asm-i386/processor.h | 86 ++++- include/asm-i386/sigcontext.h | 4 + include/asm-i386/user.h | 4 +- include/asm-ia64/ide.h | 2 +- include/asm-sh/ide.h | 12 +- include/asm-sparc/ide.h | 2 +- include/asm-sparc64/ide.h | 2 +- include/linux/nfs_flushd.h | 3 +- include/linux/pci_ids.h | 3 + include/linux/ufs_fs.h | 31 +- kernel/ksyms.c | 1 - net/ipv6/netfilter/Config.in | 4 +- scripts/kernel-doc | 2 +- scripts/mkdep.c | 10 +- 60 files changed, 1783 insertions(+), 424 deletions(-) diff --git a/CREDITS b/CREDITS index 868858e14045..b0f58d59646e 100644 --- a/CREDITS +++ b/CREDITS @@ -1632,7 +1632,7 @@ N: Claudio S. Matsuoka E: claudio@conectiva.com E: claudio@helllabs.org W: http://helllabs.org/~claudio -D: OV511 driver hacks +D: V4L, OV511 driver hacks S: Conectiva S.A. S: R. Tocantins 89 S: 80050-430 Curitiba PR diff --git a/Documentation/Configure.help b/Documentation/Configure.help index 4d7b936a3d12..467327737eb4 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -14830,6 +14830,14 @@ CONFIG_VIDEO_DEV whenever you want). If you want to compile it as a module, say M here and read Documentation/modules.txt. +Video For Linux /proc file system information +CONFIG_VIDEO_PROC_FS + If you say Y here, you are able to access video device information + in /proc/video. + + To use this option, you have to check, that the "/proc file system + support" (CONFIG_PROC_FS) is enabled too. + AIMSlab RadioTrack (aka RadioReveal) support CONFIG_RADIO_RTRACK Choose Y here if you have one of these FM radio cards, and then fill diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 8a40bfade13a..0f84cb2186f4 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -24,6 +24,12 @@ db2ps db2pdf: $(TOPDIR)/scripts/docproc: $(MAKE) -C $(TOPDIR)/scripts docproc +kernel-hacking.sgml: kernel-hacking.tmpl + $(TOPDIR)/scripts/docgen <$< >$@ + +kernel-locking.sgml: kernel-locking.tmpl + $(TOPDIR)/scripts/docgen <$< >$@ + wanbook.sgml: wanbook.tmpl $(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/net/wan/syncppp.c \ wanbook.sgml diff --git a/Documentation/usb/ov511.txt b/Documentation/usb/ov511.txt index d57cc2e236b2..65a0c4caab3e 100644 --- a/Documentation/usb/ov511.txt +++ b/Documentation/usb/ov511.txt @@ -6,8 +6,8 @@ Author: Mark McClelland Homepage: http://alpha.dyndns.org/ov511 NEW IN THIS VERSION: - o 352x288 mode - o force_rgb parameter for apps that expect RGB instead of BGR + o 384x288 and 448x336 modes + o better /proc/video support INTRODUCTION: @@ -179,7 +179,7 @@ MODULE PARAMETERS: your colors look VERY wrong, you may want to change this. WORKING FEATURES: - o Color streaming/capture at 640x480, 352x288, and 320x240 + o Color streaming/capture at 640x480, 448x336, 384x288, 352x288, and 320x240 o YUV420 color o Monochrome o Setting/getting of saturation, contrast and brightness (no hue yet; only diff --git a/Makefile b/Makefile index 0fdbd42a42f7..a2d1995469bb 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 -PATCHLEVEL = 3 -SUBLEVEL = 99 -EXTRAVERSION = -pre9 +PATCHLEVEL = 4 +SUBLEVEL = 0 +EXTRAVERSION = -test1 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) @@ -159,8 +159,8 @@ DRIVERS-$(CONFIG_DIO) += drivers/dio/dio.a DRIVERS-$(CONFIG_SBUS) += drivers/sbus/sbus.a DRIVERS-$(CONFIG_ZORRO) += drivers/zorro/zorro.a DRIVERS-$(CONFIG_FC4) += drivers/fc4/fc4.a -DRIVERS-$(CONFIG_PPC) += drivers/macintosh/macintosh.a -DRIVERS-$(CONFIG_MAC) += drivers/macintosh/macintosh.a +DRIVERS-$(CONFIG_PPC) += drivers/macintosh/macintosh.o +DRIVERS-$(CONFIG_MAC) += drivers/macintosh/macintosh.o DRIVERS-$(CONFIG_ISAPNP) += drivers/pnp/pnp.o DRIVERS-$(CONFIG_SGI_IP22) += drivers/sgi/sgi.a DRIVERS-$(CONFIG_VT) += drivers/video/video.o @@ -427,7 +427,7 @@ sums: dep-files: scripts/mkdep archdep include/linux/version.h scripts/mkdep init/*.c > .depend - scripts/mkdep `find $(FINDHPATH) -follow -name \*.h ! -name modversions.h -print` > .hdepend + scripts/mkdep `find $(FINDHPATH) -name SCCS -prune -or -follow -name \*.h ! -name modversions.h -print` > .hdepend $(MAKE) $(patsubst %,_sfdep_%,$(SUBDIRS)) _FASTDEP_ALL_SUB_DIRS="$(SUBDIRS)" ifdef CONFIG_MODVERSIONS diff --git a/arch/i386/config.in b/arch/i386/config.in index 1208a6b82a6c..5bc10fd501f6 100644 --- a/arch/i386/config.in +++ b/arch/i386/config.in @@ -23,6 +23,7 @@ choice 'Processor family' \ 586/K5/5x86/6x86/6x86MX CONFIG_M586 \ Pentium/TSC CONFIG_M586TSC \ PPro/P-II/P-III CONFIG_M686 \ + Pentium-III CONFIG_M686FX \ K6/II/III CONFIG_MK6 \ Athlon CONFIG_MK7" PPro # @@ -60,6 +61,14 @@ if [ "$CONFIG_M686" = "y" ]; then define_bool CONFIG_X86_PGE y define_bool CONFIG_X86_USE_PPRO_CHECKSUM y fi +if [ "$CONFIG_M686FX" = "y" ]; then + define_int CONFIG_X86_L1_CACHE_BYTES 32 + define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_GOOD_APIC y + define_bool CONFIG_X86_PGE y + define_bool CONFIG_X86_USE_PPRO_CHECKSUM y + define_bool CONFIG_X86_FX y +fi if [ "$CONFIG_MK6" = "y" ]; then define_int CONFIG_X86_L1_CACHE_BYTES 32 define_bool CONFIG_X86_ALIGNMENT_16 y @@ -89,7 +98,9 @@ if [ "$CONFIG_HIGHMEM64G" = "y" ]; then define_bool CONFIG_X86_PAE y fi -bool 'Math emulation' CONFIG_MATH_EMULATION +if [ "$CONFIG_X86_FX" != "y" ]; then + bool 'Math emulation' CONFIG_MATH_EMULATION +fi bool 'MTRR (Memory Type Range Register) support' CONFIG_MTRR bool 'Symmetric multi-processing support' CONFIG_SMP if [ "$CONFIG_SMP" != "y" ]; then diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index 50887c15c7e0..26f3d505de78 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S @@ -413,6 +413,11 @@ ENTRY(spurious_interrupt_bug) pushl $ SYMBOL_NAME(do_spurious_interrupt_bug) jmp error_code +ENTRY(xmm_fault) + pushl $0 + pushl $ SYMBOL_NAME(do_xmm_fault) + jmp error_code + .data ENTRY(sys_call_table) .long SYMBOL_NAME(sys_ni_syscall) /* 0 - old "setup()" system call*/ diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 96eedb51959b..dddd807c8469 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -2,6 +2,8 @@ * linux/arch/i386/kernel/process.c * * Copyright (C) 1995 Linus Torvalds + * Pentium III code by Ingo Molnar with changes and support for + * OS exception support by Goutham Rao */ /* @@ -469,6 +471,94 @@ void copy_segments(struct task_struct *p, struct mm_struct *new_mm) return; } +#ifdef CONFIG_X86_FX + +int i387_hard_to_user ( struct _fpstate * user, + struct i387_hard_struct * hard) +{ + int i, err = 0; + short *tmp, *tmp2; + long *ltmp1, *ltmp2; + + err |= put_user(hard->cwd, &user->cw); + err |= put_user(hard->swd, &user->sw); + err |= put_user(fputag_KNIto387(hard->twd), &user->tag); + err |= put_user(hard->fip, &user->ipoff); + err |= put_user(hard->fcs, &user->cssel); + err |= put_user(hard->fdp, &user->dataoff); + err |= put_user(hard->fds, &user->datasel); + err |= put_user(hard->mxcsr, &user->mxcsr); + + tmp = (short *)&user->_st; + tmp2 = (short *)&hard->st_space; + + /* + * Transform the two layouts: + * (we do not mix 32-bit access with 16-bit access because + * thats suboptimal on PPros) + */ + for (i = 0; i < 8; i++) + { + err |= put_user(*tmp2, tmp); tmp++; tmp2++; + err |= put_user(*tmp2, tmp); tmp++; tmp2++; + err |= put_user(*tmp2, tmp); tmp++; tmp2++; + err |= put_user(*tmp2, tmp); tmp++; tmp2++; + err |= put_user(*tmp2, tmp); tmp++; tmp2 += 3; + } + + ltmp1 = (unsigned long *)&(user->_xmm[0]); + ltmp2 = (unsigned long *)&(hard->xmm_space[0]); + for(i = 0; i < 88; i++) + { + err |= put_user(*ltmp2, ltmp1); + ltmp1++; ltmp2++; + } + + return err; +} + +int i387_user_to_hard (struct i387_hard_struct * hard, + struct _fpstate * user) +{ + int i, err = 0; + short *tmp, *tmp2; + long *ltmp1, *ltmp2; + + err |= get_user(hard->cwd, &user->cw); + err |= get_user(hard->swd, &user->sw); + err |= get_user(hard->twd, &user->tag); + hard->twd = fputag_387toKNI(hard->twd); + err |= get_user(hard->fip, &user->ipoff); + err |= get_user(hard->fcs, &user->cssel); + err |= get_user(hard->fdp, &user->dataoff); + err |= get_user(hard->fds, &user->datasel); + err |= get_user(hard->mxcsr, &user->mxcsr); + + tmp2 = (short *)&hard->st_space; + tmp = (short *)&user->_st; + + for (i = 0; i < 8; i++) + { + err |= get_user(*tmp2, tmp); tmp++; tmp2++; + err |= get_user(*tmp2, tmp); tmp++; tmp2++; + err |= get_user(*tmp2, tmp); tmp++; tmp2++; + err |= get_user(*tmp2, tmp); tmp++; tmp2++; + err |= get_user(*tmp2, tmp); tmp++; tmp2 += 3; + } + + ltmp1 = (unsigned long *)(&user->_xmm[0]); + ltmp2 = (unsigned long *)(&hard->xmm_space[0]); + for(i = 0; i < (88); i++) + { + err |= get_user(*ltmp2, ltmp1); + ltmp2++; ltmp1++; + } + + return err; +} + +#endif + /* * Save a segment. */ diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c index de965615045c..01edbc37afcf 100644 --- a/arch/i386/kernel/ptrace.c +++ b/arch/i386/kernel/ptrace.c @@ -1,5 +1,6 @@ /* ptrace.c */ /* By Ross Biro 1/23/92 */ +/* FXSAVE/FXRSTOR support by Ingo Molnar and modifications by Goutham Rao */ /* edited by Linus Torvalds */ #include /* for CONFIG_MATH_EMULATION */ @@ -398,14 +399,14 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ret = 0; if ( !child->used_math ) { /* Simulate an empty FPU. */ - child->thread.i387.hard.cwd = 0xffff037f; - child->thread.i387.hard.swd = 0xffff0000; - child->thread.i387.hard.twd = 0xffffffff; - } + i387_set_cwd(child->thread.i387.hard, 0x037f); + i387_set_swd(child->thread.i387.hard, 0x0000); + i387_set_twd(child->thread.i387.hard, 0xffff); + } #ifdef CONFIG_MATH_EMULATION if ( boot_cpu_data.hard_math ) { #endif - __copy_to_user((void *)data, &child->thread.i387.hard, sizeof(struct user_i387_struct)); + i387_hard_to_user((struct _fpstate *)data, &child->thread.i387.hard); #ifdef CONFIG_MATH_EMULATION } else { save_i387_soft(&child->thread.i387.soft, (struct _fpstate *)data); @@ -423,7 +424,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) #ifdef CONFIG_MATH_EMULATION if ( boot_cpu_data.hard_math ) { #endif - __copy_from_user(&child->thread.i387.hard, (void *)data, sizeof(struct user_i387_struct)); + i387_user_to_hard(&child->thread.i387.hard,(struct _fpstate *)data); #ifdef CONFIG_MATH_EMULATION } else { restore_i387_soft(&child->thread.i387.soft, (struct _fpstate *)data); diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 358d9f91764e..6a1e10f104d3 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -39,7 +39,8 @@ * Detection for Celeron coppermine, identify_cpu() overhauled, * and a few other clean ups. * Dave Jones , April 2000 - * + * Pentium-III code by Ingo Molnar and modifications by Goutham Rao + * */ /* @@ -800,6 +801,20 @@ void __init setup_arch(char **cmdline_p) conswitchp = &dummy_con; #endif #endif +#ifdef CONFIG_X86_FX + if (boot_cpu_data.x86_capability & X86_FEATURE_FXSR) + { + printk("Enabling extended fast FPU save and restore ... "); + set_in_cr4(X86_CR4_OSFXSR); + printk("done.\n"); + } + if (boot_cpu_data.x86_capability & X86_FEATURE_XMM) + { + printk("Enabling KNI unmasked exception support ... "); + set_in_cr4(X86_CR4_OSXMMEXCPT); + printk("done.\n"); + } +#endif } static int __init get_model_name(struct cpuinfo_x86 *c) @@ -1513,7 +1528,9 @@ int get_cpuinfo(char * buffer) case X86_VENDOR_INTEL: x86_cap_flags[16] = "pat"; + x86_cap_flags[18] = "pn"; x86_cap_flags[24] = "fxsr"; + x86_cap_flags[25] = "xmm"; break; case X86_VENDOR_CENTAUR: diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c index 4e813fac7cdf..9ae16467294c 100644 --- a/arch/i386/kernel/signal.c +++ b/arch/i386/kernel/signal.c @@ -4,6 +4,8 @@ * Copyright (C) 1991, 1992 Linus Torvalds * * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson + * Pentium III support by Ingo Molnar, modifications and OS Exception support + * by Goutham Rao */ #include @@ -155,7 +157,7 @@ static inline int restore_i387_hard(struct _fpstate *buf) { struct task_struct *tsk = current; clear_fpu(tsk); - return __copy_from_user(&tsk->thread.i387.hard, buf, sizeof(*buf)); + return i387_user_to_hard(&tsk->thread.i387.hard, buf); } static inline int restore_i387(struct _fpstate *buf) @@ -309,7 +311,7 @@ static inline int save_i387_hard(struct _fpstate * buf) unlazy_fpu(tsk); tsk->thread.i387.hard.status = tsk->thread.i387.hard.swd; - if (__copy_to_user(buf, &tsk->thread.i387.hard, sizeof(*buf))) + if (i387_hard_to_user(buf, &tsk->thread.i387.hard)) return -1; return 1; } diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 7fb5ebc61140..7e2986134fa3 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -2,6 +2,7 @@ * linux/arch/i386/traps.c * * Copyright (C) 1991, 1992 Linus Torvalds + * FXSAVE/FXRSTOR support by Ingo Molnar, OS exception support by Goutham Rao */ /* @@ -120,6 +121,7 @@ asmlinkage void coprocessor_error(void); asmlinkage void reserved(void); asmlinkage void alignment_check(void); asmlinkage void spurious_interrupt_bug(void); +asmlinkage void xmm_fault(void); int kstack_depth_to_print = 24; @@ -273,21 +275,7 @@ DO_ERROR(11, SIGBUS, "segment not present", segment_not_present, current) DO_ERROR(12, SIGBUS, "stack segment", stack_segment, current) DO_ERROR(17, SIGSEGV, "alignment check", alignment_check, current) DO_ERROR(18, SIGSEGV, "reserved", reserved, current) -/* I don't have documents for this but it does seem to cover the cache - flush from user space exception some people get. */ -DO_ERROR(19, SIGSEGV, "cache flush denied", cache_flush_denied, current) - -asmlinkage void cache_flush_denied(struct pt_regs * regs, long error_code) -{ - if (regs->eflags & VM_MASK) { - handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code); - return; - } - die_if_kernel("cache flush denied",regs,error_code); - current->thread.error_code = error_code; - current->thread.trap_no = 19; - force_sig(SIGSEGV, current); -} +DO_VM86_ERROR(19, SIGFPE, "XMM fault", xmm_fault, current) asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) { @@ -586,7 +574,7 @@ asmlinkage void math_state_restore(struct pt_regs regs) __asm__ __volatile__("clts"); /* Allow maths ops (or we recurse) */ if(current->used_math) - __asm__("frstor %0": :"m" (current->thread.i387)); + i387_restore_hard(current->thread.i387); else { /* @@ -829,6 +817,8 @@ void __init trap_init(void) set_trap_gate(15,&spurious_interrupt_bug); set_trap_gate(16,&coprocessor_error); set_trap_gate(17,&alignment_check); + set_trap_gate(19,&xmm_fault); + set_system_gate(SYSCALL_VECTOR,&system_call); /* diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index f63f542bad55..e8524e430e0c 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.54 2000/05/12 23:51:24 davem Exp $ +# $Id: Makefile,v 1.55 2000/05/23 23:09:08 davem Exp $ # Makefile for the linux kernel. # # Note! Dependencies are done automagically by 'make dep', which also diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index 135ee279eea3..2800d1bd5710 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig @@ -201,6 +201,13 @@ CONFIG_BLK_DEV_IDE=y # CONFIG_BLK_DEV_HD is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set +# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set +# CONFIG_BLK_DEV_IDEDISK_IBM is not set +# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set +# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set +# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set +# CONFIG_BLK_DEV_IDEDISK_WD is not set # CONFIG_BLK_DEV_IDECS is not set CONFIG_BLK_DEV_IDECD=y CONFIG_BLK_DEV_IDETAPE=m diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index edb6b05718aa..df823619ca9a 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile @@ -81,13 +81,11 @@ check_asm: dummy @echo -e "# error Please issue 'make check_asm' in linux top-level directory first\n# endif\n#endif\n" >> asm_offsets.h @echo -e "#ifndef CONFIG_SMP\n" >> asm_offsets.h @echo "#include " > tmp.c - @echo "#undef __SMP__" >> tmp.c @echo "#undef CONFIG_SMP" >> tmp.c @echo "#include " >> tmp.c $(CPP) $(CPPFLAGS) tmp.c -o tmp.i @echo "/* Automatically generated. Do not edit. */" > check_asm.c @echo "#include " >> check_asm.c - @echo "#undef __SMP__" >> check_asm.c @echo "#undef CONFIG_SMP" >> check_asm.c @echo "#include " >> check_asm.c @echo 'struct task_struct _task;' >> check_asm.c @@ -128,7 +126,7 @@ check_asm: dummy $(SH) ./check_asm.sh thread tmp.i check_asm.c @echo 'return 0; }' >> check_asm.c @rm -f tmp.[ci] - #$(CC) -D__SMP__ -o check_asm check_asm.c + #$(CC) -o check_asm check_asm.c # Until we can do this natively, a hack has to take place $(CC) $(CPPFLAGS) $(CMODEL_CFLAG) -ffixed-g4 -S -o check_asm.s check_asm.c $(HOSTCC) -Wa,-Av9a -o check_asm check_asm.s @@ -153,7 +151,7 @@ check_asm: dummy $(SH) ./check_asm.sh thread tmp.i check_asm.c @echo 'return 0; }' >> check_asm.c @rm -f tmp.[ci] - #$(CC) -D__SMP__ -DSPIN_LOCK_DEBUG -o check_asm check_asm.c + #$(CC) -DSPIN_LOCK_DEBUG -o check_asm check_asm.c # Until we can do this natively, a hack has to take place $(CC) $(CPPFLAGS) -DSPIN_LOCK_DEBUG $(CMODEL_CFLAG) -ffixed-g4 -S -o check_asm.s check_asm.c $(HOSTCC) -Wa,-Av9a -o check_asm check_asm.s diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index 6c00ba2f69c0..9f5626b5bc3e 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -1,4 +1,4 @@ -/* $Id: ioctl32.c,v 1.90 2000/05/22 07:29:39 davem Exp $ +/* $Id: ioctl32.c,v 1.91 2000/05/23 05:25:44 davem Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) @@ -2353,6 +2353,542 @@ static int do_lvm_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) } #endif +#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) +/* This really belongs in include/linux/drm.h -DaveM */ +#include "../../../drivers/char/drm/drm.h" + +typedef struct drm32_version { + int version_major; /* Major version */ + int version_minor; /* Minor version */ + int version_patchlevel;/* Patch level */ + int name_len; /* Length of name buffer */ + u32 name; /* Name of driver */ + int date_len; /* Length of date buffer */ + u32 date; /* User-space buffer to hold date */ + int desc_len; /* Length of desc buffer */ + u32 desc; /* User-space buffer to hold desc */ +} drm32_version_t; +#define DRM32_IOCTL_VERSION DRM_IOWR(0x00, drm32_version_t) + +static int drm32_version(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + drm32_version_t *uversion = (drm32_version_t *)arg; + char *name_ptr, *date_ptr, *desc_ptr; + u32 tmp1, tmp2, tmp3; + drm_version_t kversion; + mm_segment_t old_fs; + int ret; + + memset(&kversion, 0, sizeof(kversion)); + if (get_user(kversion.name_len, &uversion->name_len) || + get_user(kversion.date_len, &uversion->date_len) || + get_user(kversion.desc_len, &uversion->desc_len) || + get_user(tmp1, &uversion->name) || + get_user(tmp2, &uversion->date) || + get_user(tmp3, &uversion->desc)) + return -EFAULT; + + name_ptr = (char *) A(tmp1); + date_ptr = (char *) A(tmp2); + desc_ptr = (char *) A(tmp3); + + ret = -ENOMEM; + if (kversion.name_len && name_ptr) { + kversion.name = kmalloc(kversion.name_len, GFP_KERNEL); + if (!kversion.name) + goto out; + } + if (kversion.date_len && date_ptr) { + kversion.date = kmalloc(kversion.date_len, GFP_KERNEL); + if (!kversion.date) + goto out; + } + if (kversion.desc_len && desc_ptr) { + kversion.desc = kmalloc(kversion.desc_len, GFP_KERNEL); + if (!kversion.desc) + goto out; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_ioctl (fd, DRM_IOCTL_VERSION, (unsigned long)&kversion); + set_fs(old_fs); + + if (!ret) { + if ((kversion.name && + copy_to_user(name_ptr, kversion.name, kversion.name_len)) || + (kversion.date && + copy_to_user(date_ptr, kversion.date, kversion.date_len)) || + (kversion.desc && + copy_to_user(desc_ptr, kversion.desc, kversion.desc_len))) + ret = -EFAULT; + if (put_user(kversion.version_major, &uversion->version_major) || + put_user(kversion.version_minor, &uversion->version_minor) || + put_user(kversion.version_patchlevel, &uversion->version_patchlevel) || + put_user(kversion.name_len, &uversion->name_len) || + put_user(kversion.date_len, &uversion->date_len) || + put_user(kversion.desc_len, &uversion->desc_len)) + ret = -EFAULT; + } + +out: + if (kversion.name) + kfree(kversion.name); + if (kversion.date) + kfree(kversion.date); + if (kversion.desc) + kfree(kversion.desc); + return ret; +} + +typedef struct drm32_unique { + size_t unique_len; /* Length of unique */ + u32 unique; /* Unique name for driver instantiation */ +} drm32_unique_t; +#define DRM32_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm32_unique_t) +#define DRM32_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm32_unique_t) + +static int drm32_getsetunique(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + drm32_unique_t *uarg = (drm32_unique_t *)arg; + drm_unique_t karg; + mm_segment_t old_fs; + char *uptr; + u32 tmp; + int ret; + + if (get_user(karg.unique_len, &uarg->unique_len)) + return -EFAULT; + karg.unique = NULL; + + if (get_user(tmp, &uarg->unique)) + return -EFAULT; + + uptr = (char *) A(tmp); + + if (uptr) { + karg.unique = kmalloc(karg.unique_len, GFP_KERNEL); + if (!karg.unique) + return -ENOMEM; + if (cmd == DRM32_IOCTL_SET_UNIQUE && + copy_from_user(karg.unique, uptr, karg.unique_len)) { + kfree(karg.unique); + return -EFAULT; + } + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + if (cmd == DRM32_IOCTL_GET_UNIQUE) + ret = sys_ioctl (fd, DRM_IOCTL_GET_UNIQUE, (unsigned long)&karg); + else + ret = sys_ioctl (fd, DRM_IOCTL_SET_UNIQUE, (unsigned long)&karg); + set_fs(old_fs); + + if (!ret) { + if (cmd == DRM32_IOCTL_GET_UNIQUE && + copy_to_user(uptr, karg.unique, karg.unique_len)) + ret = -EFAULT; + if (put_user(karg.unique_len, &uarg->unique_len)) + ret = -EFAULT; + } + + kfree(karg.unique); + + return ret; +} + +typedef struct drm32_map { + u32 offset; /* Requested physical address (0 for SAREA)*/ + u32 size; /* Requested physical size (bytes) */ + drm_map_type_t type; /* Type of memory to map */ + drm_map_flags_t flags; /* Flags */ + u32 handle; /* User-space: "Handle" to pass to mmap */ + /* Kernel-space: kernel-virtual address */ + int mtrr; /* MTRR slot used */ + /* Private data */ +} drm32_map_t; +#define DRM32_IOCTL_ADD_MAP DRM_IOWR(0x15, drm32_map_t) + +static int drm32_addmap(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + drm32_map_t *uarg = (drm32_map_t *) arg; + drm_map_t karg; + mm_segment_t old_fs; + u32 tmp; + int ret; + + ret = get_user(karg.offset, &uarg->offset); + ret |= get_user(karg.size, &uarg->size); + ret |= get_user(karg.type, &uarg->type); + ret |= get_user(karg.flags, &uarg->flags); + ret |= get_user(tmp, &uarg->handle); + ret |= get_user(karg.mtrr, &uarg->mtrr); + if (ret) + return -EFAULT; + + karg.handle = (void *) A(tmp); + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_ioctl(fd, DRM_IOCTL_ADD_MAP, (unsigned long) &karg); + set_fs(old_fs); + + if (!ret) { + ret = put_user(karg.offset, &uarg->offset); + ret |= put_user(karg.size, &uarg->size); + ret |= put_user(karg.type, &uarg->type); + ret |= put_user(karg.flags, &uarg->flags); + tmp = (u32) (long)karg.handle; + ret |= put_user(tmp, &uarg->handle); + ret |= put_user(karg.mtrr, &uarg->mtrr); + if (ret) + ret = -EFAULT; + } + + return ret; +} + +typedef struct drm32_buf_info { + int count; /* Entries in list */ + u32 list; /* (drm_buf_desc_t *) */ +} drm32_buf_info_t; +#define DRM32_IOCTL_INFO_BUFS DRM_IOWR(0x18, drm32_buf_info_t) + +static int drm32_info_bufs(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + drm32_buf_info_t *uarg = (drm32_buf_info_t *)arg; + drm_buf_desc_t *ulist; + drm_buf_info_t karg; + mm_segment_t old_fs; + int orig_count, ret; + u32 tmp; + + if (get_user(karg.count, &uarg->count) || + get_user(tmp, &uarg->list)) + return -EFAULT; + + ulist = (drm_buf_desc_t *) A(tmp); + + orig_count = karg.count; + + karg.list = kmalloc(karg.count * sizeof(drm_buf_desc_t), GFP_KERNEL); + if (!karg.list) + return -EFAULT; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_ioctl(fd, DRM_IOCTL_INFO_BUFS, (unsigned long) &karg); + set_fs(old_fs); + + if (!ret) { + if (karg.count <= orig_count && + (copy_to_user(ulist, karg.list, + karg.count * sizeof(drm_buf_desc_t)))) + ret = -EFAULT; + if (put_user(karg.count, &uarg->count)) + ret = -EFAULT; + } + + kfree(karg.list); + + return ret; +} + +typedef struct drm32_buf_free { + int count; + u32 list; /* (int *) */ +} drm32_buf_free_t; +#define DRM32_IOCTL_FREE_BUFS DRM_IOW( 0x1a, drm32_buf_free_t) + +static int drm32_free_bufs(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + drm32_buf_free_t *uarg = (drm32_buf_free_t *)arg; + drm_buf_free_t karg; + mm_segment_t old_fs; + int *ulist; + int ret; + u32 tmp; + + if (get_user(karg.count, &uarg->count) || + get_user(tmp, &uarg->list)) + return -EFAULT; + + ulist = (int *) A(tmp); + + karg.list = kmalloc(karg.count * sizeof(int), GFP_KERNEL); + if (!karg.list) + return -ENOMEM; + + ret = -EFAULT; + if (copy_from_user(karg.list, ulist, (karg.count * sizeof(int)))) + goto out; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_ioctl(fd, DRM_IOCTL_FREE_BUFS, (unsigned long) &karg); + set_fs(old_fs); + +out: + kfree(karg.list); + + return ret; +} + +typedef struct drm32_buf_pub { + int idx; /* Index into master buflist */ + int total; /* Buffer size */ + int used; /* Amount of buffer in use (for DMA) */ + u32 address; /* Address of buffer (void *) */ +} drm32_buf_pub_t; + +typedef struct drm32_buf_map { + int count; /* Length of buflist */ + u32 virtual; /* Mmaped area in user-virtual (void *) */ + u32 list; /* Buffer information (drm_buf_pub_t *) */ +} drm32_buf_map_t; +#define DRM32_IOCTL_MAP_BUFS DRM_IOWR(0x19, drm32_buf_map_t) + +static int drm32_map_bufs(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + drm32_buf_map_t *uarg = (drm32_buf_map_t *)arg; + drm32_buf_pub_t *ulist; + drm_buf_map_t karg; + mm_segment_t old_fs; + int orig_count, ret, i; + u32 tmp1, tmp2; + + if (get_user(karg.count, &uarg->count) || + get_user(tmp1, &uarg->virtual) || + get_user(tmp2, &uarg->list)) + return -EFAULT; + + karg.virtual = (void *) A(tmp1); + ulist = (drm32_buf_pub_t *) A(tmp2); + + orig_count = karg.count; + + karg.list = kmalloc(karg.count * sizeof(drm_buf_pub_t), GFP_KERNEL); + if (!karg.list) + return -ENOMEM; + + ret = -EFAULT; + for (i = 0; i < karg.count; i++) { + if (get_user(karg.list[i].idx, &ulist[i].idx) || + get_user(karg.list[i].total, &ulist[i].total) || + get_user(karg.list[i].used, &ulist[i].used) || + get_user(tmp1, &ulist[i].address)) + goto out; + + karg.list[i].address = (void *) A(tmp1); + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_ioctl(fd, DRM_IOCTL_MAP_BUFS, (unsigned long) &karg); + set_fs(old_fs); + + if (!ret) { + for (i = 0; i < orig_count; i++) { + tmp1 = (u32) (long) karg.list[i].address; + if (put_user(karg.list[i].idx, &ulist[i].idx) || + put_user(karg.list[i].total, &ulist[i].total) || + put_user(karg.list[i].used, &ulist[i].used) || + put_user(tmp1, &ulist[i].address)) { + ret = -EFAULT; + goto out; + } + } + if (put_user(karg.count, &uarg->count)) + ret = -EFAULT; + } + +out: + kfree(karg.list); + return ret; +} + +typedef struct drm32_dma { + /* Indices here refer to the offset into + buflist in drm_buf_get_t. */ + int context; /* Context handle */ + int send_count; /* Number of buffers to send */ + u32 send_indices; /* List of handles to buffers (int *) */ + u32 send_sizes; /* Lengths of data to send (int *) */ + drm_dma_flags_t flags; /* Flags */ + int request_count; /* Number of buffers requested */ + int request_size; /* Desired size for buffers */ + u32 request_indices; /* Buffer information (int *) */ + u32 request_sizes; /* (int *) */ + int granted_count; /* Number of buffers granted */ +} drm32_dma_t; +#define DRM32_IOCTL_DMA DRM_IOWR(0x29, drm32_dma_t) + +/* RED PEN The DRM layer blindly dereferences the send/request + * indice/size arrays even though they are userland + * pointers. -DaveM + */ +static int drm32_dma(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + drm32_dma_t *uarg = (drm32_dma_t *) arg; + int *u_si, *u_ss, *u_ri, *u_rs; + drm_dma_t karg; + mm_segment_t old_fs; + int ret; + u32 tmp1, tmp2, tmp3, tmp4; + + karg.send_indices = karg.send_sizes = NULL; + karg.request_indices = karg.request_sizes = NULL; + + if (get_user(karg.context, &uarg->context) || + get_user(karg.send_count, &uarg->send_count) || + get_user(tmp1, &uarg->send_indices) || + get_user(tmp2, &uarg->send_sizes) || + get_user(karg.flags, &uarg->flags) || + get_user(karg.request_count, &uarg->request_count) || + get_user(karg.request_size, &uarg->request_size) || + get_user(tmp3, &uarg->request_indices) || + get_user(tmp4, &uarg->request_sizes) || + get_user(karg.granted_count, &uarg->granted_count)) + return -EFAULT; + + u_si = (int *) A(tmp1); + u_ss = (int *) A(tmp2); + u_ri = (int *) A(tmp3); + u_rs = (int *) A(tmp4); + + if (karg.send_count) { + karg.send_indices = kmalloc(karg.send_count * sizeof(int), GFP_KERNEL); + karg.send_sizes = kmalloc(karg.send_count * sizeof(int), GFP_KERNEL); + + ret = -ENOMEM; + if (!karg.send_indices || !karg.send_sizes) + goto out; + + ret = -EFAULT; + if (copy_from_user(karg.send_indices, u_si, + (karg.send_count * sizeof(int))) || + copy_from_user(karg.send_sizes, u_ss, + (karg.send_count * sizeof(int)))) + goto out; + } + + if (karg.request_count) { + karg.request_indices = kmalloc(karg.request_count * sizeof(int), GFP_KERNEL); + karg.request_sizes = kmalloc(karg.request_count * sizeof(int), GFP_KERNEL); + + ret = -ENOMEM; + if (!karg.request_indices || !karg.request_sizes) + goto out; + + ret = -EFAULT; + if (copy_from_user(karg.request_indices, u_ri, + (karg.request_count * sizeof(int))) || + copy_from_user(karg.request_sizes, u_rs, + (karg.request_count * sizeof(int)))) + goto out; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_ioctl(fd, DRM_IOCTL_DMA, (unsigned long) &karg); + set_fs(old_fs); + + if (!ret) { + if (put_user(karg.context, &uarg->context) || + put_user(karg.send_count, &uarg->send_count) || + put_user(karg.flags, &uarg->flags) || + put_user(karg.request_count, &uarg->request_count) || + put_user(karg.request_size, &uarg->request_size) || + put_user(karg.granted_count, &uarg->granted_count)) + ret = -EFAULT; + + if (karg.send_count) { + if (copy_to_user(u_si, karg.send_indices, + (karg.send_count * sizeof(int))) || + copy_to_user(u_ss, karg.send_sizes, + (karg.send_count * sizeof(int)))) + ret = -EFAULT; + } + if (karg.request_count) { + if (copy_to_user(u_ri, karg.request_indices, + (karg.request_count * sizeof(int))) || + copy_to_user(u_rs, karg.request_sizes, + (karg.request_count * sizeof(int)))) + ret = -EFAULT; + } + } + +out: + if (karg.send_indices) + kfree(karg.send_indices); + if (karg.send_sizes) + kfree(karg.send_sizes); + if (karg.request_indices) + kfree(karg.request_indices); + if (karg.request_sizes) + kfree(karg.request_sizes); + + return ret; +} + +typedef struct drm32_ctx_res { + int count; + u32 contexts; /* (drm_ctx_t *) */ +} drm32_ctx_res_t; +#define DRM32_IOCTL_RES_CTX DRM_IOWR(0x26, drm_ctx_res_t) + +static int drm32_res_ctx(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + drm32_ctx_res_t *uarg = (drm32_ctx_res_t *) arg; + drm_ctx_t *ulist; + drm_ctx_res_t karg; + mm_segment_t old_fs; + int orig_count, ret; + u32 tmp; + + karg.contexts = NULL; + if (get_user(karg.count, &uarg->count) || + get_user(tmp, &uarg->contexts)) + return -EFAULT; + + ulist = (drm_ctx_t *) A(tmp); + + orig_count = karg.count; + if (karg.count && ulist) { + karg.contexts = kmalloc((karg.count * sizeof(drm_ctx_t)), GFP_KERNEL); + if (!karg.contexts) + return -ENOMEM; + if (copy_from_user(karg.contexts, ulist, + (karg.count * sizeof(drm_ctx_t)))) { + kfree(karg.contexts); + return -EFAULT; + } + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_ioctl(fd, DRM_IOCTL_RES_CTX, (unsigned long) &karg); + set_fs(old_fs); + + if (!ret) { + if (orig_count) { + if (copy_to_user(ulist, karg.contexts, + (orig_count * sizeof(drm_ctx_t)))) + ret = -EFAULT; + } + if (put_user(karg.count, &uarg->count)) + ret = -EFAULT; + } + + if (karg.contexts) + kfree(karg.contexts); + + return ret; +} + +#endif + static int ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg) { return -EINVAL; @@ -2961,6 +3497,27 @@ COMPATIBLE_IOCTL(LV_SET_ACCESS) COMPATIBLE_IOCTL(LV_SET_STATUS) COMPATIBLE_IOCTL(LV_SET_ALLOCATION) #endif /* LVM */ +#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) +COMPATIBLE_IOCTL(DRM_IOCTL_GET_MAGIC) +COMPATIBLE_IOCTL(DRM_IOCTL_IRQ_BUSID) +COMPATIBLE_IOCTL(DRM_IOCTL_AUTH_MAGIC) +COMPATIBLE_IOCTL(DRM_IOCTL_BLOCK) +COMPATIBLE_IOCTL(DRM_IOCTL_UNBLOCK) +COMPATIBLE_IOCTL(DRM_IOCTL_CONTROL) +COMPATIBLE_IOCTL(DRM_IOCTL_ADD_BUFS) +COMPATIBLE_IOCTL(DRM_IOCTL_MARK_BUFS) +COMPATIBLE_IOCTL(DRM_IOCTL_ADD_CTX) +COMPATIBLE_IOCTL(DRM_IOCTL_RM_CTX) +COMPATIBLE_IOCTL(DRM_IOCTL_MOD_CTX) +COMPATIBLE_IOCTL(DRM_IOCTL_GET_CTX) +COMPATIBLE_IOCTL(DRM_IOCTL_SWITCH_CTX) +COMPATIBLE_IOCTL(DRM_IOCTL_NEW_CTX) +COMPATIBLE_IOCTL(DRM_IOCTL_ADD_DRAW) +COMPATIBLE_IOCTL(DRM_IOCTL_RM_DRAW) +COMPATIBLE_IOCTL(DRM_IOCTL_LOCK) +COMPATIBLE_IOCTL(DRM_IOCTL_UNLOCK) +COMPATIBLE_IOCTL(DRM_IOCTL_FINISH) +#endif /* DRM */ /* elevator */ COMPATIBLE_IOCTL(BLKELVGET) COMPATIBLE_IOCTL(BLKELVSET) @@ -3108,6 +3665,17 @@ HANDLE_IOCTL(LE_REMAP, do_lvm_ioctl) HANDLE_IOCTL(PV_CHANGE, do_lvm_ioctl) HANDLE_IOCTL(PV_STATUS, do_lvm_ioctl) #endif /* LVM */ +#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) +HANDLE_IOCTL(DRM32_IOCTL_VERSION, drm32_version); +HANDLE_IOCTL(DRM32_IOCTL_GET_UNIQUE, drm32_getsetunique); +HANDLE_IOCTL(DRM32_IOCTL_SET_UNIQUE, drm32_getsetunique); +HANDLE_IOCTL(DRM32_IOCTL_ADD_MAP, drm32_addmap); +HANDLE_IOCTL(DRM32_IOCTL_INFO_BUFS, drm32_info_bufs); +HANDLE_IOCTL(DRM32_IOCTL_FREE_BUFS, drm32_free_bufs); +HANDLE_IOCTL(DRM32_IOCTL_MAP_BUFS, drm32_map_bufs); +HANDLE_IOCTL(DRM32_IOCTL_DMA, drm32_dma); +HANDLE_IOCTL(DRM32_IOCTL_RES_CTX, drm32_res_ctx); +#endif /* DRM */ IOCTL_TABLE_END unsigned int ioctl32_hash_table[1024]; diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 12a872447040..942f3764010a 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -1,4 +1,4 @@ -/* $Id: sparc64_ksyms.c,v 1.84 2000/05/09 17:40:14 davem Exp $ +/* $Id: sparc64_ksyms.c,v 1.85 2000/05/23 02:14:25 davem Exp $ * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -83,6 +83,7 @@ extern int (*handle_mathemu)(struct pt_regs *, struct fpustate *); extern long sparc32_open(const char * filename, int flags, int mode); extern int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *)); extern int unregister_ioctl32_conversion(unsigned int cmd); +extern int io_remap_page_range(unsigned long from, unsigned long offset, unsigned long size, pgprot_t prot, int space); extern void bcopy (const char *, char *, int); extern int __ashrdi3(int, int); @@ -223,6 +224,9 @@ EXPORT_SYMBOL(pci_dma_supported); EXPORT_SYMBOL(register_ioctl32_conversion); EXPORT_SYMBOL(unregister_ioctl32_conversion); +/* I/O device mmaping on Sparc64. */ +EXPORT_SYMBOL(io_remap_page_range); + /* Solaris/SunOS binary compatibility */ EXPORT_SYMBOL(_sigpause_common); diff --git a/arch/sparc64/mm/modutil.c b/arch/sparc64/mm/modutil.c index 6d68d7468761..8ae715c3828a 100644 --- a/arch/sparc64/mm/modutil.c +++ b/arch/sparc64/mm/modutil.c @@ -1,4 +1,4 @@ -/* $Id: modutil.c,v 1.4 1998/07/26 06:29:08 davem Exp $ +/* $Id: modutil.c,v 1.5 2000/05/23 23:09:08 davem Exp $ * arch/sparc64/mm/modutil.c * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -58,7 +58,7 @@ void * module_map (unsigned long size) area->next = *p; *p = area; - if (vmalloc_area_pages(VMALLOC_VMADDR(addr), size)) { + if (vmalloc_area_pages(VMALLOC_VMADDR(addr), size, GFP_KERNEL)) { vfree(addr); return NULL; } diff --git a/drivers/char/Config.in b/drivers/char/Config.in index 792832a306e4..5fed698d65f2 100644 --- a/drivers/char/Config.in +++ b/drivers/char/Config.in @@ -157,6 +157,7 @@ comment 'Video For Linux' tristate 'Video For Linux' CONFIG_VIDEO_DEV if [ "$CONFIG_VIDEO_DEV" != "n" ]; then + bool ' V4L information in proc filesystem' CONFIG_VIDEO_PROC_FS Y dep_tristate ' I2C on parallel port' CONFIG_I2C_PARPORT $CONFIG_PARPORT $CONFIG_I2C comment 'Radio Adapters' dep_tristate ' ADS Cadet AM/FM Tuner' CONFIG_RADIO_CADET $CONFIG_VIDEO_DEV diff --git a/drivers/char/videodev.c b/drivers/char/videodev.c index 618f02f85d22..98c9e97315e4 100644 --- a/drivers/char/videodev.c +++ b/drivers/char/videodev.c @@ -11,7 +11,8 @@ * * Author: Alan Cox, * - * Fixes: + * Fixes: 20000516 Claudio Matsuoka + * - Added procfs support */ #include @@ -40,6 +41,27 @@ static struct video_device *video_device[VIDEO_NUM_DEVICES]; + +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) + +#include + +struct videodev_proc_data { + struct list_head proc_list; + char name[16]; + struct video_device *vdev; + struct proc_dir_entry *proc_entry; + struct video_capability vcap; +}; + +static struct proc_dir_entry *video_dev_proc_entry = NULL; +struct proc_dir_entry *video_proc_entry = NULL; +EXPORT_SYMBOL(video_proc_entry); +LIST_HEAD(videodev_proc_list); + +#endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */ + + #ifdef CONFIG_VIDEO_BT848 extern int i2c_tuner_init(struct video_init *); #endif @@ -215,6 +237,152 @@ int video_mmap(struct file *file, struct vm_area_struct *vma) return -EINVAL; } +/* + * /proc support + */ + +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) + +/* Hmm... i'd like to see video_capability information here, but + * how can I access it (without changing the other drivers? -claudio + */ +static int videodev_proc_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + char *out = page; + struct video_device *vfd = data; + struct videodev_proc_data *d; + struct list_head *tmp; + int len; + char c = ' '; + + list_for_each (tmp, &videodev_proc_list) { + d = list_entry(tmp, struct videodev_proc_data, proc_list); + if (vfd == d->vdev) + break; + } + + /* Sanity check */ + if (tmp == &videodev_proc_list) + goto skip; + +#define PRINT_VID_TYPE(x) do { if (vfd->type & x) \ + out += sprintf (out, "%c%s", c, #x); c='|';} while (0) + + out += sprintf (out, "name : %s\n", vfd->name); + out += sprintf (out, "type :"); + PRINT_VID_TYPE(VID_TYPE_CAPTURE); + PRINT_VID_TYPE(VID_TYPE_TUNER); + PRINT_VID_TYPE(VID_TYPE_TELETEXT); + PRINT_VID_TYPE(VID_TYPE_OVERLAY); + PRINT_VID_TYPE(VID_TYPE_CHROMAKEY); + PRINT_VID_TYPE(VID_TYPE_CLIPPING); + PRINT_VID_TYPE(VID_TYPE_FRAMERAM); + PRINT_VID_TYPE(VID_TYPE_SCALES); + PRINT_VID_TYPE(VID_TYPE_MONOCHROME); + PRINT_VID_TYPE(VID_TYPE_SUBCAPTURE); + PRINT_VID_TYPE(VID_TYPE_MPEG_DECODER); + PRINT_VID_TYPE(VID_TYPE_MPEG_ENCODER); + PRINT_VID_TYPE(VID_TYPE_MJPEG_DECODER); + PRINT_VID_TYPE(VID_TYPE_MJPEG_ENCODER); + out += sprintf (out, "\n"); + out += sprintf (out, "hardware : 0x%x\n", vfd->hardware); +#if 0 + out += sprintf (out, "channels : %d\n", d->vcap.channels); + out += sprintf (out, "audios : %d\n", d->vcap.audios); + out += sprintf (out, "maxwidth : %d\n", d->vcap.maxwidth); + out += sprintf (out, "maxheight : %d\n", d->vcap.maxheight); + out += sprintf (out, "minwidth : %d\n", d->vcap.minwidth); + out += sprintf (out, "minheight : %d\n", d->vcap.minheight); +#endif + +skip: + len = out - page; + len -= off; + if (len < count) { + *eof = 1; + if (len <= 0) + return 0; + } else + len = count; + + *start = page + off; + + return len; +} + +static void videodev_proc_create(void) +{ + video_proc_entry = create_proc_entry("video", S_IFDIR, &proc_root); + + if (video_proc_entry == NULL) { + printk("video_dev: unable to initialise /proc/video\n"); + return; + } + + video_proc_entry->owner = THIS_MODULE; + video_dev_proc_entry = create_proc_entry("dev", S_IFDIR, video_proc_entry); + + if (video_dev_proc_entry == NULL) { + printk("video_dev: unable to initialise /proc/video/dev\n"); + return; + } + + video_dev_proc_entry->owner = THIS_MODULE; +} + +static void videodev_proc_destroy(void) +{ + if (video_dev_proc_entry != NULL) + remove_proc_entry("dev", video_proc_entry); + + if (video_proc_entry != NULL) + remove_proc_entry("video", &proc_root); +} + +static void videodev_proc_create_dev (struct video_device *vfd, char *name) +{ + struct videodev_proc_data *d; + struct proc_dir_entry *p; + + if (video_dev_proc_entry == NULL) + return; + + d = kmalloc (sizeof (struct videodev_proc_data), GFP_KERNEL); + if (!d) + return; + + p = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, video_dev_proc_entry); + p->data = vfd; + p->read_proc = videodev_proc_read; + + d->proc_entry = p; + d->vdev = vfd; + strcpy (d->name, name); + + /* How can I get capability information ? */ + + list_add (&d->proc_list, &videodev_proc_list); +} + +static void videodev_proc_destroy_dev (struct video_device *vfd) +{ + struct list_head *tmp; + struct videodev_proc_data *d; + + list_for_each (tmp, &videodev_proc_list) { + d = list_entry(tmp, struct videodev_proc_data, proc_list); + if (vfd == d->vdev) { + remove_proc_entry(d->name, video_dev_proc_entry); + list_del (&d->proc_list); + kfree (d); + break; + } + } +} + +#endif /* CONFIG_VIDEO_PROC_FS */ + extern struct file_operations video_fops; /** @@ -306,6 +474,13 @@ int video_register_device(struct video_device *vfd, int type) VIDEO_MAJOR, vfd->minor, S_IFCHR | S_IRUSR | S_IWUSR, 0, 0, &video_fops, NULL); + +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) + sprintf (name, "%s%d", name_base, i - base); + videodev_proc_create_dev (vfd, name); +#endif + + return 0; } } @@ -324,6 +499,11 @@ void video_unregister_device(struct video_device *vfd) { if(video_device[vfd->minor]!=vfd) panic("vfd: bad unregister"); + +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) + videodev_proc_destroy_dev (vfd); +#endif + devfs_unregister (vfd->devfs_handle); video_device[vfd->minor]=NULL; MOD_DEC_USE_COUNT; @@ -361,6 +541,10 @@ int __init videodev_init(void) * Init kernel installed video drivers */ +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) + videodev_proc_create (); +#endif + while(vfli->init!=NULL) { vfli->init(vfli); @@ -377,6 +561,10 @@ int init_module(void) void cleanup_module(void) { +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) + videodev_proc_destroy (); +#endif + devfs_unregister_chrdev(VIDEO_MAJOR, "video_capture"); } diff --git a/drivers/ide/Config.in b/drivers/ide/Config.in index 09c6451cfd13..b591b3563c52 100644 --- a/drivers/ide/Config.in +++ b/drivers/ide/Config.in @@ -41,7 +41,6 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then bool ' Boot off-board chipsets first support' CONFIG_BLK_DEV_OFFBOARD dep_bool ' Use PCI DMA by default when available' CONFIG_IDEDMA_PCI_AUTO $CONFIG_BLK_DEV_IDEDMA_PCI define_bool CONFIG_BLK_DEV_IDEDMA $CONFIG_BLK_DEV_IDEDMA_PCI - define_bool CONFIG_IDEDMA_PCI_EXPERIMENTAL $CONFIG_EXPERIMENTAL dep_bool ' ATA Work(s) In Progress (EXPERIMENTAL)' CONFIG_IDEDMA_PCI_WIP $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_EXPERIMENTAL dep_bool ' Good-Bad DMA Model-Firmware (WIP)' CONFIG_IDEDMA_NEW_DRIVE_LISTINGS $CONFIG_IDEDMA_PCI_WIP dep_bool ' AEC62XX chipset support' CONFIG_BLK_DEV_AEC62XX $CONFIG_BLK_DEV_IDEDMA_PCI @@ -82,12 +81,14 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then dep_bool ' PowerMac IDE DMA support' CONFIG_BLK_DEV_IDEDMA_PMAC $CONFIG_BLK_DEV_IDE_PMAC dep_bool ' Use DMA by default' CONFIG_IDEDMA_PMAC_AUTO $CONFIG_BLK_DEV_IDEDMA_PMAC define_bool CONFIG_BLK_DEV_IDEDMA $CONFIG_BLK_DEV_IDEDMA_PMAC + define_bool CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_BLK_DEV_IDEDMA_PMAC fi if [ "$CONFIG_ARCH_ACORN" = "y" ]; then dep_bool ' ICS IDE interface support' CONFIG_BLK_DEV_IDE_ICSIDE $CONFIG_ARCH_ACORN dep_bool ' ICS DMA support' CONFIG_BLK_DEV_IDEDMA_ICS $CONFIG_BLK_DEV_IDE_ICSIDE dep_bool ' Use ICS DMA by default' CONFIG_IDEDMA_ICS_AUTO $CONFIG_BLK_DEV_IDEDMA_ICS define_bool CONFIG_BLK_DEV_IDEDMA $CONFIG_BLK_DEV_IDEDMA_ICS + define_bool CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_BLK_DEV_IDEDMA_ICS dep_bool ' RapIDE interface support' CONFIG_BLK_DEV_IDE_RAPIDE $CONFIG_ARCH_ACORN fi if [ "$CONFIG_AMIGA" = "y" ]; then diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index 278ad7ab7038..028dbcffeff3 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -97,7 +97,7 @@ ifeq ($(CONFIG_BLK_DEV_IDE_ICSIDE),y) IDE_OBJS += icside.o endif -ifeq ($(CONFIG_BLK_DEV_IDEDMA),y) +ifeq ($(CONFIG_BLK_DEV_IDEDMA_PCI),y) IDE_OBJS += ide-dma.o endif diff --git a/drivers/ide/hd.c b/drivers/ide/hd.c index 1c6a0b286d6e..eb73c24456c8 100644 --- a/drivers/ide/hd.c +++ b/drivers/ide/hd.c @@ -778,6 +778,8 @@ static void hd_geninit(void) #endif for (drive=0 ; drive < NR_HD ; drive++) { + hd[drive<<6].nr_sects = hd_info[drive].head * + hd_info[drive].sect * hd_info[drive].cyl; printk ("hd%c: %ldMB, CHS=%d/%d/%d\n", drive+'a', hd[drive<<6].nr_sects / 2048, hd_info[drive].cyl, hd_info[drive].head, hd_info[drive].sect); @@ -890,3 +892,4 @@ static int parse_hd_setup (char *line) { return 0; } __setup("hd=", parse_hd_setup); + diff --git a/drivers/ide/ide-features.c b/drivers/ide/ide-features.c index fcf0aab63377..cb3790fa62f4 100644 --- a/drivers/ide/ide-features.c +++ b/drivers/ide/ide-features.c @@ -12,6 +12,7 @@ * May be copied or modified under the terms of the GNU General Public License */ +#include #define __NO_VERSION__ #include #include @@ -257,11 +258,12 @@ int ide_config_drive_speed (ide_drive_t *drive, byte speed) { ide_hwif_t *hwif = HWIF(drive); int i, error = 1; - byte unit = (drive->select.b.unit & 0x01); byte stat; +#ifdef CONFIG_BLK_DEV_IDEDMA_PCI + byte unit = (drive->select.b.unit & 0x01); outb(inb(hwif->dma_base+2) & ~(1<<(5+unit)), hwif->dma_base+2); - +#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ /* * Don't use ide_wait_cmd here - it will * attempt to set_geometry and recalibrate, @@ -324,11 +326,13 @@ int ide_config_drive_speed (ide_drive_t *drive, byte speed) drive->id->dma_mword &= ~0x0F00; drive->id->dma_1word &= ~0x0F00; +#ifdef CONFIG_BLK_DEV_IDEDMA_PCI if (speed > XFER_PIO_4) { outb(inb(hwif->dma_base+2)|(1<<(5+unit)), hwif->dma_base+2); } else { outb(inb(hwif->dma_base+2) & ~(1<<(5+unit)), hwif->dma_base+2); } +#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ switch(speed) { case XFER_UDMA_7: drive->id->dma_ultra |= 0x8080; break; diff --git a/drivers/ide/ide-geometry.c b/drivers/ide/ide-geometry.c index 29de5bb09d56..a291785971cf 100644 --- a/drivers/ide/ide-geometry.c +++ b/drivers/ide/ide-geometry.c @@ -3,7 +3,7 @@ */ #include -#ifdef CONFIG_IDE +#if defined(CONFIG_IDE) && !defined(CONFIG_BLK_DEV_HD) #include #include @@ -211,4 +211,4 @@ int ide_xlate_1024 (kdev_t i_rdev, int xparm, int ptheads, const char *msg) drive->bios_cyl, drive->bios_head, drive->bios_sect); return ret; } -#endif /* CONFIG_IDE */ +#endif /* (CONFIG_IDE) && !(CONFIG_BLK_DEV_HD) */ diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 83b14b1fd7d3..ddf6c8daefa7 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -425,10 +425,10 @@ static int hwif_check_regions (ide_hwif_t *hwif) if (hwif->io_ports[IDE_CONTROL_OFFSET]) region_errors += ide_check_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1); - +#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC) if (hwif->io_ports[IDE_IRQ_OFFSET]) region_errors += ide_check_region(hwif->io_ports[IDE_IRQ_OFFSET], 1); - +#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */ /* * If any errors are return, we drop the hwif interface. */ @@ -437,8 +437,8 @@ static int hwif_check_regions (ide_hwif_t *hwif) static void hwif_register (ide_hwif_t *hwif) { - if ((hwif->io_ports[IDE_DATA_OFFSET] | 7) == - (hwif->io_ports[IDE_STATUS_OFFSET])) { + if (((unsigned long)hwif->io_ports[IDE_DATA_OFFSET] | 7) == + ((unsigned long)hwif->io_ports[IDE_STATUS_OFFSET])) { ide_request_region(hwif->io_ports[IDE_DATA_OFFSET], 8, hwif->name); hwif->straight8 = 1; goto jump_straight8; @@ -464,8 +464,10 @@ static void hwif_register (ide_hwif_t *hwif) jump_straight8: if (hwif->io_ports[IDE_CONTROL_OFFSET]) ide_request_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1, hwif->name); +#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC) if (hwif->io_ports[IDE_IRQ_OFFSET]) ide_request_region(hwif->io_ports[IDE_IRQ_OFFSET], 1, hwif->name); +#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */ } /* diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 2b590266b680..09e1b12fb71e 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -3912,8 +3912,12 @@ static int idetape_get_logical_blk (ide_drive_t *drive, int logical_blk_num, int #endif clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags); position = idetape_read_position(drive); - printk(KERN_INFO "ide-tape: %s: blank block detected, positioning tape to block %d\n", tape->name, position + 60); - idetape_position_tape(drive, position + 60, 0, 1); + if (position >= 2980 && position < 3000) + position = 3000; + else + position += 60; + printk(KERN_INFO "ide-tape: %s: blank block detected, positioning tape to block %d\n", tape->name, position); + idetape_position_tape(drive, position, 0, 1); cnt += 40; continue; } else diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index cb34d354478e..a3394807b166 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -824,7 +824,7 @@ byte ide_dump_status (ide_drive_t *drive, const char *msg, byte stat) if (drive->media == ide_disk) { printk(" { "); if (err & ABRT_ERR) printk("DriveStatusError "); - if (err & ICRC_ERR) printk((err & ABRT_ERR) ? "BadCRC " : "BadSector "); + if (err & ICRC_ERR) printk("%s", (err & ABRT_ERR) ? "BadCRC " : "BadSector "); if (err & ECC_ERR) printk("UncorrectableError "); if (err & ID_ERR) printk("SectorIdNotFound "); if (err & TRK0_ERR) printk("TrackZeroNotFound "); @@ -1896,8 +1896,10 @@ void hwif_unregister (ide_hwif_t *hwif) jump_eight: if (hwif->io_ports[IDE_CONTROL_OFFSET]) ide_release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1); +#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC) if (hwif->io_ports[IDE_IRQ_OFFSET]) ide_release_region(hwif->io_ports[IDE_IRQ_OFFSET], 1); +#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */ } void ide_unregister (unsigned int index) @@ -2006,12 +2008,12 @@ void ide_unregister (unsigned int index) else hwgroup->hwif = HWIF(hwgroup->drive); -#ifdef CONFIG_BLK_DEV_IDEDMA +#ifdef CONFIG_BLK_DEV_IDEDMA_PCI if (hwif->dma_base) { (void) ide_release_dma(hwif); hwif->dma_base = 0; } -#endif /* CONFIG_BLK_DEV_IDEDMA */ +#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ /* * Remove us from the kernel's knowledge @@ -2087,9 +2089,11 @@ void ide_setup_ports ( hw_regs_t *hw, case IDE_CONTROL_OFFSET: hw->io_ports[i] = ctrl; break; +#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC) case IDE_IRQ_OFFSET: hw->io_ports[i] = intr; break; +#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */ default: hw->io_ports[i] = 0; break; @@ -2552,8 +2556,6 @@ static int ide_ioctl (struct inode *inode, struct file *file, if ((HWIF(drive)->speedproc) != NULL) HWIF(drive)->speedproc(drive, xfer_rate); ide_driveid_update(drive); - } else { - printk("%s: \n", drive->name); } abort: if (copy_to_user((void *)arg, argbuf, argsize)) @@ -3617,10 +3619,10 @@ void cleanup_module (void) for (index = 0; index < MAX_HWIFS; ++index) { ide_unregister(index); -#ifdef CONFIG_BLK_DEV_IDEDMA +#ifdef CONFIG_BLK_DEV_IDEDMA_PCI if (ide_hwifs[index].dma_base) (void) ide_release_dma(&ide_hwifs[index]); -#endif /* CONFIG_BLK_DEV_IDEDMA */ +#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ } #ifdef CONFIG_PROC_FS diff --git a/drivers/ide/piix.c b/drivers/ide/piix.c index 90af168c351f..56c1852361d4 100644 --- a/drivers/ide/piix.c +++ b/drivers/ide/piix.c @@ -86,7 +86,7 @@ static int piix_get_info (char *buffer, char **addr, off_t offset, int count) u32 bibma = bmide_dev->resource[4].start; u16 reg40 = 0, psitre = 0, reg42 = 0, ssitre = 0; u8 c0 = 0, c1 = 0; - u8 reg44 = 0, reg48 = 0, reg4a = 0, reg4b = 0, reg54 = 0; + u8 reg44 = 0, reg48 = 0, reg4a = 0, reg4b = 0, reg54 = 0, reg55 = 0; pci_read_config_word(bmide_dev, 0x40, ®40); pci_read_config_word(bmide_dev, 0x42, ®42); @@ -95,6 +95,7 @@ static int piix_get_info (char *buffer, char **addr, off_t offset, int count) pci_read_config_byte(bmide_dev, 0x4a, ®4a); pci_read_config_byte(bmide_dev, 0x4b, ®4b); pci_read_config_byte(bmide_dev, 0x54, ®54); + pci_read_config_byte(bmide_dev, 0x55, ®55); psitre = (reg40 & 0x4000) ? 1 : 0; ssitre = (reg42 & 0x4000) ? 1 : 0; @@ -264,13 +265,15 @@ static int piix_tune_chipset (ide_drive_t *drive, byte speed) ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; byte maslave = hwif->channel ? 0x42 : 0x40; - int a_speed = 2 << (drive->dn * 4); + int a_speed = 3 << (drive->dn * 4); int u_flag = 1 << drive->dn; - int v_flag = 0x10 << drive->dn; + int v_flag = 0x01 << drive->dn; + int w_flag = 0x10 << drive->dn; int u_speed = 0; int err = 0; int sitre; short reg4042, reg44, reg48, reg4a, reg54; + byte reg55; pci_read_config_word(dev, maslave, ®4042); sitre = (reg4042 & 0x4000) ? 1 : 0; @@ -278,6 +281,7 @@ static int piix_tune_chipset (ide_drive_t *drive, byte speed) pci_read_config_word(dev, 0x48, ®48); pci_read_config_word(dev, 0x4a, ®4a); pci_read_config_word(dev, 0x54, ®54); + pci_read_config_byte(dev, 0x55, ®55); switch(speed) { case XFER_UDMA_4: @@ -294,6 +298,7 @@ static int piix_tune_chipset (ide_drive_t *drive, byte speed) if (speed >= XFER_UDMA_0) { if (!(reg48 & u_flag)) pci_write_config_word(dev, 0x48, reg48|u_flag); + pci_write_config_byte(dev, 0x55, (byte) reg55 & ~w_flag); if (!(reg4a & u_speed)) { pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); pci_write_config_word(dev, 0x4a, reg4a|u_speed); @@ -313,6 +318,8 @@ static int piix_tune_chipset (ide_drive_t *drive, byte speed) pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); if (reg54 & v_flag) pci_write_config_word(dev, 0x54, reg54 & ~v_flag); + if (reg55 & w_flag) + pci_write_config_byte(dev, 0x55, (byte) reg55 & ~w_flag); } piix_tune_drive(drive, piix_dma_2_pio(speed)); @@ -404,10 +411,11 @@ unsigned int __init pci_init_piix (struct pci_dev *dev, const char *name) unsigned int __init ata66_piix (ide_hwif_t *hwif) { byte reg54h = 0, reg55h = 0, ata66 = 0; - byte mask = hwif->channel ? 0x0c : 0x03; + byte mask = hwif->channel ? 0xc0 : 0x30; pci_read_config_byte(hwif->pci_dev, 0x54, ®54h); pci_read_config_byte(hwif->pci_dev, 0x55, ®55h); + ata66 = (reg54h & mask) ? 1 : 0; return ata66; @@ -415,8 +423,10 @@ unsigned int __init ata66_piix (ide_hwif_t *hwif) void __init ide_init_piix (ide_hwif_t *hwif) { +#ifndef CONFIG_IA64 if (!hwif->irq) hwif->irq = hwif->channel ? 15 : 14; +#endif /* CONFIG_IA64 */ hwif->tuneproc = &piix_tune_drive; hwif->drives[0].autotune = 1; diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c index 39258362ca8d..6c201599f81f 100644 --- a/drivers/ide/via82cxxx.c +++ b/drivers/ide/via82cxxx.c @@ -243,7 +243,7 @@ static const struct { #define arraysize(x) (sizeof(x)/sizeof(*(x))) -#define DISPLAY_VIA_TIMINGS +#undef DISPLAY_VIA_TIMINGS #if defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS) #include @@ -657,6 +657,7 @@ static int via82cxxx_tune_chipset (ide_drive_t *drive, byte speed) struct pci_dev *dev = hwif->pci_dev; struct chipset_bus_clock_list_entry * temp_table = NULL; + byte unit = (drive->select.b.unit & 0x01) ? 1 : 0; byte ata2_pci = 0x00; byte ata3_pci = 0x00; byte timing = 0x00; @@ -677,7 +678,9 @@ static int via82cxxx_tune_chipset (ide_drive_t *drive, byte speed) return -1; } - if ((via82cxxx_table == via82cxxx_type_four) && (speed <= XFER_UDMA_2)) { + if ((via82cxxx_table == via82cxxx_type_four) && + (!(hwif->udma_four)) && + (speed <= XFER_UDMA_2)) { temp_table = via82cxxx_type_three; } else { temp_table = via82cxxx_table; @@ -689,6 +692,8 @@ static int via82cxxx_tune_chipset (ide_drive_t *drive, byte speed) pci_read_config_byte(dev, ata3_pci, &ultra); ultra = pci_bus_clock_list_ultra(speed, bus_speed, temp_table); + if ((unit) && (hwif->udma_four)) + ultra |= 0x04; pci_write_config_byte(dev, ata3_pci, ultra); if (!drive->init_speed) diff --git a/drivers/sound/es1370.c b/drivers/sound/es1370.c index 7f05925cd5e7..ec3849a748b7 100644 --- a/drivers/sound/es1370.c +++ b/drivers/sound/es1370.c @@ -2455,9 +2455,8 @@ static struct initvol { { SOUND_MIXER_WRITE_OGAIN, 0x4040 } }; -#define RSRCISIOREGION(dev,num) ((dev)->resource[(num)].start != 0 && \ - ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) -#define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start) +#define RSRCISIOREGION(dev,num) (pci_resource_start((dev), (num)) != 0 && \ + pci_resource_flags((dev), (num)) & IORESOURCE_IO) static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) { @@ -2488,7 +2487,7 @@ static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_devic spin_lock_init(&s->lock); s->magic = ES1370_MAGIC; s->dev = pcidev; - s->io = RSRCADDRESS(pcidev, 0); + s->io = pci_resource_start(pcidev, 0); s->irq = pcidev->irq; if (!request_region(s->io, ES1370_EXTENT, "es1370")) { printk(KERN_ERR "es1370: io ports %#lx-%#lx in use\n", s->io, s->io+ES1370_EXTENT-1); @@ -2616,12 +2615,7 @@ static int __init init_es1370(void) if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; printk(KERN_INFO "es1370: version v0.33 time " __TIME__ " " __DATE__ "\n"); - if (!pci_register_driver(&es1370_driver)) { - pci_unregister_driver(&es1370_driver); - return -ENODEV; - } - return 0; - + return pci_module_init(&es1370_driver); } static void __exit cleanup_es1370(void) diff --git a/drivers/sound/es1371.c b/drivers/sound/es1371.c index 1623c98ba681..44189f010c0b 100644 --- a/drivers/sound/es1371.c +++ b/drivers/sound/es1371.c @@ -100,6 +100,8 @@ * Tim Janik's BSE (Bedevilled Sound Engine) found this * 07.02.2000 0.24 Use pci_alloc_consistent and pci_register_driver * 07.02.2000 0.25 Use ac97_codec + * 01.03.2000 0.26 SPDIF patch by Mikael Bouillot + * Use pci_module_init */ /*****************************************************************************/ @@ -205,6 +207,7 @@ static const unsigned sample_size[] = { 1, 2, 2, 4 }; static const unsigned sample_shift[] = { 0, 1, 1, 2 }; +#define CTRL_RECEN_B 0x08000000 /* 1 = don't mix analog in to digital out */ #define CTRL_SPDIFEN_B 0x04000000 #define CTRL_JOY_SHIFT 24 #define CTRL_JOY_MASK 3 @@ -344,22 +347,6 @@ static const unsigned sample_shift[] = { 0, 1, 1, 2 }; #define SCTRL_P1FMT 0x00000003 /* format mask */ #define SCTRL_SH_P1FMT 0 -/* codec constants */ - -#define CODEC_ID_DEDICATEDMIC 0x001 -#define CODEC_ID_MODEMCODEC 0x002 -#define CODEC_ID_BASSTREBLE 0x004 -#define CODEC_ID_SIMULATEDSTEREO 0x008 -#define CODEC_ID_HEADPHONEOUT 0x010 -#define CODEC_ID_LOUDNESS 0x020 -#define CODEC_ID_18BITDAC 0x040 -#define CODEC_ID_20BITDAC 0x080 -#define CODEC_ID_18BITADC 0x100 -#define CODEC_ID_20BITADC 0x200 - -#define CODEC_ID_SESHIFT 10 -#define CODEC_ID_SEMASK 0x1f - /* misc stuff */ #define POLL_COUNT 0x1000 @@ -405,6 +392,9 @@ struct es1371_state { u16 device; u8 rev; /* the chip revision */ + /* options */ + int spdif_volume; /* S/PDIF output is enabled if != -1 */ + #ifdef ES1371_DEBUG /* debug /proc entry */ struct proc_dir_entry *ps; @@ -1135,6 +1125,67 @@ static loff_t es1371_llseek(struct file *file, loff_t offset, int origin) /* --------------------------------------------------------------------- */ +/* Conversion table for S/PDIF PCM volume emulation through the SRC */ +/* dB-linear table of DAC vol values; -0dB to -46.5dB with mute */ +static const unsigned short DACVolTable[101] = +{ + 0x1000, 0x0f2a, 0x0e60, 0x0da0, 0x0cea, 0x0c3e, 0x0b9a, 0x0aff, + 0x0a6d, 0x09e1, 0x095e, 0x08e1, 0x086a, 0x07fa, 0x078f, 0x072a, + 0x06cb, 0x0670, 0x061a, 0x05c9, 0x057b, 0x0532, 0x04ed, 0x04ab, + 0x046d, 0x0432, 0x03fa, 0x03c5, 0x0392, 0x0363, 0x0335, 0x030b, + 0x02e2, 0x02bc, 0x0297, 0x0275, 0x0254, 0x0235, 0x0217, 0x01fb, + 0x01e1, 0x01c8, 0x01b0, 0x0199, 0x0184, 0x0170, 0x015d, 0x014b, + 0x0139, 0x0129, 0x0119, 0x010b, 0x00fd, 0x00f0, 0x00e3, 0x00d7, + 0x00cc, 0x00c1, 0x00b7, 0x00ae, 0x00a5, 0x009c, 0x0094, 0x008c, + 0x0085, 0x007e, 0x0077, 0x0071, 0x006b, 0x0066, 0x0060, 0x005b, + 0x0057, 0x0052, 0x004e, 0x004a, 0x0046, 0x0042, 0x003f, 0x003c, + 0x0038, 0x0036, 0x0033, 0x0030, 0x002e, 0x002b, 0x0029, 0x0027, + 0x0025, 0x0023, 0x0021, 0x001f, 0x001e, 0x001c, 0x001b, 0x0019, + 0x0018, 0x0017, 0x0016, 0x0014, 0x0000 +}; + +/* + * when we are in S/PDIF mode, we want to disable any analog output so + * we filter the mixer ioctls + */ +static int mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd, unsigned long arg) +{ + struct es1371_state *s = (struct es1371_state *)codec->private_data; + int val; + unsigned long flags; + unsigned int left, right; + + VALIDATE_STATE(s); + /* filter mixer ioctls to catch PCM and MASTER volume when in S/PDIF mode */ + if (s->spdif_volume == -1) + return codec->mixer_ioctl(codec, cmd, arg); + switch (cmd) { + case SOUND_MIXER_WRITE_VOLUME: + return 0; + + case SOUND_MIXER_WRITE_PCM: /* use SRC for PCM volume */ + get_user_ret(val, (int *)arg, -EFAULT); + right = ((val >> 8) & 0xff); + left = (val & 0xff); + if (right > 100) + right = 100; + if (left > 100) + left = 100; + s->spdif_volume = (right << 8) | left; + spin_lock_irqsave(&s->lock, flags); + src_write(s, SRCREG_VOL_DAC2, DACVolTable[100 - left]); + src_write(s, SRCREG_VOL_DAC2+1, DACVolTable[100 - right]); + spin_unlock_irqrestore(&s->lock, flags); + return 0; + + case SOUND_MIXER_READ_PCM: + return put_user(s->spdif_volume, (int *)arg); + } + return codec->mixer_ioctl(codec, cmd, arg); +} + +/* --------------------------------------------------------------------- */ + /* * AC97 Mixer Register to Connections mapping of the Concert 97 board * @@ -1180,8 +1231,10 @@ static int es1371_release_mixdev(struct inode *inode, struct file *file) static int es1371_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - struct ac97_codec *codec = &((struct es1371_state *)file->private_data)->codec; - return codec->mixer_ioctl(codec, cmd, arg); + struct es1371_state *s = (struct es1371_state *)file->private_data; + struct ac97_codec *codec = &s->codec; + + return mixdev_ioctl(codec, cmd, arg); } static /*const*/ struct file_operations es1371_mixer_fops = { @@ -1778,7 +1831,7 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd return -EINVAL; } - return s->codec.mixer_ioctl(&s->codec, cmd, arg); + return mixdev_ioctl(&s->codec, cmd, arg); } static int es1371_open(struct inode *inode, struct file *file) @@ -2181,7 +2234,7 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int return -EINVAL; } - return s->codec.mixer_ioctl(&s->codec, cmd, arg); + return mixdev_ioctl(&s->codec, cmd, arg); } static int es1371_open_dac(struct inode *inode, struct file *file) @@ -2581,6 +2634,7 @@ static int proc_es1371_dump (char *buf, char **start, off_t fpos, int length, in static int joystick[NR_DEVICE] = { 0, }; static int spdif[NR_DEVICE] = { 0, }; +static int nomix[NR_DEVICE] = { 0, }; static unsigned int devindex = 0; @@ -2588,6 +2642,8 @@ MODULE_PARM(joystick, "1-" __MODULE_STRING(NR_DEVICE) "i"); MODULE_PARM_DESC(joystick, "sets address and enables joystick interface (still need separate driver)"); MODULE_PARM(spdif, "1-" __MODULE_STRING(NR_DEVICE) "i"); MODULE_PARM_DESC(spdif, "if 1 the output is in S/PDIF digital mode"); +MODULE_PARM(nomix, "1-" __MODULE_STRING(NR_DEVICE) "i"); +MODULE_PARM_DESC(nomix, "if 1 no analog audio is mixed to the digital output"); MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu"); MODULE_DESCRIPTION("ES1371 AudioPCI97 Driver"); @@ -2613,9 +2669,8 @@ static struct initvol { { SOUND_MIXER_WRITE_IGAIN, 0x4040 } }; -#define RSRCISIOREGION(dev,num) ((dev)->resource[(num)].start != 0 && \ - ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) -#define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start) +#define RSRCISIOREGION(dev,num) (pci_resource_start((dev), (num)) != 0 && \ + (pci_resource_flags((dev), (num)) & IORESOURCE_IO)) static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) { @@ -2649,7 +2704,7 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic spin_lock_init(&s->lock); s->magic = ES1371_MAGIC; s->dev = pcidev; - s->io = RSRCADDRESS(pcidev, 0); + s->io = pci_resource_start(pcidev, 0); s->irq = pcidev->irq; s->vendor = pcidev->vendor; s->device = pcidev->device; @@ -2688,6 +2743,10 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic /* initialize codec registers */ s->ctrl = 0; + if (pcidev->subsystem_vendor == 0x107b && pcidev->subsystem_device == 0x2150) { + s->ctrl |= CTRL_GPIO_OUT0; + printk(KERN_INFO PFX "Running On Gateway 2000 Solo 2510 - Amp On \n"); + } if ((joystick[devindex] & ~0x18) == 0x200) { if (check_region(joystick[devindex], JOY_EXTENT)) printk(KERN_ERR PFX "joystick address 0x%x already in use\n", joystick[devindex]); @@ -2697,12 +2756,16 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic } s->sctrl = 0; cssr = 0; + s->spdif_volume = -1; /* check to see if s/pdif mode is being requested */ if (spdif[devindex]) { if (s->rev >= 4) { printk(KERN_INFO PFX "enabling S/PDIF output\n"); + s->spdif_volume = 0; cssr |= STAT_EN_SPDIF; s->ctrl |= CTRL_SPDIFEN_B; + if (nomix[devindex]) /* don't mix analog inputs to s/pdif output */ + s->ctrl |= CTRL_RECEN_B; } else { printk(KERN_ERR PFX "revision %d does not support S/PDIF\n", s->rev); } @@ -2742,10 +2805,16 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic fs = get_fs(); set_fs(KERNEL_DS); val = SOUND_MASK_LINE; - s->codec.mixer_ioctl(&s->codec, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val); + mixdev_ioctl(&s->codec, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val); for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) { val = initvol[i].vol; - s->codec.mixer_ioctl(&s->codec, initvol[i].mixch, (unsigned long)&val); + mixdev_ioctl(&s->codec, initvol[i].mixch, (unsigned long)&val); + } + /* mute master and PCM when in S/PDIF mode */ + if (s->spdif_volume != -1) { + val = 0x0000; + s->codec.mixer_ioctl(&s->codec, SOUND_MIXER_WRITE_VOLUME, (unsigned long)&val); + s->codec.mixer_ioctl(&s->codec, SOUND_MIXER_WRITE_PCM, (unsigned long)&val); } set_fs(fs); /* turn on S/PDIF output driver if requested */ @@ -2820,12 +2889,8 @@ static int __init init_es1371(void) { if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "es1371: version v0.25 time " __TIME__ " " __DATE__ "\n"); - if (!pci_register_driver(&es1371_driver)) { - pci_unregister_driver(&es1371_driver); - return -ENODEV; - } - return 0; + printk(KERN_INFO PFX "version v0.26 time " __TIME__ " " __DATE__ "\n"); + return pci_module_init(&es1371_driver); } static void __exit cleanup_es1371(void) diff --git a/drivers/sound/esssolo1.c b/drivers/sound/esssolo1.c index 1c62eafed743..2d7e15f5132b 100644 --- a/drivers/sound/esssolo1.c +++ b/drivers/sound/esssolo1.c @@ -68,6 +68,7 @@ * Integrated (aka redid 8-)) APM support patch by Zach Brown * 07.02.2000 0.13 Use pci_alloc_consistent and pci_register_driver * 19.02.2000 0.14 Use pci_dma_supported to determine if recording should be disabled + * 13.03.2000 0.15 Reintroduce initialization of a couple of PCI config space registers */ /*****************************************************************************/ @@ -2130,6 +2131,14 @@ static int setup_solo1(struct solo1_state *s) mm_segment_t fs; int i, val; + /* initialize DDMA base address */ + printk(KERN_DEBUG "solo1: ddma base address: 0x%lx\n", s->ddmabase); + pci_write_config_word(pcidev, 0x60, (s->ddmabase & (~0xf)) | 1); + /* set DMA policy to DDMA, IRQ emulation off (CLKRUN disabled for now) */ + pci_write_config_dword(pcidev, 0x50, 0); + /* disable legacy audio address decode */ + pci_write_config_word(pcidev, 0x40, 0x907f); + /* initialize the chips */ if (!reset_ctrl(s)) { printk(KERN_ERR "esssolo1: cannot reset controller\n"); @@ -2190,9 +2199,8 @@ static int solo1_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) } -#define RSRCISIOREGION(dev,num) ((dev)->resource[(num)].start != 0 && \ - ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) -#define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start) +#define RSRCISIOREGION(dev,num) (pci_resource_start((dev), (num)) != 0 && \ + (pci_resource_flags((dev), (num)) & IORESOURCE_IO)) static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) { @@ -2229,12 +2237,12 @@ static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device spin_lock_init(&s->lock); s->magic = SOLO1_MAGIC; s->dev = pcidev; - s->iobase = RSRCADDRESS(pcidev, 0); - s->sbbase = RSRCADDRESS(pcidev, 1); - s->vcbase = RSRCADDRESS(pcidev, 2); + s->iobase = pci_resource_start(pcidev, 0); + s->sbbase = pci_resource_start(pcidev, 1); + s->vcbase = pci_resource_start(pcidev, 2); s->ddmabase = s->vcbase + DDMABASE_OFFSET; - s->mpubase = RSRCADDRESS(pcidev, 3); - s->gpbase = RSRCADDRESS(pcidev, 4); + s->mpubase = pci_resource_start(pcidev, 3); + s->gpbase = pci_resource_start(pcidev, 4); s->irq = pcidev->irq; if (!request_region(s->iobase, IOBASE_EXTENT, "ESS Solo1")) { printk(KERN_ERR "solo1: io ports in use\n"); @@ -2252,13 +2260,12 @@ static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device printk(KERN_ERR "solo1: io ports in use\n"); goto err_region4; } - if (pci_enable_device(pcidev)) - goto err_irq; if (request_irq(s->irq, solo1_interrupt, SA_SHIRQ, "ESS Solo1", s)) { printk(KERN_ERR "solo1: irq %u in use\n", s->irq); goto err_irq; } - printk(KERN_DEBUG "solo1: ddma base address: 0x%lx\n", s->ddmabase); + if (pci_enable_device(pcidev)) + goto err_irq; printk(KERN_INFO "solo1: joystick port at %#lx\n", s->gpbase+1); /* register devices */ if ((s->dev_audio = register_sound_dsp(&solo1_audio_fops, -1)) < 0) @@ -2352,7 +2359,7 @@ static int __init init_solo1(void) { if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "solo1: version v0.14 time " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "solo1: version v0.15 time " __TIME__ " " __DATE__ "\n"); if (!pci_register_driver(&solo1_driver)) { pci_unregister_driver(&solo1_driver); return -ENODEV; diff --git a/drivers/sound/sonicvibes.c b/drivers/sound/sonicvibes.c index 5aa31f506575..7a8a7117b473 100644 --- a/drivers/sound/sonicvibes.c +++ b/drivers/sound/sonicvibes.c @@ -2428,9 +2428,8 @@ static struct initvol { { SOUND_MIXER_WRITE_PCM, 0x4040 } }; -#define RSRCISIOREGION(dev,num) ((dev)->resource[(num)].start != 0 && \ - ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) -#define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start) +#define RSRCISIOREGION(dev,num) (pci_resource_start((dev), (num)) != 0 && \ + (pci_resource_flags((dev), (num)) & IORESOURCE_IO)) static int __devinit sv_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) { @@ -2484,13 +2483,13 @@ static int __devinit sv_probe(struct pci_dev *pcidev, const struct pci_device_id spin_lock_init(&s->lock); s->magic = SV_MAGIC; s->dev = pcidev; - s->iosb = RSRCADDRESS(pcidev, RESOURCE_SB); - s->ioenh = RSRCADDRESS(pcidev, RESOURCE_ENH); - s->iosynth = RSRCADDRESS(pcidev, RESOURCE_SYNTH); - s->iomidi = RSRCADDRESS(pcidev, RESOURCE_MIDI); - s->iogame = RSRCADDRESS(pcidev, RESOURCE_GAME); - s->iodmaa = RSRCADDRESS(pcidev, RESOURCE_DDMA); - s->iodmac = RSRCADDRESS(pcidev, RESOURCE_DDMA) + SV_EXTENT_DMA; + s->iosb = pci_resource_start(pcidev, RESOURCE_SB); + s->ioenh = pci_resource_start(pcidev, RESOURCE_ENH); + s->iosynth = pci_resource_start(pcidev, RESOURCE_SYNTH); + s->iomidi = pci_resource_start(pcidev, RESOURCE_MIDI); + s->iogame = pci_resource_start(pcidev, RESOURCE_GAME); + s->iodmaa = pci_resource_start(pcidev, RESOURCE_DDMA); + s->iodmac = pci_resource_start(pcidev, RESOURCE_DDMA) + SV_EXTENT_DMA; pci_write_config_dword(pcidev, 0x40, s->iodmaa | 9); /* enable and use extended mode */ pci_write_config_dword(pcidev, 0x48, s->iodmac | 9); /* enable */ printk(KERN_DEBUG "sv: io ports: %#lx %#lx %#lx %#lx %#lx %#x %#x\n", @@ -2655,11 +2654,7 @@ static int __init init_sonicvibes(void) if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT))) printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n"); #endif - if (!pci_register_driver(&sv_driver)) { - pci_unregister_driver(&sv_driver); - return -ENODEV; - } - return 0; + return pci_module_init(&sv_driver); } static void __exit cleanup_sonicvibes(void) diff --git a/drivers/usb/audio.c b/drivers/usb/audio.c index 40903a9c299a..ad94fef5562b 100644 --- a/drivers/usb/audio.c +++ b/drivers/usb/audio.c @@ -52,14 +52,17 @@ * decent headphones! * "Let's make things better" -> but please Philips start with your * own stuff!!!! - * 1999-11-02: It takes the Philips boxes several seconds to acquire synchronisation + * 1999-11-02: Thomas Sailer + * It takes the Philips boxes several seconds to acquire synchronisation * that means they won't play short sounds. Should probably maintain * the ISO datastream even if there's nothing to play. * Fix counting the total_bytes counter, RealPlayer G2 depends on it. - * 1999-12-20: Fix bad bug in conversion to per interface probing. + * 1999-12-20: Thomas Sailer + * Fix bad bug in conversion to per interface probing. * disconnect was called multiple times for the audio device, * leading to a premature freeing of the audio structures - * 2000-05-13: I don't remember who changed the find_format routine, + * 2000-05-13: Thomas Sailer + * I don't remember who changed the find_format routine, * but the change was completely broken for the Dallas * chip. Anyway taking sampling rate into account in find_format * is bad and should not be done unless there are devices with @@ -72,8 +75,20 @@ * for the Dallas chip. * Also fix a rather long standing problem with applications that * use "small" writes producing no sound at all. - * 2000-05-15: My fears came true, the Philips camera indeed has pretty stupid + * 2000-05-15: Thomas Sailer + * My fears came true, the Philips camera indeed has pretty stupid * audio descriptors. + * 2000-05-17: Thomas Sailer + * Nemsoft spotted my stupid last minute change, thanks + * 2000-05-19: Thomas Sailer + * Fixed FEATURE_UNIT thinkos found thanks to the KC Technology + * Xtend device. Basically the driver treated FEATURE_UNIT's sourced + * by mono terminals as stereo. + * 2000-05-20: Thomas Sailer + * SELECTOR support (and thus selecting record channels from the mixer). + * Somewhat peculiar due to OSS interface limitations. Only works + * for channels where a "slider" is already in front of it (i.e. + * a MIXER unit or a FEATURE unit with volume capability). * */ @@ -211,6 +226,7 @@ struct mixerchannel { __u16 value; __u16 osschannel; /* number of the OSS channel */ __s16 minval, maxval; + __u16 slctunitid; __u8 unitid; __u8 selector; __u8 chnum; @@ -988,7 +1004,7 @@ static int usbin_start(struct usb_audiodev *as) } spin_lock_irqsave(&as->lock, flags); } - if (u->dma.count <= 0 && !u->dma.mapped) + if (u->dma.count >= u->dma.dmasize && !u->dma.mapped) return 0; u->flags |= FLG_RUNNING; if (!(u->flags & FLG_URB0RUNNING)) { @@ -1719,7 +1735,7 @@ static int wrmixer(struct usb_mixerdev *ms, unsigned mixch, unsigned value) if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, (ch->selector << 8) | ch->chnum, ms->iface | (ch->unitid << 8), data, 2, HZ) < 0) goto err; - if (ch->chnum == 0) + if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT))) return 0; data[0] = v2; data[1] = v2 >> 8; @@ -1735,7 +1751,7 @@ static int wrmixer(struct usb_mixerdev *ms, unsigned mixch, unsigned value) if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, (ch->selector << 8) | ch->chnum, ms->iface | (ch->unitid << 8), data, 1, HZ) < 0) goto err; - if (ch->chnum == 0) + if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT))) return 0; data[0] = v2 >> 8; if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, @@ -1754,6 +1770,89 @@ static int wrmixer(struct usb_mixerdev *ms, unsigned mixch, unsigned value) return -1; } +static int get_rec_src(struct usb_mixerdev *ms) +{ + struct usb_device *dev = ms->state->usbdev; + unsigned int mask = 0, retmask = 0; + unsigned int i, j; + unsigned char buf; + int err = 0; + + for (i = 0; i < ms->numch; i++) { + if (!ms->ch[i].slctunitid || (mask & (1 << i))) + continue; + if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, + 0, ms->iface | (ms->ch[i].slctunitid << 8), &buf, 1, HZ) < 0) { + err = -EIO; + printk(KERN_ERR "usbaudio: selector read request device %u if %u unit %u failed\n", + dev->devnum, ms->iface, ms->ch[i].slctunitid & 0xff); + continue; + } + for (j = i; j < ms->numch; i++) { + if ((ms->ch[i].slctunitid ^ ms->ch[j].slctunitid) & 0xff) + continue; + mask |= 1 << j; + if (buf == (ms->ch[j].slctunitid >> 8)) + retmask |= 1 << ms->ch[j].osschannel; + } + } + if (err) + return -EIO; + return retmask; +} + +static int set_rec_src(struct usb_mixerdev *ms, int srcmask) +{ + struct usb_device *dev = ms->state->usbdev; + unsigned int mask = 0, smask, bmask; + unsigned int i, j; + unsigned char buf; + int err = 0; + + for (i = 0; i < ms->numch; i++) { + if (!ms->ch[i].slctunitid || (mask & (1 << i))) + continue; + if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, + 0, ms->iface | (ms->ch[i].slctunitid << 8), &buf, 1, HZ) < 0) { + err = -EIO; + printk(KERN_ERR "usbaudio: selector read request device %u if %u unit %u failed\n", + dev->devnum, ms->iface, ms->ch[i].slctunitid & 0xff); + continue; + } + /* first generate smask */ + smask = bmask = 0; + for (j = i; j < ms->numch; i++) { + if ((ms->ch[i].slctunitid ^ ms->ch[j].slctunitid) & 0xff) + continue; + smask |= 1 << ms->ch[j].osschannel; + if (buf == (ms->ch[j].slctunitid >> 8)) + bmask |= 1 << ms->ch[j].osschannel; + mask |= 1 << j; + } + /* check for multiple set sources */ + j = hweight32(srcmask & smask); + if (j == 0) + continue; + if (j > 1) + srcmask &= ~bmask; + for (j = i; j < ms->numch; i++) { + if ((ms->ch[i].slctunitid ^ ms->ch[j].slctunitid) & 0xff) + continue; + if (!(srcmask & (1 << ms->ch[j].osschannel))) + continue; + buf = ms->ch[j].slctunitid >> 8; + if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, + 0, ms->iface | (ms->ch[j].slctunitid << 8), &buf, 1, HZ) < 0) { + err = -EIO; + printk(KERN_ERR "usbaudio: selector write request device %u if %u unit %u failed\n", + dev->devnum, ms->iface, ms->ch[j].slctunitid & 0xff); + continue; + } + } + } + return err ? -EIO : 0; +} + /* --------------------------------------------------------------------- */ /* @@ -1886,8 +1985,10 @@ static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsign if (_IOC_DIR(cmd) == _IOC_READ) { switch (_IOC_NR(cmd)) { case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ - /* don't know how to handle this yet */ - return put_user(0, (int *)arg); + val = get_rec_src(ms); + if (val < 0) + return val; + return put_user(val, (int *)arg); case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */ for (val = i = 0; i < ms->numch; i++) @@ -1895,9 +1996,11 @@ static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsign return put_user(val, (int *)arg); case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */ - /* don't know how to handle this yet */ - return put_user(0, (int *)arg); - + for (val = i = 0; i < ms->numch; i++) + if (ms->ch[i].slctunitid) + val |= 1 << ms->ch[i].osschannel; + return put_user(val, (int *)arg); + case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */ for (val = i = 0; i < ms->numch; i++) if (ms->ch[i].flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)) @@ -1905,7 +2008,7 @@ static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsign return put_user(val, (int *)arg); case SOUND_MIXER_CAPS: - return put_user(0, (int *)arg); + return put_user(SOUND_CAP_EXCL_INPUT, (int *)arg); default: i = _IOC_NR(cmd); @@ -1925,8 +2028,7 @@ static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsign switch (_IOC_NR(cmd)) { case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ get_user_ret(val, (int *)arg, -EFAULT); - /* set recording source: val */ - return 0; + return set_rec_src(ms, val); default: i = _IOC_NR(cmd); @@ -2852,7 +2954,7 @@ static unsigned int getvolchannel(struct consmixstate *state) { unsigned int u; - if ((state->termtype & 0xff00) == 0x0000 && !(state->mixchmask & SOUND_MASK_VOLUME)) + if ((state->termtype & 0xff00) == 0x0000 && (state->mixchmask & SOUND_MASK_VOLUME)) return SOUND_MIXER_VOLUME; if ((state->termtype & 0xff00) == 0x0100) { if (state->mixchmask & SOUND_MASK_PCM) @@ -2864,8 +2966,6 @@ static unsigned int getvolchannel(struct consmixstate *state) return SOUND_MIXER_MIC; if ((state->termtype & 0xff00) == 0x0300 && (state->mixchmask & SOUND_MASK_SPEAKER)) return SOUND_MIXER_SPEAKER; - if ((state->termtype & 0xff00) == 0x0300 && (state->mixchmask & SOUND_MASK_SPEAKER)) - return SOUND_MIXER_SPEAKER; if ((state->termtype & 0xff00) == 0x0500) { if (state->mixchmask & SOUND_MASK_PHONEIN) return SOUND_MIXER_PHONEIN; @@ -2950,7 +3050,7 @@ static void prepmixch(struct consmixstate *state) if (v3 > 100) v3 = 100; ch->value = v3; - if (ch->chnum != 0) { + if (ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)) { if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, (ch->selector << 8) | (ch->chnum + 1), state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0) goto err; @@ -2986,7 +3086,7 @@ static void prepmixch(struct consmixstate *state) if (v3 > 100) v3 = 100; ch->value = v3; - if (ch->chnum != 0) { + if (ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)) { if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, (ch->selector << 8) | (ch->chnum + 1), state->ctrlif | (ch->unitid << 8), buf, 1, HZ) < 0) goto err; @@ -3095,15 +3195,24 @@ static void usb_audio_mixerunit(struct consmixstate *state, unsigned char *mixer static void usb_audio_selectorunit(struct consmixstate *state, unsigned char *selector) { - unsigned int chnum, i; + unsigned int chnum, i, mixch; + struct mixerchannel *mch; if (!selector[4]) { printk(KERN_ERR "usbaudio: unit %u invalid SELECTOR_UNIT descriptor\n", selector[3]); return; } + mixch = state->nrmixch; usb_audio_recurseunit(state, selector[5]); + if (state->nrmixch != mixch) { + mch = &state->mixch[state->nrmixch-1]; + mch->slctunitid = selector[5] | (1 << 8); + } else { + printk(KERN_INFO "usbaudio: selector unit %u: ignoring channel 1\n", selector[3]); + } chnum = state->nrchannels; for (i = 1; i < selector[4]; i++) { + mixch = state->nrmixch; usb_audio_recurseunit(state, selector[5+i]); if (chnum != state->nrchannels) { printk(KERN_ERR "usbaudio: selector unit %u: input pins with varying channel numbers\n", selector[3]); @@ -3112,6 +3221,12 @@ static void usb_audio_selectorunit(struct consmixstate *state, unsigned char *se state->nrchannels = 0; return; } + if (state->nrmixch != mixch) { + mch = &state->mixch[state->nrmixch-1]; + mch->slctunitid = selector[5] | ((i + 1) << 8); + } else { + printk(KERN_INFO "usbaudio: selector unit %u: ignoring channel %u\n", selector[3], i+1); + } } state->termtype = 0; state->chconfig = 0; @@ -3167,7 +3282,7 @@ static void usb_audio_featureunit(struct consmixstate *state, unsigned char *ftr ch->unitid = ftr[3]; ch->selector = VOLUME_CONTROL; ch->chnum = 1; - ch->flags = MIXFLG_STEREOIN | MIXFLG_STEREOOUT; + ch->flags = (state->nrchannels > 1) ? (MIXFLG_STEREOIN | MIXFLG_STEREOOUT) : 0; prepmixch(state); } } else if (mchftr & 2) { @@ -3187,7 +3302,7 @@ static void usb_audio_featureunit(struct consmixstate *state, unsigned char *ftr ch->unitid = ftr[3]; ch->selector = BASS_CONTROL; ch->chnum = 1; - ch->flags = MIXFLG_STEREOIN | MIXFLG_STEREOOUT; + ch->flags = (state->nrchannels > 1) ? (MIXFLG_STEREOIN | MIXFLG_STEREOOUT) : 0; prepmixch(state); } } else if (mchftr & 4) { @@ -3207,7 +3322,7 @@ static void usb_audio_featureunit(struct consmixstate *state, unsigned char *ftr ch->unitid = ftr[3]; ch->selector = TREBLE_CONTROL; ch->chnum = 1; - ch->flags = MIXFLG_STEREOIN | MIXFLG_STEREOOUT; + ch->flags = (state->nrchannels > 1) ? (MIXFLG_STEREOIN | MIXFLG_STEREOOUT) : 0; prepmixch(state); } } else if (mchftr & 16) { @@ -3239,7 +3354,7 @@ static void usb_audio_recurseunit(struct consmixstate *state, unsigned char unit unsigned int i, j; if (test_and_set_bit(unitid, &state->unitbitmap)) { - printk(KERN_ERR "usbaudio: mixer path recursion detected, unit %d!\n", unitid); + printk(KERN_INFO "usbaudio: mixer path revisits unit %d\n", unitid); return; } p1 = find_audiocontrol_unit(state->buffer, state->buflen, NULL, unitid, state->ctrlif); diff --git a/drivers/usb/ibmcam.c b/drivers/usb/ibmcam.c index 2deab03fa631..c083f2982326 100644 --- a/drivers/usb/ibmcam.c +++ b/drivers/usb/ibmcam.c @@ -7,6 +7,22 @@ * * (C) Copyright 1999 Johannes Erdfelt * (C) Copyright 1999 Randy Dunlap + * + * 5/24/00 Removed optional (and unnecessary) locking of the driver while + * the device remains plugged in. Corrected race conditions in ibmcam_open + * and ibmcam_probe() routines using this as a guideline: + * + * (2) The big kernel lock is automatically released when a process sleeps + * in the kernel and is automatically reacquired on reschedule if the + * process had the lock originally. Any code that can be compiled as + * a module and is entered with the big kernel lock held *MUST* + * increment the use count to activate the indirect module protection + * before doing anything that might sleep. + * + * In practice, this means that all routines that live in modules and + * are invoked under the big kernel lock should do MOD_INC_USE_COUNT + * as their very first action. And all failure paths from that + * routine must do MOD_DEC_USE_COUNT before returning. */ #include @@ -26,21 +42,6 @@ #include "ibmcam.h" -/* - * IBMCAM_LOCKS_DRIVER_WHILE_DEVICE_IS_PLUGGED: This symbol controls - * the locking of the driver. If non-zero, the driver counts the - * probe() call as usage and increments module usage counter; this - * effectively prevents removal of the module (with rmmod) until the - * device is unplugged (then disconnect() callback reduces the module - * usage counter back, and module can be removed). - * - * This behavior may be useful if you prefer to lock the driver in - * memory until device is unplugged. However you can't reload the - * driver if you want to alter some parameters - you'd need to unplug - * the camera first. Therefore, I recommend setting 0. - */ -#define IBMCAM_LOCKS_DRIVER_WHILE_DEVICE_IS_PLUGGED 0 - #define ENABLE_HEXDUMP 0 /* Enable if you need it */ static int debug = 0; @@ -2346,6 +2347,7 @@ static int ibmcam_new_frame(struct usb_ibmcam *ibmcam, int framenum) * camera is also initialized here (once per connect), at * expense of V4L client (it waits on open() call). * 1/27/00 Used IBMCAM_NUMSBUF as number of URB buffers. + * 5/24/00 Corrected to prevent race condition (MOD_xxx_USE_COUNT). */ static int ibmcam_open(struct video_device *dev, int flags) { @@ -2353,6 +2355,7 @@ static int ibmcam_open(struct video_device *dev, int flags) const int sb_size = FRAMES_PER_DESC * ibmcam->iso_packet_len; int i, err = 0; + MOD_INC_USE_COUNT; down(&ibmcam->lock); if (ibmcam->user) @@ -2425,14 +2428,13 @@ static int ibmcam_open(struct video_device *dev, int flags) else err = -EBUSY; } - if (!err) { + if (!err) ibmcam->user++; - MOD_INC_USE_COUNT; - } } } - up(&ibmcam->lock); + if (err) + MOD_DEC_USE_COUNT; return err; } @@ -2446,6 +2448,7 @@ static int ibmcam_open(struct video_device *dev, int flags) * History: * 1/22/00 Moved scratch buffer deallocation here. * 1/27/00 Used IBMCAM_NUMSBUF as number of URB buffers. + * 5/24/00 Moved MOD_DEC_USE_COUNT outside of code that can sleep. */ static void ibmcam_close(struct video_device *dev) { @@ -2462,13 +2465,13 @@ static void ibmcam_close(struct video_device *dev) kfree(ibmcam->sbuf[i].data); ibmcam->user--; - MOD_DEC_USE_COUNT; if (ibmcam->remove_pending) { printk(KERN_INFO "ibmcam_close: Final disconnect.\n"); usb_ibmcam_release(ibmcam); } up(&ibmcam->lock); + MOD_DEC_USE_COUNT; } static int ibmcam_init_done(struct video_device *dev) @@ -2891,7 +2894,7 @@ static void usb_ibmcam_configure_video(struct usb_ibmcam *ibmcam) } /* - * usb_ibmcam_release() + * ibmcam_find_struct() * * This code searches the array of preallocated (static) structures * and returns index of the first one that isn't in use. Returns -1 @@ -2929,6 +2932,7 @@ static int ibmcam_find_struct(void) * History: * 1/22/00 Moved camera init code to ibmcam_open() * 1/27/00 Changed to use static structures, added locking. + * 5/24/00 Corrected to prevent race condition (MOD_xxx_USE_COUNT). */ static void *usb_ibmcam_probe(struct usb_device *dev, unsigned int ifnum) { @@ -2994,10 +2998,14 @@ static void *usb_ibmcam_probe(struct usb_device *dev, unsigned int ifnum) RESTRICT_TO_RANGE(videosize, VIDEOSIZE_176x144, VIDEOSIZE_352x240); } + /* Code below may sleep, need to lock module while we are here */ + MOD_INC_USE_COUNT; + devnum = ibmcam_find_struct(); if (devnum == -1) { printk(KERN_INFO "IBM USB camera driver: Too many devices!\n"); - return NULL; + ibmcam = NULL; /* Do not free, it's preallocated */ + goto probe_done; } ibmcam = &cams[devnum]; @@ -3017,17 +3025,14 @@ static void *usb_ibmcam_probe(struct usb_device *dev, unsigned int ifnum) usb_ibmcam_configure_video(ibmcam); up (&ibmcam->lock); -#if IBMCAM_LOCKS_DRIVER_WHILE_DEVICE_IS_PLUGGED - MOD_INC_USE_COUNT; -#endif - if (video_register_device(&ibmcam->vdev, VFL_TYPE_GRABBER) == -1) { printk(KERN_ERR "video_register_device failed\n"); - return NULL; + ibmcam = NULL; /* Do not free, it's preallocated */ } if (debug > 1) printk(KERN_DEBUG "video_register_device() successful\n"); - +probe_done: + MOD_DEC_USE_COUNT; return ibmcam; } @@ -3055,17 +3060,26 @@ static void usb_ibmcam_release(struct usb_ibmcam *ibmcam) * structure (pointed by 'ptr') and after that driver should be removable * with no ill consequences. * - * TODO: This code behaves badly on surprise removal! + * This code handles surprise removal. The ibmcam->user is a counter which + * increments on open() and decrements on close(). If we see here that + * this counter is not 0 then we have a client who still has us opened. + * We set ibmcam->remove_pending flag as early as possible, and after that + * all access to the camera will gracefully fail. These failures should + * prompt client to (eventually) close the video device, and then - in + * ibmcam_close() - we decrement ibmcam->ibmcam_used and usage counter. * * History: * 1/22/00 Added polling of MOD_IN_USE to delay removal until all users gone. * 1/27/00 Reworked to allow pending disconnects; see ibmcam_close() + * 5/24/00 Corrected to prevent race condition (MOD_xxx_USE_COUNT). */ static void usb_ibmcam_disconnect(struct usb_device *dev, void *ptr) { static const char proc[] = "usb_ibmcam_disconnect"; struct usb_ibmcam *ibmcam = (struct usb_ibmcam *) ptr; + MOD_INC_USE_COUNT; + if (debug > 0) printk(KERN_DEBUG "%s(%p,%p.)\n", proc, dev, ptr); @@ -3077,16 +3091,14 @@ static void usb_ibmcam_disconnect(struct usb_device *dev, void *ptr) ibmcam->dev = NULL; /* USB device is no more */ -#if IBMCAM_LOCKS_DRIVER_WHILE_DEVICE_IS_PLUGGED - MOD_DEC_USE_COUNT; -#endif if (ibmcam->user) printk(KERN_INFO "%s: In use, disconnect pending.\n", proc); else usb_ibmcam_release(ibmcam); up(&ibmcam->lock); - printk(KERN_INFO "IBM USB camera disconnected.\n"); + + MOD_DEC_USE_COUNT; } static struct usb_driver ibmcam_driver = { diff --git a/drivers/usb/ov511.c b/drivers/usb/ov511.c index e97410c32ecd..73a54a7b2039 100644 --- a/drivers/usb/ov511.c +++ b/drivers/usb/ov511.c @@ -30,7 +30,7 @@ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -static const char version[] = "1.14"; +static const char version[] = "1.15"; #define __NO_VERSION__ @@ -263,9 +263,10 @@ static void rvfree(void *mem, unsigned long size) * Based on the CPiA driver version 0.7.4 -claudio **********************************************************************/ -#ifdef CONFIG_PROC_FS +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) + static struct proc_dir_entry *ov511_proc_entry = NULL; -static struct proc_dir_entry *video_proc_entry = NULL; +extern struct proc_dir_entry *video_proc_entry; #define YES_NO(x) ((x) ? "yes" : "no") @@ -343,6 +344,7 @@ static int ov511_read_proc(char *page, char **start, off_t off, len = count; *start = page + off; + return len; } @@ -357,12 +359,11 @@ static void create_proc_ov511_cam (struct usb_ov511 *ov511) char name[7]; struct proc_dir_entry *ent; - PDEBUG (4, "creating /proc/video/ov511/videoX entry"); if (!ov511_proc_entry || !ov511) return; sprintf(name, "video%d", ov511->vdev.minor); - PDEBUG (4, "creating %s", name); + PDEBUG (4, "creating /proc/video/ov511/%s", name); ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, ov511_proc_entry); @@ -372,7 +373,6 @@ static void create_proc_ov511_cam (struct usb_ov511 *ov511) ent->data = ov511; ent->read_proc = ov511_read_proc; ent->write_proc = ov511_write_proc; - ent->size = 3626; /* FIXME */ ov511->proc_entry = ent; } @@ -391,22 +391,13 @@ static void destroy_proc_ov511_cam (struct usb_ov511 *ov511) static void proc_ov511_create(void) { - struct proc_dir_entry *p = NULL; - /* No current standard here. Alan prefers /proc/video/ as it keeps * /proc "less cluttered than /proc/randomcardifoundintheshed/" * -claudio */ - PDEBUG (3, "creating /proc/video"); - video_proc_entry = proc_mkdir("video", p); - if (!video_proc_entry) { - if (!p) { - err("Unable to initialise /proc/video\n"); - return; - } else { /* FIXME - this doesn't work */ - PDEBUG (3, "/proc/video already exists"); - video_proc_entry = p; - } + if (video_proc_entry == NULL) { + err("Unable to initialise /proc/video/ov511"); + return; } ov511_proc_entry = create_proc_entry("ov511", S_IFDIR, video_proc_entry); @@ -414,16 +405,19 @@ static void proc_ov511_create(void) if (ov511_proc_entry) ov511_proc_entry->owner = THIS_MODULE; else - err("Unable to initialise /proc/video/ov511\n"); + err("Unable to initialise /proc/ov511"); } static void proc_ov511_destroy(void) { PDEBUG (3, "removing /proc/video/ov511"); + + if (ov511_proc_entry == NULL) + return; + remove_proc_entry("ov511", video_proc_entry); - remove_proc_entry("video", NULL); } -#endif /* CONFIG_PROC_FS */ +#endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */ /********************************************************************** @@ -852,7 +846,7 @@ ov7610_get_picture(struct usb_ov511 *ov511, struct video_picture *p) return 0; } -/* FIXME: add 176x144, 160x140 */ +/* FIXME: add 400x300, 176x144, 160x140 */ static struct mode_list mlist[] = { { 640, 480, VIDEO_PALETTE_GREY, 0x4f, 0x3d, 0x00, 0x00, 0x4f, 0x3d, 0x00, 0x00, 0x04, 0x03, 0x24, 0x04, 0x9e }, @@ -866,6 +860,14 @@ static struct mode_list mlist[] = { 0x2b, 0x25, 0x00, 0x00, 0x01, 0x03, 0x04, 0x04, 0x1e }, { 352, 288, VIDEO_PALETTE_RGB24,0x2b, 0x25, 0x00, 0x00, 0x2b, 0x25, 0x00, 0x00, 0x01, 0x03, 0x04, 0x04, 0x1e }, + { 384, 288, VIDEO_PALETTE_GREY, 0x2f, 0x25, 0x00, 0x00, + 0x2f, 0x25, 0x00, 0x00, 0x01, 0x03, 0x04, 0x04, 0x1e }, + { 384, 288, VIDEO_PALETTE_RGB24,0x2f, 0x25, 0x00, 0x00, + 0x2f, 0x25, 0x00, 0x00, 0x01, 0x03, 0x04, 0x04, 0x1e }, + { 448, 336, VIDEO_PALETTE_GREY, 0x37, 0x29, 0x00, 0x00, + 0x37, 0x29, 0x00, 0x00, 0x01, 0x03, 0x04, 0x04, 0x1e }, + { 448, 336, VIDEO_PALETTE_RGB24,0x37, 0x29, 0x00, 0x00, + 0x37, 0x29, 0x00, 0x00, 0x01, 0x03, 0x04, 0x04, 0x1e }, { 0, 0 } }; @@ -1302,158 +1304,190 @@ static int ov511_move_data(struct usb_ov511 *ov511, urb_t *urb) int i, totlen = 0; int aPackNum[10]; struct ov511_frame *frame; + unsigned char *pData; + int iPix; - PDEBUG(4, "ov511_move_data"); + PDEBUG (4, "Moving %d packets", urb->number_of_packets); for (i = 0; i < urb->number_of_packets; i++) { int n = urb->iso_frame_desc[i].actual_length; int st = urb->iso_frame_desc[i].status; + urb->iso_frame_desc[i].actual_length = 0; urb->iso_frame_desc[i].status = 0; + cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset; aPackNum[i] = n ? cdata[ov511->packet_size - 1] : -1; - if (!n || ov511->curframe == -1) continue; + if (!n || ov511->curframe == -1) + continue; if (st) PDEBUG(2, "data error: [%d] len=%d, status=%d", i, n, st); frame = &ov511->frame[ov511->curframe]; - /* Can we find a frame end */ + /* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th + * byte non-zero. The EOF packet has image width/height in the + * 10th and 11th packets. The 9th bit is given as follows: + * + * bit 7: EOF + * 6: compression enabled + * 5: 422/420/400 modes + * 4: 422/420/400 modes + * 3: 1 + * 2: snapshot bottom on + * 1: snapshot frame + * 0: even/odd field + */ + + /* Check for SOF/EOF packet */ if ((cdata[0] | cdata[1] | cdata[2] | cdata[3] | - cdata[4] | cdata[5] | cdata[6] | cdata[7]) == 0 && - (cdata[8] & 8) && (cdata[8] & 0x80)) { + cdata[4] | cdata[5] | cdata[6] | cdata[7]) || + (~cdata[8] & 0x08)) + goto check_middle; + + /* Frame end */ + if (cdata[8] & 0x80) { +#if 0 + struct timeval *ts; + + ts = (struct timeval *)(frame->data + MAX_FRAME_SIZE); + do_gettimeofday (ts); +#endif - struct timeval *ts; - ts = (struct timeval *)(frame->data + MAX_FRAME_SIZE); - do_gettimeofday(ts); + PDEBUG(4, "Frame end, curframe = %d, packnum=%d, hw=%d, vw=%d", + ov511->curframe, (int)(cdata[ov511->packet_size - 1]), + (int)(cdata[9]), (int)(cdata[10])); - PDEBUG(4, "Frame End, curframe = %d, packnum=%d, hw=%d, vw=%d", - ov511->curframe, (int)(cdata[ov511->packet_size - 1]), - (int)(cdata[9]), (int)(cdata[10])); + if (frame->scanstate == STATE_LINES) { + int iFrameNext; - if (frame->scanstate == STATE_LINES) { - int iFrameNext; if (fix_rgb_offset) fixFrameRGBoffset(frame); frame->grabstate = FRAME_DONE; - if (waitqueue_active(&frame->wq)) { - frame->grabstate = FRAME_DONE; - wake_up_interruptible(&frame->wq); + + if (waitqueue_active(&frame->wq)) { + frame->grabstate = FRAME_DONE; + wake_up_interruptible(&frame->wq); } - /* If next frame is ready or grabbing, point to it */ + + /* If next frame is ready or grabbing, + * point to it */ iFrameNext = (ov511->curframe + 1) % OV511_NUMFRAMES; - if (ov511->frame[iFrameNext].grabstate== FRAME_READY || - ov511->frame[iFrameNext].grabstate== FRAME_GRABBING) { - ov511->curframe = iFrameNext; - ov511->frame[iFrameNext].scanstate = STATE_SCANNING; + if (ov511->frame[iFrameNext].grabstate == FRAME_READY + || ov511->frame[iFrameNext].grabstate == FRAME_GRABBING) { + ov511->curframe = iFrameNext; + ov511->frame[iFrameNext].scanstate = STATE_SCANNING; } else { - - PDEBUG(4, "Frame not ready? state = %d", - ov511->frame[iFrameNext].grabstate); - - ov511->curframe = -1; + if (frame->grabstate == FRAME_DONE) { + PDEBUG(4, "Frame done! congratulations"); + } else { + PDEBUG(4, "Frame not ready? state = %d", + ov511->frame[iFrameNext].grabstate); + } + + ov511->curframe = -1; } - } - } - - /* Can we find a frame start */ - else if ((cdata[0] | cdata[1] | cdata[2] | cdata[3] | - cdata[4] | cdata[5] | cdata[6] | cdata[7]) == 0 && - (cdata[8] & 8)) { - - PDEBUG(4, "ov511: Found Frame Start!, framenum = %d", - ov511->curframe); + } + /* Image corruption caused by misplaced frame->segment = 0 + * fixed by carlosf@conectiva.com.br + */ + } else { + /* Frame start */ + PDEBUG(4, "Frame start, framenum = %d", ov511->curframe); /* Check to see if it's a snapshot frame */ /* FIXME?? Should the snapshot reset go here? Performance? */ if (cdata[8] & 0x02) { frame->snapshot = 1; - PDEBUG(3, "ov511_move_data: snapshot detected"); + PDEBUG(3, "snapshot detected"); } frame->scanstate = STATE_LINES; frame->segment = 0; } +check_middle: /* Are we in a frame? */ - if (frame->scanstate == STATE_LINES) { - unsigned char * pData; - int iPix; - - /* Deal with leftover from last segment, if any */ - if (frame->segment) { - pData = ov511->scratch; - iPix = - ov511->scratchlen; - memmove(pData + ov511->scratchlen, cdata, - iPix+frame->segsize); - } else { - pData = &cdata[iPix = 9]; - } - - /* Parse the segments */ - while(iPix <= (ov511->packet_size - 1) - frame->segsize && - frame->segment < frame->width * frame->height / 256) { - int iSegY; - int iSegUV; - int iY, jY, iUV, jUV; - int iOutY, iOutUV; - unsigned char * pOut; - - iSegY = iSegUV = frame->segment; - pOut = frame->data; - - frame->segment++; - iPix += frame->segsize; - - if (frame->sub_flag) { - int iSeg1; - iSeg1 = iSegY / (ov511->subw / 32); - iSeg1 *= frame->width / 32; - iSegY = iSeg1 + (iSegY % (ov511->subw / 32)); - if (iSegY >= frame->width * ov511->subh / 256) - break; - - iSeg1 = iSegUV / (ov511->subw / 16); - iSeg1 *= frame->width / 16; - iSegUV = iSeg1 + (iSegUV % (ov511->subw / 16)); - - pOut += (ov511->subx + - ov511->suby * frame->width) * frame->depth; - } - - iY = iSegY / (frame->width / WDIV); - jY = iSegY - iY * (frame->width / WDIV); - iOutY = (iY*HDIV*frame->width + jY*WDIV) * frame->depth; - iUV = iSegUV / (frame->width / WDIV * 2); - jUV = iSegUV - iUV * (frame->width / WDIV * 2); - iOutUV = (iUV*HDIV*2*frame->width + jUV*WDIV/2) * frame->depth; - - if (frame->format == VIDEO_PALETTE_GREY) { - ov511_parse_data_grey(pData, pOut, iOutY, frame->width); - } else if (frame->format == VIDEO_PALETTE_RGB24) { - ov511_parse_data_rgb24(pData, pOut, iOutY, iOutUV, iY & 1, - frame->width); - } - pData = &cdata[iPix]; - } + if (frame->scanstate != STATE_LINES) + continue; - /* Save extra data for next time */ - if (frame->segment < frame->width * frame->height / 256) { - ov511->scratchlen = (ov511->packet_size - 1) - iPix; - if (ov511->scratchlen < frame->segsize) { - memmove(ov511->scratch, pData, ov511->scratchlen); - } else { - ov511->scratchlen = 0; - } + /* Deal with leftover from last segment, if any */ + if (frame->segment) { + pData = ov511->scratch; + iPix = -ov511->scratchlen; + memmove(pData + ov511->scratchlen, cdata, + iPix+frame->segsize); + } else { + pData = &cdata[iPix = 9]; + } + + /* Parse the segments */ + while (iPix <= (ov511->packet_size - 1) - frame->segsize && + frame->segment < frame->width * frame->height / 256) { + int iSegY, iSegUV; + int iY, jY, iUV, jUV; + int iOutY, iOutUV; + unsigned char *pOut; + + iSegY = iSegUV = frame->segment; + pOut = frame->data; + frame->segment++; + iPix += frame->segsize; + + /* Handle subwindow */ + if (frame->sub_flag) { + int iSeg1; + + iSeg1 = iSegY / (ov511->subw / 32); + iSeg1 *= frame->width / 32; + iSegY = iSeg1 + (iSegY % (ov511->subw / 32)); + if (iSegY >= frame->width * ov511->subh / 256) + break; + + iSeg1 = iSegUV / (ov511->subw / 16); + iSeg1 *= frame->width / 16; + iSegUV = iSeg1 + (iSegUV % (ov511->subw / 16)); + + pOut += (ov511->subx + ov511->suby * frame->width) * + (frame->depth >> 3); } + + /* + * iY counts segment lines + * jY counts segment columns + * iOutY is the offset (in bytes) of the segment upper left corner + */ + iY = iSegY / (frame->width / WDIV); + jY = iSegY - iY * (frame->width / WDIV); + iOutY = (iY*HDIV*frame->width + jY*WDIV) * (frame->depth >> 3); + iUV = iSegUV / (frame->width / WDIV * 2); + jUV = iSegUV - iUV * (frame->width / WDIV * 2); + iOutUV = (iUV*HDIV*2*frame->width + jUV*WDIV/2) * (frame->depth >> 3); + + if (frame->format == VIDEO_PALETTE_GREY) + ov511_parse_data_grey (pData, pOut, iOutY, frame->width); + else if (frame->format == VIDEO_PALETTE_RGB24) + ov511_parse_data_rgb24 (pData, pOut, iOutY, iOutUV, + iY & 1, frame->width); + + pData = &cdata[iPix]; } - } + /* Save extra data for next time */ + if (frame->segment < frame->width * frame->height / 256) { + ov511->scratchlen = (ov511->packet_size - 1) - iPix; + if (ov511->scratchlen < frame->segsize) + memmove(ov511->scratch, pData, + ov511->scratchlen); + else + ov511->scratchlen = 0; + } + } - PDEBUG(5, "pn: %d %d %d %d %d %d %d %d %d %d\n", + PDEBUG(5, "pn: %d %d %d %d %d %d %d %d %d %d", aPackNum[0], aPackNum[1], aPackNum[2], aPackNum[3], aPackNum[4], aPackNum[5],aPackNum[6], aPackNum[7], aPackNum[8], aPackNum[9]); @@ -1472,8 +1506,6 @@ static void ov511_isoc_irq(struct urb *urb) if (!ov511->streaming) { PDEBUG(2, "hmmm... not streaming, but got interrupt"); return; - } else { - PDEBUG(5, "streaming. got interrupt"); } sbuf = &ov511->sbuf[ov511->cursbuf]; @@ -1723,7 +1755,7 @@ static void ov511_close(struct video_device *dev) static int ov511_init_done(struct video_device *dev) { -#ifdef CONFIG_PROC_FS +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) create_proc_ov511_cam((struct usb_ov511 *)dev); #endif @@ -1749,6 +1781,8 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg) { struct video_capability b; + PDEBUG (4, "VIDIOCGCAP"); + strcpy(b.name, "OV511 USB Camera"); b.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE; b.channels = 1; @@ -1798,6 +1832,8 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg) { struct video_picture p; + PDEBUG (4, "VIDIOCGPICT"); + if (ov7610_get_picture(ov511, &p)) return -EIO; @@ -1809,18 +1845,33 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg) case VIDIOCSPICT: { struct video_picture p; + int i; + + PDEBUG (4, "VIDIOCSPICT"); if (copy_from_user(&p, arg, sizeof(p))) return -EFAULT; - + if (ov7610_set_picture(ov511, &p)) return -EIO; + /* FIXME: check validity */ + + PDEBUG(4, "Setting depth=%d, palette=%d", p.depth, p.palette); + for (i = 0; i < OV511_NUMFRAMES; i++) { + ov511->frame[i].depth = p.depth; + ov511->frame[i].format = p.palette; + ov511->frame[i].segsize = GET_SEGSIZE(p.palette); + } + return 0; } case VIDIOCGCAPTURE: { int vf; + + PDEBUG (4, "VIDIOCGCAPTURE"); + if (copy_from_user(&vf, arg, sizeof(vf))) return -EFAULT; ov511->sub_flag = vf; @@ -1836,16 +1887,25 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg) return -EINVAL; if (vc.decimation) return -EINVAL; +#if 0 vc.x /= 4; vc.x *= 4; vc.y /= 2; vc.y *= 2; vc.width /= 32; vc.width *= 32; - if (vc.width == 0) vc.width = 32; +#else + vc.x &= ~3L; + vc.y &= ~1L; + vc.y &= ~31L; +#endif + if (vc.width == 0) + vc.width = 32; + vc.height /= 16; vc.height *= 16; - if (vc.height == 0) vc.height = 16; + if (vc.height == 0) + vc.height = 16; ov511->subx = vc.x; ov511->suby = vc.y; @@ -1857,9 +1917,15 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg) case VIDIOCSWIN: { struct video_window vw; + int i, result; if (copy_from_user(&vw, arg, sizeof(vw))) return -EFAULT; + + PDEBUG (4, "VIDIOCSWIN: width=%d, height=%d", + vw.width, vw.height); + +#if 0 if (vw.flags) return -EINVAL; if (vw.clipcount) @@ -1868,8 +1934,22 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg) return -EINVAL; if (vw.width != DEFAULT_WIDTH) return -EINVAL; +#endif + + /* If we're collecting previous frame wait + before changing modes */ + interruptible_sleep_on(&ov511->wq); + if (signal_pending(current)) return -EINTR; - ov511->compress = 0; + result = ov511_mode_init_regs(ov511, vw.width, vw.height, + ov511->frame[0].format, ov511->sub_flag); + if (result < 0) + return result; + + for (i = 0; i < OV511_NUMFRAMES; i++) { + ov511->frame[i].width = vw.width; + ov511->frame[i].height = vw.height; + } return 0; } @@ -1877,13 +1957,15 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg) { struct video_window vw; - vw.x = 0; + vw.x = 0; /* FIXME */ vw.y = 0; - vw.width = DEFAULT_WIDTH; - vw.height = DEFAULT_HEIGHT; + vw.width = ov511->frame[0].width; + vw.height = ov511->frame[0].height; vw.chromakey = 0; vw.flags = 30; + PDEBUG (4, "VIDIOCGWIN: %dx%d", vw.width, vw.height); + if (copy_to_user(arg, &vw, sizeof(vw))) return -EFAULT; @@ -1935,19 +2017,16 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg) before changing modes */ interruptible_sleep_on(&ov511->wq); if (signal_pending(current)) return -EINTR; - ov511_mode_init_regs(ov511, - vm.width, vm.height, - vm.format, ov511->sub_flag); + ov511_mode_init_regs(ov511, vm.width, vm.height, + vm.format, ov511->sub_flag); } ov511->frame[vm.frame].width = vm.width; ov511->frame[vm.frame].height = vm.height; ov511->frame[vm.frame].format = vm.format; ov511->frame[vm.frame].sub_flag = ov511->sub_flag; - ov511->frame[vm.frame].segsize = - vm.format == VIDEO_PALETTE_RGB24 ? 384 : 256; - ov511->frame[vm.frame].depth = - vm.format == VIDEO_PALETTE_RGB24 ? 3 : 1; + ov511->frame[vm.frame].segsize = GET_SEGSIZE(vm.format); + ov511->frame[vm.frame].depth = GET_DEPTH(vm.format); /* Mark it as ready */ ov511->frame[vm.frame].grabstate = FRAME_READY; @@ -1965,11 +2044,11 @@ static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg) ov511->frame[frame].grabstate); switch (ov511->frame[frame].grabstate) { - case FRAME_UNUSED: - return -EINVAL; - case FRAME_READY: - case FRAME_GRABBING: - case FRAME_ERROR: + case FRAME_UNUSED: + return -EINVAL; + case FRAME_READY: + case FRAME_GRABBING: + case FRAME_ERROR: redo: if (!ov511->dev) return -EIO; @@ -1989,23 +2068,21 @@ redo: if ((ret = ov511_new_frame(ov511, frame)) < 0) return ret; goto redo; - } - case FRAME_DONE: - ov511->frame[frame].grabstate = FRAME_UNUSED; - break; - } - - ov511->frame[frame].grabstate = FRAME_UNUSED; - - /* Reset the hardware snapshot button */ - /* FIXME - Is this the best place for this? */ - if ((ov511->snap_enabled) && - (ov511->frame[frame].snapshot)) { - ov511->frame[frame].snapshot = 0; - ov511_reg_write(ov511->dev, 0x52, 0x01); - ov511_reg_write(ov511->dev, 0x52, 0x03); - ov511_reg_write(ov511->dev, 0x52, 0x01); - } + } + case FRAME_DONE: + ov511->frame[frame].grabstate = FRAME_UNUSED; + + /* Reset the hardware snapshot button */ + /* FIXME - Is this the best place for this? */ + if ((ov511->snap_enabled) && + (ov511->frame[frame].snapshot)) { + ov511->frame[frame].snapshot = 0; + ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x01); + ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x03); + ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x01); + } + break; + } /* end switch */ return 0; } @@ -2038,7 +2115,7 @@ redo: return -EINVAL; default: return -ENOIOCTLCMD; - } /* End switch(cmd) */ + } /* end switch */ return 0; } @@ -2610,7 +2687,7 @@ static void ov511_disconnect(struct usb_device *dev, void *ptr) ov511->sbuf[0].urb = NULL; } -#ifdef CONFIG_PROC_FS +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) destroy_proc_ov511_cam(ov511); #endif @@ -2637,8 +2714,7 @@ static struct usb_driver ov511_driver = { static int __init usb_ov511_init(void) { -#ifdef CONFIG_PROC_FS - PDEBUG(3, "creating /proc/ov511"); +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) proc_ov511_create(); #endif @@ -2655,7 +2731,7 @@ static void __exit usb_ov511_exit(void) usb_deregister(&ov511_driver); info("ov511 driver deregistered"); -#ifdef CONFIG_PROC_FS +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) proc_ov511_destroy(); #endif } diff --git a/fs/nfs/flushd.c b/fs/nfs/flushd.c index 460d4eba965e..02024c90e4a9 100644 --- a/fs/nfs/flushd.c +++ b/fs/nfs/flushd.c @@ -136,6 +136,7 @@ int nfs_reqlist_alloc(struct nfs_server *server) return -ENOMEM; memset(cache, 0, sizeof(*cache)); + atomic_set(&cache->nr_requests, 0); init_waitqueue_head(&cache->request_wait); server->rw_requests = cache; @@ -280,7 +281,7 @@ nfs_flushd(struct rpc_task *task) cache->runat = jiffies + task->tk_timeout; spin_lock(&nfs_flushd_lock); - if (!cache->nr_requests && !cache->inodes) { + if (!atomic_read(&cache->nr_requests) && !cache->inodes) { cache->task = NULL; task->tk_action = NULL; } else diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 44e3030c3814..cf0ea6ef34cb 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -417,6 +417,8 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent) if (data->wsize == 0) server->wsize = nfs_block_size(fsinfo.wtpref, NULL); server->dtsize = nfs_block_size(fsinfo.dtpref, NULL); + if (server->dtsize > PAGE_CACHE_SIZE) + server->dtsize = PAGE_CACHE_SIZE; /* NFSv3: we don't have bsize, but rather rtmult and wtmult... */ if (!fsinfo.bsize) fsinfo.bsize = (fsinfo.rtmult>fsinfo.wtmult) ? fsinfo.rtmult : fsinfo.wtmult; diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 464776ac3c68..cb97c40bc4a6 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -68,7 +68,7 @@ * Spinlock */ spinlock_t nfs_wreq_lock = SPIN_LOCK_UNLOCKED; -static unsigned int nfs_nr_requests = 0; +static atomic_t nfs_nr_requests = ATOMIC_INIT(0); /* * Local structures @@ -490,9 +490,9 @@ struct nfs_page *nfs_create_request(struct file *file, struct page *page, */ do { /* If we're over the global soft limit, wake up all requests */ - if (nfs_nr_requests >= MAX_REQUEST_SOFT) { + if (atomic_read(&nfs_nr_requests) >= MAX_REQUEST_SOFT) { dprintk("NFS: hit soft limit (%d requests)\n", - nfs_nr_requests); + atomic_read(&nfs_nr_requests)); if (!cache->task) nfs_reqlist_init(NFS_SERVER(inode)); nfs_wake_flushd(); @@ -500,7 +500,7 @@ struct nfs_page *nfs_create_request(struct file *file, struct page *page, /* If we haven't reached the local hard limit yet, * try to allocate the request struct */ - if (cache->nr_requests < MAX_REQUEST_HARD) { + if (atomic_read(&cache->nr_requests) < MAX_REQUEST_HARD) { req = nfs_page_alloc(); if (req != NULL) break; @@ -508,7 +508,7 @@ struct nfs_page *nfs_create_request(struct file *file, struct page *page, /* We're over the hard limit. Wait for better times */ dprintk("NFS: create_request sleeping (total %d pid %d)\n", - cache->nr_requests, current->pid); + atomic_read(&cache->nr_requests), current->pid); timeout = 1 * HZ; if (NFS_SERVER(inode)->flags & NFS_MOUNT_INTR) { @@ -520,7 +520,7 @@ struct nfs_page *nfs_create_request(struct file *file, struct page *page, sleep_on_timeout(&cache->request_wait, timeout); dprintk("NFS: create_request waking up (tot %d pid %d)\n", - cache->nr_requests, current->pid); + atomic_read(&cache->nr_requests), current->pid); } while (!req); if (!req) return NULL; @@ -539,8 +539,8 @@ struct nfs_page *nfs_create_request(struct file *file, struct page *page, req->wb_count = 1; /* register request's existence */ - cache->nr_requests++; - nfs_nr_requests++; + atomic_inc(&cache->nr_requests); + atomic_inc(&nfs_nr_requests); return req; } @@ -580,9 +580,15 @@ nfs_release_request(struct nfs_page *req) page_cache_release(page); nfs_page_free(req); /* wake up anyone waiting to allocate a request */ - cache->nr_requests--; - nfs_nr_requests--; + atomic_dec(&cache->nr_requests); + atomic_dec(&nfs_nr_requests); wake_up(&cache->request_wait); +#ifdef NFS_PARANOIA + if (atomic_read(&cache->nr_requests) < 0) + BUG(); + if (atomic_read(&nfs_nr_requests) < 0) + BUG(); +#endif } /* @@ -931,7 +937,7 @@ nfs_strategy(struct inode *inode) if (dirty >= wpages) nfs_flush_file(inode, NULL, 0, 0, 0); if (inode->u.nfs_i.ncommit > NFS_STRATEGY_PAGES * wpages && - nfs_nr_requests > MAX_REQUEST_SOFT) + atomic_read(&nfs_nr_requests) > MAX_REQUEST_SOFT) nfs_commit_file(inode, NULL, 0, 0, 0); } #else diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c index c47830ff30a1..c5c8b0a917b8 100644 --- a/fs/nfsd/nfscache.c +++ b/fs/nfsd/nfscache.c @@ -98,6 +98,8 @@ void nfsd_cache_shutdown(void) { struct svc_cacherep *rp; + size_t i; + unsigned long order; if (!cache_initialized) return; @@ -110,7 +112,10 @@ nfsd_cache_shutdown(void) cache_initialized = 0; cache_disabled = 1; - kfree (nfscache); + i = CACHESIZE * sizeof (struct svc_cacherep); + for (order = 0; (PAGE_SIZE << order) < i; order++) + ; + free_pages ((unsigned long)nfscache, order); nfscache = NULL; kfree (hash_list); hash_list = NULL; diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c index 886e2f4c0bd6..53386a08d42b 100644 --- a/fs/partitions/msdos.c +++ b/fs/partitions/msdos.c @@ -27,9 +27,9 @@ #include #include -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) +#ifdef CONFIG_BLK_DEV_IDE #include /* IDE xlate */ -#endif /* (CONFIG_BLK_DEV_IDE) || (CONFIG_BLK_DEV_HD) */ +#endif /* CONFIG_BLK_DEV_IDE */ #include @@ -350,19 +350,19 @@ int msdos_partition(struct gendisk *hd, kdev_t dev, unsigned char *data; int mask = (1 << hd->minor_shift) - 1; int sector_size = get_hardsect_size(dev) / 512; -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) +#ifdef CONFIG_BLK_DEV_IDE int tested_for_xlate = 0; read_mbr: -#endif /* (CONFIG_BLK_DEV_IDE) || (CONFIG_BLK_DEV_HD) */ +#endif /* CONFIG_BLK_DEV_IDE */ if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) { if (warn_no_part) printk(" unable to read partition table\n"); return -1; } data = bh->b_data; -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) +#ifdef CONFIG_BLK_DEV_IDE check_table: -#endif /* (CONFIG_BLK_DEV_IDE) || (CONFIG_BLK_DEV_HD) */ +#endif /* CONFIG_BLK_DEV_IDE */ /* Use bforget(), because we may have changed the disk geometry */ if (*(unsigned short *) (0x1fe + data) != cpu_to_le16(MSDOS_LABEL_MAGIC)) { bforget(bh); @@ -370,7 +370,7 @@ check_table: } p = (struct partition *) (0x1be + data); -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) +#ifdef CONFIG_BLK_DEV_IDE if (!tested_for_xlate++) { /* Do this only once per disk */ /* * Look for various forms of IDE disk geometry translation @@ -426,7 +426,7 @@ check_table: (void) ide_xlate_1024(dev, 2, heads, " [PTBL]"); } } -#endif /* (CONFIG_BLK_DEV_IDE) || (CONFIG_BLK_DEV_HD) */ +#endif /* CONFIG_BLK_DEV_IDE */ /* Look for partitions in two passes: First find the primary partitions, and the DOS-type extended partitions. diff --git a/fs/super.c b/fs/super.c index f1d873331056..5b8974e5b0ef 100644 --- a/fs/super.c +++ b/fs/super.c @@ -1167,7 +1167,8 @@ static int copy_mount_options (const void *data, unsigned long *where) { int i; unsigned long page; - + unsigned long size; + *where = 0; if (!data) return 0; @@ -1179,13 +1180,18 @@ static int copy_mount_options (const void *data, unsigned long *where) * gave us is valid. Just in case, we'll zero * the remainder of the page. */ - i = copy_from_user((void *)page, data, PAGE_SIZE); - if (i == PAGE_SIZE) { + /* copy_from_user cannot cross TASK_SIZE ! */ + size = TASK_SIZE - (unsigned long)data; + if (size > PAGE_SIZE) + size = PAGE_SIZE; + + i = size - copy_from_user((void *)page, data, size); + if (!i) { free_page(page); return -EFAULT; } - if (i) - memset((char *)page + PAGE_SIZE - i, 0, i); + if (i != PAGE_SIZE) + memset((char *)page + i, 0, PAGE_SIZE - i); *where = page; return 0; } diff --git a/fs/ufs/super.c b/fs/ufs/super.c index d9620a1c6ca9..7784203e0f1a 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -55,6 +55,9 @@ * * write support Daniel Pirkl 1998 * + * HP/UX hfs filesystem support added by + * Martin K. Petersen , August 1999 + * */ @@ -279,6 +282,8 @@ static int ufs_parse_options (char * options, unsigned * mount_options) ufs_set_opt (*mount_options, UFSTYPE_OPENSTEP); else if (!strcmp (value, "sunx86")) ufs_set_opt (*mount_options, UFSTYPE_SUNx86); + else if (!strcmp (value, "hp")) + ufs_set_opt (*mount_options, UFSTYPE_HP); else { printk ("UFS-fs: Invalid type option: %s\n", value); return 0; @@ -473,7 +478,7 @@ struct super_block * ufs_read_super (struct super_block * sb, void * data, if (!(sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE)) { printk("You didn't specify the type of your ufs filesystem\n\n" "mount -t ufs -o ufstype=" - "sun|sunx86|44bsd|old|nextstep|netxstep-cd|openstep ...\n\n" + "sun|sunx86|44bsd|old|hp|nextstep|netxstep-cd|openstep ...\n\n" ">>>WARNING<<< Wrong ufstype may corrupt your filesystem, " "default is ufstype=old\n"); ufs_set_opt (sb->u.ufs_sb.s_mount_opt, UFSTYPE_OLD); @@ -573,6 +578,19 @@ struct super_block * ufs_read_super (struct super_block * sb, void * data, } break; + case UFS_MOUNT_UFSTYPE_HP: + UFSD(("ufstype=hp\n")) + uspi->s_fsize = block_size = 1024; + uspi->s_fmask = ~(1024 - 1); + uspi->s_fshift = 10; + uspi->s_sbsize = super_block_size = 2048; + uspi->s_sbbase = 0; + flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; + if (!(sb->s_flags & MS_RDONLY)) { + printk(KERN_INFO "ufstype=hp is supported read-only\n"); + sb->s_flags |= MS_RDONLY; + } + break; default: printk("unknown ufstype\n"); goto failed; @@ -598,18 +616,30 @@ again: #if defined(__LITTLE_ENDIAN) || defined(__BIG_ENDIAN) /* sane bytesex */ switch (usb3->fs_magic) { case UFS_MAGIC: + case UFS_MAGIC_LFN: + case UFS_MAGIC_FEA: + case UFS_MAGIC_4GB: swab = UFS_NATIVE_ENDIAN; goto magic_found; case UFS_CIGAM: + case UFS_CIGAM_LFN: + case UFS_CIGAM_FEA: + case UFS_CIGAM_4GB: swab = UFS_SWABBED_ENDIAN; goto magic_found; } #else /* bytesex perversion */ switch (le32_to_cpup(&usb3->fs_magic)) { case UFS_MAGIC: + case UFS_MAGIC_LFN: + case UFS_MAGIC_FEA: + case UFS_MAGIC_4GB: swab = UFS_LITTLE_ENDIAN; goto magic_found; case UFS_CIGAM: + case UFS_CIGAM_LFN: + case UFS_CIGAM_FEA: + case UFS_CIGAM_4GB: swab = UFS_BIG_ENDIAN; goto magic_found; } diff --git a/include/asm-alpha/ide.h b/include/asm-alpha/ide.h index f142fc6dc73f..da698627e283 100644 --- a/include/asm-alpha/ide.h +++ b/include/asm-alpha/ide.h @@ -61,6 +61,7 @@ static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, } if (irq != NULL) *irq = 0; + hw->io_ports[IDE_IRQ_OFFSET] = 0; } /* @@ -74,7 +75,6 @@ static __inline__ void ide_init_default_hwifs(void) int index; for (index = 0; index < MAX_HWIFS; index++) { - memset(&hw, 0, sizeof(hw_regs_t)); ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL); hw.irq = ide_default_irq(ide_default_io_base(index)); ide_register_hw(&hw, NULL); diff --git a/include/asm-i386/ide.h b/include/asm-i386/ide.h index 25ec3b594296..6ac787665c0a 100644 --- a/include/asm-i386/ide.h +++ b/include/asm-i386/ide.h @@ -69,6 +69,7 @@ static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, } if (irq != NULL) *irq = 0; + hw->io_ports[IDE_IRQ_OFFSET] = 0; } static __inline__ void ide_init_default_hwifs(void) @@ -78,7 +79,6 @@ static __inline__ void ide_init_default_hwifs(void) int index; for(index = 0; index < MAX_HWIFS; index++) { - memset(&hw, 0, sizeof(hw_regs_t)); ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL); hw.irq = ide_default_irq(ide_default_io_base(index)); ide_register_hw(&hw, NULL); diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h index 41f386716d1e..01f9832dd807 100644 --- a/include/asm-i386/processor.h +++ b/include/asm-i386/processor.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -90,13 +91,15 @@ struct cpuinfo_x86 { #define X86_FEATURE_22 0x00400000 #define X86_FEATURE_MMX 0x00800000 /* multimedia extensions */ #define X86_FEATURE_FXSR 0x01000000 /* FXSAVE and FXRSTOR instructions (fast save and restore of FPU context), and CR4.OSFXSR (OS uses these instructions) available */ -#define X86_FEATURE_25 0x02000000 +#define X86_FEATURE_XMM 0x02000000 /* Intel MMX2 instruction set */ #define X86_FEATURE_26 0x04000000 #define X86_FEATURE_27 0x08000000 #define X86_FEATURE_28 0x10000000 #define X86_FEATURE_29 0x20000000 #define X86_FEATURE_30 0x40000000 #define X86_FEATURE_AMD3D 0x80000000 +#define X86_CR4_OSFXSR 0x0200 /* fast FPU save/restore */ +#define X86_CR4_OSXMMEXCPT 0x0400 /* KNI (MMX2) unmasked exception 16 */ extern struct cpuinfo_x86 boot_cpu_data; extern struct tss_struct init_tss[NR_CPUS]; @@ -240,6 +243,22 @@ extern unsigned int mca_pentium_flag; #define IO_BITMAP_OFFSET offsetof(struct tss_struct,io_bitmap) #define INVALID_IO_BITMAP_OFFSET 0x8000 +#ifndef CONFIG_X86_FX + +#define i387_save_hard(x) \ + __asm__("fnsave %0\n\tfwait": :"m" (x)) +#define i387_restore_hard(x) \ + __asm__("frstor %0": :"m" (x)) + +#define i387_hard_to_user(uaddr, x) \ + __copy_to_user((uaddr), (x), sizeof(struct i387_hard_struct)) +#define i387_user_to_hard(x, uaddr) \ + __copy_from_user((x), (uaddr), sizeof(struct i387_hard_struct)) + +#define i387_set_cwd(x,v) do { (x).cwd = 0xffff0000 | (v); } while (0) +#define i387_set_swd(x,v) do { (x).swd = 0xffff0000 | (v); } while (0) +#define i387_set_twd(x,v) do { (x).twd = 0xffff0000 | (v); } while (0) + struct i387_hard_struct { long cwd; long swd; @@ -252,6 +271,69 @@ struct i387_hard_struct { long status; /* software status information */ }; +#else + +/* + * has to be 128-bit aligned + */ +struct i387_hard_struct { + unsigned short cwd; + unsigned short swd; + unsigned short twd; + unsigned short fopcode; + unsigned int fip; + unsigned short fcs; + unsigned short __reserved_01; + unsigned int fdp; + unsigned short fds; + unsigned short __reserved_02; + unsigned int mxcsr; + unsigned int __reserved_03; + unsigned int st_space[32]; /* 8*16 bytes for each FP/MMX-reg = 128 bytes */ + unsigned int xmm_space[22*4]; /* 22 cachelines for MMX2 registers */ + unsigned long status; +} __attribute__ ((aligned (16))); + +/* + * tag word conversion (thanks to Gabriel Paubert for noticing the + * subtle format difference and implementing these functions) + * + * there are several erratas wrt. the tag word in the i387, thus + * any software relying on it's value is questionable, but we + * definitely want to be as close as possible. + */ +static inline unsigned short fputag_KNIto387(unsigned char tb) { + unsigned short tw = tb; + tw = ((tw<<4) | tw) &0x0f0f; /* zzzz7654zzzz3210 */ + tw = ((tw<<2) | tw) &0x3333; /* zz76zz54zz32zz10 */ + tw = ((tw<<1) | tw) &0x5555; /* z7z6z5z4z3z2z1z0 */ + return ~(tw*3); +} + +static inline unsigned char fputag_387toKNI(unsigned short tw) { + tw = ~tw; + tw = (tw | (tw>>1)) & 0x5555; /* z7z6z5z4z3z2z1z0 */ + tw = (tw | (tw>>1)) & 0x3333; /* zz76zz54zz32zz10 */ + tw = (tw | (tw>>3)) & 0x0f0f; /* zzzz7654zzzz3210 */ + return (tw|(tw>>4)) & 0x00ff; /* zzzzzzzz76543210 */ +} + +#define i387_set_cwd(x,v) do { (x).cwd = (short)(v); } while (0) +#define i387_set_swd(x,v) do { (x).swd = (short)(v); } while (0) +#define i387_set_twd(x,v) do { (x).twd = fputag_387toKNI(v); } while (0) + +#define i387_save_hard(x) \ + { __asm__ __volatile__(".byte 0x0f, 0xae, 0x06": :"S" (&(x))); } while (0) + +#define i387_restore_hard(x) \ +do { __asm__ __volatile__(".byte 0x0f, 0xae, 0x4f, 0x00": :"D" (&(x))); } while(0) + +extern int i387_hard_to_user ( struct _fpstate * user, + struct i387_hard_struct * hard); +extern int i387_user_to_hard (struct i387_hard_struct * hard, + struct _fpstate * user); +#endif + struct i387_soft_struct { long cwd; long swd; @@ -387,7 +469,7 @@ extern void forget_segments(void); * FPU lazy state save handling.. */ #define save_fpu(tsk) do { \ - asm volatile("fnsave %0\n\tfwait":"=m" (tsk->thread.i387)); \ + i387_save_hard(tsk->thread.i387); \ tsk->flags &= ~PF_USEDFPU; \ stts(); \ } while (0) diff --git a/include/asm-i386/sigcontext.h b/include/asm-i386/sigcontext.h index 616fb14158af..424ce8bdce36 100644 --- a/include/asm-i386/sigcontext.h +++ b/include/asm-i386/sigcontext.h @@ -24,6 +24,10 @@ struct _fpstate { datasel; struct _fpreg _st[8]; unsigned long status; +#ifdef CONFIG_X86_FX + unsigned long mxcsr; + unsigned long _xmm[4*22]; +#endif }; struct sigcontext { diff --git a/include/asm-i386/user.h b/include/asm-i386/user.h index b0d067e7af13..2d0849738369 100644 --- a/include/asm-i386/user.h +++ b/include/asm-i386/user.h @@ -36,8 +36,8 @@ struct user_i387_struct { long twd; long fip; long fcs; - long foo; - long fos; + long fdp; + long fds; long st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */ }; diff --git a/include/asm-ia64/ide.h b/include/asm-ia64/ide.h index 1b473c252991..c0fe76856689 100644 --- a/include/asm-ia64/ide.h +++ b/include/asm-ia64/ide.h @@ -74,6 +74,7 @@ ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port } if (irq != NULL) *irq = 0; + hw->io_ports[IDE_IRQ_OFFSET] = 0; } static __inline__ void @@ -84,7 +85,6 @@ ide_init_default_hwifs (void) int index; for(index = 0; index < MAX_HWIFS; index++) { - memset(&hw, 0, sizeof(hw_regs_t)); ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL); hw.irq = ide_default_irq(ide_default_io_base(index)); ide_register_hw(&hw, NULL); diff --git a/include/asm-sh/ide.h b/include/asm-sh/ide.h index ec82befa24a4..cc30fac03d32 100644 --- a/include/asm-sh/ide.h +++ b/include/asm-sh/ide.h @@ -17,7 +17,7 @@ #include #ifndef MAX_HWIFS -#define MAX_HWIFS 1 +#define MAX_HWIFS 1 /* XXX: For my board -- gniibe */ #endif #define ide__sti() __sti() @@ -25,8 +25,8 @@ static __inline__ int ide_default_irq(ide_ioreg_t base) { switch (base) { - case 0x01f0: return 14; - case 0x0170: return 15; + case 0xba0001f0: return 14; + case 0xba000170: return 14; default: return 0; } @@ -36,9 +36,9 @@ static __inline__ ide_ioreg_t ide_default_io_base(int index) { switch (index) { case 0: - return 0x01f0; + return 0xba0001f0; case 1: - return 0x0170; + return 0xba000170; default: return 0; } @@ -60,6 +60,7 @@ static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, } if (irq != NULL) *irq = 0; + hw->io_ports[IDE_IRQ_OFFSET] = 0; } static __inline__ void ide_init_default_hwifs(void) @@ -69,7 +70,6 @@ static __inline__ void ide_init_default_hwifs(void) int index; for(index = 0; index < MAX_HWIFS; index++) { - memset(&hw, 0, sizeof(hw_regs_t)); ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL); hw.irq = ide_default_irq(ide_default_io_base(index)); ide_register_hw(&hw, NULL); diff --git a/include/asm-sparc/ide.h b/include/asm-sparc/ide.h index 79b0e47a1344..aa0bcbfdbd72 100644 --- a/include/asm-sparc/ide.h +++ b/include/asm-sparc/ide.h @@ -52,6 +52,7 @@ static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, } if (irq != NULL) *irq = 0; + hw->io_ports[IDE_IRQ_OFFSET] = 0; } /* @@ -65,7 +66,6 @@ static __inline__ void ide_init_default_hwifs(void) int index; for (index = 0; index < MAX_HWIFS; index++) { - memset(&hw, 0, sizeof(hw_regs_t)); ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL); hw.irq = ide_default_irq(ide_default_io_base(index)); ide_register_hw(&hw, NULL); diff --git a/include/asm-sparc64/ide.h b/include/asm-sparc64/ide.h index 471ee71a055d..71bfa67ca7ce 100644 --- a/include/asm-sparc64/ide.h +++ b/include/asm-sparc64/ide.h @@ -46,6 +46,7 @@ static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, } if (irq != NULL) *irq = 0; + hw->io_ports[IDE_IRQ_OFFSET] = 0; } /* @@ -59,7 +60,6 @@ static __inline__ void ide_init_default_hwifs(void) int index; for (index = 0; index < MAX_HWIFS; index++) { - memset(&hw, 0, sizeof(hw_regs_t)); ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL); hw.irq = ide_default_irq(ide_default_io_base(index)); ide_register_hw(&hw, NULL); diff --git a/include/linux/nfs_flushd.h b/include/linux/nfs_flushd.h index 015a3c032724..ff235df973ea 100644 --- a/include/linux/nfs_flushd.h +++ b/include/linux/nfs_flushd.h @@ -4,6 +4,7 @@ #ifdef __KERNEL__ +#include #include /* @@ -43,7 +44,7 @@ extern void nfs_wake_flushd(void); * This is the per-mount writeback cache. */ struct nfs_reqlist { - unsigned int nr_requests; + atomic_t nr_requests; unsigned long runat; wait_queue_head_t request_wait; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index ff648072eb8b..0c2289c061cf 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -169,6 +169,8 @@ #define PCI_DEVICE_ID_ATI_RAGE128_RL 0x524c #define PCI_DEVICE_ID_ATI_RAGE128_PF 0x5046 #define PCI_DEVICE_ID_ATI_RAGE128_PR 0x5052 +#define PCI_DEVICE_ID_ATI_RAGE128_LE 0x4c45 +#define PCI_DEVICE_ID_ATI_RAGE128_LF 0x4c46 #define PCI_VENDOR_ID_VLSI 0x1004 #define PCI_DEVICE_ID_VLSI_82C592 0x0005 @@ -246,6 +248,7 @@ #define PCI_DEVICE_ID_IBM_TR_WAKE 0x003e #define PCI_DEVICE_ID_IBM_MPIC 0x0046 #define PCI_DEVICE_ID_IBM_3780IDSP 0x007d +#define PCI_DEVICE_ID_IBM_405GP 0x0156 #define PCI_DEVICE_ID_IBM_MPIC_2 0xffff #define PCI_VENDOR_ID_WD 0x101c diff --git a/include/linux/ufs_fs.h b/include/linux/ufs_fs.h index 631791186172..96cb38e67bd6 100644 --- a/include/linux/ufs_fs.h +++ b/include/linux/ufs_fs.h @@ -18,6 +18,10 @@ * Niels Kristian Bech Jensen . * * Write support by Daniel Pirkl + * + * HP/UX hfs filesystem support added by + * Martin K. Petersen , August 1999 + * */ #ifndef __LINUX_UFS_FS_H @@ -38,6 +42,30 @@ #define UFS_MAGIC 0x00011954 #define UFS_CIGAM 0x54190100 /* byteswapped MAGIC */ + +/* HP specific MAGIC values */ + +#define UFS_MAGIC_LFN 0x00095014 /* fs supports filenames > 14 chars */ +#define UFS_CIGAM_LFN 0x14500900 /* srahc 41 < semanelif stroppus sf */ + +#define UFS_MAGIC_SEC 0x00612195 /* B1 security fs */ +#define UFS_CIGAM_SEC 0x95216100 + +#define UFS_MAGIC_FEA 0x00195612 /* fs_featurebits supported */ +#define UFS_CIGAM_FEA 0x12561900 + +#define UFS_MAGIC_4GB 0x05231994 /* fs > 4 GB && fs_featurebits */ +#define UFS_CIGAM_4GB 0x94192305 + +/* Seems somebody at HP goofed here. B1 and lfs are both 0x2 !?! */ +#define UFS_FSF_LFN 0x00000001 /* long file names */ +#define UFS_FSF_B1 0x00000002 /* B1 security */ +#define UFS_FSF_LFS 0x00000002 /* large files */ +#define UFS_FSF_LUID 0x00000004 /* large UIDs */ + +/* End of HP stuff */ + + #define UFS_BSIZE 8192 #define UFS_MINBSIZE 4096 #define UFS_FSIZE 1024 @@ -111,7 +139,7 @@ #define UFS_MOUNT_ONERROR_UMOUNT 0x00000004 #define UFS_MOUNT_ONERROR_REPAIR 0x00000008 -#define UFS_MOUNT_UFSTYPE 0x000007F0 +#define UFS_MOUNT_UFSTYPE 0x00000FF0 #define UFS_MOUNT_UFSTYPE_OLD 0x00000010 #define UFS_MOUNT_UFSTYPE_44BSD 0x00000020 #define UFS_MOUNT_UFSTYPE_SUN 0x00000040 @@ -119,6 +147,7 @@ #define UFS_MOUNT_UFSTYPE_NEXTSTEP_CD 0x00000100 #define UFS_MOUNT_UFSTYPE_OPENSTEP 0x00000200 #define UFS_MOUNT_UFSTYPE_SUNx86 0x00000400 +#define UFS_MOUNT_UFSTYPE_HP 0x00000800 #define ufs_clear_opt(o,opt) o &= ~UFS_MOUNT_##opt #define ufs_set_opt(o,opt) o |= UFS_MOUNT_##opt diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 597d292f5fb1..beeddf7db4a8 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -116,7 +116,6 @@ EXPORT_SYMBOL(kmem_cache_free); EXPORT_SYMBOL(kmalloc); EXPORT_SYMBOL(kfree); EXPORT_SYMBOL(kfree_s); -EXPORT_SYMBOL(vmalloc); EXPORT_SYMBOL(vfree); EXPORT_SYMBOL(__vmalloc); EXPORT_SYMBOL(mem_map); diff --git a/net/ipv6/netfilter/Config.in b/net/ipv6/netfilter/Config.in index 626e1634d0de..3895451ba38c 100644 --- a/net/ipv6/netfilter/Config.in +++ b/net/ipv6/netfilter/Config.in @@ -31,12 +31,12 @@ if [ "$CONFIG_IP6_NF_IPTABLES" != "n" ]; then # The targets dep_tristate ' Packet filtering' CONFIG_IP6_NF_FILTER $CONFIG_IP6_NF_IPTABLES - if [ "$CONFIG_IP6_NF_FILTER" != "n" ]; then +# if [ "$CONFIG_IP6_NF_FILTER" != "n" ]; then # dep_tristate ' REJECT target support' CONFIG_IP6_NF_TARGET_REJECT $CONFIG_IP6_NF_FILTER # if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then # dep_tristate ' MIRROR target support (EXPERIMENTAL)' CONFIG_IP6_NF_TARGET_MIRROR $CONFIG_IP6_NF_FILTER # fi - fi +# fi dep_tristate ' Packet mangling' CONFIG_IP6_NF_MANGLE $CONFIG_IP6_NF_IPTABLES if [ "$CONFIG_IP6_NF_MANGLE" != "n" ]; then diff --git a/scripts/kernel-doc b/scripts/kernel-doc index a5370a1ab418..f58867de76a2 100644 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -316,7 +316,7 @@ sub output_sgml { my $count; my $id; - $id = $args{'module'}."-".$args{'function'}; + $id = "API-".$args{'function'}; $id =~ s/[^A-Za-z0-9]/-/g; print "\n"; diff --git a/scripts/mkdep.c b/scripts/mkdep.c index aa46a07baa93..433fba27c9de 100644 --- a/scripts/mkdep.c +++ b/scripts/mkdep.c @@ -285,8 +285,8 @@ void use_config(const char * name, int len) */ #define MAX2(a,b) ((a)>(b)?(a):(b)) #define MIN2(a,b) ((a)<(b)?(a):(b)) -#define MAX6(a,b,c,d,e,f) (MAX2(a,MAX2(b,MAX2(c,MAX2(d,MAX2(e,f)))))) -#define MIN6(a,b,c,d,e,f) (MIN2(a,MIN2(b,MIN2(c,MIN2(d,MIN2(e,f)))))) +#define MAX5(a,b,c,d,e) (MAX2(a,MAX2(b,MAX2(c,MAX2(d,e))))) +#define MIN5(a,b,c,d,e) (MIN2(a,MIN2(b,MIN2(c,MIN2(d,e))))) @@ -304,7 +304,7 @@ void use_config(const char * name, int len) * About 98% of the CPU time is spent here, and most of that is in * the 'start' paragraph. Because the current characters are * in a register, the start loop usually eats 4 or 8 characters - * per memory read. The MAX6 and MIN6 tests dispose of most + * per memory read. The MAX5 and MIN5 tests dispose of most * input characters with 1 or 2 comparisons. */ void state_machine(const char * map, const char * end) @@ -317,8 +317,8 @@ void state_machine(const char * map, const char * end) start: GETNEXT __start: - if (current > MAX6('/','\'','"','#','C','_')) goto start; - if (current < MIN6('/','\'','"','#','C','_')) goto start; + if (current > MAX5('/','\'','"','#','C')) goto start; + if (current < MIN5('/','\'','"','#','C')) goto start; CASE('/', slash); CASE('\'', squote); CASE('"', dquote); -- 2.39.5