Commit 2dd9c63b authored by Linus Torvalds's avatar Linus Torvalds

Import 2.3.35

parent 6ed83574
......@@ -331,6 +331,10 @@ S: Bessemerstraat 21
S: Amsterdam
S: The Netherlands
N: Zach Brown
E: zab@zabbo.net
D: maestro pci sound
N: Ray Burr
E: ryb@nightmare.com
D: Original author of Amiga FFS filesystem
......
......@@ -7912,11 +7912,11 @@ CONFIG_USB_MOUSE
The module will be called mouse.o. If you want to compile it as a
module, say M here and read Documentation/modules.txt.
USB HP scanner support
CONFIG_USB_HP_SCANNER
Say Y here if you want to connect a USB HP scanner to your
computer's USB port. Please read drivers/usb/README.hp_scanner
for more information.
USB scanner support
CONFIG_USB_SCANNER
Say Y here if you want to connect a USB scanner to your
computer's USB port. Please read drivers/usb/README.scanner
and drivers/usb/README.scanner_hp_sane for more information.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
......@@ -11179,6 +11179,12 @@ CONFIG_SOUND_NM256
See Documentation/sound/NM256 for further information.
ESS Maestro sound chipsets
CONFIG_SOUND_MAESTRO
Say Y or M if you have a sound system driven by ESS's Maestro line
of PCI sound chips. These include the Maestro 1, Maestro 2, and
Maestro 2E. See Documentation/sound/Maestro for more details.
Are you using a crosscompiler
CONFIG_CROSSCOMPILE
Say Y here if you are compiling the kernel on a different
......
Cramfs - cram a filesystem onto a small ROM
cramfs is designed to be simple and small, and to compress things well.
It uses the zlib routines to compress a file one page at a time, and
allows random page access. The meta-data is not compressed, but is
expressed in a very terse representation to make it use much less
diskspace than traditional filesystems.
You can't write to a cramfs filesystem (making it compressible and
compact also makes it _very_ hard to update on-the-fly), so you have to
create the disk image with the "mkcramfs" utility in scripts/cramfs.
An OSS/Lite Driver for the ESS Maestro family of sound cards
Zach Brown, December 1999
Driver Status and Availability
------------------------------
The most recent version of this driver will hopefully always be available at
http://people.redhat.com/zab/maestro/
I will try and maintain the most recent stable version of the driver
in both the stable and development kernel lines.
ESS Maestro Chip Family
-----------------------
There are 3 main variants of the ESS Maestro PCI sound chip. The first
is the Maestro 1. It was originally produced by Platform Tech as the
'AGOGO'. It can be recognized by Platform Tech's PCI ID 0x1285 with
0x0100 as the device ID. It was put on some sound boards and a few laptops.
ESS bought the design and cleaned it up as the Maestro 2. This starts
their marking with the ESS vendor ID 0x125D and the 'year' device IDs.
The Maestro 2 claims 0x1968 while the Maestro 2e has 0x1978.
The various families of Maestro are mostly identical as far as this
driver is concerned. It doesn't touch the DSP parts that differ (though
it could for FM synthesis)
Driver OSS Behavior
--------------------
This OSS driver exports /dev/mixer and /dev/dsp to applications, which
mostly adhere to the OSS spec. This driver doesn't register itself
with /dev/sndstat, so don't expect information to appear there.
The /dev/dsp device exported behaves almost as expected. Playback is
supported in all the various lovely formats. 8/16bit stereo/mono from
8khz to 48khz, and mmap()ing for playback behaves. Capture/recording
is limited due to oddities with the Maestro hardware. One can only
record in 16bit stereo. For recording the maestro uses non interleaved
stereo buffers so that mmap()ing the incoming data does not result in
a ring buffer of LRLR data. mmap()ing of the read buffers is therefore
disallowed until this can be cleaned up.
/dev/mixer is an interface to the AC'97 codec on the Maestro. It is
worth noting that there are a variety of AC'97s that can be wired to
the Maestro. Which is used is entirely up to the hardware implementor.
This should only be visible to the user by the presence, or lack, of
'Bass' and 'Treble' sliders in the mixer. Not all AC'97s have them.
The driver doesn't support MIDI or FM playback at the moment. Typically
the Maestro is wired to an MPU MIDI chip, but some hardware implementations
don't. We need to assemble a white list of hardware implementations that
have MIDI wired properly before we can claim to support it safely.
Compiling and Installing
------------------------
With the drivers inclusion into the kernel, compiling and installing
is the same as most OSS/Lite modular sound drivers. Compilation
of the driver is enabled through the CONFIG_SOUND_MAESTRO variable
in the config system.
It may be modular or statically linked. If it is modular it should be
installed with the rest of the modules for the kernel on the system.
Typically this will be in /lib/modules/ somewhere. 'alias sound maestro'
should also be added to your module configs (typically /etc/conf.modules)
if you're using modular OSS/Lite sound and want to default to using a
maestro chip.
As this is a PCI device, the module does not need to be informed of
any IO or IRQ resources it should use, it devines these from the
system. Somtimes, on sucky PCs, the BIOS fails to allocated resources
for the maestro. This will result in a message like:
maestro: PCI subsystem reports IRQ 0, this might not be correct.
from the kernel. Should this happen the sound chip most likely will
not operate correctly. To solve this one has to dig through their BIOS
(typically entered by hitting a hot key at boot time) and figure out
what magic needs to happen so that the BIOS will reward the maestro with
an IRQ. This operation is incredibly system specific, so you're on your
own. Sometimes the magic lies in 'PNP Capable Operating System' settings.
There are very few options to the driver. One is 'debug' which will
tell the driver to print minimal debugging information as it runs. This
can be collected with 'dmesg' or through the klogd daemon.
The other, more interesting option, is 'dsps_order'. Typically at
install time the driver will only register one available /dev/dsp device
for its use. The 'dsps_order' module parameter allows for more devices
to be allocated, as a power of two. Up to 4 devices can be registered
( dsps_order=2 ). These devices act as fully distinct units and use
separate channels in the maestro.
.. more details ..
-----------------
drivers/sound/maestro.c contains comments that hopefully explain
the maestro implementation.
......@@ -529,6 +529,12 @@ W: http://www.linuxppc.org/
L: linuxppc-dev@lists.linuxppc.org
S: Maintained
MAESTRO PCI SOUND DRIVER
P: Zach Brown
M: zab@redhat.com
W: http://people.redhat.com/zab/maestro/
S: Supported
M68K
P: Jes Sorensen
M: Jes.Sorensen@cern.ch
......
......@@ -109,7 +109,6 @@ CFLAGS += $(shell if $(CC) -fno-strict-aliasing -S -o /dev/null -xc /dev/null >/
#
CORE_FILES =kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o
FILESYSTEMS =fs/filesystems.a
NETWORKS =net/network.a
DRIVERS =drivers/block/block.a \
drivers/char/char.o \
......@@ -256,7 +255,6 @@ vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs
$(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o \
--start-group \
$(CORE_FILES) \
$(FILESYSTEMS) \
$(NETWORKS) \
$(DRIVERS) \
$(LIBS) \
......
......@@ -417,6 +417,7 @@ CONFIG_AUTOFS_FS=y
# CONFIG_MSDOS_FS is not set
# CONFIG_UMSDOS_FS is not set
# CONFIG_VFAT_FS is not set
# CONFIG_CRAMFS is not set
CONFIG_ISO9660_FS=y
# CONFIG_JOLIET is not set
# CONFIG_MINIX_FS is not set
......
......@@ -85,12 +85,16 @@ comment 'General setup'
if [ "$CONFIG_APUS" = "y" ]; then
define_bool CONFIG_PCI n
else if [ "$CONFIG_OAK" = "y" ]; then
fi
if [ "$CONFIG_OAK" = "y" ]; then
define_bool CONFIG_PCI n
else if [ "$CONFIG_8xx" = "y" ]; then
fi
if [ "$CONFIG_8xx" = "y" ]; then
bool 'QSpan PCI' CONFIG_PCI
else
if [ "$CONFIG_APUS" != "y" ]; then
define_bool CONFIG_PCI y
fi
fi
bool 'Networking support' CONFIG_NET
......
......@@ -249,7 +249,7 @@ chrp_setup_arch(void)
else
#endif
ROOT_DEV = to_kdev_t(0x0802); /* sda2 (sda1 is for the kernel) */
sprintf(cmd_line, "console=ttyS0,9600 console=tty0");
printk("Boot arguments: %s\n", cmd_line);
request_region(0x20,0x20,"pic1");
......@@ -391,7 +391,7 @@ void chrp_post_irq(int irq)
* openpic irq. So we just check to make sure the controller
* is an openpic and if it is then eoi
*
* We do it this way since our irq_desc[irq].ctl can change
* We do it this way since our irq_desc[irq].handler can change
* with RTL and no longer be open_pic -- Cort
*/
if ( irq >= open_pic.irq_offset)
......@@ -413,10 +413,10 @@ void __init chrp_init_IRQ(void)
}
open_pic.irq_offset = 16;
for ( i = 16 ; i < NR_IRQS ; i++ )
irq_desc[i].ctl = &open_pic;
irq_desc[i].handler = &open_pic;
openpic_init(1);
for ( i = 0 ; i < 16 ; i++ )
irq_desc[i].ctl = &i8259_pic;
irq_desc[i].handler = &i8259_pic;
i8259_init();
#ifdef CONFIG_XMON
request_irq(openpic_to_irq(HYDRA_INT_ADB_NMI),
......
......@@ -332,7 +332,7 @@ void __init gemini_init_IRQ(void)
/* gemini has no 8259 */
open_pic.irq_offset = 0;
for( i=0; i < NR_IRQS; i++ )
irq_desc[i].ctl = &open_pic;
irq_desc[i].handler = &open_pic;
openpic_init(1);
#ifdef __SMP__
request_irq(OPENPIC_VEC_IPI, openpic_ipi_action,
......@@ -512,7 +512,7 @@ void gemini_post_irq(int irq)
* openpic irq. So we just check to make sure the controller
* is an openpic and if it is then eoi
*
* We do it this way since our irq_desc[irq].ctl can change
* We do it this way since our irq_desc[irq].handler can change
* with RTL and no longer be open_pic -- Cort
*/
if ( irq >= open_pic.irq_offset)
......
......@@ -44,6 +44,7 @@
#include <linux/openpic.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <asm/bitops.h>
#include <asm/hydra.h>
......@@ -71,7 +72,7 @@ volatile unsigned char *chrp_int_ack_special;
#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
struct irqdesc irq_desc[NR_IRQS] = {{0, 0}, };
irq_desc_t irq_desc[NR_IRQS];
int ppc_spurious_interrupts = 0;
unsigned int ppc_local_bh_count[NR_CPUS];
unsigned int ppc_local_irq_count[NR_CPUS];
......@@ -244,8 +245,8 @@ int get_irq_list(char *buf)
#else
len += sprintf(buf+len, "%10u ", kstat_irqs(i));
#endif /* __SMP__ */
if ( irq_desc[i].ctl )
len += sprintf(buf+len, " %s ", irq_desc[i].ctl->typename );
if ( irq_desc[i].handler )
len += sprintf(buf+len, " %s ", irq_desc[i].handler->typename );
else
len += sprintf(buf+len, " None ");
len += sprintf(buf+len, " %s",action->name);
......
......@@ -4,7 +4,7 @@
#include <linux/kernel_stat.h>
#include <linux/interrupt.h>
#include <asm/irq_control.h>
#include <linux/irq.h>
void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq);
......
......@@ -278,7 +278,7 @@ m8xx_init_IRQ(void)
ppc8xx_pic.irq_offset = 0;
for ( i = 0 ; i < NR_SIU_INTS ; i++ )
irq_desc[i].ctl = &ppc8xx_pic;
irq_desc[i].handler = &ppc8xx_pic;
/* We could probably incorporate the CPM into the multilevel
* interrupt structure.
......@@ -288,7 +288,7 @@ m8xx_init_IRQ(void)
#if defined(CONFIG_PCI)
for ( i = NR_SIU_INTS ; i < (NR_SIU_INTS + NR_8259_INTS) ; i++ )
irq_desc[i].ctl = &i8259_pic;
irq_desc[i].handler = &i8259_pic;
i8259_pic.irq_offset = NR_SIU_INTS;
i8259_init();
request_8xxirq(ISA_BRIDGE_INT, mbx_i8259_action, 0, "8259 cascade", NULL);
......
/*
* MBX pci routines.
* The MBX uses the QSpan PCI bridge. The config address register
* is located 0x500 from the base of the bridge control/status registers.
* The data register is located at 0x504.
* This is a two step operation. First, the address register is written,
* then the data register is read/written as required.
* I don't know what to do about interrupts (yet).
*/
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/bios32.h>
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/mbx.h>
/*
* This blows......The MBX uses the Tundra QSpan PCI bridge. When
* reading the configuration space, if something does not respond
* the bus times out and we get a machine check interrupt. So, the
* good ol' exception tables come to mind to trap it and return some
* value.
*
* On an error we just return a -1, since that is what the caller wants
* returned if nothing is present. I copied this from __get_user_asm,
* with the only difference of returning -1 instead of EFAULT.
* There is an associated hack in the machine check trap code.
*
* The QSPAN is also a big endian device, that is it makes the PCI
* look big endian to us. This presents a problem for the Linux PCI
* functions, which assume little endian. For example, we see the
* first 32-bit word like this:
* ------------------------
* | Device ID | Vendor ID |
* ------------------------
* If we read/write as a double word, that's OK. But in our world,
* when read as a word, device ID is at location 0, not location 2 as
* the little endian PCI would believe. We have to switch bits in
* the PCI addresses given to us to get the data to/from the correct
* byte lanes.
*
* The QSPAN only supports 4 bits of "slot" in the dev_fn instead of 5.
* It always forces the MS bit to zero. Therefore, dev_fn values
* greater than 128 are returned as "no device found" errors.
*
* The QSPAN can only perform long word (32-bit) configuration cycles.
* The "offset" must have the two LS bits set to zero. Read operations
* require we read the entire word and then sort out what should be
* returned. Write operations other than long word require that we
* read the long word, update the proper word or byte, then write the
* entire long word back.
*
* PCI Bridge hack. We assume (correctly) that bus 0 is the primary
* PCI bus from the QSPAN. If we are called with a bus number other
* than zero, we create a Type 1 configuration access that a downstream
* PCI bridge will interpret.
*/
#define __get_mbx_pci_config(x, addr, op) \
__asm__ __volatile__( \
"1: "op" %0,0(%1)\n" \
" eieio\n" \
"2:\n" \
".section .fixup,\"ax\"\n" \
"3: li %0,-1\n" \
" b 2b\n" \
".section __ex_table,\"a\"\n" \
" .align 2\n" \
" .long 1b,3b\n" \
".text" \
: "=r"(x) : "r"(addr))
#define QS_CONFIG_ADDR ((volatile uint *)(PCI_CSR_ADDR + 0x500))
#define QS_CONFIG_DATA ((volatile uint *)(PCI_CSR_ADDR + 0x504))
#define mk_config_addr(bus, dev, offset) \
(((bus)<<16) | ((dev)<<8) | (offset & 0xfc))
#define mk_config_type1(bus, dev, offset) \
mk_config_addr(bus, dev, offset) | 1;
int mbx_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned char *val)
{
uint temp;
u_char *cp;
if ((bus > 7) || (dev_fn > 127)) {
*val = 0xff;
return PCIBIOS_DEVICE_NOT_FOUND;
}
if (bus == 0)
*QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
else
*QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
__get_mbx_pci_config(temp, QS_CONFIG_DATA, "lwz");
offset ^= 0x03;
cp = ((u_char *)&temp) + (offset & 0x03);
*val = *cp;
return PCIBIOS_SUCCESSFUL;
}
int mbx_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned short *val)
{
uint temp;
ushort *sp;
if ((bus > 7) || (dev_fn > 127)) {
*val = 0xffff;
return PCIBIOS_DEVICE_NOT_FOUND;
}
if (bus == 0)
*QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
else
*QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
__get_mbx_pci_config(temp, QS_CONFIG_DATA, "lwz");
offset ^= 0x02;
sp = ((ushort *)&temp) + ((offset >> 1) & 1);
*val = *sp;
return PCIBIOS_SUCCESSFUL;
}
int mbx_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned int *val)
{
if ((bus > 7) || (dev_fn > 127)) {
*val = 0xffffffff;
return PCIBIOS_DEVICE_NOT_FOUND;
}
if (bus == 0)
*QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
else
*QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
__get_mbx_pci_config(*val, QS_CONFIG_DATA, "lwz");
return PCIBIOS_SUCCESSFUL;
}
int mbx_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned char val)
{
uint temp;
u_char *cp;
if ((bus > 7) || (dev_fn > 127))
return PCIBIOS_DEVICE_NOT_FOUND;
mbx_pcibios_read_config_dword(bus, dev_fn, offset, &temp);
offset ^= 0x03;
cp = ((u_char *)&temp) + (offset & 0x03);
*cp = val;
if (bus == 0)
*QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
else
*QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
*QS_CONFIG_DATA = temp;
return PCIBIOS_SUCCESSFUL;
}
int mbx_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned short val)
{
uint temp;
ushort *sp;
if ((bus > 7) || (dev_fn > 127))
return PCIBIOS_DEVICE_NOT_FOUND;
mbx_pcibios_read_config_dword(bus, dev_fn, offset, &temp);
offset ^= 0x02;
sp = ((ushort *)&temp) + ((offset >> 1) & 1);
*sp = val;
if (bus == 0)
*QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
else
*QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
*QS_CONFIG_DATA = temp;
return PCIBIOS_SUCCESSFUL;
}
int mbx_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned int val)
{
if ((bus > 7) || (dev_fn > 127))
return PCIBIOS_DEVICE_NOT_FOUND;
if (bus == 0)
*QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
else
*QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
*(unsigned int *)QS_CONFIG_DATA = val;
return PCIBIOS_SUCCESSFUL;
}
int mbx_pcibios_find_device(unsigned short vendor, unsigned short dev_id,
unsigned short index, unsigned char *bus_ptr,
unsigned char *dev_fn_ptr)
{
int num, devfn;
unsigned int x, vendev;
if (vendor == 0xffff)
return PCIBIOS_BAD_VENDOR_ID;
vendev = (dev_id << 16) + vendor;
num = 0;
for (devfn = 0; devfn < 32; devfn++) {
mbx_pcibios_read_config_dword(0, devfn<<3, PCI_VENDOR_ID, &x);
if (x == vendev) {
if (index == num) {
*bus_ptr = 0;
*dev_fn_ptr = devfn<<3;
return PCIBIOS_SUCCESSFUL;
}
++num;
}
}
return PCIBIOS_DEVICE_NOT_FOUND;
}
int mbx_pcibios_find_class(unsigned int class_code, unsigned short index,
unsigned char *bus_ptr, unsigned char *dev_fn_ptr)
{
int devnr, x, num;
num = 0;
for (devnr = 0; devnr < 32; devnr++) {
mbx_pcibios_read_config_dword(0, devnr<<3, PCI_CLASS_REVISION, &x);
if ((x>>8) == class_code) {
if (index == num) {
*bus_ptr = 0;
*dev_fn_ptr = devnr<<3;
return PCIBIOS_SUCCESSFUL;
}
++num;
}
}
return PCIBIOS_DEVICE_NOT_FOUND;
}
void __init
mbx_pcibios_fixup(void)
{
/* Nothing to do here? */
}
void __init
mbx_setup_pci_ptrs(void)
{
set_config_access_method(mbx);
ppc_md.pcibios_fixup = mbx_pcibios_fixup;
}
This diff is collapsed.
......@@ -416,13 +416,13 @@ void openpic_maptimer(u_int timer, u_int cpumask)
void openpic_enable_irq(u_int irq)
{
check_arg_irq(irq);
openpic_clearfield(&OpenPIC->Source[irq-irq_desc[irq].ctl->irq_offset].Vector_Priority, OPENPIC_MASK);
openpic_clearfield(&OpenPIC->Source[irq-irq_desc[irq].handler->irq_offset].Vector_Priority, OPENPIC_MASK);
}
void openpic_disable_irq(u_int irq)
{
check_arg_irq(irq);
openpic_setfield(&OpenPIC->Source[irq-irq_desc[irq].ctl->irq_offset].Vector_Priority, OPENPIC_MASK);
openpic_setfield(&OpenPIC->Source[irq-irq_desc[irq].handler->irq_offset].Vector_Priority, OPENPIC_MASK);
}
/*
......
......@@ -135,7 +135,7 @@ static void gatwick_action(int cpl, void *dev_id, struct pt_regs *regs)
* don't. Put this here to check for it.
* -- Cort
*/
if ( irq_desc[irq].ctl != &gatwick_pic )
if ( irq_desc[irq].handler != &gatwick_pic )
printk("gatwick irq not from gatwick pic\n");
else
ppc_irq_dispatch_handler( regs, irq );
......@@ -361,7 +361,7 @@ pmac_pic_init(void)
max_irqs = 64;
}
for ( i = 0; i < max_real_irqs ; i++ )
irq_desc[i].ctl = &pmac_pic;
irq_desc[i].handler = &pmac_pic;
/* get addresses of first controller */
if (irqctrler) {
......@@ -401,7 +401,7 @@ pmac_pic_init(void)
if (device_is_compatible(irqctrler, "gatwick"))
pmac_fix_gatwick_interrupts(irqctrler, max_real_irqs);
for ( i = max_real_irqs ; i < max_irqs ; i++ )
irq_desc[i].ctl = &gatwick_pic;
irq_desc[i].handler = &gatwick_pic;
request_irq( second_irq, gatwick_action, SA_INTERRUPT,
"gatwick cascade", 0 );
}
......
......@@ -10,6 +10,7 @@
#include <linux/nvram.h>
#include <linux/spinlock.h>
#include <linux/console.h>
#include <linux/irq.h>
#include <asm/page.h>
#include <asm/semaphore.h>
......
......@@ -617,12 +617,12 @@ prep_init_IRQ(void)
if (OpenPIC != NULL) {
for ( i = 16 ; i < 36 ; i++ )
irq_desc[i].ctl = &open_pic;
irq_desc[i].handler = &open_pic;
openpic_init(1);
}
for ( i = 0 ; i < 16 ; i++ )
irq_desc[i].ctl = &i8259_pic;
irq_desc[i].handler = &i8259_pic;
i8259_init();
#ifdef __SMP__
request_irq(openpic_to_irq(OPENPIC_VEC_SPURIOUS), openpic_ipi_action,
......
......@@ -412,7 +412,7 @@ void __init pci_read_bridge_bases(struct pci_bus *child)
}
}
static __init struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
static struct pci_bus * __init pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
{
struct pci_bus *child;
......@@ -445,7 +445,7 @@ static __init struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci
* A CardBus bridge is basically the same as a regular PCI bridge,
* except we don't scan behind it because it will be changing.
*/
static __init int pci_scan_cardbus(struct pci_bus *bus, struct pci_dev *dev, int busnr)
static int __init pci_scan_cardbus(struct pci_bus *bus, struct pci_dev *dev, int busnr)
{
unsigned short cr;
unsigned int buses;
......@@ -500,7 +500,7 @@ static unsigned int __init pci_do_scan_bus(struct pci_bus *bus);
/*
* If it's a bridge, scan the bus behind it.
*/
static __init int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max)
static int __init pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max)
{
unsigned int buses;
unsigned short cr;
......@@ -566,7 +566,7 @@ static __init int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int
* Read interrupt line and base address registers.
* The architecture-dependent code can tweak these, of course.
*/
static __init void pci_read_irq(struct pci_dev *dev)
static void __init pci_read_irq(struct pci_dev *dev)
{
unsigned char irq;
......
......@@ -2150,7 +2150,7 @@
1948 Solo?
1968 ES1968 Maestro 2
1969 ES1969 Solo-1 Audiodrive
1978 ES1978 Maestro Audiodrive
1978 ES1978 Maestro 2E
2808 ES336H Fax Modem (Later Model)
2898 ES2898 Modem
125e Specialvideo Engineering SRL
......@@ -2216,7 +2216,7 @@
e886 IT8330G
1284 Sahara Networks, Inc.
1285 Platform Technologies, Inc.
0100 PT-201C-O-P AGOGO-XP sound chip
0100 AGOGO sound chip (aka ESS Maestro 1)
1286 Mazet GmbH
1287 M-Pact, Inc.
001e LS220D DVD Decoder
......
......@@ -340,10 +340,13 @@ void cb_free(socket_info_t *s)
if (c) {
struct pci_dev **p;
/* Unlink from PCI device chain */
for (p = &pci_devices; *p; p = &((*p)->next)) {
p = &pci_devices;
while (*p) {
struct pci_dev * dev = *p;
if (dev->bus != s->cap.cb_bus)
if (dev->bus != s->cap.cb_bus) {
p = &dev->next;
continue;
}
*p = dev->next;
#ifdef CONFIG_PROC_FS
pci_proc_detach_device(dev);
......
......@@ -304,6 +304,8 @@ printk("yenta_set_map(%d, %x, %x, %x)\n", map, start, stop, card_start);
exca_writeb(socket, I365_ADDRWIN, addr);
}
exca_writeb(socket, CB_MEM_PAGE(map), start >> 24);
word = (start >> 12) & 0x0fff;
if (mem->flags & MAP_16BIT)
word |= I365_MEM_16BIT;
......@@ -327,8 +329,6 @@ printk("yenta_set_map(%d, %x, %x, %x)\n", map, start, stop, card_start);
word |= I365_MEM_REG;
exca_writew(socket, I365_MEM(map) + I365_W_OFF, word);
exca_writeb(socket, CB_MEM_PAGE(map), start >> 24);
if (mem->flags & MAP_ACTIVE)
exca_writeb(socket, I365_ADDRWIN, addr | enable);
return 0;
......
......@@ -20,9 +20,7 @@ fi
dep_tristate ' Ensoniq AudioPCI (ES1370)' CONFIG_SOUND_ES1370 $CONFIG_SOUND
dep_tristate ' Creative Ensoniq AudioPCI 97 (ES1371)' CONFIG_SOUND_ES1371 $CONFIG_SOUND
dep_tristate ' ESS Technology Solo1' CONFIG_SOUND_ESSSOLO1 $CONFIG_SOUND
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
dep_tristate ' ESS Maestro, Maestro2, Maestro2E driver (EXPERIMENTAL)' CONFIG_SOUND_MAESTRO $CONFIG_SOUND
fi
dep_tristate ' ESS Maestro, Maestro2, Maestro2E driver' CONFIG_SOUND_MAESTRO $CONFIG_SOUND
dep_tristate ' S3 SonicVibes' CONFIG_SOUND_SONICVIBES $CONFIG_SOUND
if [ "$CONFIG_VISWS" = "y" ]; then
dep_tristate ' SGI Visual Workstation Sound' CONFIG_SOUND_VWSND $CONFIG_SOUND
......
This diff is collapsed.
......@@ -22,7 +22,7 @@ comment 'USB Devices'
dep_tristate ' USB keyboard support' CONFIG_USB_KBD $CONFIG_USB
dep_tristate ' USB mouse support' CONFIG_USB_MOUSE $CONFIG_USB
dep_tristate ' USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
dep_tristate ' USB HP scanner support' CONFIG_USB_HP_SCANNER $CONFIG_USB
dep_tristate ' USB Scanner support' CONFIG_USB_SCANNER $CONFIG_USB
dep_tristate ' USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB
dep_tristate ' USB Communications Device Class (ACM) support' CONFIG_USB_ACM $CONFIG_USB
dep_tristate ' USB Serial Converter support' CONFIG_USB_SERIAL $CONFIG_USB
......
......@@ -53,15 +53,13 @@ ifeq ($(CONFIG_USB_MOUSE),y)
endif
ifeq ($(CONFIG_USB_MOUSE),m)
M_OBJS += mouse.o
MI_OBJS += mouse.o
endif
ifeq ($(CONFIG_USB_HP_SCANNER),y)
L_OBJS += hp_scanner.o
ifeq ($(CONFIG_USB_SCANNER),y)
L_OBJS += scanner.o
endif
ifeq ($(CONFIG_USB_HP_SCANNER),m)
M_OBJS +=hp_scanner.o
MI_OBJS +=hp_scanner.o
ifeq ($(CONFIG_USB_SCANNER),m)
M_OBJS +=scanner.o
endif
ifeq ($(CONFIG_USB_ACM),y)
......@@ -69,7 +67,6 @@ ifeq ($(CONFIG_USB_ACM),y)
endif
ifeq ($(CONFIG_USB_ACM),m)
M_OBJS += acm.o
MI_OBJS += acm.o
endif
ifeq ($(CONFIG_USB_PRINTER),y)
......@@ -78,7 +75,6 @@ endif
ifeq ($(CONFIG_USB_PRINTER),m)
M_OBJS += printer.o
MI_OBJS += printer.o
endif
ifeq ($(CONFIG_USB_SERIAL),y)
......@@ -87,7 +83,6 @@ endif
ifeq ($(CONFIG_USB_SERIAL),m)
M_OBJS += usb-serial.o
MI_OBJS += usb-serial.o
endif
ifneq ($(CONFIG_ADB_KEYBOARD),y)
......@@ -111,7 +106,6 @@ endif
ifeq ($(CONFIG_USB_AUDIO),m)
M_OBJS += audio.o
MI_OBJS += audio.o
endif
ifeq ($(CONFIG_USB_CPIA),y)
......@@ -120,7 +114,6 @@ endif
ifeq ($(CONFIG_USB_CPIA),m)
M_OBJS += cpia.o
MI_OBJS += cpia.o
endif
ifeq ($(CONFIG_USB_DC2XX),y)
......@@ -128,7 +121,6 @@ ifeq ($(CONFIG_USB_DC2XX),y)
endif
ifeq ($(CONFIG_USB_DC2XX),m)
M_OBJS += dc2xx.o
MI_OBJS += dc2xx.o
endif
ifeq ($(CONFIG_USB_SCSI),y)
......@@ -152,7 +144,6 @@ endif
ifeq ($(CONFIG_USB_EZUSB),m)
M_OBJS += ezusb.o
MI_OBJS += ezusb.o
endif
ifeq ($(CONFIG_USB_USS720),y)
......@@ -161,7 +152,6 @@ endif
ifeq ($(CONFIG_USB_USS720),m)
M_OBJS += uss720.o
MI_OBJS += uss720.o
endif
ifeq ($(CONFIG_USB_DABUSB),y)
......@@ -170,7 +160,6 @@ endif
ifeq ($(CONFIG_USB_DABUSB),m)
M_OBJS += dabusb.o
MI_OBJS += dabusb.o
endif
include $(TOPDIR)/Rules.make
......
August 30, 1999
Overview
This README will address issues regarding how to configure the kernel
to access a USB HP Scanner. The scanner should support the Scanner
Control Language (SCL) so that applications such as SANE can access it
properly. Refer to the document README.hp_scanner_sane for guidance
on how to configure SANE to use the USB HP Scanner.
Requirements
A host with a USB port. Ideally, either a UHCI (Intel) or OHCI
(Compaq and others) hardware port should work. However, I've only
been able to really use an OHCI controller. I did have access to a
system with a UHCI controller but some very limited testing did not
produce satisfactory results.
A Linux kernel with USB support (preferably 2.3.15+).
A Linux kernel with USB HP Scanner support.
Configuration
Add both USB controller support and USB HP Scanner support using `make
menuconfig`. If you decide to use the ohci-hcd driver, don't forget
to add HUB support. Compile and install the modules. Testing was
performed only as modules, YMMV.
Add a device for the USB scanner: `mknod /dev/usbscanner c 16 1`
Set appropriate permissions for /dev/usbscanner. Both read and write
permissions are needed for proper operation.
Load the appropriate modules:
OHCI:
modprobe usb-ohci
modprobe hp_scanner
OHCI-HCD:
modprobe usb-ohci-hcd
modprobe hub
modprobe hp_scanner
That's it. SANE should now be able to access the device.
There is a small test program (hp_scan.c) that can be used to test the
scanner device. It's purpose is to test the driver(s) without having
to retrieve/configure SANE. Hp_scan.c will scan the entire bed and
put the output into a file called out.dat in the current directory.
The data in the file is raw data.
David /\/elson
dnelson@jump.net
Oct 19, 1999
CHANGES
- Ammended for linux-2.3.22+
- Appended hp_scan.c to end of this README
- Removed most references to HP
OVERVIEW
This README will address issues regarding how to configure the kernel
to access a USB scanner. Although the driver was originally conceived
for USB HP scanners, it's general enough so that it can be used with
other scanners. Also, one can now pass the USB Vendor and
Product ID's using module parameters for unknown scanners. Refer to
the document README.scanner_hp_sane for guidance on how to configure
SANE to use a USB HP Scanner.
ADDITIONAL INFORMATION
http://www.linux-usb.org/
http://www.dynamine.net/linux-usb/HOWTO/
REQUIREMENTS
A host with a USB port. Ideally, either a UHCI (Intel) or OHCI
(Compaq and others) hardware port should work. However, I've only
been able to really use an OHCI controller. I did have access to a
system with a UHCI controller but some very limited testing did not
produce satisfactory results. Luke Ordelmans
<postbus@ordelmans.demon.nl> has reported success using the UHCI host
controller with kernel 2.3.18 and a ChainTech motherboard. Here
lately I've been having better success with the ohci-hcd driver. But
since Linux USB support is still in a state of constant development
that may change at a later date. I am confident that eventually all
the host contollers will perform without incident.
A Linux kernel with USB support (preferably linux-2.3.18+)
A Linux kernel with USB Scanner support.
CONFIGURATION
Using `make menuconfig` or your prefered method for configuring the
kernel, select 'Support for USB', 'OHCI/OHCI-HCD/UHCI' depending on
your hardware, 'USB hub support', and 'USB Scanner support'. Compile
and install the modules (you may need to execute `depmod -a` to update
the module dependencies). Testing was performed only as modules,
YMMV.
Add a device for the USB scanner:
linux-2.3.22 and above: `mknod /dev/usbscanner c 180 48`
linux-2.3.21 and below: `mknod /dev/usbscanner c 16 1`
Set appropriate permissions for /dev/usbscanner (don't forget about
group and world permissions). Both read and write permissions are
required for proper operation.
Load the appropriate modules (if compiled as modules):
OHCI:
modprobe usb-ohci
modprobe scanner
OHCI-HCD:
modprobe usb-ohci-hcd
modprobe hub
modprobe scanner
UHCI:
modprobe usb-uhci
modprobe hub (don't know if this is required or not)
modprobe scanner
That's it. SANE should now be able to access the device.
There is a small test program (hp_scan.c -- appended below) that can
be used to test the scanner device if it's an HP scanner that supports
SCL. Its purpose is to test the driver without having to
retrieve/configure SANE. Hp_scan.c will scan the entire bed and put
the output into a file called 'out.dat' in the current directory. The
data in the file is raw data so it's not very useful for imaging.
MODULE PARAMETERS
If you have a device that wish to experiment with or try using this
driver with, but the Vendor and Product ID's are not coded in, don't
despair. If the driver was compiled as a module, you can pass options
to the driver. Simply add 'options scanner vendor=0x####
product=0x****' to the conf.modules/modules.conf file replacing the
#'s and the *'s with the correct ID's. The ID's can be retrieved from
the messages file or using `cat /proc/bus/usb/devices` if USB /proc
support was selected during kernel configuration.
BUGS
If you encounter any problems feel free to drop me an email.
David /\/elson
dnelson@jump.net
http://www.jump.net/~dnelson
--------------- snip -- hp_scan.c -- snip ---------------
/*
This is a really crude attempt at writing a short test program. It's
mostly only to be used to test connectivity with USB HP scanners that
understand SCL. Currently, the supported models are 4100C, 5200C,
6200C, and the 6300C. Note that the 4200C is *NOT* acceptable.
Copyright (C) David E. Nelson <dnelson@jump.net>, 1999
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 <stdio.h>
#include <stdlib.h>
#include <error.h>
#include <unistd.h>
#include <fcntl.h>
/*
Gray Output produces about a 8945400 byte file.
Color Output produces a 26836200 byte file.
To compile: gcc -o hp_scan hp_scan.c
*/
// #define COLOR /* Undef to scan GrayScale */
int send_cmd(int, const char *, int);
int read_cmd(int, char *, int);
int
main(void) {
ssize_t cnt = 0, total_cnt = 0;
FILE *fpout;
int fp;
int data_size = 32768;
char *data;
static char reset_cmd[] = {'\x1b','E'};
#ifdef COLOR
static char data_type_cmd[] = {'\x1b','*','a','5','T'}; /* Color */
static char data_width_cmd[] = {'\x1b','*','a','2','4','G'}; /* 24 Bit Color */
#else
static char data_type_cmd[] = {'\x1b','*','a','4','T'}; /* Gray */
static char data_width_cmd[] = {'\x1b','*','a','8','G'}; /* 8 Bit Gray */
#endif
static char query_cmd[] = {'\x1b', '*', 's', '2', '5', '7', 'E'};
static char start_scan_cmd[] = {'\x1b','*','f','0','S'};
if(!(data=malloc(data_size))) {
perror("malloc failed");
exit (1);
}
if((fp=open("/dev/usbscanner", O_RDWR)) < 0) {
perror("Unable to open scanner device");
exit (1);
}
if((fpout=fopen("out.dat", "w+")) == NULL) {
perror("Unable to open ouput file");
exit(1);
}
send_cmd(fp, reset_cmd, sizeof(reset_cmd));
send_cmd(fp, data_type_cmd, sizeof(data_type_cmd));
send_cmd(fp, data_width_cmd, sizeof(data_width_cmd));
send_cmd(fp, start_scan_cmd, sizeof(start_scan_cmd));
while ((cnt = read(fp, data, data_size)) > 0) {
printf("Read: %u\n", cnt);
if(fwrite(data, sizeof(char), cnt, fpout) < 0) {
perror("Write to output file failed");
exit (1);
}
total_cnt += cnt;
}
if (cnt < 0) {
perror("Read from scanner failed");
exit (1);
}
printf("\nRead %lu bytes.\n", total_cnt);
send_cmd(fp, reset_cmd, sizeof(reset_cmd));
close(fp);
fclose(fpout);
return (0);
}
int
send_cmd(int fp, const char * cmd, int length) {
int result;
int x;
if((result = write(fp, cmd, length)) != length) {
printf ("Write warning: %d bytes requested, %d written\n");
} else if (result < 0) {
perror ("send_cmd failure");
exit (1);
}
return (result);
}
int
read_cmd(int fp, char * response, int length) {
return read(fp, response, length);
}
August 30, 1999
Oct. 19, 1999
NOTE: This is all VERY alpha. Use at your own risk. There is no
warranty expressed nor implied.
CHANGES
- Ammended for Linux-2.3.22+
Introduction
INTRODUCTION
This document will hopefully provide enough info on how to get SANE
working with a Hewlett Packard USB capable scanner using the USB
......@@ -12,30 +13,31 @@ interface. The majority of HP Scanners support the Scanner Control
Language (SCL) which is both published by HP and supported by SANE.
The only HP Scanner that I'm aware of that does not support SCL is the
4200C. All other HP scanners with USB interfaces should work (4100C,
5200C, 6200C). Of course as HP releases new scanners this information
may change.
5200C, 6200C, and 6300C). Of course as HP releases new scanners this
information may change.
Requirements
REQUIREMENTS
In order to get this running you'll need USB support in your kernel in
addition to USB HP Scanner support. Please refer to README.hp_scanner
for issues pertaining to Linux USB and USB HP Scanner support.
addition to USB Scanner support. Please refer to README.scanner
for issues pertaining to Linux USB and USB Scanner support.
An installed version of SANE which is available from
http://www.mostang.com/sane/. Testing has been performed using
version SANE-1.0.1. For instructions on building and installing SANE,
refer to the various README files within the distribution.
refer to the various README files within the SANE distribution.
Ok, so what do I do?
OK, I'VE INSTALLED SANE. SO WHAT DO I DO NOW?
NOTE: $INSTALL_DIR is the location where SANE was installed. It may
be /usr/local, /usr, /opt or somewhere else. If you don't know, ask
your system administrator.
1) Make sure that you have the libsane-hp.* libraries under the
$INSTALL_DIR/lib/sane/ directory.
$INSTALL_DIR/lib/sane/ directory. If you don't, then the HP backend
was either not compiled or installed properly.
2) Under the directory $INSTALL_DIR/etc/sane.d/ edit the following
files: dll.conf, hp.conf.
......@@ -44,24 +46,24 @@ files: dll.conf, hp.conf.
hp.conf: This should contain two lines:
option connect-device
/dev/usbscanner
option connect-device
3) You should now be able to use SANE (xscanimage or scanimage).
Don't forget to read any relevant man pages regarding the usage of
SANE. If you have other entries uncommented in dll.conf, you my have
to specify the device to (x)scanimage. The xscanimage (1) man page
has info on how to get 'The Gimp' to work with xscanimage. Note that
Gimp support must be compiled into SANE for it work. If you are
dealing with a RedHat system, you'll also need to install the
gimp-devel rpm package.
NOTE: Most of the time xscanimage will run without incident, then on
the next invocation it'll core dump at different locations. I don't
know why yet and I don't have a work around either other than to try
again. But once you get it started, it'll scan without any problems
(or at least it does for me).
SANE. If you have other entries uncommented in dll.conf, you may have
to specify the device to (x)scanimage. Again, `man` is your friend.
The xscanimage (1) man page has info on how to get 'The Gimp' to work
with xscanimage. Note that Gimp support must be compiled into SANE
for it work. If you are dealing with a RedHat system, this means that
you'll also need to install the gimp-devel rpm package.
NOTE: The issues regarding core dumping by (x)scanimage have (or seem
to be thus far) been resolved with version 0.2+ of the USB scanner
driver which should be available in linux-2.3.23. If you notice
otherwise, please contact me.
David /\/elson
dnelson@jump.net
http://www.jump.net/~dnelson
This diff is collapsed.
This diff is collapsed.
/* -*- linux-c -*- */
/*
* Driver for USB HP Scanners
*
* David E. Nelson (dnelson@jump.net)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Based upon mouse.c (Brad Keryan) and printer.c (Michael Gee).
*
* History
* 0.1 8/31/1999
*
* Developed/tested using linux-2.3.15 with minor ohci.c changes to
* support short packes during bulk xfer mode. Some testing was
* done with ohci-hcd but the performace was low. Very limited
* testing was performed with uhci but I was unable to get it to
* work. Initial relase to the linux-usb development effort.
*
* */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/random.h>
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/malloc.h>
#include <linux/spinlock.h>
#include "usb.h"
/* stall/wait timeout for scanner */
#define NAK_TIMEOUT (HZ)
/* For some reason, an IBUF_SIZE of 8192 causes REALLY big problems
* with linux-2.3.15. Anything more than 4k seems to not have an
* effect on increasing performance. Anything smaller than 4k hurts
* it. */
#define IBUF_SIZE 4096
/* This is a scanner, so not much data is sent to it. The largest
* stuff may be some kind of maps and stuff but that's kinda rare. */
#define OBUF_SIZE 128
struct hpscan_usb_data {
struct usb_device *hpscan_dev; /* init: probe_scanner */
__u8 isopen; /* nz if open */
__u8 present; /* Device is present on the bus */
char *obuf; /* transfer buffers */
char *ibuf;
wait_queue_head_t wait_q; /* for timeouts */
};
static struct hpscan_usb_data hpscan;
static int
open_scanner(struct inode * inode, struct file * file)
{
struct hpscan_usb_data *hps = &hpscan;
if (hps->isopen) {
return -EBUSY;
}
hps->isopen = 1;
init_waitqueue_head(&hps->wait_q);
MOD_INC_USE_COUNT;
return 0;
}
static int
close_scanner(struct inode * inode, struct file * file)
{
struct hpscan_usb_data *hps = &hpscan;
hps->isopen = 0;
MOD_DEC_USE_COUNT;
return 0;
}
static ssize_t
write_scanner(struct file * file, const char * buffer,
size_t count, loff_t *ppos)
{
struct hpscan_usb_data *hps = &hpscan;
unsigned long copy_size;
unsigned long bytes_written = 0;
unsigned long partial;
int result = 0;
int maxretry;
do {
unsigned long thistime;
char *obuf = hps->obuf;
thistime = copy_size = (count > OBUF_SIZE) ? OBUF_SIZE : count;
if (copy_from_user(hps->obuf, buffer, copy_size))
return -EFAULT;
maxretry = 5;
while (thistime) {
if (!hps->hpscan_dev)
return -ENODEV;
if (signal_pending(current)) {
return bytes_written ? bytes_written : -EINTR;
}
result = usb_bulk_msg(hps->hpscan_dev,usb_sndbulkpipe(hps->hpscan_dev, 2), obuf, thistime, &partial, HZ*10);
//printk(KERN_DEBUG "write stats: result:%d thistime:%lu partial:%lu\n", result, thistime, partial);
if (result == USB_ST_TIMEOUT) { /* NAK - so hold for a while */
if(!maxretry--) {
return -ETIME;
}
interruptible_sleep_on_timeout(&hps->wait_q, NAK_TIMEOUT);
continue;
} else if (!result & partial) {
obuf += partial;
thistime -= partial;
} else
break;
};
if (result) {
printk("Write Whoops - %x\n", result);
return -EIO;
}
bytes_written += copy_size;
count -= copy_size;
buffer += copy_size;
} while ( count > 0 );
return bytes_written ? bytes_written : -EIO;
}
static ssize_t
read_scanner(struct file * file, char * buffer,
size_t count, loff_t *ppos)
{
struct hpscan_usb_data *hps = &hpscan;
ssize_t read_count;
unsigned long partial;
int this_read;
int result;
/* Wait for the scanner to get it's act together. This may involve
* resetting the head, warming up the lamp, etc. maxretry is number
* of seconds. */
int maxretry = 30;
char *ibuf = hps->ibuf;
read_count = 0;
while (count) {
if (signal_pending(current)) {
return read_count ? read_count : -EINTR;
}
if (!hps->hpscan_dev)
return -ENODEV;
this_read = (count > IBUF_SIZE) ? IBUF_SIZE : count;
result = usb_bulk_msg(hps->hpscan_dev, usb_rcvbulkpipe(hps->hpscan_dev, 1), ibuf, this_read, &partial, HZ*10);
printk(KERN_DEBUG "read stats: result:%d this_read:%u partial:%lu\n", result, this_read, partial);
if (partial) {
count = this_read = partial;
} else if (result == USB_ST_TIMEOUT || result == 15) { /* FIXME: 15 ??? */
if(!maxretry--) {
printk(KERN_DEBUG "read_scanner: maxretry timeout\n");
return -ETIME;
}
interruptible_sleep_on_timeout(&hps->wait_q, NAK_TIMEOUT);
continue;
} else if (result != USB_ST_DATAUNDERRUN) {
printk("Read Whoops - result:%u partial:%lu this_read:%u\n", result, partial, this_read);
return -EIO;
} else {
return (0);
}
if (this_read) {
if (copy_to_user(buffer, ibuf, this_read))
return -EFAULT;
count -= this_read;
read_count += this_read;
buffer += this_read;
}
}
return read_count;
}
static void *
probe_scanner(struct usb_device *dev, unsigned int ifnum)
{
struct hpscan_usb_data *hps = &hpscan;
/*
* Don't bother using an HP 4200C since it does NOT understand
* SCL and HP isn't going to be releasing the specs any time
* soon. */
if (dev->descriptor.idVendor != 0x3f0 ) {
printk(KERN_INFO "Scanner is not an HP Scanner.\n");
return NULL;
}
if (dev->descriptor.idProduct != 0x101 && /* HP 4100C */
dev->descriptor.idProduct != 0x202 && /* HP 5100C */
dev->descriptor.idProduct != 0x601) { /* HP 6300C */
printk(KERN_INFO "Scanner model not supported/tested.\n");
return NULL;
}
printk(KERN_DEBUG "USB Scanner found at address %d\n", dev->devnum);
hps->present = 1;
hps->hpscan_dev = dev;
if (!(hps->obuf = (char *)kmalloc(OBUF_SIZE, GFP_KERNEL))) {
return NULL;
}
if (!(hps->ibuf = (char *)kmalloc(IBUF_SIZE, GFP_KERNEL))) {
return NULL;
}
return hps;
}
static void
disconnect_scanner(struct usb_device *dev, void *ptr)
{
struct hpscan_usb_data *hps = (struct hpscan_usb_data *) ptr;
if (hps->isopen) {
/* better let it finish - the release will do whats needed */
hps->hpscan_dev = NULL;
return;
}
kfree(hps->ibuf);
kfree(hps->obuf);
hps->present = 0;
}
static struct
file_operations usb_scanner_fops = {
NULL, /* seek */
read_scanner,
write_scanner,
NULL, /* readdir */
NULL, /* poll */
NULL, /* ioctl */
NULL, /* mmap */
open_scanner,
NULL, /* flush */
close_scanner,
NULL,
NULL, /* fasync */
};
static struct
usb_driver scanner_driver = {
"usbscanner",
probe_scanner,
disconnect_scanner,
{ NULL, NULL },
&usb_scanner_fops,
48
};
int
usb_hp_scanner_init(void)
{
if (usb_register(&scanner_driver) < 0)
return -1;
printk(KERN_DEBUG "USB Scanner support registered.\n");
return 0;
}
void
usb_hp_scanner_cleanup(void)
{
struct hpscan_usb_data *hps = &hpscan;
hps->present = 0;
usb_deregister(&scanner_driver);
}
#ifdef MODULE
int
init_module(void)
{
return usb_hp_scanner_init();
}
void
cleanup_module(void)
{
usb_hp_scanner_cleanup();
}
#endif
......@@ -4,6 +4,8 @@
* (C) Copyright 1999 Linus Torvalds
* (C) Copyright 1999 Johannes Erdfelt
* (C) Copyright 1999 Gregory P. Smith
*
* $Id: hub.c,v 1.15 1999/12/27 15:17:45 acher Exp $
*/
#include <linux/kernel.h>
......@@ -45,6 +47,12 @@ static int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size)
USB_DT_HUB << 8, 0, data, size, HZ);
}
static int usb_clear_hub_feature(struct usb_device *dev, int feature)
{
return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0 , NULL, 0, HZ);
}
static int usb_clear_port_feature(struct usb_device *dev, int port, int feature)
{
return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
......@@ -190,7 +198,6 @@ static int usb_hub_configure(struct usb_hub *hub)
printk(KERN_INFO "hub: enabling power on all ports\n");
for (i = 0; i < hub->nports; i++)
usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER);
return 0;
}
......@@ -305,7 +312,9 @@ static void usb_hub_port_connect_change(struct usb_device *hub, int port)
struct usb_device *usb;
struct usb_port_status portsts;
unsigned short portstatus, portchange;
int tries;
wait_ms(100);
/* Check status */
if (usb_get_port_status(hub, port + 1, &portsts)<0) {
printk(KERN_ERR "get_port_status failed\n");
......@@ -314,7 +323,8 @@ static void usb_hub_port_connect_change(struct usb_device *hub, int port)
portstatus = le16_to_cpu(portsts.wPortStatus);
portchange = le16_to_cpu(portsts.wPortChange);
printk("hub.c: portstatus %x, change %x\n",portstatus,portchange);
printk("hub.c: portstatus %x, change %x, %s\n",portstatus,portchange,
(portstatus&(1<<USB_PORT_FEAT_LOWSPEED)?"Low Speed":"High Speed"));
/* If it's not in CONNECT and ENABLE state, we're done */
if ((!(portstatus & USB_PORT_STAT_CONNECTION)) &&
(!(portstatus & USB_PORT_STAT_ENABLE))) {
......@@ -324,10 +334,37 @@ static void usb_hub_port_connect_change(struct usb_device *hub, int port)
return;
}
wait_ms(400);
/* Reset the port */
usb_set_port_feature(hub, port + 1, USB_PORT_FEAT_RESET);
wait_ms(100);
#define MAX_TRIES 5
for(tries=0;tries<MAX_TRIES;tries++) {
usb_set_port_feature(hub, port + 1, USB_PORT_FEAT_RESET);
wait_ms(200);
if (usb_get_port_status(hub, port + 1, &portsts)<0) {
printk(KERN_ERR "get_port_status failed\n");
return;
}
portstatus = le16_to_cpu(portsts.wPortStatus);
portchange = le16_to_cpu(portsts.wPortChange);
printk("hub.c: portstatus %x, change %x, %s\n",portstatus,portchange,
(portstatus&(1<<USB_PORT_FEAT_LOWSPEED)?"Low Speed":"High Speed"));
if ((portstatus&(1<<USB_PORT_FEAT_ENABLE)))
break;
wait_ms(200);
}
if (tries==MAX_TRIES) {
printk("hub.c: Can not enable port %i after %i retries, disabling port\n",port+1,MAX_TRIES);
return;
}
/* Allocate a new device struct for it */
usb = usb_alloc_dev(hub, hub->bus);
if (!usb) {
printk(KERN_ERR "couldn't allocate usb_device\n");
......
......@@ -13,8 +13,8 @@ void usb_major_init(void);
void usb_major_cleanup(void);
int usb_mouse_init(void);
void usb_mouse_cleanup(void);
int usb_hp_scanner_init(void);
void usb_hp_scanner_cleanup(void);
int usb_scanner_init(void);
void usb_scanner_cleanup(void);
int usb_printer_init(void);
int usb_scsi_init(void);
int usb_serial_init(void);
......
......@@ -9,7 +9,7 @@ unsigned char usb_kbd_map[256] =
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
0x1c, 0x01, 0x0e, 0x0f, 0x39, 0x0c, 0x0d, 0x1a,
0x1b, 0x2b, 0x00, 0x27, 0x28, 0x29, 0x33, 0x34,
0x1b, 0x2b, 0x2b, 0x27, 0x28, 0x29, 0x33, 0x34,
0x35, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
0x41, 0x42, 0x43, 0x44, 0x57, 0x58, 0xb7, 0x46,
......@@ -18,7 +18,7 @@ unsigned char usb_kbd_map[256] =
0xcb, 0xd0, 0xc8, 0x45, 0xb5, 0x37, 0x4a, 0x4e,
0x9c, 0x4f, 0x50, 0x51, 0x4b, 0x4c, 0x4d, 0x47,
0x48, 0x49, 0x52, 0x53, 0x00, 0x6d, 0x00, 0x00,
0x48, 0x49, 0x52, 0x53, 0x56, 0x6d, 0x00, 0x00,
0xbd, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
......
......@@ -236,22 +236,38 @@ static ssize_t write_mouse(struct file * file,
/*
* Look like a PS/2 mouse, please..
*
* In XFree86 (3.3.5 tested) you must select Protocol "NetMousePS/2",
* then use your wheel as Button 4 and 5 via ZAxisMapping 4 5.
* The PS/2 protocol is fairly strange, but
* oh, well, it's at least common..
*/
static ssize_t read_mouse(struct file * file, char * buffer, size_t count, loff_t *ppos)
{
DECLARE_WAITQUEUE(wait, current);
int retval = 0;
static int state = 0;
struct mouse_state *mouse = &static_mouse_state;
if (!mouse->present)
return 0;
/*
* FIXME - Other mouse drivers handle blocking and nonblocking reads
* differently here...
*/
if (!mouse->ready) {
if (file->f_flags & O_NONBLOCK) return -EAGAIN;
add_wait_queue(&mouse->wait, &wait);
repeat:
set_current_state(TASK_INTERRUPTIBLE);
if (!mouse->ready && !signal_pending(current)) {
schedule();
goto repeat;
}
current->state = TASK_RUNNING;
remove_wait_queue(&mouse->wait, &wait);
}
if (signal_pending(current)) return -ERESTARTSYS;
if (!mouse->present)
return 0;
if (count) {
mouse->ready = 0;
switch (state) {
......@@ -389,7 +405,7 @@ struct file_operations usb_mouse_fops = {
{
printk(KERN_DEBUG "%s(%d): mouse resume\n", __FILE__, __LINE__);
/* restart the usb controller's polling of the mouse */
pipe = usb_rcvintpipe(mouse->dev, mouse->bEndpointAddress);
FILL_INT_URB(mouse->urb,mouse->dev,pipe,
mouse->buffer,
......@@ -411,10 +427,11 @@ struct file_operations usb_mouse_fops = {
static void mouse_disconnect(struct usb_device *dev, void *priv)
{
struct mouse_state *mouse = priv;
/* stop the usb interrupt transfer */
if (mouse->present) {
usb_unlink_urb(mouse->urb);
usb_unlink_urb(mouse->urb);
wake_up(&mouse->wait);
}
/* this might need work */
......
/* Driver for USB Printers
*
* Copyright 1999 Michael Gee (michael@linuxspecific.com)
......@@ -22,6 +21,14 @@
#include "usb.h"
/* Define IEEE_DEVICE_ID if you want to see the IEEE-1284 Device ID string.
* This may include the printer's serial number.
* An example from an HP 970C DeskJet printer is (this is one long string,
* with the serial number changed):
MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:Hewlett-Packard DeskJet 970C;SERN:US970CSEPROF;VSTATUS:$HB0$NC0,ff,DN,IDLE,CUT,K1,C0,DP,NR,KP000,CP027;VP:0800,FL,B0;VJ: ;
*/
#define IEEE_DEVICE_ID
#define NAK_TIMEOUT (HZ) /* stall wait for printer */
#define MAX_RETRY_COUNT ((60*60*HZ)/NAK_TIMEOUT) /* should not take 1 minute a page! */
......@@ -62,12 +69,16 @@ static struct pp_usb_data *minor_data[MAX_PRINTERS];
static unsigned char printer_read_status(struct pp_usb_data *p)
{
__u8 status;
int err;
struct usb_device *dev = p->pusb_dev;
if (usb_control_msg(dev, usb_rcvctrlpipe(dev,0),
err = usb_control_msg(dev, usb_rcvctrlpipe(dev,0),
USB_PRINTER_REQ_GET_PORT_STATUS,
USB_TYPE_CLASS | USB_RT_INTERFACE | USB_DIR_IN,
0, 0, &status, sizeof(status), HZ)) {
0, 0, &status, sizeof(status), HZ);
if (err < 0) {
printk(KERN_ERR "usblp%d: read_status control_msg error = %d\n",
p->minor, err);
return 0;
}
return status;
......@@ -105,11 +116,15 @@ static int printer_check_status(struct pp_usb_data *p)
static void printer_reset(struct pp_usb_data *p)
{
struct usb_device *dev = p->pusb_dev;
int err;
usb_control_msg(dev, usb_sndctrlpipe(dev,0),
err = usb_control_msg(dev, usb_sndctrlpipe(dev,0),
USB_PRINTER_REQ_SOFT_RESET,
USB_TYPE_CLASS | USB_RECIP_OTHER,
0, 0, NULL, 0, HZ);
if (err < 0)
printk(KERN_ERR "usblp%d: reset control_msg error = %d\n",
p->minor, err);
}
static int open_printer(struct inode *inode, struct file *file)
......@@ -125,10 +140,14 @@ static int open_printer(struct inode *inode, struct file *file)
p->minor = MINOR(inode->i_rdev);
if (p->isopen++) {
printk(KERN_ERR "usblp%d: printer is already open\n",
p->minor);
return -EBUSY;
}
if (!(p->obuf = (char *)__get_free_page(GFP_KERNEL))) {
p->isopen = 0;
printk(KERN_ERR "usblp%d: cannot allocate memory\n",
p->minor);
return -ENOMEM;
}
......@@ -176,6 +195,7 @@ static ssize_t write_printer(struct file *file,
if (copy_from_user(p->obuf, buffer, copy_size))
return -EFAULT;
maxretry = MAX_RETRY_COUNT;
while (thistime) {
if (!p->pusb_dev)
return -ENODEV;
......@@ -238,6 +258,9 @@ static ssize_t read_printer(struct file *file,
result = usb_bulk_msg(p->pusb_dev,
usb_rcvbulkpipe(p->pusb_dev, p->bulk_in_ep),
buf, this_read, &partial, HZ*20);
if (result < 0)
printk(KERN_ERR "usblp%d read_printer bulk_msg error = %d\n",
p->minor, result);
/* unlike writes, we don't retry a NAK, just stop now */
if (!result & partial)
......@@ -253,6 +276,7 @@ static ssize_t read_printer(struct file *file,
buffer += this_read;
}
}
return read_count;
}
......@@ -261,6 +285,7 @@ static void *printer_probe(struct usb_device *dev, unsigned int ifnum)
struct usb_interface_descriptor *interface;
struct pp_usb_data *pp;
int i;
__u8 status;
/*
* FIXME - this will not cope with combined printer/scanners
......@@ -311,19 +336,20 @@ static void *printer_probe(struct usb_device *dev, unsigned int ifnum)
break;
}
if (i >= MAX_PRINTERS) {
printk(KERN_ERR "No minor table space available for USB Printer\n");
printk(KERN_ERR "No minor table space available for new USB printer\n");
return NULL;
}
printk(KERN_INFO "USB Printer found at address %d\n", dev->devnum);
printk(KERN_INFO "USB printer found at address %d\n", dev->devnum);
if (!(pp = kmalloc(sizeof(struct pp_usb_data), GFP_KERNEL))) {
printk(KERN_DEBUG "usb_printer: no memory!\n");
printk(KERN_DEBUG "USB printer: no memory!\n");
return NULL;
}
memset(pp, 0, sizeof(struct pp_usb_data));
minor_data[i] = PPDATA(pp);
pp->minor = i;
pp->pusb_dev = dev;
pp->maxout = (BIG_BUF_SIZE > PAGE_SIZE) ? PAGE_SIZE : BIG_BUF_SIZE;
......@@ -355,37 +381,44 @@ static void *printer_probe(struct usb_device *dev, unsigned int ifnum)
pp->bulk_out_index,
pp->bulk_out_ep);
#if 1
#ifdef IEEE_DEVICE_ID
{
__u8 status;
__u8 ieee_id[64]; /* first 2 bytes are (big-endian) length */
int length = be16_to_cpup((__u16 *)ieee_id);
__u8 ieee_id[64]; /* first 2 bytes are (big-endian) length */
/* This string space may be too short. */
int length = (ieee_id[0] << 8) + ieee_id[1]; /* high-low */
/* This calc. or be16_to_cpu() both get
* some weird results for <length>. */
int err;
/* Let's get the device id if possible. */
if (usb_control_msg(dev, usb_rcvctrlpipe(dev,0),
err = usb_control_msg(dev, usb_rcvctrlpipe(dev,0),
USB_PRINTER_REQ_GET_DEVICE_ID,
USB_TYPE_CLASS | USB_RT_INTERFACE | USB_DIR_IN,
0, 0, ieee_id,
sizeof(ieee_id)-1, HZ) == 0) {
sizeof(ieee_id)-1, HZ);
if (err >= 0) {
if (ieee_id[1] < sizeof(ieee_id) - 1)
ieee_id[ieee_id[1]+2] = '\0';
else
ieee_id[sizeof(ieee_id)-1] = '\0';
printk(KERN_INFO " usblp%d Device ID length=%d, string=%s\n",
pp->minor, length, &ieee_id[2]);
printk(KERN_INFO "usblp%d Device ID length=%d [%x:%x]\n",
pp->minor, length, ieee_id[0], ieee_id[1]);
printk(KERN_INFO "usblp%d Device ID=%s\n",
pp->minor, &ieee_id[2]);
}
else
printk(KERN_INFO " usblp%d: error reading IEEE-1284 Device ID\n",
pp->minor);
status = printer_read_status(PPDATA(pp));
printk(KERN_INFO " usblp%d Probe Status is %x: %s,%s,%s\n",
pp->minor, status,
(status & LP_PSELECD) ? "Selected" : "Not Selected",
(status & LP_POUTPA) ? "No Paper" : "Paper",
(status & LP_PERRORP) ? "No Error" : "Error");
printk(KERN_INFO "usblp%d: error = %d reading IEEE-1284 Device ID\n",
pp->minor, err);
}
#endif
status = printer_read_status(PPDATA(pp));
printk(KERN_INFO "usblp%d probe status is %x: %s,%s,%s\n",
pp->minor, status,
(status & LP_PSELECD) ? "Selected" : "Not Selected",
(status & LP_POUTPA) ? "No Paper" : "Paper",
(status & LP_PERRORP) ? "No Error" : "Error");
return pp;
}
......@@ -431,7 +464,7 @@ int usb_printer_init(void)
if (usb_register(&printer_driver))
return -1;
printk(KERN_INFO "USB Printer support registered.\n");
printk(KERN_INFO "USB Printer driver registered.\n");
return 0;
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -43,8 +43,8 @@ int usb_init(void)
# ifdef CONFIG_USB_MOUSE
usb_mouse_init();
# endif
# ifdef CONFIG_USB_HP_SCANNER
usb_hp_scanner_init();
# ifdef CONFIG_USB_SCANNER
usb_scanner_init();
# endif
# ifdef CONFIG_USB_KBD
usb_kbd_init();
......@@ -92,8 +92,8 @@ void cleanup_drivers(void)
# ifdef CONFIG_USB_MOUSE
usb_mouse_cleanup();
# endif
# ifdef CONFIG_USB_HP_SCANNER
usb_hp_scanner_cleanup();
# ifdef CONFIG_USB_SCANNER
usb_scanner_cleanup();
# endif
# ifdef CONFIG_USB_DABUSB
dabusb_cleanup();
......
......@@ -15,7 +15,7 @@
* It should be considered a slave, with no callbacks. Callbacks
* are evil.
*
* $Id: usb.c,v 1.37 1999/12/17 10:48:08 fliegl Exp $
* $Id: usb.c,v 1.39 1999/12/27 15:17:47 acher Exp $
*/
#ifndef EXPORT_SYMTAB
......@@ -36,12 +36,9 @@
#define MODSTR "usbcore: "
#ifdef USB_DEBUG
#define dbg printk
#define dbg(format, arg...) printk(format, ## arg)
#else
#define dbg nix
static void nix(const char *format, ...)
{
}
#define dbg(format, arg...)
#endif
/*
......
This diff is collapsed.
......@@ -29,6 +29,7 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
tristate 'EFS filesystem support (read only) (EXPERIMENTAL)' CONFIG_EFS_FS
fi
tristate 'Compressed ROM filessytem support' CONFIG_CRAMFS
tristate 'ISO 9660 CDROM filesystem support' CONFIG_ISO9660_FS
if [ "$CONFIG_ISO9660_FS" != "n" ]; then
bool ' Microsoft Joliet CDROM extensions' CONFIG_JOLIET
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment