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
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
$(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.tmpl >wanbook.sgml
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:
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
VERSION = 2
-PATCHLEVEL = 3
-SUBLEVEL = 99
-EXTRAVERSION = -pre9
+PATCHLEVEL = 4
+SUBLEVEL = 0
+EXTRAVERSION = -test1
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
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
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
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
#
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
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
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*/
* 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
*/
/*
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.
*/
/* ptrace.c */
/* By Ross Biro 1/23/92 */
+/* FXSAVE/FXRSTOR support by Ingo Molnar and modifications by Goutham Rao */
/* edited by Linus Torvalds */
#include <linux/config.h> /* for CONFIG_MATH_EMULATION */
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);
#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);
* Detection for Celeron coppermine, identify_cpu() overhauled,
* and a few other clean ups.
* Dave Jones <dave@powertweak.com>, April 2000
- *
+ * Pentium-III code by Ingo Molnar and modifications by Goutham Rao
+ *
*/
/*
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)
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:
* 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 <linux/config.h>
{
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)
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;
}
* linux/arch/i386/traps.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
+ * FXSAVE/FXRSTOR support by Ingo Molnar, OS exception support by Goutham Rao
*/
/*
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;
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)
{
__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
{
/*
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);
/*
-# $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
# 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
@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 <linux/config.h>" > tmp.c
- @echo "#undef __SMP__" >> tmp.c
@echo "#undef CONFIG_SMP" >> tmp.c
@echo "#include <linux/sched.h>" >> tmp.c
$(CPP) $(CPPFLAGS) tmp.c -o tmp.i
@echo "/* Automatically generated. Do not edit. */" > check_asm.c
@echo "#include <linux/config.h>" >> check_asm.c
- @echo "#undef __SMP__" >> check_asm.c
@echo "#undef CONFIG_SMP" >> check_asm.c
@echo "#include <linux/sched.h>" >> check_asm.c
@echo 'struct task_struct _task;' >> check_asm.c
$(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
# <hack> 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
$(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
# <hack> 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
-/* $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)
}
#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;
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)
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];
-/* $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)
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);
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);
-/* $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)
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;
}
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
*
* Author: Alan Cox, <alan@redhat.com>
*
- * Fixes:
+ * Fixes: 20000516 Claudio Matsuoka <claudio@conectiva.com>
+ * - Added procfs support
*/
#include <linux/config.h>
static struct video_device *video_device[VIDEO_NUM_DEVICES];
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+
+#include <linux/proc_fs.h>
+
+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
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;
/**
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;
}
}
{
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;
* 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);
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");
}
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
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
IDE_OBJS += icside.o
endif
-ifeq ($(CONFIG_BLK_DEV_IDEDMA),y)
+ifeq ($(CONFIG_BLK_DEV_IDEDMA_PCI),y)
IDE_OBJS += ide-dma.o
endif
#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);
return 0;
}
__setup("hd=", parse_hd_setup);
+
* May be copied or modified under the terms of the GNU General Public License
*/
+#include <linux/config.h>
#define __NO_VERSION__
#include <linux/module.h>
#include <linux/types.h>
{
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,
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;
*/
#include <linux/config.h>
-#ifdef CONFIG_IDE
+#if defined(CONFIG_IDE) && !defined(CONFIG_BLK_DEV_HD)
#include <linux/ide.h>
#include <asm/io.h>
drive->bios_cyl, drive->bios_head, drive->bios_sect);
return ret;
}
-#endif /* CONFIG_IDE */
+#endif /* (CONFIG_IDE) && !(CONFIG_BLK_DEV_HD) */
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.
*/
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;
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) */
}
/*
#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
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 ");
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)
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
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;
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))
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
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);
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;
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;
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:
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);
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));
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;
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;
#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 <linux/stat.h>
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;
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;
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)
{ 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)
{
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);
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)
* 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 <mikael.bouillot@bigfoot.com>
+ * Use pci_module_init
*/
/*****************************************************************************/
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
#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
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;
/* --------------------------------------------------------------------- */
+/* 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
*
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 = {
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)
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)
static int joystick[NR_DEVICE] = { 0, };
static int spdif[NR_DEVICE] = { 0, };
+static int nomix[NR_DEVICE] = { 0, };
static unsigned int devindex = 0;
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");
{ 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)
{
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;
/* 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]);
}
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);
}
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 */
{
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)
* 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
*/
/*****************************************************************************/
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");
}
-#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)
{
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");
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)
{
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;
{ 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)
{
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",
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)
* 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
* 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).
*
*/
__u16 value;
__u16 osschannel; /* number of the OSS channel */
__s16 minval, maxval;
+ __u16 slctunitid;
__u8 unitid;
__u8 selector;
__u8 chnum;
}
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)) {
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;
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,
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;
+}
+
/* --------------------------------------------------------------------- */
/*
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++)
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))
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);
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);
{
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)
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;
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;
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;
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]);
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;
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) {
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) {
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) {
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);
*
* (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 <linux/kernel.h>
#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;
* 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)
{
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)
else
err = -EBUSY;
}
- if (!err) {
+ if (!err)
ibmcam->user++;
- MOD_INC_USE_COUNT;
- }
}
}
-
up(&ibmcam->lock);
+ if (err)
+ MOD_DEC_USE_COUNT;
return err;
}
* 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)
{
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)
}
/*
- * 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
* 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)
{
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];
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;
}
* 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);
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 = {
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-static const char version[] = "1.14";
+static const char version[] = "1.15";
#define __NO_VERSION__
* 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")
len = count;
*start = page + off;
+
return len;
}
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);
ent->data = ov511;
ent->read_proc = ov511_read_proc;
ent->write_proc = ov511_write_proc;
- ent->size = 3626; /* FIXME */
ov511->proc_entry = ent;
}
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);
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 */
/**********************************************************************
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 },
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 }
};
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]);
if (!ov511->streaming) {
PDEBUG(2, "hmmm... not streaming, but got interrupt");
return;
- } else {
- PDEBUG(5, "streaming. got interrupt");
}
sbuf = &ov511->sbuf[ov511->cursbuf];
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
{
struct video_capability b;
+ PDEBUG (4, "VIDIOCGCAP");
+
strcpy(b.name, "OV511 USB Camera");
b.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE;
b.channels = 1;
{
struct video_picture p;
+ PDEBUG (4, "VIDIOCGPICT");
+
if (ov7610_get_picture(ov511, &p))
return -EIO;
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;
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;
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)
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;
}
{
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;
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;
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;
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;
}
return -EINVAL;
default:
return -ENOIOCTLCMD;
- } /* End switch(cmd) */
+ } /* end switch */
return 0;
}
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
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
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
}
return -ENOMEM;
memset(cache, 0, sizeof(*cache));
+ atomic_set(&cache->nr_requests, 0);
init_waitqueue_head(&cache->request_wait);
server->rw_requests = cache;
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
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;
* 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
*/
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();
/* 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;
/* 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) {
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;
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;
}
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
}
/*
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
nfsd_cache_shutdown(void)
{
struct svc_cacherep *rp;
+ size_t i;
+ unsigned long order;
if (!cache_initialized)
return;
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;
#include <linux/string.h>
#include <linux/blk.h>
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD)
+#ifdef CONFIG_BLK_DEV_IDE
#include <linux/ide.h> /* IDE xlate */
-#endif /* (CONFIG_BLK_DEV_IDE) || (CONFIG_BLK_DEV_HD) */
+#endif /* CONFIG_BLK_DEV_IDE */
#include <asm/system.h>
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);
}
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
(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.
{
int i;
unsigned long page;
-
+ unsigned long size;
+
*where = 0;
if (!data)
return 0;
* 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;
}
*
* write support Daniel Pirkl <daniel.pirkl@email.cz> 1998
*
+ * HP/UX hfs filesystem support added by
+ * Martin K. Petersen <mkp@mkp.net>, August 1999
+ *
*/
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;
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);
}
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;
#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;
}
}
if (irq != NULL)
*irq = 0;
+ hw->io_ports[IDE_IRQ_OFFSET] = 0;
}
/*
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);
}
if (irq != NULL)
*irq = 0;
+ hw->io_ports[IDE_IRQ_OFFSET] = 0;
}
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);
#include <asm/segment.h>
#include <asm/page.h>
#include <asm/types.h>
+#include <asm/sigcontext.h>
#include <linux/config.h>
#include <linux/threads.h>
#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];
#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;
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;
* 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)
datasel;
struct _fpreg _st[8];
unsigned long status;
+#ifdef CONFIG_X86_FX
+ unsigned long mxcsr;
+ unsigned long _xmm[4*22];
+#endif
};
struct sigcontext {
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 */
};
}
if (irq != NULL)
*irq = 0;
+ hw->io_ports[IDE_IRQ_OFFSET] = 0;
}
static __inline__ 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);
#include <linux/config.h>
#ifndef MAX_HWIFS
-#define MAX_HWIFS 1
+#define MAX_HWIFS 1 /* XXX: For my board -- gniibe */
#endif
#define ide__sti() __sti()
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;
}
{
switch (index) {
case 0:
- return 0x01f0;
+ return 0xba0001f0;
case 1:
- return 0x0170;
+ return 0xba000170;
default:
return 0;
}
}
if (irq != NULL)
*irq = 0;
+ hw->io_ports[IDE_IRQ_OFFSET] = 0;
}
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);
}
if (irq != NULL)
*irq = 0;
+ hw->io_ports[IDE_IRQ_OFFSET] = 0;
}
/*
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);
}
if (irq != NULL)
*irq = 0;
+ hw->io_ports[IDE_IRQ_OFFSET] = 0;
}
/*
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);
#ifdef __KERNEL__
+#include <asm/atomic.h>
#include <linux/nfs_fs_sb.h>
/*
* 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;
#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
#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
* Niels Kristian Bech Jensen <nkbj@image.dk>.
*
* Write support by Daniel Pirkl <daniel.pirkl@email.cz>
+ *
+ * HP/UX hfs filesystem support added by
+ * Martin K. Petersen <mkp@mkp.net>, August 1999
+ *
*/
#ifndef __LINUX_UFS_FS_H
#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
#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
#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
EXPORT_SYMBOL(kmalloc);
EXPORT_SYMBOL(kfree);
EXPORT_SYMBOL(kfree_s);
-EXPORT_SYMBOL(vmalloc);
EXPORT_SYMBOL(vfree);
EXPORT_SYMBOL(__vmalloc);
EXPORT_SYMBOL(mem_map);
# 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
my $count;
my $id;
- $id = $args{'module'}."-".$args{'function'};
+ $id = "API-".$args{'function'};
$id =~ s/[^A-Za-z0-9]/-/g;
print "<refentry>\n";
*/
#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)))))
* 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)
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);