S: Germany
N: Christoph Hellwig
-E: chhellwig@gmx.net
-D: Sound/OSS hacking
+E: hch@caldera.de
+E: hch@infradead.org
+D: misc driver & makefile hacking
+D: freevxfs driver
S: Triftstraße 26
S: 38644 Goslar
S: Germany
The module will be called ov511.o. If you want to compile it as a
module, say M here and read Documentation/modules.txt.
+Philips webcam support
+CONFIG_USB_PWC
+ Say Y or M here if you want to use one of these Philips USB webcams:
+ PCA645, PCA646, PCVC675, PCVC680, PCVC690, PCVC730, PCVC740, or
+ the Askey VC010. The PCA635, PCVC665 and PCVC720 are not
+ supported by this driver and never will be.
+
+ This driver has an optional plugin, which is distributed as a
+ binary module only. It contains code that allow you to use
+ higher resolutions and framerates but may not be distributed
+ as source. But even without this plugin you can these cams
+ for most applications.
+
+ See Documentation/usb/philips.txt for more information and
+ installation instructions.
+
+ The built-in microphone is enabled by selecting USB Audio support.
+
+ This driver uses the Video For Linux API. You must say Y or M to
+ "Video For Linux" (under Character Devices) to use this driver.
+ Information on this API and pointers to "v4l" programs may be found
+ on the WWW at http://roadrunner.swansea.uk.linux.org/v4l.shtml .
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called pwc.o. If you want to compile it as a
+ module, say M here and read Documentation/modules.txt.
+
+
USB ADMtek Pegasus-based ethernet device support
CONFIG_USB_PEGASUS
Say Y if you want to use your USB ethernet device. Supported
The module is called hpfs.o. If you want to compile it as a module,
say M here and read Documentation/modules.txt. If unsure, say N.
+FreeVxFS file system support (VERITAS VxFS(TM) compatible)
+CONFIG_VXFS_FS
+ FreeVxFS is a filesystem driver that support the VERITAS VxFS(TM)
+ filesystem format. VERITAS VxFS(TM) is the standard filesystem
+ of SCO UnixWare (and possibly others) and optionally available
+ for Sunsoft Solaris, HP-UX and many other operating systems.
+ Currently only readonly access is supported.
+
+ NOTE: the filesystem type as used by mount(1), mount(2) and fstab(5)
+ is 'vxfs' as it describes the filesystem format, not the
+ actual driver.
+
+ This file system is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module is called freevxfs.o. If you want to compile it as a module,
+ say M here and read Documentation/modules.txt. If unsure, say N.
+
NTFS support (read only)
CONFIG_NTFS_FS
NTFS is the file system of Microsoft Windows NT. Say Y if you want
--- /dev/null
+This file contains some additional information for the Philips webcams.
+E-mail: webcam@smcc.demon.nl Last updated: 2001-04-25
+
+The main webpage for the Philips driver is http://www.smcc.demon.nl/webcam/.
+It contains a lot of extra information, a FAQ, and the binary plugin
+'PWCX'. This plugin contains decompression routines that allow you to
+use higher image sizes and framerates; in addition the webcam uses less
+bandwidth on the USB bus (handy if you want to run more than 1 camera
+simultaneously). These routines fall under an NDA, and may therefor not be
+distributed as source; however, its use is completely optional.
+
+You can build this code either into your kernel, or as a module. I recommend
+the latter, since it makes troubleshooting a lot easier. The built-in
+microphone is supported through the USB Audio class.
+
+(Taken from install.html)
+
+When you load the module you can set some default settings for the
+camera; some programs depend on a particular image-size or -format. The
+options are:
+
+size
+ Can be one of 'sqcif', 'qsif', 'qcif', 'sif', 'cif' or
+ 'vga', for an image size of resp. 128x96, 160x120, 176x144,
+ 320x240, 352x288 and 640x480 (of course, only for those cameras that support these resolutions).
+
+fps
+ Specifies the desired framerate. Is an integer in the range of 4-30.
+
+palette
+ Specifies the desired colour order that should be delivered by read() and
+ mmap(). The string can be one of bgr24, rgb24, rgb32, bgr32, yuyv,
+ yuv420, yuv420p. If the tool you use produces odd colours (more
+ specificly, red and blue are swapped), try palette=bgr24 or
+ palette=rgb24.
+
+fbufs
+ This paramter specifies the number of internal buffers to use for storing
+ frames from the cam. This will help if the process that reads images from
+ the cam is a bit slow or momentarely busy. However, on slow machines it
+ only introduces lag, so choose carefully. The default is 3, which is
+ reasonable. You can set it between 2 and 5.
+
+mbufs
+ This is an integer between 1 and 4. It will tell the module the number of
+ buffers to reserve for mmap(), VIDIOCCGMBUF, VIDIOCMCAPTURE and friends.
+ The default is 2, which is adequate for most applications (double
+ buffering).
+
+ Should you experience a lot of 'Dumping frame...' messages during
+ grabbing with a tool that uses mmap(), you might want to increase if.
+ However, it doesn't really buffer images, it just gives you a bit more
+ slack when your program is behind. But you need a multi-threaded or
+ forked program to really take advantage of these buffers.
+
+ The absolute maximum is 4, but don't set it too high! Every buffer takes
+ up 1.22 MB of RAM, so unless you have a lot of memory setting this to
+ something more than 2 is an absolute waste. This memory is only
+ allocated during open(), so nothing is wasted when the camera is not in
+ use.
+
+power_save
+ When power_save is enabled (set to 1), the module will try to shut down
+ the cam on close() and re-activate on open(). This will save power and
+ turn off the LED. Not all cameras support this though (the 645 and 646
+ don't have power saving at all), and some models don't work either (they
+ will shut down, but never wake up). Consider this experimental. By
+ default this option is disabled.
+
+compression (only useful with the plugin)
+ With this option you can control the compression factor that the camera
+ use to squeeze the image through the USB bus. You can set the
+ parameter between 0 and 3:
+ 0 = prefer uncompressed images; if the requested mode is not available
+ in an uncompressed format, the driver will silently switch to low
+ compression.
+ 1 = low compression.
+ 2 = medium compression.
+ 3 = high compression.
+
+ High compression takes less bandwidth of course, but it could also
+ introduce some unwanted artefacts. The default is 2, medium compression.
+ See the FAQ on the website for an overview of which modes require
+ compression.
+
+ The compression parameter only applies to the Vesta & ToUCam cameras.
+ The 645 and 646 have fixed compression parameters.
+
+trace
+
+ In order to better detect problems, it is now possible to turn on a
+ 'trace' of some of the calls the module makes; it logs all items in your
+ kernel log at debug level.
+
+ The trace variable is a bitmask; each bit represents a certain feature.
+ If you want to trace something, look up the bit value(s) in the table
+ below, add the values together and supply that to the trace variable.
+
+ Value Value Description Default
+ (dec) (hex)
+ 1 0x1 Module initialization; this will log messages On
+ while loading and unloading the module
+
+ 2 0x2 probe() and disconnect() traces On
+
+ 4 0x4 Trace open() and close() calls Off
+
+ 8 0x8 read(), mmap() and associated ioctl() calls Off
+
+ 16 0x10 Memory allocation of buffers, etc. Off
+
+ 32 0x20 Showing underflow, overflow and Dumping frame On
+ messages
+
+ 64 0x40 Show viewport and image sizes Off
+
+
+ For example, to trace the open() & read() fuctions, sum 8 + 4 = 12,
+ so you would supply trace=12 during insmod or modprobe. If
+ you want to turn the initialization and probing tracing off, set trace=0.
+ The default value for trace is 35 (0x23).
+
+ Example:
+
+ # modprobe pwc size=cif fps=15 power_save=1
+
+The fbufs, mbufs and trace parameters are global and apply to all connected
+cameras. Each camera has its own set of buffers.
+
+size, fps, palette only specify defaults when you open() the device; this is
+to accommodate some tools that don't set the size or colour palette. You can
+change these settings after open() with the Video4Linux ioctl() calls. The
+default of defaults is QCIF size at 10 fps, BGR order.
+
+The compression parameter is semiglobal; it sets the initial compression
+preference for all camera's, but this parameter can be set per camera with
+the VIDIOCPWCSCQUAL ioctl() call.
+
+All parameters are optional.
+
+
L: linux-net@vger.kernel.org
S: Maintained
+FREEVXFS FILESYSTEM
+P: Christoph Hellwig
+M: hch@caldera.de
+W: ftp://ftp.openlinux.org/pub/people/hch/vxfs
+S: Maintained
+
FTAPE/QIC-117
P: Claus-Justus Heine
M: claus@momo.math.rwth-aachen.de
VERSION = 2
PATCHLEVEL = 4
SUBLEVEL = 5
-EXTRAVERSION =-pre4
+EXTRAVERSION =-pre5
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
* Richard L. Sites and Richard T. Witek.
*/
#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
#include <unistd.h>
#include <sys/fcntl.h>
if (hose->index == bus) break;
if (!hose) return -ENODEV;
} else {
- /* Special hook for ISA access. */
- if (bus == 0 && dfn == 0) {
- hose = pci_isa_hose;
- } else {
- dev = pci_find_slot(bus, dfn);
- if (!dev)
- return -ENODEV;
- hose = dev->sysdata;
- }
+ /* Special hook for ISA access. */
+ if (bus == 0 && dfn == 0) {
+ hose = pci_isa_hose;
+ } else {
+ dev = pci_find_slot(bus, dfn);
+ if (!dev)
+ return -ENODEV;
+ hose = dev->sysdata;
+ }
}
switch (which & ~IOBASE_FROM_HOSE) {
return -EOPNOTSUPP;
}
+
+/* Return the index of the PCI controller for device PDEV. */
+int
+pci_controller_num(struct pci_dev *pdev)
+{
+ struct pci_controller *hose = pdev->sysdata;
+ return (hose ? hose->index : -ENXIO);
+}
paddr &= ~PAGE_MASK;
npages = calc_npages(paddr + size);
dma_ofs = iommu_arena_alloc(arena, npages);
- if (dma_ofs < 0)
- return -1;
+ if (dma_ofs < 0) {
+ /* If we attempted a direct map above but failed, die. */
+ if (leader->dma_address == 0)
+ return -1;
+
+ /* Otherwise, break up the remaining virtually contiguous
+ hunks into individual direct maps. */
+ for (sg = leader; sg < end; ++sg)
+ if (sg->dma_address == 2 || sg->dma_address == -2)
+ sg->dma_address = 0;
+
+ /* Retry. */
+ return sg_fill(leader, end, out, arena, max_dma);
+ }
out->dma_address = arena->dma_base + dma_ofs*PAGE_SIZE + paddr;
out->dma_length = size;
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/bootmem.h>
+#include <linux/pci.h>
#ifdef CONFIG_BLK_DEV_INITRD
#include <linux/blk.h>
#include <asm/hwrpb.h>
#include <asm/dma.h>
#include <asm/io.h>
-#include <asm/pci.h>
#include <asm/mmu_context.h>
#include <asm/console.h>
{
if (alpha_using_srm) {
alpha_mv.device_interrupt = srm_device_interrupt;
- alpha_mv.kill_arch = NULL;
}
init_i8259a_irqs();
{
switch (mode) {
case LINUX_REBOOT_CMD_RESTART:
- {
+ if (! alpha_using_srm) {
u8 t8;
pcibios_read_config_byte(0, 0x38, 0x43, &t8);
pcibios_write_config_byte(0, 0x38, 0x43, t8 | 0x80);
* Luckily, the work-around for this is not too horrible. See
* __isamem_convert_addr for the details.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
* published by the Free Software Foundation.
*/
+#include <linux/config.h>
/*
* DMA channel structure.
#include <unistd.h> /* contains read/write */
#include <fcntl.h>
#include <linux/a.out.h>
-#include <linux/config.h>
#include <errno.h>
#define MINIX_HEADER 32
*
*/
+#include <linux/config.h>
#include <linux/linkage.h>
#include <linux/sys.h>
#include <asm/sv_addr_ag.h>
*
*/
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/kernel.h>
CONFIG_ISO9660_FS=y
# CONFIG_JOLIET is not set
# CONFIG_MINIX_FS is not set
+# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
#
# CONFIG_USB_IBMCAM is not set
# CONFIG_USB_OV511 is not set
+# CONFIG_USB_PWC is not set
# CONFIG_USB_DSBR is not set
# CONFIG_USB_DABUSB is not set
{
wrmsr(0x401+4*i, 0x0, 0x0);
}
- __asm__ __volatile__ (
- "movl %%cr4, %%eax\n\t"
- "orl $0x40, %%eax\n\t"
- "movl %%eax, %%cr4\n\t" : : : "eax");
+ set_in_cr4(X86_CR4_MCE);
printk(KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n", smp_processor_id());
done=1;
}
/* Unhide possibly hidden capability flags
The mp6 iDragon family don't have MSRs.
- We switch on extra features with this cpuid wierdness: */
+ We switch on extra features with this cpuid weirdness: */
__asm__ (
"movl $0x6363452a, %%eax\n\t"
"movl $0x3231206c, %%ecx\n\t"
/* Now the feature flags better reflect actual CPU features! */
- printk(KERN_DEBUG "CPU: After generic, caps: %08x %08x %08x %08x\n",
+ printk(KERN_DEBUG "CPU: After generic, caps: %08x %08x %08x %08x\n",
c->x86_capability[0],
c->x86_capability[1],
c->x86_capability[2],
boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
}
- printk(KERN_DEBUG "CPU: Common caps: %08x %08x %08x %08x\n",
+ printk(KERN_DEBUG "CPU: Common caps: %08x %08x %08x %08x\n",
boot_cpu_data.x86_capability[0],
boot_cpu_data.x86_capability[1],
boot_cpu_data.x86_capability[2],
".previous"
: : "r" (from) );
- for(i=0; i<4096/64; i++)
+ for(i=0; i<(4096-320)/64; i++)
{
__asm__ __volatile__ (
"1: prefetch 320(%0)\n"
from+=64;
to+=64;
}
+ for(i=(4096-320)/64; i<4096/64; i++)
+ {
+ __asm__ __volatile__ (
+ "2: movq (%0), %%mm0\n"
+ " movntq %%mm0, (%1)\n"
+ " movq 8(%0), %%mm1\n"
+ " movntq %%mm1, 8(%1)\n"
+ " movq 16(%0), %%mm2\n"
+ " movntq %%mm2, 16(%1)\n"
+ " movq 24(%0), %%mm3\n"
+ " movntq %%mm3, 24(%1)\n"
+ " movq 32(%0), %%mm4\n"
+ " movntq %%mm4, 32(%1)\n"
+ " movq 40(%0), %%mm5\n"
+ " movntq %%mm5, 40(%1)\n"
+ " movq 48(%0), %%mm6\n"
+ " movntq %%mm6, 48(%1)\n"
+ " movq 56(%0), %%mm7\n"
+ " movntq %%mm7, 56(%1)\n"
+ : : "r" (from), "r" (to) : "memory");
+ from+=64;
+ to+=64;
+ }
/* since movntq is weakly-ordered, a "sfence" is needed to become
* ordered again.
*/
static void fast_clear_page(void *page)
{
int i;
- if (!(current->flags & PF_USEDFPU))
- clts();
- else
- {
- __asm__ __volatile__ ( " fnsave %0; fwait\n"::"m"(current->thread.i387));
- current->flags &= ~PF_USEDFPU;
- }
+
+ kernel_fpu_begin();
__asm__ __volatile__ (
" pxor %%mm0, %%mm0\n" : :
: : "r" (page) : "memory");
page+=128;
}
- stts();
+
+ kernel_fpu_end();
}
static void fast_copy_page(void *to, void *from)
{
int i;
- if (!(current->flags & PF_USEDFPU))
- clts();
- else
- {
- __asm__ __volatile__ ( " fnsave %0; fwait\n"::"m"(current->thread.i387));
- current->flags &= ~PF_USEDFPU;
- }
+
+
+ kernel_fpu_begin();
__asm__ __volatile__ (
"1: prefetch (%0)\n"
from+=64;
to+=64;
}
- stts();
+ kernel_fpu_end();
}
int 'Maximum number of SCSI disks that can be loaded as modules' CONFIG_SD_EXTRA_DEVS 40
fi
dep_tristate ' SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
- if [ "$CONFIG_BLK_DEV_ST" != "n" ]; then
+ if [ "$CONFIG_CHR_DEV_ST" != "n" ]; then
int 'Maximum number of SCSI tapes that can be loaded as modules' CONFIG_ST_EXTRA_DEVS 2
fi
dep_tristate ' SCSI CD-ROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
+# BK Id: SCCS/s.Makefile 1.3 05/17/01 18:14:19 cort
+#
#
# Makefile for the linux MPC8xx ppc-specific parts of comm processor
#
+/*
+ * BK Id: SCCS/s.commproc.c 1.5 05/17/01 18:14:19 cort
+ */
/*
* General Purpose functions for the global management of the
+/*
+ * BK Id: SCCS/s.enet.c 1.6 05/17/01 18:14:19 cort
+ */
/*
* Ethernet driver for Motorola MPC8260.
* Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+/*
+ * BK Id: SCCS/s.fcc_enet.c 1.7 05/17/01 18:14:20 cort
+ */
/*
* Fast Ethernet Controller (FCC) driver for Motorola MPC8260.
* Copyright (c) 2000 MontaVista Software, Inc. Dan Malek (dmalek@jlc.net)
+/*
+ * BK Id: SCCS/s.uart.c 1.6 05/17/01 18:14:20 cort
+ */
/*
* UART driver for MPC8260 CPM SCC or SMC
* Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+# BK Id: SCCS/s.Makefile 1.3 05/17/01 18:14:20 cort
+#
#
# Makefile for the linux MPC8xx ppc-specific parts of comm processor
#
+/*
+ * BK Id: SCCS/s.commproc.c 1.8 05/18/01 07:54:04 patch
+ */
/*
* General Purpose functions for the global management of the
* The internal baud rate clock is the system clock divided by 16.
* This assumes the baudrate is 16x oversampled by the uart.
*/
-#define BRG_INT_CLK (((bd_t *)__res)->bi_intfreq * 1000000)
+#define BRG_INT_CLK (((bd_t *)__res)->bi_intfreq)
#define BRG_UART_CLK (BRG_INT_CLK/16)
#define BRG_UART_CLK_DIV16 (BRG_UART_CLK/16)
+/*
+ * BK Id: SCCS/s.commproc.h 1.8 05/17/01 18:14:20 cort
+ */
/*
* MPC8xx Communication Processor Module.
+/*
+ * BK Id: SCCS/s.enet.c 1.10 05/17/01 18:14:20 cort
+ */
/*
* Ethernet driver for Motorola MPC8xx.
* Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
+/*
+ * BK Id: SCCS/s.fec.c 1.12 05/18/01 07:54:04 patch
+ */
/*
* Fast Ethernet Controller (FEC) driver for Motorola MPC8xx.
* Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
/* Set MII speed to 2.5 MHz
*/
fecp->fec_mii_speed = fep->phy_speed =
- (
- ( ((bd->bi_intfreq * 1000000) + 500000) / 2500000 / 2 )
- & 0x3F
- ) << 1;
+ (( (bd->bi_intfreq + 500000) / 2500000 / 2 ) & 0x3F ) << 1;
#else
fecp->fec_mii_speed = 0; /* turn off MDIO */
#endif /* CONFIG_USE_MDIO */
+/*
+ * BK Id: SCCS/s.uart.c 1.10 05/17/01 18:14:20 cort
+ */
/*
* UART driver for MPC860 CPM SCC or SMC
* Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
+# BK Id: SCCS/s.Makefile 1.13 05/21/01 00:48:24 cort
+#
# This file is included by the global makefile so that you can add your own
# architecture-specific flags and dependencies. Remember to do have actions
# for "archclean" and "archdep" for cleaning up and making dependencies for
+# BK Id: SCCS/s.Makefile 1.5 05/21/01 00:48:24 cort
+#
#
# Makefile for Linux arch/m68k/amiga source directory
#
+/*
+ * BK Id: SCCS/s.amiga_ksyms.c 1.5 05/17/01 18:14:20 cort
+ */
#include "../../m68k/amiga/amiga_ksyms.c"
+/*
+ * BK Id: SCCS/s.amiints.c 1.8 05/21/01 00:48:24 cort
+ */
/*
* linux/arch/m68k/amiga/amiints.c -- Amiga Linux interrupt handling code
*
+/*
+ * BK Id: SCCS/s.amisound.c 1.5 05/17/01 18:14:20 cort
+ */
#include "../../m68k/amiga/amisound.c"
+/*
+ * BK Id: SCCS/s.bootinfo.c 1.5 05/17/01 18:14:20 cort
+ */
/*
* linux/arch/ppc/amiga/bootinfo.c
*
+/*
+ * BK Id: SCCS/s.chipram.c 1.7 05/21/01 00:49:49 cort
+ */
#include "../../m68k/amiga/chipram.c"
+/*
+ * BK Id: SCCS/s.cia.c 1.7 05/21/01 00:48:24 cort
+ */
/*
* linux/arch/m68k/amiga/cia.c - CIA support
*
+/*
+ * BK Id: SCCS/s.config.c 1.7 05/21/01 00:48:24 cort
+ */
#define m68k_debug_device debug_device
/*
+/*
+ * BK Id: SCCS/s.ints.c 1.5 05/17/01 18:14:20 cort
+ */
/*
* linux/arch/ppc/amiga/ints.c
*
+/*
+ * BK Id: SCCS/s.pcmcia.c 1.5 05/17/01 18:14:20 cort
+ */
#include "../../m68k/amiga/pcmcia.c"
+/*
+ * BK Id: SCCS/s.time.c 1.5 05/17/01 18:14:20 cort
+ */
#include <linux/config.h> /* CONFIG_HEARTBEAT */
#include <linux/errno.h>
#include <linux/sched.h>
-# $Id: config.in,v 1.106 1999/09/14 19:21:18 cort Exp $
+# BK Id: SCCS/s.config.in 1.24 05/21/01 00:48:24 cort
+#
# For a description of the syntax of this configuration file,
# see Documentation/kbuild/config-language.txt.
#
bool 'AltiVec Support' CONFIG_ALTIVEC
fi
-if [ "$CONFIG_ALL_PPC" != "y" ];then
- define_bool CONFIG_MACH_SPECIFIC y
-fi
-
if [ "$CONFIG_4xx" = "y" -o "$CONFIG_8xx" = "y" ]; then
bool 'Math emulation' CONFIG_MATH_EMULATION
fi
define_bool CONFIG_PCI $CONFIG_PCI_QSPAN
else
if [ "$CONFIG_APUS" = "y" ]; then
- bool 'PCI for Permedia2' CONFIG_PCI
+ bool 'PCI for Permedia2' CONFIG_PCI_PERMEDIA
+ define_bool CONFIG_PCI $CONFIG_PCI_PERMEDIA
else
define_bool CONFIG_PCI y
fi
# CONFIG_PPC601_SYNC_FIX is not set
# CONFIG_ALL_PPC is not set
# CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
CONFIG_MATH_EMULATION=y
CONFIG_SASH=y
CONFIG_SASH_PATH="/bin/sash"
# CONFIG_PPC601_SYNC_FIX is not set
# CONFIG_ALL_PPC is not set
# CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
CONFIG_MATH_EMULATION=y
CONFIG_SASH=y
CONFIG_SASH_PATH="/bin/sash"
# CONFIG_PPC601_SYNC_FIX is not set
# CONFIG_ALL_PPC is not set
# CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
CONFIG_MATH_EMULATION=y
CONFIG_SASH=y
CONFIG_SASH_PATH="/bin/sash"
# CONFIG_PPC601_SYNC_FIX is not set
# CONFIG_ALL_PPC is not set
# CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
CONFIG_MATH_EMULATION=y
CONFIG_SASH=y
CONFIG_SASH_PATH="/bin/sash"
# CONFIG_PPC601_SYNC_FIX is not set
# CONFIG_ALL_PPC is not set
# CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
CONFIG_MATH_EMULATION=y
CONFIG_SASH=y
CONFIG_SASH_PATH="/bin/sash"
# CONFIG_PPC601_SYNC_FIX is not set
# CONFIG_ALL_PPC is not set
# CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
CONFIG_MATH_EMULATION=y
CONFIG_SASH=y
CONFIG_SASH_PATH="/bin/sash"
# CONFIG_PPC601_SYNC_FIX is not set
# CONFIG_SMP is not set
# CONFIG_ALTIVEC is not set
-CONFIG_MACH_SPECIFIC=y
#
# General setup
CONFIG_PPC601_SYNC_FIX=y
# CONFIG_ALL_PPC is not set
# CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
CONFIG_MATH_EMULATION=y
#
CONFIG_PPC601_SYNC_FIX=y
# CONFIG_ALL_PPC is not set
# CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
#
# General setup
# CONFIG_PPC601_SYNC_FIX is not set
# CONFIG_SMP is not set
CONFIG_ALTIVEC=y
-CONFIG_MACH_SPECIFIC=y
#
# General setup
CONFIG_PPC601_SYNC_FIX=y
# CONFIG_ALL_PPC is not set
# CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
CONFIG_MATH_EMULATION=y
#
# CONFIG_WALNUT is not set
CONFIG_PPC601_SYNC_FIX=y
# CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
# CONFIG_MATH_EMULATION is not set
#
CONFIG_PPC601_SYNC_FIX=y
# CONFIG_ALL_PPC is not set
# CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
CONFIG_MATH_EMULATION=y
#
CONFIG_PPC601_SYNC_FIX=y
# CONFIG_ALL_PPC is not set
# CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
CONFIG_MATH_EMULATION=y
#
CONFIG_WALNUT=y
CONFIG_PPC601_SYNC_FIX=y
# CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
# CONFIG_MATH_EMULATION is not set
#
+# BK Id: SCCS/s.Makefile 1.17 05/21/01 00:48:24 cort
+#
#
# Makefile for the linux kernel.
#
obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o
ifeq ($(CONFIG_8xx),y)
obj-$(CONFIG_PCI) += qspan_pci.c
+ifndef CONFIG_MATH_EMULATION
+obj-y += softemu8xx.o
+endif
else
obj-y += hashtable.o
endif
-obj-$(CONFIG_MATH_EMULATION) += softemu8xx.o
obj-$(CONFIG_MBX) += i8259.o
obj-$(CONFIG_APUS) += apus_setup.o
ifeq ($(CONFIG_APUS),y)
+/*
+ * BK Id: SCCS/s.align.c 1.5 05/17/01 18:14:21 cort
+ */
/*
* align.c - handle alignment exceptions for the Power PC.
*
+/*
+ * BK Id: SCCS/s.apus_pci.c 1.3 05/17/01 18:14:21 cort
+ */
/*
* Copyright (C) Michel Dänzer <michdaen@iiic.ethz.ch>
*
+/*
+ * BK Id: SCCS/s.apus_pci.h 1.4 05/17/01 18:14:21 cort
+ */
/*
* Phase5 CybervisionPPC (TVP4020) definitions for the Permedia2 framebuffer
* driver.
*
* Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
* --------------------------------------------------------------------------
- * $Id: cvisionppc.h,v 1.9 1999/03/12 09:45:06 illo Exp $
- * --------------------------------------------------------------------------
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file README.legal in the main directory of this archive
* for more details.
+/*
+ * BK Id: SCCS/s.apus_setup.c 1.11 05/17/01 18:14:21 cort
+ */
/*
* linux/arch/ppc/kernel/apus_setup.c
*
+/*
+ * BK Id: SCCS/s.bitops.c 1.7 05/17/01 18:14:21 cort
+ */
/*
* Copyright (C) 1996 Paul Mackerras.
*/
+/*
+ * BK Id: SCCS/s.checks.c 1.6 05/17/01 18:14:21 cort
+ */
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
+/*
+ * BK Id: SCCS/s.chrp_pci.c 1.16 05/17/01 18:14:21 cort
+ */
/*
* CHRP pci routines.
*/
+/*
+ * BK Id: SCCS/s.chrp_setup.c 1.17 05/17/01 18:14:21 cort
+ */
/*
* linux/arch/ppc/kernel/setup.c
*
+/*
+ * BK Id: SCCS/s.chrp_time.c 1.7 05/17/01 18:14:21 cort
+ */
/*
* linux/arch/i386/kernel/time.c
*
/*
- * arch/ppc/kernel/entry.S
- *
- * $Id: entry.S,v 1.4 1999/09/14 05:18:14 dmalek Exp $
- *
+ * BK Id: SCCS/s.entry.S 1.12 05/21/01 11:49:59 paulus
+ */
+/*
* PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
* Rewritten by Cort Dougan (cort@fsmlabs.com) for PReP
rlwinm r0,r0,0,17,15 /* clear MSR_EE in r0 */
SYNC /* Some chip revs have problems here... */
mtmsr r0 /* Update machine state */
-
+
+ stwcx. r0,0,r1 /* to clear the reservation */
+
/* if returning to user mode, set new sprg2 and save kernel SP */
lwz r0,_MSR(r1)
andi. r0,r0,MSR_PR
+/*
+ * BK Id: SCCS/s.error_log.c 1.6 05/17/01 18:14:21 cort
+ */
/*
* arch/ppc/kernel/error_log.c
*
+/*
+ * BK Id: SCCS/s.error_log.h 1.5 05/17/01 18:14:21 cort
+ */
#ifndef __ERROR_LOG_H__
#define __ERROR_LOG_H__
+/*
+ * BK Id: SCCS/s.feature.c 1.10 05/17/01 18:14:21 cort
+ */
/*
* arch/ppc/kernel/feature.c
*
+/*
+ * BK Id: SCCS/s.find_name.c 1.5 05/17/01 18:14:21 cort
+ */
#include <stdio.h>
#include <asm/page.h>
#include <sys/mman.h>
+/*
+ * BK Id: SCCS/s.galaxy_pci.c 1.7 05/17/01 18:14:21 cort
+ */
/*
*
* Copyright (c) 2000 Grant Erickson <grant@borg.umn.edu>
+/*
+ * BK Id: SCCS/s.gemini_pci.c 1.5 05/17/01 18:14:21 cort
+ */
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/pci.h>
+/*
+ * BK Id: SCCS/s.gemini_prom.S 1.5 05/17/01 18:14:21 cort
+ */
/*
* arch/ppc/kernel/gemini_prom.S
*
+/*
+ * BK Id: SCCS/s.gemini_setup.c 1.7 05/17/01 18:14:21 cort
+ */
/*
* linux/arch/ppc/kernel/setup.c
*
+/*
+ * BK Id: SCCS/s.hashtable.S 1.11 05/17/01 18:14:21 cort
+ */
/*
* arch/ppc/kernel/hashtable.S
*
- * $Id: hashtable.S,v 1.6 1999/10/08 01:56:15 paulus Exp $
- *
* PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
* Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
/*
- * arch/ppc/kernel/head.S
- *
- * $Id: head.S,v 1.154 1999/10/12 00:33:31 cort Exp $
- *
+ * BK Id: SCCS/s.head.S 1.18 05/21/01 11:49:59 paulus
+ */
+/*
* PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
*
mflr r23
andi. r24,r23,0x3f00 /* get vector offset */
stw r24,TRAP(r21)
- li r22,RESULT
- stwcx. r22,r22,r21 /* to clear the reservation */
li r22,0
stw r22,RESULT(r21)
mtspr SPRG2,r22 /* r1 is now kernel sp */
+/*
+ * BK Id: SCCS/s.head_4xx.S 1.6 05/21/01 11:50:00 paulus
+ */
/*
* Copyright (c) 1995-1996 Gary Thomas <gdt@linuxppc.org>
* Initial PowerPC version.
mflr r23
andi. r24,r23,0x3f00 # Get vector offset
stw r24,TRAP(r21)
- li r22,RESULT
- stwcx. r22,r22,r21 # Clear the reservation
li r22,0
stw r22,RESULT(r21)
mtspr SPRN_SPRG2,r22 # r1 is now the kernel stack pointer
+/*
+ * BK Id: SCCS/s.head_8xx.S 1.11 05/21/01 11:50:00 paulus
+ */
/*
* arch/ppc/kernel/except_8xx.S
*
- * $Id: head_8xx.S,v 1.4 1999/09/18 18:43:19 dmalek Exp $
- *
* PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
* Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
mflr r23
andi. r24,r23,0x3f00 /* get vector offset */
stw r24,TRAP(r21)
- li r22,RESULT
- stwcx. r22,r22,r21 /* to clear the reservation */
li r22,0
stw r22,RESULT(r21)
mtspr SPRG2,r22 /* r1 is now kernel sp */
+/*
+ * BK Id: SCCS/s.i8259.c 1.7 05/17/01 18:14:21 cort
+ */
#include <linux/stddef.h>
#include <linux/init.h>
+/*
+ * BK Id: SCCS/s.i8259.h 1.5 05/17/01 18:14:21 cort
+ */
#ifndef _PPC_KERNEL_i8259_H
#define _PPC_KERNEL_i8259_H
/*
- * $Id: idle.c,v 1.68 1999/10/15 18:16:03 cort Exp $
- *
+ * BK Id: SCCS/s.idle.c 1.11 05/17/01 18:14:21 cort
+ */
+/*
* Idle daemon for PowerPC. Idle daemon will handle any action
* that needs to be taken when the system becomes idle.
*
+/*
+ * BK Id: SCCS/s.indirect_pci.c 1.7 05/17/01 18:14:21 cort
+ */
/*
* Support for indirect PCI bridges.
*
/*
- * $Id: irq.c,v 1.113 1999/09/17 17:22:56 cort Exp $
- *
+ * BK Id: SCCS/s.irq.c 1.23 05/17/01 18:14:21 cort
+ */
+/*
* arch/ppc/kernel/irq.c
*
* Derived from arch/i386/kernel/irq.c
+/*
+ * BK Id: SCCS/s.local_irq.h 1.7 05/17/01 18:14:21 cort
+ */
#ifndef _PPC_KERNEL_LOCAL_IRQ_H
#define _PPC_KERNEL_LOCAL_IRQ_H
/*
- * $Id: m8xx_setup.c,v 1.4 1999/09/18 18:40:36 dmalek Exp $
- *
+ * BK Id: SCCS/s.m8260_setup.c 1.15 05/17/01 18:14:21 cort
+ */
+/*
* linux/arch/ppc/kernel/setup.c
*
* Copyright (C) 1995 Linus Torvalds
/*
- * $Id: m8xx_setup.c,v 1.4 1999/09/18 18:40:36 dmalek Exp $
- *
+ * BK Id: SCCS/s.m8xx_setup.c 1.17 05/18/01 07:54:04 patch
+ */
+/*
* linux/arch/ppc/kernel/setup.c
*
* Copyright (C) 1995 Linus Torvalds
ide_pio_timings_t ide_pio_clocks[6];
/* Make clock cycles and always round up */
-#define PCMCIA_MK_CLKS( t, T ) (( (t) * (T) + 999U ) / 1000U )
+#define PCMCIA_MK_CLKS( t, T ) (( (t) * ((T)/1000000) + 999U ) / 1000U )
#endif /* CONFIG_BLK_DEV_MPC8xx_IDE */
#endif /* CONFIG_BLK_DEV_IDE || CONFIG_BLK_DEV_IDE_MODULE */
+#ifdef CONFIG_BLK_DEV_RAM
+extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */
+extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */
+extern int rd_image_start; /* starting block # of image */
+#endif
+
extern char saved_command_line[256];
extern unsigned long find_available_memory(void);
/* Processor frequency is MHz.
* The value 'fp' is the number of decrementer ticks per second.
*/
- fp = (binfo->bi_intfreq * 1000000) / 16;
+ fp = binfo->bi_intfreq / 16;
freq = fp*60; /* try to make freq/1e6 an integer */
divisor = 60;
printk("Decrementer Frequency = %d/%d\n", freq, divisor);
bp = (bd_t *)__res;
- len += sprintf(len+buffer,"clock\t\t: %ldMHz\n"
- "bus clock\t: %ldMHz\n",
- bp->bi_intfreq /*/ 1000000*/,
- bp->bi_busfreq /*/ 1000000*/);
+ len += sprintf(len+buffer,"clock\t\t: %dMHz\n"
+ "bus clock\t: %dMHz\n",
+ bp->bi_intfreq / 1000000,
+ bp->bi_busfreq / 1000000);
return len;
}
#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
ide_insw(port, buf, ns);
#else
- ide_insw(port+_IO_BASE, buf, ns);
+ _insw_ns((unsigned short *)(port+_IO_BASE), buf, ns);
#endif
}
#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
ide_outsw(port, buf, ns);
#else
- ide_outsw(port+_IO_BASE, buf, ns);
+ _outsw_ns((unsigned short *)(port+_IO_BASE), buf, ns);
#endif
}
return (ioport_dsc[base].irq);
#else
- return 14;
+ return 9;
#endif
}
const char *device,
void *dev_id)
{
-#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
return request_8xxirq(irq, handler, flags, device, dev_id);
-#else
- return request_irq(irq, handler, flags, device, dev_id);
-#endif
}
/* We can use an external IDE controller
void m8xx_ide_init_hwif_ports(hw_regs_t *hw,
ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
{
- ide_ioreg_t *p = hw->io_ports;
int i;
#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
+ ide_ioreg_t *p = hw->io_ports;
volatile pcmconf8xx_t *pcmp;
static unsigned long pcmcia_base = 0;
-#else
- ide_ioreg_t port = data_port; /* ??? XXX ??? XXX */
-#endif
unsigned long base;
+#endif
#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
*p = 0;
/* Just a regular IDE drive on some I/O port.
*/
- i = 8;
- while (i--)
- *p++ = port++;
- *p++ = base + 0x206;
- if (irq != NULL)
- *irq = 0;
+ if (data_port == 0)
+ return;
+
+ for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; ++i)
+ hw->io_ports[i] = data_port + i - IDE_DATA_OFFSET;
+
+ hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+ return;
+
#endif /* CONFIG_BLK_DEV_MPC8xx_IDE */
}
#endif /* CONFIG_BLK_DEV_IDE || CONFIG_BLK_DEV_IDE_MODULE */
#define PCMCIA_SL(t) ((t==32) ? 0 : ((t & 0x1F)<<7)) /* Strobe Length */
#endif
-
/* Calculate PIO timings */
static void
m8xx_ide_tuneproc(ide_drive_t *drive, byte pio)
#endif /* CONFIG_BLK_DEV_MPC8xx_IDE */
#endif /* CONFIG_BLK_DEV_IDE || CONFIG_BLK_DEV_IDE_MODULE */
-
/* -------------------------------------------------------------------- */
/*
ppc_md.kbd_leds = NULL;
ppc_md.kbd_init_hw = NULL;
#ifdef CONFIG_MAGIC_SYSRQ
- ppc_md.kbd_sysrq_xlate = NULL;
+ ppc_md.ppc_kbd_sysrq_xlate = NULL;
#endif
#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+/*
+ * BK Id: SCCS/s.misc.S 1.16 05/17/01 18:14:21 cort
+ */
/*
* This file contains miscellaneous low-level functions.
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+/*
+ * BK Id: SCCS/s.mk_defs.c 1.5 05/17/01 18:14:21 cort
+ */
/*
* This program is used to generate definitions needed by
* assembly language modules.
+/*
+ * BK Id: SCCS/s.oak_setup.c 1.5 05/17/01 18:14:21 cort
+ */
/*
*
* Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
+/*
+ * BK Id: SCCS/s.oak_setup.h 1.5 05/17/01 18:14:21 cort
+ */
/*
*
* Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
+/*
+ * BK Id: SCCS/s.open_pic.c 1.20 05/17/01 18:14:21 cort
+ */
/*
* arch/ppc/kernel/open_pic.c -- OpenPIC Interrupt Handling
*
+/*
+ * BK Id: SCCS/s.open_pic.h 1.8 05/17/01 18:14:21 cort
+ */
/*
* arch/ppc/kernel/open_pic.h -- OpenPIC Interrupt Handling
*
+/*
+ * BK Id: SCCS/s.open_pic_defs.h 1.7 05/17/01 18:14:21 cort
+ */
/*
* linux/openpic.h -- OpenPIC definitions
*
+/*
+ * BK Id: SCCS/s.pci-dma.c 1.5 05/17/01 18:14:21 cort
+ */
/*
* Copyright (C) 2000 Ani Joshi <ajoshi@unixbox.com>
*
/*
- * $Id: pci.c,v 1.64 1999/09/17 18:01:53 cort Exp $
+ * BK Id: SCCS/s.pci.c 1.21 05/21/01 01:31:30 cort
+ */
+/*
* Common pmac/prep/chrp pci routines. -- Cort
*/
return ret;
}
-
/* Obsolete functions. Should be removed once the symbios driver
* is fixed
*/
+/*
+ * BK Id: SCCS/s.pci.h 1.7 05/17/01 18:14:21 cort
+ */
#ifndef __PPC_KERNEL_PCI_H__
#define __PPC_KERNEL_PCI_H__
+/*
+ * BK Id: SCCS/s.pmac_backlight.c 1.5 05/17/01 18:14:21 cort
+ */
/*
* Miscellaneous procedures for dealing with the PowerMac hardware.
* Contains support for the backlight.
+/*
+ * BK Id: SCCS/s.pmac_nvram.c 1.5 05/17/01 18:14:21 cort
+ */
/*
* Miscellaneous procedures for dealing with the PowerMac hardware.
*/
+/*
+ * BK Id: SCCS/s.pmac_pci.c 1.14 05/17/01 18:14:21 cort
+ */
/*
* Support for PCI bridges found on Power Macintoshes.
* At present the "bandit" and "chaos" bridges are supported.
+/*
+ * BK Id: SCCS/s.pmac_pic.c 1.14 05/17/01 18:14:21 cort
+ */
#include <linux/config.h>
#include <linux/stddef.h>
#include <linux/init.h>
+/*
+ * BK Id: SCCS/s.pmac_pic.h 1.5 05/17/01 18:14:21 cort
+ */
#ifndef _PPC_KERNEL_PMAC_PIC_H
#define _PPC_KERNEL_PMAC_PIC_H
+/*
+ * BK Id: SCCS/s.pmac_setup.c 1.21 05/17/01 18:14:21 cort
+ */
/*
* linux/arch/ppc/kernel/setup.c
*
+/*
+ * BK Id: SCCS/s.pmac_time.c 1.8 05/17/01 18:14:21 cort
+ */
/*
* Support for periodic interrupts (100 per second) and for getting
* the current time from the RTC on Power Macintoshes.
-/* $Id: ppc-stub.c,v 1.6 1999/08/12 22:18:11 cort Exp $
+/*
+ * BK Id: SCCS/s.ppc-stub.c 1.6 05/17/01 18:14:21 cort
+ */
+/*
* ppc-stub.c: KGDB support for the Linux kernel.
*
* adapted from arch/sparc/kernel/sparc-stub.c for the PowerPC
+/*
+ * BK Id: SCCS/s.ppc4xx_pic.c 1.5 05/17/01 18:14:21 cort
+ */
/*
*
* Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+/*
+ * BK Id: SCCS/s.ppc4xx_pic.h 1.5 05/17/01 18:14:21 cort
+ */
/*
*
* Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+/*
+ * BK Id: SCCS/s.ppc8260_pic.c 1.5 05/17/01 18:14:21 cort
+ */
#include <linux/stddef.h>
#include <linux/init.h>
+/*
+ * BK Id: SCCS/s.ppc8260_pic.h 1.7 05/17/01 18:14:21 cort
+ */
#ifndef _PPC_KERNEL_PPC8260_H
#define _PPC_KERNEL_PPC8260_H
+/*
+ * BK Id: SCCS/s.ppc8xx_pic.c 1.10 05/17/01 18:14:21 cort
+ */
#include <linux/config.h>
#include <linux/stddef.h>
#include <linux/init.h>
+/*
+ * BK Id: SCCS/s.ppc8xx_pic.h 1.7 05/17/01 18:14:21 cort
+ */
#ifndef _PPC_KERNEL_PPC8xx_H
#define _PPC_KERNEL_PPC8xx_H
+/*
+ * BK Id: SCCS/s.ppc_asm.h 1.10 05/17/01 18:14:21 cort
+ */
/*
* arch/ppc/kernel/ppc_asm.h
*
/*
- * $Id: ppc_htab.c,v 1.29 1999/09/10 05:05:50 paulus Exp $
- *
+ * BK Id: SCCS/s.ppc_htab.c 1.8 05/17/01 18:14:21 cort
+ */
+/*
* PowerPC hash table management proc entry. Will show information
* about the current hash table and will allow changes to it.
*
+/*
+ * BK Id: SCCS/s.ppc_ksyms.c 1.31 05/18/01 08:18:10 patch
+ */
#include <linux/config.h>
#include <linux/module.h>
#include <linux/threads.h>
EXPORT_SYMBOL(kernel_flag);
#endif /* CONFIG_SMP */
-#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
-EXPORT_SYMBOL_NOVERS(isa_io_base);
-EXPORT_SYMBOL_NOVERS(isa_mem_base);
-EXPORT_SYMBOL_NOVERS(pci_dram_offset);
-#endif
EXPORT_SYMBOL(ISA_DMA_THRESHOLD);
EXPORT_SYMBOL_NOVERS(DMA_MODE_READ);
EXPORT_SYMBOL(DMA_MODE_WRITE);
-#ifndef CONFIG_8xx
#if defined(CONFIG_ALL_PPC)
EXPORT_SYMBOL(_prep_type);
EXPORT_SYMBOL(ucSystemType);
#endif
-#endif
#if !__INLINE_BITOPS
EXPORT_SYMBOL(set_bit);
#endif
#ifdef CONFIG_PCI
+EXPORT_SYMBOL_NOVERS(isa_io_base);
+EXPORT_SYMBOL_NOVERS(isa_mem_base);
+EXPORT_SYMBOL_NOVERS(pci_dram_offset);
EXPORT_SYMBOL(pci_alloc_consistent);
EXPORT_SYMBOL(pci_free_consistent);
#endif /* CONFIG_PCI */
EXPORT_SYMBOL(synchronize_irq);
#endif
-#ifndef CONFIG_MACH_SPECIFIC
-EXPORT_SYMBOL(_machine);
-#endif
EXPORT_SYMBOL(ppc_md);
#ifdef CONFIG_ADB
EXPORT_SYMBOL(set_backlight_enable);
EXPORT_SYMBOL(register_backlight_controller);
#endif /* CONFIG_PMAC_BACKLIGHT */
-#ifndef CONFIG_MACH_SPECIFIC
-EXPORT_SYMBOL_NOVERS(have_of);
-#endif /* CONFIG_MACH_SPECIFIC */
#if defined(CONFIG_ALL_PPC)
+EXPORT_SYMBOL(_machine);
+EXPORT_SYMBOL_NOVERS(have_of);
EXPORT_SYMBOL_NOVERS(sys_ctrler);
EXPORT_SYMBOL(find_devices);
EXPORT_SYMBOL(find_type_devices);
+/*
+ * BK Id: SCCS/s.prep_nvram.c 1.9 05/17/01 18:14:22 cort
+ */
/*
* linux/arch/ppc/kernel/prep_nvram.c
*
/*
- * $Id: prep_pci.c,v 1.40 1999/09/17 17:23:05 cort Exp $
+ * BK Id: SCCS/s.prep_pci.c 1.18 05/17/01 18:14:22 cort
+ */
+/*
* PReP pci functions.
* Originally by Gary Thomas
* rewritten and updated by Cort Dougan (cort@cs.nmt.edu)
+/*
+ * BK Id: SCCS/s.prep_setup.c 1.20 05/21/01 09:19:50 trini
+ */
/*
* linux/arch/ppc/kernel/setup.c
*
extern int probingmem;
extern unsigned long loops_per_jiffy;
+#ifdef CONFIG_BLK_DEV_RAM
+extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */
+extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */
+extern int rd_image_start; /* starting block # of image */
+#endif
+
+#ifdef CONFIG_SOUND_MODULE
+EXPORT_SYMBOL(ppc_cs4232_dma);
+EXPORT_SYMBOL(ppc_cs4232_dma2);
+#endif
+
int __prep
prep_get_cpuinfo(char *buffer)
{
case _PREP_Motorola:
/* Enable L2. Assume we don't need to flush -- Cort*/
*(unsigned char *)(0x8000081c) |= 3;
- ROOT_DEV = to_kdev_t(0x0802); /* sda2 */
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); /* /dev/ram */
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = to_kdev_t(0x00ff); /* /dev/nfs */
+#else
+ ROOT_DEV = to_kdev_t(0x0802); /* /dev/sda2 */
+#endif
break;
}
/* remap the VGA memory */
vgacon_remap_base = 0xf0000000;
/*vgacon_remap_base = ioremap(0xc0000000, 0xba000);*/
- conswitchp = &vga_con;
-#else
+ conswitchp = &vga_con;
+#elif defined(CONFIG_DUMMY_CONSOLE)
conswitchp = &dummy_con;
#endif
}
}
#endif
+#ifdef CONFIG_BLK_DEV_INITRD
+ if ( r4 )
+ {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
/* Copy cmd_line parameters */
if ( r6)
{
#endif
#endif
}
-
-#ifdef CONFIG_SOUND_MODULE
-EXPORT_SYMBOL(ppc_cs4232_dma);
-EXPORT_SYMBOL(ppc_cs4232_dma2);
-#endif
+/*
+ * BK Id: SCCS/s.prep_time.c 1.7 05/17/01 18:14:22 cort
+ */
/*
* linux/arch/i386/kernel/time.c
*
+/*
+ * BK Id: SCCS/s.proc_rtas.c 1.5 05/17/01 18:14:22 cort
+ */
/*
* arch/ppc/kernel/proc_rtas.c
* Copyright (C) 2000 Tilmann Bitterberg
/*
- * $Id: process.c,v 1.97 1999/09/14 19:07:42 cort Exp $
- *
+ * BK Id: SCCS/s.process.c 1.15 05/17/01 18:14:22 cort
+ */
+/*
* linux/arch/ppc/kernel/process.c
*
* Derived from "arch/i386/kernel/process.c"
/*
- * $Id: prom.c,v 1.79 1999/10/08 01:56:32 paulus Exp $
- *
+ * BK Id: SCCS/s.prom.c 1.17 05/17/01 18:14:22 cort
+ */
+/*
* Procedures for interfacing to the Open Firmware PROM on
* Power Macintosh computers.
*
+/*
+ * BK Id: SCCS/s.ptrace.c 1.5 05/17/01 18:14:22 cort
+ */
/*
* linux/arch/ppc/kernel/ptrace.c
*
+/*
+ * BK Id: SCCS/s.qspan_pci.c 1.5 05/17/01 18:14:22 cort
+ */
/*
* QSpan pci routines.
* Most 8xx boards use the QSpan PCI bridge. The config address register
/*
- * $Id: residual.c,v 1.17 1999/09/27 18:40:23 cort Exp $
- *
+ * BK Id: SCCS/s.residual.c 1.7 05/17/01 18:14:22 cort
+ */
+/*
* Code to deal with the PReP residual data.
*
* Written by: Cort Dougan (cort@cs.nmt.edu)
/*
- * $Id: semaphore.c,v 1.1 1999/08/31 15:11:44 cort Exp $
- *
+ * BK Id: SCCS/s.semaphore.c 1.12 05/17/01 18:14:22 cort
+ */
+/*
* PowerPC-specific semaphore code.
*
* Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
/*
- * $Id: setup.c,v 1.160 1999/10/08 01:56:38 paulus Exp $
+ * BK Id: SCCS/s.setup.c 1.23 05/21/01 16:08:53 cort
+ */
+/*
* Common prep/pmac/chrp boot and setup code.
*/
unsigned long ISA_DMA_THRESHOLD;
unsigned long DMA_MODE_READ, DMA_MODE_WRITE;
-#ifndef CONFIG_MACH_SPECIFIC
+#ifdef CONFIG_ALL_PPC
int _machine = 0;
int have_of = 0;
-#endif /* CONFIG_MACH_SPECIFIC */
+#endif /* CONFIG_ALL_PPC */
#ifdef CONFIG_MAGIC_SYSRQ
unsigned long SYSRQ_KEY;
return len;
}
-#ifndef CONFIG_MACH_SPECIFIC
+#ifdef CONFIG_ALL_PPC
void __init
intuit_machine_type(void)
{
}
}
}
-#endif /* CONFIG_MACH_SPECIFIC */
+#endif /* CONFIG_ALL_PPC */
/*
* Find out what kind of machine we're on and save any data we need
if ( ppc_md.progress ) ppc_md.progress("id mach(): start", 0x100);
-#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) && !defined(CONFIG_8260)
-#ifndef CONFIG_MACH_SPECIFIC
+#ifdef CONFIG_ALL_PPC
/* if we didn't get any bootinfo telling us what we are... */
if ( _machine == 0 )
{
- /* boot loader will tell us if we're APUS */
- if ( r3 == 0x61707573 )
- {
- _machine = _MACH_apus;
- r3 = 0;
- }
/* prep boot loader tells us if we're prep or not */
- else if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) )
+ if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) )
{
_machine = _MACH_prep;
} else
have_of = 1;
}
-#endif /* CONFIG_MACH_SPECIFIC */
if ( have_of )
{
/* prom_init has already been called from __start */
if (boot_infos)
relocate_nodes();
-#ifndef CONFIG_MACH_SPECIFIC
/* we need to set _machine before calling finish_device_tree */
if (_machine == 0)
intuit_machine_type();
-#endif /* CONFIG_MACH_SPECIFIC */
finish_device_tree();
/*
* If we were booted via quik, r3 points to the physical
sizeof(cmd_line));
} else if (boot_infos != 0) {
/* booted by BootX - check for ramdisk */
- if (boot_infos->kernelParamsOffset != 0)
+ if (boot_infos->kernelParamsOffset != 0)
strncpy(cmd_line, (char *) boot_infos
+ boot_infos->kernelParamsOffset,
sizeof(cmd_line));
chosen = find_devices("chosen");
if (chosen != NULL) {
p = get_property(chosen, "bootargs", NULL);
- if (p != NULL)
+ if (p != NULL) {
+ cmd_line[0] = 0;
strncpy(cmd_line, p, sizeof(cmd_line));
+ }
}
}
cmd_line[sizeof(cmd_line) - 1] = 0;
}
+#endif /* CONFIG_ALL_PPC */
+#if defined(CONFIG_ALL_PPC)
switch (_machine)
{
case _MACH_Pmac:
case _MACH_chrp:
chrp_init(r3, r4, r5, r6, r7);
break;
-#ifdef CONFIG_APUS
- case _MACH_apus:
- apus_init(r3, r4, r5, r6, r7);
- break;
-#endif
-#ifdef CONFIG_GEMINI
- case _MACH_gemini:
- gemini_init(r3, r4, r5, r6, r7);
- break;
-#endif
default:
printk("Unknown machine type in identify_machine!\n");
}
-
- /* Check for nobats option (used in mapin_ram). */
- if (strstr(cmd_line, "nobats")) {
- extern int __map_without_bats;
- __map_without_bats = 1;
- }
-#else
-#if defined(CONFIG_4xx)
+#elif defined(CONFIG_APUS)
+ apus_init(r3, r4, r5, r6, r7);
+#elif defined(CONFIG_GEMINI)
+ gemini_init(r3, r4, r5, r6, r7);
+#elif defined(CONFIG_4xx)
oak_init(r3, r4, r5, r6, r7);
#elif defined(CONFIG_8xx)
m8xx_init(r3, r4, r5, r6, r7);
m8260_init(r3, r4, r5, r6, r7);
#else
#error "No board type has been defined for identify_machine()!"
-#endif /* CONFIG_4xx */
-#endif /* !CONFIG_4xx && !CONFIG_8xx */
+#endif
+
+#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) && !defined(CONFIG_8260)
+ /* Check for nobats option (used in mapin_ram). */
+ if (strstr(cmd_line, "nobats")) {
+ extern int __map_without_bats;
+ __map_without_bats = 1;
+ }
+#endif /* !CONFIG_4xx && !CONFIG_8xx && !CONFIG_8260 */
/* Look for mem= option on command line */
if (strstr(cmd_line, "mem=")) {
initrd_end = data[0] + rec->size;
break;
#endif /* CONFIG_BLK_DEV_INITRD */
-#ifndef CONFIG_MACH_SPECIFIC
+#ifdef CONFIG_ALL_PPC
case BI_MACHTYPE:
_machine = data[0];
have_of = data[1];
break;
-#endif /* CONFIG_MACH_SPECIFIC */
+#endif /* CONFIG_ALL_PPC */
}
}
+/*
+ * BK Id: SCCS/s.signal.c 1.7 05/17/01 18:14:22 cort
+ */
/*
* linux/arch/ppc/kernel/signal.c
*
+/*
+ * BK Id: SCCS/s.sleep.S 1.7 05/17/01 18:14:22 cort
+ */
/*
* This file contains sleep low-level functions for PowerBook G3.
* Copyright (C) 1999 Benjamin Herrenschmidt (benh@kernel.crashing.org)
+/*
+ * BK Id: SCCS/s.smp.c 1.23 05/17/01 18:14:22 cort
+ */
/*
* Smp support for ppc.
*
+/*
+ * BK Id: SCCS/s.softemu8xx.c 1.8 05/17/01 18:14:22 cort
+ */
/*
* Software emulation of some PPC instructions for the 8xx core.
*
+/*
+ * BK Id: SCCS/s.syscalls.c 1.8 05/17/01 18:14:22 cort
+ */
/*
* linux/arch/ppc/kernel/sys_ppc.c
*
/*
- * $Id: time.c,v 1.57 1999/10/21 03:08:16 cort Exp $
+ * BK Id: SCCS/s.time.c 1.15 05/17/01 18:14:22 cort
+ */
+/*
* Common time routines among all ppc machines.
*
* Written by Cort Dougan (cort@cs.nmt.edu) to merge
+/*
+ * BK Id: SCCS/s.traps.c 1.11 05/17/01 18:14:22 cort
+ */
/*
* linux/arch/ppc/kernel/traps.c
*
+/*
+ * BK Id: SCCS/s.walnut_setup.c 1.5 05/17/01 18:14:22 cort
+ */
/*
*
* Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
+/*
+ * BK Id: SCCS/s.walnut_setup.h 1.5 05/17/01 18:14:22 cort
+ */
/*
*
* Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
+/*
+ * BK Id: SCCS/s.xics.c 1.5 05/17/01 18:14:22 cort
+ */
/*
* arch/ppc/kernel/xics.c
*
+/*
+ * BK Id: SCCS/s.xics.h 1.5 05/17/01 18:14:22 cort
+ */
/*
* arch/ppc/kernel/xics.h
*
+# BK Id: SCCS/s.Makefile 1.7 05/17/01 18:14:22 cort
+#
#
# Makefile for ppc-specific library files..
#
+/*
+ * BK Id: SCCS/s.checksum.S 1.5 05/17/01 18:14:22 cort
+ */
/*
* This file contains assembly-language implementations
* of IP-style 1's complement checksum routines.
/*
- * $Id: locks.c,v 1.25 1999/09/10 10:40:13 davem Exp $
- *
+ * BK Id: SCCS/s.locks.c 1.8 05/17/01 18:14:22 cort
+ */
+/*
* Locks for smp ppc
*
* Written by Cort Dougan (cort@cs.nmt.edu)
+/*
+ * BK Id: SCCS/s.strcase.c 1.5 05/17/01 18:14:22 cort
+ */
#include <linux/ctype.h>
int strcasecmp(const char *s1, const char *s2)
+/*
+ * BK Id: SCCS/s.string.S 1.5 05/17/01 18:14:22 cort
+ */
/*
* String handling functions for PowerPC.
*
+# BK Id: SCCS/s.Makefile 1.3 05/17/01 18:14:22 cort
+#
#
#
#
+/*
+ * BK Id: SCCS/s.double.h 1.5 05/17/01 18:14:22 cort
+ */
/*
* Definitions for IEEE Double Precision
*/
-/* $Id: fabs.c,v 1.1 1999/08/23 18:59:21 cort Exp $
+/*
+ * BK Id: SCCS/s.fabs.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: fadd.c,v 1.1 1999/08/23 18:59:22 cort Exp $
+/*
+ * BK Id: SCCS/s.fadd.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: fadds.c,v 1.1 1999/08/23 18:59:25 cort Exp $
+/*
+ * BK Id: SCCS/s.fadds.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: fcmpo.c,v 1.1 1999/08/23 18:59:26 cort Exp $
+/*
+ * BK Id: SCCS/s.fcmpo.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: fcmpu.c,v 1.1 1999/08/23 18:59:28 cort Exp $
+/*
+ * BK Id: SCCS/s.fcmpu.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: fctiw.c,v 1.1 1999/08/23 18:59:30 cort Exp $
+/*
+ * BK Id: SCCS/s.fctiw.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: fctiwz.c,v 1.1 1999/08/23 18:59:31 cort Exp $
+/*
+ * BK Id: SCCS/s.fctiwz.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: fdiv.c,v 1.1 1999/08/23 18:59:33 cort Exp $
+/*
+ * BK Id: SCCS/s.fdiv.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: fdivs.c,v 1.1 1999/08/23 18:59:35 cort Exp $
+/*
+ * BK Id: SCCS/s.fdivs.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: fmadd.c,v 1.1 1999/08/23 18:59:36 cort Exp $
+/*
+ * BK Id: SCCS/s.fmadd.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: fmadds.c,v 1.1 1999/08/23 18:59:38 cort Exp $
+/*
+ * BK Id: SCCS/s.fmadds.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: fmr.c,v 1.1 1999/08/23 18:59:40 cort Exp $
+/*
+ * BK Id: SCCS/s.fmr.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: fmsub.c,v 1.1 1999/08/23 18:59:41 cort Exp $
+/*
+ * BK Id: SCCS/s.fmsub.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: fmsubs.c,v 1.1 1999/08/23 18:59:42 cort Exp $
+/*
+ * BK Id: SCCS/s.fmsubs.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: fmul.c,v 1.1 1999/08/23 18:59:44 cort Exp $
+/*
+ * BK Id: SCCS/s.fmul.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: fmuls.c,v 1.1 1999/08/23 18:59:45 cort Exp $
+/*
+ * BK Id: SCCS/s.fmuls.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: fnabs.c,v 1.1 1999/08/23 18:59:47 cort Exp $
+/*
+ * BK Id: SCCS/s.fnabs.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: fneg.c,v 1.1 1999/08/23 18:59:48 cort Exp $
+/*
+ * BK Id: SCCS/s.fneg.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: fnmadd.c,v 1.1 1999/08/23 18:59:50 cort Exp $
+/*
+ * BK Id: SCCS/s.fnmadd.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: fnmadds.c,v 1.1 1999/08/23 18:59:51 cort Exp $
+/*
+ * BK Id: SCCS/s.fnmadds.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: fnmsub.c,v 1.1 1999/08/23 18:59:53 cort Exp $
+/*
+ * BK Id: SCCS/s.fnmsub.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: fnmsubs.c,v 1.1 1999/08/23 18:59:54 cort Exp $
+/*
+ * BK Id: SCCS/s.fnmsubs.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: fres.c,v 1.1 1999/08/23 18:59:56 cort Exp $
+/*
+ * BK Id: SCCS/s.fres.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: frsp.c,v 1.1 1999/08/23 18:59:57 cort Exp $
+/*
+ * BK Id: SCCS/s.frsp.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: frsqrte.c,v 1.1 1999/08/23 18:59:58 cort Exp $
+/*
+ * BK Id: SCCS/s.frsqrte.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: fsel.c,v 1.1 1999/08/23 18:59:59 cort Exp $
+/*
+ * BK Id: SCCS/s.fsel.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: fsqrt.c,v 1.1 1999/08/23 19:00:01 cort Exp $
+/*
+ * BK Id: SCCS/s.fsqrt.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: fsqrts.c,v 1.1 1999/08/23 19:00:03 cort Exp $
+/*
+ * BK Id: SCCS/s.fsqrts.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: fsub.c,v 1.1 1999/08/23 19:00:05 cort Exp $
+/*
+ * BK Id: SCCS/s.fsub.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: fsubs.c,v 1.1 1999/08/23 19:00:07 cort Exp $
+/*
+ * BK Id: SCCS/s.fsubs.c 1.6 05/17/01 18:14:22 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: lfd.c,v 1.1 1999/08/23 19:00:08 cort Exp $
+/*
+ * BK Id: SCCS/s.lfd.c 1.6 05/17/01 18:14:23 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: lfs.c,v 1.1 1999/08/23 19:00:10 cort Exp $
+/*
+ * BK Id: SCCS/s.lfs.c 1.6 05/17/01 18:14:23 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: math.c,v 1.1 1999/08/23 19:00:11 cort Exp $
+/*
+ * BK Id: SCCS/s.math.c 1.6 05/17/01 18:14:23 cort
+ */
+/*
* arch/ppc/math-emu/math.c
*
* Copyright (C) 1999 Eddie C. Dost (ecd@atecom.com)
-/* $Id: mcrfs.c,v 1.1 1999/08/23 19:00:13 cort Exp $
+/*
+ * BK Id: SCCS/s.mcrfs.c 1.6 05/17/01 18:14:23 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: mffs.c,v 1.1 1999/08/23 19:00:14 cort Exp $
+/*
+ * BK Id: SCCS/s.mffs.c 1.6 05/17/01 18:14:23 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: mtfsb0.c,v 1.1 1999/08/23 19:00:16 cort Exp $
+/*
+ * BK Id: SCCS/s.mtfsb0.c 1.6 05/17/01 18:14:23 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: mtfsb1.c,v 1.1 1999/08/23 19:00:17 cort Exp $
+/*
+ * BK Id: SCCS/s.mtfsb1.c 1.6 05/17/01 18:14:23 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: mtfsf.c,v 1.1 1999/08/23 19:00:19 cort Exp $
+/*
+ * BK Id: SCCS/s.mtfsf.c 1.6 05/17/01 18:14:23 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: mtfsfi.c,v 1.1 1999/08/23 19:00:20 cort Exp $
+/*
+ * BK Id: SCCS/s.mtfsfi.c 1.6 05/17/01 18:14:23 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
+/*
+ * BK Id: SCCS/s.op-1.h 1.5 05/17/01 18:14:23 cort
+ */
/*
* Basic one-word fraction declaration and manipulation.
*/
+/*
+ * BK Id: SCCS/s.op-2.h 1.5 05/17/01 18:14:23 cort
+ */
/*
* Basic two-word fraction declaration and manipulation.
*/
+/*
+ * BK Id: SCCS/s.op-4.h 1.5 05/17/01 18:14:23 cort
+ */
/*
* Basic four-word fraction declaration and manipulation.
*
+/*
+ * BK Id: SCCS/s.op-common.h 1.5 05/17/01 18:14:23 cort
+ */
#define _FP_DECL(wc, X) \
_FP_I_TYPE X##_c, X##_s, X##_e; \
+/*
+ * BK Id: SCCS/s.sfp-machine.h 1.5 05/17/01 18:14:23 cort
+ */
/* Machine-dependent software floating-point definitions. PPC version.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
+/*
+ * BK Id: SCCS/s.single.h 1.5 05/17/01 18:14:23 cort
+ */
/*
* Definitions for IEEE Single Precision
*/
+/*
+ * BK Id: SCCS/s.soft-fp.h 1.5 05/17/01 18:14:23 cort
+ */
#ifndef SOFT_FP_H
#define SOFT_FP_H
-/* $Id: stfd.c,v 1.1 1999/08/23 19:00:33 cort Exp $
+/*
+ * BK Id: SCCS/s.stfd.c 1.6 05/17/01 18:14:23 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: stfiwx.c,v 1.1 1999/08/23 19:00:34 cort Exp $
+/*
+ * BK Id: SCCS/s.stfiwx.c 1.6 05/17/01 18:14:23 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
-/* $Id: stfs.c,v 1.1 1999/08/23 19:00:35 cort Exp $
+/*
+ * BK Id: SCCS/s.stfs.c 1.6 05/17/01 18:14:23 cort
*/
-
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
+/*
+ * BK Id: SCCS/s.types.c 1.5 05/17/01 18:14:23 cort
+ */
#include "soft-fp.h"
#include "double.h"
+/*
+ * BK Id: SCCS/s.udivmodti4.c 1.5 05/17/01 18:14:23 cort
+ */
/* This has so very few changes over libgcc2's __udivmoddi4 it isn't funny. */
#include "soft-fp.h"
+++ /dev/null
-#!/bin/bash
-
-OFFSET=`$1 -h $2 | grep $3 | grep -v zvmlinux| awk '{print $6}'`
-echo "0x"$OFFSET
+++ /dev/null
-#!/bin/bash
-
-OFFSET=`$1 -h $2 | grep $3 | grep -v zvmlinux | awk '{print $3}'`
-echo "0x"$OFFSET
+/*
+ * BK Id: SCCS/s.4xx_tlb.c 1.5 05/17/01 18:14:23 cort
+ */
/*
*
* Copyright (c) 1998-1999 TiVo, Inc.
+/*
+ * BK Id: SCCS/s.4xx_tlb.h 1.5 05/17/01 18:14:23 cort
+ */
/*
*
* Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+# BK Id: SCCS/s.Makefile 1.3 05/17/01 18:14:23 cort
+#
#
# Makefile for the linux ppc-specific parts of the memory manager.
#
+/*
+ * BK Id: SCCS/s.extable.c 1.5 05/17/01 18:14:23 cort
+ */
/*
* linux/arch/ppc/mm/extable.c
*
+/*
+ * BK Id: SCCS/s.fault.c 1.10 05/17/01 18:14:23 cort
+ */
/*
* arch/ppc/mm/fault.c
*
/*
- * $Id: init.c,v 1.195 1999/10/15 16:39:39 cort Exp $
- *
+ * BK Id: SCCS/s.init.c 1.22 05/17/01 18:14:23 cort
+ */
+/*
* PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
*
+/*
+ * BK Id: SCCS/s.mem_pieces.c 1.5 05/17/01 18:14:23 cort
+ */
/*
* Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
* Changes to accomodate Power Macintoshes.
+/*
+ * BK Id: SCCS/s.mem_pieces.h 1.5 05/17/01 18:14:23 cort
+ */
/*
* Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
* Changes to accomodate Power Macintoshes.
+++ /dev/null
-/*
- * Copyright (c) 1997 Paul Mackerras <paulus@cs.anu.edu.au>
- * Initial Power Macintosh COFF version.
- * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
- * Modifications for IBM PowerPC 400-class processor evaluation
- * boards.
- *
- * Module name: crt0.S
- *
- * Description:
- * Boot loader execution entry point. Clears out .bss section as per
- * ANSI C requirements. Invalidates and flushes the caches over the
- * range covered by the boot loader's .text section. Sets up a stack
- * below the .text section entry point.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- */
-
-#include "../kernel/ppc_asm.tmpl"
-
- .text
-
- .globl _start
-_start:
- ## Clear out the BSS as per ANSI C requirements
-
- lis r7,_end@ha #
- addi r7,r7,_end@l # r7 = &_end
- lis r8,__bss_start@ha #
- addi r8,r8,__bss_start@l # r8 = &_bss_start
-
- ## Determine how large an area, in number of words, to clear
-
- subf r7,r8,r7 # r7 = &_end - &_bss_start + 1
- addi r7,r7,3 # r7 += 3
- srwi. r7,r7,2 # r7 = size in words.
- beq 2f # If the size is zero, do not bother
- addi r8,r8,-4 # r8 -= 4
- mtctr r7 # SPRN_CTR = number of words to clear
- li r0,0 # r0 = 0
-1: stwu r0,4(r8) # Clear out a word
- bdnz 1b # If we are not done yet, keep clearing
-
- ## Flush and invalidate the caches for the range in memory covering
- ## the .text section of the boot loader
-
-2: lis r9,_start@h # r9 = &_start
- lis r8,_etext@ha #
- addi r8,r8,_etext@l # r8 = &_etext
-3: dcbf r0,r9 # Flush the data cache
- icbi r0,r9 # Invalidate the instruction cache
- addi r9,r9,0x10 # Increment by one cache line
- cmplwi cr0,r9,r8 # Are we at the end yet?
- blt 3b # No, keep flushing and invalidating
-
- ## Set up the stack
-
- lis r9,_start@h # r9 = &_start (text section entry)
- addi r9,r9,_start@l
- subi r1,r9,64 # Start the stack 64 bytes below _start
- clrrwi r1,r1,4 # Make sure it is aligned on 16 bytes.
- li r0,0
- stwu r0,-16(r1)
- mtlr r9
-
- b start # All done, start the real work.
+# BK Id: SCCS/s.Makefile 1.3 05/17/01 18:14:23 cort
+#
# Makefile for xmon
O_TARGET := x.o
+/*
+ * BK Id: SCCS/s.adb.c 1.5 05/17/01 18:14:23 cort
+ */
/*
* Copyright (C) 1996 Paul Mackerras.
*/
+/*
+ * BK Id: SCCS/s.ansidecl.h 1.5 05/17/01 18:14:23 cort
+ */
/* ANSI and traditional C compatability macros
Copyright 1991, 1992 Free Software Foundation, Inc.
This file is part of the GNU C Library.
+/*
+ * BK Id: SCCS/s.nonstdio.h 1.5 05/17/01 18:14:23 cort
+ */
typedef int FILE;
extern FILE *xmon_stdin, *xmon_stdout;
#define EOF (-1)
+/*
+ * BK Id: SCCS/s.ppc-dis.c 1.5 05/17/01 18:14:23 cort
+ */
/* ppc-dis.c -- Disassemble PowerPC instructions
Copyright 1994 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support
+/*
+ * BK Id: SCCS/s.ppc-opc.c 1.5 05/17/01 18:14:23 cort
+ */
/* ppc-opc.c -- PowerPC opcode list
Copyright 1994 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support
+/*
+ * BK Id: SCCS/s.ppc.h 1.5 05/17/01 18:14:23 cort
+ */
/* ppc.h -- Header file for PowerPC opcode table
Copyright 1994 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support
+/*
+ * BK Id: SCCS/s.privinst.h 1.5 05/17/01 18:14:23 cort
+ */
/*
* Copyright (C) 1996 Paul Mackerras.
*/
+/*
+ * BK Id: SCCS/s.setjmp.c 1.5 05/17/01 18:14:23 cort
+ */
/*
* Copyright (C) 1996 Paul Mackerras.
*
+/*
+ * BK Id: SCCS/s.start.c 1.12 05/21/01 21:39:13 paulus
+ */
/*
* Copyright (C) 1996 Paul Mackerras.
*/
static int console;
static int use_screen;
-static int via_modem = 1;
+static int via_modem;
static int xmon_use_sccb;
static struct device_node *macio_node;
+/*
+ * BK Id: SCCS/s.start_8xx.c 1.7 05/17/01 18:14:23 cort
+ */
/*
* Copyright (C) 1996 Paul Mackerras.
* Copyright (C) 2000 Dan Malek.
+/*
+ * BK Id: SCCS/s.subr_prf.c 1.5 05/17/01 18:14:23 cort
+ */
/*
* Written by Cort Dougan to replace the version originally used
* by Paul Mackerras, which came from NetBSD and thus had copyright
+/*
+ * BK Id: SCCS/s.xmon.c 1.9 05/17/01 18:14:24 cort
+ */
/*
* Routines providing a simple monitor for use on the PowerMac.
*
* GPIO pin support for HD64465 companion chip.
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <asm/io.h>
#include <asm/machvec.h>
+#include <linux/config.h>
#include <linux/module.h>
#define SH3_PCMCIA_BUG_WORKAROUND 1
* I/O routines for SEGA Dreamcast
*/
-#include <linux/config.h>
#include <asm/io.h>
#include <asm/machvec.h>
* (prumpf@tux.org).
*/
-
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <asm/io.h>
* Hitachi 7751 and the STM ST40 STB1.
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/irq.h>
* SEGA Dreamcast machine vector
*/
+#include <linux/config.h>
#include <linux/init.h>
#include <asm/machvec.h>
* SEGA Dreamcast support
*/
-#include <linux/config.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/param.h>
* (prumpf@tux.org).
*/
-#include <linux/config.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/param.h>
*
*/
+#include <linux/config.h>
#include <linux/init.h>
#include <linux/mman.h>
#include <linux/mm.h>
-# $Id: config.in,v 1.109 2001/04/18 21:06:05 davem Exp $
+# $Id: config.in,v 1.110 2001/05/20 05:14:46 davem Exp $
# For a description of the syntax of this configuration file,
# see Documentation/kbuild/config-language.txt.
#
dep_tristate ' SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
- if [ "$CONFIG_BLK_DEV_ST" != "n" ]; then
- int 'Maximum number of SCSI tapes that can be loaded as modules' CONFIG_ST_EXTRA_DEVS 2
- fi
+ dep_tristate ' SCSI OnStream SC-x0 tape support' CONFIG_CHR_DEV_OSST $CONFIG_SCSI
dep_tristate ' SCSI CDROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
-# $Id: config.in,v 1.142 2001/05/05 07:46:04 davem Exp $
+# $Id: config.in,v 1.143 2001/05/20 05:14:46 davem Exp $
# For a description of the syntax of this configuration file,
# see the Configure script.
#
dep_tristate ' SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
- if [ "$CONFIG_BLK_DEV_ST" != "n" ]; then
- int 'Maximum number of SCSI tapes that can be loaded as modules' CONFIG_ST_EXTRA_DEVS 2
- fi
+ dep_tristate ' SCSI OnStream SC-x0 tape support' CONFIG_CHR_DEV_OSST $CONFIG_SCSI
dep_tristate ' SCSI CDROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
CONFIG_BLK_DEV_SD=y
CONFIG_SD_EXTRA_DEVS=40
CONFIG_CHR_DEV_ST=y
-CONFIG_ST_EXTRA_DEVS=2
+CONFIG_CHR_DEV_OSST=m
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_SR_EXTRA_DEVS=2
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/threads.h>
#include <linux/init.h>
-/* $Id: semaphore.c,v 1.6 2001/04/14 01:12:02 davem Exp $
- * Generic semaphore code. Buyer beware. Do your own
- * specific changes in <asm/semaphore-helper.h>
+/* $Id: semaphore.c,v 1.8 2001/05/18 08:01:35 davem Exp $
+ * semaphore.c: Sparc64 semaphore implementation.
+ *
+ * This is basically the PPC semaphore scheme ported to use
+ * the sparc64 atomic instructions, so see the PPC code for
+ * credits.
*/
#include <linux/sched.h>
-#include <asm/semaphore-helper.h>
/*
- * Semaphores are implemented using a two-way counter:
- * The "count" variable is decremented for each process
- * that tries to sleep, while the "waking" variable is
- * incremented when the "up()" code goes to wake up waiting
- * processes.
- *
- * Notably, the inline "up()" and "down()" functions can
- * efficiently test if they need to do any extra work (up
- * needs to do something only if count was negative before
- * the increment operation.
- *
- * waking_non_zero() (from asm/semaphore.h) must execute
- * atomically.
- *
- * When __up() is called, the count was negative before
- * incrementing it, and we need to wake up somebody.
+ * Atomically update sem->count.
+ * This does the equivalent of the following:
*
- * This routine adds one to the count of processes that need to
- * wake up and exit. ALL waiting processes actually wake up but
- * only the one that gets to the "waking" field first will gate
- * through and acquire the semaphore. The others will go back
- * to sleep.
- *
- * Note that these functions are only called when there is
- * contention on the lock, and as such all this is the
- * "non-critical" part of the whole semaphore business. The
- * critical part is the inline stuff in <asm/semaphore.h>
- * where we want to avoid any extra jumps and calls.
+ * old_count = sem->count;
+ * tmp = MAX(old_count, 0) + incr;
+ * sem->count = tmp;
+ * return old_count;
*/
+static __inline__ int __sem_update_count(struct semaphore *sem, int incr)
+{
+ int old_count, tmp;
+
+ __asm__ __volatile__("\n"
+" ! __sem_update_count old_count(%0) tmp(%1) incr(%4) &sem->count(%3)\n"
+"1: ldsw [%3], %0\n"
+" mov %0, %1\n"
+" cmp %0, 0\n"
+" movl %%icc, 0, %1\n"
+" add %1, %4, %1\n"
+" cas [%3], %0, %1\n"
+" cmp %0, %1\n"
+" bne,pn %%icc, 1b\n"
+" nop\n"
+ : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
+ : "r" (&sem->count), "r" (incr), "m" (sem->count)
+ : "cc");
+
+ return old_count;
+}
+
void __up(struct semaphore *sem)
{
- wake_one_more(sem);
+ __sem_update_count(sem, 1);
wake_up(&sem->wait);
}
-/*
- * Perform the "down" function. Return zero for semaphore acquired,
- * return negative for signalled out of the function.
- *
- * If called from __down, the return is ignored and the wait loop is
- * not interruptible. This means that a task waiting on a semaphore
- * using "down()" cannot be killed until someone does an "up()" on
- * the semaphore.
- *
- * If called from __down_interruptible, the return value gets checked
- * upon return. If the return value is negative then the task continues
- * with the negative value in the return register (it can be tested by
- * the caller).
- *
- * Either form may be used in conjunction with "up()".
- *
- */
-
-#define DOWN_VAR \
- struct task_struct *tsk = current; \
+void __down(struct semaphore * sem)
+{
+ struct task_struct *tsk = current;
DECLARE_WAITQUEUE(wait, tsk);
-#define DOWN_HEAD(task_state) \
- \
- \
- tsk->state = (task_state); \
- add_wait_queue(&sem->wait, &wait); \
- \
- /* \
- * Ok, we're set up. sem->count is known to be less than zero \
- * so we must wait. \
- * \
- * We can let go the lock for purposes of waiting. \
- * We re-acquire it after awaking so as to protect \
- * all semaphore operations. \
- * \
- * If "up()" is called before we call waking_non_zero() then \
- * we will catch it right away. If it is called later then \
- * we will have to go through a wakeup cycle to catch it. \
- * \
- * Multiple waiters contend for the semaphore lock to see \
- * who gets to gate through and who has to wait some more. \
- */ \
- for (;;) {
+ tsk->state = TASK_UNINTERRUPTIBLE;
+ add_wait_queue_exclusive(&sem->wait, &wait);
-#define DOWN_TAIL(task_state) \
- tsk->state = (task_state); \
- } \
- tsk->state = TASK_RUNNING; \
+ while (__sem_update_count(sem, -1) <= 0) {
+ schedule();
+ tsk->state = TASK_UNINTERRUPTIBLE;
+ }
remove_wait_queue(&sem->wait, &wait);
+ tsk->state = TASK_RUNNING;
-void __down(struct semaphore * sem)
-{
- DOWN_VAR
- DOWN_HEAD(TASK_UNINTERRUPTIBLE)
- if (waking_non_zero(sem))
- break;
- schedule();
- DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+ wake_up(&sem->wait);
}
int __down_interruptible(struct semaphore * sem)
{
- int ret = 0;
- DOWN_VAR
- DOWN_HEAD(TASK_INTERRUPTIBLE)
+ int retval = 0;
+ struct task_struct *tsk = current;
+ DECLARE_WAITQUEUE(wait, tsk);
- ret = waking_non_zero_interruptible(sem, tsk);
- if (ret)
- {
- if (ret == 1)
- /* ret != 0 only if we get interrupted -arca */
- ret = 0;
- break;
- }
- schedule();
- DOWN_TAIL(TASK_INTERRUPTIBLE)
- return ret;
-}
+ tsk->state = TASK_INTERRUPTIBLE;
+ add_wait_queue_exclusive(&sem->wait, &wait);
-int __down_trylock(struct semaphore * sem)
-{
- return waking_non_zero_trylock(sem);
+ while (__sem_update_count(sem, -1) <= 0) {
+ if (signal_pending(current)) {
+ __sem_update_count(sem, 0);
+ retval = -EINTR;
+ break;
+ }
+ schedule();
+ tsk->state = TASK_INTERRUPTIBLE;
+ }
+ tsk->state = TASK_RUNNING;
+ remove_wait_queue(&sem->wait, &wait);
+ wake_up(&sem->wait);
+ return retval;
}
-/* $Id: sparc64_ksyms.c,v 1.106 2001/05/11 07:46:28 davem Exp $
+/* $Id: sparc64_ksyms.c,v 1.107 2001/05/18 08:01:35 davem Exp $
* arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
/* semaphores */
EXPORT_SYMBOL(__down);
EXPORT_SYMBOL(__down_interruptible);
-EXPORT_SYMBOL(__down_trylock);
EXPORT_SYMBOL(__up);
/* Atomic counter implementation. */
size = buf.length - file->f_pos;
if (size > *len)
size = *len;
- if (copy_to_user(buffer, data, size))
+ if (copy_to_user(buffer, data, size)) {
+ kfree(buf.pointer);
return -EFAULT;
+ }
}
kfree(buf.pointer);
length = slm_getstats( (char *)page, MINOR(node->i_rdev) );
if (length < 0) {
- free_page( page );
- return( length );
+ count = length;
+ goto out;
}
if (file->f_pos >= length) {
- free_page( page );
- return( 0 );
+ count = 0;
+ goto out;
}
if (count + file->f_pos > length)
count = length - file->f_pos;
end = count + file->f_pos;
- copy_to_user( buf, (char *)page + file->f_pos, count );
- free_page( page );
+ if (copy_to_user(buf, (char *)page + file->f_pos, count)) {
+ count = -EFAULT;
+ goto out;
+ }
file->f_pos = end;
+out: free_page( page );
return( count );
}
if (filled + n > BufferSize)
n = BufferSize - filled;
- copy_from_user( BufferP, buf, n );
+ if (copy_from_user(BufferP, buf, n))
+ return -EFAULT;
BufferP += n;
filled += n;
if (put_user(stat,
(long *)&((struct SLM_status *)arg)->stat))
return -EFAULT;
- copy_to_user( ((struct SLM_status *)arg)->str, str,
- strlen(str) + 1 );
+ if (copy_to_user( ((struct SLM_status *)arg)->str, str,
+ strlen(str) + 1))
+ return -EFAULT;
}
return( stat );
}
case SLMIOGPSIZE: { /* get paper size */
int w, h;
- err = verify_area( VERIFY_WRITE, (long *)arg,
- sizeof(struct SLM_paper_size) );
- if (err) return( err );
-
if ((err = slm_get_pagesize( device, &w, &h ))) return( err );
if (put_user(w, (long *)&((struct SLM_paper_size *)arg)->width))
/* partition in use? Incomplete check for now. */
devp = MKDEV(MAJOR(dev), minor);
- if (get_super(devp) || /* mounted? */
- is_swap_partition(devp))
+ if (is_mounted(devp) || is_swap_partition(devp))
return -EBUSY;
/* all seems OK */
#include <linux/genhd.h>
#define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
-#define DRIVER_NAME "Compaq CISS Driver (v 2.4.3)"
-#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,4,3)
+#define DRIVER_NAME "Compaq CISS Driver (v 2.4.5)"
+#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,4,5)
/* Embedded module documentation macros - see modules.h */
MODULE_AUTHOR("Charles M. White III - Compaq Computer Corporation");
#include "cciss.h"
#include <linux/cciss_ioctl.h>
+/* define the PCI info for the cards we can control */
+const struct pci_device_id cciss_pci_device_id[] = {
+ { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISS,
+ 0x0E11, 0x4070, 0, 0, 0},
+ { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB,
+ 0x0E11, 0x4080, 0, 0, 0},
+ { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB,
+ 0x0E11, 0x4082, 0, 0, 0},
+};
+MODULE_DEVICE_TABLE(pci, cciss_pci_device_id);
+
#define NR_PRODUCTS (sizeof(products)/sizeof(struct board_type))
/* board_id = Subsystem Device ID & Vendor ID
#define READ_AHEAD 128
#define NR_CMDS 128 /* #commands that can be outstanding */
#define MAX_CTLR 8
-static int nr_ctlr;
+
+#define CCISS_DMA_MASK 0xFFFFFFFF /* 32 bit DMA */
+
static ctlr_info_t *hba[MAX_CTLR];
static struct proc_dir_entry *proc_cciss;
* For operations that cannot sleep, a command block is allocated at init,
* and managed by cmd_alloc() and cmd_free() using a simple bitmap to track
* which ones are free or in use. For operations that can wait for kmalloc
- * to possible sleep, this routine can be called with a NULL pointer.
- * cmd_free() MUST be called with a NULL pointer if cmd_alloc was.
+ * to possible sleep, this routine can be called with get_from_pool set to 0.
+ * cmd_free() MUST be called with a got_from_pool set to 0 if cmd_alloc was.
*/
-static CommandList_struct * cmd_alloc(ctlr_info_t *h)
+static CommandList_struct * cmd_alloc(ctlr_info_t *h, int get_from_pool)
{
CommandList_struct *c;
int i;
u64bit temp64;
+ dma_addr_t cmd_dma_handle, err_dma_handle;
- if (h == NULL)
+ if (!get_from_pool)
{
- c = (CommandList_struct *)kmalloc(sizeof(CommandList_struct),
- GFP_KERNEL);
+ c = (CommandList_struct *) pci_alloc_consistent(
+ h->pdev, sizeof(CommandList_struct), &cmd_dma_handle);
if(c==NULL)
return NULL;
memset(c, 0, sizeof(CommandList_struct));
- c->err_info = (ErrorInfo_struct *)kmalloc(
- sizeof(ErrorInfo_struct), GFP_KERNEL);
+ c->err_info = (ErrorInfo_struct *)pci_alloc_consistent(
+ h->pdev, sizeof(ErrorInfo_struct),
+ &err_dma_handle);
if (c->err_info == NULL)
{
- kfree(c);
+ pci_free_consistent(h->pdev,
+ sizeof(CommandList_struct), c, cmd_dma_handle);
return NULL;
}
memset(c->err_info, 0, sizeof(ErrorInfo_struct));
printk(KERN_DEBUG "cciss: using command buffer %d\n", i);
#endif
c = h->cmd_pool + i;
- memset(c, 0, sizeof(CommandList_struct));
+ memset(c, 0, sizeof(CommandList_struct));
+ cmd_dma_handle = h->cmd_pool_dhandle
+ + i*sizeof(CommandList_struct);
c->err_info = h->errinfo_pool + i;
memset(c->err_info, 0, sizeof(ErrorInfo_struct));
+ err_dma_handle = h->errinfo_pool_dhandle
+ + i*sizeof(ErrorInfo_struct);
h->nr_allocs++;
}
-
- temp64.val = (__u64) virt_to_bus(c->err_info);
+ c->busaddr = (__u32) cmd_dma_handle;
+ temp64.val = (__u64) err_dma_handle;
c->ErrDesc.Addr.lower = temp64.val32.lower;
c->ErrDesc.Addr.upper = temp64.val32.upper;
c->ErrDesc.Len = sizeof(ErrorInfo_struct);
- c->busaddr = virt_to_bus(c);
+
+ c->ctlr = h->ctlr;
return c;
/*
* Frees a command block that was previously allocated with cmd_alloc().
*/
-static void cmd_free(ctlr_info_t *h, CommandList_struct *c)
+static void cmd_free(ctlr_info_t *h, CommandList_struct *c, int got_from_pool)
{
int i;
+ u64bit temp64;
- if( h == NULL)
+ if( !got_from_pool)
{
- kfree(c->err_info);
- kfree(c);
+ temp64.val32.lower = c->ErrDesc.Addr.lower;
+ temp64.val32.upper = c->ErrDesc.Addr.upper;
+ pci_free_consistent(h->pdev, sizeof(ErrorInfo_struct),
+ c->err_info, (dma_addr_t) temp64.val);
+ pci_free_consistent(h->pdev, sizeof(CommandList_struct),
+ c, (dma_addr_t) c->busaddr);
} else
{
i = c - h->cmd_pool;
cciss_pci_info_struct pciinfo;
if (!arg) return -EINVAL;
- pciinfo.bus = hba[ctlr]->pci_bus;
- pciinfo.dev_fn = hba[ctlr]->pci_dev_fn;
+ pciinfo.bus = hba[ctlr]->pdev->bus->number;
+ pciinfo.dev_fn = hba[ctlr]->pdev->devfn;
pciinfo.board_id = hba[ctlr]->board_id;
if (copy_to_user((void *) arg, &pciinfo, sizeof( cciss_pci_info_struct )))
return -EFAULT;
if (iocommand.Request.Type.Direction == XFER_WRITE)
{
/* Copy the data into the buffer we created */
- if (copy_from_user(buff, iocommand.buf,
- iocommand.buf_size)) {
- kfree(buff);
+ if (copy_from_user(buff, iocommand.buf, iocommand.buf_size))
return -EFAULT;
- }
}
- if ((c = cmd_alloc(NULL)) == NULL)
+ if ((c = cmd_alloc(h , 0)) == NULL)
{
kfree(buff);
return -ENOMEM;
// Fill in the scatter gather information
if (iocommand.buf_size > 0 )
- {
- temp64.val = (__u64) virt_to_bus(buff);
+ {
+ temp64.val = pci_map_single( h->pdev, buff,
+ iocommand.buf_size,
+ PCI_DMA_BIDIRECTIONAL);
c->SG[0].Addr.lower = temp64.val32.lower;
c->SG[0].Addr.upper = temp64.val32.upper;
c->SG[0].Len = iocommand.buf_size;
while(c->cmd_type != CMD_IOCTL_DONE)
schedule_timeout(1);
+ /* unlock the buffers from DMA */
+ temp64.val32.lower = c->SG[0].Addr.lower;
+ temp64.val32.upper = c->SG[0].Addr.upper;
+ pci_unmap_single( h->pdev, (dma_addr_t) temp64.val,
+ iocommand.buf_size, PCI_DMA_BIDIRECTIONAL);
+
/* Copy the error information out */
iocommand.error_info = *(c->err_info);
if ( copy_to_user((void *) arg, &iocommand, sizeof( IOCTL_Command_struct) ) )
{
- cmd_free(NULL, c);
kfree(buff);
+ cmd_free(h, c, 0);
return( -EFAULT);
}
/* Copy the data out of the buffer we created */
if (copy_to_user(iocommand.buf, buff, iocommand.buf_size))
{
- cmd_free(NULL, c);
- kfree(buff);
- return -EFAULT;
+ kfree(buff);
+ cmd_free(h, c, 0);
}
}
- cmd_free(NULL, c);
kfree(buff);
+ cmd_free(h, c, 0);
return(0);
}
int i;
unsigned long complete;
ctlr_info_t *info_p= hba[ctlr];
- u64bit temp64;
+ u64bit buff_dma_handle;
- c = cmd_alloc(info_p);
+ c = cmd_alloc(info_p, 1);
if (c == NULL)
{
printk(KERN_WARNING "cciss: unable to get memory");
printk(KERN_WARNING
"cciss: Unknown Command 0x%c sent attempted\n",
cmd);
- cmd_free(info_p, c);
+ cmd_free(info_p, c, 1);
return(IO_ERROR);
};
// Fill in the scatter gather information
if (size > 0 )
{
- temp64.val = (__u64) virt_to_bus(buff);
- c->SG[0].Addr.lower = temp64.val32.lower;
- c->SG[0].Addr.upper = temp64.val32.upper;
+ buff_dma_handle.val = (__u64) pci_map_single( info_p->pdev,
+ buff, size, PCI_DMA_BIDIRECTIONAL);
+ c->SG[0].Addr.lower = buff_dma_handle.val32.lower;
+ c->SG[0].Addr.upper = buff_dma_handle.val32.upper;
c->SG[0].Len = size;
c->SG[0].Ext = 0; // we are not chaining
}
printk(KERN_DEBUG "cciss: command completed\n");
#endif /* CCISS_DEBUG */
+ /* unlock the data buffer from DMA */
+ pci_unmap_single(info_p->pdev, (dma_addr_t) buff_dma_handle.val,
+ size, PCI_DMA_BIDIRECTIONAL);
if (complete != 1) {
if ( (complete & CISS_ERROR_BIT)
&& (complete & ~CISS_ERROR_BIT) == c->busaddr)
c->err_info->MoreErrInfo.Invalid_Cmd.offense_size,
c->err_info->MoreErrInfo.Invalid_Cmd.offense_num,
c->err_info->MoreErrInfo.Invalid_Cmd.offense_value);
- cmd_free(info_p,c);
+ cmd_free(info_p,c, 1);
return(IO_ERROR);
}
}
printk( KERN_WARNING "cciss cciss%d: SendCmd "
"Invalid command list address returned! (%lx)\n",
ctlr, complete);
- cmd_free(info_p, c);
+ cmd_free(info_p, c, 1);
return (IO_ERROR);
}
} else {
"cciss cciss%d: SendCmd Timeout out, "
"No command list address returned!\n",
ctlr);
- cmd_free(info_p, c);
+ cmd_free(info_p, c, 1);
return (IO_ERROR);
}
- cmd_free(info_p, c);
+ cmd_free(info_p, c, 1);
return (IO_OK);
}
/*
static inline void complete_command( CommandList_struct *cmd, int timeout)
{
int status = 1;
-
+ int i;
+ u64bit temp64;
+
if (timeout)
status = 0;
+ /* unmap the DMA mapping for all the scatter gather elements */
+ for(i=0; i<cmd->Header.SGList; i++)
+ {
+ temp64.val32.lower = cmd->SG[i].Addr.lower;
+ temp64.val32.upper = cmd->SG[i].Addr.upper;
+ pci_unmap_single(hba[cmd->ctlr]->pdev,
+ temp64.val, cmd->SG[i].Len,
+ (cmd->Request.Type.Direction == XFER_READ) ?
+ PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
+ }
+
if(cmd->err_info->CommandStatus != 0)
{ /* an error has occurred */
switch(cmd->err_info->CommandStatus)
struct list_head *queue_head = &q->queue_head;
struct request *creq;
u64bit temp64;
+ struct my_sg tmp_sg[MAXSGENTRIES];
+ int i;
// Loop till the queue is empty if or it is plugged
while (1)
if (creq->nr_segments > MAXSGENTRIES)
BUG();
- if ((h->ctlr != MAJOR(creq->rq_dev)-MAJOR_NR) || (h->ctlr > nr_ctlr))
+ if (h->ctlr != MAJOR(creq->rq_dev)-MAJOR_NR )
{
printk(KERN_WARNING "doreq cmd for %d, %x at %p\n",
h->ctlr, creq->rq_dev, creq);
return;
}
- if (( c = cmd_alloc(h)) == NULL)
+ if (( c = cmd_alloc(h, 1)) == NULL)
{
start_io(h);
return;
sect += bh->b_size/512;
if (bh->b_data == lastdataend)
{ // tack it on to the last segment
- c->SG[seg-1].Len +=bh->b_size;
+ tmp_sg[seg-1].len +=bh->b_size;
lastdataend += bh->b_size;
} else
{
if (seg == MAXSGENTRIES)
BUG();
- c->SG[seg].Len = bh->b_size;
- temp64.val = (__u64) virt_to_bus(bh->b_data);
- c->SG[seg].Addr.lower = temp64.val32.lower;
- c->SG[seg].Addr.upper = temp64.val32.upper;
- c->SG[0].Ext = 0; // we are not chaining
+ tmp_sg[seg].len = bh->b_size;
+ tmp_sg[seg].start_addr = bh->b_data;
lastdataend = bh->b_data + bh->b_size;
seg++;
}
bh = bh->b_reqnext;
}
+ /* get the DMA records for the setup */
+ for (i=0; i<seg; i++)
+ {
+ c->SG[i].Len = tmp_sg[i].len;
+ temp64.val = (__u64) pci_map_single( h->pdev,
+ tmp_sg[i].start_addr,
+ tmp_sg[i].len,
+ (c->Request.Type.Direction == XFER_READ) ?
+ PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
+ c->SG[i].Addr.lower = temp64.val32.lower;
+ c->SG[i].Addr.upper = temp64.val32.upper;
+ c->SG[i].Ext = 0; // we are not chaining
+ }
/* track how many SG entries we are using */
if( seg > h->maxSG)
h->maxSG = seg;
removeQ(&h->cmpQ, c);
if (c->cmd_type == CMD_RWREQ) {
complete_command(c, 0);
- cmd_free(h, c);
+ cmd_free(h, c, 1);
} else if (c->cmd_type == CMD_IOCTL_PEND) {
c->cmd_type = CMD_IOCTL_DONE;
}
}
#endif /* CCISS_DEBUG */
-static int cciss_pci_init(ctlr_info_t *c, unchar bus, unchar device_fn)
+static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
{
ushort vendor_id, device_id, command;
unchar cache_line_size, latency_timer;
unchar irq, revision;
uint addr[6];
__u32 board_id;
- struct pci_dev *pdev;
int cfg_offset;
int cfg_base_addr;
int cfg_base_addr_index;
int i;
- pdev = pci_find_slot(bus, device_fn);
vendor_id = pdev->vendor;
device_id = pdev->device;
irq = pdev->irq;
addr[i] = pdev->resource[i].start;
if (pci_enable_device(pdev))
+ {
+ printk(KERN_ERR "cciss: Unable to Enable PCI device\n");
return( -1);
+ }
+ if (pci_set_dma_mask(pdev, CCISS_DMA_MASK ) != 0)
+ {
+ printk(KERN_ERR "cciss: Unable to set DMA mask\n");
+ return(-1);
+ }
(void) pci_read_config_word(pdev, PCI_COMMAND,&command);
(void) pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
}
return 0;
-}
-/*
- * Scans PCI space for any controllers that this driver can control.
- */
-static int cciss_pci_detect(void)
-{
-
- int index;
- unchar bus=0, dev_fn=0;
-
- #define CCISS_BOARD_TYPES 2
- static int cciss_device_id[CCISS_BOARD_TYPES] = {
- PCI_DEVICE_ID_COMPAQ_CISS, PCI_DEVICE_ID_COMPAQ_CISSB};
- int brdtype;
-
- /* search for all PCI board types that could be for this driver */
- for(brdtype=0; brdtype<CCISS_BOARD_TYPES; brdtype++)
- {
- for(index=0; ; index++) {
- if (pcibios_find_device(PCI_VENDOR_ID_COMPAQ,
- cciss_device_id[brdtype],
- index, &bus, &dev_fn))
- break;
- printk(KERN_DEBUG "cciss: Device %x has been found at %x %x\n",
- cciss_device_id[brdtype], bus, dev_fn);
- if (index == 1000000) break;
- if (nr_ctlr == 8) {
- printk(KERN_WARNING "cciss: This driver"
- " supports a maximum of 8 controllers.\n");
- break;
- }
- hba[nr_ctlr] = kmalloc(sizeof(ctlr_info_t), GFP_KERNEL);
- if(hba[nr_ctlr]==NULL)
- {
- printk(KERN_ERR "cciss: out of memory.\n");
- continue;
- }
- memset(hba[nr_ctlr], 0, sizeof(ctlr_info_t));
- if (cciss_pci_init(hba[nr_ctlr], bus, dev_fn) != 0)
- {
- kfree(hba[nr_ctlr]);
- continue;
- }
- sprintf(hba[nr_ctlr]->devname, "cciss%d", nr_ctlr);
- hba[nr_ctlr]->ctlr = nr_ctlr;
- hba[nr_ctlr]->pci_bus = bus;
- hba[nr_ctlr]->pci_dev_fn = dev_fn;
- nr_ctlr++;
-
- }
- }
- return nr_ctlr;
-
}
/*
kfree(size_buff);
}
+/* Function to find the first free pointer into our hba[] array */
+/* Returns -1 if no free entries are left. */
+static int alloc_cciss_hba(void)
+{
+ int i;
+ for(i=0; i< MAX_CTLR; i++)
+ {
+ if (hba[i] == NULL)
+ {
+ hba[i] = kmalloc(sizeof(ctlr_info_t), GFP_KERNEL);
+ if(hba[i]==NULL)
+ {
+ printk(KERN_ERR "cciss: out of memory.\n");
+ return (-1);
+ }
+ return (i);
+ }
+ }
+ printk(KERN_WARNING "cciss: This driver supports a maximum"
+ " of 8 controllers.\n");
+ return(-1);
+}
+
+static void free_hba(int i)
+{
+ kfree(hba[i]);
+ hba[i]=NULL;
+}
+
/*
* This is it. Find all the controllers and register them. I really hate
* stealing all these major device numbers.
* returns the number of block devices registered.
*/
-int __init cciss_init(void)
+static int __init cciss_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
- int num_cntlrs_reg = 0;
- int i,j;
request_queue_t *q;
-
- /* detect controllers */
- cciss_pci_detect();
-
- if (nr_ctlr == 0)
- return(num_cntlrs_reg);
-
- printk(KERN_INFO DRIVER_NAME "\n");
- printk(KERN_INFO "Found %d controller(s)\n", nr_ctlr);
- for(i=0;i<nr_ctlr;i++)
+ int i;
+ int j;
+
+ printk(KERN_DEBUG "cciss: Device 0x%x has been found at"
+ " bus %d dev %d func %d\n",
+ pdev->device, pdev->bus->number, PCI_SLOT(pdev->devfn),
+ PCI_FUNC(pdev->devfn));
+ i = alloc_cciss_hba();
+ if( i < 0 )
+ return (-1);
+ memset(hba[i], 0, sizeof(ctlr_info_t));
+ if (cciss_pci_init(hba[i], pdev) != 0)
{
- if( register_blkdev(MAJOR_NR+i, hba[i]->devname, &cciss_fops))
- {
- printk(KERN_ERR "cciss: Unable to get major number "
- "%d for %s\n", MAJOR_NR+i, hba[i]->devname);
- continue;
- }
- /* make sure the board interrupts are off */
- hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF);
- if( request_irq(hba[i]->intr, do_cciss_intr, SA_INTERRUPT|SA_SHIRQ, hba[i]->devname, hba[i]))
- {
- printk(KERN_ERR "ciss: Unable to get irq %d for %s\n",
- hba[i]->intr, hba[i]->devname);
- unregister_blkdev( MAJOR_NR+i, hba[i]->devname);
- continue;
- }
- num_cntlrs_reg++;
- hba[i]->cmd_pool_bits = (__u32*)kmalloc(
- ((NR_CMDS+31)/32)*sizeof(__u32), GFP_KERNEL);
- hba[i]->cmd_pool = (CommandList_struct *)kmalloc(
- NR_CMDS * sizeof(CommandList_struct),
- GFP_KERNEL);
- hba[i]->errinfo_pool = (ErrorInfo_struct *)kmalloc(
- NR_CMDS * sizeof( ErrorInfo_struct),
- GFP_KERNEL);
- if((hba[i]->cmd_pool_bits == NULL)
- || (hba[i]->cmd_pool == NULL)
- || (hba[i]->errinfo_pool == NULL))
- {
- nr_ctlr = i;
- kfree(hba[i]->cmd_pool_bits);
- kfree(hba[i]->cmd_pool);
- kfree(hba[i]->errinfo_pool);
- free_irq(hba[i]->intr, hba[i]);
- unregister_blkdev(MAJOR_NR+i, hba[i]->devname);
- num_cntlrs_reg--;
- printk( KERN_ERR "cciss: out of memory");
- return(num_cntlrs_reg);
- }
+ free_hba(i);
+ return (-1);
+ }
+ sprintf(hba[i]->devname, "cciss%d", i);
+ hba[i]->ctlr = i;
+ hba[i]->pdev = pdev;
+
+ if( register_blkdev(MAJOR_NR+i, hba[i]->devname, &cciss_fops))
+ {
+ printk(KERN_ERR "cciss: Unable to get major number "
+ "%d for %s\n", MAJOR_NR+i, hba[i]->devname);
+ free_hba(i);
+ return(-1);
+ }
+ /* make sure the board interrupts are off */
+ hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF);
+ if( request_irq(hba[i]->intr, do_cciss_intr,
+ SA_INTERRUPT|SA_SHIRQ, hba[i]->devname, hba[i]))
+ {
+ printk(KERN_ERR "ciss: Unable to get irq %d for %s\n",
+ hba[i]->intr, hba[i]->devname);
+ unregister_blkdev( MAJOR_NR+i, hba[i]->devname);
+ free_hba(i);
+ return(-1);
+ }
+ hba[i]->cmd_pool_bits = (__u32*)kmalloc(
+ ((NR_CMDS+31)/32)*sizeof(__u32), GFP_KERNEL);
+ hba[i]->cmd_pool = (CommandList_struct *)pci_alloc_consistent(
+ hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct),
+ &(hba[i]->cmd_pool_dhandle));
+ hba[i]->errinfo_pool = (ErrorInfo_struct *)pci_alloc_consistent(
+ hba[i]->pdev, NR_CMDS * sizeof( ErrorInfo_struct),
+ &(hba[i]->errinfo_pool_dhandle));
+ if((hba[i]->cmd_pool_bits == NULL)
+ || (hba[i]->cmd_pool == NULL)
+ || (hba[i]->errinfo_pool == NULL))
+ {
+ if(hba[i]->cmd_pool_bits)
+ kfree(hba[i]->cmd_pool_bits);
+ if(hba[i]->cmd_pool)
+ pci_free_consistent(hba[i]->pdev,
+ NR_CMDS * sizeof(CommandList_struct),
+ hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle);
+ if(hba[i]->errinfo_pool)
+ pci_free_consistent(hba[i]->pdev,
+ NR_CMDS * sizeof( ErrorInfo_struct),
+ hba[i]->errinfo_pool,
+ hba[i]->errinfo_pool_dhandle);
+ free_irq(hba[i]->intr, hba[i]);
+ unregister_blkdev(MAJOR_NR+i, hba[i]->devname);
+ free_hba(i);
+ printk( KERN_ERR "cciss: out of memory");
+ return(-1);
+ }
- /* command and error info recs zeroed out before
+ /* Initialize the pdev driver private data.
+ have it point to hba[i]. */
+ pdev->driver_data = hba[i];
+ /* command and error info recs zeroed out before
they are used */
- memset(hba[i]->cmd_pool_bits, 0,
- ((NR_CMDS+31)/32)*sizeof(__u32));
+ memset(hba[i]->cmd_pool_bits, 0, ((NR_CMDS+31)/32)*sizeof(__u32));
#ifdef CCISS_DEBUG
- printk(KERN_DEBUG "Scanning for drives on controller cciss%d\n",i);
+ printk(KERN_DEBUG "Scanning for drives on controller cciss%d\n",i);
#endif /* CCISS_DEBUG */
- cciss_getgeometry(i);
+ cciss_getgeometry(i);
- /* Turn the interrupts on so we can service requests */
- hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON);
+ /* Turn the interrupts on so we can service requests */
+ hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON);
- cciss_procinit(i);
+ cciss_procinit(i);
- q = BLK_DEFAULT_QUEUE(MAJOR_NR + i);
- q->queuedata = hba[i];
- blk_init_queue(q, do_cciss_request);
- blk_queue_headactive(q, 0);
+ q = BLK_DEFAULT_QUEUE(MAJOR_NR + i);
+ q->queuedata = hba[i];
+ blk_init_queue(q, do_cciss_request);
+ blk_queue_headactive(q, 0);
- /* fill in the other Kernel structs */
- blksize_size[MAJOR_NR+i] = hba[i]->blocksizes;
- hardsect_size[MAJOR_NR+i] = hba[i]->hardsizes;
- read_ahead[MAJOR_NR+i] = READ_AHEAD;
+ /* fill in the other Kernel structs */
+ blksize_size[MAJOR_NR+i] = hba[i]->blocksizes;
+ hardsect_size[MAJOR_NR+i] = hba[i]->hardsizes;
+ read_ahead[MAJOR_NR+i] = READ_AHEAD;
- /* Set the pointers to queue functions */
- q->back_merge_fn = cpq_back_merge_fn;
- q->front_merge_fn = cpq_front_merge_fn;
- q->merge_requests_fn = cpq_merge_requests_fn;
+ /* Set the pointers to queue functions */
+ q->back_merge_fn = cpq_back_merge_fn;
+ q->front_merge_fn = cpq_front_merge_fn;
+ q->merge_requests_fn = cpq_merge_requests_fn;
- /* Fill in the gendisk data */
- hba[i]->gendisk.major = MAJOR_NR + i;
- hba[i]->gendisk.major_name = "cciss";
- hba[i]->gendisk.minor_shift = NWD_SHIFT;
- hba[i]->gendisk.max_p = MAX_PART;
- hba[i]->gendisk.part = hba[i]->hd;
- hba[i]->gendisk.sizes = hba[i]->sizes;
- hba[i]->gendisk.nr_real = hba[i]->num_luns;
+ /* Fill in the gendisk data */
+ hba[i]->gendisk.major = MAJOR_NR + i;
+ hba[i]->gendisk.major_name = "cciss";
+ hba[i]->gendisk.minor_shift = NWD_SHIFT;
+ hba[i]->gendisk.max_p = MAX_PART;
+ hba[i]->gendisk.part = hba[i]->hd;
+ hba[i]->gendisk.sizes = hba[i]->sizes;
+ hba[i]->gendisk.nr_real = hba[i]->num_luns;
- /* Get on the disk list */
- hba[i]->gendisk.next = gendisk_head;
- gendisk_head = &(hba[i]->gendisk);
+ /* Get on the disk list */
+ hba[i]->gendisk.next = gendisk_head;
+ gendisk_head = &(hba[i]->gendisk);
- cciss_geninit(i);
- for(j=0; j<NWD; j++)
- register_disk(&(hba[i]->gendisk),
- MKDEV(MAJOR_NR+i, j <<4),
- MAX_PART, &cciss_fops,
- hba[i]->drv[j].nr_blocks);
- }
- return(nr_ctlr);
+ cciss_geninit(i);
+ for(j=0; j<NWD; j++)
+ register_disk(&(hba[i]->gendisk),
+ MKDEV(MAJOR_NR+i, j <<4),
+ MAX_PART, &cciss_fops,
+ hba[i]->drv[j].nr_blocks);
+
+ return(1);
}
-EXPORT_NO_SYMBOLS;
+static void __devexit cciss_remove_one (struct pci_dev *pdev)
+{
+ ctlr_info_t *tmp_ptr;
+ int i;
+ struct gendisk *g;
-/* This is a bit of a hack... */
+ if (pdev->driver_data == NULL)
+ {
+ printk( KERN_ERR "cciss: Unable to remove device \n");
+ return;
+ }
+ tmp_ptr = (ctlr_info_t *) pdev->driver_data;
+ i = tmp_ptr->ctlr;
+ if (hba[i] == NULL)
+ {
+ printk(KERN_ERR "cciss: device appears to "
+ "already be removed \n");
+ return;
+ }
+ /* Turn board interrupts off */
+ hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF);
+ free_irq(hba[i]->intr, hba[i]);
+ pdev->driver_data = NULL;
+ iounmap((void*)hba[i]->vaddr);
+ unregister_blkdev(MAJOR_NR+i, hba[i]->devname);
+ remove_proc_entry(hba[i]->devname, proc_cciss);
+
+
+ /* remove it from the disk list */
+ if (gendisk_head == &(hba[i]->gendisk))
+ {
+ gendisk_head = hba[i]->gendisk.next;
+ } else
+ {
+ for(g=gendisk_head; g ; g=g->next)
+ {
+ if(g->next == &(hba[i]->gendisk))
+ {
+ g->next = hba[i]->gendisk.next;
+ }
+ }
+ }
+ pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct),
+ hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle);
+ pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof( ErrorInfo_struct),
+ hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle);
+ kfree(hba[i]->cmd_pool_bits);
+ free_hba(i);
+}
+
+static struct pci_driver cciss_pci_driver = {
+ name: "cciss",
+ probe: cciss_init_one,
+ remove: cciss_remove_one,
+ id_table: cciss_pci_device_id, /* id_table */
+};
+
+/*
+* This is it. Register the PCI driver information for the cards we control
+* the OS will call our registered routines when it finds one of our cards.
+*/
+int __init cciss_init(void)
+{
+
+ printk(KERN_INFO DRIVER_NAME "\n");
+ /* Register for out PCI devices */
+ if (pci_register_driver(&cciss_pci_driver) > 0 )
+ return 0;
+ else
+ return -ENODEV;
+
+ }
+
+EXPORT_NO_SYMBOLS;
static int __init init_cciss_module(void)
{
- if (cciss_init() == 0) /* all the block dev numbers already used */
- return -EIO; /* or no controllers were found */
- return 0;
+ return ( cciss_init());
}
static void __exit cleanup_cciss_module(void)
{
int i;
- struct gendisk *g;
- for(i=0; i<nr_ctlr; i++)
+ pci_unregister_driver(&cciss_pci_driver);
+ /* double check that all controller entrys have been removed */
+ for (i=0; i< MAX_CTLR; i++)
{
- /* Turn board interrupts off */
- hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF);
- free_irq(hba[i]->intr, hba[i]);
- iounmap((void*)hba[i]->vaddr);
- unregister_blkdev(MAJOR_NR+i, hba[i]->devname);
- remove_proc_entry(hba[i]->devname, proc_cciss);
-
- /* remove it from the disk list */
- if (gendisk_head == &(hba[i]->gendisk))
- {
- gendisk_head = hba[i]->gendisk.next;
- } else
+ if (hba[i] != NULL)
{
- for(g=gendisk_head; g ; g=g->next)
- {
- if(g->next == &(hba[i]->gendisk))
- {
- g->next = hba[i]->gendisk.next;
- }
- }
+ printk(KERN_WARNING "cciss: had to remove"
+ " controller %d\n", i);
+ cciss_remove_one(hba[i]->pdev);
}
- remove_proc_entry("cciss", proc_root_driver);
- kfree(hba[i]->cmd_pool);
- kfree(hba[i]->errinfo_pool);
- kfree(hba[i]->cmd_pool_bits);
- kfree(hba[i]);
}
+ remove_proc_entry("cciss", proc_root_driver);
}
module_init(init_cciss_module);
#define MAJOR_NR COMPAQ_CISS_MAJOR
+struct my_sg {
+ int len;
+ char *start_addr;
+};
+
struct ctlr_info;
typedef struct ctlr_info ctlr_info_t;
char devname[8];
char *product_name;
char firm_ver[4]; // Firmware version
- unchar pci_bus;
- unchar pci_dev_fn;
+ struct pci_dev *pdev;
__u32 board_id;
ulong vaddr;
__u32 paddr;
//* pointers to command and error info pool */
CommandList_struct *cmd_pool;
+ dma_addr_t cmd_pool_dhandle;
ErrorInfo_struct *errinfo_pool;
+ dma_addr_t errinfo_pool_dhandle;
__u32 *cmd_pool_bits;
int nr_allocs;
int nr_frees;
/* information associated with the command */
__u32 busaddr; /* physical address of this record */
ErrorInfo_struct * err_info; /* pointer to the allocated mem */
+ int ctlr;
int cmd_type;
struct _CommandList_struct *prev;
struct _CommandList_struct *next;
#define SMART2_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
-#define DRIVER_NAME "Compaq SMART2 Driver (v 2.4.3)"
-#define DRIVER_VERSION SMART2_DRIVER_VERSION(2,4,3)
+#define DRIVER_NAME "Compaq SMART2 Driver (v 2.4.4)"
+#define DRIVER_VERSION SMART2_DRIVER_VERSION(2,4,4)
/* Embedded module documentation macros - see modules.h */
/* Original author Chris Frantz - Compaq Computer Corporation */
#define MAX_CTLR 8
#define CTLR_SHIFT 8
+#define CPQARRAY_DMA_MASK 0xFFFFFFFF /* 32 bit DMA */
+
static int nr_ctlr;
static ctlr_info_t *hba[MAX_CTLR];
static void getgeometry(int ctlr);
static void start_fwbk(int ctlr);
-static cmdlist_t * cmd_alloc(ctlr_info_t *h);
-static void cmd_free(ctlr_info_t *h, cmdlist_t *c);
+static cmdlist_t * cmd_alloc(ctlr_info_t *h, int get_from_pool);
+static void cmd_free(ctlr_info_t *h, cmdlist_t *c, int got_from_pool);
static int sendcmd(
__u8 cmd,
del_timer(&hba[i]->timer);
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR + i));
remove_proc_entry(hba[i]->devname, proc_array);
- kfree(hba[i]->cmd_pool);
+ pci_free_consistent(hba[i]->pci_dev,
+ NR_CMDS * sizeof(cmdlist_t), (hba[i]->cmd_pool),
+ hba[i]->cmd_pool_dhandle);
kfree(hba[i]->cmd_pool_bits);
if (gendisk_head == &ida_gendisk[i]) {
continue;
}
num_cntlrs_reg++;
- hba[i]->cmd_pool = (cmdlist_t *)kmalloc(
- NR_CMDS * sizeof(cmdlist_t), GFP_KERNEL);
+ hba[i]->cmd_pool = (cmdlist_t *)pci_alloc_consistent(
+ hba[i]->pci_dev, NR_CMDS * sizeof(cmdlist_t),
+ &(hba[i]->cmd_pool_dhandle));
hba[i]->cmd_pool_bits = (__u32*)kmalloc(
((NR_CMDS+31)/32)*sizeof(__u32), GFP_KERNEL);
if(hba[i]->cmd_pool_bits)
kfree(hba[i]->cmd_pool_bits);
if(hba[i]->cmd_pool)
- kfree(hba[i]->cmd_pool);
+ pci_free_consistent(hba[i]->pci_dev,
+ NR_CMDS * sizeof(cmdlist_t),
+ hba[i]->cmd_pool,
+ hba[i]->cmd_pool_dhandle);
free_irq(hba[i]->intr, hba[i]);
unregister_blkdev(MAJOR_NR+i, hba[i]->devname);
num_cntlrs_reg--;
addr[i] = pci_resource_start(pdev, i);
if (pci_enable_device(pdev))
+ {
+ printk(KERN_ERR "cpqarray: Unable to Enable PCI device\n");
return -1;
+ }
+ if (pci_set_dma_mask(pdev, CPQARRAY_DMA_MASK) != 0)
+ {
+ printk(KERN_ERR "cpqarray: Unable to set DMA mask\n");
+ return -1;
+ }
pci_read_config_word(pdev, PCI_COMMAND, &command);
pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
struct list_head * queue_head = &q->queue_head;
struct buffer_head *bh;
struct request *creq;
+ struct my_sg tmp_sg[SG_MAX];
+ int i;
// Loop till the queue is empty if or it is plugged
while (1)
return;
}
- if ((c = cmd_alloc(h)) == NULL)
+ if ((c = cmd_alloc(h,1)) == NULL)
{
start_io(h);
return;
while(bh) {
sect += bh->b_size/512;
if (bh->b_data == lastdataend) {
- c->req.sg[seg-1].size += bh->b_size;
+ tmp_sg[seg-1].size += bh->b_size;
lastdataend += bh->b_size;
} else {
if (seg == SG_MAX)
BUG();
- c->req.sg[seg].size = bh->b_size;
- c->req.sg[seg].addr = (__u32)virt_to_bus(bh->b_data);
+ tmp_sg[seg].size = bh->b_size;
+ tmp_sg[seg].start_addr = bh->b_data;
lastdataend = bh->b_data + bh->b_size;
seg++;
}
bh = bh->b_reqnext;
}
+ /* Now do all the DMA Mappings */
+ for( i=0; i < seg; i++)
+ {
+ c->req.sg[i].size = tmp_sg[i].size;
+ c->req.sg[i].addr = (__u32) pci_map_single(
+ h->pci_dev, tmp_sg[i].start_addr,
+ tmp_sg[i].size,
+ (creq->cmd == READ) ?
+ PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
+ }
DBGPX( printk("Submitting %d sectors in %d segments\n", sect, seg); );
c->req.hdr.sg_cnt = seg;
c->req.hdr.blk_cnt = sect;
static inline void complete_command(cmdlist_t *cmd, int timeout)
{
int ok=1;
+ int i;
if (cmd->req.hdr.rcode & RCODE_NONFATAL &&
(hba[cmd->ctlr]->misc_tflags & MISC_NONFATAL_WARN) == 0) {
ok = 0;
}
if (timeout) ok = 0;
+ /* unmap the DMA mapping for all the scatter gather elements */
+ for(i=0; i<cmd->req.hdr.sg_cnt; i++)
+ {
+ pci_unmap_single(hba[cmd->ctlr]->pci_dev,
+ cmd->req.sg[i].addr, cmd->req.sg[i].size,
+ (cmd->req.hdr.cmd == IDA_READ) ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
+ }
complete_buffers(cmd->bh, ok);
}
removeQ(&h->cmpQ, c);
if (c->type == CMD_RWREQ) {
complete_command(c, 0);
- cmd_free(h, c);
+ cmd_free(h, c, 1);
} else if (c->type == CMD_IOCTL_PEND) {
c->type = CMD_IOCTL_DONE;
}
unsigned long flags;
int error;
- if ((c = cmd_alloc(NULL)) == NULL)
+ if ((c = cmd_alloc(h, 0)) == NULL)
return -ENOMEM;
c->ctlr = ctlr;
c->hdr.unit = (io->unit & UNITVALID) ? (io->unit & ~UNITVALID) : dsk;
if (!p)
{
error = -ENOMEM;
- cmd_free(NULL, c);
+ cmd_free(h, c, 0);
return(error);
}
copy_from_user(p, (void*)io->sg[0].addr, io->sg[0].size);
- c->req.hdr.blk = virt_to_bus(&(io->c));
+ c->req.hdr.blk = pci_map_single(h->pci_dev, &(io->c),
+ sizeof(ida_ioctl_t),
+ PCI_DMA_BIDIRECTIONAL);
c->req.sg[0].size = io->sg[0].size;
- c->req.sg[0].addr = virt_to_bus(p);
+ c->req.sg[0].addr = pci_map_single(h->pci_dev, p,
+ c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL);
c->req.hdr.sg_cnt = 1;
break;
case IDA_READ:
if (!p)
{
error = -ENOMEM;
- cmd_free(NULL, c);
+ cmd_free(h, c, 0);
return(error);
}
c->req.sg[0].size = io->sg[0].size;
- c->req.sg[0].addr = virt_to_bus(p);
+ c->req.sg[0].addr = pci_map_single(h->pci_dev, p,
+ c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL);
c->req.hdr.sg_cnt = 1;
break;
case IDA_WRITE:
if (!p)
{
error = -ENOMEM;
- cmd_free(NULL, c);
+ cmd_free(h, c, 0);
return(error);
}
copy_from_user(p, (void*)io->sg[0].addr, io->sg[0].size);
c->req.sg[0].size = io->sg[0].size;
- c->req.sg[0].addr = virt_to_bus(p);
+ c->req.sg[0].addr = pci_map_single(h->pci_dev, p,
+ c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL);
c->req.hdr.sg_cnt = 1;
break;
default:
c->req.sg[0].size = sizeof(io->c);
- c->req.sg[0].addr = virt_to_bus(&io->c);
+ c->req.sg[0].addr = pci_map_single(h->pci_dev,&io->c,
+ c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL);
c->req.hdr.sg_cnt = 1;
}
-
+
/* Put the request on the tail of the request queue */
spin_lock_irqsave(&io_request_lock, flags);
addQ(&h->reqQ, c);
while(c->type != CMD_IOCTL_DONE)
schedule();
+ /* Unmap the DMA */
+ pci_unmap_single(h->pci_dev, c->req.sg[0].addr, c->req.sg[0].size,
+ PCI_DMA_BIDIRECTIONAL);
/* Post submit processing */
switch(io->cmd) {
case PASSTHRU_A:
+ pci_unmap_single(h->pci_dev, c->req.hdr.blk,
+ sizeof(ida_ioctl_t),
+ PCI_DMA_BIDIRECTIONAL);
case IDA_READ:
case DIAG_PASS_THRU:
copy_to_user((void*)io->sg[0].addr, p, io->sg[0].size);
}
io->rcode = c->req.hdr.rcode;
- cmd_free(NULL, c);
+ cmd_free(h, c, 0);
return(0);
}
* critical (and can wait for kmalloc and possibly sleep) can pass in NULL
* as the first argument to get a new command.
*/
-static cmdlist_t * cmd_alloc(ctlr_info_t *h)
+static cmdlist_t * cmd_alloc(ctlr_info_t *h, int get_from_pool)
{
cmdlist_t * c;
int i;
+ dma_addr_t cmd_dhandle;
- if (h == NULL) {
- c = (cmdlist_t*)kmalloc(sizeof(cmdlist_t), GFP_KERNEL);
+ if (!get_from_pool) {
+ c = (cmdlist_t*)pci_alloc_consistent(h->pci_dev,
+ sizeof(cmdlist_t), &cmd_dhandle);
if(c==NULL)
return NULL;
} else {
return NULL;
} while(test_and_set_bit(i%32, h->cmd_pool_bits+(i/32)) != 0);
c = h->cmd_pool + i;
+ cmd_dhandle = h->cmd_pool_dhandle + i*sizeof(cmdlist_t);
h->nr_allocs++;
}
memset(c, 0, sizeof(cmdlist_t));
- c->busaddr = virt_to_bus(c);
+ c->busaddr = cmd_dhandle;
return c;
}
-static void cmd_free(ctlr_info_t *h, cmdlist_t *c)
+static void cmd_free(ctlr_info_t *h, cmdlist_t *c, int got_from_pool)
{
int i;
- if (h == NULL) {
- kfree(c);
+ if (!got_from_pool) {
+ pci_free_consistent(h->pci_dev, sizeof(cmdlist_t), c,
+ c->busaddr);
} else {
i = c - h->cmd_pool;
clear_bit(i%32, h->cmd_pool_bits+(i/32));
unsigned long i;
ctlr_info_t *info_p = hba[ctlr];
- c = cmd_alloc(info_p);
+ c = cmd_alloc(info_p, 1);
if(!c)
return IO_ERROR;
c->ctlr = ctlr;
c->req.hdr.blk = blk;
c->req.hdr.blk_cnt = blkcnt;
c->req.hdr.cmd = (unsigned char) cmd;
- c->req.sg[0].addr = (__u32) virt_to_bus(buff);
+ c->req.sg[0].addr = (__u32) pci_map_single(info_p->pci_dev,
+ buff, c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL);
/*
* Disable interrupt
*/
*/
info_p->access.submit_command(info_p, c);
complete = pollcomplete(ctlr);
+
+ pci_unmap_single(info_p->pci_dev, (dma_addr_t) c->req.sg[0].addr,
+ c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL);
if (complete != 1) {
if (complete != c->busaddr) {
printk( KERN_WARNING
"cpqarray ida%d: idaSendPciCmd "
"Invalid command list address returned! (%08lx)\n",
ctlr, (unsigned long)complete);
- cmd_free(info_p, c);
+ cmd_free(info_p, c, 1);
return (IO_ERROR);
}
} else {
"cpqarray ida%d: idaSendPciCmd Timeout out, "
"No command list address returned!\n",
ctlr);
- cmd_free(info_p, c);
+ cmd_free(info_p, c, 1);
return (IO_ERROR);
}
"cmd: 0x%x, return code = 0x%x\n",
ctlr, c->req.hdr.cmd, c->req.hdr.rcode);
- cmd_free(info_p, c);
+ cmd_free(info_p, c, 1);
return (IO_ERROR);
}
}
- cmd_free(info_p, c);
+ cmd_free(info_p, c, 1);
return (IO_OK);
}
#ifdef __KERNEL__
+struct my_sg {
+ int size;
+ char *start_addr;
+};
+
struct ctlr_info;
typedef struct ctlr_info ctlr_info_t;
cmdlist_t *reqQ;
cmdlist_t *cmpQ;
cmdlist_t *cmd_pool;
+ dma_addr_t cmd_pool_dhandle;
__u32 *cmd_pool_bits;
unsigned int Qdepth;
sizeof(struct floppy_struct));
return err;
}
- return -ENOIOCTLCMD;
+ return -ENOTTY;
}
static int floppy_open(struct inode *inode, struct file *filp)
#include "drmP.h"
-#include <linux/config.h>
#include <linux/sched.h>
#include <linux/smp_lock.h>
#include <asm/shmparam.h>
DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);
priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
+ if(priv == NULL)
+ return -ENOMEM;
memset(priv, 0, sizeof(*priv));
+
filp->private_data = priv;
priv->uid = current->euid;
priv->pid = current->pid;
/* First we read the data in from the file system into a temp buffer */
+ memoff(ch);
+ restore_flags(flags);
+
if (bytesAvailable)
{ /* Begin bytesAvailable */
post_fep_init.
--------------------------------------------------------------------- */
buf = ch->tmp_buf;
- memoff(ch);
- restore_flags(flags);
} /* End from_user */
};
switch (cmd) {
default:
- return -ENOIOCTLCMD;
+ return -ENOTTY;
case WDIOC_GETSUPPORT:
if (copy_to_user
((struct watchdog_info *) arg, &ident, sizeof (ident)))
break;
default:
- return -ENOIOCTLCMD;
+ return -ENOTTY;
}
return 0;
mixcomwd_ping();
break;
default:
- return -ENOIOCTLCMD;
+ return -ENOTTY;
}
return 0;
}
struct moxa_str *ch;
int len, port;
unsigned long flags;
- unsigned char *temp;
ch = (struct moxa_str *) tty->driver_data;
if (ch == NULL)
port = ch->port;
save_flags(flags);
if (from_user) {
+ if (count > PAGE_SIZE)
+ count = PAGE_SIZE;
down(&moxaBuffSem);
if (copy_from_user(moxaXmitBuff, buf, count)) {
len = -EFAULT;
current_params.tap_interval = new.tap_interval;
return 0;
}
- return -ENOIOCTLCMD;
+ return -ENOTTY;
}
switch(cmd) {
default:
- return -ENOIOCTLCMD;
+ return -ENOTTY;
case WDIOC_GETSUPPORT:
i = copy_to_user((void*)arg, &ident, sizeof(ident));
int total, remain, size, stlen;
unsigned int head, tail;
unsigned long flags;
-
/* printk("Entering pcxe_write()\n"); */
if ((ch=chan(tty))==NULL)
if (from_user) {
+ down(&ch->tmp_buf_sem);
save_flags(flags);
cli();
globalwinon(ch);
/* It seems to be necessary to make sure that the value is stable here somehow
This is a rather odd pice of code here. */
do
- { tail = bc->tout;
+ {
+ tail = bc->tout;
} while (tail != bc->tout);
tail &= (size - 1);
stlen = (head >= tail) ? (size - (head - tail) - 1) : (tail - head - 1);
count = MIN(stlen, count);
+ memoff(ch);
+ restore_flags(flags);
+
if (count)
if (copy_from_user(ch->tmp_buf, buf, count))
count = 0;
buf = ch->tmp_buf;
- memoff(ch);
- restore_flags(flags);
}
/*
}
memoff(ch);
restore_flags(flags);
+
+ if(from_user)
+ up(&ch->tmp_buf_sem);
return(total);
}
ch->txbufsize = bc->tmax + 1;
ch->rxbufsize = bc->rmax + 1;
ch->tmp_buf = kmalloc(ch->txbufsize,GFP_KERNEL);
+ init_MUTEX(&ch->tmp_buf_sem);
if (!ch->tmp_buf) {
printk(KERN_ERR "Unable to allocate memory for temp buffers\n");
unchar *txptr;
unchar *rxptr;
unchar *tmp_buf; /* Temp buffer */
+ struct semaphore tmp_buf_sem;
/* ---- Termios data ---- */
ulong c_iflag;
ulong c_cflag;
*/
sector_size = 512;
- if (get_super(rdev) != NULL) {
+ if (is_mounted(rdev)) {
if (blksize_size[MAJOR(rdev)])
sector_size = blksize_size[MAJOR(rdev)][MINOR(rdev)];
} else {
*
* 12/4 - 2000 [Initial revision]
* 25/4 - 2000 Added /dev/watchdog support
+ * 09/5 - 2001 [smj@oro.net] fixed fop_write to "return 1" on success
*
*
* Theory of operation:
/* Well, anyhow someone wrote to us, we should return that favour */
next_heartbeat = jiffies + WDT_HEARTBEAT;
+ return 1;
}
return 0;
}
tty->flip.flag_buf_ptr++;
tty->flip.char_buf_ptr++;
}
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
ignore_char:
+#endif
*status = serial_inp(info, UART_LSR);
} while ((*status & UART_LSR_DR) && (max_count-- > 0));
#if (LINUX_VERSION_CODE > 131394) /* 2.1.66 */
spin_unlock_irq(&priv->tx_lock);
return 0;
}
-#endif CONFIG_NET_FC
+#endif /* CONFIG_NET_FC */
/*
* i2o_lan_packet_send(): Send a packet as is, including the MAC header.
/*
* Set up BM-DMA capability (PnP BIOS should have done this)
*/
- if (!IDE_PCI_DEVID_EQ(d->devid, DEVID_CS5530)
+ if (!IDE_PCI_DEVID_EQ(d->devid, DEVID_CS5530))
hwif->autodma = 0; /* default DMA off if we had to configure it here */
(void) pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_MASTER);
if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) || !(pcicmd & PCI_COMMAND_MASTER)) {
#endif
}
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,51)
-static int capifs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
-static void capifs_write_inode(struct inode *inode) { };
-#else
static int capifs_statfs(struct super_block *sb, struct statfs *buf);
-#endif
-static void capifs_read_inode(struct inode *inode);
static struct super_operations capifs_sops = {
- read_inode: capifs_read_inode,
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,51)
- write_inode: capifs_write_inode,
-#endif
put_super: capifs_put_super,
statfs: capifs_statfs,
};
/*
* Get the root inode and dentry, but defer checking for errors.
*/
- root_inode = iget(s, 1); /* inode 1 == root directory */
+ root_inode = capifs_new_inode(s);
+ if (root_inode) {
+ root_inode->i_ino = 1;
+ root_inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
+ root_inode->i_op = &capifs_root_inode_operations;
+ root_inode->i_fop = &capifs_root_operations;
+ root_inode->i_nlink = 2;
+ }
root = d_alloc_root(root_inode);
/*
}
#endif
-static void capifs_read_inode(struct inode *inode)
+static struct inode *capifs_new_inode(struct super_block *sb);
{
- ino_t ino = inode->i_ino;
- struct capifs_sb_info *sbi = SBI(inode->i_sb);
-
- inode->i_mode = 0;
- inode->i_nlink = 0;
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
- inode->i_blocks = 0;
- inode->i_blksize = 1024;
- inode->i_uid = inode->i_gid = 0;
-
- if ( ino == 1 ) {
- inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
- inode->i_op = &capifs_root_inode_operations;
- inode->i_fop = &capifs_root_operations;
- inode->i_nlink = 2;
- return;
- }
-
- ino -= 2;
- if ( ino >= sbi->max_ncci )
- return; /* Bogus */
-
- init_special_inode(inode, S_IFCHR, 0);
-
- return;
+ inode = new_inode(sb);
+ if (inode) {
+ inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ inode->i_blocks = 0;
+ inode->i_blksize = 1024;
+ inode->i_uid = inode->i_gid = 0;
+ }
+ return inode;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,51)
break;
}
}
+ if ( ino >= sbi->max_ncci )
+ continue;
- if ((np->inode = iget(sb, ino+2)) != 0) {
+ if ((np->inode = capifs_new_inode(sb)) != NULL) {
struct inode *inode = np->inode;
inode->i_uid = sbi->setuid ? sbi->uid : current->fsuid;
inode->i_gid = sbi->setgid ? sbi->gid : current->fsgid;
- inode->i_mode = sbi->mode | S_IFCHR;
- inode->i_rdev = np->kdev;
- inode->i_nlink++;
+ inode->i_nlink = 1;
+ inode->i_ino = ino + 2;
+ init_special_inode(inode, sbi->mode|S_IFCHR, np->kdev);
}
}
}
kmalloc(sizeof(struct ippp_struct), GFP_KERNEL))) {
printk(KERN_WARNING "isdn_ppp_init: Could not alloc ippp_table\n");
for (j = 0; j < i; j++)
- kfree(ippp_table[i]);
+ kfree(ippp_table[j]);
return -1;
}
memset((char *) ippp_table[i], 0, sizeof(struct ippp_struct));
}
memset(rdev, 0, sizeof(*rdev));
- if (get_super(newdev)) {
+ if (is_mounted(newdev)) {
printk("md: can not import %s, has active inodes!\n",
partition_name(newdev));
err = -EBUSY;
}
/* this shouldn't be needed as above would have fired */
- if (!ro && get_super(dev)) {
+ if (!ro && is_mounted(dev)) {
printk (STILL_MOUNTED, mdidx(mddev));
OUT(-EBUSY);
}
vcp = vmalloc(sizeof(struct video_clip)*(vw.clipcount+4));
if (vcp==NULL)
return -ENOMEM;
- if (vw.clipcount && copy_from_user(vcp,vw.clips,sizeof(struct video_clip)*vw.clipcount))
+ if (vw.clipcount && copy_from_user(vcp,vw.clips,sizeof(struct video_clip)*vw.clipcount)) {
+ vfree(vcp);
return -EFAULT;
+ }
on = ztv->running;
if (on)
if (!databuf)
return -ENOMEM;
- if (copy_from_user(databuf, buf.ptr, buf.length))
+ if (copy_from_user(databuf, buf.ptr, buf.length)) {
+ kfree(databuf);
return -EFAULT;
+ }
ret = (mtd->write_oob)(mtd, buf.start, buf.length, &retlen, databuf);
#ifndef _ACENIC_H_
#define _ACENIC_H_
+#include <linux/config.h>
/*
* Generate TX index update each time, when TX ring is closed.
* Copyright (C) 1996 Paul Mackerras.
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
-/* $Id: sunhme.c,v 1.118 2001/05/11 02:09:30 davem Exp $
+/* $Id: sunhme.c,v 1.119 2001/05/17 04:12:16 davem Exp $
* sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching,
* auto carrier detecting ethernet driver. Also known as the
* "Happy Meal Ethernet" found on SunSwift SBUS cards.
#define OLYMPIC_DEBUG 0
-
-#include <linux/config.h>
#include <linux/module.h>
-
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/errno.h>
*/
#include "tulip.h"
+#include <linux/config.h>
#include <linux/etherdevice.h>
#include <linux/pci.h>
#ifndef __NET_TULIP_H__
#define __NET_TULIP_H__
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/spinlock.h>
#define DRV_VERSION "0.9.15-pre2"
#define DRV_RELDATE "May 16, 2001"
+#include <linux/config.h>
#include <linux/module.h>
#include "tulip.h"
#include <linux/pci.h>
if (!(page = (char *)__get_free_page(GFP_KERNEL))) {
return -ENOMEM;
}
- copy_from_user(page, buffer, count = (min(count, PAGE_SIZE)));
+ if(copy_from_user(page, buffer, count = (min(count, PAGE_SIZE))))
+ {
+ count = -EFAULT;
+ goto out;
+ }
if (page[count-1] == '\n')
page[count-1] = '\0';
else if (count < PAGE_SIZE)
page[count] = '\0';
else if (page[count]) {
- count = -EINVAL;
+ count = -EINVAL;
goto out;
}
+ page[count]=0; /* Null terminate */
} else {
byte *tmp;
if (!(page = (char *)__get_free_page(GFP_KERNEL))) return -ENOMEM;
- copy_from_user(page, buffer, count);
+ if(copy_from_user(page, buffer, count))
+ {
+ count = -EFAULT;
+ goto out;
+ }
if (page[count-1] == '\n')
page[count-1] = '\0';
*
* Author: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*
-* Copyright: (c) 1998-2000 Arnaldo Carvalho de Melo
+* Copyright: (c) 1998-2001 Arnaldo Carvalho de Melo
*
* Based on sdlamain.c by Gene Kozin <genek@compuserve.com> &
* Jaspreet Singh <jaspreet@sangoma.com>
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
* ============================================================================
+* 2001/05/09 acme Fix MODULE_DESC for debug, .bss nitpicks,
+* some cleanups
* 2000/07/13 acme remove useless #ifdef MODULE and crap
-* #if KERNEL_VERSION > blah
+* #if KERNEL_VERSION > blah
* 2000/07/06 acme __exit at cyclomx_cleanup
* 2000/04/02 acme dprintk and cycx_debug
* module_init/module_exit
#include <linux/stddef.h> /* offsetof(), etc. */
#include <linux/errno.h> /* return codes */
#include <linux/string.h> /* inline memset(), etc. */
-#include <linux/slab.h> /* kmalloc(), kfree() */
+#include <linux/slab.h> /* kmalloc(), kfree() */
#include <linux/kernel.h> /* printk(), and other useful stuff */
#include <linux/module.h> /* support for loadable modules */
#include <linux/ioport.h> /* request_region(), release_region() */
/* Debug */
-unsigned int cycx_debug = 0;
+unsigned int cycx_debug;
MODULE_AUTHOR("Arnaldo Carvalho de Melo");
MODULE_DESCRIPTION("Cyclom 2X Sync Card Driver.");
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "cyclomx debug level");
+MODULE_PARM(cycx_debug, "i");
+MODULE_PARM_DESC(cycx_debug, "cyclomx debug level");
/* Defines & Macros */
#define DRV_VERSION 0 /* version number */
-#define DRV_RELEASE 9 /* release (minor version) number */
+#define DRV_RELEASE 10 /* release (minor version) number */
#define MAX_CARDS 1 /* max number of adapters */
#define CONFIG_CYCLOMX_CARDS 1
/* private data */
static char drvname[] = "cyclomx";
static char fullname[] = "CYCLOM 2X(tm) Sync Card Driver";
-static char copyright[] = "(c) 1998-2000 Arnaldo Carvalho de Melo "
+static char copyright[] = "(c) 1998-2001 Arnaldo Carvalho de Melo "
"<acme@conectiva.com.br>";
static int ncards = CONFIG_CYCLOMX_CARDS;
-static cycx_t *card_array = NULL; /* adapter data space */
+static cycx_t *card_array; /* adapter data space */
/* Kernel Loadable Module Entry Points */
*/
int __init cyclomx_init (void)
{
- int cnt, err = 0;
+ int cnt, err = -ENOMEM;
printk(KERN_INFO "%s v%u.%u %s\n",
fullname, DRV_VERSION, DRV_RELEASE, copyright);
ncards = min(ncards, MAX_CARDS);
ncards = max(ncards, 1);
card_array = kmalloc(sizeof(cycx_t) * ncards, GFP_KERNEL);
-
if (!card_array)
- return -ENOMEM;
+ goto out;
memset(card_array, 0, sizeof(cycx_t) * ncards);
wandev->magic = ROUTER_MAGIC;
wandev->name = card->devname;
wandev->private = card;
- wandev->setup = &setup;
- wandev->shutdown = &shutdown;
- wandev->ioctl = &ioctl;
+ wandev->setup = setup;
+ wandev->shutdown = shutdown;
+ wandev->ioctl = ioctl;
err = register_wan_device(wandev);
if (err) {
}
}
- if (cnt)
- ncards = cnt; /* adjust actual number of cards */
- else {
+ err = -ENODEV;
+ if (!cnt) {
kfree(card_array);
- err = -ENODEV;
+ goto out;
}
-
- return err;
+ err = 0;
+ ncards = cnt; /* adjust actual number of cards */
+out: return err;
}
/*
*/
static int setup (wan_device_t *wandev, wandev_conf_t *conf)
{
+ int err = -EFAULT;
cycx_t *card;
- int err = 0;
int irq;
/* Sanity checks */
+
if (!wandev || !wandev->private || !conf)
- return -EFAULT;
+ goto out;
card = wandev->private;
-
+ err = -EBUSY;
if (wandev->state != WAN_UNCONFIGURED)
- return -EBUSY;
+ goto out;
+ err = -EINVAL;
if (!conf->data_size || !conf->data) {
printk(KERN_ERR "%s: firmware not found in configuration "
"data!\n", wandev->name);
- return -EINVAL;
+ goto out;
}
if (conf->irq <= 0) {
printk(KERN_ERR "%s: can't configure without IRQ!\n",
wandev->name);
- return -EINVAL;
+ goto out;
}
/* Allocate IRQ */
if (request_irq(irq, cycx_isr, 0, wandev->name, card)) {
printk(KERN_ERR "%s: can't reserve IRQ %d!\n",
wandev->name, irq);
- return -EINVAL;
+ goto out;
}
/* Configure hardware, load firmware, etc. */
memset(&card->hw, 0, sizeof(cycxhw_t));
- card->hw.irq = irq;
+ card->hw.irq = irq;
card->hw.dpmbase = conf->maddr;
card->hw.dpmsize = CYCX_WINDOWSIZE;
- card->hw.fwid = CFID_X25_2X;
- card->lock = SPIN_LOCK_UNLOCKED;
+ card->hw.fwid = CFID_X25_2X;
+ card->lock = SPIN_LOCK_UNLOCKED;
init_waitqueue_head(&card->wait_stats);
- err = cycx_setup(&card->hw, conf->data, conf->data_size);
- if (err) {
- free_irq(irq, card);
- return err;
- }
+ err = cycx_setup(&card->hw, conf->data, conf->data_size);
+ if (err)
+ goto out_irq;
/* Initialize WAN device data space */
wandev->irq = irq;
if (err) {
cycx_down(&card->hw);
- free_irq(irq, card);
- return err;
+ goto out_irq;
}
- return 0;
+ err = 0;
+out: return err;
+out_irq:
+ free_irq(irq, card);
+ goto out;
}
/*
*/
static int shutdown (wan_device_t *wandev)
{
+ int ret = -EFAULT;
cycx_t *card;
/* sanity checks */
if (!wandev || !wandev->private)
- return -EFAULT;
+ goto out;
+ ret = 0;
if (wandev->state == WAN_UNCONFIGURED)
- return 0;
+ goto out;
card = wandev->private;
wandev->state = WAN_UNCONFIGURED;
printk(KERN_INFO "%s: irq %d being freed!\n", wandev->name,
wandev->irq);
free_irq(wandev->irq, card);
-
- return 0;
+out: return ret;
}
/*
*/
static void cycx_isr (int irq, void *dev_id, struct pt_regs *regs)
{
-#define card ((cycx_t*)dev_id)
+ cycx_t *card = (cycx_t *)dev_id;
+
if (!card || card->wandev.state == WAN_UNCONFIGURED)
- return;
+ goto out;
if (card->in_isr) {
printk(KERN_WARNING "%s: interrupt re-entrancy on IRQ %d!\n",
card->devname, card->wandev.irq);
- return;
+ goto out;
}
if (card->isr)
card->isr(card);
-#undef card
+out: return;
}
/*
/* Set WAN device state. */
void cyclomx_set_state (cycx_t *card, int state)
{
- unsigned long host_cpu_flags;
+ unsigned long flags;
char *string_state = NULL;
- spin_lock_irqsave(&card->lock, host_cpu_flags);
+ spin_lock_irqsave(&card->lock, flags);
if (card->wandev.state != state) {
switch (state) {
}
card->state_tick = jiffies;
- spin_unlock_irqrestore(&card->lock, host_cpu_flags);
+ spin_unlock_irqrestore(&card->lock, flags);
}
module_init(cyclomx_init);
module_exit(cyclomx_cleanup);
-
-/* End */
#endif
#include <linux/if.h>
-#include <linux/wanpipe.h>
#include <linux/sdla_ppp.h> /* PPP firmware API definitions */
#include <linux/sdlasfm.h> /* S514 Type Definition */
/****** Defines & Macros ****************************************************/
#if defined(_LINUX_) /****** Linux *******************************/
+#include <linux/config.h>
#include <linux/version.h>
#include <linux/kernel.h> /* printk(), and other useful stuff */
#include <linux/stddef.h> /* offsetof(), etc. */
#include <linux/random.h>
#include <linux/pkt_sched.h>
#include <asm/byteorder.h>
+#include <asm/uaccess.h>
#include <linux/spinlock.h>
#include <net/syncppp.h>
static struct sppp *spppq;
static struct timer_list sppp_keepalive_timer;
-static spinlock_t spppq_lock;
+static spinlock_t spppq_lock = SPIN_LOCK_UNLOCKED;
static void sppp_keepalive (unsigned long dummy);
static void sppp_cp_send (struct sppp *sp, u16 proto, u8 type,
if(ifr->ifr_flags)
sp->pp_flags|=PP_DEBUG;
break;
+ case SPPPIOCGFLAGS:
+ if(copy_to_user(ifr->ifr_data, &sp->pp_flags, sizeof(sp->pp_flags)))
+ return -EFAULT;
+ break;
+ case SPPPIOCSFLAGS:
+ if(copy_from_user(&sp->pp_flags, ifr->ifr_data, sizeof(sp->pp_flags)))
+ return -EFAULT;
+ break;
default:
return -EINVAL;
}
debug=PP_DEBUG;
printk(KERN_INFO "Cronyx Ltd, Synchronous PPP and CISCO HDLC (c) 1994\n");
printk(KERN_INFO "Linux port (c) 1998 Building Number Three Ltd & Jan \"Yenya\" Kasprzak.\n");
- spin_lock_init(&spppq_lock);
sppp_packet_type.type=htons(ETH_P_WAN_PPP);
dev_add_pack(&sppp_packet_type);
return 0;
chdlc_priv_area->if_ptr = pppdev;
/* prepare network device data space for registration */
+
+#ifdef LINUX_2_4
+ strcpy(dev->name,card->u.c.if_name);
+#else
+ dev->name = (char *)kmalloc(strlen(card->u.c.if_name) + 2, GFP_KERNEL);
+ if(dev->name == NULL)
+ {
+ kfree(chdlc_priv_area);
+ return -ENOMEM;
+ }
+ sprintf(dev->name, "%s", card->u.c.if_name);
+#endif
/* Attach PPP protocol layer to pppdev
* The sppp_attach() will initilize the dev structure
* if_open(), if_close(), if_send() and get_stats() functions.
*/
sppp_attach(pppdev);
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,16)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,16)
dev = pppdev->dev;
- #else
+#else
dev = &pppdev->dev;
- #endif
+#endif
sp = &pppdev->sppp;
/* Enable PPP Debugging */
// FIXME Fix this up somehow
//sp->pp_flags |= PP_DEBUG;
sp->pp_flags &= ~PP_CISCO;
-
- #ifdef LINUX_2_4
- strcpy(dev->name,card->u.c.if_name);
- #else
- dev->name = (char *)kmalloc(strlen(card->u.c.if_name) + 2, GFP_KERNEL);
- sprintf(dev->name, "%s", card->u.c.if_name);
- #endif
dev->init = &if_init;
dev->priv = chdlc_priv_area;
chdlc_private_area_t* chdlc_priv_area = dev->priv;
sdla_t* card = chdlc_priv_area->card;
wan_device_t* wandev = &card->wandev;
- #ifdef LINUX_2_0
+#ifdef LINUX_2_0
int i;
- #endif
+#endif
/* NOTE: Most of the dev initialization was
* done in sppp_attach(), called by new_if()
dev->stop = &if_close;
dev->hard_start_xmit = &if_send;
dev->get_stats = &if_stats;
- #ifdef LINUX_2_4
+#ifdef LINUX_2_4
dev->tx_timeout = &if_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
- #endif
+#endif
- #ifdef LINUX_2_0
+#ifdef LINUX_2_0
dev->family = AF_INET;
- #endif
+#endif
/* Initialize hardware parameters */
dev->irq = wandev->irq;
dev->tx_queue_len = 100;
/* Initialize socket buffers */
- #if !defined(LINUX_2_1) && !defined(LINUX_2_4)
+#if !defined(LINUX_2_1) && !defined(LINUX_2_4)
for (i = 0; i < DEV_NUMBUFFS; ++i)
skb_queue_head_init(&dev->buffs[i]);
- #endif
+#endif
return 0;
}
/* Only one open per interface is allowed */
- #ifdef LINUX_2_4
+#ifdef LINUX_2_4
if (netif_running(dev))
return -EBUSY;
- #else
+#else
if (dev->start)
return -EBUSY; /* only one open is allowed */
- #endif
+#endif
/* Start PPP Layer */
if (sppp_open(dev)){
do_gettimeofday(&tv);
chdlc_priv_area->router_start_time = tv.tv_sec;
- #ifdef LINUX_2_4
+#ifdef LINUX_2_4
netif_start_queue(dev);
- #else
+#else
dev->interrupt = 0;
dev->tbusy = 0;
dev->start = 1;
- #endif
+#endif
wanpipe_open(card);
sppp_close(dev);
stop_net_queue(dev);
- #ifndef LINUX_2_4
+#ifndef LINUX_2_4
dev->start=0;
- #endif
+#endif
wanpipe_close(card);
unsigned long smp_flags;
int err=0;
- #ifdef LINUX_2_4
+#ifdef LINUX_2_4
netif_stop_queue(dev);
- #endif
+#endif
if (skb == NULL){
return 0;
}
- #ifndef LINUX_2_4
+#ifndef LINUX_2_4
if (dev->tbusy){
/* If our device stays busy for at least 5 seconds then we will
/* unbusy the interface */
dev->tbusy = 0;
}
- #endif
+#endif
if (ntohs(skb->protocol) != htons(PVC_PROT)){
/* check the udp packet type */
}else{
++card->wandev.stats.tx_packets;
- #if defined(LINUX_2_1) || defined(LINUX_2_4)
+#if defined(LINUX_2_1) || defined(LINUX_2_4)
card->wandev.stats.tx_bytes += skb->len;
- #endif
- #ifdef LINUX_2_4
+#endif
+#ifdef LINUX_2_4
dev->trans_start = jiffies;
- #endif
+#endif
start_net_queue(dev);
}
goto rx_exit;
}
- #ifdef LINUX_2_4
+#ifdef LINUX_2_4
if (!netif_running(dev)){
goto rx_exit;
}
- #else
+#else
if (!dev->start){
goto rx_exit;
}
- #endif
+#endif
chdlc_priv_area = dev->priv;
void s508_lock (sdla_t *card, unsigned long *smp_flags)
{
- #if defined(__SMP__) || defined(LINUX_2_4)
+#if defined(__SMP__) || defined(LINUX_2_4)
spin_lock_irqsave(&card->wandev.lock, *smp_flags);
if (card->next){
/* It is ok to use spin_lock here, since we
* already turned off interrupts */
spin_lock(&card->next->wandev.lock);
}
- #else
+#else
disable_irq(card->hw.irq);
- #endif
+#endif
}
void s508_unlock (sdla_t *card, unsigned long *smp_flags)
{
- #if defined(__SMP__) || defined(LINUX_2_4)
+#if defined(__SMP__) || defined(LINUX_2_4)
if (card->next){
spin_unlock(&card->next->wandev.lock);
}
spin_unlock_irqrestore(&card->wandev.lock, *smp_flags);
- #else
+#else
enable_irq(card->hw.irq);
- #endif
+#endif
}
void
hwc_tty_init (void)
{
-#ifdef CONFIG_3215
+#if defined(CONFIG_3215_CONSOLE) || defined(CONFIG_3270_CONSOLE)
if (MACHINE_IS_VM)
return;
#endif
VDEB(printk("port_base=%x\n", port_base));
break;
}
+ release_region(ports[i], 0x10);
}
}
}
Feb 20, 1999 (v3.1e)
1) I took the warning from the Linux Kernel Hackers Guide serious and
- checked the cmd->result return value to the done-function very carefuly.
+ checked the cmd->result return value to the done-function very carefully.
It is obvious, that the IBM SCSI only delivers the tsb.dev_status, if
some error appeared, else it is undefined. Now, this is fixed. Before
any SCB command gets queued, the tsb.dev_status is set to 0, so the
9 Disclaimer
------------
- Beside the GNU public license and the dependant disclaimers and disclaimers
+ Beside the GNU General Public License and the dependant disclaimers and disclaimers
concerning the Linux-kernel in special, this SCSI-driver comes without any
warranty. Its functionality is tested as good as possible on certain
machines and combinations of computer hardware, which does not exclude,
*
*/
+#include <linux/config.h>
+
/*
* The next three defines are user configurable. These should be the only
* defines a user might need to get in here and change. There are other
if ( ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 )
&& ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 ) )
break;
+ release_region(qbase, 0x10 );
}
if (qbase == 0x430)
return 0;
{ SOUND_MIXER_WRITE_OGAIN, 0x4040 }
};
-#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)
{
struct es1370_state *s;
mm_segment_t fs;
- int i, val;
+ int i, val, ret;
+
+ if ((ret=pci_enable_device(pcidev)))
+ return ret;
- if (!RSRCISIOREGION(pcidev, 0))
- return -1;
+ if ( !(pci_resource_flags(pcidev, 0) & IORESOURCE_IO) ||
+ !pci_resource_start(pcidev, 0)
+ )
+ return -ENODEV;
if (pcidev->irq == 0)
- return -1;
+ return -ENODEV;
i = pci_set_dma_mask(pcidev, 0xffffffff);
if (i) {
printk(KERN_WARNING "es1370: architecture does not support 32bit PCI busmaster DMA\n");
}
if (!(s = kmalloc(sizeof(struct es1370_state), GFP_KERNEL))) {
printk(KERN_WARNING "es1370: out of memory\n");
- return -1;
+ return -ENOMEM;
}
memset(s, 0, sizeof(struct es1370_state));
init_waitqueue_head(&s->dma_adc.wait);
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);
+ ret = -EBUSY;
goto err_region;
}
- if (pci_enable_device(pcidev))
- goto err_irq;
- if (request_irq(s->irq, es1370_interrupt, SA_SHIRQ, "es1370", s)) {
+ if ((ret=request_irq(s->irq, es1370_interrupt, SA_SHIRQ, "es1370",s))) {
printk(KERN_ERR "es1370: irq %u in use\n", s->irq);
goto err_irq;
}
+
/* initialize codec registers */
/* note: setting CTRL_SERR_DIS is reported to break
* mic bias setting (by Kim.Berts@fisub.mail.abb.com) */
(s->ctrl & CTRL_XCTL0) ? "out" : "in",
(s->ctrl & CTRL_XCTL1) ? "1" : "0");
/* register devices */
- if ((s->dev_audio = register_sound_dsp(&es1370_audio_fops, -1)) < 0)
+ if ((s->dev_audio = register_sound_dsp(&es1370_audio_fops, -1)) < 0) {
+ ret = s->dev_audio;
goto err_dev1;
- if ((s->dev_mixer = register_sound_mixer(&es1370_mixer_fops, -1)) < 0)
+ }
+ if ((s->dev_mixer = register_sound_mixer(&es1370_mixer_fops, -1)) < 0) {
+ ret = s->dev_mixer;
goto err_dev2;
- if ((s->dev_dac = register_sound_dsp(&es1370_dac_fops, -1)) < 0)
+ }
+ if ((s->dev_dac = register_sound_dsp(&es1370_dac_fops, -1)) < 0) {
+ ret = s->dev_dac;
goto err_dev3;
- if ((s->dev_midi = register_sound_midi(&es1370_midi_fops, -1)) < 0)
+ }
+ if ((s->dev_midi = register_sound_midi(&es1370_midi_fops, -1)) < 0) {
+ ret = s->dev_midi;
goto err_dev4;
+ }
/* initialize the chips */
outl(s->ctrl, s->io+ES1370_REG_CONTROL);
outl(s->sctrl, s->io+ES1370_REG_SERIAL_CONTROL);
release_region(s->io, ES1370_EXTENT);
err_region:
kfree(s);
- return -1;
+ return ret;
}
static void __devinit es1370_remove(struct pci_dev *dev)
{ SOUND_MIXER_WRITE_IGAIN, 0x4040 }
};
-#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)
{
struct es1371_state *s;
mm_segment_t fs;
- int i, val;
+ int i, val, res = -1;
unsigned long tmo;
signed long tmo2;
unsigned int cssr;
- if (!RSRCISIOREGION(pcidev, 0))
- return -1;
+ if ((res=pci_enable_device(pcidev)))
+ return res;
+
+ if (!(pci_resource_flags(pcidev, 0) & IORESOURCE_IO))
+ return -ENODEV;
if (pcidev->irq == 0)
- return -1;
+ return -ENODEV;
i = pci_set_dma_mask(pcidev, 0xffffffff);
if (i) {
printk(KERN_WARNING "es1371: architecture does not support 32bit PCI busmaster DMA\n");
}
if (!(s = kmalloc(sizeof(struct es1371_state), GFP_KERNEL))) {
printk(KERN_WARNING PFX "out of memory\n");
- return -1;
+ return -ENOMEM;
}
memset(s, 0, sizeof(struct es1371_state));
init_waitqueue_head(&s->dma_adc.wait);
s->vendor, s->device, s->rev);
if (!request_region(s->io, ES1371_EXTENT, "es1371")) {
printk(KERN_ERR PFX "io ports %#lx-%#lx in use\n", s->io, s->io+ES1371_EXTENT-1);
+ res = -EBUSY;
goto err_region;
}
- if (pci_enable_device(pcidev))
- goto err_irq;
- if (request_irq(s->irq, es1371_interrupt, SA_SHIRQ, "es1371", s)) {
+ if ((res=request_irq(s->irq, es1371_interrupt, SA_SHIRQ, "es1371",s))) {
printk(KERN_ERR PFX "irq %u in use\n", s->irq);
goto err_irq;
}
printk(KERN_INFO PFX "found es1371 rev %d at io %#lx irq %u\n"
KERN_INFO PFX "features: joystick 0x%x\n", s->rev, s->io, s->irq, joystick[devindex]);
/* register devices */
- if ((s->dev_audio = register_sound_dsp(&es1371_audio_fops, -1)) < 0)
+ if ((res=(s->dev_audio = register_sound_dsp(&es1371_audio_fops,-1))<0))
goto err_dev1;
- if ((s->codec.dev_mixer = register_sound_mixer(&es1371_mixer_fops, -1)) < 0)
+ if ((res=(s->codec.dev_mixer = register_sound_mixer(&es1371_mixer_fops, -1)) < 0))
goto err_dev2;
- if ((s->dev_dac = register_sound_dsp(&es1371_dac_fops, -1)) < 0)
+ if ((res=(s->dev_dac = register_sound_dsp(&es1371_dac_fops, -1)) < 0))
goto err_dev3;
- if ((s->dev_midi = register_sound_midi(&es1371_midi_fops, -1)) < 0)
+ if ((res=(s->dev_midi = register_sound_midi(&es1371_midi_fops, -1))<0 ))
goto err_dev4;
#ifdef ES1371_DEBUG
/* intialize the debug proc device */
/* init the sample rate converter */
src_init(s);
/* codec init */
- if (!ac97_probe_codec(&s->codec))
+ if (!ac97_probe_codec(&s->codec)) {
+ res = -ENODEV;
goto err_gp;
+ }
/* set default values */
fs = get_fs();
release_region(s->io, ES1371_EXTENT);
err_region:
kfree(s);
- return -1;
+ return res;
}
static void __devinit es1371_remove(struct pci_dev *dev)
* Fix SETTRIGGER non OSS API conformity
* 10.03.2001 provide abs function, prevent picking up a bogus kernel macro
* for abs. Bug report by Andrew Morton <andrewm@uow.edu.au>
+ * 15.05.2001 pci_enable_device moved, return values in probe cleaned
+ * up. Marcus Meissner <mm@caldera.de>
*/
/*****************************************************************************/
/* --------------------------------------------------------------------- */
-/* prevent picking up a bogus abs macro */
-#undef abs
-extern inline int abs(int x)
-{
- if (x < 0)
- return -x;
- return x;
-}
-
-/* --------------------------------------------------------------------- */
-
#ifndef PCI_VENDOR_ID_ESS
#define PCI_VENDOR_ID_ESS 0x125d
#endif
return 0;
}
-
-#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)
{
struct solo1_state *s;
struct pm_dev *pmdev;
+ int ret;
- if (!RSRCISIOREGION(pcidev, 0) ||
- !RSRCISIOREGION(pcidev, 1) ||
- !RSRCISIOREGION(pcidev, 2) ||
- !RSRCISIOREGION(pcidev, 3))
- return -1;
+ if ((ret=pci_enable_device(pcidev)))
+ return ret;
+ if (!(pci_resource_flags(pcidev, 0) & IORESOURCE_IO) ||
+ !(pci_resource_flags(pcidev, 1) & IORESOURCE_IO) ||
+ !(pci_resource_flags(pcidev, 2) & IORESOURCE_IO) ||
+ !(pci_resource_flags(pcidev, 3) & IORESOURCE_IO))
+ return -ENODEV;
if (pcidev->irq == 0)
- return -1;
+ return -ENODEV;
/* Recording requires 24-bit DMA, so attempt to set dma mask
* to 24 bits first, then 32 bits (playback only) if that fails.
if (pci_set_dma_mask(pcidev, 0x00ffffff) &&
pci_set_dma_mask(pcidev, 0xffffffff)) {
printk(KERN_WARNING "solo1: architecture does not support 24bit or 32bit PCI busmaster DMA\n");
- return -1;
+ return -ENODEV;
}
if (!(s = kmalloc(sizeof(struct solo1_state), GFP_KERNEL))) {
printk(KERN_WARNING "solo1: out of memory\n");
- return -1;
+ return -ENOMEM;
}
memset(s, 0, sizeof(struct solo1_state));
init_waitqueue_head(&s->dma_adc.wait);
s->gameport.io = pci_resource_start(pcidev, 4);
s->gameport.size = pci_resource_len(pcidev,4);
s->irq = pcidev->irq;
+ ret = -EBUSY;
if (!request_region(s->iobase, IOBASE_EXTENT, "ESS Solo1")) {
printk(KERN_ERR "solo1: io ports in use\n");
goto err_region1;
printk(KERN_ERR "solo1: gameport io ports in use\n");
s->gameport.io = s->gameport.size = 0;
}
- if (request_irq(s->irq, solo1_interrupt, SA_SHIRQ, "ESS Solo1", s)) {
+ if ((ret=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;
}
- if (pci_enable_device(pcidev))
- goto err_irq;
printk(KERN_INFO "solo1: joystick port at %#x\n", s->gameport.io+1);
/* register devices */
- if ((s->dev_audio = register_sound_dsp(&solo1_audio_fops, -1)) < 0)
+ if ((s->dev_audio = register_sound_dsp(&solo1_audio_fops, -1)) < 0) {
+ ret = s->dev_audio;
goto err_dev1;
- if ((s->dev_mixer = register_sound_mixer(&solo1_mixer_fops, -1)) < 0)
+ }
+ if ((s->dev_mixer = register_sound_mixer(&solo1_mixer_fops, -1)) < 0) {
+ ret = s->dev_mixer;
goto err_dev2;
- if ((s->dev_midi = register_sound_midi(&solo1_midi_fops, -1)) < 0)
+ }
+ if ((s->dev_midi = register_sound_midi(&solo1_midi_fops, -1)) < 0) {
+ ret = s->dev_midi;
goto err_dev3;
- if ((s->dev_dmfm = register_sound_special(&solo1_dmfm_fops, 15 /* ?? */)) < 0)
+ }
+ if ((s->dev_dmfm = register_sound_special(&solo1_dmfm_fops, 15 /* ?? */)) < 0) {
+ ret = s->dev_dmfm;
goto err_dev4;
- if (setup_solo1(s))
+ }
+ if (setup_solo1(s)) {
+ ret = -EIO;
goto err;
+ }
/* register gameport */
gameport_register_port(&s->gameport);
/* store it in the driver field */
release_region(s->mpubase, MPUBASE_EXTENT);
err_region1:
kfree(s);
- return -1;
+ return ret;
}
static void __devinit solo1_remove(struct pci_dev *dev)
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
0,0,0,0,
0,1,1,-1},
+ {"Sound Blaster AWE 32",
+ ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0045),
+ ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
+ 0,0,0,0,
+ 0,1,1,-1},
{"Sound Blaster AWE 32",
ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0047),
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
{ ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0044),
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
+ { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0045),
+ ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
+
{ ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0048),
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
comment 'USB Multimedia devices'
dep_tristate ' USB IBM (Xirlink) C-it Camera support' CONFIG_USB_IBMCAM $CONFIG_USB $CONFIG_VIDEO_DEV
dep_tristate ' USB OV511 Camera support' CONFIG_USB_OV511 $CONFIG_USB $CONFIG_VIDEO_DEV
+ dep_tristate ' USB Philips Cameras' CONFIG_USB_PWC $CONFIG_USB $CONFIG_VIDEO_DEV
dep_tristate ' D-Link USB FM radio support (EXPERIMENTAL)' CONFIG_USB_DSBR $CONFIG_USB $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL
dep_tristate ' DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB
list-multi := usbcore.o
usbcore-objs := usb.o usb-debug.o hub.o
+ifneq ($(CONFIG_USB_PWC),n)
+ # By default we use the C colour conversion functions unless we
+ # detect an Intel CPU, for which there is assembly available
+ ccvt-objs := ccvt_c.o vcvt_c.o
+ ifeq ($(CONFIG_X86),y)
+ ccvt-objs := ccvt_i386.o vcvt_i386.o
+ endif
+
+ export-objs += pwc-uncompress.o
+ list-multi += pwc.o
+endif
+
+pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o $(ccvt-objs)
+
+
# Optional parts of multipart objects.
ifeq ($(CONFIG_USB_DEVICEFS),y)
obj-$(CONFIG_USB_PRINTER) += printer.o
obj-$(CONFIG_USB_AUDIO) += audio.o
obj-$(CONFIG_USB_IBMCAM) += ibmcam.o
+obj-$(CONFIG_USB_PWC) += pwc.o
obj-$(CONFIG_USB_DC2XX) += dc2xx.o
obj-$(CONFIG_USB_MDC800) += mdc800.o
obj-$(CONFIG_USB_USS720) += uss720.o
usbcore.o: $(usbcore-objs)
$(LD) -r -o $@ $(usbcore-objs)
+pwc.o: $(pwc-objs)
+ $(LD) -r -o $@ $(pwc-objs)
+
#undef DEBUG
#include <linux/usb.h>
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.18"
+#define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik"
+#define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters"
+
/*
* CMSPAR, some architectures can't have space and mark parity.
*/
return -1;
}
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
+
return 0;
}
module_init(acm_init);
module_exit(acm_exit);
-MODULE_AUTHOR("Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik");
-MODULE_DESCRIPTION("USB Abstract Control Model driver for USB modems and ISDN adapters");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
* 2000-11-26: Thomas Sailer
* Workaround for Dallas DS4201. The DS4201 uses PCM8 as format tag for
* its 8 bit modes, but expects signed data (and should therefore have used PCM).
+ * 2001-04-08: gb
+ * Identify version on module load.
*
*/
#include "audio.h"
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Alan Cox <alan@lxorguk.ukuu.org.uk>, Thomas Sailer (sailer@ife.ee.ethz.ch)"
+#define DRIVER_DESC "USB Audio Class driver"
+
#define AUDIO_DEBUG 1
#define SND_DEV_DSP16 5
static int __init usb_audio_init(void)
{
usb_register(&usb_audio_driver);
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
return 0;
}
module_init(usb_audio_init);
module_exit(usb_audio_cleanup);
-MODULE_AUTHOR("Alan Cox <alan@lxorguk.ukuu.org.uk>, Thomas Sailer (sailer@ife.ee.ethz.ch)");
-MODULE_DESCRIPTION("USB Audio Class driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
* Copyright (c) 2000 Mark Douglas Corner <mcorner@umich.edu>
*
* USB Bluetooth driver, based on the Bluetooth Spec version 1.0B
+ *
+ * (08/04/2001) gb
+ * Identify version on module load.
*
* (2001/03/10) Version 0.8 gkh
* Fixed problem with not unlinking interrupt urb on device close
#define DEBUG
#include <linux/usb.h>
-/* Module information */
-MODULE_AUTHOR("Greg Kroah-Hartman, Mark Douglas Corner");
-MODULE_DESCRIPTION("USB Bluetooth driver");
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.8"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman, Mark Douglas Corner"
+#define DRIVER_DESC "USB Bluetooth driver"
/* define this if you have hardware that is not good */
/*#define BTBUGGYHARDWARE */
return -1;
}
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
+
return 0;
}
module_init(usb_bluetooth_init);
module_exit(usb_bluetooth_exit);
+/* Module information */
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
--- /dev/null
+/*
+ (C) 2000 Nemosoft Unv. nemosoft@smcc.demon.nl
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+#ifndef CCVT_H
+#define CCVT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Colour ConVerT: going from one colour space to another
+
+ Format descriptions:
+ 420i = "4:2:0 interlaced"
+ YYYY UU YYYY UU even lines
+ YYYY VV YYYY VV odd lines
+ U/V data is subsampled by 2 both in horizontal
+ and vertical directions, and intermixed with the Y values.
+
+ 420p = "4:2:0 planar"
+ YYYYYYYY N lines
+ UUUU N/2 lines
+ VVVV N/2 lines
+ U/V is again subsampled, but all the Ys, Us and Vs are placed
+ together in separate buffers. The buffers may be placed in
+ one piece of contiguous memory though, with Y buffer first,
+ followed by U, followed by V.
+
+ yuyv = "4:2:2 interlaced"
+ YUYV YUYV YUYV ... N lines
+ The U/V data is subsampled by 2 in horizontal direction only.
+
+ bgr24 = 3 bytes per pixel, in the order Blue Green Red (whoever came up
+ with that idea...)
+ rgb24 = 3 bytes per pixel, in the order Red Green Blue (which is sensible)
+ rgb32 = 4 bytes per pixel, in the order Red Green Blue Alpha, with
+ Alpha really being a filler byte (0)
+ bgr32 = last but not least, 4 bytes per pixel, in the order Blue Green Red
+ Alpha, Alpha again a filler byte (0)
+ */
+
+/* Functions in ccvt_i386.S/ccvt_c.c */
+/* 4:2:0 YUV interlaced to RGB/BGR */
+void ccvt_420i_bgr24(int width, int height, void *src, void *dst);
+void ccvt_420i_rgb24(int width, int height, void *src, void *dst);
+void ccvt_420i_bgr32(int width, int height, void *src, void *dst);
+void ccvt_420i_rgb32(int width, int height, void *src, void *dst);
+
+/* 4:2:2 YUYV interlaced to RGB/BGR */
+void ccvt_yuyv_rgb32(int width, int height, void *src, void *dst);
+void ccvt_yuyv_bgr32(int width, int height, void *src, void *dst);
+
+/* 4:2:0 YUV planar to RGB/BGR */
+void ccvt_420p_rgb32(int width, int height, void *srcy, void *srcu, void *srcv, void *dst);
+void ccvt_420p_bgr32(int width, int height, void *srcy, void *srcu, void *srcv, void *dst);
+
+/* RGB/BGR to 4:2:0 YUV interlaced */
+
+/* RGB/BGR to 4:2:0 YUV planar */
+void ccvt_rgb24_420p(int width, int height, void *src, void *dsty, void *dstu, void *dstv);
+void ccvt_bgr24_420p(int width, int height, void *src, void *dsty, void *dstu, void *dstv);
+
+/* Go from 420i to other yuv formats */
+void ccvt_420i_420p(int width, int height, void *src, void *dsty, void *dstu, void *dstv);
+void ccvt_420i_yuyv(int width, int height, void *src, void *dst);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/*
+ Colour conversion routines (RGB <-> YUV) in plain C
+ (C) 2000-2001 Nemosoft Unv. nemosoft@smcc.demon.nl
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+
+#include "ccvt.h"
+#include "vcvt.h"
+
+/* We use the viewport routines, with a viewport width that is exactly
+ the same as the image width. The overhead for computing the view/image
+ offsets is very small anyway.
+
+ The assembly routines are still different, since they are quite optimized.
+ */
+void ccvt_420i_rgb24(int width, int height, void *src, void *dst)
+{
+ vcvt_420i_rgb24(width, height, width, src, dst);
+}
+
+void ccvt_420i_bgr24(int width, int height, void *src, void *dst)
+{
+ vcvt_420i_bgr24(width, height, width, src, dst);
+}
+
+void ccvt_420i_rgb32(int width, int height, void *src, void *dst)
+{
+ vcvt_420i_rgb32(width, height, width, src, dst);
+}
+
+void ccvt_420i_bgr32(int width, int height, void *src, void *dst)
+{
+ vcvt_420i_bgr32(width, height, width, src, dst);
+}
+
+
+void ccvt_420i_420p(int width, int height, void *src, void *dsty, void *dstu, void *dstv)
+{
+ vcvt_420i_420p(width, height, width, src, dsty, dstu, dstv);
+}
+
+void ccvt_420i_yuyv(int width, int height, void *src, void *dst)
+{
+ vcvt_420i_yuyv(width, height, width, src, dst);
+}
--- /dev/null
+/*
+Colour conversion routines (RGB <-> YUV) in x86 assembly
+
+(C) 2000 Nemosoft Unv. nemosoft@smcc.demon.nl
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+
+/* The ccvt_* functions always start with width and height, so these
+ parameters are in 8(%ebp) and 12 (%ebp). The other parameters can be
+ 2 to 4 pointers, and one of these combinations:
+ *src, *dst
+ *srcy, *srcu, *srv, *dst
+ *src, *dsty, *dstu, *dstv
+ */
+
+#define __ASSEMBLY__
+#include <linux/linkage.h>
+
+#define Width 8(%ebp)
+#define Height 12(%ebp)
+
+/* 2 parameters, 1 in, 1 out */
+#define Src2 16(%ebp)
+#define Dst2 20(%ebp)
+
+/* 4 parameters, 3 in, 1 out */
+#define SrcY 16(%ebp)
+#define SrcU 20(%ebp)
+#define SrcV 24(%ebp)
+#define Dst4 28(%ebp)
+
+/* 4 parameters, 1 in, 3 out */
+#define Src4 16(%ebp)
+#define DstY 20(%ebp)
+#define DstU 24(%ebp)
+#define DstV 28(%ebp)
+
+/* This buffer space used to be staticly allocted, but this is going to
+ give problems with multiple cams (though I have yet to see it).
+ Therefor, we reserve at least 64 + 8 = 72 bytes on the stack with
+ `enter'.
+ */
+
+#define PixelBuffer -64(%ebp)
+#define Uptr -68(%ebp)
+#define Vptr -72(%ebp)
+
+ .text
+
+/* This function will load the src and destination pointers, including
+ Uptr/Vptr when necessary, and test the width/height parameters.
+ - %esi will be set to Src or SrcY
+ - %edi will be set to Dst or DstY
+ the carry flag will be set if any of these tests fail.
+ It assumes %ebp has been set.
+ */
+/* 2 parameters, src & dst */
+test_param_2:
+ mov Src2, %esi
+ mov Dst2, %edi
+
+ cmp $0, %esi # NULL pointers?
+ je param_fail
+ cmp $0, %edi
+ je param_fail
+
+ jmp test_width_height
+
+/* 3 inputs, 1 output */
+test_param_31:
+ mov Dst4, %edi # NULL pointers
+ cmp $0, %edi
+ je param_fail
+
+ mov SrcV, %esi
+ cmp $0, %esi
+ je param_fail
+ mov %esi, Vptr
+
+ mov SrcU, %esi
+ cmp $0, %esi
+ je param_fail
+ mov %esi, Uptr
+
+ mov SrcY, %esi
+ cmp $0, %esi
+ je param_fail
+
+ jmp test_width_height
+
+/* 1 input, 3 output */
+test_param_13:
+ mov Src4, %esi # NULL pointers
+ cmp $0, %esi
+ je param_fail
+
+ mov DstV, %edi
+ cmp $0, %edi
+ je param_fail
+ mov %edi, Vptr
+
+ mov DstU, %edi
+ cmp $0, %edi
+ je param_fail
+ mov %edi, Uptr
+
+ mov DstY, %edi
+ cmp $0, %edi
+ je param_fail
+
+ jmp test_width_height
+
+ nop
+
+test_width_height:
+ cmpl $0, Width
+ jbe param_fail
+ testl $3, Width # multiple of 4?
+ jnz param_fail # Nope...
+
+ cmp $0, Height # check illegal height
+ jbe param_fail
+ testl $1, Height # Odd no. of lines?
+ jnz param_fail # Aye
+
+ /* fall through */
+
+/* exit points */
+param_ok:
+ clc # Success: clear carry
+ ret
+
+param_fail:
+ stc # Fail: set carry
+ ret
+
+
+
+# This will fill PixelBuffer with 4 grey scale pixels (Y)
+# In: %eax = Value (Y3Y2Y1Y0)
+# Out:
+# Modifies: %ecx (-4)
+# Destroys: %edx
+expand_4_y:
+ mov %eax, %edx # Keep in edx (we need eax)
+ lea PixelBuffer, %edi
+
+0: # This code is executed 4 times
+ movzbl %dl, %eax # move, zero extending byte-to-long
+ shl $8, %eax # 8 digit precision
+
+ stosl # Expand into PixelBuffer
+ stosl
+ stosl
+ add $4, %edi # Skip alpha
+
+ shr $8, %edx # next Y
+
+ dec %ecx
+ test $3, %ecx
+ jnz 0b
+
+ ret # from expand_4_y
+
+# This will add the color factors to the (grey) values in PixelBuffer
+# In: %ebx (U1U0V1V0)
+# Out:
+# Modifies:
+# Destroys: %edi, %ebx, %eax, %edx
+expand_4_uv:
+ lea PixelBuffer, %edi # reset pointer
+
+ # V0
+ sub $128, %bl
+ movsbl %bl, %eax
+ mov $359, %edx # Vr
+ mul %edx
+ add %eax, 0x00(%edi)
+ add %eax, 0x10(%edi)
+
+ movsbl %bl, %eax
+ mov $183, %edx # Vg
+ mul %edx
+ sub %eax, 0x04(%edi)
+ sub %eax, 0x14(%edi)
+
+ # V1
+ sub $128, %bh
+ movsbl %bh, %eax
+ mov $359, %edx # Vr
+ mul %edx
+ add %eax, 0x20(%edi)
+ add %eax, 0x30(%edi)
+
+ movsbl %bh, %eax
+ mov $183, %edx # Vg
+ mul %edx
+ sub %eax, 0x24(%edi)
+ sub %eax, 0x34(%edi)
+
+ # U0
+ bswap %ebx # Get U values in lower half
+ sub $128, %bh
+ movsbl %bh, %eax
+ mov $88, %edx # Ug
+ mul %edx
+ sub %eax, 0x04(%edi)
+ sub %eax, 0x14(%edi)
+
+ movsbl %bh, %eax
+ mov $454, %edx # Ub
+ mul %edx
+ add %eax, 0x08(%edi)
+ add %eax, 0x18(%edi)
+
+ # U1
+ sub $128, %bl
+ movsbl %bl, %eax
+ mov $88, %edx # Ug
+ mul %edx
+ sub %eax, 0x24(%edi)
+ sub %eax, 0x34(%edi)
+
+ movsbl %bl, %eax
+ mov $454, %edx # Ub
+ mul %edx
+ add %eax, 0x28(%edi)
+ add %eax, 0x38(%edi)
+ ret # expand_4_uv
+
+
+/* This function expands 4 420i pixels into PixelBuffer */
+do_four_yuvi:
+ push %edi
+
+ lodsl # 4 bytes at a time
+
+ call expand_4_y
+
+ # now do UV values. on even lines, Y is followed by U values; on
+ # odd lines V values follow. The U and V values are always pushed
+ # on the stack in this order:
+ # U V
+
+ # First, calculate offset per line (1.5 * width)
+ mov Width, %ebx # width
+ shl %ebx # 2 *
+ add Width, %ebx # 3 *
+ shr %ebx # 1.5 *
+
+ # even or odd lines
+ testl $1, Height
+ jz 2f
+
+ # odd line; we are at V data, but do U data first
+ neg %ebx # make ebx offset negative
+ mov (%esi,%ebx),%ax # U
+ push %ax
+ lodsw # V
+ push %ax
+ jmp 3f
+
+2: # even line
+ lodsw # U
+ push %ax
+ sub $2, %ebx
+ mov (%esi,%ebx), %ax # V
+ push %ax
+
+3: # Okay, so we now have the U and V values... expand into PixelBuffer
+
+ pop %ebx
+ call expand_4_uv
+
+ pop %edi
+ ret # from do_four_yuvi
+
+
+# Do four pixels, in planar format
+do_four_yuvp:
+ push %edi
+
+ # The first part is the same as for interlaced (4 bytes Y)
+ lodsl # 4 bytes at a time
+ call expand_4_y
+
+ # now gather U and V values...
+ mov Uptr, %ebx # Use Uptr/Vptr
+ mov (%ebx), %ax
+ push %ax
+ add $2, %ebx
+ mov %ebx, Uptr
+
+ mov Vptr, %ebx
+ mov (%ebx), %ax
+ push %ax
+ add $2, %ebx
+ mov %ebx, Vptr
+
+ pop %ebx
+ call expand_4_uv
+
+ pop %edi
+ ret
+
+
+# Do four pixels, in yuyv interlaced format
+do_four_yuyv:
+ push %edi
+
+ lodsl # v0y1u0y0
+ mov %eax, %ebx
+ bswap %ebx # y0u0y1v0
+ mov %bh, %ah # v0y1y1y0
+ and $0x00ff00ff, %ebx # __u0__v0
+ push %ax # y1y0
+
+ lodsl # v1y3u1y2 # mix register instructions
+ mov %eax, %edx # so CPU pipeline doesnt stall
+ rol $16, %eax # u1y2v1y3
+ mov %dl, %dh # v1y3y2y2
+ and $0xff00ff00, %eax # u1__v1__
+ mov $0, %dl # v1y3y2__
+ or %eax, %ebx # u1u0v1v0
+ shl $8, %edx # y3y2____
+ pop %dx # y3y2y1y0
+ mov %edx, %eax
+ call expand_4_y
+ call expand_4_uv
+
+ pop %edi
+ ret
+
+limit_pixels:
+ # Limit all values in PixelBuffer
+ push %esi
+ push %edi
+ push %ecx
+ lea PixelBuffer, %esi
+ mov %esi, %edi
+ mov $16, %ecx
+0: lodsl
+ cmp $0, %eax # this would have been a perfect spot for CMOVxx instructions...
+ jl 2f # except they only work on Pentium Pro processors,
+ cmp $0xff00, %eax # and not even all of them
+ jg 3f
+ add $4, %edi # no use for stosl here
+ loop 0b
+ jmp 9f
+2: mov $0, %eax
+ stosl
+ loop 0b
+ jmp 9f
+3: mov $0xff00, %eax
+ stosl
+ loop 0b
+ jmp 9f
+
+9: pop %ecx
+ pop %edi
+ pop %esi
+ ret # from limit_pixels
+
+/* Copy RGB values from PixelBuffer into destination buffer, 4 bytes
+ with alpha
+ */
+
+/* Push 3 pixel (12 bytes), in correct order */
+push_rgb24:
+ push %ecx
+ push %esi
+ lea PixelBuffer, %esi
+ mov $4, %ecx
+0: lodsl
+ shr $8, %eax
+ mov %al, (%edi) # Red
+ lodsl
+ shr $8, %eax
+ mov %al, 1(%edi) # Green
+ lodsl
+ shr $8, %eax
+ mov %al, 2(%edi) # Blue
+ add $3, %edi
+ lodsl # dummy
+ loop 0b
+ pop %esi
+ pop %ecx
+ ret
+
+/* Push 3 pixels (12 bytes), in wrong order */
+push_bgr24:
+ push %ecx
+ push %esi
+ lea PixelBuffer, %esi
+ mov $4, %ecx
+0: lodsl
+ shr $8, %eax
+ mov %al, 2(%edi) # Red
+ lodsl
+ shr $8, %eax
+ mov %al, 1(%edi) # Green
+ lodsl
+ shr $8, %eax
+ mov %al, (%edi) # Blue
+ add $3, %edi
+ lodsl # dummy
+ loop 0b
+ pop %esi
+ pop %ecx
+ ret
+
+/* The simplest format: push 4 bytes, RGBa */
+push_rgb32:
+ push %ecx
+ push %esi
+ mov $16, %ecx
+ lea PixelBuffer, %esi
+0: lodsl # red
+ shr $8, %eax # 8 bit precision
+ stosb
+ loop 0b
+ pop %esi
+ pop %ecx
+ ret
+
+
+/* Gosh. Would you believe it. They even made this format... (Qt 2.*) */
+push_bgr32:
+ # copy all 4 values to output buffer
+ push %ecx
+ push %esi
+ mov $4, %ecx
+ lea PixelBuffer, %esi
+0: lodsl # red
+ shr $8, %eax # 8 bit precision
+ mov %al, 2(%edi)
+ lodsl # green
+ shr $8, %eax
+ mov %al, 1(%edi)
+ lodsl # blue
+ shr $8, %eax
+ mov %al, (%edi)
+ add $4, %edi
+ lodsl # dummy
+ loop 0b
+ pop %esi
+ pop %ecx
+ ret
+
+/*************************************/
+
+/* Functions to go from YUV interlaced formats to RGB */
+
+/* Go from interlaced to RGB, red first */
+
+ENTRY(ccvt_420i_rgb24)
+ enter $72, $0 # no extra space, no stackframes
+ push %ebx
+ push %esi
+ push %edi
+
+ call test_param_2
+ jc 9f
+
+0: mov Width, %ecx # width
+1: call do_four_yuvi
+ call limit_pixels
+ call push_rgb24
+
+ cmp $0, %ecx
+ jnz 1b # end of line?
+ decl Height # yes; decrement line counter
+ jnz 0b
+
+9: pop %edi
+ pop %esi
+ pop %ebx
+ leave
+ ret
+
+/* Go from interlaced to BGR, blue first */
+
+ENTRY(ccvt_420i_bgr24)
+ enter $72, $0 # no extra space, no stackframes
+ push %ebx
+ push %esi
+ push %edi
+
+ call test_param_2
+ jc 9f
+
+0: mov Width, %ecx # width
+1: call do_four_yuvi
+ call limit_pixels
+ call push_bgr24
+
+ cmp $0, %ecx
+ jnz 1b # end of line?
+ decl Height # yes; decrement line counter
+ jnz 0b
+
+9: pop %edi
+ pop %esi
+ pop %ebx
+ leave
+ ret
+
+
+/* From interlaced to RGBa */
+
+ENTRY(ccvt_420i_rgb32)
+ enter $72, $0 # no extra space, no stackframes
+ push %ebx
+ push %esi
+ push %edi
+
+ call test_param_2
+ jc 9f
+
+0: mov Width, %ecx # width
+1: call do_four_yuvi
+ call limit_pixels
+ call push_rgb32
+
+ cmp $0, %ecx # end of line?
+ jnz 1b
+ decl Height # yes; decrement line counter
+ jnz 0b
+
+9: pop %edi
+ pop %esi
+ pop %ebx
+ leave
+ ret
+
+/* Guess what? Go from interlaced to BGRa */
+
+ENTRY(ccvt_420i_bgr32)
+ enter $72, $0 # no extra space, no stackframes
+ push %ebx
+ push %esi
+ push %edi
+
+ call test_param_2
+ jc 9f
+
+0: mov Width, %ecx # width
+1: call do_four_yuvi
+ call limit_pixels
+ call push_bgr32
+
+ cmp $0, %ecx # end of line?
+ jnz 1b
+ decl Height # yes; decrement line counter
+ jnz 0b
+
+9: pop %edi
+ pop %esi
+ pop %ebx
+ leave
+ ret
+
+
+
+
+/* From YUYV to RGBa */
+
+ENTRY(ccvt_yuyv_rgb32)
+ enter $72, $0 # no extra space, no stackframes
+ push %ebx
+ push %esi
+ push %edi
+
+ call test_param_2
+ jc 9f
+
+0: mov Width, %ecx # width
+1: call do_four_yuyv
+ call limit_pixels
+ call push_rgb32
+
+ cmp $0, %ecx # end of line?
+ jnz 1b
+
+8: decl Height # yes; decrement line counter
+ jnz 0b
+
+9: pop %edi
+ pop %esi
+ pop %ebx
+ leave
+ ret
+
+/* From YUYV to BGRa */
+ENTRY(ccvt_yuyv_bgr32)
+ enter $72, $0 # no extra space, no stackframes
+ push %ebx
+ push %esi
+ push %edi
+
+ call test_param_2
+ jc 9f
+
+ # YUYV -> RGBa RGBa
+
+0: mov Width, %ecx # width
+1: call do_four_yuyv
+ call limit_pixels
+ call push_bgr32
+
+ cmp $0, %ecx # end of line?
+ jnz 1b
+
+8: decl Height # yes; decrement line counter
+ jnz 0b
+
+9: pop %edi
+ pop %esi
+ pop %ebx
+ leave
+ ret
+
+
+
+
+/* Planar to RGBa */
+
+ENTRY(ccvt_420p_rgb32)
+ enter $72, $0
+ push %ebx
+ push %esi
+ push %edi
+
+ call test_param_31
+ jc 9f
+
+ mov Width, %eax # width
+ mull Height # * height
+ mov SrcU, %eax # Copy U/V pointers
+ mov %eax, Uptr
+ mov SrcV, %eax
+ mov %eax, Vptr
+
+0: mov Width, %ecx # width
+1: call do_four_yuvp
+ call limit_pixels
+ call push_rgb32
+
+ cmp $0, %ecx # end of line?
+ jnz 1b
+
+ testl $1, Height # odd/even line
+ jnz 8f
+
+ mov Width, %eax # Even: rewind U/V pointers
+ shr %eax
+ sub %eax, Uptr
+ sub %eax, Vptr
+
+8: decl Height # yes; decrement line counter
+ jnz 0b
+
+9: pop %edi
+ pop %esi
+ pop %ebx
+ leave
+ ret
+
+/* Okay... eventually, you end up with a very complete set of conversion
+ routines. I just wished things were a bit simpler. */
+
+ENTRY(ccvt_420p_bgr32)
+ enter $72, $0
+ push %ebx
+ push %esi
+ push %edi
+
+ call test_param_31
+ jc 9f
+
+ mov Width, %eax # width
+ mull Height # * height
+ mov SrcU, %eax # Copy U/V pointers
+ mov %eax, Uptr
+ mov SrcV, %eax
+ mov %eax, Vptr
+
+0: mov Width, %ecx # width
+1: call do_four_yuvp
+ call limit_pixels
+ call push_bgr32
+
+ cmp $0, %ecx # end of line?
+ jnz 1b
+
+ testl $1, Height # odd/even line
+ jnz 8f
+
+ mov Width, %eax # Even: rewind U/V pointers
+ shr %eax
+ sub %eax, Uptr
+ sub %eax, Vptr
+
+8: decl Height # yes; decrement line counter
+ jnz 0b
+
+9: pop %edi
+ pop %esi
+ pop %ebx
+ leave
+ ret
+
+
+
+
+/* Go from RGB (red first) to 4:2:0 planar.
+ * Note: this requires decimation of the U/V space by 2 in both directions
+ * Also, a matrix multiply would be QUITE convenient...
+
+ This is the matrix:
+ (Y ) ( 77 150 29) (R)
+ (Cb) = (-43 -85 128) * (G)
+ (Cr) (128 -107 -21) (B)
+ */
+
+ENTRY(ccvt_rgb24_420p)
+ enter $96, $0 # 24 bytes extra stack, no stackframes
+ push %ebx # -76: line width in bytes
+ push %esi # -80: height (copy)
+ push %edi # -84: width (copy)
+ # -88: red factor
+ # -92: green factor
+ # -96: blue factor
+ call test_param_13
+ jc 9f
+
+ mov Width, %eax
+ shl %eax
+ add Width, %eax # 3 * width = line increment
+ mov %eax, -76(%ebp)
+
+ mov Height, %eax
+ mov %eax, -80(%ebp) # copy height into stackframe
+
+ /*
+ This is a bit complicated... since U/V decimation is taking
+ place both in horizontal and vertical direction, we have to
+ process 2 lines in parallel. Also, 2 adjacent pixels are
+ considered. We average the U/V values over these 4 pixels
+ (of course, we could have just taken the U/V value of the first
+ pixel and be done with it, but that's not how we do things around
+ here)
+ */
+
+ # 1st pass: Y values. Set factors
+ movl $77 , -88(%ebp) # 0.299
+ movl $150, -92(%ebp) # 0.587
+ movl $29 , -96(%ebp) # 0.114
+
+0: mov Width, %ecx # width
+1: xor %ebx, %ebx # 0
+ call rgb_multiply
+ shr $8, %ebx # divide by 256 (no need for limitor, since 77 + 150 + 29 = 256)
+ mov %bl, %al
+ stosb # store it into Y buffer
+
+ dec %ecx # end of line?
+ jnz 1b
+ decl -80(%ebp) # end of image?
+ jnz 0b
+
+ # Okay, now the U/V pointers...
+ # The following code is passed twice, with different factors
+ # Note that the %esi pointer jumps around quite a bit
+
+ # factors for U
+ movl $-43, -88(%ebp) # -0.1687
+ movl $-85, -92(%ebp) # -0.3313
+ movl $128, -96(%ebp) # 0.5
+ mov DstU, %edi # Set %edi register now
+
+7: mov Src4, %esi # Rewind source pointer
+
+ mov Height, %eax # height
+ shr %eax # / 2
+ mov %eax, -80(%ebp) # copy
+
+2: mov Width, %eax # width
+ shr %eax # / 2
+ mov %eax, -84(%ebp) # copy
+
+3: xor %ebx, %ebx # 0
+ mov $4, %ecx # average over 4 pixels
+
+4: call rgb_multiply
+
+ dec %ecx
+ jz 5f # done?
+ cmp $2, %ecx # 3rd pixel.. move %esi to next line, with offset
+ jne 4b
+ sub $6, %esi # backup to where we started
+ add -76(%ebp), %esi # add line increment
+ jmp 4b
+
+5: # okay, 4 pixels done...
+ sub -76(%ebp), %esi # Get %esi back to its proper place
+
+ add $0x20000, %ebx # add 0.5 factor
+ shr $10, %ebx # Divide by 4 * 256
+ mov %bl, %al
+ stosb # store it!
+
+ decl -84(%ebp) # end of line?
+ jnz 3b
+ add -76(%ebp), %esi # %esi to next line (actually, 2 lines further)
+ decl -80(%ebp) # end of image?
+ jnz 2b
+
+ # check if 3rd pass has been done
+ cmpl $128, -88(%ebp)
+ je 9f # Done!
+ # Set factors for V pass
+ movl $128 , -88(%ebp) # 0.5
+ movl $-107, -92(%ebp) # -0.4187
+ movl $-21 , -96(%ebp) # -0.0813
+ mov DstV, %edi # %edi to V buffer
+ jmp 7b # "Do it to me one more time..."
+
+9: pop %edi
+ pop %esi
+ pop %ebx
+ leave
+ ret
+
+
+
+
+ENTRY(ccvt_bgr24_420p)
+ enter $96, $0 # 24 bytes extra stack, no stackframes
+ push %ebx # -4: line width in bytes
+ push %esi # -8: height (copy)
+ push %edi # -12: width (copy)
+ # -16: red factor
+ # -20: green factor
+ # -24: blue factor
+ call test_param_13
+ jc 9f
+
+ /* No surprise, this code looks just like rgb24_420p, but with swapped factors */
+
+ mov Width, %eax
+ shl %eax
+ add Width, %eax # 3 * width = line increment
+ mov %eax, -76(%ebp)
+
+ mov Height, %eax
+ mov %eax, -80(%ebp) # copy height into stackframe
+
+ # 1st pass: Y values. Set factors
+ movl $29 , -88(%ebp) # 0.114
+ movl $150, -92(%ebp) # 0.587
+ movl $77 , -96(%ebp) # 0.299
+
+0: mov Width, %ecx # width
+1: xor %ebx, %ebx # 0
+ call rgb_multiply
+ shr $8, %ebx # divide by 256 (no need for limitor, since 77 + 150 + 29 = 256)
+ mov %bl, %al
+ stosb # store it into Y buffer
+
+ dec %ecx # end of line?
+ jnz 1b
+ decl -80(%ebp) # end of image?
+ jnz 0b
+
+ # Okay, now the U/V pointers...
+ # The following code is passed twice, with different factors
+ # Note that the %esi pointer jumps around quite a bit
+
+ # factors for U
+ movl $123, -88(%ebp) # 0.5
+ movl $-85, -92(%ebp) # -0.3313
+ movl $-43, -96(%ebp) # -0.1687
+ mov DstU, %edi # Set %edi register now
+
+7: mov Src4, %esi # Rewind source pointer
+
+ mov Height, %eax # height
+ shr %eax # / 2
+ mov %eax, -80(%ebp) # copy
+
+2: mov Width, %eax # width
+ shr %eax # / 2
+ mov %eax, -84(%ebp) # copy
+
+3: xor %ebx, %ebx # 0
+ mov $4, %ecx # average over 4 pixels
+
+4: call rgb_multiply
+
+ dec %ecx
+ jz 5f # done?
+ cmp $2, %ecx # 3rd pixel.. move %esi to next line, with offset
+ jne 4b
+ sub $6, %esi # backup to where we started
+ add -76(%ebp), %esi # add line increment
+ jmp 4b
+
+5: # okay, 4 pixels done...
+ sub -76(%ebp), %esi # Get %esi back to its proper place
+
+ add $0x20000, %ebx # add 0.5 factor
+ shr $10, %ebx # Divide by 4 * 256
+ mov %bl, %al
+ stosb # store it!
+
+ decl -84(%ebp) # end of line?
+ jnz 3b
+ add -76(%ebp), %esi # %esi to next line (actually, 2 lines further)
+ decl -80(%ebp) # end of image?
+ jnz 2b
+
+ # check if 3rd pass has been done
+ cmpl $-21, -88(%ebp)
+ je 9f # Done!
+ # Set factors for V pass
+ movl $-21 , -88(%ebp) # -0.0813
+ movl $-107, -92(%ebp) # -0.4187
+ movl $128 , -96(%ebp) # 0.5
+ mov DstV, %edi # %edi to V buffer
+ jmp 7b # "Do it to me one more time..."
+
+9: pop %edi
+ pop %esi
+ pop %ebx
+ leave
+ ret
+
+
+/* RGB-to-YUV helper functions */
+
+rgb_multiply:
+ # do one RGB vector multiplication; its assumed the RGB factors
+ # are set on the stack. The data is accumulated in ebx.
+ lodsb # red byte
+ and $0xff, %eax
+ mov -88(%ebp), %edx # red factor
+ mul %edx
+ add %eax, %ebx
+ lodsb # green byte
+ and $0xff, %eax
+ mov -92(%ebp), %edx # green factor
+ mul %edx
+ add %eax, %ebx
+ lodsb # blue byte
+ and $0xff, %eax
+ mov -96(%ebp), %edx # blue factor
+ mul %edx
+ add %eax, %ebx # ebx now contains sum
+ ret
+
+
+
+/**************************************************************************/
+
+
+/* Go from 'interlaced' (YYYY UU/VV) format to planar */
+
+ENTRY(ccvt_420i_420p)
+ enter $76, $0 # 4 bytes extra space, no stackframes
+ push %ebx # -4: width / 4
+ push %esi
+ push %edi
+
+ call test_param_13
+ jc 9f
+
+ # Okay, this is fairly easy... we first grab the Y values (4 bytes
+ # at a time), then rewind and do the U values, and repeat for V.
+ # This leaves us with a nice planar format
+
+ mov Width, %eax
+ shr %eax
+ shr %eax # width / 4
+ mov %eax, -76(%ebp) # Store
+
+ # Y
+ mov Height, %edx # line counter
+0: mov -76(%ebp), %ecx
+1: lodsl # get 4 bytes...
+ stosl # ...push 4 bytes
+ add $2, %esi # Skip U or V
+ loop 1b
+ dec %edx
+ jnz 0b
+
+ # U
+ mov Src4, %esi # rewind source pointer
+ mov DstU, %edi
+ add $4, %esi # set to U
+ mov Height, %edx
+ shr %edx # height / 2
+ mov Width, %ebx
+ shl %ebx
+ add Width, %ebx
+ shr %ebx # Width * 1.5 (line offset)
+
+2: mov -76(%ebp), %ecx # width / 4
+3: lodsw # 2 bytes at a time
+ stosw
+ add $4, %esi # skip Y
+ loop 3b
+ add %ebx, %esi # Skip line (U is on even lines)
+ dec %edx
+ jnz 2b
+
+ # V
+ mov Src4, %esi # rewind, set to V in first odd line
+ add $4, %esi
+ add %ebx, %esi # register re-use; no compiler can beat that :)
+ mov DstV, %edi # V ptr
+ mov Height, %edx
+ shr %edx # height / 2
+
+4: mov -76(%ebp), %ecx # Get width/4
+5: lodsw
+ stosw
+ add $4, %esi # Skip Y
+ loop 5b
+ add %ebx, %esi # Skip line (V is on odd lines)
+ dec %edx
+ jnz 4b
+
+ /* That's it! */
+
+9: pop %edi
+ pop %esi
+ pop %ebx
+ leave
+ ret
+
+
+/* Go from 4:2:0 interlaced to 'normal' YUYV */
+
+ENTRY(ccvt_420i_yuyv)
+ enter $80, $0 # 8 bytes extra space, no stackframes
+ push %ebx
+ push %esi
+ push %edi
+
+ call test_param_2
+ jc 9f
+
+ mov Width, %ecx # -4: width / 4 = no. loops per line
+ shr %ecx
+ shr %ecx
+ mov %ecx, -76(%ebp)
+
+ mov Width, %ebx # -8: width * 1.5 = line offset
+ shl %ebx
+ add Width, %ebx
+ shr %ebx
+ mov %ebx, -80(%ebp)
+
+ # Okay, this requires a bit of byte shuffling... we go from
+ # YYYY UU
+ # YYYY VV
+ # to
+ # YUYV YUYV
+ # YUYV YUYV
+ # which indeed takes up more space
+
+ #
+
+0: mov -76(%ebp), %ecx
+
+1: lodsl # 4 Y in eax
+ testl $1, Height # even or odd line?
+ jnz 2f
+
+ # Even
+ mov -80(%ebp), %ebx
+ mov (%ebx, %esi), %dx # 16 bits V
+ shl $16, %edx # store in high word
+ mov (%esi), %dx # 16 bits U
+ add $2, %esi
+ jmp 3f
+
+2: # Odd
+ mov -80(%ebp), %ebx
+ neg %ebx # negative offset
+ mov (%esi), %dx # 16 bits V
+ shl $16, %edx # store in high word
+ mov (%ebx, %esi), %dx # 16 bits U
+ add $2, %esi
+
+3: # eax = Y3Y2Y1Y0, edx = V1V0U1U0, ebx is free
+ push %eax
+
+ movzbl %al, %ebx # ______y0
+ and $0xFF00, %eax # ____y1__
+ shl $8, %eax # __y1____
+ or %ebx, %eax # __y1__y0
+ mov %edx, %ebx # v1v0u1u0
+ shl $8, %ebx # v0u1u0__
+ and $0xff00ff00, %ebx # v0__u0__
+ or %ebx, %eax # v0y1u0y0
+ stosl
+
+ pop %eax # y3y2y1y0
+ # Second half
+ shr $8, %eax # __y3y2y1
+ shr $8, %ax # __y3__y2
+ and $0xff00ff00, %edx # v1__u1__
+ or %edx, %eax # v1y3u1y2
+ stosl
+
+ loop 1b
+
+
+ decl Height # height--
+ jnz 0b
+ # Done
+
+9: pop %edi
+ pop %esi
+ pop %ebx
+ leave
+ ret
#include "dabusb.h"
#include "dabfirmware.h"
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.54"
+#define DRIVER_AUTHOR "Deti Fliegl, deti@fliegl.de"
+#define DRIVER_DESC "DAB-USB Interface Driver for Linux (c)1999"
+
/* --------------------------------------------------------------------- */
#define NRDABUSB 4
return -1;
dbg("dabusb_init: driver registered");
+
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
+
return 0;
}
/* --------------------------------------------------------------------- */
-MODULE_AUTHOR ("Deti Fliegl, deti@fliegl.de");
-MODULE_DESCRIPTION ("DAB-USB Interface Driver for Linux (c)1999");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
MODULE_PARM (buffers, "i");
MODULE_PARM_DESC (buffers, "Number of buffers (default=256)");
* 12 Aug, 2000 .. add some real locking, remove an Oops
* 10 Oct, 2000 .. usb_device_id table created.
* 01 Nov, 2000 .. usb_device_id support added by Adam J. Richter
+ * 08 Apr, 2001 .. Identify version on module load. gb
*
* Thanks to: the folk who've provided USB product IDs, sent in
* patches, and shared their successes!
#include <linux/usb.h>
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "David Brownell, <dbrownell@users.sourceforge.net>"
+#define DRIVER_DESC "USB Camera Driver for Kodak DC-2xx series cameras"
+
/* current USB framework handles max of 16 USB devices per driver */
#define MAX_CAMERAS 16
{
if (usb_register (&camera_driver) < 0)
return -1;
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
return 0;
}
usb_deregister (&camera_driver);
}
-
-MODULE_AUTHOR("David Brownell, <dbrownell@users.sourceforge.net>");
-MODULE_DESCRIPTION("USB Camera Driver for Kodak DC-2xx series cameras");
-
module_init (usb_dc2xx_init);
module_exit (usb_dc2xx_cleanup);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
#include <linux/videodev.h>
#include <linux/usb.h>
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.24"
+#define DRIVER_AUTHOR "Markus Demleitner <msdemlei@tucana.harvard.edu>"
+#define DRIVER_DESC "D-Link DSB-R100 USB radio driver"
+
#define DSB100_VENDOR 0x04b4
#define DSB100_PRODUCT 0x1002
};
static int users = 0;
+static int radio_nr = -1;
static struct usb_device_id usb_dsbr100_table [] = {
{ USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) },
{
usb_dsbr100_radio.priv = NULL;
usb_register(&usb_dsbr100_driver);
- if (video_register_device(&usb_dsbr100_radio,VFL_TYPE_RADIO)==-1) {
+ if (video_register_device(&usb_dsbr100_radio,VFL_TYPE_RADIO,radio_nr)==-1) {
warn("couldn't register video device");
return -EINVAL;
}
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
return 0;
}
module_init (dsbr100_init);
module_exit (dsbr100_exit);
-MODULE_AUTHOR("Markus Demleitner <msdemlei@tucana.harvard.edu>");
-MODULE_DESCRIPTION("D-Link DSB-R100 USB radio driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
/*
vi: ts=8
#define hid_dump_device(c) do { } while (0)
#endif
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.16"
+#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik <vojtech@suse.cz>"
+#define DRIVER_DESC "USB HID support drivers"
+
#define unk KEY_UNKNOWN
static unsigned char hid_keyboard[256] = {
static int __init hid_init(void)
{
usb_register(&hid_driver);
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
return 0;
}
module_init(hid_init);
module_exit(hid_exit);
-MODULE_AUTHOR("Andreas Gal, Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("USB HID support drivers");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
#include "ibmcam.h"
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Johannes Erdfelt, Randy Dunlap"
+#define DRIVER_DESC "IBM/Xirlink C-it USB Camera Driver for Linux (c) 2000"
+
#define ENABLE_HEXDUMP 0 /* Enable if you need it */
static int debug = 0;
+static int video_nr = -1;
+
/* Completion states of the data parser */
typedef enum {
scan_Continue, /* Just parse next item */
MODULE_PARM(init_model2_yb, "i");
MODULE_PARM_DESC(init_model2_yb, "Model2 preconfiguration: 0-255 (default=160)");
-MODULE_AUTHOR ("module author");
-MODULE_DESCRIPTION ("IBM/Xirlink C-it USB Camera Driver for Linux (c) 2000");
-
/* Still mysterious i2c commands */
static const unsigned short unknown_88 = 0x0088;
static const unsigned short unknown_89 = 0x0089;
usb_ibmcam_configure_video(ibmcam);
up (&ibmcam->lock);
- if (video_register_device(&ibmcam->vdev, VFL_TYPE_GRABBER) == -1) {
+ if (video_register_device(&ibmcam->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
printk(KERN_ERR "video_register_device failed\n");
ibmcam = NULL; /* Do not free, it's preallocated */
}
struct usb_ibmcam *ibmcam = &cams[u];
memset (ibmcam, 0, sizeof(struct usb_ibmcam));
}
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
return usb_register(&ibmcam_driver);
}
module_init(usb_ibmcam_init);
module_exit(usb_ibmcam_cleanup);
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
/* --------------------------------------------------------------------- */
+/*
+ * This list of superblocks is still used,
+ * but since usbdevfs became FS_SINGLE
+ * there is only one super_block.
+ */
static LIST_HEAD(superlist);
struct special {
iput(inode);
}
+static int parse_options(struct super_block *s, char *data)
+{
+ uid_t devuid = 0, busuid = 0, listuid = 0;
+ gid_t devgid = 0, busgid = 0, listgid = 0;
+ umode_t devmode = S_IWUSR | S_IRUGO, busmode = S_IXUGO | S_IRUGO, listmode = S_IRUGO;
+ char *curopt = NULL, *value;
+
+ /* parse options */
+ if (data)
+ curopt = strtok(data, ",");
+ for (; curopt; curopt = strtok(NULL, ",")) {
+ if ((value = strchr(curopt, '=')) != NULL)
+ *value++ = 0;
+ if (!strcmp(curopt, "devuid")) {
+ if (!value || !value[0])
+ return -EINVAL;
+ devuid = simple_strtoul(value, &value, 0);
+ if (*value)
+ return -EINVAL;
+ }
+ if (!strcmp(curopt, "devgid")) {
+ if (!value || !value[0])
+ return -EINVAL;
+ devgid = simple_strtoul(value, &value, 0);
+ if (*value)
+ return -EINVAL;
+ }
+ if (!strcmp(curopt, "devmode")) {
+ if (!value || !value[0])
+ return -EINVAL;
+ devmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
+ if (*value)
+ return -EINVAL;
+ }
+ if (!strcmp(curopt, "busuid")) {
+ if (!value || !value[0])
+ return -EINVAL;
+ busuid = simple_strtoul(value, &value, 0);
+ if (*value)
+ return -EINVAL;
+ }
+ if (!strcmp(curopt, "busgid")) {
+ if (!value || !value[0])
+ return -EINVAL;
+ busgid = simple_strtoul(value, &value, 0);
+ if (*value)
+ return -EINVAL;
+ }
+ if (!strcmp(curopt, "busmode")) {
+ if (!value || !value[0])
+ return -EINVAL;
+ busmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
+ if (*value)
+ return -EINVAL;
+ }
+ if (!strcmp(curopt, "listuid")) {
+ if (!value || !value[0])
+ return -EINVAL;
+ listuid = simple_strtoul(value, &value, 0);
+ if (*value)
+ return -EINVAL;
+ }
+ if (!strcmp(curopt, "listgid")) {
+ if (!value || !value[0])
+ return -EINVAL;
+ listgid = simple_strtoul(value, &value, 0);
+ if (*value)
+ return -EINVAL;
+ }
+ if (!strcmp(curopt, "listmode")) {
+ if (!value || !value[0])
+ return -EINVAL;
+ listmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
+ if (*value)
+ return -EINVAL;
+ }
+ }
+
+ s->u.usbdevfs_sb.devuid = devuid;
+ s->u.usbdevfs_sb.devgid = devgid;
+ s->u.usbdevfs_sb.devmode = devmode;
+ s->u.usbdevfs_sb.busuid = busuid;
+ s->u.usbdevfs_sb.busgid = busgid;
+ s->u.usbdevfs_sb.busmode = busmode;
+ s->u.usbdevfs_sb.listuid = listuid;
+ s->u.usbdevfs_sb.listgid = listgid;
+ s->u.usbdevfs_sb.listmode = listmode;
+
+ return 0;
+}
+
static struct usb_bus *usbdevfs_findbus(int busnr)
{
struct list_head *list;
return 0;
}
+static int usbdevfs_remount(struct super_block *s, int *flags, char *data)
+{
+ struct list_head *ilist = s->u.usbdevfs_sb.ilist.next;
+ struct inode *inode;
+ int ret;
+
+ if ((ret = parse_options(s, data))) {
+ printk(KERN_WARNING "usbdevfs: remount parameter error\n");
+ return ret;
+ }
+
+ for (; ilist != &s->u.usbdevfs_sb.ilist; ilist = ilist->next) {
+ inode = list_entry(ilist, struct inode, u.usbdev_i.slist);
+
+ switch (ITYPE(inode->i_ino)) {
+ case ISPECIAL :
+ inode->i_uid = s->u.usbdevfs_sb.listuid;
+ inode->i_gid = s->u.usbdevfs_sb.listgid;
+ inode->i_mode = s->u.usbdevfs_sb.listmode | S_IFREG;
+ break;
+ case IBUS :
+ inode->i_uid = s->u.usbdevfs_sb.busuid;
+ inode->i_gid = s->u.usbdevfs_sb.busgid;
+ inode->i_mode = s->u.usbdevfs_sb.busmode | S_IFDIR;
+ break;
+ case IDEVICE :
+ inode->i_uid = s->u.usbdevfs_sb.devuid;
+ inode->i_gid = s->u.usbdevfs_sb.devgid;
+ inode->i_mode = s->u.usbdevfs_sb.devmode | S_IFREG;
+ break;
+ }
+ }
+
+ return 0;
+}
+
static struct super_operations usbdevfs_sops = {
read_inode: usbdevfs_read_inode,
put_super: usbdevfs_put_super,
statfs: usbdevfs_statfs,
+ remount_fs: usbdevfs_remount,
};
struct super_block *usbdevfs_read_super(struct super_block *s, void *data, int silent)
struct list_head *blist;
struct usb_bus *bus;
unsigned int i;
- uid_t devuid = 0, busuid = 0, listuid = 0;
- gid_t devgid = 0, busgid = 0, listgid = 0;
- umode_t devmode = S_IWUSR | S_IRUGO, busmode = S_IXUGO | S_IRUGO, listmode = S_IRUGO;
- char *curopt = NULL, *value;
- /* parse options */
- if (data)
- curopt = strtok(data, ",");
- for (; curopt; curopt = strtok(NULL, ",")) {
- if ((value = strchr(curopt, '=')) != NULL)
- *value++ = 0;
- if (!strcmp(curopt, "devuid")) {
- if (!value || !value[0])
- goto opterr;
- devuid = simple_strtoul(value, &value, 0);
- if (*value)
- goto opterr;
- }
- if (!strcmp(curopt, "devgid")) {
- if (!value || !value[0])
- goto opterr;
- devgid = simple_strtoul(value, &value, 0);
- if (*value)
- goto opterr;
- }
- if (!strcmp(curopt, "devmode")) {
- if (!value || !value[0])
- goto opterr;
- devmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
- if (*value)
- goto opterr;
- }
- if (!strcmp(curopt, "busuid")) {
- if (!value || !value[0])
- goto opterr;
- busuid = simple_strtoul(value, &value, 0);
- if (*value)
- goto opterr;
- }
- if (!strcmp(curopt, "busgid")) {
- if (!value || !value[0])
- goto opterr;
- busgid = simple_strtoul(value, &value, 0);
- if (*value)
- goto opterr;
- }
- if (!strcmp(curopt, "busmode")) {
- if (!value || !value[0])
- goto opterr;
- busmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
- if (*value)
- goto opterr;
- }
- if (!strcmp(curopt, "listuid")) {
- if (!value || !value[0])
- goto opterr;
- listuid = simple_strtoul(value, &value, 0);
- if (*value)
- goto opterr;
- }
- if (!strcmp(curopt, "listgid")) {
- if (!value || !value[0])
- goto opterr;
- listgid = simple_strtoul(value, &value, 0);
- if (*value)
- goto opterr;
- }
- if (!strcmp(curopt, "listmode")) {
- if (!value || !value[0])
- goto opterr;
- listmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
- if (*value)
- goto opterr;
- }
+ if (parse_options(s, data)) {
+ printk(KERN_WARNING "usbdevfs: mount parameter error\n");
+ return NULL;
}
+
/* fill superblock */
s->s_blocksize = 1024;
s->s_blocksize_bits = 10;
s->s_op = &usbdevfs_sops;
INIT_LIST_HEAD(&s->u.usbdevfs_sb.slist);
INIT_LIST_HEAD(&s->u.usbdevfs_sb.ilist);
- s->u.usbdevfs_sb.devuid = devuid;
- s->u.usbdevfs_sb.devgid = devgid;
- s->u.usbdevfs_sb.devmode = devmode;
- s->u.usbdevfs_sb.busuid = busuid;
- s->u.usbdevfs_sb.busgid = busgid;
- s->u.usbdevfs_sb.busmode = busmode;
root_inode = iget(s, IROOT);
if (!root_inode)
goto out_no_root;
for (i = 0; i < NRSPECIAL; i++) {
if (!(inode = iget(s, IROOT+1+i)))
continue;
- inode->i_uid = listuid;
- inode->i_gid = listgid;
- inode->i_mode = listmode | S_IFREG;
+ inode->i_uid = s->u.usbdevfs_sb.listuid;
+ inode->i_gid = s->u.usbdevfs_sb.listgid;
+ inode->i_mode = s->u.usbdevfs_sb.listmode | S_IFREG;
special[i].inode = inode;
list_add_tail(&inode->u.usbdev_i.slist, &s->u.usbdevfs_sb.ilist);
list_add_tail(&inode->u.usbdev_i.dlist, &special[i].inodes);
printk("usbdevfs_read_super: get root inode failed\n");
iput(root_inode);
return NULL;
-
- opterr:
- printk(KERN_WARNING "usbdevfs: mount parameter error\n");
- return NULL;
}
static DECLARE_FSTYPE(usbdevice_fs_type, "usbdevfs", usbdevfs_read_super, FS_SINGLE);
}
if ((ret = usb_register(&usbdevfs_driver)))
return ret;
- if ((ret = register_filesystem(&usbdevice_fs_type)))
+ if ((ret = register_filesystem(&usbdevice_fs_type))) {
usb_deregister(&usbdevfs_driver);
+ return ret;
+ }
kern_mount(&usbdevice_fs_type);
#ifdef CONFIG_PROC_FS
/* create mount point for usbdevfs */
--- /dev/null
+ /* SQCIF */
+ {
+ /* 5 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ },
+ /* QSIF */
+ {
+ /* 5 fps */
+ {
+ {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+ {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+ {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+ {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+ },
+ /* 10 fps */
+ {
+ {2, 291, 0, {0x1C, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0x01, 0x80}},
+ {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
+ {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
+ {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
+ },
+ /* 15 fps */
+ {
+ {3, 437, 0, {0x1B, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x01, 0x80}},
+ {2, 292, 640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
+ {2, 292, 640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
+ {1, 192, 420, {0x13, 0xF4, 0x30, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
+ },
+ /* 20 fps */
+ {
+ {4, 589, 0, {0x1A, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4D, 0x02, 0x80}},
+ {3, 448, 730, {0x12, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xC0, 0x01, 0x80}},
+ {2, 292, 476, {0x12, 0xF4, 0x30, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0x01, 0x80}},
+ {1, 192, 312, {0x12, 0xF4, 0x50, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
+ },
+ /* 25 fps */
+ {
+ {5, 703, 0, {0x19, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x02, 0x80}},
+ {3, 447, 610, {0x11, 0xF4, 0x30, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x28, 0xBF, 0x01, 0x80}},
+ {2, 292, 398, {0x11, 0xF4, 0x50, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x28, 0x24, 0x01, 0x80}},
+ {1, 193, 262, {0x11, 0xF4, 0x50, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x28, 0xC1, 0x00, 0x80}},
+ },
+ /* 30 fps */
+ {
+ {8, 874, 0, {0x18, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x6A, 0x03, 0x80}},
+ {5, 704, 730, {0x10, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x28, 0xC0, 0x02, 0x80}},
+ {3, 448, 492, {0x10, 0xF4, 0x30, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x28, 0xC0, 0x01, 0x80}},
+ {2, 292, 320, {0x10, 0xF4, 0x50, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x28, 0x24, 0x01, 0x80}},
+ },
+ },
+ /* QCIF */
+ {
+ /* 5 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ },
+ /* SIF */
+ {
+ /* 5 fps */
+ {
+ {4, 582, 0, {0x0D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x02, 0x80}},
+ {3, 387, 1276, {0x05, 0xF4, 0x30, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x01, 0x80}},
+ {2, 291, 960, {0x05, 0xF4, 0x30, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0x01, 0x80}},
+ {1, 191, 630, {0x05, 0xF4, 0x50, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x18, 0xBF, 0x00, 0x80}},
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {6, 775, 1278, {0x04, 0xF4, 0x30, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x03, 0x80}},
+ {3, 447, 736, {0x04, 0xF4, 0x30, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x28, 0xBF, 0x01, 0x80}},
+ {2, 292, 480, {0x04, 0xF4, 0x70, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x28, 0x24, 0x01, 0x80}},
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {9, 955, 1050, {0x03, 0xF4, 0x30, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x03, 0x80}},
+ {4, 592, 650, {0x03, 0xF4, 0x30, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x50, 0x02, 0x80}},
+ {3, 448, 492, {0x03, 0xF4, 0x50, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x38, 0xC0, 0x01, 0x80}},
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {9, 958, 782, {0x02, 0xF4, 0x30, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x03, 0x80}},
+ {5, 703, 574, {0x02, 0xF4, 0x50, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x02, 0x80}},
+ {3, 446, 364, {0x02, 0xF4, 0x90, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x38, 0xBE, 0x01, 0x80}},
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {9, 958, 654, {0x01, 0xF4, 0x30, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x03, 0x80}},
+ {6, 776, 530, {0x01, 0xF4, 0x50, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x03, 0x80}},
+ {4, 592, 404, {0x01, 0xF4, 0x70, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x48, 0x50, 0x02, 0x80}},
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {9, 957, 526, {0x00, 0xF4, 0x50, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x03, 0x80}},
+ {6, 775, 426, {0x00, 0xF4, 0x70, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x03, 0x80}},
+ {4, 590, 324, {0x00, 0x7A, 0x88, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x50, 0x4E, 0x02, 0x80}},
+ },
+ },
+ /* CIF */
+ {
+ /* 5 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ },
+ /* VGA */
+ {
+ /* 5 fps */
+ {
+ {0, },
+ {6, 773, 1272, {0x25, 0xF4, 0x30, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}},
+ {4, 592, 976, {0x25, 0xF4, 0x50, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x02, 0x80}},
+ {3, 448, 738, {0x25, 0xF4, 0x90, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x01, 0x80}},
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {9, 956, 788, {0x24, 0xF4, 0x70, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x03, 0x80}},
+ {6, 776, 640, {0x24, 0xF4, 0xB0, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x03, 0x80}},
+ {4, 592, 488, {0x24, 0x7A, 0xE8, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x02, 0x80}},
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {9, 957, 526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
+ {9, 957, 526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
+ {8, 895, 492, {0x23, 0x7A, 0xE8, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x03, 0x80}},
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ },
* mknod /dev/mustek c 180 32
*
* The driver supports only one camera.
+ *
+ * (08/04/2001) gb
+ * Identify version on module load.
*
* version 0.7.5
* Fixed potential SMP races with Spinlocks.
#include <linux/usb.h>
-#define VERSION "0.7.5"
-#define RELEASE_DATE "(30/10/2000)"
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.7.5 (30/10/2000)"
+#define DRIVER_AUTHOR "Henning Zabel <henning@uni-paderborn.de>"
+#define DRIVER_DESC "USB Driver for Mustek MDC800 Digital Camera"
/* Vendor and Product Information */
#define MDC800_VENDOR_ID 0x055f
if (usb_register (&mdc800_usb_driver) < 0)
goto cleanup_on_fail;
- info ("Mustek Digital Camera Driver " VERSION " (MDC800)");
- info (RELEASE_DATE " Henning Zabel <henning@uni-paderborn.de>");
+ info (DRIVER_VERSION " " DRIVER_AUTHOR);
+ info (DRIVER_DESC);
return 0;
mdc800=0;
}
-
-MODULE_AUTHOR ("Henning Zabel <henning@uni-paderborn.de>");
-MODULE_DESCRIPTION ("USB Driver for Mustek MDC800 Digital Camera");
-
module_init (usb_mdc800_init);
module_exit (usb_mdc800_cleanup);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
* 20010311 Remove all timeouts and tidy up generally (john)
* 20010320 check return value of scsi_register()
* 20010320 Version 0.4.3
+ * 20010408 Identify version on module load.
*/
#include <linux/module.h>
#include "microtek.h"
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.4.3"
+#define DRIVER_AUTHOR "John Fremlin <vii@penguinpowered.com>, Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de>"
+#define DRIVER_DESC "Microtek Scanmaker X6 USB scanner driver"
+
/* Should we do debugging? */
//#define MTS_DO_DEBUG
MTS_DEBUG("driver registered.\n");
}
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
+
return 0;
}
module_init(microtek_drv_init);
module_exit(microtek_drv_exit);
-MODULE_AUTHOR("John Fremlin <vii@penguinpowered.com>, Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de>");
-MODULE_DESCRIPTION("Microtek Scanmaker X6 USB scanner driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
--- /dev/null
+ /* SQCIF */
+ {
+ {0, 0, {0x04, 0x01, 0x03}},
+ {8, 0, {0x05, 0x01, 0x03}},
+ {7, 0, {0x08, 0x01, 0x03}},
+ {7, 0, {0x0A, 0x01, 0x03}},
+ {6, 0, {0x0C, 0x01, 0x03}},
+ {5, 0, {0x0F, 0x01, 0x03}},
+ {4, 0, {0x14, 0x01, 0x03}},
+ {3, 0, {0x18, 0x01, 0x03}},
+ },
+ /* QSIF */
+ {
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ },
+ /* QCIF */
+ {
+ {0, 0, {0x04, 0x01, 0x02}},
+ {8, 0, {0x05, 0x01, 0x02}},
+ {7, 0, {0x08, 0x01, 0x02}},
+ {6, 0, {0x0A, 0x01, 0x02}},
+ {5, 0, {0x0C, 0x01, 0x02}},
+ {4, 0, {0x0F, 0x01, 0x02}},
+ {1, 0, {0x14, 0x01, 0x02}},
+ {1, 0, {0x18, 0x01, 0x02}},
+ },
+ /* SIF */
+ {
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ },
+ /* CIF */
+ {
+ {4, 0, {0x04, 0x01, 0x01}},
+ {7, 1, {0x05, 0x03, 0x01}},
+ {6, 1, {0x08, 0x03, 0x01}},
+ {4, 1, {0x0A, 0x03, 0x01}},
+ {3, 1, {0x0C, 0x03, 0x01}},
+ {2, 1, {0x0F, 0x03, 0x01}},
+ {0},
+ {0},
+ },
+ /* VGA */
+ {
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ },
* 01-nov-2000
* usb_device_id table support added by Adam J. Richter <adam@yggdrasil.com>.
*
+ * 08-apr-2001 gb
+ * Identify version on module load.
+ *
*-------------------------------------------------------------------------*/
#include <linux/config.h>
#endif
#include <linux/usb.h>
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "David Brownell <dbrownell@users.sourceforge.net>"
+#define DRIVER_DESC "NetChip 1080 Driver (USB Host-to-Host Link)"
+
static const struct usb_device_id products [] = {
// reference design
get_random_bytes (node_id, sizeof node_id);
node_id [0] &= 0x7f;
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
+
return 0;
}
module_init (net1080_init);
}
module_exit (net1080_exit);
-MODULE_AUTHOR ("David Brownell <dbrownell@users.sourceforge.net>");
-MODULE_DESCRIPTION ("NetChip 1080 Driver (USB Host-to-Host Link)");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-static const char version[] = "1.28";
-
#define __NO_VERSION__
#include <linux/config.h>
#include "ov511.h"
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.28"
+#define DRIVER_AUTHOR "Mark McClelland <mwm@i.am> & Bret Wallach & Orion Sky Lawlor <olawlor@acm.org> & Kevin Moore & Charl P. Botha <cpbotha@ieee.org> & Claudio Matsuoka <claudio@conectiva.com>"
+#define DRIVER_DESC "OV511 USB Camera Driver"
+
#define OV511_I2C_RETRIES 3
/* Video Size 640 x 480 x 3 bytes for RGB */
/* PARAMETER VARIABLES: */
static int autoadjust = 1; /* CCD dynamically changes exposure, etc... */
+static int video_nr = -1;
+
/* 0=no debug messages
* 1=init/detection/unload and other significant messages,
* 2=some warning messages
MODULE_PARM(dumppix, "i");
MODULE_PARM_DESC(dumppix, "Dump raw pixel data, in one of 3 formats. See ov511_dumppix() for details");
-MODULE_AUTHOR("Mark McClelland <mwm@i.am> & Bret Wallach & Orion Sky Lawlor <olawlor@acm.org> & Kevin Moore & Charl P. Botha <cpbotha@ieee.org> & Claudio Matsuoka <claudio@conectiva.com>");
-MODULE_DESCRIPTION("OV511 USB Camera Driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
static struct usb_driver ov511_driver;
init_waitqueue_head(&ov511->wq);
- if (video_register_device(&ov511->vdev, VFL_TYPE_GRABBER) < 0) {
+ if (video_register_device(&ov511->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
err("video_register_device failed");
return -EBUSY;
}
if (usb_register(&ov511_driver) < 0)
return -1;
- info("ov511 driver version %s registered", version);
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
return 0;
}
#include <linux/module.h>
#include "pegasus.h"
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.4.18 2001/03/18 (C) 1999-2000"
+#define DRIVER_AUTHOR "Petko Manolov <petkan@dce.bg>"
+#define DRIVER_DESC "ADMtek AN986 Pegasus USB Ethernet driver"
#define PEGASUS_USE_INTR
#define PEGASUS_WRITE_EEPROM
-static const char *version = __FILE__ ": v0.4.18 2001/03/18 (C) 1999-2000 Petko Manolov (petkan@dce.bg)";
-
-
static int loopback = 0;
static int mii_mode = 0;
static int multicast_filter_limit = 32;
};
-MODULE_AUTHOR("Petko Manolov <petkan@dce.bg>");
-MODULE_DESCRIPTION("ADMtek AN986 Pegasus USB Ethernet driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_PARM(loopback, "i");
MODULE_PARM(mii_mode, "i");
MODULE_PARM_DESC(loopback, "Enable MAC loopback mode (bit 0)");
int __init pegasus_init(void)
{
- info( "%s", version );
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
return usb_register( &pegasus_driver );
}
__u32 private; /* LSB is gpio reset value */
};
-
+#define VENDOR_3COM 0x0506
#define VENDOR_ACCTON 0x083a
#define VENDOR_ADMTEK 0x07a6
#define VENDOR_BILLIONTON 0x08dd
#define VENDOR_LANEED 0x056e
#define VENDOR_LINKSYS 0x066b
#define VENDOR_MELCO 0x0411
+#define VENDOR_SMARTBRIDGES 0x08d1
#define VENDOR_SMC 0x0707
#define VENDOR_SOHOWARE 0x15e8
-
#else /* PEGASUS_DEV */
-
+PEGASUS_DEV( "3Com USB Ethernet 3C460B", VENDOR_3COM, 0x4601,
+ DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "Accton USB 10/100 Ethernet Adapter", VENDOR_ACCTON, 0x1046,
DEFAULT_GPIO_RESET )
PEGASUS_DEV( "ADMtek ADM8511 \"Pegasus II\" USB Ethernet",
DEFAULT_GPIO_RESET )
PEGASUS_DEV( "D-Link DU-E100", VENDOR_DLINK2, 0x4002,
DEFAULT_GPIO_RESET )
+PEGASUS_DEV( "FiberLine USB", VENDOR_DLINK2, 0x4102,
+ DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "IO DATA USB ET/TX", VENDOR_IODATA, 0x0904,
DEFAULT_GPIO_RESET )
PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x4002,
LINKSYS_GPIO_RESET )
PEGASUS_DEV( "MELCO/BUFFALO LUA-TX", VENDOR_MELCO, 0x0001,
DEFAULT_GPIO_RESET )
+PEGASUS_DEV( "smartNIC 2 PnP Adapter", VENDOR_SMARTBRIDGES, 0x0003,
+ DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "SMC 202 USB Ethernet", VENDOR_SMC, 0x0200,
DEFAULT_GPIO_RESET )
PEGASUS_DEV( "SOHOware NUB100 Ethernet", VENDOR_SOHOWARE, 0x9100,
DEFAULT_GPIO_RESET )
-
#endif /* PEGASUS_DEV */
#define dev_kfree_skb_any dev_kfree_skb
#endif
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.5.7"
+#define DRIVER_AUTHOR "Deti Fliegl, deti@fliegl.de"
+#define DRIVER_DESC "PL-2302 USB Interface Driver for Linux (c)2000"
+
/* Definitions formerly in plusb.h relocated. No need to export them -EZA */
#define _PLUSB_INTPIPE 0x1
dbg("plusb_init: driver registered");
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
+
return 0;
}
/* --------------------------------------------------------------------- */
-MODULE_AUTHOR ("Deti Fliegl, deti@fliegl.de");
-MODULE_DESCRIPTION ("PL-2302 USB Interface Driver for Linux (c)2000");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
module_init (plusb_init);
#undef DEBUG
#include <linux/usb.h>
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.8"
+#define DRIVER_AUTHOR "Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap"
+#define DRIVER_DESC "USB Printer Device Class driver"
+
#define USBLP_BUF_SIZE 8192
#define DEVICE_ID_SIZE 1024
{
if (usb_register(&usblp_driver))
return -1;
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
return 0;
}
module_init(usblp_init);
module_exit(usblp_exit);
-MODULE_AUTHOR("Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap");
-MODULE_DESCRIPTION("USB Printer Device Class driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
--- /dev/null
+/* Driver for Philips webcam
+ Functions that send various control messages to the webcam, including
+ video modes.
+ (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+/* Control functions for the cam; brightness, contrast, video mode, etc. */
+
+#ifdef __KERNEL__
+#include <asm/uaccess.h>
+#endif
+#include <asm/errno.h>
+
+#include "pwc.h"
+#include "pwc-ioctl.h"
+#include "pwc-uncompress.h"
+
+/* Request types: video */
+#define SET_LUM_CTL 0x01
+#define GET_LUM_CTL 0x02
+#define SET_CHROM_CTL 0x03
+#define GET_CHROM_CTL 0x04
+#define SET_STATUS_CTL 0x05
+#define GET_STATUS_CTL 0x06
+#define SET_EP_STREAM_CTL 0x07
+#define GET_EP_STREAM_CTL 0x08
+
+/* Selectors for the Luminance controls [GS]ET_LUM_CTL */
+#define AGC_MODE_FORMATTER 0x2000
+#define PRESET_AGC_FORMATTER 0x2100
+#define SHUTTER_MODE_FORMATTER 0x2200
+#define PRESET_SHUTTER_FORMATTER 0x2300
+#define PRESET_CONTOUR_FORMATTER 0x2400
+#define AUTO_CONTOUR_FORMATTER 0x2500
+#define BACK_LIGHT_COMPENSATION_FORMATTER 0x2600
+#define CONTRAST_FORMATTER 0x2700
+#define DYNAMIC_NOISE_CONTROL_FORMATTER 0x2800
+#define FLICKERLESS_MODE_FORMATTER 0x2900
+#define AE_CONTROL_SPEED 0x2A00
+#define BRIGHTNESS_FORMATTER 0x2B00
+#define GAMMA_FORMATTER 0x2C00
+
+/* Selectors for the Chrominance controls [GS]ET_CHROM_CTL */
+#define WB_MODE_FORMATTER 0x1000
+#define AWB_CONTROL_SPEED_FORMATTER 0x1100
+#define AWB_CONTROL_DELAY_FORMATTER 0x1200
+#define PRESET_MANUAL_RED_GAIN_FORMATTER 0x1300
+#define PRESET_MANUAL_BLUE_GAIN_FORMATTER 0x1400
+#define COLOUR_MODE_FORMATTER 0x1500
+#define SATURATION_MODE_FORMATTER1 0x1600
+#define SATURATION_MODE_FORMATTER2 0x1700
+
+/* Selectors for the Status controls [GS]ET_STATUS_CTL */
+#define SAVE_USER_DEFAULTS_FORMATTER 0x0200
+#define RESTORE_USER_DEFAULTS_FORMATTER 0x0300
+#define RESTORE_FACTORY_DEFAULTS_FORMATTER 0x0400
+#define READ_AGC_FORMATTER 0x0500
+#define READ_SHUTTER_FORMATTER 0x0600
+#define READ_RED_GAIN_FORMATTER 0x0700
+#define READ_BLUE_GAIN_FORMATTER 0x0800
+#define READ_RAW_Y_MEAN_FORMATTER 0x3100
+#define SET_POWER_SAVE_MODE_FORMATTER 0x3200
+#define MIRROR_IMAGE_FORMATTER 0x3300
+#define LED_FORMATTER 0x3400
+
+/* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */
+#define VIDEO_OUTPUT_CONTROL_FORMATTER 0x0100
+
+static char *size2name[PSZ_MAX] =
+{
+ "subQCIF",
+ "QSIF",
+ "QCIF",
+ "SIF",
+ "CIF",
+ "VGA",
+};
+
+/********/
+
+/* Entries for the Nala (645/646) camera; the Nala doesn't have compression
+ preferences, so you either get compressed or non-compressed streams.
+
+ An alternate value of 0 means this mode is not available at all.
+ */
+
+struct Nala_table_entry {
+ char alternate; /* USB alternate setting */
+ int compressed; /* Compressed yes/no */
+
+ unsigned char mode[3]; /* precomputed mode table */
+};
+
+static struct Nala_table_entry Nala_table[PSZ_MAX][8] =
+{
+#include "nala.inc"
+};
+
+/* This tables contains entries for the 675/680/690 (Timon) camera, with
+ 4 different qualities (no compression, low, medium, high).
+ It lists the bandwidth requirements for said mode by its alternate interface
+ number. An alternate of 0 means that the mode is unavailable.
+
+ There are 6 * 4 * 4 entries:
+ 6 different resolutions subqcif, qsif, qcif, sif, cif, vga
+ 6 framerates: 5, 10, 15, 20, 25, 30
+ 4 compression modi: none, low, medium, high
+
+ When an uncompressed mode is not available, the next available compressed mode
+ will be choosen (unless the decompressor is absent). Sometimes there are only
+ 1 or 2 compressed modes available; in that case entries are duplicated.
+*/
+struct Timon_table_entry
+{
+ char alternate; /* USB alternate interface */
+ unsigned short packetsize; /* Normal packet size */
+ unsigned short bandlength; /* Bandlength when decompressing */
+ unsigned char mode[13]; /* precomputed mode settings for cam */
+};
+
+static struct Timon_table_entry Timon_table[PSZ_MAX][6][4] =
+{
+#include "timon.inc"
+};
+
+/* Entries for the Kiara (730/740) camera */
+
+struct Kiara_table_entry
+{
+ char alternate; /* USB alternate interface */
+ unsigned short packetsize; /* Normal packet size */
+ unsigned short bandlength; /* Bandlength when decompressing */
+ unsigned char mode[12]; /* precomputed mode settings for cam */
+};
+
+static struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] =
+{
+#include "kiara.inc"
+};
+
+
+/****************************************************************************/
+
+
+
+
+#if PWC_DEBUG
+void pwc_hexdump(void *p, int len)
+{
+ int i;
+ unsigned char *s;
+ char buf[100], *d;
+
+ s = (unsigned char *)p;
+ d = buf;
+ *d = '\0';
+ Debug("Doing hexdump @ %p, %d bytes.\n", p, len);
+ for (i = 0; i < len; i++) {
+ d += sprintf(d, "%02X ", *s++);
+ if ((i & 0xF) == 0xF) {
+ Debug("%s\n", buf);
+ d = buf;
+ *d = '\0';
+ }
+ }
+ if ((i & 0xF) != 0)
+ Debug("%s\n", buf);
+}
+#endif
+
+static inline int send_video_command(struct usb_device *udev, int index, void *buf, int buflen)
+{
+#ifdef __KERNEL__
+ return usb_control_msg(udev,
+ usb_sndctrlpipe(udev, 0),
+ SET_EP_STREAM_CTL,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ VIDEO_OUTPUT_CONTROL_FORMATTER,
+ index,
+ buf, buflen, HZ);
+#else
+ return 0;
+#endif
+}
+
+
+
+static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
+{
+ unsigned char buf[3];
+ int ret, fps;
+ struct Nala_table_entry *pEntry;
+ int frames2frames[31] =
+ { /* closest match of framerate */
+ 0, 0, 0, 0, 4, /* 0-4 */
+ 5, 5, 7, 7, 10, /* 5-9 */
+ 10, 10, 12, 12, 15, /* 10-14 */
+ 15, 15, 15, 20, 20, /* 15-19 */
+ 20, 20, 20, 24, 24, /* 20-24 */
+ 24, 24, 24, 24, 24, /* 25-29 */
+ 24 /* 30 */
+ };
+ int frames2table[31] =
+ { 0, 0, 0, 0, 0, /* 0-4 */
+ 1, 1, 1, 2, 2, /* 5-9 */
+ 3, 3, 4, 4, 4, /* 10-14 */
+ 5, 5, 5, 5, 5, /* 15-19 */
+ 6, 6, 6, 6, 7, /* 20-24 */
+ 7, 7, 7, 7, 7, /* 25-29 */
+ 7 /* 30 */
+ };
+
+ if (size < 0 || size > PSZ_CIF || frames < 4 || frames > 25)
+ return -EINVAL;
+ frames = frames2frames[frames];
+ fps = frames2table[frames];
+ pEntry = &Nala_table[size][fps];
+ if (pEntry->alternate == 0)
+ return -EINVAL;
+
+ if (pEntry->compressed && pdev->decompressor == NULL)
+ return -ENOENT; /* Not supported. */
+
+ memcpy(buf, pEntry->mode, 3);
+ ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3);
+ if (ret < 0)
+ return ret;
+ if (pEntry->compressed)
+ ret = pdev->decompressor->init(pdev->release, buf, &pdev->decompress_data);
+ if (ret < 0)
+ return ret;
+
+ /* Set various parameters */
+ pdev->vframes = frames;
+ pdev->vsize = size;
+ pdev->valternate = pEntry->alternate;
+ pdev->image = pwc_image_sizes[size];
+ pdev->frame_size = (pdev->image.x * pdev->image.y * 3) / 2;
+ if (pEntry->compressed) {
+ if (pdev->release < 5) { /* 4 fold compression */
+ pdev->vbandlength = 528;
+ pdev->frame_size /= 4;
+ }
+ else {
+ pdev->vbandlength = 704;
+ pdev->frame_size /= 3;
+ }
+ }
+ else
+ pdev->vbandlength = 0;
+ return 0;
+}
+
+
+static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
+{
+ unsigned char buf[13];
+ struct Timon_table_entry *pChoose;
+ int ret, fps;
+
+ if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3)
+ return -EINVAL;
+ if (size == PSZ_VGA && frames > 15)
+ return -EINVAL;
+ fps = (frames / 5) - 1;
+
+ /* Find a supported framerate with progressively higher compression ratios
+ if the preferred ratio is not available.
+ */
+ pChoose = NULL;
+ if (pdev->decompressor == NULL) {
+#if PWC_DEBUG
+ Debug("Trying to find uncompressed mode.\n");
+#endif
+ pChoose = &Timon_table[size][fps][0];
+ }
+ else {
+ while (compression <= 3) {
+ pChoose = &Timon_table[size][fps][compression];
+ if (pChoose->alternate != 0)
+ break;
+ compression++;
+ }
+ }
+ if (pChoose == NULL || pChoose->alternate == 0)
+ return -ENOENT; /* Not supported. */
+
+ memcpy(buf, pChoose->mode, 13);
+ if (snapshot)
+ buf[0] |= 0x80;
+ ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 13);
+ if (ret < 0)
+ return ret;
+
+ if (pChoose->bandlength > 0)
+ ret = pdev->decompressor->init(pdev->release, buf, &pdev->decompress_data);
+ if (ret < 0)
+ return ret;
+
+ /* Set various parameters */
+ pdev->vframes = frames;
+ pdev->vsize = size;
+ pdev->vsnapshot = snapshot;
+ pdev->valternate = pChoose->alternate;
+ pdev->image = pwc_image_sizes[size];
+ pdev->vbandlength = pChoose->bandlength;
+ if (pChoose->bandlength > 0)
+ pdev->frame_size = (pChoose->bandlength * pdev->image.y) / 4;
+ else
+ pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
+ return 0;
+}
+
+
+static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
+{
+ struct Kiara_table_entry *pChoose;
+ int fps, ret;
+ unsigned char buf[12];
+
+ if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3)
+ return -EINVAL;
+ if (size == PSZ_VGA && frames > 15)
+ return -EINVAL;
+ fps = (frames / 5) - 1;
+
+ /* Find a supported framerate with progressively higher compression ratios
+ if the preferred ratio is not available.
+ */
+ pChoose = NULL;
+ if (pdev->decompressor == NULL) {
+#if PWC_DEBUG
+ Debug("Trying to find uncompressed mode.\n");
+#endif
+ pChoose = &Kiara_table[size][fps][0];
+ }
+ else {
+ while (compression <= 3) {
+ pChoose = &Kiara_table[size][fps][compression];
+ if (pChoose->alternate != 0)
+ break;
+ compression++;
+ }
+ }
+ if (pChoose == NULL || pChoose->alternate == 0)
+ return -ENOENT; /* Not supported. */
+
+ /* usb_control_msg won't take staticly allocated arrays as argument?? */
+ memcpy(buf, pChoose->mode, 12);
+ if (snapshot)
+ buf[0] |= 0x80;
+
+ /* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */
+ ret = send_video_command(pdev->udev, 4 /* pdev->vendpoint */, buf, 12);
+ if (ret < 0)
+ return ret;
+
+ if (pChoose->bandlength > 0)
+ ret = pdev->decompressor->init(pdev->release, buf, &pdev->decompress_data);
+ if (ret < 0)
+ return ret;
+
+ /* All set and go */
+ pdev->vframes = frames;
+ pdev->vsize = size;
+ pdev->vsnapshot = snapshot;
+ pdev->valternate = pChoose->alternate;
+ pdev->image = pwc_image_sizes[size];
+ pdev->vbandlength = pChoose->bandlength;
+ if (pChoose->bandlength > 0)
+ pdev->frame_size = (pChoose->bandlength * pdev->image.y) / 4;
+ else
+ pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
+ pdev->frame_size += (pdev->frame_header_size + pdev->frame_trailer_size);
+ return 0;
+}
+
+
+/**
+ @pdev: device structure
+ @width: viewport width
+ @height: viewport height
+ @frame: framerate, in fps
+ @compression: preferred compression ratio
+ @snapshot: snapshot mode or streaming
+ */
+int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot)
+{
+ int ret, size;
+
+ size = pwc_decode_size(pdev, width, height);
+ if (size < 0) {
+ Debug("Could not find suitable size.\n");
+ return -ERANGE;
+ }
+ ret = -EINVAL;
+ switch(pdev->type) {
+ case 645:
+ case 646:
+ ret = set_video_mode_Nala(pdev, size, frames);
+ break;
+
+ case 675:
+ case 680:
+ case 690:
+ ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot);
+ break;
+
+ case 730:
+ case 740:
+ ret = set_video_mode_Kiara(pdev, size, frames, compression, snapshot);
+ break;
+ }
+ if (ret < 0) {
+ if (ret == -ENOENT)
+ Info("Video mode %s@%d fps is only supported with the decompressor module (pwcx).\n", size2name[size], frames);
+ else {
+ Err("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
+ return ret;
+ }
+ }
+ /* If the video mode was not supported, we still adjust the view size,
+ since xawtv (Again! Stupid program...) doesn't care zit about
+ return values.
+ */
+ pdev->view.x = width;
+ pdev->view.y = height;
+ pwc_set_image_buffer_size(pdev);
+ Trace(TRACE_SIZE, "Set viewport to %dx%d, image size is %dx%d. Palette = %d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y, pdev->vpalette);
+ return 0;
+}
+
+
+void pwc_set_image_buffer_size(struct pwc_device *pdev)
+{
+ int factor, i, filler = 0;
+
+ switch(pdev->vpalette) {
+ case VIDEO_PALETTE_RGB32 | 0x80:
+ case VIDEO_PALETTE_RGB32:
+ factor = 16;
+ filler = 0;
+ break;
+ case VIDEO_PALETTE_RGB24 | 0x80:
+ case VIDEO_PALETTE_RGB24:
+ factor = 12;
+ filler = 0;
+ break;
+ case VIDEO_PALETTE_YUYV:
+ case VIDEO_PALETTE_YUV422:
+ factor = 8;
+ filler = 128;
+ break;
+ case VIDEO_PALETTE_YUV420:
+ case VIDEO_PALETTE_YUV420P:
+ factor = 6;
+ filler = 128;
+ break;
+#if PWC_DEBUG
+ case VIDEO_PALETTE_RAW:
+ pdev->image.size = pdev->frame_size;
+ pdev->view.size = pdev->frame_size;
+ return;
+ break;
+#endif
+ default:
+ factor = 0;
+ break;
+ }
+
+ /* Set sizes in bytes */
+ pdev->image.size = pdev->image.x * pdev->image.y * factor / 4;
+ pdev->view.size = pdev->view.x * pdev->view.y * factor / 4;
+
+ pdev->offset.x = (pdev->view.x - pdev->image.x) / 2;
+ pdev->offset.y = (pdev->view.y - pdev->image.y) / 2;
+ if (pdev->vpalette == VIDEO_PALETTE_YUV420 || pdev->vpalette == VIDEO_PALETTE_YUV420P) {
+ /* Align offset, or you'll get some very weird results in
+ YUV mode... x must be multiple of 4 (to get the Y's in
+ place), and y even (or you'll mixup U & V).
+ */
+ pdev->offset.x &= 0xFFFC;
+ pdev->offset.y &= 0xFFFE;
+ /* This is the offset in the Y area, hence no factor */
+ pdev->offset.size = (pdev->offset.y * pdev->view.x + pdev->offset.x);
+ }
+ else
+ pdev->offset.size = (pdev->offset.y * pdev->view.x + pdev->offset.x) * factor / 4;
+
+ /* Set buffers to gray */
+ for (i = 0; i < MAX_IMAGES; i++) {
+ if (pdev->image_ptr[i] != NULL)
+ memset(pdev->image_ptr[i], filler, pdev->view.size);
+ }
+}
+
+
+#ifdef __KERNEL__
+/* BRIGHTNESS */
+
+int pwc_get_brightness(struct pwc_device *pdev)
+{
+ char buf;
+ int ret;
+
+ ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+ GET_LUM_CTL,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ BRIGHTNESS_FORMATTER,
+ pdev->vcinterface,
+ &buf, 1, HZ / 2);
+ if (ret < 0)
+ return ret;
+ return buf << 9;
+}
+
+int pwc_set_brightness(struct pwc_device *pdev, int value)
+{
+ char buf;
+
+ if (value < 0)
+ value = 0;
+ if (value > 0xffff)
+ value = 0xffff;
+ buf = (value >> 9) & 0x7f;
+ return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+ SET_LUM_CTL,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ BRIGHTNESS_FORMATTER,
+ pdev->vcinterface,
+ &buf, 1, HZ / 2);
+}
+
+/* CONTRAST */
+
+int pwc_get_contrast(struct pwc_device *pdev)
+{
+ char buf;
+ int ret;
+
+ ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+ GET_LUM_CTL,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ CONTRAST_FORMATTER,
+ pdev->vcinterface,
+ &buf, 1, HZ / 2);
+ if (ret < 0)
+ return ret;
+ return buf << 10;
+}
+
+int pwc_set_contrast(struct pwc_device *pdev, int value)
+{
+ char buf;
+
+ if (value < 0)
+ value = 0;
+ if (value > 0xffff)
+ value = 0xffff;
+ buf = (value >> 10) & 0x3f;
+ return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+ SET_LUM_CTL,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ CONTRAST_FORMATTER,
+ pdev->vcinterface,
+ &buf, 1, HZ / 2);
+}
+
+/* GAMMA */
+
+int pwc_get_gamma(struct pwc_device *pdev)
+{
+ char buf;
+ int ret;
+
+ ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+ GET_LUM_CTL,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ GAMMA_FORMATTER,
+ pdev->vcinterface,
+ &buf, 1, HZ / 2);
+ if (ret < 0)
+ return ret;
+ return buf << 11;
+}
+
+int pwc_set_gamma(struct pwc_device *pdev, int value)
+{
+ char buf;
+
+ if (value < 0)
+ value = 0;
+ if (value > 0xffff)
+ value = 0xffff;
+ buf = (value >> 11) & 0x1f;
+ return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+ SET_LUM_CTL,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ GAMMA_FORMATTER,
+ pdev->vcinterface,
+ &buf, 1, HZ / 2);
+}
+
+
+/* SATURATION */
+
+int pwc_get_saturation(struct pwc_device *pdev)
+{
+ char buf;
+ int ret;
+
+ if (pdev->type < 730)
+ return -1;
+ ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+ GET_CHROM_CTL,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ SATURATION_MODE_FORMATTER1,
+ pdev->vcinterface,
+ &buf, 1, HZ / 2);
+ if (ret < 0)
+ return ret;
+ return 32768 + buf * 327;
+}
+
+int pwc_set_saturation(struct pwc_device *pdev, int value)
+{
+ char buf;
+
+ if (pdev->type < 730)
+ return -EINVAL;
+ if (value < 0)
+ value = 0;
+ if (value > 0xffff)
+ value = 0xffff;
+ /* saturation ranges from -100 to +100 */
+ buf = (value - 32768) / 327;
+ return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+ SET_CHROM_CTL,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ SATURATION_MODE_FORMATTER1,
+ pdev->vcinterface,
+ &buf, 1, HZ / 2);
+}
+
+/* AGC */
+
+static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
+{
+ char buf;
+ int ret;
+
+ if (mode)
+ buf = 0x0; /* auto */
+ else
+ buf = 0xff; /* fixed */
+
+ ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+ SET_LUM_CTL,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ AGC_MODE_FORMATTER,
+ pdev->vcinterface,
+ &buf, 1, HZ / 2);
+
+ if (!mode && ret >= 0) {
+ if (value < 0)
+ value = 0;
+ if (value > 0xffff)
+ value = 0xffff;
+ buf = (value >> 10) & 0x3F;
+ ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+ SET_LUM_CTL,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ PRESET_AGC_FORMATTER,
+ pdev->vcinterface,
+ &buf, 1, HZ / 2);
+ }
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
+static inline int pwc_get_agc(struct pwc_device *pdev, int *value)
+{
+ unsigned char buf;
+ int ret;
+
+ ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+ GET_LUM_CTL,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ AGC_MODE_FORMATTER,
+ pdev->vcinterface,
+ &buf, 1, HZ / 2);
+ if (ret < 0)
+ return ret;
+
+ if (buf != 0) { /* fixed */
+ ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+ GET_LUM_CTL,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ PRESET_AGC_FORMATTER,
+ pdev->vcinterface,
+ &buf, 1, HZ / 2);
+ if (ret < 0)
+ return ret;
+ if (buf > 0x3F)
+ buf = 0x3F;
+ *value = (buf << 10);
+ }
+ else { /* auto */
+ ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+ GET_STATUS_CTL,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ READ_AGC_FORMATTER,
+ pdev->vcinterface,
+ &buf, 1, HZ / 2);
+ if (ret < 0)
+ return ret;
+ /* Gah... this value ranges from 0x00 ... 0x9F */
+ if (buf > 0x9F)
+ buf = 0x9F;
+ *value = -(48 + buf * 409);
+ }
+
+ return 0;
+}
+
+static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value)
+{
+ char buf[2];
+ int speed, ret;
+
+
+ if (mode)
+ buf[0] = 0x0; /* auto */
+ else
+ buf[0] = 0xff; /* fixed */
+
+ ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+ SET_LUM_CTL,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ SHUTTER_MODE_FORMATTER,
+ pdev->vcinterface,
+ buf, 1, HZ / 2);
+
+ if (!mode && ret >= 0) {
+ if (value < 0)
+ value = 0;
+ if (value > 0xffff)
+ value = 0xffff;
+ switch(pdev->type) {
+ case 675:
+ case 680:
+ case 690:
+ /* speed ranges from 0x0 to 0x290 (656) */
+ speed = (value / 100);
+ buf[1] = speed >> 8;
+ buf[0] = speed & 0xff;
+ break;
+ case 730:
+ case 740:
+ /* speed seems to range from 0x0 to 0xff */
+ buf[1] = 0;
+ buf[0] = value >> 8;
+ break;
+ }
+
+ ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+ SET_LUM_CTL,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ PRESET_SHUTTER_FORMATTER,
+ pdev->vcinterface,
+ &buf, 2, HZ / 2);
+ }
+ return ret;
+}
+
+
+/* POWER */
+
+int pwc_camera_power(struct pwc_device *pdev, int power)
+{
+ char buf;
+
+ if (pdev->type < 675 || pdev->release < 6)
+ return 0; /* Not supported by Nala or Timon < release 6 */
+
+ if (power)
+ buf = 0x00; /* active */
+ else
+ buf = 0xFF; /* power save */
+ return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+ SET_STATUS_CTL,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ SET_POWER_SAVE_MODE_FORMATTER,
+ pdev->vcinterface,
+ &buf, 1, HZ / 2);
+}
+
+
+
+/* private calls */
+
+static inline int pwc_restore_user(struct pwc_device *pdev)
+{
+ return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+ SET_STATUS_CTL,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ RESTORE_USER_DEFAULTS_FORMATTER,
+ pdev->vcinterface,
+ NULL, 0, HZ / 2);
+}
+
+static inline int pwc_save_user(struct pwc_device *pdev)
+{
+ return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+ SET_STATUS_CTL,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ SAVE_USER_DEFAULTS_FORMATTER,
+ pdev->vcinterface,
+ NULL, 0, HZ / 2);
+}
+
+static inline int pwc_restore_factory(struct pwc_device *pdev)
+{
+ return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+ SET_STATUS_CTL,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ RESTORE_FACTORY_DEFAULTS_FORMATTER,
+ pdev->vcinterface,
+ NULL, 0, HZ / 2);
+}
+
+int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
+{
+ switch(cmd) {
+ case VIDIOCPWCRUSER:
+ {
+ if (pwc_restore_user(pdev))
+ return -EINVAL;
+ break;
+ }
+
+ case VIDIOCPWCSUSER:
+ {
+ if (pwc_save_user(pdev))
+ return -EINVAL;
+ break;
+ }
+
+ case VIDIOCPWCFACTORY:
+ {
+ if (pwc_restore_factory(pdev))
+ return -EINVAL;
+ break;
+ }
+
+ case VIDIOCPWCSCQUAL:
+ {
+ int qual, ret;
+
+ if (copy_from_user(&qual, arg, sizeof(int)))
+ return -EFAULT;
+
+ if (qual < 0 || qual > 3)
+ return -EINVAL;
+ ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, qual, pdev->vsnapshot);
+ if (ret < 0)
+ return ret;
+ pdev->vcompression = qual;
+ break;
+ }
+
+ case VIDIOCPWCGCQUAL:
+ {
+ if (copy_to_user(arg, &pdev->vcompression, sizeof(int)))
+ return -EFAULT;
+ break;
+ }
+
+ case VIDIOCPWCSAGC:
+ {
+ int agc;
+
+ if (copy_from_user(&agc, arg, sizeof(agc)))
+ return -EFAULT;
+ else {
+ if (pwc_set_agc(pdev, agc < 0 ? 1 : 0, agc))
+ return -EINVAL;
+ }
+ break;
+ }
+
+ case VIDIOCPWCGAGC:
+ {
+ int agc;
+
+ if (pwc_get_agc(pdev, &agc))
+ return -EINVAL;
+ if (copy_to_user(arg, &agc, sizeof(agc)))
+ return -EFAULT;
+ break;
+ }
+
+ case VIDIOCPWCSSHUTTER:
+ {
+ int shutter_speed, ret;
+
+ if (copy_from_user(&shutter_speed, arg, sizeof(shutter_speed)))
+ return -EFAULT;
+ else {
+ ret = pwc_set_shutter_speed(pdev, shutter_speed < 0 ? 1 : 0, shutter_speed);
+ if (ret < 0)
+ return ret;
+ }
+ break;
+ }
+
+ default:
+ return -ENOIOCTLCMD;
+ break;
+ }
+ return 0;
+}
+
+#endif
--- /dev/null
+/* Linux driver for Philips webcam
+ USB and Video4Linux interface part.
+ (C) 1999-2001 Nemosoft Unv.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+/*
+ This code forms the interface between the USB layers and the Philips
+ specific stuff. Some adanved stuff of the driver falls under an
+ NDA, signed between me and Philips B.V., Eindhoven, the Netherlands, and
+ is thus not distributed in source form. The binary pwcx.o module
+ contains the code that falls under the NDA.
+
+ In case you're wondering: 'pwc' stands for "Philips WebCam", but
+ I really didn't want to type 'philips_web_cam' every time (I'm lazy as
+ any Linux kernel hacker, but I don't like uncomprehensible abbreviations
+ without explanation).
+
+ Oh yes, convention: to disctinguish between all the various pointers to
+ device-structures, I use these names for the pointer variables:
+ udev: struct usb_device *
+ vdev: struct video_device *
+ pdev: struct pwc_devive *
+*/
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/wrapper.h>
+#include <asm/io.h>
+
+#include "pwc.h"
+#include "pwc-ioctl.h"
+#include "pwc-uncompress.h"
+
+#if !defined(MAP_NR)
+#define MAP_NR(a) virt_to_page(a)
+#endif
+
+/* Function prototypes and driver templates */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+
+/* hotplug device table support */
+static __devinitdata struct usb_device_id pwc_device_table [] = {
+ { USB_DEVICE(0x0471, 0x0302) },
+ { USB_DEVICE(0x0471, 0x0303) },
+ { USB_DEVICE(0x0471, 0x0304) },
+ { USB_DEVICE(0x0471, 0x0307) },
+ { USB_DEVICE(0x0471, 0x0308) },
+ { USB_DEVICE(0x0471, 0x030C) },
+ { USB_DEVICE(0x0471, 0x0310) },
+ { USB_DEVICE(0x0471, 0x0311) },
+ { USB_DEVICE(0x069A, 0x0001) },
+ { }
+};
+MODULE_DEVICE_TABLE(usb, pwc_device_table);
+
+static void *usb_pwc_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id);
+static void usb_pwc_disconnect(struct usb_device *udev, void *ptr);
+
+static struct usb_driver pwc_driver =
+{
+ name: "Philips webcam", /* name */
+ id_table: pwc_device_table,
+ probe: usb_pwc_probe, /* probe() */
+ disconnect: usb_pwc_disconnect, /* disconnect() */
+};
+
+#else
+
+static void *usb_pwc_probe(struct usb_device *udev, unsigned int ifnum);
+static void usb_pwc_disconnect(struct usb_device *udev, void *ptr);
+
+static struct usb_driver pwc_driver =
+{
+ name: "Philips webcam", /* name */
+ probe: usb_pwc_probe, /* probe() */
+ disconnect: usb_pwc_disconnect, /* disconnect() */
+};
+#endif
+
+
+static int default_size = PSZ_QCIF;
+static int default_fps = 10;
+static int default_palette = VIDEO_PALETTE_RGB24; /* This is normal for webcams */
+static int default_fbufs = 3; /* Default number of frame buffers */
+static int default_mbufs = 2; /* Default number of mmap() buffers */
+ int pwc_trace = TRACE_MODULE | TRACE_FLOW;
+static int power_save = 0;
+int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */
+
+static struct semaphore mem_lock;
+static void *mem_leak = NULL; /* For delayed kfree()s. See below */
+
+static int video_nr = -1;
+
+/***/
+
+static int pwc_video_open(struct video_device *vdev, int mode);
+static void pwc_video_close(struct video_device *vdev);
+static long pwc_video_read(struct video_device *vdev, char *buf, unsigned long count, int noblock);
+static long pwc_video_write(struct video_device *vdev, const char *buf, unsigned long count, int noblock);
+static unsigned int pwc_video_poll(struct video_device *vdev, struct file *file, poll_table *wait);
+static int pwc_video_ioctl(struct video_device *vdev, unsigned int cmd, void *arg);
+static int pwc_video_mmap(struct video_device *dev, const char *adr, unsigned long size);
+
+static struct video_device pwc_template = {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3)
+ owner: NULL,
+#endif
+ name: "Philips Webcam", /* Filled in later */
+ type: VID_TYPE_CAPTURE,
+#ifdef VID_HARDWARE_PWC
+ hardware: VID_HARDWARE_PWC, /* Let's pretend for now */
+#else
+ hardware: 0, /* 2.2.14 backport (?) */
+#endif
+ open: pwc_video_open,
+ close: pwc_video_close,
+ read: pwc_video_read,
+ write: pwc_video_write,
+ poll: pwc_video_poll,
+ ioctl: pwc_video_ioctl,
+ mmap: pwc_video_mmap,
+ initialize: NULL, /* initialize */
+ minor: 0 /* minor */
+};
+
+/***************************************************************************/
+
+/* Okay, this is some magic that I worked out and the reasoning behind it...
+
+ The biggest problem with any USB device is of course: "what to do
+ when the user unplugs the device while it is in use by an application?"
+ We have several options:
+ 1) Curse them with the 7 plagues when they do (requires divine intervention)
+ 2) Tell them not to (won't work: they'll do it anyway)
+ 3) Oops the kernel (this will have a negative effect on a user's uptime)
+ 4) Do something sensible.
+
+ Of course, we go for option 4.
+
+ It happens that this device will be linked to two times, once from
+ usb_device and once from the video_device in their respective 'private'
+ pointers. This is done when the device is probed() and all initialization
+ succeeded. The pwc_device struct links back to both structures.
+
+ When a device is unplugged while in use it will be removed from the
+ list of known USB devices; I also de-register as a V4L device, but
+ unfortunately I can't free the memory since the struct is still in use
+ by the file descriptor. This free-ing is then deferend until the first
+ opportunity. Crude, but it works.
+
+ A small 'advantage' is that if a user unplugs the cam and plugs it back
+ in, it should get assigned the same video device minor, but unfortunately
+ it's non-trivial to re-link the cam back to the video device... (that
+ would surely be magic! :))
+*/
+
+/***************************************************************************/
+/* Private functions */
+
+/* Memory management functions, nicked from cpia.c, which nicked them from
+ bttv.c. So far, I've counted duplication of this code 6 times
+ (bttv, cpia, ibmcam, ov511, pwc, ieee1394).
+ */
+
+/* Given PGD from the address space's page table, return the kernel
+ * virtual mapping of the physical memory mapped at ADR.
+ */
+static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
+{
+ unsigned long ret = 0UL;
+ pmd_t *pmd;
+ pte_t *ptep, pte;
+
+ if (!pgd_none(*pgd)) {
+ pmd = pmd_offset(pgd, adr);
+ if (!pmd_none(*pmd)) {
+ ptep = pte_offset(pmd, adr);
+ pte = *ptep;
+ if (pte_present(pte)) {
+ ret = (unsigned long) page_address(pte_page(pte));
+ ret |= (adr & (PAGE_SIZE-1));
+ }
+ }
+ }
+ return ret;
+}
+
+static inline unsigned long uvirt_to_bus(unsigned long adr)
+{
+ unsigned long kva, ret;
+
+ kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr);
+ ret = virt_to_bus((void *)kva);
+ return ret;
+}
+
+static inline unsigned long kvirt_to_bus(unsigned long adr)
+{
+ unsigned long va, kva, ret;
+
+ va = VMALLOC_VMADDR(adr);
+ kva = uvirt_to_kva(pgd_offset_k(va), va);
+ ret = virt_to_bus((void *)kva);
+ return ret;
+}
+
+/* Here we want the physical address of the memory.
+ * This is used when initializing the contents of the
+ * area and marking the pages as reserved.
+ */
+static inline unsigned long kvirt_to_pa(unsigned long adr)
+{
+ unsigned long va, kva, ret;
+
+ va = VMALLOC_VMADDR(adr);
+ kva = uvirt_to_kva(pgd_offset_k(va), va);
+ ret = __pa(kva);
+ return ret;
+}
+
+static void *rvmalloc(unsigned long size)
+{
+ void *mem;
+ unsigned long adr, page;
+
+ /* Round it off to PAGE_SIZE */
+ size += (PAGE_SIZE - 1);
+ size &= ~(PAGE_SIZE - 1);
+
+ mem = vmalloc(size);
+ if (!mem)
+ return NULL;
+
+ memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+ adr = (unsigned long) mem;
+ while (size > 0) {
+ page = kvirt_to_pa(adr);
+ mem_map_reserve(MAP_NR(__va(page)));
+ adr += PAGE_SIZE;
+ if (size > PAGE_SIZE)
+ size -= PAGE_SIZE;
+ else
+ size = 0;
+ }
+ return mem;
+}
+
+static void rvfree(void *mem, unsigned long size)
+{
+ unsigned long adr, page;
+
+ if (!mem)
+ return;
+
+ size += (PAGE_SIZE - 1);
+ size &= ~(PAGE_SIZE - 1);
+
+ adr=(unsigned long) mem;
+ while (size > 0) {
+ page = kvirt_to_pa(adr);
+ mem_map_unreserve(MAP_NR(__va(page)));
+ adr += PAGE_SIZE;
+ if (size > PAGE_SIZE)
+ size -= PAGE_SIZE;
+ else
+ size = 0;
+ }
+ vfree(mem);
+}
+
+
+
+static int pwc_allocate_buffers(struct pwc_device *pdev)
+{
+ int i;
+ void *kbuf;
+
+ Trace(TRACE_MEMORY, "Entering allocate_buffers(%p).\n", pdev);
+
+ if (pdev == NULL)
+ return -ENXIO;
+
+#ifdef PWC_MAGIC
+ if (pdev->magic != PWC_MAGIC) {
+ Err("allocate_buffers(): magic failed.\n");
+ return -ENXIO;
+ }
+#endif
+ /* Allocate Isochronuous pipe buffers */
+ for (i = 0; i < MAX_ISO_BUFS; i++) {
+ if (pdev->sbuf[i].data == NULL) {
+ kbuf = kmalloc(ISO_BUFFER_SIZE, GFP_KERNEL);
+ if (kbuf == NULL) {
+ Err("Failed to allocate iso buffer %d.\n", i);
+ return -ENOMEM;
+ }
+ pdev->sbuf[i].data = kbuf;
+ memset(kbuf, 0, ISO_BUFFER_SIZE);
+ }
+ }
+
+ /* Allocate frame buffer structure */
+ if (pdev->fbuf == NULL) {
+ kbuf = kmalloc(default_fbufs * sizeof(struct pwc_frame_buf), GFP_KERNEL);
+ if (kbuf == NULL) {
+ Err("Failed to allocate frame buffer structure.\n");
+ return -ENOMEM;
+ }
+ pdev->fbuf = kbuf;
+ memset(kbuf, 0, default_fbufs * sizeof(struct pwc_frame_buf));
+ }
+ /* create frame buffers, and make circular ring */
+ for (i = 0; i < default_fbufs; i++) {
+ if (pdev->fbuf[i].data == NULL) {
+ kbuf = vmalloc(FRAME_SIZE); /* need vmalloc since frame buffer > 128K */
+ if (kbuf == NULL) {
+ Err("Failed to allocate frame buffer %d.\n", i);
+ return -ENOMEM;
+ }
+ pdev->fbuf[i].data = kbuf;
+ memset(kbuf, 0, FRAME_SIZE);
+ }
+ }
+
+ /* Allocate decompressor buffer space */
+ kbuf = vmalloc(FRAME_SIZE);
+ if (kbuf == NULL) {
+ Err("Failed to allocate compressed image buffer.\n");
+ return -ENOMEM;
+ }
+ memset(kbuf, 0, FRAME_SIZE);
+ pdev->decompress_buffer = kbuf;
+
+ /* Allocate image buffer; double buffer for mmap() */
+ kbuf = rvmalloc(default_mbufs * pdev->view_max.size * 4);
+ if (kbuf == NULL) {
+ Err("Failed to allocate image buffer(s).\n");
+ return -ENOMEM;
+ }
+ pdev->image_data = kbuf;
+ for (i = 0; i < default_mbufs; i++)
+ pdev->image_ptr[i] = kbuf + (i * pdev->view_max.size * 4);
+ for (; i < MAX_IMAGES; i++)
+ pdev->image_ptr[i] = NULL;
+
+ Trace(TRACE_MEMORY, "Leaving pwc_allocate_buffers().\n");
+
+ return 0;
+}
+
+static void pwc_free_buffers(struct pwc_device *pdev)
+{
+ int i;
+
+ Trace(TRACE_MEMORY, "Entering free_buffers(%p).\n", pdev);
+
+ if (pdev == NULL)
+ return;
+#ifdef PWC_MAGIC
+ if (pdev->magic != PWC_MAGIC) {
+ Err("free_buffers(): magic failed.\n");
+ return;
+ }
+#endif
+ /* Release Iso-pipe buffers */
+ Trace(TRACE_MEMORY, "Freeing ISO buffers.\n");
+ for (i = 0; i < MAX_ISO_BUFS; i++)
+ if (pdev->sbuf[i].data != NULL) {
+ kfree(pdev->sbuf[i].data);
+ pdev->sbuf[i].data = NULL;
+ }
+ /* The same for frame buffers */
+ Trace(TRACE_MEMORY, "Freeing frame buffers.\n");
+ if (pdev->fbuf != NULL) {
+ for (i = 0; i < default_fbufs; i++) {
+ if (pdev->fbuf[i].data != NULL) {
+ vfree(pdev->fbuf[i].data);
+ pdev->fbuf[i].data = NULL;
+ }
+ }
+ kfree(pdev->fbuf);
+ pdev->fbuf = NULL;
+ }
+ /* Intermediate decompression buffer */
+ Trace(TRACE_MEMORY, "Freeing decompression buffer\n");
+ if (pdev->decompress_buffer != NULL)
+ vfree(pdev->decompress_buffer);
+ pdev->decompress_buffer = NULL;
+
+ /* Release image buffers */
+ Trace(TRACE_MEMORY, "Freeing image buffers\n");
+ if (pdev->image_data != NULL)
+ rvfree(pdev->image_data, default_mbufs * pdev->view_max.size * 4);
+ pdev->image_data = NULL;
+ Trace(TRACE_MEMORY, "Leaving free_buffers().\n");
+}
+
+/* The frame & image buffer mess.
+
+ Yes, this is a mess. Well, it used to be simple, but alas... In this
+ module, 3 buffers schemes are used to get the data from the USB bus to
+ the user program. The first scheme involves the ISO buffers (called thus
+ since they transport ISO data from the USB controller), and not really
+ interesting. Suffices to say the data from this buffer is quickly
+ gathered in an interrupt handler (pwc_isoc_hanlder) and placed into the
+ frame buffer.
+
+ The frame buffer is the second scheme, and is the central element here.
+ It collects the data from a single frame from the camera (hence, the
+ name). Frames are delimited by the USB camera with a short USB packet,
+ so that's easy to detect. The frame buffers form a list that is filled
+ by the camera+USB controller and drained by the user process through
+ either read() or mmap().
+
+ The image buffer is the third scheme, in which frames are decompressed
+ and converted into any of the desired image formats (rgb, bgr, yuv, etc).
+ For mmap() there is more than one image buffer available.
+
+ The frame buffers provide the image buffering, in case the user process
+ is a bit slow. This introduces lag and some undesired side-effects.
+ The problem arises when the frame buffer is full. I used to drop the last
+ frame, which makes the data in the queue stale very quickly. But dropping
+ the frame at the head of the queue proved to be a litte bit more difficult.
+ I tried a circular linked scheme, but this introduced more problems than
+ it solved.
+
+ Because filling and draining are completely asynchronous processes, this
+ requires some fiddling with pointers and mutexes.
+
+ Eventually, I came up with a system with 2 lists: an 'empty' frame list
+ and a 'full' frame list:
+ * Initially, all frame buffers but one are on the 'empty' list; the one
+ remaining buffer is our initial fill frame.
+ * If a frame is needed for filling, we take it from the 'empty' list,
+ unless that list is empty, in which case we take the buffer at the
+ head of the 'full' list.
+ * When our fill buffer has been filled, it is appended to the 'full'
+ list.
+ * If a frame is needed by read() or mmap(), it is taken from the head of
+ the 'full' list, handled, and then appended to the 'empty' list. If no
+ buffer is present on the 'full' list, we wait.
+ The advantage is that the buffer that is currently being decompressed/
+ converted, is on neither list, and thus not in our way (any other scheme
+ I tried had the problem of old data lingering in the queue).
+
+ Whatever strategy you choose, it always remains a tradeoff: with more
+ frame buffers the chances of a missed frame are reduced. On the other
+ hand, on slower machines it introduces lag because the queue will
+ always be full.
+ */
+
+/**
+ \brief Find next frame buffer to fill. Take from empty or full list, whichever comes first.
+ */
+static inline int pwc_next_fill_frame(struct pwc_device *pdev)
+{
+ int ret, flags;
+
+ ret = 0;
+ spin_lock_irqsave(&pdev->ptrlock, flags);
+ if (pdev->fill_frame != NULL) {
+ /* append to 'full' list */
+ if (pdev->full_frames == NULL) {
+ pdev->full_frames = pdev->fill_frame;
+ pdev->full_frames_tail = pdev->full_frames;
+ }
+ else {
+ pdev->full_frames_tail->next = pdev->fill_frame;
+ pdev->full_frames_tail = pdev->fill_frame;
+ }
+ }
+ if (pdev->empty_frames != NULL) {
+ /* We have empty frames available. That's easy */
+ pdev->fill_frame = pdev->empty_frames;
+ pdev->empty_frames = pdev->empty_frames->next;
+ }
+ else {
+ /* Hmm. Take it from the full list */
+#if PWC_DEBUG
+ /* sanity check */
+ if (pdev->full_frames == NULL) {
+ Err("Neither empty or full frames available!\n");
+ spin_unlock_irqrestore(&pdev->ptrlock, flags);
+ return -EINVAL;
+ }
+#endif
+ pdev->fill_frame = pdev->full_frames;
+ pdev->full_frames = pdev->full_frames->next;
+ ret = 1;
+ }
+ pdev->fill_frame->next = NULL;
+#if PWC_DEBUG
+ Trace(TRACE_SEQUENCE, "Assigning sequence number %d.\n", pdev->sequence);
+ pdev->fill_frame->sequence = pdev->sequence++;
+#endif
+ spin_unlock_irqrestore(&pdev->ptrlock, flags);
+ return ret;
+}
+
+
+/**
+ \brief Reset all buffers, pointers and lists, except for the image_used[] buffer.
+
+ If the image_used[] buffer is cleared too mmap()/VIDIOCSYNC will run into trouble.
+ */
+static void pwc_reset_buffers(struct pwc_device *pdev)
+{
+ int i, flags;
+
+ spin_lock_irqsave(&pdev->ptrlock, flags);
+ pdev->full_frames = NULL;
+ pdev->full_frames_tail = NULL;
+ for (i = 0; i < default_fbufs; i++) {
+ pdev->fbuf[i].filled = 0;
+ if (i > 0)
+ pdev->fbuf[i].next = &pdev->fbuf[i - 1];
+ else
+ pdev->fbuf->next = NULL;
+ }
+ pdev->empty_frames = &pdev->fbuf[default_fbufs - 1];
+ pdev->empty_frames_tail = pdev->fbuf;
+ pdev->read_frame = NULL;
+ pdev->fill_frame = pdev->empty_frames;
+ pdev->empty_frames = pdev->empty_frames->next;
+
+ pdev->image_read_pos = 0;
+ pdev->fill_image = 0;
+ spin_unlock_irqrestore(&pdev->ptrlock, flags);
+}
+
+
+/**
+ \brief Do all the handling for getting one frame: get pointer, decompress, advance pointers.
+ */
+static int pwc_handle_frame(struct pwc_device *pdev)
+{
+ int ret = 0, flags;
+
+ spin_lock_irqsave(&pdev->ptrlock, flags);
+ /* First grab our read_frame; this is removed from all lists, so
+ we can release the lock after this without problems */
+ if (pdev->read_frame != NULL) {
+ /* This can't theoretically happen */
+ Err("Huh? Read frame still in use?\n");
+ }
+ else {
+ if (pdev->full_frames == NULL) {
+ Err("Woops. No frames ready.\n");
+ }
+ else {
+ pdev->read_frame = pdev->full_frames;
+ pdev->full_frames = pdev->full_frames->next;
+ pdev->read_frame->next = NULL;
+ }
+
+ if (pdev->read_frame != NULL) {
+#if PWC_DEBUG
+ Trace(TRACE_SEQUENCE, "Decompressing frame %d\n", pdev->read_frame->sequence);
+#endif
+ /* Decompression is a lenghty process, so it's outside of the lock.
+ This gives the isoc_handler the opportunity to fill more frames
+ in the mean time.
+ */
+ spin_unlock_irqrestore(&pdev->ptrlock, flags);
+ ret = pwc_decompress(pdev);
+ spin_lock_irqsave(&pdev->ptrlock, flags);
+
+ /* We're done with read_buffer, tack it to the end of the empty buffer list */
+ if (pdev->empty_frames == NULL) {
+ pdev->empty_frames = pdev->read_frame;
+ pdev->empty_frames_tail = pdev->empty_frames;
+ }
+ else {
+ pdev->empty_frames_tail->next = pdev->read_frame;
+ pdev->empty_frames_tail = pdev->read_frame;
+ }
+ pdev->read_frame = NULL;
+ }
+ }
+ spin_unlock_irqrestore(&pdev->ptrlock, flags);
+ return ret;
+}
+
+/**
+ \brief Advance pointers of image buffer (after each user request)
+*/
+static inline void pwc_next_image(struct pwc_device *pdev)
+{
+ pdev->image_used[pdev->fill_image] = 0;
+ pdev->fill_image = (pdev->fill_image + 1) % default_mbufs;
+}
+
+static int pwc_set_palette(struct pwc_device *pdev, int pal)
+{
+ if ( pal == VIDEO_PALETTE_RGB24
+ || pal == VIDEO_PALETTE_RGB32
+ || pal == (VIDEO_PALETTE_RGB24 | 0x80)
+ || pal == (VIDEO_PALETTE_RGB32 | 0x80)
+ || pal == VIDEO_PALETTE_YUYV
+ || pal == VIDEO_PALETTE_YUV422
+ || pal == VIDEO_PALETTE_YUV420
+ || pal == VIDEO_PALETTE_YUV420P
+#if PWC_DEBUG
+ || pal == VIDEO_PALETTE_RAW
+#endif
+ ) {
+ pdev->vpalette = pal;
+ pwc_set_image_buffer_size(pdev);
+ return 0;
+ }
+ return -1;
+}
+
+
+
+/* This gets called for the Isochronous pipe (video). This is done in
+ * interrupt time, so it has to be fast, not crash, and not stall. Neat.
+ */
+static void pwc_isoc_handler(purb_t urb)
+{
+ struct pwc_device *pdev;
+ int i, fst, flen;
+ int awake;
+ struct pwc_frame_buf *fbuf;
+ unsigned char *fillptr, *iso_buf;
+
+ pdev = (struct pwc_device *)urb->context;
+ if (pdev == NULL) {
+ Err("isoc_handler() called with NULL device?!\n");
+ return;
+ }
+#ifdef PWC_MAGIC
+ if (pdev->magic != PWC_MAGIC) {
+ Err("isoc_handler() called with bad magic!\n");
+ return;
+ }
+#endif
+ if (urb->status == -ENOENT || urb->status == -ECONNRESET) {
+ Trace(TRACE_OPEN, "pwc_isoc_handler(): URB unlinked.\n");
+ return;
+ }
+ if (urb->status != -EINPROGRESS && urb->status != 0) {
+ Trace(TRACE_FLOW, "pwc_isoc_handler() called with status %d.\n", urb->status);
+ return;
+ }
+
+ fbuf = pdev->fill_frame;
+ if (fbuf == NULL) {
+ Err("pwc_isoc_handler without valid fill frame.\n");
+ if (waitqueue_active(&pdev->frameq))
+ wake_up_interruptible(&pdev->frameq);
+ if (waitqueue_active(&pdev->pollq))
+ wake_up_interruptible(&pdev->pollq);
+ return;
+ }
+ fillptr = fbuf->data + fbuf->filled;
+ awake = 0;
+
+ /* vsync: 0 = don't copy data
+ 1 = sync-hunt
+ 2 = synched
+ */
+ /* Compact data */
+ for (i = 0; i < urb->number_of_packets; i++) {
+ fst = urb->iso_frame_desc[i].status;
+ flen = urb->iso_frame_desc[i].actual_length;
+ iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+ if (fst == 0) {
+ if (flen > 0) { /* if valid data... */
+ if (pdev->vsync > 0) { /* ...and we are not sync-hunting... */
+ pdev->vsync = 2;
+
+ /* ...copy data to frame buffer, if possible */
+ if (flen + fbuf->filled > pdev->frame_size) {
+ Trace(TRACE_FLOW, "Frame buffer overflow (flen = %d, frame_size = %d).\n", flen, pdev->frame_size);
+ pdev->vsync = 0; /* Hmm, let's wait for an EOF (end-of-frame) */
+ pdev->vframes_error++;
+ }
+ else {
+ memmove(fillptr, iso_buf, flen);
+ fillptr += flen;
+ }
+ }
+ fbuf->filled += flen;
+ } /* ..flen > 0 */
+
+ if (flen < pdev->vlast_packet_size) {
+ /* Shorter packet... We probably have the end of an image-frame;
+ wake up read() process and let select()/poll() do something.
+ Decompression is done in user time over there.
+ */
+ if (pdev->vsync == 2) {
+ /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus
+ frames on the USB wire after an exposure change. This conditition is
+ however detected in the cam and a bit is set in the header.
+ */
+ if (pdev->type == 730) {
+ unsigned char *ptr = (unsigned char *)fbuf->data;
+
+ if (ptr[1] == 1 && ptr[0] & 0x10) {
+#if PWC_DEBUG
+ Debug("Hyundai CMOS sensor bug. Dropping frame %d.\n", fbuf->sequence);
+#endif
+ pdev->drop_frames = 2;
+ pdev->vframes_error++;
+ }
+ /* Sometimes the trailer of the 730 is still sent as a 4 byte packet
+ after a short frame; this condition is filtered out specifically. A 4 byte
+ frame doesn't make sense anyway.
+ So we get either this sequence:
+ drop_bit set -> 4 byte frame -> short frame -> good frame
+ Or this one:
+ drop_bit set -> short frame -> good frame
+ So we drop either 3 or 2 frames in all!
+ */
+ if (fbuf->filled == 4)
+ pdev->drop_frames++;
+ }
+
+ /* In case we were instructed to drop the frame, do so silently.
+ The buffer pointers are not updated either (but the counters are reset below).
+ */
+ if (pdev->drop_frames)
+ pdev->drop_frames--;
+ else {
+ /* Check for underflow first */
+ if (fbuf->filled < pdev->frame_size) {
+ Trace(TRACE_FLOW, "Frame buffer underflow (%d bytes); discarded.\n", fbuf->filled);
+ pdev->vframes_error++;
+ }
+ else {
+ /* Send only once per EOF */
+ awake = 1; /* delay wake_ups */
+
+ /* Find our next frame to fill. This will always succeed, since we
+ * nick a frame from either empty or full list, but if we had to
+ * take it from the full list, it means a frame got dropped.
+ */
+ if (pwc_next_fill_frame(pdev)) {
+ pdev->vframes_dumped++;
+ if ((pdev->vframe_count > FRAME_LOWMARK) && (pwc_trace & TRACE_FLOW)) {
+ if (pdev->vframes_dumped < 20)
+ Info("Dumping frame %d.\n", pdev->vframe_count);
+ if (pdev->vframes_dumped == 20)
+ Info("Dumping frame %d (last message).\n", pdev->vframe_count);
+ }
+ }
+ fbuf = pdev->fill_frame;
+ }
+ } /* !drop_frames */
+ pdev->vframe_count++;
+ }
+ fbuf->filled = 0;
+ fillptr = fbuf->data;
+ pdev->vsync = 1;
+ } /* .. flen < last_packet_size */
+ pdev->vlast_packet_size = flen;
+ } /* ..status == 0 */
+ }
+ if (awake) {
+ if (waitqueue_active(&pdev->frameq))
+ wake_up_interruptible(&pdev->frameq);
+ if (waitqueue_active(&pdev->pollq))
+ wake_up_interruptible(&pdev->pollq);
+ }
+}
+
+
+static int pwc_isoc_init(struct pwc_device *pdev)
+{
+ struct usb_device *udev;
+ purb_t urb;
+ int i, j, ret;
+
+ struct usb_interface_descriptor *idesc;
+ int cur_alt;
+
+ if (pdev == NULL)
+ return -EFAULT;
+ if (pdev->iso_init)
+ return 0;
+ pdev->vsync = 0;
+ udev = pdev->udev;
+
+ /* Get the current alternate interface, adjust packet size */
+ if (!udev->actconfig)
+ return -EFAULT;
+ cur_alt = udev->actconfig->interface[0].act_altsetting;
+ idesc = &udev->actconfig->interface[0].altsetting[cur_alt];
+ if (!idesc)
+ return -EFAULT;
+
+ /* Search video endpoint */
+ pdev->vmax_packet_size = -1;
+ for (i = 0; i < idesc->bNumEndpoints; i++)
+ if ((idesc->endpoint[i].bEndpointAddress & 0xF) == pdev->vendpoint) {
+ pdev->vmax_packet_size = idesc->endpoint[i].wMaxPacketSize;
+ break;
+ }
+
+ if (pdev->vmax_packet_size < 0) {
+ Err("Failed to find packet size for video endpoint in current alternate setting.\n");
+ return -ENFILE; /* Odd error, that should be noticable */
+ }
+
+ ret = 0;
+ for (i = 0; i < MAX_ISO_BUFS; i++) {
+ urb = usb_alloc_urb(ISO_FRAMES_PER_DESC);
+ if (urb == NULL) {
+ Err("Failed to allocate urb %d\n", i);
+ ret = -ENOMEM;
+ break;
+ }
+ pdev->sbuf[i].urb = urb;
+ }
+ if (ret) {
+ /* De-allocate in reverse order */
+ while (i >= 0) {
+ if (pdev->sbuf[i].urb != NULL)
+ usb_free_urb(pdev->sbuf[i].urb);
+ i--;
+ }
+ return ret;
+ }
+
+
+ /* init URB structure */
+ for (i = 0; i < MAX_ISO_BUFS; i++) {
+ urb = pdev->sbuf[i].urb;
+
+ urb->next = pdev->sbuf[(i + 1) % MAX_ISO_BUFS].urb;
+ urb->dev = udev;
+ urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint);
+ urb->transfer_flags = USB_ISO_ASAP;
+ urb->transfer_buffer = pdev->sbuf[i].data;
+ urb->transfer_buffer_length = ISO_BUFFER_SIZE;
+ urb->complete = pwc_isoc_handler;
+ urb->context = pdev;
+ urb->start_frame = 0;
+ urb->number_of_packets = ISO_FRAMES_PER_DESC;
+ for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
+ urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE;
+ urb->iso_frame_desc[j].length = ISO_MAX_FRAME_SIZE;
+ }
+ }
+
+ /* link */
+ for (i = 0; i < MAX_ISO_BUFS; i++) {
+ ret = usb_submit_urb(pdev->sbuf[i].urb);
+ if (ret)
+ Err("isoc_init() submit_urb %d failed with error %d\n", i, ret);
+ }
+
+ /* data should stream in now */
+ pdev->iso_init = 1;
+ return 0;
+}
+
+static void pwc_isoc_cleanup(struct pwc_device *pdev)
+{
+ int i;
+
+ if (pdev == NULL)
+ return;
+ if (!pdev->iso_init)
+ return;
+ /* Stop camera, but only if we are sure the camera is still there */
+ if (!pdev->unplugged)
+ usb_set_interface(pdev->udev, 0, 0);
+ for (i = MAX_ISO_BUFS - 1; i >= 0; i--) {
+ pdev->sbuf[i].urb->next = NULL;
+ usb_unlink_urb(pdev->sbuf[i].urb);
+ usb_free_urb(pdev->sbuf[i].urb);
+ pdev->sbuf[i].urb = NULL;
+ }
+ pdev->iso_init = 0;
+}
+
+int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot)
+{
+ int ret;
+
+ /* Stop isoc stuff */
+ pwc_isoc_cleanup(pdev);
+ /* Reset parameters */
+ pwc_reset_buffers(pdev);
+ /* Try to set video mode... */
+ ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot);
+ if (ret) /* That failed... restore old mode (we know that worked) */
+ ret = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
+ else /* Set (new) alternate interface */
+ ret = usb_set_interface(pdev->udev, 0, pdev->valternate);
+ if (!ret)
+ ret = pwc_isoc_init(pdev);
+ pdev->drop_frames = 1; /* try to avoid garbage during switch */
+ return ret;
+}
+
+
+static inline void set_mem_leak(void *ptr)
+{
+ down(&mem_lock);
+ if (mem_leak != NULL)
+ Err("Memleak: overwriting mem_leak pointer!\n");
+ Trace(TRACE_MEMORY, "Setting mem_leak to 0x%p.\n", ptr);
+ mem_leak = ptr;
+ up(&mem_lock);
+}
+
+static inline void free_mem_leak(void)
+{
+ down(&mem_lock);
+ if (mem_leak != NULL) {
+ Trace(TRACE_MEMORY, "Freeing mem_leak ptr 0x%p.\n", mem_leak);
+ kfree(mem_leak);
+ mem_leak = NULL;
+ }
+ up(&mem_lock);
+}
+
+
+/***************************************************************************/
+/* Video4Linux functions */
+
+static int pwc_video_open(struct video_device *vdev, int mode)
+{
+ int i;
+ struct pwc_device *pdev;
+
+ Trace(TRACE_OPEN, "video_open called(0x%p, 0%o).\n", vdev, mode);
+
+ if (vdev == NULL) {
+ Err("video_open() called with NULL structure?\n");
+ return -EFAULT;
+ }
+ pdev = (struct pwc_device *)vdev->priv;
+ if (pdev == NULL) {
+ Err("video_open() called with NULL pwc_device.\n");
+ return -EFAULT;
+ }
+
+ MOD_INC_USE_COUNT;
+ down(&pdev->modlock);
+ if (!pdev->usb_init) {
+ Trace(TRACE_OPEN, "Doing first time initialization.\n");
+ /* Reset camera */
+ if (usb_set_interface(pdev->udev, 0, 0))
+ Info("Failed to set alternate interface to 0.\n");
+ pdev->usb_init = 1;
+ }
+ else {
+ /* Turn on camera */
+ if (power_save) {
+ i = pwc_camera_power(pdev, 1);
+ if (i < 0)
+ Info("Failed to restore power to the camera! (%d)\n", i);
+ }
+ }
+
+ /* So far, so good. Allocate memory. */
+ i = pwc_allocate_buffers(pdev);
+ if (i < 0) {
+ Trace(TRACE_OPEN, "Failed to allocate memory.\n");
+ MOD_DEC_USE_COUNT;
+ up(&pdev->modlock);
+ return i;
+ }
+
+ /* Reset buffers & parameters */
+ pwc_reset_buffers(pdev);
+ for (i = 0; i < default_mbufs; i++)
+ pdev->image_used[i] = 0;
+ pdev->vframe_count = 0;
+ pdev->vframes_dumped = 0;
+ pdev->vframes_error = 0;
+ pdev->vpalette = default_palette;
+#if PWC_DEBUG
+ pdev->sequence = 0;
+#endif
+
+ /* Find our decompressor, if any */
+ pdev->decompressor = pwc_find_decompressor(pdev->type);
+#if PWC_DEBUG
+ Debug("Found decompressor for %d at 0x%p\n", pdev->type, pdev->decompressor);
+#endif
+
+ /* Set some defaults */
+ pdev->vsnapshot = 0;
+ if (pdev->type == 730 || pdev->type == 740)
+ pdev->vsize = PSZ_QSIF;
+ else
+ pdev->vsize = PSZ_QCIF;
+ pdev->vframes = 10;
+
+ /* Start iso pipe for video; first try user-supplied size/fps, if
+ that fails try QCIF/10 or QSIF/10 (a reasonable default),
+ then give up
+ */
+ i = pwc_set_video_mode(pdev, pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y, default_fps, pdev->vcompression, 0);
+ if (i) {
+ Trace(TRACE_OPEN, "First attempt at set_video_mode failed.\n");
+ if (pdev->type == 730 || pdev->type == 740)
+ i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QSIF].x, pwc_image_sizes[PSZ_QSIF].y, 10, pdev->vcompression, 0);
+ else
+ i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QCIF].x, pwc_image_sizes[PSZ_QCIF].y, 10, pdev->vcompression, 0);
+ }
+ if (i) {
+ Trace(TRACE_OPEN, "Second attempt at set_video_mode failed.\n");
+ MOD_DEC_USE_COUNT;
+ up(&pdev->modlock);
+ return i;
+ }
+ i = usb_set_interface(pdev->udev, 0, pdev->valternate);
+ if (i) {
+ Trace(TRACE_OPEN, "Failed to set alternate interface = %d.\n", i);
+ MOD_DEC_USE_COUNT;
+ up(&pdev->modlock);
+ return -EINVAL;
+ }
+ i = pwc_isoc_init(pdev);
+ if (i) {
+ Trace(TRACE_OPEN, "Failed to init ISOC stuff = %d.\n", i);
+ MOD_DEC_USE_COUNT;
+ up(&pdev->modlock);
+ return i;
+ }
+
+ pdev->vopen++;
+ /* lock decompressor; this has a small race condition, since we
+ could in theory unload pwcx.o between pwc_find_decompressor()
+ above and this call. I doubt it's ever going to be a problem.
+ */
+ if (pdev->decompressor != NULL)
+ pdev->decompressor->lock();
+ up(&pdev->modlock);
+ Trace(TRACE_OPEN, "video_open() returning 0.\n");
+ return 0;
+}
+
+/* Note that all cleanup is done in the reverse order as in _open */
+static void pwc_video_close(struct video_device *vdev)
+{
+ struct pwc_device *pdev;
+ int i;
+
+ Trace(TRACE_OPEN, "video_close called(0x%p).\n", vdev);
+ if (vdev == NULL) {
+ Err("video_close() called with NULL structure?\n");
+ return;
+ }
+ pdev = (struct pwc_device *)vdev->priv;
+ if (pdev == NULL) {
+ Err("video_close() called with NULL pwc_device.\n");
+ return;
+ }
+ if (pdev->vopen == 0)
+ Info("video_close() called on closed device?\n");
+
+ /* Free isoc URBs */
+ pwc_isoc_cleanup(pdev);
+
+ /* Dump statistics, but only if a reasonable amount of frames were
+ processed (to prevent endless log-entries in case of snap-shot
+ programs)
+ */
+ if (pdev->vframe_count > 20)
+ Info("Closing video device: %d frames received, dumped %d frames, %d frames with errors.\n", pdev->vframe_count, pdev->vframes_dumped, pdev->vframes_error);
+
+ if (pdev->unplugged) {
+ /* The device was unplugged or some other error occured */
+ /* We unregister the video_device */
+ Trace(TRACE_OPEN, "Delayed video device unregistered.\n");
+ video_unregister_device(pdev->vdev);
+ }
+ else {
+ /* Normal close: stop isochronuous and interrupt endpoint */
+ Trace(TRACE_OPEN, "Normal close(): setting interface to 0.\n");
+ usb_set_interface(pdev->udev, 0, 0);
+
+ /* Turn off LED by powering down camera */
+ if (power_save) {
+ i = pwc_camera_power(pdev, 0);
+ if (i < 0)
+ Err("Failed to power down camera (%d)\n", i);
+ }
+ }
+
+ pdev->vopen = 0;
+ pwc_free_buffers(pdev);
+ if (pdev->decompressor != NULL) {
+ pdev->decompressor->exit(&pdev->decompress_data);
+ pdev->decompressor->unlock();
+ }
+ pdev->decompressor = NULL;
+
+ /* wake up _disconnect() routine */
+ if (pdev->unplugged)
+ wake_up(&pdev->remove_ok);
+
+ MOD_DEC_USE_COUNT;
+}
+
+static long pwc_video_read(struct video_device *vdev, char *buf, unsigned long count, int noblock)
+{
+ struct pwc_device *pdev;
+
+ Trace(TRACE_READ, "video_read(0x%p, %p, %ld, %d) called.\n", vdev, buf, count, noblock);
+ if (vdev == NULL)
+ return -EFAULT;
+ pdev = vdev->priv;
+ if (pdev == NULL)
+ return -EFAULT;
+ if (pdev->unplugged) {
+ Debug("pwc_video_read: Device got unplugged (1).\n");
+ return -EPIPE; /* unplugged device! */
+ }
+
+ /* In case we're doing partial reads, we don't have to wait for a frame */
+ if (pdev->image_read_pos == 0) {
+ /* See if a frame is completed, process that */
+ if (noblock && pdev->full_frames == NULL)
+ return -EAGAIN;
+ while (pdev->full_frames == NULL) {
+ interruptible_sleep_on(&pdev->frameq);
+ if (pdev->unplugged) {
+ Debug("pwc_video_read: Device got unplugged (2).\n");
+ return -EPIPE;
+ }
+ if (signal_pending(current))
+ return -EINTR;
+ }
+
+ /* Decompress & convert now */
+ if (pwc_handle_frame(pdev))
+ return -EFAULT;
+ }
+
+ Trace(TRACE_READ, "Copying data to user space.\n");
+ /* copy bytes to user space; we allow for partial reads */
+ if (count + pdev->image_read_pos > pdev->view.size)
+ count = pdev->view.size - pdev->image_read_pos;
+ if (copy_to_user(buf, pdev->image_ptr[pdev->fill_image] + pdev->image_read_pos, count))
+ return -EFAULT;
+ pdev->image_read_pos += count;
+ if (pdev->image_read_pos >= pdev->view.size) { /* All data has been read */
+ pdev->image_read_pos = 0;
+ pwc_next_image(pdev);
+ }
+ return count;
+}
+
+
+static long pwc_video_write(struct video_device *vdev, const char *buf, unsigned long count, int noblock)
+{
+ return -EINVAL;
+}
+
+static unsigned int pwc_video_poll(struct video_device *vdev, struct file *file, poll_table *wait)
+{
+ struct pwc_device *pdev;
+
+ if (vdev == NULL)
+ return -EFAULT;
+ pdev = vdev->priv;
+ if (pdev == NULL)
+ return -EFAULT;
+
+ poll_wait(file, &pdev->pollq, wait);
+ if (pdev->unplugged) {
+ Debug("pwc_video_poll: Device got unplugged.\n");
+ return POLLERR;
+ }
+ if (pdev->full_frames != NULL) /* we have frames waiting */
+ return (POLLIN | POLLRDNORM);
+
+ return 0;
+}
+
+static int pwc_video_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
+{
+ struct pwc_device *pdev;
+
+ if (vdev == NULL)
+ return -EFAULT;
+ pdev = vdev->priv;
+ if (pdev == NULL)
+ return -EFAULT;
+
+ switch (cmd) {
+ /* Query cabapilities */
+ case VIDIOCGCAP:
+ {
+ struct video_capability caps;
+
+ strcpy(caps.name, vdev->name);
+ caps.type = VID_TYPE_CAPTURE;
+ caps.channels = 1;
+ caps.audios = 1;
+ caps.minwidth = pdev->view_min.x;
+ caps.minheight = pdev->view_min.y;
+ caps.maxwidth = pdev->view_max.x;
+ caps.maxheight = pdev->view_max.y;
+ if (copy_to_user(arg, &caps, sizeof(caps)))
+ return -EFAULT;
+ break;
+ }
+
+ /* Channel functions (simulate 1 channel) */
+ case VIDIOCGCHAN:
+ {
+ struct video_channel v;
+
+ if (copy_from_user(&v, arg, sizeof(v)))
+ return -EFAULT;
+ if (v.channel != 0)
+ return -EINVAL;
+
+ v.flags = 0;
+ v.tuners = 0;
+ v.type = VIDEO_TYPE_CAMERA;
+ strcpy(v.name, "Webcam");
+
+ if (copy_to_user(arg, &v, sizeof(v)))
+ return -EFAULT;
+
+ return 0;
+ }
+
+ case VIDIOCSCHAN:
+ {
+ /* The spec says the argument is an integer, but
+ the bttv driver uses a video_channel arg, which
+ makes sense becasue it also has the norm flag.
+ */
+ struct video_channel v;
+
+ if (copy_from_user(&v, arg, sizeof(v)))
+ return -EFAULT;
+
+ if (v.channel != 0)
+ return -EINVAL;
+
+ return 0;
+ }
+
+
+ /* Picture functions; contrast etc. */
+ case VIDIOCGPICT:
+ {
+ struct video_picture p;
+ int val;
+
+ p.colour = 0x8000;
+ p.hue = 0x8000;
+ val = pwc_get_brightness(pdev);
+ if (val >= 0)
+ p.brightness = val;
+ else
+ p.brightness = 0xffff;
+ val = pwc_get_contrast(pdev);
+ if (val >= 0)
+ p.contrast = val;
+ else
+ p.contrast = 0xffff;
+ /* Gamma, Whiteness, what's the difference? :) */
+ val = pwc_get_gamma(pdev);
+ if (val >= 0)
+ p.whiteness = val;
+ else
+ p.whiteness = 0xffff;
+ val = pwc_get_saturation(pdev);
+ if (val >= 0)
+ p.colour = val;
+ else
+ p.colour = 0xffff;
+ p.depth = 24;
+ p.palette = pdev->vpalette;
+ p.hue = 0xFFFF; /* N/A */
+
+ if (copy_to_user(arg, &p, sizeof(p)))
+ return -EFAULT;
+ break;
+ }
+
+ case VIDIOCSPICT:
+ {
+ struct video_picture p;
+
+ if (copy_from_user(&p, arg, sizeof(p)))
+ return -EFAULT;
+
+ pwc_set_brightness(pdev, p.brightness);
+ pwc_set_contrast(pdev, p.contrast);
+ pwc_set_gamma(pdev, p.whiteness);
+ pwc_set_saturation(pdev, p.colour);
+ if (p.palette && p.palette != pdev->vpalette) {
+ if (pwc_set_palette(pdev, p.palette) < 0)
+ return -EINVAL;
+ }
+ break;
+ }
+
+ /* Window/size parameters */
+ case VIDIOCGWIN:
+ {
+ struct video_window vw;
+
+ vw.x = 0;
+ vw.y = 0;
+ vw.width = pdev->view.x;
+ vw.height = pdev->view.y;
+ vw.chromakey = 0;
+ vw.flags = (pdev->vframes << PWC_FPS_SHIFT) |
+ (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0);
+
+ if (copy_to_user(arg, &vw, sizeof(vw)))
+ return -EFAULT;
+ break;
+ }
+
+ case VIDIOCSWIN:
+ {
+ struct video_window vw;
+ int fps, snapshot, ret;
+
+ if (copy_from_user(&vw, arg, sizeof(vw)))
+ return -EFAULT;
+
+/*
+ size = pwc_decode_size(pdev, vw.width, vw.height);
+ if (size < 0)
+ return -EINVAL;
+*/
+ fps = (vw.flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT;
+ snapshot = vw.flags & PWC_FPS_SNAPSHOT;
+ if (fps == 0)
+ fps = pdev->vframes;
+ if (pdev->view.x == vw.width && pdev->view.y && fps == pdev->vframes && snapshot == pdev->vsnapshot)
+ return 0;
+ ret = pwc_try_video_mode(pdev, vw.width, vw.height, fps, pdev->vcompression, snapshot);
+ if (ret)
+ return ret;
+ break;
+ }
+
+ /* We don't have overlay support (yet) */
+ case VIDIOCGFBUF:
+ {
+ struct video_buffer vb;
+
+ vb.base = NULL;
+ vb.height = 0;
+ vb.width = 0;
+ vb.depth = 0;
+ vb.bytesperline = 0;
+
+ if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb)))
+ return -EFAULT;
+ break;
+ }
+
+ /* mmap() functions */
+ case VIDIOCGMBUF:
+ {
+ /* Tell the user program how much memory is needed for a mmap() */
+ struct video_mbuf vm;
+ int i;
+
+ memset(&vm, 0, sizeof(vm));
+ vm.size = default_mbufs * pdev->view_max.size * 4;
+ vm.frames = default_mbufs; /* double buffering should be enough */
+ for (i = 0; i < default_mbufs; i++)
+ vm.offsets[i] = i * pdev->view_max.size * 4;
+
+ if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
+ return -EFAULT;
+ break;
+ }
+
+ case VIDIOCMCAPTURE:
+ {
+ /* Start capture into a given image buffer (called 'frame' in video_mmap structure) */
+ struct video_mmap vm;
+
+ if (copy_from_user((void *)&vm, (void *)arg, sizeof(vm)))
+ return -EFAULT;
+ Trace(TRACE_READ, "VIDIOCMCAPTURE: %dx%d, frame %d, format %d\n", vm.width, vm.height, vm.frame, vm.format);
+ if (vm.frame < 0 || vm.frame >= default_mbufs)
+ return -EINVAL;
+
+ /* xawtv is nasty. It probes the available palettes
+ by setting a very small image size and trying
+ various palettes... The driver doesn't support
+ such small images, so I'm working around it.
+ */
+ if (vm.format && vm.format != pdev->vpalette)
+ if (pwc_set_palette(pdev, vm.format) < 0)
+ return -EINVAL;
+
+ if ((vm.width != pdev->view.x || vm.height != pdev->view.y) &&
+ (vm.width >= pdev->view_min.x && vm.height >= pdev->view_min.y)) {
+ int ret;
+
+ Trace(TRACE_OPEN, "VIDIOCMCAPTURE: changing size to please xawtv :-(.\n");
+/*
+ size = pwc_decode_size(pdev, vm.width, vm.height);
+ if (size < 0)
+ return -EINVAL;
+*/
+ ret = pwc_try_video_mode(pdev, vm.width, vm.height, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
+ if (ret)
+ return ret;
+ } /* ... size mismatch */
+
+ /* FIXME: should we lock here? */
+ if (pdev->image_used[vm.frame])
+ return -EBUSY; /* buffer wasn't available. Bummer */
+ pdev->image_used[vm.frame] = 1;
+
+ /* Okay, we're done here. In the SYNC call we wait until a
+ frame comes available, then expand image into the given
+ buffer.
+ In contrast to the CPiA cam the Philips cams deliver a
+ constant stream, almost like a grabber card. Also,
+ we have separate buffers for the rawdata and the image,
+ meaning we can nearly always expand into the requested buffer.
+ */
+ Trace(TRACE_READ, "VIDIOCMCAPTURE done.\n");
+ break;
+ }
+
+ case VIDIOCSYNC:
+ {
+ /* The doc says: "Whenever a buffer is used it should
+ call VIDIOCSYNC to free this frame up and continue."
+
+ The only odd thing about this whole procedure is
+ that MCAPTURE flags the buffer as "in use", and
+ SYNC immediately unmarks it, while it isn't
+ after SYNC that you know that the buffer actually
+ got filled! So you better not start a CAPTURE in
+ the same frame immediately (use double buffering).
+ This is not a problem for this cam, since it has
+ extra intermediate buffers, but a hardware
+ grabber card will then overwrite the buffer
+ you're working on.
+ */
+ int mbuf, ret;
+
+ if (copy_from_user((void *)&mbuf, arg, sizeof(int)))
+ return -EFAULT;
+
+ Trace(TRACE_READ, "VIDIOCSYNC called (%d).\n", mbuf);
+
+ if (mbuf < 0 || mbuf >= default_mbufs)
+ return -EINVAL;
+ /* check if this buffer was requested anyway */
+ if (pdev->image_used[mbuf] == 0)
+ return -EINVAL;
+
+ /* We (re)use the frame-waitqueue here. That may
+ conflict with read(), but any programmer that uses
+ read() and mmap() simultaneously should be given
+ a job at Micro$oft. As janitor.
+ */
+ while (pdev->full_frames == NULL) {
+ interruptible_sleep_on(&pdev->frameq);
+ if (pdev->unplugged) {
+ Debug("VIDIOCSYNC: Device got unplugged.\n");
+ return -EPIPE;
+ }
+ if (signal_pending(current))
+ return -EINTR;
+ }
+ /* The frame is ready. Expand in the image buffer
+ requested by the user. I don't care if you
+ mmap() 5 buffers and request data in this order:
+ buffer 4 2 3 0 1 2 3 0 4 3 1 . . .
+ Grabber hardware may not be so forgiving.
+ */
+ Trace(TRACE_READ, "VIDIOCSYNC: frame ready.\n");
+ pdev->fill_image = mbuf; /* tell in which buffer we want the image to be expanded */
+ /* Decompress, etc */
+ ret = pwc_handle_frame(pdev);
+ pdev->image_used[mbuf] = 0;
+ if (ret)
+ return -EFAULT;
+ break;
+ }
+
+ default:
+ return pwc_ioctl(pdev, cmd, arg);
+ } /* ..switch */
+ return 0;
+}
+
+static int pwc_video_mmap(struct video_device *vdev, const char *adr, unsigned long size)
+{
+ struct pwc_device *pdev;
+ unsigned long start = (unsigned long)adr;
+ unsigned long page, pos;
+
+ Trace(TRACE_READ, "mmap(0x%p, 0x%p, %lu) called.\n", vdev, adr, size);
+ if (vdev == NULL)
+ return -EFAULT;
+ pdev = vdev->priv;
+ if (pdev == NULL)
+ return -EFAULT;
+
+ pos = (unsigned long)pdev->image_data;
+ while (size > 0) {
+ page = kvirt_to_pa(pos);
+ if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED))
+ return -EAGAIN;
+
+ start += PAGE_SIZE;
+ pos += PAGE_SIZE;
+ if (size > PAGE_SIZE)
+ size -= PAGE_SIZE;
+ else
+ size = 0;
+ }
+
+ return 0;
+}
+
+/***************************************************************************/
+/* USB functions */
+
+/* This function gets called when a new device is plugged in or the usb core
+ * is loaded.
+ */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+static void *usb_pwc_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id)
+#else
+static void *usb_pwc_probe(struct usb_device *udev, unsigned int ifnum)
+#endif
+{
+ struct pwc_device *pdev = NULL;
+ struct video_device *vdev;
+ struct usb_config_descriptor *config;
+ struct usb_interface *iface;
+ int vendor_id, product_id, type_id;
+ int i;
+
+ free_mem_leak();
+
+ /* Check if we can handle this device */
+ Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n", udev->descriptor.idVendor, udev->descriptor.idProduct, ifnum);
+
+ /* the interfaces are probed one by one. We are only interested in the
+ video interface (0) now.
+ Interface 1 is the Audio Control, and interface 2 Audio itself.
+ */
+ if (ifnum > 0)
+ return NULL;
+
+ vendor_id = udev->descriptor.idVendor;
+ product_id = udev->descriptor.idProduct;
+
+ if (vendor_id != 0x0471 && vendor_id != 0x069A)
+ return NULL; /* Not Philips or Askey, for sure. */
+
+ if (vendor_id == 0x0471) {
+ switch (product_id) {
+ case 0x0302:
+ Info("Philips PCA645VC USB webcam detected.\n");
+ type_id = 645;
+ break;
+ case 0x0303:
+ Info("Philips PCA646VC USB webcam detected.\n");
+ type_id = 646;
+ break;
+ case 0x0304:
+ Info("Askey VC010 type 2 USB webcam detected.\n");
+ type_id = 646;
+ break;
+ case 0x0307:
+ Info("Philips PCVC675K (Vesta) USB webcam detected.\n");
+ type_id = 675;
+ break;
+ case 0x0308:
+ Info("Philips PCVC680K (Vesta Pro) USB webcam detected.\n");
+ type_id = 680;
+ break;
+ case 0x030C:
+ Info("Philips PCVC690K (Vesta Scanner) USB webcam detected.\n");
+ type_id = 690;
+ break;
+ case 0x0310:
+ Info("Philips PCVC730K (ToUCam Fun) USB webcam detected.\n");
+ type_id = 730;
+ break;
+ case 0x0311:
+ Info("Philips PCVC740K (ToUCam Pro) USB webcam detected.\n");
+ type_id = 740;
+ break;
+ default:
+ return NULL;
+ break;
+ }
+ }
+ if (vendor_id == 0x069A) {
+ switch(product_id) {
+ case 0x0001:
+ Info("Askey VC010 type 1 USB webcam detected.\n");
+ type_id = 645;
+ break;
+ default:
+ return NULL;
+ break;
+ }
+ }
+ if (udev->descriptor.bNumConfigurations > 1)
+ Info("Warning: more than 1 configuration available.\n");
+
+ config = udev->actconfig;
+ iface = &config->interface[0];
+
+ /* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */
+ pdev = kmalloc(sizeof(struct pwc_device), GFP_KERNEL);
+ if (pdev == NULL) {
+ Err("Oops, could not allocate memory for pwc_device.\n");
+ return NULL;
+ }
+ memset(pdev, 0, sizeof(struct pwc_device));
+ pdev->type = type_id;
+ pwc_construct(pdev);
+
+ init_MUTEX(&pdev->modlock);
+ pdev->ptrlock = SPIN_LOCK_UNLOCKED;
+
+ pdev->udev = udev;
+ init_waitqueue_head(&pdev->frameq);
+ init_waitqueue_head(&pdev->pollq);
+ init_waitqueue_head(&pdev->remove_ok);
+ pdev->vcompression = pwc_preferred_compression;
+
+ /* Now hook it up to the video subsystem */
+ vdev = kmalloc(sizeof(struct video_device), GFP_KERNEL);
+ if (vdev == NULL) {
+ Err("Oops, could not allocate memory for video_device.\n");
+ return NULL;
+ }
+ memcpy(vdev, &pwc_template, sizeof(pwc_template));
+ sprintf(vdev->name, "Philips %d webcam", pdev->type);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3)
+ SET_MODULE_OWNER(vdev);
+#endif
+ pdev->vdev = vdev;
+ vdev->priv = pdev;
+
+ pdev->release = udev->descriptor.bcdDevice;
+ Trace(TRACE_PROBE, "Release: %04x\n", pdev->release);
+
+ i = video_register_device(vdev, VFL_TYPE_GRABBER, video_nr);
+ if (i < 0) {
+ Err("Failed to register as video device (%d).\n", i);
+ return NULL;
+ }
+ else {
+ Trace(TRACE_PROBE, "Registered video struct at 0x%p.\n", vdev);
+ Info("Registered as /dev/video%d.\n", vdev->minor & 0x3F);
+ }
+
+#if 0
+ /* Shut down camera now (some people like the LED off) */
+ if (power_save) {
+ Trace(TRACE_PROBE, "Powering down camera");
+ i = pwc_camera_power(pdev, 0);
+ if (i < 0)
+ Info("Failed to power-down the camera (%d)\n", i);
+ }
+#endif
+
+ Trace(TRACE_PROBE, "probe() function returning struct at 0x%p.\n", pdev);
+ return pdev;
+}
+
+/* The user janked out the cable... */
+static void usb_pwc_disconnect(struct usb_device *udev, void *ptr)
+{
+ struct pwc_device *pdev;
+
+ free_mem_leak();
+
+ pdev = (struct pwc_device *)ptr;
+ if (pdev == NULL) {
+ Err("pwc_disconnect() Called without private pointer.\n");
+ return;
+ }
+ if (pdev->udev == NULL) {
+ Err("pwc_disconnect() already called for %p\n", pdev);
+ return;
+ }
+ if (pdev->udev != udev) {
+ Err("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n");
+ return;
+ }
+#ifdef PWC_MAGIC
+ if (pdev->magic != PWC_MAGIC) {
+ Err("pwc_disconnect() Magic number failed. Consult your scrolls and try again.\n");
+ return;
+ }
+#endif
+
+ pdev->unplugged = 1;
+ if (pdev->vdev != NULL) {
+ if (pdev->vopen) {
+ Info("Disconnected while device/video is open!\n");
+
+ /* Wake up any processes that might be waiting for
+ a frame, let them return an error condition
+ */
+ wake_up(&pdev->frameq);
+ wake_up(&pdev->pollq);
+
+ /* Wait until we get a 'go' from _close(). This
+ had a gigantic race condition, since we kfree()
+ stuff here, but we have to wait until close()
+ is finished. */
+
+ Trace(TRACE_PROBE, "Sleeping on remove_ok.\n");
+ sleep_on(&pdev->remove_ok);
+ Trace(TRACE_PROBE, "Done sleeping.\n");
+ set_mem_leak(pdev->vdev);
+ pdev->vdev = NULL;
+ }
+ else {
+ /* Normal disconnect; remove from available devices */
+ Trace(TRACE_PROBE, "Unregistering video device normally.\n");
+ video_unregister_device(pdev->vdev);
+ kfree(pdev->vdev);
+ pdev->vdev = NULL;
+ }
+ }
+ pdev->udev = NULL;
+ kfree(pdev);
+}
+
+
+
+/*
+ * Initialization code & module stuff
+ */
+
+static char *size = NULL;
+static int fps = 0;
+static char *palette = NULL;
+static int fbufs = 0;
+static int mbufs = 0;
+static int trace = -1;
+static int compression = -1;
+
+MODULE_PARM(video_nr, "i");
+MODULE_PARM(size, "s");
+MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga");
+MODULE_PARM(fps, "i");
+MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
+MODULE_PARM(palette, "s");
+MODULE_PARM_DESC(palette, "Initial colour format of images. One of rgb24, bgr24, rgb32, bgr32, yuyv, yuv420, yuv420p");
+MODULE_PARM(fbufs, "i");
+MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve");
+MODULE_PARM(mbufs, "i");
+MODULE_PARM_DESC(mbufs, "Number of external (mmap()ed) image buffers");
+MODULE_PARM(trace, "i");
+MODULE_PARM_DESC(trace, "For debugging purposes");
+MODULE_PARM(power_save, "i");
+MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off");
+MODULE_PARM(compression, "i");
+MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");
+
+MODULE_DESCRIPTION("Philips USB webcam driver");
+MODULE_AUTHOR("Nemosoft Unv. <nemosoft@smcc.demon.nl>");
+
+static int __init usb_pwc_init(void)
+{
+ int s;
+ char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" };
+
+ Info("Philips PCA645/646 + PCVC675/680/690 + PCVC730/740 webcam module version " PWC_VERSION " loaded.\n");
+ Info("Also supports Askey VC010 cam.\n");
+
+ if (fps) {
+ if (fps < 5 || fps > 30) {
+ Err("Framerate out of bounds (5-30).\n");
+ return -EINVAL;
+ }
+ default_fps = fps;
+ Info("Default framerate set to %d.\n", default_fps);
+ }
+
+ if (size) {
+ /* string; try matching with array */
+ for (s = 0; s < PSZ_MAX; s++) {
+ if (!strcmp(sizenames[s], size)) { /* Found! */
+ default_size = s;
+ break;
+ }
+ }
+ if (s == PSZ_MAX) {
+ Err("Size not recognized; try size=[sqcif | qsif | qcif | sif | cif | vga].\n");
+ return -EINVAL;
+ }
+ Info("Default image size set to %s [%dx%d].\n", sizenames[default_size], pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y);
+ }
+ if (palette) {
+ /* Determine default palette */
+ if (!strcmp(palette, "bgr24"))
+ default_palette = VIDEO_PALETTE_RGB24;
+ else if (!strcmp(palette, "rgb24"))
+ default_palette = VIDEO_PALETTE_RGB24 | 0x80;
+ else if (!strcmp(palette, "bgr32"))
+ default_palette = VIDEO_PALETTE_RGB32;
+ else if (!strcmp(palette, "rgb32"))
+ default_palette = VIDEO_PALETTE_RGB32 | 0x80;
+ else if (!strcmp(palette, "yuyv"))
+ default_palette = VIDEO_PALETTE_YUYV;
+ else if (!strcmp(palette, "yuv420"))
+ default_palette = VIDEO_PALETTE_YUV420;
+ else if (!strcmp(palette, "yuv420p"))
+ default_palette = VIDEO_PALETTE_YUV420P;
+ else {
+ Err("Palette not recognized: try palette=[bgr24 | rgb24 | bgr32 | rgb32 | yuyv | yuv420 | yuv420p].\n");
+ return -EINVAL;
+ }
+ Info("Default palette set to %d.\n", default_palette);
+ }
+ if (mbufs) {
+ if (mbufs < 1 || mbufs > MAX_IMAGES) {
+ Err("Illegal number of mmap() buffers; use a number between 1 and %d.\n", MAX_IMAGES);
+ return -EINVAL;
+ }
+ default_mbufs = mbufs;
+ Info("Number of image buffers set to %d.\n", default_mbufs);
+ }
+ if (fbufs) {
+ if (fbufs < 2 || fbufs > MAX_FRAMES) {
+ Err("Illegal number of frame buffers; use a number between 2 and %d.\n", MAX_FRAMES);
+ return -EINVAL;
+ }
+ default_fbufs = fbufs;
+ Info("Number of frame buffers set to %d.\n", default_fbufs);
+ }
+ if (trace >= 0) {
+ Info("Trace options: 0x%04x\n", trace);
+ pwc_trace = trace;
+ }
+ if (compression >= 0) {
+ if (compression > 3) {
+ Err("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n");
+ return -EINVAL;
+ }
+ pwc_preferred_compression = compression;
+ Info("Preferred compression set to %d.\n", pwc_preferred_compression);
+ }
+ if (power_save)
+ Info("Enabling power save on open/close.\n");
+
+ init_MUTEX(&mem_lock);
+ Trace(TRACE_PROBE, "Registering driver at address 0x%p.\n", &pwc_driver);
+ return usb_register(&pwc_driver);
+}
+
+static void __exit usb_pwc_exit(void)
+{
+ free_mem_leak();
+ Trace(TRACE_MODULE, "Deregistering driver.\n");
+ usb_deregister(&pwc_driver);
+ Info("Philips webcam module removed.\n");
+}
+
+module_init(usb_pwc_init);
+module_exit(usb_pwc_exit);
+
--- /dev/null
+/* (C) 2001 Nemosoft Unv. webcam@smcc.demon.nl
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef PWC_IOCTL_H
+#define PWC_IOCTL_H
+
+/* These are private ioctl() commands, specific for the Philips webcams.
+ They contain functions not found in other webcams, and settings not
+ specified in the Video4Linux API.
+
+ The #define names are built up like follows:
+ VIDIOC VIDeo IOCtl prefix
+ PWC Philps WebCam
+ G optional: Get
+ S optional: Set
+ ... the function
+ */
+
+
+
+
+/* The frame rate is encoded in the video_window.flags parameter using
+ the upper 16 bits, since some flags are defined nowadays. The following
+ defines provide a mask and shift to filter out this value.
+
+ In 'Snapshot' mode the camera freezes its automatic exposure and colour
+ balance controls.
+ */
+#define PWC_FPS_SHIFT 16
+#define PWC_FPS_MASK 0x00FF0000
+#define PWC_FPS_FRMASK 0x003F0000
+#define PWC_FPS_SNAPSHOT 0x00400000
+
+
+ /* Restore user settings */
+#define VIDIOCPWCRUSER _IO('v', 192)
+ /* Save user settings */
+#define VIDIOCPWCSUSER _IO('v', 193)
+ /* Restore factory settings */
+#define VIDIOCPWCFACTORY _IO('v', 194)
+
+ /* You can manipulate the compression factor. A compression preference of 0
+ means use uncompressed modes when available; 1 is low compression, 2 is
+ medium and 3 is high compression preferred. Of course, the higher the
+ compression, the lower the bandwidth used but more chance of artefacts
+ in the image. The driver automatically chooses a higher compression when
+ the preferred mode is not available.
+ */
+ /* Set preferred compression quality (0 = uncompressed, 3 = highest compression) */
+#define VIDIOCPWCSCQUAL _IOW('v', 195, int)
+ /* Get preferred compression quality */
+#define VIDIOCPWCGCQUAL _IOR('v', 195, int)
+
+ /* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */
+#define VIDIOCPWCSAGC _IOW('v', 200, int)
+ /* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */
+#define VIDIOCPWCGAGC _IOR('v', 200, int)
+ /* Set shutter speed; int < 0 = auto; >= 0 = fixed, range 0..65535 */
+#define VIDIOCPWCSSHUTTER _IOW('v', 201, int)
+
+#endif
--- /dev/null
+/* Linux driver for Philips webcam
+ Various miscellaneous functions and tables.
+ (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <linux/slab.h>
+
+#include "pwc.h"
+
+struct pwc_coord pwc_image_sizes[PSZ_MAX] =
+{
+ { 128, 96, 0 },
+ { 160, 120, 0 },
+ { 176, 144, 0 },
+ { 320, 240, 0 },
+ { 352, 288, 0 },
+ { 640, 480, 0 },
+};
+
+/* x,y -> PSZ_ */
+int pwc_decode_size(struct pwc_device *pdev, int width, int height)
+{
+ int i, find;
+
+ /* Make sure we don't go beyond our max size */
+ if (width > pdev->view_max.x || height > pdev->view_max.y)
+ return -1;
+ /* Find the largest size supported by the camera that fits into the
+ requested size.
+ */
+ find = -1;
+ for (i = 0; i < PSZ_MAX; i++) {
+ if (pdev->image_mask & (1 << i)) {
+ if (pwc_image_sizes[i].x <= width && pwc_image_sizes[i].y <= height)
+ find = i;
+ }
+ }
+ return find;
+}
+
+/* initialize variables depending on type */
+void pwc_construct(struct pwc_device *pdev)
+{
+ switch(pdev->type) {
+ case 645:
+ case 646:
+ pdev->view_min.x = 128;
+ pdev->view_min.y = 96;
+ pdev->view_max.x = 352;
+ pdev->view_max.y = 288;
+ pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QCIF | 1 << PSZ_CIF;
+ pdev->vcinterface = 2;
+ pdev->vendpoint = 4;
+ pdev->frame_header_size = 0;
+ pdev->frame_trailer_size = 0;
+ break;
+ case 675:
+ case 680:
+ case 690:
+ pdev->view_min.x = 128;
+ pdev->view_min.y = 96;
+ pdev->view_max.x = 640;
+ pdev->view_max.y = 480;
+ pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF | 1 << PSZ_VGA;
+ pdev->vcinterface = 3;
+ pdev->vendpoint = 4;
+ pdev->frame_header_size = 0;
+ pdev->frame_trailer_size = 0;
+ break;
+ case 730:
+ case 740:
+ pdev->view_min.x = 160;
+ pdev->view_min.y = 120;
+ pdev->view_max.x = 640;
+ pdev->view_max.y = 480;
+ pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA;
+ pdev->vcinterface = 3;
+ pdev->vendpoint = 5;
+ pdev->frame_header_size = TOUCAM_HEADER_SIZE;
+ pdev->frame_trailer_size = TOUCAM_TRAILER_SIZE;
+ break;
+ }
+ pdev->view_min.size = pdev->view_min.x * pdev->view_min.y;
+ pdev->view_max.size = pdev->view_max.x * pdev->view_max.y;
+}
+
+
--- /dev/null
+/* Linux driver for Philips webcam
+ Decompression frontend.
+ (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+/*
+ This is where the decompression routines register and unregister
+ themselves. It also has a decompressor wrapper function.
+*/
+
+#include "ccvt.h"
+#include "vcvt.h"
+#include "pwc.h"
+#include "pwc-uncompress.h"
+
+
+/* This contains a list of all registered decompressors */
+LIST_HEAD(pwc_decompressor_list);
+
+/* Should the pwc_decompress structure ever change, we increase the
+ version number so that we don't get nasty surprises, or can
+ dynamicly adjust our structure.
+ */
+const int pwc_decompressor_version = PWC_MAJOR;
+
+/* Add decompressor to list, ignoring duplicates */
+void pwc_register_decompressor(struct pwc_decompressor *pwcd)
+{
+ if (pwc_find_decompressor(pwcd->type) == NULL) {
+ Debug("Adding decompressor for model %d.\n", pwcd->type);
+ list_add_tail(&pwcd->pwcd_list, &pwc_decompressor_list);
+ }
+}
+
+/* Remove decompressor from list */
+void pwc_unregister_decompressor(int type)
+{
+ struct pwc_decompressor *find;
+
+ find = pwc_find_decompressor(type);
+ if (find != NULL) {
+ Debug("Removing decompressor for model %d.\n", type);
+ list_del(&find->pwcd_list);
+ }
+}
+
+/* Find decompressor in list */
+struct pwc_decompressor *pwc_find_decompressor(int type)
+{
+ struct list_head *tmp;
+ struct pwc_decompressor *pwcd;
+
+ list_for_each(tmp, &pwc_decompressor_list) {
+ pwcd = list_entry(tmp, struct pwc_decompressor, pwcd_list);
+ if (pwcd->type == type)
+ return pwcd;
+ }
+ return NULL;
+}
+
+
+
+int pwc_decompress(struct pwc_device *pdev)
+{
+ struct pwc_frame_buf *fbuf;
+ int n, l, c, w;
+ void *yuv, *image, *dst;
+
+ if (pdev == NULL)
+ return -EFAULT;
+#if defined(__KERNEL__) && defined(PWC_MAGIC)
+ if (pdev->magic != PWC_MAGIC) {
+ Err("pwc_decompress(): magic failed.\n");
+ return -EFAULT;
+ }
+#endif
+
+ fbuf = pdev->read_frame;
+ if (fbuf == NULL)
+ return -EFAULT;
+ image = pdev->image_ptr[pdev->fill_image];
+ if (!image)
+ return -EFAULT;
+
+#if PWC_DEBUG
+ /* This is a quickie */
+ if (pdev->vpalette == VIDEO_PALETTE_RAW) {
+ memcpy(image, fbuf->data, pdev->frame_size);
+ return 0;
+ }
+#endif
+
+ /* Compressed formats are decompressed in decompress_buffer, then
+ * transformed into the desired format
+ */
+ yuv = pdev->decompress_buffer;
+ n = 0;
+ if (pdev->vbandlength == 0) { /* uncompressed */
+ yuv = fbuf->data + pdev->frame_header_size; /* Skip header */
+ }
+ else {
+ if (pdev->decompressor)
+ n = pdev->decompressor->decompress(pdev->decompress_data, pdev->image.x, pdev->image.y, pdev->vbandlength, yuv, fbuf->data + pdev->frame_header_size, 0);
+ else
+ n = -ENXIO; /* No such device or address: missing decompressor */
+ }
+ if (n < 0) {
+ Err("Error in decompression engine: %d\n", n);
+ return n;
+ }
+
+ /* At this point 'yuv' always points to the uncompressed, non-scaled YUV420I data */
+ if (pdev->image.x == pdev->view.x && pdev->image.y == pdev->view.y) {
+ /* Sizes matches; make it quick */
+ switch(pdev->vpalette) {
+ case VIDEO_PALETTE_RGB24 | 0x80:
+ ccvt_420i_rgb24(pdev->image.x, pdev->image.y, yuv, image);
+ break;
+ case VIDEO_PALETTE_RGB24:
+ ccvt_420i_bgr24(pdev->image.x, pdev->image.y, yuv, image);
+ break;
+ case VIDEO_PALETTE_RGB32 | 0x80:
+ ccvt_420i_rgb32(pdev->image.x, pdev->image.y, yuv, image);
+ break;
+ case VIDEO_PALETTE_RGB32:
+ ccvt_420i_bgr32(pdev->image.x, pdev->image.y, yuv, image);
+ break;
+ case VIDEO_PALETTE_YUYV:
+ case VIDEO_PALETTE_YUV422:
+ ccvt_420i_yuyv(pdev->image.x, pdev->image.y, yuv, image);
+ break;
+ case VIDEO_PALETTE_YUV420:
+ memcpy(image, yuv, pdev->image.size);
+ break;
+ case VIDEO_PALETTE_YUV420P:
+ n = pdev->image.x * pdev->image.y;
+ ccvt_420i_420p(pdev->image.x, pdev->image.y, yuv, image, image + n, image + n + (n / 4));
+ break;
+ }
+ }
+ else {
+ /* Size mismatch; use viewport conversion routines */
+ switch(pdev->vpalette) {
+ case VIDEO_PALETTE_RGB24 | 0x80:
+ vcvt_420i_rgb24(pdev->image.x, pdev->image.y, pdev->view.x, yuv, image + pdev->offset.size);
+ break;
+ case VIDEO_PALETTE_RGB24:
+ vcvt_420i_bgr24(pdev->image.x, pdev->image.y, pdev->view.x, yuv, image + pdev->offset.size);
+ break;
+ case VIDEO_PALETTE_RGB32 | 0x80:
+ vcvt_420i_rgb32(pdev->image.x, pdev->image.y, pdev->view.x, yuv, image + pdev->offset.size);
+ break;
+ case VIDEO_PALETTE_RGB32:
+ vcvt_420i_bgr32(pdev->image.x, pdev->image.y, pdev->view.x, yuv, image + pdev->offset.size);
+ break;
+ case VIDEO_PALETTE_YUYV:
+ case VIDEO_PALETTE_YUV422:
+ vcvt_420i_yuyv(pdev->image.x, pdev->image.y, pdev->view.x, yuv, image + pdev->offset.size);
+ break;
+ case VIDEO_PALETTE_YUV420:
+ dst = image + pdev->offset.size;
+ w = pdev->view.x * 6;
+ c = pdev->image.x * 6;
+ for (l = 0; l < pdev->image.y; l++) {
+ memcpy(dst, yuv, c);
+ dst += w;
+ yuv += c;
+ }
+ break;
+ case VIDEO_PALETTE_YUV420P:
+ n = pdev->view.x * pdev->view.y;
+ vcvt_420i_420p(pdev->image.x, pdev->image.y, pdev->view.x, yuv,
+ image + pdev->offset.size,
+ image + n + pdev->offset.size / 4,
+ image + n + n / 4 + pdev->offset.size / 4);
+ break;
+ }
+ }
+ return 0;
+}
+
+
+/* wrapper functions.
+ By using these wrapper functions and exporting them with no VERSIONING,
+ I can be sure the pwcx.o module will load on all systems.
+*/
+
+void *pwc_kmalloc(size_t size, int priority)
+{
+ return kmalloc(size, priority);
+}
+
+void pwc_kfree(const void *pointer)
+{
+ kfree(pointer);
+}
+
+/* Make sure these functions are available for the decompressor plugin
+ both when this code is compiled into the kernel or as as module.
+ We are using unversioned names!
+ */
+EXPORT_SYMBOL_NOVERS(pwc_decompressor_version);
+EXPORT_SYMBOL_NOVERS(pwc_register_decompressor);
+EXPORT_SYMBOL_NOVERS(pwc_unregister_decompressor);
+EXPORT_SYMBOL_NOVERS(pwc_find_decompressor);
+EXPORT_SYMBOL_NOVERS(pwc_kmalloc);
+EXPORT_SYMBOL_NOVERS(pwc_kfree);
--- /dev/null
+/* (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef PWC_DEC_H
+#define PWC_DEC_H
+
+#include <linux/config.h>
+
+#include <linux/list.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The decompressor structure.
+ Every type of decompressor registers itself with the main module.
+ When a device is opened, it looks up the correct compressor, and
+ uses that when a compressed video mode is requested.
+ */
+struct pwc_decompressor
+{
+ int type; /* type of camera (645, 646, etc) */
+ int (* init)(int release, void *buffer, void **data); /* Initialization routine; should be called after each set_video_mode */
+ void (* exit)(void **data); /* Cleanup routine */
+ int (* decompress)(void *data, int width, int height, int bandlength, void *dst, void *src, int planar); /* The decompression routine itself */
+ void (* lock)(void); /* make sure module cannot be unloaded */
+ void (* unlock)(void); /* release lock on module */
+
+ struct list_head pwcd_list;
+};
+
+
+/* Our structure version number. Is set to the version number major */
+extern const int pwc_decompressor_version;
+
+/* Adds decompressor to list, based on its 'type' field (which matches the 'type' field in pwc_device; ignores any double requests */
+extern void pwc_register_decompressor(struct pwc_decompressor *pwcd);
+/* Removes decompressor, based on the type number */
+extern void pwc_unregister_decompressor(int type);
+/* Returns pointer to decompressor struct, or NULL if it doesn't exist */
+extern struct pwc_decompressor *pwc_find_decompressor(int type);
+
+#ifdef CONFIG_USB_PWCX
+/* If the decompressor is compiled in, we must call these manually */
+extern int usb_pwcx_init(void);
+extern void usb_pwcx_exit(void);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/* (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef PWC_H
+#define PWC_H
+
+#ifdef __KERNEL__
+#include <asm/semaphore.h>
+#include <asm/errno.h>
+#include <linux/usb.h>
+#include <linux/spinlock.h>
+#else
+#include <errno.h>
+#include <sys/types.h>
+
+#define printk printf
+#define KERN_DEBUG "<7>"
+#define KERN_INFO "<6>"
+#define KERN_ERR "<3>"
+#endif
+
+#include <linux/config.h>
+#include <linux/videodev.h>
+#include <linux/wait.h>
+
+/* Defines and structures for the Philips webcam */
+/* Used for checking memory corruption/pointer validation */
+#define PWC_MAGIC 0x89DC10ABUL
+#undef PWC_MAGIC
+
+/* Debugging info on/off */
+#define PWC_DEBUG 0
+
+#define TRACE_MODULE 0x0001
+#define TRACE_PROBE 0x0002
+#define TRACE_OPEN 0x0004
+#define TRACE_READ 0x0008
+#define TRACE_MEMORY 0x0010
+#define TRACE_FLOW 0x0020
+#define TRACE_SIZE 0x0040
+#define TRACE_SEQUENCE 0x1000
+
+#define Trace(R, A...) if (pwc_trace & R) printk(KERN_DEBUG PWC_NAME " " ##A)
+#define Debug(A...) printk(KERN_DEBUG PWC_NAME " " ##A)
+#define Info(A...) printk(KERN_INFO PWC_NAME " " ##A)
+#define Err(A...) printk(KERN_ERR PWC_NAME " " ##A)
+
+
+/* Defines for ToUCam cameras */
+#define TOUCAM_HEADER_SIZE 8
+#define TOUCAM_TRAILER_SIZE 4
+
+/* Version block */
+#define PWC_MAJOR 7
+#define PWC_MINOR 1
+#define PWC_RELEASE "7.1"
+
+#if defined(CONFIG_ARM)
+ #define PWC_PROCESSOR "ARM"
+#endif
+#if defined(CONFIG_M686)
+ #define PWC_PROCESSOR "PPro"
+#endif
+#if !defined(PWC_PROCESSOR)
+ #define PWC_PROCESSOR "P5"
+#endif
+
+#if defined(__SMP__) || defined(CONFIG_SMP)
+#define PWC_SMP "(SMP)"
+#else
+#define PWC_SMP "(UP)"
+#endif
+
+#define PWC_VERSION PWC_RELEASE " " PWC_PROCESSOR " " PWC_SMP
+#define PWC_NAME "pwc"
+
+/* Turn certain features on/off */
+#define PWC_INT_PIPE 0
+
+/* Ignore errors in the first N frames, to allow for startup delays */
+#define FRAME_LOWMARK 5
+
+/* Size and number of buffers for the ISO pipe. */
+#define MAX_ISO_BUFS 2
+#define ISO_FRAMES_PER_DESC 10
+#define ISO_MAX_FRAME_SIZE 960
+#define ISO_BUFFER_SIZE (ISO_FRAMES_PER_DESC * ISO_MAX_FRAME_SIZE)
+
+/* Frame buffers: contains compressed or uncompressed video data. */
+#define MAX_FRAMES 5
+/* Maximum size after decompression is 640x480 YUV data, 1.5 * 640 * 480 */
+#define FRAME_SIZE (460800 + TOUCAM_HEADER_SIZE + TOUCAM_TRAILER_SIZE)
+
+/* Absolute maximum number of buffers available for mmap() */
+#define MAX_IMAGES 4
+
+struct pwc_coord
+{
+ int x, y; /* guess what */
+ int size; /* size, or offset */
+};
+
+/* The following structures were based on cpia.h. Why reinvent the wheel? :-) */
+struct pwc_iso_buf
+{
+ void *data;
+ int length;
+ int read;
+#ifdef __KERNEL__
+ purb_t urb;
+#endif
+};
+
+/* intermediate buffers with raw data from the USB cam */
+struct pwc_frame_buf
+{
+ void *data;
+ volatile int filled; /* number of bytes filled */
+ struct pwc_frame_buf *next; /* list */
+#if PWC_DEBUG
+ int sequence; /* Sequence number */
+#endif
+};
+
+struct pwc_device
+{
+#ifdef PWC_MAGIC
+ int magic;
+#endif
+ /* Pointer to our usb_device */
+ struct usb_device *udev;
+
+ int type; /* type of cam (645, 646, 675, 680, 690) */
+ int release; /* release number */
+ int unplugged; /* set when the plug is pulled */
+ int usb_init; /* set when the cam has been initialized over USB */
+
+ /*** Video data ***/
+ int vopen; /* flag */
+ struct video_device *vdev;
+ int vendpoint; /* video isoc endpoint */
+ int vcinterface; /* video control interface */
+ int valternate; /* alternate interface needed */
+ int vframes, vsize; /* frames-per-second & size (see PSZ_*) */
+ int vpalette; /* YUV, RGB24, RGB32, etc */
+ int vframe_count; /* received frames */
+ int vframes_dumped; /* counter for dumped frames */
+ int vframes_error; /* frames received in error */
+ int vmax_packet_size; /* USB maxpacket size */
+ int vlast_packet_size; /* for frame synchronisation */
+ int vcompression; /* desired compression factor */
+ int vbandlength; /* compressed band length; 0 is uncompressed */
+ char vsnapshot; /* snapshot mode */
+ char vsync; /* used by isoc handler */
+
+ /* The image acquisition requires 3 to 5 steps:
+ 1. data is gathered in short packets from the USB controller
+ 2. data is synchronized and packed into a frame buffer
+ 3. in case data is compressed, decompress it into a separate buffer
+ 4. data is optionally converted to RGB/YUV
+ 5. data is transfered to the user process
+
+ Note that MAX_ISO_BUFS != MAX_FRAMES != MAX_IMAGES....
+ We have in effect a back-to-back-double-buffer system.
+ */
+ /* 1: isoc */
+ struct pwc_iso_buf sbuf[MAX_ISO_BUFS];
+ char iso_init;
+
+ /* 2: frame */
+ struct pwc_frame_buf *fbuf;
+ struct pwc_frame_buf *empty_frames, *empty_frames_tail;
+ struct pwc_frame_buf *full_frames, *full_frames_tail;
+ struct pwc_frame_buf *read_frame;
+ struct pwc_frame_buf *fill_frame;
+ int frame_size;
+ int frame_header_size, frame_trailer_size;
+ int drop_frames;
+#if PWC_DEBUG
+ int sequence; /* Debugging aid */
+#endif
+
+ /* 3: decompression */
+ struct pwc_decompressor *decompressor; /* function block with decompression routines */
+ void *decompress_data; /* private data for decompression engine */
+ void *decompress_buffer; /* decompressed data */
+
+ /* 4: image */
+ /* We have an 'image' and a 'view', where 'image' is the fixed-size image
+ as delivered by the camera, and 'view' is the size requested by the
+ program. The camera image is centered in this viewport, laced with
+ a gray or black border. view_min <= image <= view <= view_max;
+ */
+ int image_mask; /* bitmask of supported sizes */
+ struct pwc_coord view_min, view_max; /* minimum and maximum sizes */
+ struct pwc_coord image, view; /* image and viewport size */
+ struct pwc_coord offset; /* offset within the viewport */
+
+ void *image_data; /* total buffer, which is subdivided into ... */
+ void *image_ptr[MAX_IMAGES]; /* ...several images... */
+ int fill_image; /* ...which are rotated. */
+ int image_read_pos; /* In case we read data in pieces, keep track of were we are in the imagebuffer */
+ int image_used[MAX_IMAGES]; /* For MCAPTURE and SYNC */
+
+#ifdef __KERNEL__
+ /* Kernel specific structures. These were once moved to the end
+ of the structure and padded with bytes after I found out
+ some of these have different sizes in different kernel versions.
+ But since this is now a source release, I don't have this problem
+ anymore.
+
+ Fortunately none of these structures are needed in the pwcx module.
+ */
+ struct semaphore modlock; /* to prevent races in video_open(), etc */
+ spinlock_t ptrlock; /* for manipulating the buffer pointers */
+
+ /*** Misc. data ***/
+ wait_queue_head_t frameq; /* When waiting for a frame to finish... */
+ wait_queue_head_t pollq; /* poll() has it's own waitqueue */
+ wait_queue_head_t remove_ok; /* When we got hot unplugged, we have to avoid a few race conditions */
+#if PWC_INT_PIPE
+ void *usb_int_handler; /* for the interrupt endpoint */
+#endif
+#endif
+};
+
+/* Enumeration of image sizes */
+#define PSZ_SQCIF 0x00
+#define PSZ_QSIF 0x01
+#define PSZ_QCIF 0x02
+#define PSZ_SIF 0x03
+#define PSZ_CIF 0x04
+#define PSZ_VGA 0x05
+#define PSZ_MAX 6
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Global variables */
+extern int pwc_trace;
+extern int pwc_preferred_compression;
+
+/** functions in pwc-if.c */
+int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot);
+
+/** Functions in pwc-misc.c */
+/* sizes in pixels */
+extern struct pwc_coord pwc_image_sizes[PSZ_MAX];
+
+int pwc_decode_size(struct pwc_device *pdev, int width, int height);
+void pwc_construct(struct pwc_device *pdev);
+
+/** Functions in pwc-ctrl.c */
+/* Request a certain video mode. Returns < 0 if not possible */
+extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot);
+/* Calculate the number of bytes per image (not frame) */
+extern void pwc_set_image_buffer_size(struct pwc_device *pdev);
+
+/* Various controls; should be obvious. Value 0..65535, or < 0 on error */
+extern int pwc_get_brightness(struct pwc_device *pdev);
+extern int pwc_set_brightness(struct pwc_device *pdev, int value);
+extern int pwc_get_contrast(struct pwc_device *pdev);
+extern int pwc_set_contrast(struct pwc_device *pdev, int value);
+extern int pwc_get_gamma(struct pwc_device *pdev);
+extern int pwc_set_gamma(struct pwc_device *pdev, int value);
+extern int pwc_get_saturation(struct pwc_device *pdev);
+extern int pwc_set_saturation(struct pwc_device *pdev, int value);
+
+/* Power down or up the camera; not supported by all models */
+extern int pwc_camera_power(struct pwc_device *pdev, int power);
+
+/* Private ioctl()s; see pwc-ioctl.h */
+extern int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg);
+
+
+/** pwc-uncompress.c */
+/* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */
+extern int pwc_decompress(struct pwc_device *pdev);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
* Based upon mouse.c (Brad Keryan) and printer.c (Michael Gee).
*
* */
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include "rio500_usb.h"
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Cesar Miquel <miquel@df.uba.ar>"
+#define DRIVER_DESC "USB Rio 500 driver"
+
#define RIO_MINOR 64
/* stall/wait timeout for rio */
if (usb_register(&rio_driver) < 0)
return -1;
- info("USB Rio support registered.");
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
+
return 0;
}
module_init(usb_rio_init);
module_exit(usb_rio_cleanup);
-MODULE_AUTHOR("Cesar Miquel <miquel@df.uba.ar>");
-MODULE_DESCRIPTION("USB Rio 500 driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
* framework in, but haven't analyzed the "tty_flip" interface yet.
* -- Add support for flush commands
* -- Add everything that is missing :)
+ *
+ * 08-Apr-2001 gb
+ * - Identify version on module load.
*
* 12-Mar-2001 gkh
* - Added support for the GoHubs GO-COM232 device which is the same as the
#include "usb-serial.h"
#include "belkin_sa.h"
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "William Greathouse <wgreathouse@smva.com>"
+#define DRIVER_DESC "USB Belkin Serial converter driver"
+
/* function prototypes for a Belkin USB Serial Adapter F5U103 */
static int belkin_sa_startup (struct usb_serial *serial);
static void belkin_sa_shutdown (struct usb_serial *serial);
usb_serial_register (&belkin_old_device);
usb_serial_register (&peracom_device);
usb_serial_register (&gocom232_device);
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
return 0;
}
module_init (belkin_sa_init);
module_exit (belkin_sa_exit);
-MODULE_DESCRIPTION("USB Belkin Serial converter driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_PARM(debug, "i");
MODULE_PARM_DESC(debug, "Debug enabled or not");
*
* Peter Berger (pberger@brimson.com)
* Al Borchers (borchers@steinerpoint.com)
+*
+* (04/08/2001) gb
+* Identify version on module load.
*
* (11/01/2000) Adam J. Richter
* usb_device_id table support
/* Defines */
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.80.1.2"
+#define DRIVER_AUTHOR "Peter Berger <pberger@brimson.com>, Al Borchers <borchers@steinerpoint.com>"
+#define DRIVER_DESC "Digi AccelePort USB-2/USB-4 Serial Converter driver"
+
/* port output buffer length -- must be <= transfer buffer length - 2 */
/* so we can be sure to send the full buffer in one urb */
#define DIGI_OUT_BUF_SIZE 8
{
usb_serial_register (&digi_acceleport_2_device);
usb_serial_register (&digi_acceleport_4_device);
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
return 0;
}
module_exit(digi_exit);
-MODULE_AUTHOR("Peter Berger <pberger@brimson.com>, Al Borchers <borchers@steinerpoint.com>");
-MODULE_DESCRIPTION("Digi AccelePort USB-2/USB-4 Serial Converter driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_PARM(debug, "i");
MODULE_PARM_DESC(debug, "Debug enabled or not");
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
+ * (04/08/2001) gb
+ * Identify version on module load.
+ *
* (01/22/2001) gb
* Added write_room() and chars_in_buffer() support.
*
#include "usb-serial.h"
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Gary Brubaker <xavyer@ix.netcom.com>"
+#define DRIVER_DESC "USB Empeg Mark I/II Driver"
+
#define EMPEG_VENDOR_ID 0x084f
#define EMPEG_PRODUCT_ID 0x0001
}
}
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
+
return 0;
}
module_init(empeg_init);
module_exit(empeg_exit);
-MODULE_AUTHOR("Gary Brubaker <xavyer@ix.netcom.com>");
-MODULE_DESCRIPTION("USB Empeg Mark I/II Driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_PARM(debug, "i");
MODULE_PARM_DESC(debug, "Debug enabled or not");
*
* See http://reality.sgi.com/bryder_wellington/ftdi_sio for upto date testing info
* and extra documentation
+ *
+ * (04/08/2001) gb
+ * Identify version on module load.
*
* (12/3/2000) Bill Ryder
* Added support for 8U232AM device.
#include "ftdi_sio.h"
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>"
+#define DRIVER_DESC "USB FTDI RS232 Converters Driver"
+
static __devinitdata struct usb_device_id id_table_sio [] = {
{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
{ } /* Terminating entry */
dbg(__FUNCTION__);
usb_serial_register (&ftdi_sio_device);
usb_serial_register (&ftdi_8U232AM_device);
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
return 0;
}
module_init(ftdi_sio_init);
module_exit(ftdi_sio_exit);
-MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>");
-MODULE_DESCRIPTION("USB FTDI RS232 converters driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_PARM(debug, "i");
MODULE_PARM_DESC(debug, "Debug enabled or not");
* Edgeport/8i
*
* Version history:
+ *
+ * (04/08/2001) gb
+ * - Identify version on module load.
*
* 2.0 2001_03_05 greg kroah-hartman
* - reworked entire driver to fit properly in with the other usb-serial
#include "io_ionsp.h" /* info for the iosp messages */
#include "io_16654.h" /* 16654 UART defines */
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v2.0.0"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli"
+#define DRIVER_DESC "Edgeport USB Serial Driver"
+
/* First, the latest boot code - for first generation edgeports */
#define IMAGE_ARRAY_NAME BootCodeImage_GEN1
#define IMAGE_VERSION_NAME BootCodeImageVersion_GEN1
#include "io_fw_down2.h" /* Define array OperationalCodeImage[] */
-/* Module information */
-MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli");
-MODULE_DESCRIPTION("Edgeport USB Serial Driver");
-
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-
#define MAX_NAME_LEN 64
usb_serial_register (&edgeport_16dual_device);
usb_serial_register (&edgeport_compat_id_device);
usb_serial_register (&edgeport_8i_device);
-
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
return 0;
}
module_init(edgeport_init);
module_exit(edgeport_exit);
+/* Module information */
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
open source projects.
Change History
+ (04/08/2001) gb
+ Identify version on module load.
+
(11/01/2000) Adam J. Richter
usb_device_id table support.
#include "usb-serial.h"
#include "keyspan.h"
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Hugh Blemings <hugh@linuxcare.com>"
+#define DRIVER_DESC "Keyspan USB to Serial Converter Driver"
+
#define INSTAT_BUFLEN 32
#define GLOCONT_BUFLEN 64
usb_serial_register (&keyspan_usa28_device);
usb_serial_register (&keyspan_usa28x_device);
usb_serial_register (&keyspan_usa49w_device);
+
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
+
return 0;
}
}
}
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
MODULE_PARM(debug, "i");
MODULE_PARM_DESC(debug, "Debug enabled or not");
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
+ * (04/08/2001) gb
+ * Identify version on module load.
+ *
* (11/01/2000) Adam J. Richter
* usb_device_id table support
*
#include "keyspan_pda_fw.h"
#include "usb-serial.h"
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Brian Warner <warner@lothar.com>"
+#define DRIVER_DESC "USB Keyspan PDA Converter driver"
+
struct keyspan_pda_private {
int tx_room;
int tx_throttled;
{
usb_serial_register (&keyspan_pda_fake_device);
usb_serial_register (&keyspan_pda_device);
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
return 0;
}
module_init(keyspan_pda_init);
module_exit(keyspan_pda_exit);
-MODULE_AUTHOR("Brian Warner <warner@lothar.com>");
-MODULE_DESCRIPTION("USB Keyspan PDA Converter driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_PARM(debug, "i");
MODULE_PARM_DESC(debug, "Debug enabled or not");
* Basic tests have been performed with minicom/zmodem transfers and
* modem dialing under Linux 2.4.0-test10 (for me it works fine).
*
+ * 08-Apr-2001 gb
+ * - Identify version on module load.
+ *
* 06-Jan-2001 Cornel Ciocirlan
* - Added support for Sitecom U232-P25 model (Product Id 0x0230)
* - Added support for D-Link DU-H3SP USB BAY (Product Id 0x0200)
#include "mct_u232.h"
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
+#define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver"
+
/*
* Some not properly written applications do not handle the return code of
* write() correctly. This can result in character losses. A work-a-round
usb_serial_register (&mct_u232_device);
usb_serial_register (&mct_u232_sitecom_device);
usb_serial_register (&mct_u232_du_h3sp_device);
-
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
return 0;
}
module_init (mct_u232_init);
module_exit(mct_u232_exit);
-MODULE_AUTHOR("Wolfgang Grandegger <wolfgang@ces.ch>");
-MODULE_DESCRIPTION("Magic Control Technology USB-RS232 converter driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
#ifdef FIX_WRITE_RETURN_CODE_PROBLEM
MODULE_PARM(write_blocking, "i");
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
* Please report both successes and troubles to the author at omninet@kroah.com
+ *
+ * (04/08/2001) gb
+ * Identify version on module load.
*
* (11/01/2000) Adam J. Richter
* usb_device_id table support
#include "usb-serial.h"
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Anonymous"
+#define DRIVER_DESC "USB ZyXEL omni.net LCD PLUS Driver"
+
#define ZYXEL_VENDOR_ID 0x0586
#define ZYXEL_OMNINET_ID 0x1000
static int __init omninet_init (void)
{
usb_serial_register (&zyxel_omninet_device);
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
return 0;
}
module_init(omninet_init);
module_exit(omninet_exit);
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
MODULE_PARM(debug, "i");
MODULE_PARM_DESC(debug, "Debug enabled or not");
* based on a driver by Brad Keryan)
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
+ *
+ * (04/08/2001) gb
+ * Identify version on module load.
*
* 2001_02_05 gkh
* Fixed buffer overflows bug with the generic serial driver. Thanks to
#include "usb-serial.h"
-
-/* Module information */
-MODULE_AUTHOR("Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/");
-MODULE_DESCRIPTION("USB Serial Driver");
-
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/"
+#define DRIVER_DESC "USB Serial Driver"
#define MAX(a,b) (((a)>(b))?(a):(b))
#ifdef CONFIG_USB_SERIAL_GENERIC
static __u16 vendor = 0x05f9;
static __u16 product = 0xffff;
-MODULE_PARM(vendor, "i");
-MODULE_PARM_DESC(vendor, "User specified USB idVendor");
-
-MODULE_PARM(product, "i");
-MODULE_PARM_DESC(product, "User specified USB idProduct");
static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */
err("usb_register failed for the usb-serial driver. Error number %d", result);
return -1;
}
-
-
+
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
+
return 0;
}
EXPORT_SYMBOL(ezusb_set_reset);
#endif
+
+/* Module information */
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
+MODULE_PARM(vendor, "i");
+MODULE_PARM_DESC(vendor, "User specified USB idVendor");
+
+MODULE_PARM(product, "i");
+MODULE_PARM_DESC(product, "User specified USB idProduct");
+
* (at your option) any later version.
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
+ *
+ * (04/08/2001) gb
+ * Identify version on module load.
*
* (01/21/2000) gkh
* Added write_room and chars_in_buffer, as they were previously using the
#include "usb-serial.h"
#include "visor.h"
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
+#define DRIVER_DESC "USB HandSpring Visor driver"
+
#define MIN(a,b) (((a)<(b))?(a):(b))
/* function prototypes for a handspring visor */
continue;
}
}
-
+
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
+
return 0;
}
module_init(visor_init);
module_exit(visor_exit);
-MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>");
-MODULE_DESCRIPTION("USB HandSpring Visor driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_PARM(debug, "i");
MODULE_PARM_DESC(debug, "Debug enabled or not");
* (at your option) any later version.
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
+ *
+ * (04/08/2001) gb
+ * Identify version on module load.
*
* 2001_Mar_19 gkh
* Fixed MOD_INC and MOD_DEC logic, the ability to open a port more
#include "whiteheat_fw.h" /* firmware for the ConnectTech WhiteHEAT device */
#include "whiteheat.h" /* WhiteHEAT specific commands */
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
+#define DRIVER_DESC "USB ConnectTech WhiteHEAT driver"
+
#define CONNECT_TECH_VENDOR_ID 0x0710
#define CONNECT_TECH_FAKE_WHITE_HEAT_ID 0x0001
#define CONNECT_TECH_WHITE_HEAT_ID 0x8001
{
usb_serial_register (&whiteheat_fake_device);
usb_serial_register (&whiteheat_device);
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
return 0;
}
module_init(whiteheat_init);
module_exit(whiteheat_exit);
-MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>");
-MODULE_DESCRIPTION("USB ConnectTech WhiteHEAT driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_PARM(debug, "i");
MODULE_PARM_DESC(debug, "Debug enabled or not");
--- /dev/null
+ /* SQCIF */
+ {
+ /* 5 fps */
+ {
+ {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+ {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+ {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+ {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+ },
+ /* 10 fps */
+ {
+ {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+ {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+ {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+ {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+ },
+ /* 15 fps */
+ {
+ {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+ {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+ {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+ {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+ },
+ /* 20 fps */
+ {
+ {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+ {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+ {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+ {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+ },
+ /* 25 fps */
+ {
+ {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+ {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+ {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+ {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+ },
+ /* 30 fps */
+ {
+ {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+ {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+ {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+ {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+ },
+ },
+ /* QSIF */
+ {
+ /* 5 fps */
+ {
+ {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+ {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+ {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+ {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+ },
+ /* 10 fps */
+ {
+ {2, 291, 0, {0x2C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0xA1, 0xC0, 0x02}},
+ {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+ {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+ {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+ },
+ /* 15 fps */
+ {
+ {3, 437, 0, {0x2B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x6D, 0xC0, 0x02}},
+ {2, 291, 640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+ {2, 291, 640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+ {1, 191, 420, {0x2B, 0xF4, 0x0D, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+ },
+ /* 20 fps */
+ {
+ {4, 588, 0, {0x2A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4C, 0x52, 0xC0, 0x02}},
+ {3, 447, 730, {0x2A, 0xF4, 0x05, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+ {2, 292, 476, {0x2A, 0xF4, 0x0D, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
+ {1, 192, 312, {0x2A, 0xF4, 0x1D, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}},
+ },
+ /* 25 fps */
+ {
+ {5, 703, 0, {0x29, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x42, 0xC0, 0x02}},
+ {3, 447, 610, {0x29, 0xF4, 0x05, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+ {2, 292, 398, {0x29, 0xF4, 0x0D, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
+ {1, 192, 262, {0x29, 0xF4, 0x25, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}},
+ },
+ /* 30 fps */
+ {
+ {8, 873, 0, {0x28, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x69, 0x37, 0xC0, 0x02}},
+ {5, 704, 774, {0x28, 0xF4, 0x05, 0x18, 0x21, 0x17, 0x59, 0x0F, 0x18, 0xC0, 0x42, 0xC0, 0x02}},
+ {3, 448, 492, {0x28, 0xF4, 0x05, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x18, 0xC0, 0x69, 0xC0, 0x02}},
+ {2, 291, 320, {0x28, 0xF4, 0x1D, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}},
+ },
+ },
+ /* QCIF */
+ {
+ /* 5 fps */
+ {
+ {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+ {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+ {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+ {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+ },
+ /* 10 fps */
+ {
+ {3, 385, 0, {0x0C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x81, 0x79, 0xC0, 0x02}},
+ {2, 291, 800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+ {2, 291, 800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+ {1, 194, 532, {0x0C, 0xF4, 0x05, 0x10, 0x9A, 0x0F, 0xBE, 0x1B, 0x08, 0xC2, 0xF0, 0xC0, 0x02}},
+ },
+ /* 15 fps */
+ {
+ {4, 577, 0, {0x0B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x41, 0x52, 0xC0, 0x02}},
+ {3, 447, 818, {0x0B, 0xF4, 0x05, 0x19, 0x89, 0x18, 0xAD, 0x0F, 0x10, 0xBF, 0x69, 0xC0, 0x02}},
+ {2, 292, 534, {0x0B, 0xF4, 0x05, 0x10, 0xA3, 0x0F, 0xC7, 0x19, 0x10, 0x24, 0xA1, 0xC0, 0x02}},
+ {1, 195, 356, {0x0B, 0xF4, 0x15, 0x0B, 0x11, 0x0A, 0x35, 0x1E, 0x10, 0xC3, 0xF0, 0xC0, 0x02}},
+ },
+ /* 20 fps */
+ {
+ {6, 776, 0, {0x0A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x08, 0x3F, 0xC0, 0x02}},
+ {4, 591, 804, {0x0A, 0xF4, 0x05, 0x19, 0x1E, 0x18, 0x42, 0x0F, 0x18, 0x4F, 0x4E, 0xC0, 0x02}},
+ {3, 447, 608, {0x0A, 0xF4, 0x05, 0x12, 0xFD, 0x12, 0x21, 0x15, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+ {2, 291, 396, {0x0A, 0xF4, 0x15, 0x0C, 0x5E, 0x0B, 0x82, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}},
+ },
+ /* 25 fps */
+ {
+ {9, 928, 0, {0x09, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xA0, 0x33, 0xC0, 0x02}},
+ {5, 703, 800, {0x09, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x10, 0x18, 0xBF, 0x42, 0xC0, 0x02}},
+ {3, 447, 508, {0x09, 0xF4, 0x0D, 0x0F, 0xD2, 0x0E, 0xF6, 0x1B, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+ {2, 292, 332, {0x09, 0xF4, 0x1D, 0x0A, 0x5A, 0x09, 0x7E, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {9, 956, 876, {0x08, 0xF4, 0x05, 0x1B, 0x58, 0x1A, 0x7C, 0x0E, 0x20, 0xBC, 0x33, 0x10, 0x02}},
+ {4, 592, 542, {0x08, 0xF4, 0x05, 0x10, 0xE4, 0x10, 0x08, 0x17, 0x20, 0x50, 0x4E, 0x10, 0x02}},
+ {2, 291, 266, {0x08, 0xF4, 0x25, 0x08, 0x48, 0x07, 0x6C, 0x1E, 0x20, 0x23, 0xA1, 0x10, 0x02}},
+ },
+ },
+ /* SIF */
+ {
+ /* 5 fps */
+ {
+ {4, 582, 0, {0x35, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x52, 0x60, 0x02}},
+ {3, 387, 1276, {0x35, 0xF4, 0x05, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x79, 0x60, 0x02}},
+ {2, 291, 960, {0x35, 0xF4, 0x0D, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0xA1, 0x60, 0x02}},
+ {1, 191, 630, {0x35, 0xF4, 0x1D, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x08, 0xBF, 0xF4, 0x60, 0x02}},
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {6, 775, 1278, {0x34, 0xF4, 0x05, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x3F, 0x10, 0x02}},
+ {3, 447, 736, {0x34, 0xF4, 0x15, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x18, 0xBF, 0x69, 0x10, 0x02}},
+ {2, 291, 480, {0x34, 0xF4, 0x2D, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x18, 0x23, 0xA1, 0x10, 0x02}},
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {9, 955, 1050, {0x33, 0xF4, 0x05, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x33, 0x10, 0x02}},
+ {4, 591, 650, {0x33, 0xF4, 0x15, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x4F, 0x4E, 0x10, 0x02}},
+ {3, 448, 492, {0x33, 0xF4, 0x25, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x28, 0xC0, 0x69, 0x10, 0x02}},
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {9, 958, 782, {0x32, 0xF4, 0x0D, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x33, 0xD0, 0x02}},
+ {5, 703, 574, {0x32, 0xF4, 0x1D, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x42, 0xD0, 0x02}},
+ {3, 446, 364, {0x32, 0xF4, 0x3D, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x30, 0xBE, 0x69, 0xD0, 0x02}},
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {9, 958, 654, {0x31, 0xF4, 0x15, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x33, 0x90, 0x02}},
+ {6, 776, 530, {0x31, 0xF4, 0x25, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x3F, 0x90, 0x02}},
+ {4, 592, 404, {0x31, 0xF4, 0x35, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x38, 0x50, 0x4E, 0x90, 0x02}},
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {9, 957, 526, {0x30, 0xF4, 0x25, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x33, 0x60, 0x02}},
+ {6, 775, 426, {0x30, 0xF4, 0x35, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x3F, 0x60, 0x02}},
+ {4, 590, 324, {0x30, 0x7A, 0x4B, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x40, 0x4E, 0x52, 0x60, 0x02}},
+ },
+ },
+ /* CIF */
+ {
+ /* 5 fps */
+ {
+ {6, 771, 0, {0x15, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x3F, 0x80, 0x02}},
+ {4, 465, 1278, {0x15, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x03, 0x18, 0xD1, 0x65, 0x80, 0x02}},
+ {2, 291, 800, {0x15, 0xF4, 0x15, 0x18, 0xF4, 0x17, 0x3C, 0x05, 0x18, 0x23, 0xA1, 0x80, 0x02}},
+ {1, 193, 528, {0x15, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x18, 0xC1, 0xF4, 0x80, 0x02}},
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {9, 932, 1278, {0x14, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x04, 0x30, 0xA4, 0x33, 0x10, 0x02}},
+ {4, 591, 812, {0x14, 0xF4, 0x15, 0x19, 0x56, 0x17, 0x9E, 0x06, 0x28, 0x4F, 0x4E, 0x10, 0x02}},
+ {2, 291, 400, {0x14, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x28, 0x23, 0xA1, 0x10, 0x02}},
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {9, 956, 876, {0x13, 0xF4, 0x0D, 0x1B, 0x58, 0x19, 0xA0, 0x05, 0x38, 0xBC, 0x33, 0x60, 0x02}},
+ {5, 703, 644, {0x13, 0xF4, 0x1D, 0x14, 0x1C, 0x12, 0x64, 0x08, 0x38, 0xBF, 0x42, 0x60, 0x02}},
+ {3, 448, 410, {0x13, 0xF4, 0x3D, 0x0C, 0xC4, 0x0B, 0x0C, 0x0E, 0x38, 0xC0, 0x69, 0x60, 0x02}},
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {9, 956, 650, {0x12, 0xF4, 0x1D, 0x14, 0x4A, 0x12, 0x92, 0x09, 0x48, 0xBC, 0x33, 0x10, 0x03}},
+ {6, 776, 528, {0x12, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x40, 0x08, 0x3F, 0x10, 0x03}},
+ {4, 591, 402, {0x12, 0xF4, 0x3D, 0x0C, 0x8F, 0x0A, 0xD7, 0x0E, 0x40, 0x4F, 0x4E, 0x10, 0x03}},
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {9, 956, 544, {0x11, 0xF4, 0x25, 0x10, 0xF4, 0x0F, 0x3C, 0x0A, 0x48, 0xBC, 0x33, 0xC0, 0x02}},
+ {7, 840, 478, {0x11, 0xF4, 0x2D, 0x0E, 0xEB, 0x0D, 0x33, 0x0B, 0x48, 0x48, 0x3B, 0xC0, 0x02}},
+ {5, 703, 400, {0x11, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x48, 0xBF, 0x42, 0xC0, 0x02}},
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {9, 956, 438, {0x10, 0xF4, 0x35, 0x0D, 0xAC, 0x0B, 0xF4, 0x0D, 0x50, 0xBC, 0x33, 0x10, 0x02}},
+ {7, 838, 384, {0x10, 0xF4, 0x45, 0x0B, 0xFD, 0x0A, 0x45, 0x0F, 0x50, 0x46, 0x3B, 0x10, 0x02}},
+ {6, 773, 354, {0x10, 0x7A, 0x4B, 0x0B, 0x0C, 0x09, 0x80, 0x10, 0x50, 0x05, 0x3F, 0x10, 0x02}},
+ },
+ },
+ /* VGA */
+ {
+ /* 5 fps */
+ {
+ {0, },
+ {6, 773, 1272, {0x1D, 0xF4, 0x15, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x3F, 0x10, 0x02}},
+ {4, 592, 976, {0x1D, 0xF4, 0x25, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x4E, 0x10, 0x02}},
+ {3, 448, 738, {0x1D, 0xF4, 0x3D, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x69, 0x10, 0x02}},
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {9, 956, 788, {0x1C, 0xF4, 0x35, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x33, 0x10, 0x02}},
+ {6, 776, 640, {0x1C, 0x7A, 0x53, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x3F, 0x10, 0x02}},
+ {4, 592, 488, {0x1C, 0x7A, 0x6B, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x4E, 0x10, 0x02}},
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {9, 957, 526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}},
+ {9, 957, 526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}},
+ {8, 895, 492, {0x1B, 0x7A, 0x6B, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x37, 0x80, 0x02}},
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ },
* (C) Copyright 1999-2001 Johannes Erdfelt
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <asm/io.h>
#include <linux/pm.h>
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION ""
+#define DRIVER_AUTHOR "Linus Torvalds, Johannes Erdfelt, Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber"
+#define DRIVER_DESC "USB Universal Host Controller Interface driver"
+
+
/*
* debug = 0, no debugging messages
* debug = 1, dump failed URB's except for stalls
release_uhci(uhci);
}
+#ifdef CONFIG_PM
static void uhci_pci_suspend(struct pci_dev *dev)
{
reset_hc((struct uhci *) dev->driver_data);
reset_hc((struct uhci *) dev->driver_data);
start_hc((struct uhci *) dev->driver_data);
}
+#endif
static const struct pci_device_id __devinitdata uhci_pci_ids[] = { {
if (retval)
goto init_failed;
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
+
return 0;
init_failed:
module_init(uhci_hcd_init);
module_exit(uhci_hcd_cleanup);
-MODULE_AUTHOR("Linus Torvalds, Johannes Erdfelt, Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber");
-MODULE_DESCRIPTION("USB Universal Host Controller Interface driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
*
* History:
*
+ * 2001/04/08 Identify version on module load gb
* 2001/03/24 td/ed hashing to remove bus_to_virt (Steve Longerbeam);
pci_map_single (db)
* 2001/03/21 td and dev/ed allocation uses new pci_pool API (db)
#endif
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v5.2"
+#define DRIVER_AUTHOR "Roman Weissgaerber <weissg@vienna.at>, David Brownell"
+#define DRIVER_DESC "USB OHCI Host Controller Driver"
+
/* For initializing controller (mask in an HCFS mode too) */
#define OHCI_CONTROL_INIT \
(OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
#ifdef CONFIG_PMAC_PBOOK
pmu_register_sleep_notifier (&ohci_sleep_notifier);
#endif
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
return ret;
}
module_exit (ohci_hcd_cleanup);
-MODULE_AUTHOR ("Roman Weissgaerber <weissg@vienna.at>, David Brownell");
-MODULE_DESCRIPTION ("USB OHCI Host Controller Driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
/* Not Access */ USB_ST_NORESPONSE
};
+#include <linux/config.h>
/* ED States */
#include "usb-uhci.h"
#include "usb-uhci-debug.h"
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.251"
+#define DRIVER_AUTHOR "Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber"
+#define DRIVER_DESC "USB Universal Host Controller Interface driver"
+
#undef DEBUG
#undef dbg
#define dbg(format, arg...) do {} while (0)
return 0;
}
+#ifdef CONFIG_PM
_static void
uhci_pci_suspend (struct pci_dev *dev)
{
{
start_hc((uhci_t *) dev->driver_data);
}
-
+#endif
_static int __devinit alloc_uhci (struct pci_dev *dev, int irq, unsigned int io_addr, unsigned int io_size)
{
}
#endif
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
+
return retval;
}
module_exit (uhci_hcd_cleanup);
-MODULE_AUTHOR("Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber");
-MODULE_DESCRIPTION("USB Universal Host Controller Interface driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
#include <linux/init.h>
#include <linux/usb.h>
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("USB HID Boot Protocol keyboard driver");
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION ""
+#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@suse.cz>"
+#define DRIVER_DESC "USB HID Boot Protocol keyboard driver"
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
static unsigned char usb_kbd_keycode[256] = {
0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
static int __init usb_kbd_init(void)
{
usb_register(&usb_kbd_driver);
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
return 0;
}
#include <linux/init.h>
#include <linux/usb.h>
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("USB HID Boot Protocol mouse driver");
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.6"
+#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@suse.cz>"
+#define DRIVER_DESC "USB HID Boot Protocol mouse driver"
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
struct usb_mouse {
signed char data[8];
static int __init usb_mouse_init(void)
{
usb_register(&usb_mouse_driver);
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
return 0;
}
* 0.4 13.08.99 Added Vendor/Product ID of Brad Hard's cable
* 0.5 20.09.99 usb_control_msg wrapper used
* Nov01.00 usb_device_table support by Adam J. Richter
+ * 08.04.01 Identify version on module load. gb
*
*/
#include <linux/init.h>
#include <linux/usb.h>
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.5"
+#define DRIVER_AUTHOR "Thomas M. Sailer, sailer@ife.ee.ethz.ch"
+#define DRIVER_DESC "USB Parport Cable driver for Cables using the Lucent Technologies USS720 Chip"
+
/* --------------------------------------------------------------------- */
struct parport_uss720_private {
/* --------------------------------------------------------------------- */
-MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch");
-MODULE_DESCRIPTION("USB Parport Cable driver for Cables using the Lucent Technologies USS720 Chip");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
static int __init uss720_init(void)
{
if (usb_register(&uss720_driver) < 0)
return -1;
- printk(KERN_INFO "uss720: USB<->IEEE1284 cable driver v0.4 registered.\n"
- KERN_INFO "uss720: (C) 1999 by Thomas Sailer, <sailer@ife.ee.ethz.ch>\n");
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
return 0;
}
--- /dev/null
+/*
+ (C) 2001 Nemosoft Unv. nemosoft@smcc.demon.nl
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+
+/* 'Viewport' conversion routines. These functions convert from one colour
+ space to another, taking into account that the source image has a smaller
+ size than the view, and is placed inside the view:
+
+ +-------view.x------------+
+ | |
+ | +---image.x---+ |
+ | | | |
+ | | | |
+ | +-------------+ |
+ | |
+ +-------------------------+
+
+ The image should always be smaller than the view. The offset (top-left
+ corner of the image) should be precomputed, so you can place the image
+ anywhere in the view.
+
+ The functions take these parameters:
+ - width image width (in pixels)
+ - height image height (in pixels)
+ - plus view width (in pixels)
+ *src pointer at start of image
+ *dst pointer at offset (!) in view
+*/
+
+
+#ifndef VCVT_H
+#define VCVT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Functions in vcvt_i386.S/vcvt_c.c */
+/* 4:2:0 YUV interlaced to RGB/BGR */
+void vcvt_420i_bgr24(int width, int height, int plus, void *src, void *dst);
+void vcvt_420i_rgb24(int width, int height, int plus, void *src, void *dst);
+void vcvt_420i_bgr32(int width, int height, int plus, void *src, void *dst);
+void vcvt_420i_rgb32(int width, int height, int plus, void *src, void *dst);
+
+
+/* Go from 420i to other yuv formats */
+void vcvt_420i_420p(int width, int height, int plus, void *src, void *dsty, void *dstu, void *dstv);
+void vcvt_420i_yuyv(int width, int height, int plus, void *src, void *dst);
+
+#if 0
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/*
+ Colour conversion routines (RGB <-> YUV) in plain C, with viewport
+ extension.
+ (C) 2001 Nemosoft Unv. nemosoft@smcc.demon.nl
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+
+/* Colour conversion routines that use a viewport. See the assembly code/.h
+ files for more information.
+
+ If you are always converting images where the image- and viewport size
+ is the same, you can hack out the 'plus' variable and delete the
+ offset calculation at the bottom of every for(line) {} loop. Otherwise,
+ just call the functions with plus = width.
+
+ NB: for these function, the YUV420 format is defined as:
+ even lines: YYYY UU YYYY UU YYYY ..
+ odd lines: YYYY VV YYYY VV YYYY ..
+*/
+
+#include "vcvt.h"
+
+
+#define PUSH_RGB24 1
+#define PUSH_BGR24 2
+#define PUSH_RGB32 3
+#define PUSH_BGR32 4
+
+/**
+ \brief convert YUV 4:2:0 data into RGB, BGR, RGBa or BGRa
+ \param width Width of yuv data, in pixels
+ \param height Height of yuv data, in pixels
+ \param plus Width of viewport, in pixels
+ \param src beginning of YUV data
+ \param dst beginning of RGB data, \b including the initial offset into the viewport
+ \param push The requested RGB format
+
+ \e push can be any of PUSH_RGB24, PUSH_BGR24, PUSH_RGB32 or PUSH_BGR32
+
+ This is a really simplistic approach. Speedups are welcomed.
+*/
+static void vcvt_420i(int width, int height, int plus, unsigned char *src, unsigned char *dst, int push)
+{
+ int line, col, linewidth;
+ int y, u, v, yy, vr = 0, ug = 0, vg = 0, ub = 0;
+ int r, g, b;
+ unsigned char *sy, *su, *sv;
+
+ linewidth = width + (width >> 1);
+ sy = src;
+ su = sy + 4;
+ sv = su + linewidth;
+
+ /* The biggest problem is the interlaced data, and the fact that odd
+ add even lines have V and U data, resp.
+ */
+ for (line = 0; line < height; line++) {
+ for (col = 0; col < width; col++) {
+ y = *sy++;
+ yy = y << 8;
+ if ((col & 1) == 0) {
+ /* only at even colums we update the u/v data */
+ u = *su - 128;
+ ug = 88 * u;
+ ub = 454 * u;
+ v = *sv - 128;
+ vg = 183 * v;
+ vr = 359 * v;
+
+ su++;
+ sv++;
+ }
+ if ((col & 3) == 3) {
+ sy += 2; /* skip u/v */
+ su += 4; /* skip y */
+ sv += 4; /* skip y */
+ }
+
+ r = (yy + vr) >> 8;
+ g = (yy - ug - vg) >> 8;
+ b = (yy + ub ) >> 8;
+ /* At moments like this, you crave for MMX instructions with saturation */
+ if (r < 0) r = 0;
+ if (r > 255) r = 255;
+ if (g < 0) g = 0;
+ if (g > 255) g = 255;
+ if (b < 0) b = 0;
+ if (b > 255) b = 255;
+
+ switch(push) {
+ case PUSH_RGB24:
+ *dst++ = r;
+ *dst++ = g;
+ *dst++ = b;
+ break;
+
+ case PUSH_BGR24:
+ *dst++ = b;
+ *dst++ = g;
+ *dst++ = r;
+ break;
+
+ case PUSH_RGB32:
+ *dst++ = r;
+ *dst++ = g;
+ *dst++ = b;
+ *dst++ = 0;
+ break;
+
+ case PUSH_BGR32:
+ *dst++ = b;
+ *dst++ = g;
+ *dst++ = r;
+ *dst++ = 0;
+ break;
+ }
+ } /* ..for col */
+ if (line & 1) { // odd line: go to next band
+ su += linewidth;
+ sv += linewidth;
+ }
+ else { // rewind u/v pointers
+ su -= linewidth;
+ sv -= linewidth;
+ }
+ /* Adjust destination pointer, using viewport. We have just
+ filled one line worth of data, so only skip the difference
+ between the view width and the image width.
+ */
+ if (push == PUSH_RGB24 || push == PUSH_BGR24)
+ dst += ((plus - width) * 3);
+ else
+ dst += ((plus - width) * 4);
+ } /* ..for line */
+}
+
+void vcvt_420i_rgb24(int width, int height, int plus, void *src, void *dst)
+{
+ vcvt_420i(width, height, plus, (unsigned char *)src, (unsigned char *)dst, PUSH_RGB24);
+}
+
+void vcvt_420i_bgr24(int width, int height, int plus, void *src, void *dst)
+{
+ vcvt_420i(width, height, plus, (unsigned char *)src, (unsigned char *)dst, PUSH_BGR24);
+}
+
+void vcvt_420i_rgb32(int width, int height, int plus, void *src, void *dst)
+{
+ vcvt_420i(width, height, plus, (unsigned char *)src, (unsigned char *)dst, PUSH_RGB32);
+}
+
+void vcvt_420i_bgr32(int width, int height, int plus, void *src, void *dst)
+{
+ vcvt_420i(width, height, plus, (unsigned char *)src, (unsigned char *)dst, PUSH_BGR32);
+}
+
+
+/** \brief Convert from interlaces YUV 420 to planar format
+*/
+void vcvt_420i_420p(int width, int height, int plus, void *src, void *dsty, void *dstu, void *dstv)
+{
+ short *s, *dy, *du, *dv;
+ int line, col;
+
+ s = (short *)src;
+ dy = (short *)dsty;
+ du = (short *)dstu;
+ dv = (short *)dstv;
+ for (line = 0; line < height; line++) {
+ for (col = 0; col < width; col += 4) {
+ *dy++ = *s++;
+ *dy++ = *s++;
+ if (line & 1)
+ *dv++ = *s++;
+ else
+ *du++ = *s++;
+ } /* ..for col */
+ dy += (plus - width);
+ dv += ((plus - width) >> 1);
+ du += ((plus - width) >> 1);
+ } /* ..for line */
+}
+
+void vcvt_420i_yuyv(int width, int height, int plus, void *src, void *dst)
+{
+ int line, col, linewidth;
+ unsigned char *sy, *su, *sv, *d;
+
+ linewidth = width + (width >> 1);
+ sy = (unsigned char *)src;
+ su = sy + 4;
+ sv = su + linewidth;
+ d = (unsigned char *)dst;
+
+ for (line = 0; line < height; line++) {
+ for (col = 0; col < width; col += 4) {
+ /* four pixels in one go */
+ *d++ = *sy++;
+ *d++ = *su;
+ *d++ = *sy++;
+ *d++ = *sv;
+
+ *d++ = *sy++;
+ *d++ = *su++;
+ *d++ = *sy++;
+ *d++ = *sv++;
+
+ sy += 2;
+ su += 4;
+ sv += 4;
+ } /* ..for col */
+ if (line & 1) { // odd line: go to next band
+ su += linewidth;
+ sv += linewidth;
+ }
+ else { // rewind u/v pointers
+ su -= linewidth;
+ sv -= linewidth;
+ }
+ /* Adjust for viewport width */
+ d += ((plus - width) << 1);
+ } /* ..for line */
+}
+
--- /dev/null
+/*
+ Colour conversion routines (RGB <-> YUV) in x86 assembly, with viewport
+ extension.
+ (C) 2001 Nemosoft Unv. nemosoft@smcc.demon.nl
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+
+/* The vcvt_* functions always start with width and height and plus, so these
+ parameters are in 8(%ebp), 12(%ebp) and 16(%ebp).
+ The other parameters can be 2 to 4 pointers, in one of these combinations:
+ *src, *dst
+ *srcy, *srcu, *srv, *dst
+ *src, *dsty, *dstu, *dstv
+ */
+
+#define __ASSEMBLY__
+#include <linux/linkage.h>
+
+.line 35
+
+#define Width 8(%ebp)
+#define Height 12(%ebp)
+#define Plus 16(%ebp)
+
+/* 2 parameters, 1 in, 1 out */
+#define Src2 20(%ebp)
+#define Dst2 24(%ebp)
+
+/* 4 parameters, 3 in, 1 out */
+#define SrcY 20(%ebp)
+#define SrcU 24(%ebp)
+#define SrcV 28(%ebp)
+#define Dst4 32(%ebp)
+
+/* 4 parameters, 1 in, 3 out */
+#define Src4 20(%ebp)
+#define DstY 24(%ebp)
+#define DstU 28(%ebp)
+#define DstV 32(%ebp)
+
+/* This buffer space used to be staticly allocted, but this is going to
+ give problems with multiple cams (though I have yet to see it).
+ Therefor, we reserve least 64 bytes (16 * 4) bytes on the stack,
+ plus some space for extra variables.
+ */
+
+#define PixelBuffer -64(%ebp)
+#define Uptr -68(%ebp)
+#define Vptr -72(%ebp)
+#define DstPlus -76(%ebp)
+
+#define StackSpace $76
+
+ .text
+
+/* This function will load the src and destination pointers, including
+ Uptr/Vptr when necessary, and test the width/height parameters.
+ - %esi will be set to Src or SrcY
+ - %edi will be set to Dst or DstY
+ the carry flag will be set if any of these tests fail.
+ It assumes %ebp has been set.
+ */
+/* 2 parameters, src & dst */
+test_param_2:
+ mov Src2, %esi
+ mov Dst2, %edi
+
+ cmp $0, %esi # NULL pointers?
+ je param_fail
+ cmp $0, %edi
+ je param_fail
+
+ jmp test_width_height
+
+/* 3 inputs, 1 output */
+test_param_31:
+ mov Dst4, %edi # NULL pointers
+ cmp $0, %edi
+ je param_fail
+
+ mov SrcV, %esi
+ cmp $0, %esi
+ je param_fail
+ mov %esi, Vptr
+
+ mov SrcU, %esi
+ cmp $0, %esi
+ je param_fail
+ mov %esi, Uptr
+
+ mov SrcY, %esi
+ cmp $0, %esi
+ je param_fail
+
+ jmp test_width_height
+
+/* 1 input, 3 output */
+test_param_13:
+ mov Src4, %esi # NULL pointers
+ cmp $0, %esi
+ je param_fail
+
+ mov DstV, %edi
+ cmp $0, %edi
+ je param_fail
+ mov %edi, Vptr
+
+ mov DstU, %edi
+ cmp $0, %edi
+ je param_fail
+ mov %edi, Uptr
+
+ mov DstY, %edi
+ cmp $0, %edi
+ je param_fail
+
+ jmp test_width_height
+
+ nop
+
+test_width_height:
+ cmpl $0, Width
+ jbe param_fail
+ testl $3, Width # multiple of 4?
+ jnz param_fail # Nope...
+
+ cmp $0, Height # check illegal height
+ jbe param_fail
+ testl $1, Height # Odd no. of lines?
+ jnz param_fail # Aye
+
+ /* fall through */
+
+/* exit points */
+param_ok:
+ clc # Success: clear carry
+ ret
+
+param_fail:
+ stc # Fail: set carry
+ ret
+
+
+
+# This will fill PixelBuffer with 4 grey scale pixels (Y)
+# In: %eax = Value (Y3Y2Y1Y0)
+# Out:
+# Modifies: %ecx (-4)
+# Destroys: %edx
+expand_4_y:
+ mov %eax, %edx # Keep in edx (we need eax)
+ lea PixelBuffer, %edi
+
+0: # This code is executed 4 times
+ movzbl %dl, %eax # move, zero extending byte-to-long
+ shl $8, %eax # 8 digit precision
+
+ stosl # Expand into PixelBuffer
+ stosl
+ stosl
+ add $4, %edi # Skip alpha
+
+ shr $8, %edx # next Y
+
+ dec %ecx
+ test $3, %ecx
+ jnz 0b
+
+ ret # from expand_4_y
+
+# This will add the color factors to the (grey) values in PixelBuffer
+# In: %ebx (U1U0V1V0)
+# Out:
+# Modifies:
+# Destroys: %edi, %ebx, %eax, %edx
+expand_4_uv:
+ lea PixelBuffer, %edi # reset pointer
+
+ # V0
+ sub $128, %bl
+ movsbl %bl, %eax
+ mov $359, %edx # Vr
+ mul %edx
+ add %eax, 0x00(%edi)
+ add %eax, 0x10(%edi)
+
+ movsbl %bl, %eax
+ mov $183, %edx # Vg
+ mul %edx
+ sub %eax, 0x04(%edi)
+ sub %eax, 0x14(%edi)
+
+ # V1
+ sub $128, %bh
+ movsbl %bh, %eax
+ mov $359, %edx # Vr
+ mul %edx
+ add %eax, 0x20(%edi)
+ add %eax, 0x30(%edi)
+
+ movsbl %bh, %eax
+ mov $183, %edx # Vg
+ mul %edx
+ sub %eax, 0x24(%edi)
+ sub %eax, 0x34(%edi)
+
+ # U0
+ bswap %ebx # Get U values in lower half
+ sub $128, %bh
+ movsbl %bh, %eax
+ mov $88, %edx # Ug
+ mul %edx
+ sub %eax, 0x04(%edi)
+ sub %eax, 0x14(%edi)
+
+ movsbl %bh, %eax
+ mov $454, %edx # Ub
+ mul %edx
+ add %eax, 0x08(%edi)
+ add %eax, 0x18(%edi)
+
+ # U1
+ sub $128, %bl
+ movsbl %bl, %eax
+ mov $88, %edx # Ug
+ mul %edx
+ sub %eax, 0x24(%edi)
+ sub %eax, 0x34(%edi)
+
+ movsbl %bl, %eax
+ mov $454, %edx # Ub
+ mul %edx
+ add %eax, 0x28(%edi)
+ add %eax, 0x38(%edi)
+ ret # expand_4_uv
+
+
+/* This function expands 4 420i pixels into PixelBuffer */
+do_four_yuvi:
+ push %edi
+
+ lodsl # 4 bytes at a time
+
+ call expand_4_y
+
+ # now do UV values. on even lines, Y is followed by U values; on
+ # odd lines V values follow. The U and V values are always pushed
+ # on the stack in this order:
+ # U V
+
+ # First, calculate offset per line (1.5 * width)
+ mov Width, %ebx # width
+ shl %ebx # 2 *
+ add Width, %ebx # 3 *
+ shr %ebx # 1.5 *
+
+ # even or odd lines
+ testl $1, Height
+ jz 2f
+
+ # odd line; we are at V data, but do U data first
+ neg %ebx # make ebx offset negative
+ mov (%esi,%ebx),%ax # U
+ push %ax
+ lodsw # V
+ push %ax
+ jmp 3f
+
+2: # even line
+ lodsw # U
+ push %ax
+ sub $2, %ebx
+ mov (%esi,%ebx), %ax # V
+ push %ax
+
+3: # Okay, so we now have the U and V values... expand into PixelBuffer
+
+ pop %ebx
+ call expand_4_uv
+
+ pop %edi
+ ret # from do_four_yuvi
+
+
+# Do four pixels, in planar format
+do_four_yuvp:
+ push %edi
+
+ # The first part is the same as for interlaced (4 bytes Y)
+ lodsl # 4 bytes at a time
+ call expand_4_y
+
+ # now gather U and V values...
+ mov Uptr, %ebx # Use Uptr/Vptr
+ mov (%ebx), %ax
+ push %ax
+ add $2, %ebx
+ mov %ebx, Uptr
+
+ mov Vptr, %ebx
+ mov (%ebx), %ax
+ push %ax
+ add $2, %ebx
+ mov %ebx, Vptr
+
+ pop %ebx
+ call expand_4_uv
+
+ pop %edi
+ ret
+
+
+# Do four pixels, in yuyv interlaced format
+do_four_yuyv:
+ push %edi
+
+ lodsl # v0y1u0y0
+ mov %eax, %ebx
+ bswap %ebx # y0u0y1v0
+ mov %bh, %ah # v0y1y1y0
+ and $0x00ff00ff, %ebx # __u0__v0
+ push %ax # y1y0
+
+ lodsl # v1y3u1y2 # mix register instructions
+ mov %eax, %edx # so CPU pipeline doesnt stall
+ rol $16, %eax # u1y2v1y3
+ mov %dl, %dh # v1y3y2y2
+ and $0xff00ff00, %eax # u1__v1__
+ mov $0, %dl # v1y3y2__
+ or %eax, %ebx # u1u0v1v0
+ shl $8, %edx # y3y2____
+ pop %dx # y3y2y1y0
+ mov %edx, %eax
+ call expand_4_y
+ call expand_4_uv
+
+ pop %edi
+ ret
+
+limit_pixels:
+ # Limit all values in PixelBuffer
+ push %esi
+ push %edi
+ push %ecx
+ lea PixelBuffer, %esi
+ mov %esi, %edi
+ mov $16, %ecx
+0: lodsl
+ cmp $0, %eax # this would have been a perfect spot for CMOVxx instructions...
+ jl 2f # except they only work on Pentium Pro processors,
+ cmp $0xff00, %eax # and not even all of them
+ jg 3f
+ add $4, %edi # no use for stosl here
+ loop 0b
+ jmp 9f
+2: mov $0, %eax
+ stosl
+ loop 0b
+ jmp 9f
+3: mov $0xff00, %eax
+ stosl
+ loop 0b
+ jmp 9f
+
+9: pop %ecx
+ pop %edi
+ pop %esi
+ ret # from limit_pixels
+
+/* Copy RGB values from PixelBuffer into destination buffer, 4 bytes
+ with alpha
+ */
+
+/* Push 3 pixel (12 bytes), in correct order */
+push_rgb24:
+ push %ecx
+ push %esi
+ lea PixelBuffer, %esi
+ mov $4, %ecx
+0: lodsl
+ shr $8, %eax
+ mov %al, (%edi) # Red
+ lodsl
+ shr $8, %eax
+ mov %al, 1(%edi) # Green
+ lodsl
+ shr $8, %eax
+ mov %al, 2(%edi) # Blue
+ add $3, %edi
+ lodsl # dummy
+ loop 0b
+ pop %esi
+ pop %ecx
+ ret
+
+/* Push 3 pixels (12 bytes), in wrong order */
+push_bgr24:
+ push %ecx
+ push %esi
+ lea PixelBuffer, %esi
+ mov $4, %ecx
+0: lodsl
+ shr $8, %eax
+ mov %al, 2(%edi) # Red
+ lodsl
+ shr $8, %eax
+ mov %al, 1(%edi) # Green
+ lodsl
+ shr $8, %eax
+ mov %al, (%edi) # Blue
+ add $3, %edi
+ lodsl # dummy
+ loop 0b
+ pop %esi
+ pop %ecx
+ ret
+
+/* The simplest format: push 4 bytes, RGBa */
+push_rgb32:
+ push %ecx
+ push %esi
+ mov $16, %ecx
+ lea PixelBuffer, %esi
+0: lodsl # red
+ shr $8, %eax # 8 bit precision
+ stosb
+ loop 0b
+ pop %esi
+ pop %ecx
+ ret
+
+
+/* Gosh. Would you believe it. They even made this format... (Qt 2.*) */
+push_bgr32:
+ # copy all 4 values to output buffer
+ push %ecx
+ push %esi
+ mov $4, %ecx
+ lea PixelBuffer, %esi
+0: lodsl # red
+ shr $8, %eax # 8 bit precision
+ mov %al, 2(%edi)
+ lodsl # green
+ shr $8, %eax
+ mov %al, 1(%edi)
+ lodsl # blue
+ shr $8, %eax
+ mov %al, (%edi)
+ add $4, %edi
+ lodsl # dummy
+ loop 0b
+ pop %esi
+ pop %ecx
+ ret
+
+/*************************************/
+
+/* Functions to go from YUV interlaced formats to RGB */
+
+/* Go from interlaced to RGB, red first */
+
+ENTRY(vcvt_420i_rgb24)
+ enter StackSpace, $0 # no extra space, no stackframes
+ push %ebx
+ push %esi
+ push %edi
+
+ call test_param_2
+ jc 9f
+
+ mov Plus, %eax # 3 bytes per pixel
+ shl $1, %eax
+ add Plus, %eax
+ mov %eax, DstPlus
+
+0: mov Width, %ecx # width
+ push %edi # Save dst pointer
+1: call do_four_yuvi
+ call limit_pixels
+ call push_rgb24
+
+ cmp $0, %ecx
+ jnz 1b # end of line?
+ pop %edi # Get dst pointer
+ add DstPlus, %edi # Add offset
+ decl Height # yes; decrement line counter
+ jnz 0b
+
+9: pop %edi
+ pop %esi
+ pop %ebx
+ leave
+ ret
+
+/* Go from interlaced to BGR, blue first */
+
+ENTRY(vcvt_420i_bgr24)
+ enter StackSpace, $0 # no extra space, no stackframes
+ push %ebx
+ push %esi
+ push %edi
+
+ call test_param_2
+ jc 9f
+
+ mov Plus, %eax # 3 bytes per pixel
+ shl $1, %eax
+ add Plus, %eax
+ mov %eax, DstPlus
+
+0: mov Width, %ecx # width
+ push %edi
+1: call do_four_yuvi
+ call limit_pixels
+ call push_bgr24
+
+ cmp $0, %ecx
+ jnz 1b # end of line?
+ pop %edi # Get dst pointer
+ add DstPlus, %edi # Add offset
+ decl Height # yes; decrement line counter
+ jnz 0b
+
+9: pop %edi
+ pop %esi
+ pop %ebx
+ leave
+ ret
+
+
+/* From interlaced to RGBa */
+
+ENTRY(vcvt_420i_rgb32)
+ enter StackSpace, $0 # no extra space, no stackframes
+ push %ebx
+ push %esi
+ push %edi
+
+ call test_param_2
+ jc 9f
+
+ mov Plus, %eax # 4 bytes per pixel
+ shl $2, %eax
+ mov %eax, DstPlus
+
+0: mov Width, %ecx # width
+ push %edi
+1: call do_four_yuvi
+ call limit_pixels
+ call push_rgb32
+
+ cmp $0, %ecx # end of line?
+ jnz 1b
+ pop %edi # Get dst pointer
+ add DstPlus, %edi # Add offset
+ decl Height # yes; decrement line counter
+ jnz 0b
+
+9: pop %edi
+ pop %esi
+ pop %ebx
+ leave
+ ret
+
+/* Guess what? Go from interlaced to BGRa */
+
+ENTRY(vcvt_420i_bgr32)
+ enter StackSpace, $0 # no extra space, no stackframes
+ push %ebx
+ push %esi
+ push %edi
+
+ call test_param_2
+ jc 9f
+
+ mov Plus, %eax # 4 bytes per pixel
+ shl $2, %eax
+ mov %eax, DstPlus
+
+0: mov Width, %ecx # width
+ push %edi
+1: call do_four_yuvi
+ call limit_pixels
+ call push_bgr32
+
+ cmp $0, %ecx # end of line?
+ jnz 1b
+ pop %edi # Get dst pointer
+ add DstPlus, %edi # Add offset
+ decl Height # yes; decrement line counter
+ jnz 0b
+
+9: pop %edi
+ pop %esi
+ pop %ebx
+ leave
+ ret
+
+
+
+
+
+
+
+/**************************************************************************/
+
+
+/* Go from 'interlaced' (YYYY UU/VV) format to planar */
+
+ENTRY(vcvt_420i_420p)
+ enter $80, $0 # 4 bytes extra space, no stackframes
+ push %ebx # -4: width / 4
+ push %esi
+ push %edi
+
+ call test_param_13
+ jc 9f
+
+ # Okay, this is fairly easy... we first grab the Y values (4 bytes
+ # at a time), then rewind and do the U values, and repeat for V.
+ # This leaves us with a nice planar format
+
+ mov Width, %eax
+ shr %eax
+ shr %eax # width / 4
+ mov %eax, -80(%ebp) # Store
+
+ # Y
+ mov Height, %edx # line counter
+0: mov -80(%ebp), %ecx
+ push %edi
+1: lodsl # get 4 bytes...
+ stosl # ...push 4 bytes
+ add $2, %esi # Skip U or V
+ loop 1b
+ pop %edi
+ add Plus, %edi
+ dec %edx
+ jnz 0b
+
+ shrl $1, Plus # divide increment by 2
+
+ # U
+ mov Src4, %esi # rewind source pointer
+ mov DstU, %edi
+ add $4, %esi # set to U
+ mov Height, %edx
+ shr %edx # height / 2
+ mov Width, %ebx
+ shl %ebx
+ add Width, %ebx
+ shr %ebx # Width * 1.5 (line offset)
+
+2: mov -80(%ebp), %ecx # width / 4
+ push %edi
+3: lodsw # 2 bytes at a time
+ stosw
+ add $4, %esi # skip Y
+ loop 3b
+ add %ebx, %esi # Skip line (U is on even lines)
+ pop %edi
+ add Plus, %edi
+ dec %edx
+ jnz 2b
+
+ # V
+ mov Src4, %esi # rewind, set to V in first odd line
+ add $4, %esi
+ add %ebx, %esi # register re-use; no compiler can beat that :)
+ mov DstV, %edi # V ptr
+ mov Height, %edx
+ shr %edx # height / 2
+
+4: mov -80(%ebp), %ecx # Get width/4
+ push %edi
+5: lodsw
+ stosw
+ add $4, %esi # Skip Y
+ loop 5b
+ add %ebx, %esi # Skip line (V is on odd lines)
+ pop %edi
+ add Plus, %edi
+ dec %edx
+ jnz 4b
+
+ /* That's it! */
+
+9: pop %edi
+ pop %esi
+ pop %ebx
+ leave
+ ret
+
+
+/* Go from 4:2:0 interlaced to 'normal' YUYV */
+
+ENTRY(vcvt_420i_yuyv)
+ enter $84, $0 # 8 bytes extra space, no stackframes
+ push %ebx
+ push %esi
+ push %edi
+
+ call test_param_2
+ jc 9f
+
+ mov Width, %ecx # -4: width / 4 = no. loops per line
+ shr %ecx
+ shr %ecx
+ mov %ecx, -80(%ebp)
+
+ mov Width, %ebx # -8: width * 1.5 = line offset
+ shl %ebx
+ add Width, %ebx
+ shr %ebx
+ mov %ebx, -84(%ebp)
+
+ # Okay, this requires a bit of byte shuffling... we go from
+ # YYYY UU
+ # YYYY VV
+ # to
+ # YUYV YUYV
+ # YUYV YUYV
+ # which indeed takes up more space
+
+ #
+ shll Plus # Plus * 2
+0: mov -80(%ebp), %ecx
+ push %edi
+1: lodsl # 4 Y in eax
+ testl $1, Height # even or odd line?
+ jnz 2f
+
+ # Even
+ mov -84(%ebp), %ebx
+ mov (%ebx, %esi), %dx # 16 bits V
+ shl $16, %edx # store in high word
+ mov (%esi), %dx # 16 bits U
+ add $2, %esi
+ jmp 3f
+
+2: # Odd
+ mov -84(%ebp), %ebx
+ neg %ebx # negative offset
+ mov (%esi), %dx # 16 bits V
+ shl $16, %edx # store in high word
+ mov (%ebx, %esi), %dx # 16 bits U
+ add $2, %esi
+
+3: # eax = Y3Y2Y1Y0, edx = V1V0U1U0, ebx is free
+ push %eax
+
+ movzbl %al, %ebx # ______y0
+ and $0xFF00, %eax # ____y1__
+ shl $8, %eax # __y1____
+ or %ebx, %eax # __y1__y0
+ mov %edx, %ebx # v1v0u1u0
+ shl $8, %ebx # v0u1u0__
+ and $0xff00ff00, %ebx # v0__u0__
+ or %ebx, %eax # v0y1u0y0
+ stosl
+
+ pop %eax # y3y2y1y0
+ # Second half
+ shr $8, %eax # __y3y2y1
+ shr $8, %ax # __y3__y2
+ and $0xff00ff00, %edx # v1__u1__
+ or %edx, %eax # v1y3u1y2
+ stosl
+
+ loop 1b
+ pop %edi
+ add Plus, %edi
+ decl Height # height--
+ jnz 0b
+ # Done
+
+9: pop %edi
+ pop %esi
+ pop %ebx
+ leave
+ ret
* v1.12 (de) - Add support for two more inking pen IDs
* v1.14 (vp) - Use new USB device id probing scheme.
* Fix Wacom Graphire mouse wheel
+ * (gb) - Identify version on module load.
*/
/*
#include <linux/init.h>
#include <linux/usb.h>
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("USB Wacom Graphire and Wacom Intuos tablet driver");
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.14"
+#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@suse.cz>"
+#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
/*
* Wacom Graphire packet:
static int __init wacom_init(void)
{
usb_register(&wacom_driver);
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
return 0;
}
*/
#include <asm/io.h>
+#include <linux/config.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/fb.h>
tristate 'Minix fs support' CONFIG_MINIX_FS
+tristate 'FreeVxFS file system support (VERITAS VxFS(TM) compatible)' CONFIG_VXFS_FS
tristate 'NTFS file system support (read only)' CONFIG_NTFS_FS
dep_mbool ' NTFS write support (DANGEROUS)' CONFIG_NTFS_RW $CONFIG_NTFS_FS $CONFIG_EXPERIMENTAL
mod-subdirs := nls
obj-y := open.o read_write.o devices.o file_table.o buffer.o \
- super.o block_dev.o stat.o exec.o pipe.o namei.o fcntl.o \
- ioctl.o readdir.o select.o fifo.o locks.o \
+ super.o block_dev.o char_dev.o stat.o exec.o pipe.o namei.o \
+ fcntl.o ioctl.o readdir.o select.o fifo.o locks.o \
dcache.o inode.o attr.o bad_inode.o file.o iobuf.o dnotify.o \
filesystems.o
subdir-$(CONFIG_ISO9660_FS) += isofs
subdir-$(CONFIG_DEVFS_FS) += devfs
subdir-$(CONFIG_HFS_FS) += hfs
+subdir-$(CONFIG_VXFS_FS) += freevxfs
subdir-$(CONFIG_NFS_FS) += nfs
subdir-$(CONFIG_NFSD) += nfsd
subdir-$(CONFIG_LOCKD) += lockd
}
}
-void __init bdev_init(void)
+void __init bdev_cache_init(void)
{
int i;
struct list_head *head = bdev_hashtable;
--- /dev/null
+/*
+ * linux/fs/block_dev.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+
+#define HASH_BITS 6
+#define HASH_SIZE (1UL << HASH_BITS)
+#define HASH_MASK (HASH_SIZE-1)
+static struct list_head cdev_hashtable[HASH_SIZE];
+static spinlock_t cdev_lock = SPIN_LOCK_UNLOCKED;
+static kmem_cache_t * cdev_cachep;
+
+#define alloc_cdev() \
+ ((struct char_device *) kmem_cache_alloc(cdev_cachep, SLAB_KERNEL))
+#define destroy_cdev(cdev) kmem_cache_free(cdev_cachep, (cdev))
+
+static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+{
+ struct char_device * cdev = (struct char_device *) foo;
+
+ if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+ SLAB_CTOR_CONSTRUCTOR)
+ {
+ memset(cdev, 0, sizeof(*cdev));
+ sema_init(&cdev->sem, 1);
+ }
+}
+
+void __init cdev_cache_init(void)
+{
+ int i;
+ struct list_head *head = cdev_hashtable;
+
+ i = HASH_SIZE;
+ do {
+ INIT_LIST_HEAD(head);
+ head++;
+ i--;
+ } while (i);
+
+ cdev_cachep = kmem_cache_create("cdev_cache",
+ sizeof(struct char_device),
+ 0, SLAB_HWCACHE_ALIGN, init_once,
+ NULL);
+ if (!cdev_cachep)
+ panic("Cannot create cdev_cache SLAB cache");
+}
+
+/*
+ * Most likely _very_ bad one - but then it's hardly critical for small
+ * /dev and can be fixed when somebody will need really large one.
+ */
+static inline unsigned long hash(dev_t dev)
+{
+ unsigned long tmp = dev;
+ tmp = tmp + (tmp >> HASH_BITS) + (tmp >> HASH_BITS*2);
+ return tmp & HASH_MASK;
+}
+
+static struct char_device *cdfind(dev_t dev, struct list_head *head)
+{
+ struct list_head *p;
+ struct char_device *cdev;
+ for (p=head->next; p!=head; p=p->next) {
+ cdev = list_entry(p, struct char_device, hash);
+ if (cdev->dev != dev)
+ continue;
+ atomic_inc(&cdev->count);
+ return cdev;
+ }
+ return NULL;
+}
+
+struct char_device *cdget(dev_t dev)
+{
+ struct list_head * head = cdev_hashtable + hash(dev);
+ struct char_device *cdev, *new_cdev;
+ spin_lock(&cdev_lock);
+ cdev = cdfind(dev, head);
+ spin_unlock(&cdev_lock);
+ if (cdev)
+ return cdev;
+ new_cdev = alloc_cdev();
+ if (!new_cdev)
+ return NULL;
+ atomic_set(&new_cdev->count,1);
+ new_cdev->dev = dev;
+ spin_lock(&cdev_lock);
+ cdev = cdfind(dev, head);
+ if (!cdev) {
+ list_add(&new_cdev->hash, head);
+ spin_unlock(&cdev_lock);
+ return new_cdev;
+ }
+ spin_unlock(&cdev_lock);
+ destroy_cdev(new_cdev);
+ return cdev;
+}
+
+void cdput(struct char_device *cdev)
+{
+ if (atomic_dec_and_test(&cdev->count)) {
+ spin_lock(&cdev_lock);
+ list_del(&cdev->hash);
+ spin_unlock(&cdev_lock);
+ destroy_cdev(cdev);
+ }
+}
+
kmem_cache_t *bh_cachep;
EXPORT_SYMBOL(bh_cachep);
+extern void bdev_cache_init(void);
+extern void cdev_cache_init(void);
+
void __init vfs_caches_init(unsigned long mempages)
{
bh_cachep = kmem_cache_create("buffer_head",
#endif
dcache_init(mempages);
+ inode_init(mempages);
+ bdev_cache_init();
+ cdev_cache_init();
}
{
inode->i_rdev = MKDEV (de->u.fcb.u.device.major,
de->u.fcb.u.device.minor);
+ inode->i_cdev = cdget (kdev_t_to_nr(inode->i_rdev));
}
else if ( S_ISBLK (de->inode.mode) )
{
inode->i_rdev = MKDEV (de->u.fcb.u.device.major,
de->u.fcb.u.device.minor);
- inode->i_bdev = bdget (inode->i_rdev);
+ inode->i_bdev = bdget (kdev_t_to_nr(inode->i_rdev));
if (inode->i_bdev)
{
if (!inode->i_bdev->bd_op && de->u.fcb.ops)
if (S_ISCHR(mode)) {
inode->i_fop = &def_chr_fops;
inode->i_rdev = to_kdev_t(rdev);
+ inode->i_cdev = cdget(rdev);
} else if (S_ISBLK(mode)) {
inode->i_fop = &def_blk_fops;
inode->i_rdev = to_kdev_t(rdev);
static int __init dquot_init(void)
{
printk(KERN_NOTICE "VFS: Diskquotas version %s initialized\n", __DQUOT_VERSION__);
+ return 0;
}
__initcall(dquot_init);
if (!filp)
goto out;
- lock_kernel();
switch (cmd) {
case F_GETLK64:
err = fcntl_getlk64(fd, (struct flock64 *) arg);
err = do_fcntl(fd, cmd, arg, filp);
break;
}
- unlock_kernel();
fput(filp);
out:
return err;
#ifndef _VXFS_SUPER_H_
#define _VXFS_SUPER_H_
-#ident "$Id: vxfs.h 1.9 2001/04/24 19:28:36 hch Exp hch $"
+#ident "$Id: vxfs.h 1.11 2001/05/21 15:40:28 hch Exp hch $"
/*
* Veritas filesystem driver - superblock structure.
*/
#define VXFS_NEFREE 32
+
/*
* VxFS superblock (disk).
*/
struct vxfs_sb {
/*
- * Version 1
+ * Readonly fields for the version 1 superblock.
+ *
+ * Lots of this fields are no more used by version 2
+ * and never filesystems.
*/
- u_int32_t vs_magic; /* Magic, VXFS_MAGIC */
- int32_t vs_version; /* VxFS version, 1,2,3,4 */
+ u_int32_t vs_magic; /* Magic number */
+ int32_t vs_version; /* VxFS version */
u_int32_t vs_ctime; /* create time - secs */
u_int32_t vs_cutime; /* create time - usecs */
- int32_t __unused1; /* ??? */
- int32_t __unused2; /* ??? */
- vx_daddr_t vs_old_logstart; /* OLD: addr of first log blk */
- vx_daddr_t vs_old_logend; /* OLD: addr of last log blk */
- int32_t vs_bsize; /* Block size */
- int32_t vs_size; /* Number of blocks in FS */
- int32_t vs_dsize; /* Number of data blocks */
- u_int32_t vs_old_ninode; /* OLD: number of inodes */
- int32_t vs_old_nau; /* Number of allocation units */
- int32_t __unused3; /* ??? */
- int32_t vs_old_defiextsize; /* OLD: dfault indirect ext size */
- int32_t vs_old_ilbsize; /* OLD: Ilist block size in bytes */
- int32_t vs_immedlen; /* Size of immediate data area */
- int32_t vs_ndaddr; /* Number of direct extentes per inode */
- vx_daddr_t vs_firstau; /* Address of first Allocation Unit */
- vx_daddr_t vs_emap; /* Offset of extent map in AU */
- vx_daddr_t vs_imap; /* Offset of inode map in AU (V1) */
- vx_daddr_t vs_iextop; /* Offset of Ext. Op. map in AU */
- vx_daddr_t vs_istart; /* Offset of inode list in AU */
- vx_daddr_t vs_bstart; /* Offset of first data block in AU */
+ int32_t __unused1; /* unused */
+ int32_t __unused2; /* unused */
+ vx_daddr_t vs_old_logstart; /* obsolete */
+ vx_daddr_t vs_old_logend; /* obsolete */
+ int32_t vs_bsize; /* block size */
+ int32_t vs_size; /* number of blocks */
+ int32_t vs_dsize; /* number of data blocks */
+ u_int32_t vs_old_ninode; /* obsolete */
+ int32_t vs_old_nau; /* obsolete */
+ int32_t __unused3; /* unused */
+ int32_t vs_old_defiextsize; /* obsolete */
+ int32_t vs_old_ilbsize; /* obsolete */
+ int32_t vs_immedlen; /* size of immediate data area */
+ int32_t vs_ndaddr; /* number of direct extentes */
+ vx_daddr_t vs_firstau; /* address of first AU */
+ vx_daddr_t vs_emap; /* offset of extent map in AU */
+ vx_daddr_t vs_imap; /* offset of inode map in AU */
+ vx_daddr_t vs_iextop; /* offset of ExtOp. map in AU */
+ vx_daddr_t vs_istart; /* offset of inode list in AU */
+ vx_daddr_t vs_bstart; /* offset of fdblock in AU */
vx_daddr_t vs_femap; /* aufirst + emap */
vx_daddr_t vs_fimap; /* aufirst + imap */
vx_daddr_t vs_fiextop; /* aufirst + iextop */
vx_daddr_t vs_fistart; /* aufirst + istart */
vx_daddr_t vs_fbstart; /* aufirst + bstart */
- int32_t vs_nindir; /* Number of entries in indirect */
- int32_t vs_aulen; /* Length of AU in blocks */
- int32_t vs_auimlen; /* Length of AU imap in blocks */
- int32_t vs_auemlen; /* Length of AU emap in blocks */
- int32_t vs_auilen; /* Length of AU ilist in blocks */
- int32_t vs_aupad; /* Length of AU pad in blocks */
- int32_t vs_aublocks; /* Number of data blocks in AU */
- int32_t vs_maxtier; /* Log base 2 of aublocks */
- int32_t vs_inopb; /* Number of inodes per blk */
- int32_t vs_old_inopau; /* OLD: Number of inodes per AU */
- int32_t vs_old_inopilb; /* OLD: Inodes per ilist blocks */
- int32_t vs_old_ndiripau; /* OLD: Num of directory inodes per au */
- int32_t vs_iaddrlen; /* Size of indirect addr ext. */
- int32_t vs_bshift; /* Log base 2 of bsize */
- int32_t vs_inoshift; /* Log base 2 of inobp */
+ int32_t vs_nindir; /* number of entries in indir */
+ int32_t vs_aulen; /* length of AU in blocks */
+ int32_t vs_auimlen; /* length of imap in blocks */
+ int32_t vs_auemlen; /* length of emap in blocks */
+ int32_t vs_auilen; /* length of ilist in blocks */
+ int32_t vs_aupad; /* length of pad in blocks */
+ int32_t vs_aublocks; /* data blocks in AU */
+ int32_t vs_maxtier; /* log base 2 of aublocks */
+ int32_t vs_inopb; /* number of inodes per blk */
+ int32_t vs_old_inopau; /* obsolete */
+ int32_t vs_old_inopilb; /* obsolete */
+ int32_t vs_old_ndiripau; /* obsolete */
+ int32_t vs_iaddrlen; /* size of indirect addr ext. */
+ int32_t vs_bshift; /* log base 2 of bsize */
+ int32_t vs_inoshift; /* log base 2 of inobp */
int32_t vs_bmask; /* ~( bsize - 1 ) */
int32_t vs_boffmask; /* bsize - 1 */
int32_t vs_old_inomask; /* old_inopilb - 1 */
- int32_t vs_checksum; /* Checksum of V1 data */
+ int32_t vs_checksum; /* checksum of V1 data */
/*
* Version 1, writable
*/
- int32_t vs_free; /* Number of free blocks */
- int32_t vs_ifree; /* Number of free inodes */
- int32_t vs_efree[VXFS_NEFREE]; /* Number of free extents by size */
- int32_t vs_flags; /* Flags ?!? */
- u_int8_t vs_mod; /* Filesystem has been changed */
- u_int8_t vs_clean; /* Clean FS */
- u_int16_t __unused4; /* ??? */
- u_int32_t vs_firstlogid; /* Mount time log ID */
- u_int32_t vs_wtime; /* Last time written - sec */
- u_int32_t vs_wutime; /* Last time written - usec */
+ int32_t vs_free; /* number of free blocks */
+ int32_t vs_ifree; /* number of free inodes */
+ int32_t vs_efree[VXFS_NEFREE]; /* number of free extents by size */
+ int32_t vs_flags; /* flags ?!? */
+ u_int8_t vs_mod; /* filesystem has been changed */
+ u_int8_t vs_clean; /* clean FS */
+ u_int16_t __unused4; /* unused */
+ u_int32_t vs_firstlogid; /* mount time log ID */
+ u_int32_t vs_wtime; /* last time written - sec */
+ u_int32_t vs_wutime; /* last time written - usec */
u_int8_t vs_fname[6]; /* FS name */
u_int8_t vs_fpack[6]; /* FS pack name */
- int32_t vs_logversion; /* Log format version */
- int32_t __unused5; /* ??? */
+ int32_t vs_logversion; /* log format version */
+ int32_t __unused5; /* unused */
/*
* Version 2, Read-only
*/
vx_daddr_t vs_oltext[2]; /* OLT extent and replica */
int32_t vs_oltsize; /* OLT extent size */
- int32_t vs_iauimlen; /* Size of inode map */
- int32_t vs_iausize; /* Size of IAU in blocks */
- int32_t vs_dinosize; /* Size of inode in bytes */
- int32_t vs_old_dniaddr; /* OLD: Sum of indir levels per inode */
- int32_t vs_checksum2; /* Checksum of V2 RO */
+ int32_t vs_iauimlen; /* size of inode map */
+ int32_t vs_iausize; /* size of IAU in blocks */
+ int32_t vs_dinosize; /* size of inode in bytes */
+ int32_t vs_old_dniaddr; /* indir levels per inode */
+ int32_t vs_checksum2; /* checksum of V2 RO */
/*
* Actually much more...
* In core superblock filesystem private data for VxFS.
*/
struct vxfs_sb_info {
- struct vxfs_sb *vsi_raw; /* Raw (on disk) supeblock */
- struct buffer_head *vsi_bp; /* Buffer for raw superblock*/
- struct inode *vsi_fship; /* Fileset header inode */
- struct inode *vsi_ilist; /* Inode list inode */
- struct inode *vsi_stilist; /* Structual inode list inode */
- u_long vsi_iext; /* Initial inode list */
- ino_t vsi_fshino; /* Fileset header inode */
+ struct vxfs_sb *vsi_raw; /* raw (on disk) supeblock */
+ struct buffer_head *vsi_bp; /* buffer for raw superblock*/
+ struct inode *vsi_fship; /* fileset header inode */
+ struct inode *vsi_ilist; /* inode list inode */
+ struct inode *vsi_stilist; /* structual inode list inode */
+ u_long vsi_iext; /* initial inode list */
+ ino_t vsi_fshino; /* fileset header inode */
daddr_t vsi_oltext; /* OLT extent */
daddr_t vsi_oltsize; /* OLT size */
};
};
#define VXFS_IS_ORG(ip,org) ((ip)->vii_orgtype == (org))
-#define VXFS_ISNONE(ip) VXFS_IS_ORG((ip),VXFS_ORG_NONE)
-#define VXFS_ISEXT4(ip) VXFS_IS_ORG((ip),VXFS_ORG_EXT4)
-#define VXFS_ISIMMED(ip) VXFS_IS_ORG((ip),VXFS_ORG_IMMED)
-#define VXFS_ISTYPED(ip) VXFS_IS_ORG((ip),VXFS_ORG_TYPED)
+#define VXFS_ISNONE(ip) VXFS_IS_ORG((ip), VXFS_ORG_NONE)
+#define VXFS_ISEXT4(ip) VXFS_IS_ORG((ip), VXFS_ORG_EXT4)
+#define VXFS_ISIMMED(ip) VXFS_IS_ORG((ip), VXFS_ORG_IMMED)
+#define VXFS_ISTYPED(ip) VXFS_IS_ORG((ip), VXFS_ORG_TYPED)
/*
* SUCH DAMAGE.
*/
-#ident "$Id: vxfs_bmap.c,v 1.19 2001/04/24 19:28:36 hch Exp hch $"
+#ident "$Id: vxfs_bmap.c,v 1.20 2001/04/25 18:11:23 hch Exp hch $"
/*
* Veritas filesystem driver - filesystem to disk block mapping.
#ifndef _VXFS_DIR_H_
#define _VXFS_DIR_H_
-#ident "$Id: vxfs_dir.h,v 1.4 2001/04/24 19:28:36 hch Exp hch $"
+#ident "$Id: vxfs_dir.h,v 1.7 2001/05/21 15:48:26 hch Exp hch $"
/*
* Veritas filesystem driver - directory structure.
/*
* VxFS directory block header.
+ *
+ * This entry is the head of every filesystem block in a directory.
+ * It is used for free space managment and additionally includes
+ * a hash for speeding up directory search (lookup).
+ *
+ * The hash may be empty and in fact we do not use it all in the
+ * Linux driver for now.
*/
struct vxfs_dirblk {
- u_int16_t d_free;
- u_int16_t d_nhash;
- u_int16_t d_hash[1];
+ u_int16_t d_free; /* free space in dirblock */
+ u_int16_t d_nhash; /* no of hash chains */
+ u_int16_t d_hash[1]; /* hash chain */
};
/*
- * Special dirblk for immed inodes: no hash.
+ * VXFS_NAMELEN is the maximum length of the d_name field
+ * of an VxFS directory entry.
*/
-struct vxfs_immed_dirblk {
- u_int16_t d_free;
- u_int16_t d_nhash;
-};
+#define VXFS_NAMELEN 256
/*
* VxFS directory entry.
*/
-#define VXFS_NAME_LEN 256
struct vxfs_direct {
- vx_ino_t d_ino;
- u_int16_t d_reclen;
- u_int16_t d_namelen;
- u_int16_t d_hashnext;
- char d_name[VXFS_NAME_LEN];
+ vx_ino_t d_ino; /* inode number */
+ u_int16_t d_reclen; /* record length */
+ u_int16_t d_namelen; /* d_name length */
+ u_int16_t d_hashnext; /* next hash entry */
+ char d_name[VXFS_NAMELEN]; /* name */
};
+/*
+ * VXFS_DIRPAD defines the directory entry boundaries, is _must_ be
+ * a multiple of four.
+ * VXFS_NAMEMIN is the length of a directory entry with a NULL d_name.
+ * VXFS_DIRROUND is an internal macros that rounds a length to a value
+ * usable for directory sizes.
+ * VXFS_DIRLEN calculates the directory entry size for an entry with
+ * a d_name with size len.
+ */
+#define VXFS_DIRPAD 4
+#define VXFS_NAMEMIN ((int)((struct vxfs_direct *)0)->d_name)
+#define VXFS_DIRROUND(len) ((VXFS_DIRPAD + (len) - 1) & ~(VXFS_DIRPAD -1))
+#define VXFS_DIRLEN(len) (VXFS_DIRROUND(VXFS_NAMEMIN + (len)))
+
+/*
+ * VXFS_DIRBLKOV is the overhead of a specific dirblock.
+ */
+#define VXFS_DIRBLKOV(dbp) ((sizeof(short) * dbp->d_nhash) + 4)
+
#endif /* _VXFS_DIR_H_ */
#ifndef _VXFS_EXTERN_H_
#define _VXFS_EXTERN_H_
-#ident "$Id: vxfs_extern.h,v 1.18 2001/04/24 19:28:36 hch Exp hch $"
+#ident "$Id: vxfs_extern.h,v 1.20 2001/04/26 22:48:44 hch Exp hch $"
/*
* Veritas filesystem driver - external prototypes.
extern int vxfs_read_olt(struct super_block *, u_long);
/* vxfs_subr.c */
+extern struct page * vxfs_get_page(struct inode *, u_long);
+extern __inline__ void vxfs_put_page(struct page *);
extern struct buffer_head * vxfs_bread(struct inode *, int);
#endif /* _VXFS_EXTERN_H_ */
* SUCH DAMAGE.
*/
-#ident "$Id: vxfs_fshead.c,v 1.17 2001/04/24 19:28:36 hch Exp hch $"
+#ident "$Id: vxfs_fshead.c,v 1.18 2001/04/25 18:11:23 hch Exp $"
/*
* Veritas filesystem driver - fileset header routines.
#ifndef _VXFS_FSHEAD_H_
#define _VXFS_FSHEAD_H_
-#ident "$Id: vxfs_fshead.h,v 1.5 2001/04/24 19:28:36 hch Exp hch $"
+#ident "$Id: vxfs_fshead.h,v 1.6 2001/04/25 18:11:23 hch Exp hch $"
/*
* Veritas filesystem driver - fileset header structures.
* Fileset header
*/
struct vxfs_fsh {
- u_int32_t fsh_version; /* Fileset header version */
- u_int32_t fsh_fsindex;
- u_int32_t fsh_time;
- u_int32_t fsh_utime;
- u_int32_t fsh_extop;
- vx_ino_t fsh_ninodes;
- u_int32_t fsh_nau;
- u_int32_t fsh_old_ilesize;
- u_int32_t fsh_dflags;
- u_int32_t fsh_quota;
- vx_ino_t fsh_maxinode;
- vx_ino_t fsh_iauino;
- vx_ino_t fsh_ilistino[2];
- vx_ino_t fsh_lctino;
+ u_int32_t fsh_version; /* fileset header version */
+ u_int32_t fsh_fsindex; /* fileset index */
+ u_int32_t fsh_time; /* modification time - sec */
+ u_int32_t fsh_utime; /* modification time - usec */
+ u_int32_t fsh_extop; /* extop flags */
+ vx_ino_t fsh_ninodes; /* allocated inodes */
+ u_int32_t fsh_nau; /* number of IAUs */
+ u_int32_t fsh_old_ilesize; /* old size of ilist */
+ u_int32_t fsh_dflags; /* flags */
+ u_int32_t fsh_quota; /* quota limit */
+ vx_ino_t fsh_maxinode; /* maximum inode number */
+ vx_ino_t fsh_iauino; /* IAU inode */
+ vx_ino_t fsh_ilistino[2]; /* ilist inodes */
+ vx_ino_t fsh_lctino; /* link count table inode */
/*
* Slightly more fields follow, but they
* SUCH DAMAGE.
*/
-#ident "$Id: vxfs_immed.c,v 1.9 2001/04/24 19:28:36 hch Exp hch $"
+#ident "$Id: vxfs_immed.c,v 1.10 2001/04/25 18:11:23 hch Exp hch $"
/*
* Veritas filesystem driver - support for 'immed' inodes.
* SUCH DAMAGE.
*/
-#ident "$Id: vxfs_inode.c,v 1.29 2001/04/24 19:28:36 hch Exp hch $"
+#ident "$Id: vxfs_inode.c,v 1.34 2001/05/21 15:33:08 hch Exp hch $"
/*
* Veritas filesystem driver - inode routines.
printk(KERN_DEBUG "---------------------------\n");
printk(KERN_DEBUG "mode is %x\n", vip->vii_mode);
- printk(KERN_DEBUG "nlink:%u uid:%u gid:%u\n",
+ printk(KERN_DEBUG "nlink:%u, uid:%u, gid:%u\n",
vip->vii_nlink, vip->vii_uid, vip->vii_gid);
- printk(KERN_DEBUG "size=%Lx blocks=%u\n",
+ printk(KERN_DEBUG "size:%Lx, blocks:%u\n",
vip->vii_size, vip->vii_blocks);
- printk(KERN_DEBUG "orgtype=%u\n", vip->vii_orgtype);
+ printk(KERN_DEBUG "orgtype:%u\n", vip->vii_orgtype);
}
#endif
/**
- * vxfs_iget - find inode based on extent #
+ * vxfs_blkiget - find inode based on extent #
* @sbp: superblock of the filesystem we search in
* @extent: number of the extent to search
* @ino: inode number to search
*
* Description:
- * vxfs_iget searches inode @ino in the filesystem described by
- * @sbp in the extent @extent.
+ * vxfs_blkiget searches inode @ino in the filesystem described by
+ * @sbp in the extent @extent.
+ * Returns the matching VxFS inode on success, else a NULL pointer.
*
- * Returs:
- * The matching VxFS inode on success, else a NULL pointer.
+ * NOTE:
+ * While __vxfs_iget uses that pagecache this function uses the
+ * buffercache. This function should not be used outside the
+ * read_super() method, othwerwise the data may be incoherent.
*/
struct vxfs_inode_info *
vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
* @ilistp: inode list
*
* Description:
- * __vxfs_iget searches for @ino in the inode list @ilistp
- * of the filesystem described by @sbp.
- *
- * Returns:
- * The matching VxFS inode on success, else a NULL pointer.
+ * Search the for inode number @ino in the filesystem
+ * described by @sbp. Use the specified inode table (@ilistp).
+ * Returns the matching VxFS inode on success, else a NULL pointer.
*/
static struct vxfs_inode_info *
__vxfs_iget(struct super_block *sbp, ino_t ino, struct inode *ilistp)
{
- struct buffer_head *bp;
+ struct page *pp;
u_long offset;
- offset = (ino % (sbp->s_blocksize / VXFS_ISIZE)) * VXFS_ISIZE;
- bp = vxfs_bread(ilistp, ino * VXFS_ISIZE / sbp->s_blocksize);
+ offset = (ino % (PAGE_SIZE / VXFS_ISIZE)) * VXFS_ISIZE;
+ pp = vxfs_get_page(ilistp, ino * VXFS_ISIZE / PAGE_SIZE);
- if (buffer_mapped(bp)) {
+ if (!IS_ERR(pp)) {
struct vxfs_inode_info *vip;
struct vxfs_dinode *dip;
+ caddr_t kaddr = (char *)page_address(pp);
if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, SLAB_KERNEL)))
goto fail;
- dip = (struct vxfs_dinode *)(bp->b_data + offset);
+ dip = (struct vxfs_dinode *)(kaddr + offset);
memcpy(vip, dip, sizeof(struct vxfs_inode_info));
#ifdef DIAGNOSTIC
vxfs_dumpi(vip, ino);
#endif
- brelse(bp);
+ vxfs_put_page(pp);
return (vip);
}
+ printk(KERN_WARNING "vxfs: error on page %p\n", pp);
+ return NULL;
+
fail:
printk(KERN_WARNING "vxfs: unable to read inode %ld\n", ino);
- brelse(bp);
+ vxfs_put_page(pp);
return NULL;
}
-/**
- * vxfs_iget - find inode using the inode list
- * @sbp: VFS superblock
- * @ino: inode #
- *
- * Description:
- * Find inode @ino in the filesystem described by @sbp using
- * the inode list.
- *
- * Returns:
- * The matching VxFS inode on success, else a NULL pointer.
- */
-static struct vxfs_inode_info *
-vxfs_iget(struct super_block *sbp, ino_t ino)
-{
- return __vxfs_iget(sbp, ino, VXFS_SBI(sbp)->vsi_ilist);
-}
-
/**
* vxfs_stiget - find inode using the structural inode list
* @sbp: VFS superblock
* Description:
* Find inode @ino in the filesystem described by @sbp using
* the structural inode list.
- *
- * Returns:
- * The matching VxFS inode on success, else a NULL pointer.
+ * Returns the matching VxFS inode on success, else a NULL pointer.
*/
struct vxfs_inode_info *
vxfs_stiget(struct super_block *sbp, ino_t ino)
* @vip: VxFS inode
*
* Description:
- * vxfs_transmod returns a Linux mode_t for a given
- * VxFS inode structure.
- *
- * Notes:
- * Use a table instead?
+ * vxfs_transmod returns a Linux mode_t for a given
+ * VxFS inode structure.
*/
static __inline__ mode_t
vxfs_transmod(struct vxfs_inode_info *vip)
* @vip: VxFS inode
*
* Description:
- * vxfs_instino is a helper function to fill in all relevant
- * fields in @ip from @vip.
+ * vxfs_instino is a helper function to fill in all relevant
+ * fields in @ip from @vip.
*/
static void
vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip)
* @vip: fspriv inode
*
* Description:
- * vxfs_fake_inode gets a fake inode (not in the inode hash) for a
- * superblock, vxfs_inode pair.
- *
- * Returns:
- * VFS inode structure filled in.
+ * vxfs_fake_inode gets a fake inode (not in the inode hash) for a
+ * superblock, vxfs_inode pair.
+ * Returns the filled VFS inode.
*/
struct inode *
vxfs_fake_inode(struct super_block *sbp, struct vxfs_inode_info *vip)
{
- struct inode *ip;
-
- if (!(ip = get_empty_inode()))
- return NULL;
-
- ip->i_sb = sbp;
- ip->i_dev = sbp->s_dev;
- vxfs_iinit(ip, vip);
+ struct inode *ip = NULL;
+ if ((ip = new_inode(sbp))) {
+ vxfs_iinit(ip, vip);
+ ip->i_mapping->a_ops = &vxfs_aops;
+ }
return (ip);
}
* @ip: inode pointer to fill
*
* Description:
- * vxfs_read_inode reads the disk inode for @ip and fills
- * in all relevant fields in @ip.
- *
- * Locking:
- * We are under the bkl.
+ * vxfs_read_inode reads the disk inode for @ip and fills
+ * in all relevant fields in @ip.
*/
void
vxfs_read_inode(struct inode *ip)
struct address_space_operations *aops;
ino_t ino = ip->i_ino;
- if (!(vip = vxfs_iget(sbp, ino)))
+ if (!(vip = __vxfs_iget(sbp, ino, VXFS_SBI(sbp)->vsi_ilist)))
return;
vxfs_iinit(ip, vip);
* @ip: inode to discard.
*
* Description:
- * vxfs_put_inode() is called on each iput. If we are the last
- * link in memory, free the fspriv inode area.
- *
- * Locking:
- * No lock is held on entry.
+ * vxfs_put_inode() is called on each iput. If we are the last
+ * link in memory, free the fspriv inode area.
*/
void
vxfs_put_inode(struct inode *ip)
#ifndef _VXFS_INODE_H_
#define _VXFS_INODE_H_
-#ident "$Id: vxfs_inode.h,v 1.13 2001/04/24 19:28:36 hch Exp hch $"
+#ident "$Id: vxfs_inode.h,v 1.14 2001/04/25 18:11:23 hch Exp hch $"
/*
* Veritas filesystem driver - inode structure.
* SUCH DAMAGE.
*/
-#ident "$Id: vxfs_lookup.c,v 1.11 2001/04/24 19:28:36 hch Exp hch $"
+#ident "$Id: vxfs_lookup.c,v 1.17 2001/05/21 15:23:53 hch Exp hch $"
/*
* Veritas filesystem driver - lookup and other directory related code.
#include "vxfs.h"
#include "vxfs_dir.h"
#include "vxfs_inode.h"
+#include "vxfs_extern.h"
/*
* Number of VxFS blocks per page.
.readdir = vxfs_readdir,
};
-
-static __inline__ void
-vxfs_put_page(struct page *page)
-{
- kunmap(page);
- page_cache_release(page);
-}
static __inline__ u_long
dir_pages(struct inode *inode)
return (ip->i_size + bsize - 1) & ~(bsize - 1);
}
-/**
- * vxfs_get_page - read a page into memory.
- * @ip: inode to read from
- * @n: page number
- *
- * Description:
- * vxfs_get_page reads the @n th page of @ip into the pagecache.
- *
- * Returns:
- * The wanted page on success, else a NULL pointer.
- */
-static struct page *
-vxfs_get_page(struct inode *dir, u_long n)
-{
- struct address_space * mapping = dir->i_mapping;
- struct page * page;
-
- page = read_cache_page(mapping, n,
- (filler_t*)mapping->a_ops->readpage, NULL);
-
- if (!IS_ERR(page)) {
- wait_on_page(page);
- kmap(page);
- if (!Page_Uptodate(page))
- goto fail;
- /** if (!PageChecked(page)) **/
- /** vxfs_check_page(page); **/
- if (PageError(page))
- goto fail;
- }
-
- return (page);
-
-fail:
- vxfs_put_page(page);
- return ERR_PTR(-EIO);
-}
-
/*
* NOTE! unlike strncmp, vxfs_match returns 1 for success, 0 for failure.
*
- * len <= VXFS_NAME_LEN and de != NULL are guaranteed by caller.
+ * len <= VXFS_NAMELEN and de != NULL are guaranteed by caller.
*/
static __inline__ int
vxfs_match(int len, const char * const name, struct vxfs_direct *de)
static struct vxfs_direct *
vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp)
{
- const char *name = dp->d_name.name;
- u_long npages = dir_pages(ip), n, i;
+ u_long npages, page, nblocks, pblocks, block;
u_long bsize = ip->i_sb->s_blocksize;
+ const char *name = dp->d_name.name;
int namelen = dp->d_name.len;
- loff_t pos = ip->i_size - 2;
- struct vxfs_direct *de;
- struct page *pp;
-
+
+ npages = dir_pages(ip);
+ nblocks = dir_blocks(ip);
+ pblocks = VXFS_BLOCK_PER_PAGE(ip->i_sb);
- for (n = 0; n < npages; n++) {
- char *kaddr;
- u_long max;
+ for (page = 0; page < npages; page++) {
+ caddr_t kaddr;
+ struct page *pp;
- pp = vxfs_get_page(ip, n);
+ pp = vxfs_get_page(ip, page);
if (IS_ERR(pp))
continue;
+ kaddr = (caddr_t)page_address(pp);
- kaddr = (char *)page_address(pp);
- max = (pos + bsize - 1) & ~(bsize - 1);
-
- for (i = 0; i <= (PAGE_CACHE_SIZE / bsize) && i <= max; i++) {
- struct vxfs_dirblk *blp;
- char *lim;
+ for (block = 0; block <= nblocks && block <= pblocks; block++) {
+ caddr_t baddr, limit;
+ struct vxfs_dirblk *dbp;
+ struct vxfs_direct *de;
- blp = (struct vxfs_dirblk *)(kaddr + (i * bsize));
- de = (struct vxfs_direct *)((char *)blp + (2 * blp->d_nhash) + 4);
+ baddr = kaddr + (block * bsize);
+ limit = baddr + bsize - VXFS_DIRLEN(1);
- /*
- * The magic number 48 stands for the reclen offset
- * in the direct plus the size of reclen.
- */
- lim = (char *)blp + bsize - 48;
-
- do {
- if ((char *)de > lim)
- break;
- if ((char *)de + de->d_reclen > lim)
- break;
+ dbp = (struct vxfs_dirblk *)baddr;
+ de = (struct vxfs_direct *)(baddr + VXFS_DIRBLKOV(dbp));
+
+ for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) {
if (!de->d_reclen)
break;
- if (vxfs_match(namelen, name, de))
- goto found;
- } while ((de = vxfs_next_entry(de)) != NULL);
+ if (!de->d_ino)
+ continue;
+ if (vxfs_match(namelen, name, de)) {
+ *ppp = pp;
+ return (de);
+ }
+ }
}
vxfs_put_page(pp);
}
return NULL;
-
-found:
- *ppp = pp;
- return (de);
}
/**
struct inode *ip = NULL;
ino_t ino;
- if (dp->d_name.len > VXFS_NAME_LEN)
+ if (dp->d_name.len > VXFS_NAMELEN)
return ERR_PTR(-ENAMETOOLONG);
ino = vxfs_inode_by_name(dip, dp);
/* fallthrough */
}
- if (fp->f_pos >= ip->i_size)
- goto out;
-
pos = fp->f_pos - 2;
- offset = pos & ~PAGE_CACHE_MASK;
+
+ if (pos > VXFS_DIRROUND(ip->i_size))
+ return 0;
+
page = pos >> PAGE_CACHE_SHIFT;
- block = pos & (sbp->s_blocksize - 1);
+ offset = pos & ~PAGE_CACHE_MASK;
+ block = pos >> sbp->s_blocksize_bits;
npages = dir_pages(ip);
nblocks = dir_blocks(ip);
pblocks = VXFS_BLOCK_PER_PAGE(sbp);
- for (; page < npages; page++, offset = 0) {
- char *kaddr, *lim;
- struct vxfs_dirblk *dblkp;
- struct vxfs_direct *de;
+ for (; page < npages; page++, block = 0) {
+ caddr_t kaddr;
struct page *pp;
pp = vxfs_get_page(ip, page);
if (IS_ERR(pp))
continue;
-
- kaddr = (char *)page_address(pp);
+ kaddr = (caddr_t)page_address(pp);
for (; block <= nblocks && block <= pblocks; block++) {
- dblkp = (struct vxfs_dirblk *)
- (kaddr + (block * bsize));
+ caddr_t baddr, limit;
+ struct vxfs_dirblk *dbp;
+ struct vxfs_direct *de;
+
+ baddr = kaddr + (block * bsize);
+ limit = baddr + bsize - VXFS_DIRLEN(1);
+
+ dbp = (struct vxfs_dirblk *)baddr;
de = (struct vxfs_direct *)
- ((char *)dblkp + (2 * dblkp->d_nhash) + 4);
-
- /*
- * The magic number 48 stands for the reclen offset
- * in the direct plus the size of reclen.
- */
- lim = (char *)dblkp + bsize - 48;
+ (offset ?
+ (kaddr + offset) :
+ (baddr + VXFS_DIRBLKOV(dbp)));
- do {
+ for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) {
int over;
- if ((char *)de > lim)
- break;
- if ((char *)de + de->d_reclen > lim)
- break;
if (!de->d_reclen)
break;
if (!de->d_ino)
continue;
- offset = (char *)de - kaddr;
-
+ offset = (caddr_t)de - kaddr;
over = filler(retp, de->d_name, de->d_namelen,
- (page << PAGE_CACHE_SHIFT) | offset,
- de->d_ino, DT_UNKNOWN);
+ ((page << PAGE_CACHE_SHIFT) | offset) + 2,
+ de->d_ino, DT_UNKNOWN);
if (over) {
vxfs_put_page(pp);
goto done;
}
- } while ((de = vxfs_next_entry(de)) != NULL);
+ }
}
-
vxfs_put_page(pp);
- block = 0;
+ offset = 0;
}
done:
* SUCH DAMAGE.
*/
-#ident "$Id: vxfs_olt.c,v 1.7 2001/04/24 19:28:36 hch Exp hch $"
+#ident "$Id: vxfs_olt.c,v 1.8 2001/04/25 18:11:23 hch Exp hch $"
/*
* Veritas filesystem driver - object location table support.
#ifndef _VXFS_OLT_H_
#define _VXFS_OLT_H_
-#ident "$Id: vxfs_olt.h,v 1.4 2001/04/24 19:28:36 hch Exp hch $"
+#ident "$Id: vxfs_olt.h,v 1.5 2001/04/25 18:11:23 hch Exp hch $"
/*
* Veritas filesystem driver - Object Location Table data structures.
* SUCH DAMAGE.
*/
-#ident "$Id: vxfs_subr.c,v 1.3 2001/04/24 19:28:36 hch Exp hch $"
+#ident "$Id: vxfs_subr.c,v 1.5 2001/04/26 22:49:51 hch Exp hch $"
/*
* Veritas filesystem driver - shared subroutines.
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/slab.h>
+#include <linux/pagemap.h>
#include "vxfs_extern.h"
};
+/**
+ * vxfs_get_page - read a page into memory.
+ * @ip: inode to read from
+ * @n: page number
+ *
+ * Description:
+ * vxfs_get_page reads the @n th page of @ip into the pagecache.
+ *
+ * Returns:
+ * The wanted page on success, else a NULL pointer.
+ */
+struct page *
+vxfs_get_page(struct inode *ip, u_long n)
+{
+ struct address_space * mapping = ip->i_mapping;
+ struct page * pp;
+
+ pp = read_cache_page(mapping, n,
+ (filler_t*)mapping->a_ops->readpage, NULL);
+
+ if (!IS_ERR(pp)) {
+ wait_on_page(pp);
+ kmap(pp);
+ if (!Page_Uptodate(pp))
+ goto fail;
+ /** if (!PageChecked(pp)) **/
+ /** vxfs_check_page(pp); **/
+ if (PageError(pp))
+ goto fail;
+ }
+
+ return (pp);
+
+fail:
+ vxfs_put_page(pp);
+ return ERR_PTR(-EIO);
+}
+
+__inline__ void
+vxfs_put_page(struct page *pp)
+{
+ kunmap(pp);
+ page_cache_release(pp);
+}
+
/**
* vxfs_bread - read buffer for a give inode,block tuple
* @ip: inode
* @block: logical block
*
* Description:
- * The vxfs_bread function performs a bmap operation for
- * the given inode and block and reads the result block
- * into main memory.
+ * The vxfs_bread function reads block no @block of
+ * @ip into the buffercache.
*
* Returns:
* The resulting &struct buffer_head.
* SUCH DAMAGE.
*/
-#ident "$Id: vxfs_super.c,v 1.22 2001/04/24 19:28:36 hch Exp hch $"
+#ident "$Id: vxfs_super.c,v 1.24 2001/05/20 15:21:14 hch Exp hch $"
/*
* Veritas filesystem driver - superblock related routines.
bufp->f_bavail = 0;
bufp->f_files = 0;
bufp->f_ffree = infp->vsi_raw->vs_ifree;
- bufp->f_namelen = VXFS_NAME_LEN;
+ bufp->f_namelen = VXFS_NAMELEN;
return 0;
}
bdput(inode->i_bdev);
inode->i_bdev = NULL;
}
+ if (inode->i_cdev) {
+ cdput(inode->i_cdev);
+ inode->i_cdev = NULL;
+ }
inode->i_state = I_CLEAR;
}
memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));
inode->i_pipe = NULL;
inode->i_bdev = NULL;
+ inode->i_cdev = NULL;
inode->i_data.a_ops = &empty_aops;
inode->i_data.host = inode;
inode->i_data.gfp_mask = GFP_HIGHUSER;
D1(printk (KERN_NOTICE "jffs_put_super(): Successfully waited on thread.\n"));
- sb->s_dev = 0;
jffs_cleanup_control((struct jffs_control *)sb->u.generic_sbp);
D1(printk(KERN_NOTICE "JFFS: Successfully unmounted device %s.\n",
kdevname(dev)));
if (status < 0)
return status;
- if ((status = nlmclnt_proc(inode, cmd, fl)) < 0)
+ lock_kernel();
+ status = nlmclnt_proc(inode, cmd, fl);
+ unlock_kernel();
+ if (status < 0)
return status;
- else
- status = 0;
+
+ status = 0;
/*
* Make sure we clear the cache whenever we try to get the lock.
req = _nfs_find_request(inode, page);
if (req) {
if (!nfs_lock_request(req)) {
+ int error;
spin_unlock(&nfs_wreq_lock);
- nfs_wait_on_request(req);
+ error = nfs_wait_on_request(req);
nfs_release_request(req);
+ if (error < 0)
+ return ERR_PTR(error);
continue;
}
spin_unlock(&nfs_wreq_lock);
* 02/13/00 VTOC partition support added
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/genhd.h>
inode->i_gid = current->fsgid;
inode->i_blksize = PAGE_CACHE_SIZE;
inode->i_blocks = 0;
- inode->i_rdev = to_kdev_t(dev);
+ inode->i_rdev = NODEV;
inode->i_mapping->a_ops = &ramfs_aops;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
switch (mode & S_IFMT) {
return sb;
}
-static void kill_super(struct super_block *sb, int umount_root)
+static void kill_super(struct super_block *sb)
{
struct block_device *bdev;
kdev_t dev;
sb->s_type = NULL;
unlock_super(sb);
up_write(&sb->s_umount);
- if (umount_root) {
- /* special: the old device driver is going to be
- a ramdisk and the point of this call is to free its
- protected memory (even if dirty). */
- destroy_buffers(dev);
- }
if (bdev) {
blkdev_put(bdev, BDEV_FS);
bdput(bdev);
}
mnt = add_vfsmnt(NULL, sb->s_root, NULL);
if (!mnt) {
- kill_super(sb, 0);
+ kill_super(sb);
return ERR_PTR(-ENOMEM);
}
type->kern_mnt = mnt;
struct super_block *sb = mnt->mnt_sb;
spin_lock(&dcache_lock);
remove_vfsmnt(mnt);
- kill_super(sb, 0);
+ kill_super(sb);
}
/*
return 0;
}
-static int do_umount(struct vfsmount *mnt, int umount_root, int flags)
+static int do_umount(struct vfsmount *mnt, int flags)
{
struct super_block * sb = mnt->mnt_sb;
* /reboot - static binary that would close all descriptors and
* call reboot(9). Then init(8) could umount root and exec /reboot.
*/
- if (mnt == current->fs->rootmnt && !umount_root) {
+ if (mnt == current->fs->rootmnt) {
/*
* Special case for "unmounting" root ...
* we just try to remount it readonly.
mntput(mnt);
remove_vfsmnt(mnt);
- kill_super(sb, umount_root);
+ kill_super(sb);
return 0;
}
dput(nd.dentry);
/* puts nd.mnt */
down(&mount_sem);
- retval = do_umount(nd.mnt, 0, flags);
+ retval = do_umount(nd.mnt, flags);
up(&mount_sem);
goto out;
dput_and_out:
if (fstype->fs_flags & FS_SINGLE)
put_filesystem(fstype);
if (list_empty(&sb->s_mounts))
- kill_super(sb, 0);
+ kill_super(sb);
goto unlock_out;
}
dput(devfs_nd.dentry);
down(&mount_sem);
/* puts devfs_nd.mnt */
- do_umount(devfs_nd.mnt, 0, 0);
+ do_umount(devfs_nd.mnt, 0);
up(&mount_sem);
} else
path_release(&devfs_nd);
error = path_walk(put_old, &nd);
if (error) {
int blivet;
+ struct block_device *ramdisk = old_rootmnt->mnt_sb->s_bdev;
+ blivet = blkdev_get(ramdisk, FMODE_READ, 0, BDEV_FS);
printk(KERN_NOTICE "Trying to unmount old root ... ");
- blivet = do_umount(old_rootmnt, 1, 0);
if (!blivet) {
- printk("okay\n");
- return 0;
+ blivet = do_umount(old_rootmnt, 0);
+ if (!blivet) {
+ ioctl_by_bdev(ramdisk, BLKFLSBUF, 0);
+ printk("okay\n");
+ error = 0;
+ }
+ blkdev_put(ramdisk, BDEV_FS);
}
- printk(KERN_ERR "error %d\n", blivet);
+ if (blivet)
+ printk(KERN_ERR "error %d\n", blivet);
return error;
}
/* FIXME: we should hold i_zombie on nd.dentry */
__asm__("stw %1,%0" : "=m"(mem) : "r"(val))
#endif
+/* Somewhere in the middle of the GCC 2.96 development cycle, we implemented
+ a mechanism by which the user can annotate likely branch directions and
+ expect the blocks to be reordered appropriately. Define __builtin_expect
+ to nothing for earlier compilers. */
+
+#if __GNUC__ == 2 && __GNUC_MINOR__ < 96
+#define __builtin_expect(x, expected_value) (x)
+#endif
+
#endif /* __ALPHA_COMPILER_H */
extern int pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask);
/* Return the index of the PCI controller for device PDEV. */
-static __inline__ int pci_controller_num(struct pci_dev *pdev)
-{
- struct pci_controller *hose = pdev->sysdata;
-
- if (hose != NULL)
- return hose->index;
-
- return -ENXIO;
-}
-
+extern int pci_controller_num(struct pci_dev *pdev);
#endif /* __KERNEL__ */
/* Values for the `which' argument to sys_pciconfig_iobase. */
#include <asm/current.h>
#include <asm/system.h>
#include <asm/atomic.h>
-#include <linux/compiler.h>
+#include <asm/compiler.h>
#include <linux/wait.h>
#include <linux/rwsem.h>
* architectures where unaligned accesses aren't as simple.
*/
+/**
+ * get_unaligned - get value from possibly mis-aligned location
+ * @ptr: pointer to value
+ *
+ * This macro should be used for accessing values larger in size than
+ * single bytes at locations that are expected to be improperly aligned,
+ * e.g. retrieving a u16 value from a location not u16-aligned.
+ *
+ * Note that unaligned accesses can be very expensive on some architectures.
+ */
#define get_unaligned(ptr) (*(ptr))
+/**
+ * put_unaligned - put value to a possibly mis-aligned location
+ * @val: value to place
+ * @ptr: pointer to location
+ *
+ * This macro should be used for placing values larger in size than
+ * single bytes at locations that are expected to be improperly aligned,
+ * e.g. writing a u16 value to a location not u16-aligned.
+ *
+ * Note that unaligned accesses can be very expensive on some architectures.
+ */
#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
#endif
+/*
+ * BK Id: SCCS/s.8xx_immap.h 1.5 05/17/01 18:14:24 cort
+ */
/*
* MPC8xx Internal Memory Map
+/*
+ * BK Id: SCCS/s.a.out.h 1.5 05/17/01 18:14:24 cort
+ */
#ifndef __PPC_A_OUT_H__
#define __PPC_A_OUT_H__
+/*
+ * BK Id: SCCS/s.amigahw.h 1.5 05/17/01 18:14:24 cort
+ */
#ifdef __KERNEL__
#ifndef __ASMPPC_AMIGAHW_H
#define __ASMPPC_AMIGAHW_H
+/*
+ * BK Id: SCCS/s.amigaints.h 1.5 05/17/01 18:14:24 cort
+ */
/*
** amigaints.h -- Amiga Linux interrupt handling structs and prototypes
**
+/*
+ * BK Id: SCCS/s.amigappc.h 1.5 05/17/01 18:14:24 cort
+ */
/*
** asm-m68k/amigappc.h -- This header defines some values and pointers for
** the Phase 5 PowerUp card.
+/*
+ * BK Id: SCCS/s.amigayle.h 1.5 05/17/01 18:14:24 cort
+ */
#include <asm-m68k/amigayle.h>
+/*
+ * BK Id: SCCS/s.amipcmcia.h 1.5 05/17/01 18:14:24 cort
+ */
#include <asm-m68k/amipcmcia.h>
+/*
+ * BK Id: SCCS/s.atomic.h 1.8 05/17/01 18:14:24 cort
+ */
/*
* PowerPC atomic operations
*/
+/*
+ * BK Id: SCCS/s.backlight.h 1.5 05/17/01 18:14:24 cort
+ */
/*
* Routines for handling backlight control on PowerBooks
*
/*
- * $Id: bitops.h,v 1.12 2000/02/09 03:28:31 davem Exp $
+ * BK Id: SCCS/s.bitops.h 1.7 05/17/01 18:14:24 cort
+ */
+/*
* bitops.h: Bit string operations on the ppc
*/
+/*
+ * BK Id: SCCS/s.board.h 1.5 05/17/01 18:14:24 cort
+ */
/*
*
* Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+/*
+ * BK Id: SCCS/s.bootinfo.h 1.5 05/17/01 18:14:24 cort
+ */
/*
* Non-machine dependent bootinfo structure. Basic idea
* borrowed from the m68k.
+/*
+ * BK Id: SCCS/s.bootx.h 1.5 05/17/01 18:14:24 cort
+ */
/*
* This file describes the structure passed from the BootX application
* (for MacOS) when it is used to boot Linux.
+/*
+ * BK Id: SCCS/s.bseip.h 1.7 05/17/01 18:14:24 cort
+ */
/*
* A collection of structures, addresses, and values associated with
+/*
+ * BK Id: SCCS/s.bugs.h 1.5 05/17/01 18:14:24 cort
+ */
/*
* This file is included by 'init/main.c'
*/
-#ifndef _PPC_BYTEORDER_H
-#define _PPC_BYTEORDER_H
-
/*
- * $Id: byteorder.h,v 1.14 1998/08/12 05:07:12 paulus Exp $
+ * BK Id: SCCS/s.byteorder.h 1.5 05/17/01 18:14:24 cort
*/
+#ifndef _PPC_BYTEORDER_H
+#define _PPC_BYTEORDER_H
#include <asm/types.h>
+/*
+ * BK Id: SCCS/s.cache.h 1.5 05/17/01 18:14:24 cort
+ */
/*
* include/asm-ppc/cache.h
*/
+/*
+ * BK Id: SCCS/s.checksum.h 1.8 05/17/01 18:14:24 cort
+ */
#ifdef __KERNEL__
#ifndef _PPC_CHECKSUM_H
#define _PPC_CHECKSUM_H
unsigned short proto,
unsigned int sum)
{
- __asm__("
+ __asm__("\n\
addc %0,%0,%1 \n\
adde %0,%0,%2 \n\
adde %0,%0,%3 \n\
+/*
+ * BK Id: SCCS/s.cpm_8260.h 1.7 05/17/01 18:14:24 cort
+ */
/*
* MPC8260 Communication Processor Module.
+/*
+ * BK Id: SCCS/s.current.h 1.5 05/17/01 18:14:24 cort
+ */
#ifdef __KERNEL__
#ifndef _PPC_CURRENT_H
#define _PPC_CURRENT_H
+/*
+ * BK Id: SCCS/s.dbdma.h 1.5 05/17/01 18:14:24 cort
+ */
/*
* Definitions for using the Apple Descriptor-Based DMA controller
* in Power Macintosh computers.
+/*
+ * BK Id: SCCS/s.delay.h 1.7 05/17/01 18:14:24 cort
+ */
#ifdef __KERNEL__
#ifndef _PPC_DELAY_H
#define _PPC_DELAY_H
+/*
+ * BK Id: SCCS/s.div64.h 1.5 05/17/01 18:14:24 cort
+ */
#ifndef __PPC_DIV64
#define __PPC_DIV64
-/* $Id: dma.h,v 1.3 1997/03/16 06:20:39 cort Exp $
+/*
+ * BK Id: SCCS/s.dma.h 1.8 05/17/01 18:14:24 cort
+ */
+/*
* linux/include/asm/dma.h: Defines for using and allocating dma channels.
* Written by Hennus Bergman, 1992.
* High DMA channel support & info by Hannu Savolainen
+/*
+ * BK Id: SCCS/s.elf.h 1.10 05/17/01 18:14:24 cort
+ */
#ifndef __PPC_ELF_H
#define __PPC_ELF_H
+/*
+ * BK Id: SCCS/s.errno.h 1.7 05/17/01 18:14:24 cort
+ */
#ifndef _PPC_ERRNO_H
#define _PPC_ERRNO_H
+/*
+ * BK Id: SCCS/s.est8260.h 1.5 05/17/01 18:14:24 cort
+ */
/* Board information for the EST8260, which should be generic for
* all 8260 boards. The IMMR is now given to us so the hard define
+/*
+ * BK Id: SCCS/s.fads.h 1.8 05/17/01 18:14:24 cort
+ */
/*
* A collection of structures, addresses, and values associated with
+/*
+ * BK Id: SCCS/s.fcntl.h 1.5 05/17/01 18:14:24 cort
+ */
#ifndef _PPC_FCNTL_H
#define _PPC_FCNTL_H
+/*
+ * BK Id: SCCS/s.feature.h 1.9 05/17/01 18:14:24 cort
+ */
/*
* Definitions for accessing the Feature Control Register (FCR)
* on Power Macintoshes and similar machines. The FCR lets us
+/*
+ * BK Id: SCCS/s.floppy.h 1.5 05/17/01 18:14:24 cort
+ */
/*
* Architecture specific parts of the Floppy driver
*
+/*
+ * BK Id: SCCS/s.gemini.h 1.5 05/17/01 18:14:24 cort
+ */
/*
* include/asm-ppc/gemini.h
*
+/*
+ * BK Id: SCCS/s.gemini_serial.h 1.5 05/17/01 18:14:24 cort
+ */
#ifdef __KERNEL__
#ifndef __ASMPPC_GEMINI_SERIAL_H
#define __ASMPPC_GEMINI_SERIAL_H
+/*
+ * BK Id: SCCS/s.gg2.h 1.5 05/17/01 18:14:24 cort
+ */
/*
* asm-ppc/gg2.h -- VLSI VAS96011/12 `Golden Gate 2' register definitions
*
+/*
+ * BK Id: SCCS/s.hardirq.h 1.7 05/17/01 18:14:24 cort
+ */
#ifdef __KERNEL__
#ifndef __ASM_HARDIRQ_H
#define __ASM_HARDIRQ_H
+/*
+ * BK Id: SCCS/s.hdreg.h 1.5 05/17/01 18:14:24 cort
+ */
/*
* linux/include/asm-ppc/hdreg.h
*
+/*
+ * BK Id: SCCS/s.heathrow.h 1.7 05/17/01 18:14:24 cort
+ */
/*
* heathrow.h: definitions for using the "Heathrow" I/O controller chip.
*
+/*
+ * BK Id: SCCS/s.highmem.h 1.7 05/17/01 18:14:24 cort
+ */
/*
* highmem.h: virtual kernel memory mappings for high memory
*
/*
- * $Id: irq_control.h,v 1.8 1999/09/15 23:58:48 cort Exp $
- *
+ * BK Id: SCCS/s.hw_irq.h 1.10 05/17/01 18:14:24 cort
+ */
+/*
* Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
*/
#ifdef __KERNEL__
+/*
+ * BK Id: SCCS/s.hydra.h 1.5 05/17/01 18:14:24 cort
+ */
/*
* asm-ppc/hydra.h -- Mac I/O `Hydra' definitions
*
+/*
+ * BK Id: SCCS/s.ide.h 1.10 05/17/01 18:14:24 cort
+ */
/*
* linux/include/asm-ppc/ide.h
*
+/*
+ * BK Id: SCCS/s.immap_8260.h 1.5 05/17/01 18:14:24 cort
+ */
/*
* MPC8260 Internal Memory Map
+/*
+ * BK Id: SCCS/s.init.h 1.5 05/17/01 18:14:24 cort
+ */
#ifdef __KERNEL__
#ifndef _PPC_INIT_H
#define _PPC_INIT_H
+/*
+ * BK Id: SCCS/s.io.h 1.7 05/17/01 18:14:24 cort
+ */
#ifdef __KERNEL__
#ifndef _PPC_IO_H
#define _PPC_IO_H
+/*
+ * BK Id: SCCS/s.ioctl.h 1.5 05/17/01 18:14:24 cort
+ */
#ifndef _PPC_IOCTL_H
#define _PPC_IOCTL_H
+/*
+ * BK Id: SCCS/s.ioctls.h 1.7 05/17/01 18:14:24 cort
+ */
#ifndef _ASM_PPC_IOCTLS_H
#define _ASM_PPC_IOCTLS_H
+/*
+ * BK Id: SCCS/s.ipc.h 1.5 05/17/01 18:14:24 cort
+ */
#ifndef __PPC_IPC_H__
#define __PPC_IPC_H__
+/*
+ * BK Id: SCCS/s.ipcbuf.h 1.5 05/17/01 18:14:24 cort
+ */
#ifndef __PPC_IPCBUF_H__
#define __PPC_IPCBUF_H__
+/*
+ * BK Id: SCCS/s.irq.h 1.9 05/17/01 18:14:24 cort
+ */
#ifdef __KERNEL__
#ifndef _ASM_IRQ_H
#define _ASM_IRQ_H
+/*
+ * BK Id: SCCS/s.ivms8.h 1.5 05/17/01 18:14:24 cort
+ */
/*
* A collection of structures, addresses, and values associated with
* Speech Design Integrated Voicemail Systems (IVMS8) boards.
+/*
+ * BK Id: SCCS/s.keyboard.h 1.5 05/17/01 18:14:24 cort
+ */
/*
* linux/include/asm-ppc/keyboard.h
*
+/*
+ * BK Id: SCCS/s.keylargo.h 1.9 05/17/01 18:14:24 cort
+ */
/*
* keylargo.h: definitions for using the "KeyLargo" I/O controller chip.
*
-/* $Id: kgdb.h,v 1.2 1998/04/11 17:29:07 geert Exp $
+/*
+ * BK Id: SCCS/s.kgdb.h 1.5 05/17/01 18:14:24 cort
+ */
+/*
* kgdb.h: Defines and declarations for serial line source level
* remote debugging of the Linux kernel using gdb.
*
+/*
+ * BK Id: SCCS/s.kmap_types.h 1.6 05/17/01 18:14:24 cort
+ */
#ifdef __KERNEL__
#ifndef _ASM_KMAP_TYPES_H
#define _ASM_KMAP_TYPES_H
+/*
+ * BK Id: SCCS/s.linux_logo.h 1.7 05/17/01 18:14:24 cort
+ */
/*
* include/asm-ppc/linux_logo.h: A linux logo to be displayed on boot
* (pinched from the sparc port).
+/*
+ * BK Id: SCCS/s.m48t35.h 1.5 05/17/01 18:14:25 cort
+ */
/*
* Registers for the SGS-Thomson M48T35 Timekeeper RAM chip
*/
+/*
+ * BK Id: SCCS/s.machdep.h 1.11 05/17/01 18:14:25 cort
+ */
#ifdef __KERNEL__
#ifndef _PPC_MACHDEP_H
#define _PPC_MACHDEP_H
+/*
+ * BK Id: SCCS/s.mbx.h 1.8 05/17/01 18:14:25 cort
+ */
/*
* A collection of structures, addresses, and values associated with
* the Motorola MBX boards. This was originally created for the
+/*
+ * BK Id: SCCS/s.mc146818rtc.h 1.5 05/17/01 18:14:25 cort
+ */
/*
* Machine dependent access functions for RTC registers.
*/
-/* $Id: md.h,v 1.1 1997/12/15 15:12:15 jj Exp $
+/*
+ * BK Id: SCCS/s.md.h 1.5 05/17/01 18:14:25 cort
+ */
+/*
* md.h: High speed xor_block operation for RAID4/5
*
*/
+/*
+ * BK Id: SCCS/s.mediabay.h 1.5 05/17/01 18:14:25 cort
+ */
/*
* mediabay.h: definitions for using the media bay
* on PowerBook 3400 and similar computers.
+/*
+ * BK Id: SCCS/s.mk48t59.h 1.5 05/17/01 18:14:25 cort
+ */
/*
* Registers for the mk48t59 real-time-clock
*/
+/*
+ * BK Id: SCCS/s.mman.h 1.7 05/17/01 18:14:25 cort
+ */
#ifndef __PPC_MMAN_H__
#define __PPC_MMAN_H__
+/*
+ * BK Id: SCCS/s.mmu.h 1.7 05/17/01 18:14:25 cort
+ */
/*
* PowerPC memory management structures
*/
+/*
+ * BK Id: SCCS/s.mmu_context.h 1.9 05/17/01 18:14:25 cort
+ */
#include <linux/config.h>
#ifdef __KERNEL__
+/*
+ * BK Id: SCCS/s.module.h 1.5 05/17/01 18:14:25 cort
+ */
#ifndef _ASM_PPC_MODULE_H
#define _ASM_PPC_MODULE_H
/*
+/*
+ * BK Id: SCCS/s.mpc8260.h 1.5 05/17/01 18:14:25 cort
+ */
/* This is the single file included by all MPC8260 build options.
* Since there are many different boards and no standard configuration,
+/*
+ * BK Id: SCCS/s.mpc8xx.h 1.10 05/17/01 18:14:25 cort
+ */
/* This is the single file included by all MPC8xx build options.
* Since there are many different boards and no standard configuration,
+/*
+ * BK Id: SCCS/s.msgbuf.h 1.5 05/17/01 18:14:25 cort
+ */
#ifndef _PPC_MSGBUF_H
#define _PPC_MSGBUF_H
-/* $Id: namei.h,v 1.4 1998/10/28 08:13:33 jj Exp $
- * linux/include/asm-ppc/namei.h
+/*
+ * BK Id: SCCS/s.namei.h 1.5 05/17/01 18:14:25 cort
+ */
+/* linux/include/asm-ppc/namei.h
* Adapted from linux/include/asm-alpha/namei.h
*
* Included from linux/fs/namei.c
+/*
+ * BK Id: SCCS/s.nvram.h 1.5 05/17/01 18:14:25 cort
+ */
/*
* PreP compliant NVRAM access
*/
+/*
+ * BK Id: SCCS/s.oak.h 1.7 05/17/01 18:14:25 cort
+ */
/*
*
* Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+/*
+ * BK Id: SCCS/s.ohare.h 1.5 05/17/01 18:14:25 cort
+ */
/*
* ohare.h: definitions for using the "O'Hare" I/O controller chip.
*
+/*
+ * BK Id: SCCS/s.page.h 1.5 05/17/01 18:14:25 cort
+ */
#ifndef _PPC_PAGE_H
#define _PPC_PAGE_H
+/*
+ * BK Id: SCCS/s.param.h 1.5 05/17/01 18:14:25 cort
+ */
#ifndef _ASM_PPC_PARAM_H
#define _ASM_PPC_PARAM_H
+/*
+ * BK Id: SCCS/s.parport.h 1.5 05/17/01 18:14:25 cort
+ */
/*
* parport.h: platform-specific PC-style parport initialisation
*
+/*
+ * BK Id: SCCS/s.pci-bridge.h 1.11 05/21/01 01:31:30 cort
+ */
#ifdef __KERNEL__
#ifndef _ASM_PCI_BRIDGE_H
#define _ASM_PCI_BRIDGE_H
+/*
+ * BK Id: SCCS/s.pci.h 1.12 05/21/01 01:31:30 cort
+ */
#ifndef __PPC_PCI_H
#define __PPC_PCI_H
#ifdef __KERNEL__
+/*
+ * BK Id: SCCS/s.pgalloc.h 1.9 05/17/01 18:14:25 cort
+ */
#ifdef __KERNEL__
#ifndef _PPC_PGALLOC_H
#define _PPC_PGALLOC_H
+/*
+ * BK Id: SCCS/s.pgtable.h 1.9 05/17/01 18:14:25 cort
+ */
#ifdef __KERNEL__
#ifndef _PPC_PGTABLE_H
#define _PPC_PGTABLE_H
+/*
+ * BK Id: SCCS/s.pnp.h 1.5 05/17/01 18:14:25 cort
+ */
#ifdef __KERNEL__
/* 11/02/95 */
/*----------------------------------------------------------------------------*/
+/*
+ * BK Id: SCCS/s.poll.h 1.5 05/17/01 18:14:25 cort
+ */
#ifndef __PPC_POLL_H
#define __PPC_POLL_H
+/*
+ * BK Id: SCCS/s.posix_types.h 1.5 05/17/01 18:14:25 cort
+ */
#ifndef _PPC_POSIX_TYPES_H
#define _PPC_POSIX_TYPES_H
+/*
+ * BK Id: SCCS/s.ppc4xx.h 1.3 05/17/01 18:14:25 cort
+ */
/*
*
* Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+/*
+ * BK Id: SCCS/s.ppc4xx_serial.h 1.3 05/17/01 18:14:25 cort
+ */
/*
* Copyright 2000 MontaVista Software Inc.
* PPC405GP modifications
+/*
+ * BK Id: SCCS/s.prep_nvram.h 1.7 05/17/01 18:14:25 cort
+ */
/*
* PreP compliant NVRAM access
*/
+/*
+ * BK Id: SCCS/s.processor.h 1.19 05/18/01 08:18:10 patch
+ */
#ifdef __KERNEL__
#ifndef __ASM_PPC_PROCESSOR_H
#define __ASM_PPC_PROCESSOR_H
+/*
+ * BK Id: SCCS/s.prom.h 1.11 05/18/01 08:18:10 patch
+ */
/*
* Definitions for talking to the Open Firmware PROM on
* Power Macintosh computers.
extern char *prom_display_paths[];
extern unsigned int prom_num_displays;
-#ifndef CONFIG_MACH_SPECIFIC
+#ifdef CONFIG_ALL_PPC
extern int have_of;
#endif
+/*
+ * BK Id: SCCS/s.ptrace.h 1.5 05/17/01 18:14:25 cort
+ */
#ifndef _PPC_PTRACE_H
#define _PPC_PTRACE_H
+/*
+ * BK Id: SCCS/s.raven.h 1.7 05/17/01 18:14:25 cort
+ */
/*
* asm-ppc/raven.h -- Raven MPIC chip.
*
+/*
+ * BK Id: SCCS/s.residual.h 1.5 05/17/01 18:14:25 cort
+ */
/* 7/18/95 */
/*----------------------------------------------------------------------------*/
/* Residual Data header definitions and prototypes */
+/*
+ * BK Id: SCCS/s.resource.h 1.5 05/17/01 18:14:25 cort
+ */
#ifndef _PPC_RESOURCE_H
#define _PPC_RESOURCE_H
+/*
+ * BK Id: SCCS/s.rpxclassic.h 1.8 05/17/01 18:14:25 cort
+ */
/*
* A collection of structures, addresses, and values associated with
+/*
+ * BK Id: SCCS/s.rpxhiox.h 1.3 05/17/01 18:14:25 cort
+ */
/*
* The Embedded Planet HIOX expansion card definitions.
+/*
+ * BK Id: SCCS/s.rpxlite.h 1.8 05/17/01 18:14:25 cort
+ */
/*
* A collection of structures, addresses, and values associated with
#ifndef __MACH_RPX_DEFS
#define __MACH_RPX_DEFS
+#include <linux/config.h>
+
#ifndef __ASSEMBLY__
/* A Board Information structure that is given to a program when
* prom starts it up.
+/*
+ * BK Id: SCCS/s.rwsem.h 1.6 05/17/01 18:14:25 cort
+ */
/*
* include/asm-ppc/rwsem.h: R/W semaphores for PPC using the stuff
* in lib/rwsem.c. Adapted largely from include/asm-i386/rwsem.h
+/*
+ * BK Id: SCCS/s.scatterlist.h 1.5 05/17/01 18:14:25 cort
+ */
#ifdef __KERNEL__
#ifndef _PPC_SCATTERLIST_H
#define _PPC_SCATTERLIST_H
+/*
+ * BK Id: SCCS/s.segment.h 1.7 05/17/01 18:14:25 cort
+ */
#include <asm/uaccess.h>
+/*
+ * BK Id: SCCS/s.semaphore.h 1.15 05/17/01 18:14:25 cort
+ */
#ifndef _PPC_SEMAPHORE_H
#define _PPC_SEMAPHORE_H
+/*
+ * BK Id: SCCS/s.sembuf.h 1.5 05/17/01 18:14:25 cort
+ */
#ifndef _PPC_SEMBUF_H
#define _PPC_SEMBUF_H
+/*
+ * BK Id: SCCS/s.serial.h 1.12 05/17/01 18:14:25 cort
+ */
/*
* include/asm-ppc/serial.h
*/
+/*
+ * BK Id: SCCS/s.setup.h 1.5 05/17/01 18:14:25 cort
+ */
#ifdef __KERNEL__
#ifndef _PPC_SETUP_H
#define _PPC_SETUP_H
+/*
+ * BK Id: SCCS/s.shmbuf.h 1.5 05/17/01 18:14:25 cort
+ */
#ifndef _PPC_SHMBUF_H
#define _PPC_SHMBUF_H
+/*
+ * BK Id: SCCS/s.shmparam.h 1.5 05/17/01 18:14:25 cort
+ */
#ifndef _PPC_SHMPARAM_H
#define _PPC_SHMPARAM_H
+/*
+ * BK Id: SCCS/s.sigcontext.h 1.5 05/17/01 18:14:25 cort
+ */
#ifndef _ASM_PPC_SIGCONTEXT_H
#define _ASM_PPC_SIGCONTEXT_H
+/*
+ * BK Id: SCCS/s.siginfo.h 1.5 05/17/01 18:14:25 cort
+ */
#ifndef _PPC_SIGINFO_H
#define _PPC_SIGINFO_H
+/*
+ * BK Id: SCCS/s.signal.h 1.5 05/17/01 18:14:25 cort
+ */
#ifndef _ASMPPC_SIGNAL_H
#define _ASMPPC_SIGNAL_H
+/*
+ * BK Id: SCCS/s.smp.h 1.9 05/17/01 18:14:25 cort
+ */
/* smp.h: PPC specific SMP stuff.
*
* Original was a copy of sparc smp.h. Now heavily modified
+/*
+ * BK Id: SCCS/s.smplock.h 1.7 05/17/01 18:14:25 cort
+ */
/*
* <asm/smplock.h>
*
+/*
+ * BK Id: SCCS/s.socket.h 1.6 05/17/01 18:14:25 cort
+ */
#ifndef _ASM_SOCKET_H
#define _ASM_SOCKET_H
+/*
+ * BK Id: SCCS/s.sockios.h 1.5 05/17/01 18:14:25 cort
+ */
#ifndef _ASM_PPC_SOCKIOS_H
#define _ASM_PPC_SOCKIOS_H
+/*
+ * BK Id: SCCS/s.softirq.h 1.5 05/17/01 18:14:25 cort
+ */
#ifdef __KERNEL__
#ifndef __ASM_SOFTIRQ_H
#define __ASM_SOFTIRQ_H
+/*
+ * BK Id: SCCS/s.spd8xx.h 1.5 05/17/01 18:14:25 cort
+ */
/*
* A collection of structures, addresses, and values associated with
* Speech Design SPD8xxTS boards.
+/*
+ * BK Id: SCCS/s.spinlock.h 1.5 05/17/01 18:14:25 cort
+ */
#ifdef __KERNEL__
#ifndef __ASM_SPINLOCK_H
#define __ASM_SPINLOCK_H
+/*
+ * BK Id: SCCS/s.stat.h 1.5 05/17/01 18:14:26 cort
+ */
#ifndef _PPC_STAT_H
#define _PPC_STAT_H
+/*
+ * BK Id: SCCS/s.statfs.h 1.5 05/17/01 18:14:26 cort
+ */
#ifndef _PPC_STATFS_H
#define _PPC_STATFS_H
+/*
+ * BK Id: SCCS/s.string.h 1.5 05/17/01 18:14:26 cort
+ */
#ifndef _PPC_STRING_H_
#define _PPC_STRING_H_
/*
- * $Id: system.h,v 1.49 1999/09/11 18:37:54 cort Exp $
- *
+ * BK Id: SCCS/s.system.h 1.10 05/17/01 18:14:26 cort
+ */
+/*
* Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
*/
#ifndef __PPC_SYSTEM_H
+/*
+ * BK Id: SCCS/s.termbits.h 1.5 05/17/01 18:14:26 cort
+ */
#ifndef _PPC_TERMBITS_H
#define _PPC_TERMBITS_H
+/*
+ * BK Id: SCCS/s.termios.h 1.8 05/17/01 18:14:26 cort
+ */
#ifndef _PPC_TERMIOS_H
#define _PPC_TERMIOS_H
/*
- * $Id: time.h,v 1.12 1999/08/27 04:21:23 cort Exp $
+ * BK Id: SCCS/s.time.h 1.10 05/17/01 18:14:26 cort
+ */
+/*
* Common time prototypes and such for all ppc machines.
*
* Written by Cort Dougan (cort@fsmlabs.com) to merge
+/*
+ * BK Id: SCCS/s.timex.h 1.5 05/17/01 18:14:26 cort
+ */
/*
* linux/include/asm-ppc/timex.h
*
+/*
+ * BK Id: SCCS/s.tlb.h 1.5 05/17/01 18:14:26 cort
+ */
#include <asm-generic/tlb.h>
+/*
+ * BK Id: SCCS/s.tqm8xx.h 1.6 05/17/01 18:14:26 cort
+ */
/*
* A collection of structures, addresses, and values associated with
* the TQ Systems TQM8xx(L) modules. This was originally created for the
+/*
+ * BK Id: SCCS/s.traps.h 1.5 05/17/01 18:14:26 cort
+ */
#include <asm-m68k/traps.h>
+/*
+ * BK Id: SCCS/s.types.h 1.5 05/17/01 18:14:26 cort
+ */
#ifndef _PPC_TYPES_H
#define _PPC_TYPES_H
+/*
+ * BK Id: SCCS/s.uaccess.h 1.5 05/17/01 18:14:26 cort
+ */
#ifdef __KERNEL__
#ifndef _PPC_UACCESS_H
#define _PPC_UACCESS_H
+/*
+ * BK Id: SCCS/s.ucontext.h 1.5 05/17/01 18:14:26 cort
+ */
#ifndef _ASMPPC_UCONTEXT_H
#define _ASMPPC_UCONTEXT_H
+/*
+ * BK Id: SCCS/s.unaligned.h 1.5 05/17/01 18:14:26 cort
+ */
#ifdef __KERNEL__
#ifndef __PPC_UNALIGNED_H
#define __PPC_UNALIGNED_H
+/*
+ * BK Id: SCCS/s.uninorth.h 1.7 05/17/01 18:14:26 cort
+ */
/*
* uninorth.h: definitions for using the "UniNorth" host bridge chip
* from Apple. This chip is used on "Core99" machines
+/*
+ * BK Id: SCCS/s.unistd.h 1.7 05/17/01 18:14:26 cort
+ */
#ifndef _ASM_PPC_UNISTD_H_
#define _ASM_PPC_UNISTD_H_
+/*
+ * BK Id: SCCS/s.user.h 1.5 05/17/01 18:14:26 cort
+ */
#ifdef __KERNEL__
#ifndef _PPC_USER_H
#define _PPC_USER_H
+/*
+ * BK Id: SCCS/s.vc_ioctl.h 1.5 05/17/01 18:14:26 cort
+ */
#ifndef _LINUX_VC_IOCTL_H
#define _LINUX_VC_IOCTL_H
+/*
+ * BK Id: SCCS/s.vga.h 1.5 05/17/01 18:14:26 cort
+ */
/*
* Access to VGA videoram
*
+/*
+ * BK Id: SCCS/s.walnut.h 1.7 05/17/01 18:14:26 cort
+ */
/*
*
* Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+/*
+ * BK Id: SCCS/s.xor.h 1.5 05/17/01 18:14:26 cort
+ */
#include <asm-generic/xor.h>
* by Greg Banks <gbanks@pocketpenguins.com>
* (c) 2000 PocketPenguins Inc.
*/
-#include <linux/config.h>
#include <asm/hd64465.h>
/* Macro to construct a portpin number (used in all
+++ /dev/null
-#ifndef _SPARC64_SEMAPHORE_HELPER_H
-#define _SPARC64_SEMAPHORE_HELPER_H
-
-/*
- * SMP- and interrupt-safe semaphore helper functions, sparc64 version.
- *
- * (C) Copyright 1999 David S. Miller (davem@redhat.com)
- * (C) Copyright 1999 Jakub Jelinek (jj@ultra.linux.cz)
- */
-#define wake_one_more(__sem) atomic_inc(&((__sem)->waking));
-#define waking_non_zero(__sem) \
-({ int __ret; \
- __asm__ __volatile__( \
-"1: ldsw [%1], %%g5\n\t" \
- "brlez,pt %%g5, 2f\n\t" \
- " mov 0, %0\n\t" \
- "sub %%g5, 1, %%g7\n\t" \
- "cas [%1], %%g5, %%g7\n\t" \
- "cmp %%g5, %%g7\n\t" \
- "bne,pn %%icc, 1b\n\t" \
- " mov 1, %0\n" \
-"2:" : "=&r" (__ret) \
- : "r" (&((__sem)->waking)) \
- : "g5", "g7", "cc", "memory"); \
- __ret; \
-})
-
-#define waking_non_zero_interruptible(__sem, __tsk) \
-({ int __ret; \
- __asm__ __volatile__( \
-"1: ldsw [%1], %%g5\n\t" \
- "brlez,pt %%g5, 2f\n\t" \
- " mov 0, %0\n\t" \
- "sub %%g5, 1, %%g7\n\t" \
- "cas [%1], %%g5, %%g7\n\t" \
- "cmp %%g5, %%g7\n\t" \
- "bne,pn %%icc, 1b\n\t" \
- " mov 1, %0\n" \
-"2:" : "=&r" (__ret) \
- : "r" (&((__sem)->waking)) \
- : "g5", "g7", "cc", "memory"); \
- if(__ret == 0 && signal_pending(__tsk)) { \
- atomic_inc(&((__sem)->count)); \
- __ret = -EINTR; \
- } \
- __ret; \
-})
-
-#define waking_non_zero_trylock(__sem) \
-({ int __ret; \
- __asm__ __volatile__( \
-"1: ldsw [%1], %%g5\n\t" \
- "brlez,pt %%g5, 2f\n\t" \
- " mov 1, %0\n\t" \
- "sub %%g5, 1, %%g7\n\t" \
- "cas [%1], %%g5, %%g7\n\t" \
- "cmp %%g5, %%g7\n\t" \
- "bne,pn %%icc, 1b\n\t" \
- " mov 0, %0\n" \
-"2:" : "=&r" (__ret) \
- : "r" (&((__sem)->waking)) \
- : "g5", "g7", "cc", "memory"); \
- if(__ret == 1) \
- atomic_inc(&((__sem)->count)); \
- __ret; \
-})
-
-#endif /* !(_SPARC64_SEMAPHORE_HELPER_H) */
#ifndef _SPARC64_SEMAPHORE_H
#define _SPARC64_SEMAPHORE_H
-/* These are actually reasonable on the V9. */
+/* These are actually reasonable on the V9.
+ *
+ * See asm-ppc/semaphore.h for implementation commentary,
+ * only sparc64 specific issues are commented here.
+ */
#ifdef __KERNEL__
#include <asm/atomic.h>
-#include <asm/bitops.h>
#include <asm/system.h>
#include <linux/wait.h>
#include <linux/rwsem.h>
struct semaphore {
atomic_t count;
- atomic_t waking;
wait_queue_head_t wait;
-#if WAITQUEUE_DEBUG
- long __magic;
-#endif
};
-#if WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
- , (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), ATOMIC_INIT(0), __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
- __SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, count) \
+ { ATOMIC_INIT(count), \
+ __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) }
#define __MUTEX_INITIALIZER(name) \
- __SEMAPHORE_INITIALIZER(name,1)
+ __SEMAPHORE_INITIALIZER(name, 1)
-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+#define __DECLARE_SEMAPHORE_GENERIC(name, count) \
struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
+#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name, 1)
+#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name, 0)
-extern inline void sema_init (struct semaphore *sem, int val)
+static inline void sema_init (struct semaphore *sem, int val)
{
atomic_set(&sem->count, val);
- atomic_set(&sem->waking, 0);
init_waitqueue_head(&sem->wait);
-#if WAITQUEUE_DEBUG
- sem->__magic = (long)&sem->__magic;
-#endif
}
static inline void init_MUTEX (struct semaphore *sem)
extern void __down(struct semaphore * sem);
extern int __down_interruptible(struct semaphore * sem);
-extern int __down_trylock(struct semaphore * sem);
extern void __up(struct semaphore * sem);
-extern __inline__ void down(struct semaphore * sem)
+static __inline__ void down(struct semaphore * sem)
{
-#if WAITQUEUE_DEBUG
- CHECK_MAGIC(sem->__magic);
-#endif
- __asm__ __volatile__(
-" 1: lduw [%0], %%g5\n"
-" sub %%g5, 1, %%g7\n"
-" cas [%0], %%g5, %%g7\n"
-" cmp %%g5, %%g7\n"
-" bne,pn %%icc, 1b\n"
-" cmp %%g7, 1\n"
-" bl,pn %%icc, 3f\n"
-" membar #StoreStore\n"
-" 2:\n"
-" .subsection 2\n"
-" 3: mov %0, %%g5\n"
-" save %%sp, -160, %%sp\n"
-" mov %%g1, %%l1\n"
-" mov %%g2, %%l2\n"
-" mov %%g3, %%l3\n"
-" call %1\n"
-" mov %%g5, %%o0\n"
-" mov %%l1, %%g1\n"
-" mov %%l2, %%g2\n"
-" ba,pt %%xcc, 2b\n"
-" restore %%l3, %%g0, %%g3\n"
-" .previous\n"
+ /* This atomically does:
+ * old_val = sem->count;
+ * new_val = sem->count - 1;
+ * sem->count = new_val;
+ * if (old_val < 1)
+ * __down(sem);
+ *
+ * The (old_val < 1) test is equivalent to
+ * the more straightforward (new_val < 0),
+ * but it is easier to test the former because
+ * of how the CAS instruction works.
+ */
+
+ __asm__ __volatile__("\n"
+" ! down sem(%0)\n"
+"1: lduw [%0], %%g5\n"
+" sub %%g5, 1, %%g7\n"
+" cas [%0], %%g5, %%g7\n"
+" cmp %%g5, %%g7\n"
+" bne,pn %%icc, 1b\n"
+" cmp %%g7, 1\n"
+" bl,pn %%icc, 3f\n"
+" membar #StoreStore\n"
+"2:\n"
+" .subsection 2\n"
+"3: mov %0, %%g5\n"
+" save %%sp, -160, %%sp\n"
+" mov %%g1, %%l1\n"
+" mov %%g2, %%l2\n"
+" mov %%g3, %%l3\n"
+" call %1\n"
+" mov %%g5, %%o0\n"
+" mov %%l1, %%g1\n"
+" mov %%l2, %%g2\n"
+" ba,pt %%xcc, 2b\n"
+" restore %%l3, %%g0, %%g3\n"
+" .previous\n"
: : "r" (sem), "i" (__down)
: "g5", "g7", "memory", "cc");
}
-extern __inline__ int down_interruptible(struct semaphore *sem)
+static __inline__ int down_interruptible(struct semaphore *sem)
{
int ret = 0;
-#if WAITQUEUE_DEBUG
- CHECK_MAGIC(sem->__magic);
-#endif
- __asm__ __volatile__(
-" 1: lduw [%2], %%g5\n"
-" sub %%g5, 1, %%g7\n"
-" cas [%2], %%g5, %%g7\n"
-" cmp %%g5, %%g7\n"
-" bne,pn %%icc, 1b\n"
-" cmp %%g7, 1\n"
-" bl,pn %%icc, 3f\n"
-" membar #StoreStore\n"
-" 2:\n"
-" .subsection 2\n"
-" 3: mov %2, %%g5\n"
-" save %%sp, -160, %%sp\n"
-" mov %%g1, %%l1\n"
-" mov %%g2, %%l2\n"
-" mov %%g3, %%l3\n"
-" call %3\n"
-" mov %%g5, %%o0\n"
-" mov %%l1, %%g1\n"
-" mov %%l2, %%g2\n"
-" mov %%l3, %%g3\n"
-" ba,pt %%xcc, 2b\n"
-" restore %%o0, %%g0, %0\n"
-" .previous\n"
+ /* This atomically does:
+ * old_val = sem->count;
+ * new_val = sem->count - 1;
+ * sem->count = new_val;
+ * if (old_val < 1)
+ * ret = __down_interruptible(sem);
+ *
+ * The (old_val < 1) test is equivalent to
+ * the more straightforward (new_val < 0),
+ * but it is easier to test the former because
+ * of how the CAS instruction works.
+ */
+
+ __asm__ __volatile__("\n"
+" ! down_interruptible sem(%2) ret(%0)\n"
+"1: lduw [%2], %%g5\n"
+" sub %%g5, 1, %%g7\n"
+" cas [%2], %%g5, %%g7\n"
+" cmp %%g5, %%g7\n"
+" bne,pn %%icc, 1b\n"
+" cmp %%g7, 1\n"
+" bl,pn %%icc, 3f\n"
+" membar #StoreStore\n"
+"2:\n"
+" .subsection 2\n"
+"3: mov %2, %%g5\n"
+" save %%sp, -160, %%sp\n"
+" mov %%g1, %%l1\n"
+" mov %%g2, %%l2\n"
+" mov %%g3, %%l3\n"
+" call %3\n"
+" mov %%g5, %%o0\n"
+" mov %%l1, %%g1\n"
+" mov %%l2, %%g2\n"
+" mov %%l3, %%g3\n"
+" ba,pt %%xcc, 2b\n"
+" restore %%o0, %%g0, %0\n"
+" .previous\n"
: "=r" (ret)
: "0" (ret), "r" (sem), "i" (__down_interruptible)
: "g5", "g7", "memory", "cc");
return ret;
}
-extern inline int down_trylock(struct semaphore *sem)
+static __inline__ int down_trylock(struct semaphore *sem)
{
- int ret = 0;
-#if WAITQUEUE_DEBUG
- CHECK_MAGIC(sem->__magic);
-#endif
- __asm__ __volatile__(
-" 1: lduw [%2], %%g5\n"
-" sub %%g5, 1, %%g7\n"
-" cas [%2], %%g5, %%g7\n"
-" cmp %%g5, %%g7\n"
-" bne,pn %%icc, 1b\n"
-" cmp %%g7, 1\n"
-" bl,pn %%icc, 3f\n"
-" membar #StoreStore\n"
-" 2:\n"
-" .subsection 2\n"
-" 3: mov %2, %%g5\n"
-" save %%sp, -160, %%sp\n"
-" mov %%g1, %%l1\n"
-" mov %%g2, %%l2\n"
-" mov %%g3, %%l3\n"
-" call %3\n"
-" mov %%g5, %%o0\n"
-" mov %%l1, %%g1\n"
-" mov %%l2, %%g2\n"
-" mov %%l3, %%g3\n"
-" ba,pt %%xcc, 2b\n"
-" restore %%o0, %%g0, %0\n"
-" .previous\n"
- : "=r" (ret)
- : "0" (ret), "r" (sem), "i" (__down_trylock)
+ int ret;
+
+ /* This atomically does:
+ * old_val = sem->count;
+ * new_val = sem->count - 1;
+ * if (old_val < 1) {
+ * ret = 1;
+ * } else {
+ * sem->count = new_val;
+ * ret = 0;
+ * }
+ *
+ * The (old_val < 1) test is equivalent to
+ * the more straightforward (new_val < 0),
+ * but it is easier to test the former because
+ * of how the CAS instruction works.
+ */
+
+ __asm__ __volatile__("\n"
+" ! down_trylock sem(%1) ret(%0)\n"
+"1: lduw [%1], %%g5\n"
+" sub %%g5, 1, %%g7\n"
+" cmp %%g5, 1\n"
+" bl,pn %%icc, 2f\n"
+" mov 1, %0\n"
+" cas [%1], %%g5, %%g7\n"
+" cmp %%g5, %%g7\n"
+" bne,pn %%icc, 1b\n"
+" mov 0, %0\n"
+" membar #StoreStore\n"
+"2:\n"
+ : "=&r" (ret)
+ : "r" (sem)
: "g5", "g7", "memory", "cc");
+
return ret;
}
-extern __inline__ void up(struct semaphore * sem)
+static __inline__ void up(struct semaphore * sem)
{
-#if WAITQUEUE_DEBUG
- CHECK_MAGIC(sem->__magic);
-#endif
- __asm__ __volatile__(
-" membar #StoreLoad | #LoadLoad\n"
-" 1: lduw [%0], %%g5\n"
-" add %%g5, 1, %%g7\n"
-" cas [%0], %%g5, %%g7\n"
-" cmp %%g5, %%g7\n"
-" bne,pn %%icc, 1b\n"
-" addcc %%g7, 1, %%g0\n"
-" ble,pn %%icc, 3f\n"
-" nop\n"
-" 2:\n"
-" .subsection 2\n"
-" 3: mov %0, %%g5\n"
-" save %%sp, -160, %%sp\n"
-" mov %%g1, %%l1\n"
-" mov %%g2, %%l2\n"
-" mov %%g3, %%l3\n"
-" call %1\n"
-" mov %%g5, %%o0\n"
-" mov %%l1, %%g1\n"
-" mov %%l2, %%g2\n"
-" ba,pt %%xcc, 2b\n"
-" restore %%l3, %%g0, %%g3\n"
-" .previous\n"
+ /* This atomically does:
+ * old_val = sem->count;
+ * new_val = sem->count + 1;
+ * sem->count = new_val;
+ * if (old_val < 0)
+ * __up(sem);
+ *
+ * The (old_val < 0) test is equivalent to
+ * the more straightforward (new_val <= 0),
+ * but it is easier to test the former because
+ * of how the CAS instruction works.
+ */
+
+ __asm__ __volatile__("\n"
+" ! up sem(%0)\n"
+" membar #StoreLoad | #LoadLoad\n"
+"1: lduw [%0], %%g5\n"
+" add %%g5, 1, %%g7\n"
+" cas [%0], %%g5, %%g7\n"
+" cmp %%g5, %%g7\n"
+" bne,pn %%icc, 1b\n"
+" addcc %%g7, 1, %%g0\n"
+" ble,pn %%icc, 3f\n"
+" nop\n"
+"2:\n"
+" .subsection 2\n"
+"3: mov %0, %%g5\n"
+" save %%sp, -160, %%sp\n"
+" mov %%g1, %%l1\n"
+" mov %%g2, %%l2\n"
+" mov %%g3, %%l3\n"
+" call %1\n"
+" mov %%g5, %%o0\n"
+" mov %%l1, %%g1\n"
+" mov %%l2, %%g2\n"
+" ba,pt %%xcc, 2b\n"
+" restore %%l3, %%g0, %%g3\n"
+" .previous\n"
: : "r" (sem), "i" (__up)
: "g5", "g7", "memory", "cc");
}
+++ /dev/null
-#ifndef __LINUX_COMPILER_H
-#define __LINUX_COMPILER_H
-
-/* Somewhere in the middle of the GCC 2.96 development cycle, we implemented
- a mechanism by which the user can annotate likely branch directions and
- expect the blocks to be reordered appropriately. Define __builtin_expect
- to nothing for earlier compilers. */
-
-#if __GNUC__ == 2 && __GNUC_MINOR__ < 96
-#define __builtin_expect(x, expected_value) (x)
-#endif
-
-#endif /* __LINUX_COMPILER_H */
int gfp_mask; /* how to allocate the pages */
};
+struct char_device {
+ struct list_head hash;
+ atomic_t count;
+ dev_t dev;
+ atomic_t openers;
+ struct semaphore sem;
+};
+
struct block_device {
struct list_head bd_hash;
atomic_t bd_count;
struct address_space *i_mapping;
struct address_space i_data;
struct dquot *i_dquot[MAXQUOTAS];
+ /* These three should probably be a union */
struct pipe_inode_info *i_pipe;
struct block_device *i_bdev;
+ struct char_device *i_cdev;
unsigned long i_dnotify_mask; /* Directory notify events */
struct dnotify_struct *i_dnotify; /* for directory notifications */
extern int unregister_blkdev(unsigned int, const char *);
extern struct block_device *bdget(dev_t);
extern void bdput(struct block_device *);
+extern struct char_device *cdget(dev_t);
+extern void cdput(struct char_device *);
extern int blkdev_open(struct inode *, struct file *);
extern struct file_operations def_blk_fops;
extern struct file_operations def_fifo_fops;
extern struct file_system_type *get_fs_type(const char *name);
extern struct super_block *get_super(kdev_t);
extern void put_super(kdev_t);
+static inline int is_mounted(kdev_t dev)
+{
+ struct super_block *sb = get_super(dev);
+ if (sb) {
+ /* drop_super(sb); will go here */
+ return 1;
+ }
+ return 0;
+}
unsigned long generate_cluster(kdev_t, int b[], int);
unsigned long generate_cluster_swab32(kdev_t, int b[], int);
extern kdev_t ROOT_DEV;
ATTRIB_NORET;
NORET_TYPE void up_and_exit(struct semaphore *, long)
ATTRIB_NORET;
+extern int abs(int);
extern unsigned long simple_strtoul(const char *,char **,unsigned int);
extern long simple_strtol(const char *,char **,unsigned int);
extern unsigned long long simple_strtoull(const char *,char **,unsigned int);
case RAID5: return 5;
}
panic("pers_to_level()");
+ return MD_RESERVED;
}
extern inline int level_to_pers (int level)
#define _LINUX_RWSEM_SPINLOCK_H
#ifndef _LINUX_RWSEM_H
-#error please dont include asm/rwsem-spinlock.h directly, use linux/rwsem.h instead
+#error please dont include linux/rwsem-spinlock.h directly, use linux/rwsem.h instead
#endif
#include <linux/spinlock.h>
#ifdef __KERNEL__
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <asm/system.h>
uid_t busuid;
gid_t busgid;
umode_t busmode;
+ uid_t listuid;
+ gid_t listgid;
+ umode_t listmode;
};
#define VID_HARDWARE_ZR356700 28 /* Zoran 36700 series */
#define VID_HARDWARE_W9966 29
#define VID_HARDWARE_SE401 30 /* SE401 USB webcams */
-
+#define VID_HARDWARE_PWC 31 /* Philips webcams */
/*
* Initialiser list
extern void ppc_init(void);
extern void sysctl_init(void);
extern void signals_init(void);
-extern void bdev_init(void);
extern int init_pcmcia_ds(void);
extern void net_notifier_init(void);
ccwcache_init();
#endif
signals_init();
- bdev_init();
- inode_init(mempages);
#ifdef CONFIG_PROC_FS
proc_root_init();
#endif
EXPORT_SYMBOL(notify_change);
EXPORT_SYMBOL(set_blocksize);
EXPORT_SYMBOL(getblk);
+EXPORT_SYMBOL(cdget);
+EXPORT_SYMBOL(cdput);
EXPORT_SYMBOL(bdget);
EXPORT_SYMBOL(bdput);
EXPORT_SYMBOL(bread);
#define MAXRESERVE 4
static int __init reserve_setup(char *str)
{
- int opt = 2, io_start, io_num;
static int reserved = 0;
static struct resource reserve[MAXRESERVE];
- while (opt==2) {
+ for (;;) {
+ int io_start, io_num;
int x = reserved;
- if (get_option (&str, &io_start) != 2) break;
- if (get_option (&str, &io_num) == 0) break;
+ if (get_option (&str, &io_start) != 2)
+ break;
+ if (get_option (&str, &io_num) == 0)
+ break;
if (x < MAXRESERVE) {
struct resource *res = reserve + x;
res->name = "reserved";
res->start = io_start;
res->end = io_start + io_num - 1;
+ res->flags = IORESOURCE_BUSY;
res->child = NULL;
if (request_resource(res->start >= 0x10000 ? &iomem_resource : &ioport_resource, res) == 0)
reserved = x+1;
* Linus frestrict idea will clean these up nicely..
*/
- if (pos > inode->i_sb->s_maxbytes)
+ if (pos >= inode->i_sb->s_maxbytes)
{
- send_sig(SIGXFSZ, current, 0);
- err = -EFBIG;
- goto out;
+ if (count || pos > inode->i_sb->s_maxbytes) {
+ send_sig(SIGXFSZ, current, 0);
+ err = -EFBIG;
+ goto out;
+ }
+ /* zero-length writes at ->s_maxbytes are OK */
}
if (pos + count > inode->i_sb->s_maxbytes)
inode->i_gid = current->fsgid;
inode->i_blksize = PAGE_CACHE_SIZE;
inode->i_blocks = 0;
- inode->i_rdev = to_kdev_t(dev);
+ inode->i_rdev = NODEV;
inode->i_mapping->a_ops = &shmem_aops;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
spin_lock_init (&inode->u.shmem_i.lock);
* @flags: the type of memory to allocate.
*
* kmalloc is the normal method of allocating memory
- * in the kernel. The @flags argument may be one of:
+ * in the kernel.
*
- * %GFP_BUFFER - XXX
+ * The @flags argument may be one of:
*
- * %GFP_ATOMIC - allocation will not sleep. Use inside interrupt handlers.
+ * %GFP_USER - Allocate memory on behalf of user. May sleep.
*
- * %GFP_USER - allocate memory on behalf of user. May sleep.
+ * %GFP_KERNEL - Allocate normal kernel ram. May sleep.
*
- * %GFP_KERNEL - allocate normal kernel ram. May sleep.
+ * %GFP_ATOMIC - Allocation will not sleep. Use inside interrupt handlers.
*
- * %GFP_NFS - has a slightly lower probability of sleeping than %GFP_KERNEL.
- * Don't use unless you're in the NFS code.
- *
- * %GFP_KSWAPD - Don't use unless you're modifying kswapd.
+ * Additionally, the %GFP_DMA flag may be set to indicate the memory
+ * must be suitable for DMA. This can mean different things on different
+ * platforms. For example, on i386, it means that the memory must come
+ * from the first 16MB.
*/
void * kmalloc (size_t size, int flags)
{