Commit add4b624 authored by Linus Torvalds's avatar Linus Torvalds

Import 2.1.123

parent d13a7654
...@@ -237,7 +237,6 @@ CONFIG_MOUSE=y ...@@ -237,7 +237,6 @@ CONFIG_MOUSE=y
CONFIG_PSMOUSE=y CONFIG_PSMOUSE=y
CONFIG_82C710_MOUSE=y CONFIG_82C710_MOUSE=y
# CONFIG_PC110_PAD is not set # CONFIG_PC110_PAD is not set
# CONFIG_UMISC is not set
# CONFIG_QIC02_TAPE is not set # CONFIG_QIC02_TAPE is not set
# CONFIG_WATCHDOG is not set # CONFIG_WATCHDOG is not set
# CONFIG_RTC is not set # CONFIG_RTC is not set
......
...@@ -290,6 +290,43 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pci_pin) ...@@ -290,6 +290,43 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pci_pin)
return -1; return -1;
} }
/*
* ISA Edge/Level control register, ELCR
*/
static int __init ISA_ELCR(unsigned int irq)
{
if (irq < 16) {
unsigned int port = 0x4d0 + (irq >> 3);
return (inb(port) >> (irq & 7)) & 1;
}
printk("Broken MPtable reports ISA irq %d\n", irq);
return 0;
}
/*
* ISA interrupts can be:
* - level triggered, active low (ELCR = 1)
* - edge triggered, active high (ELCR = 0)
* - edge triggered, active low (magic irq 8)
*/
static int __init default_ISA_trigger(int idx)
{
unsigned int irq = mp_irqs[idx].mpc_dstirq;
if (irq == 8)
return 0;
return ISA_ELCR(irq);
}
static int __init default_ISA_polarity(int idx)
{
unsigned int irq = mp_irqs[idx].mpc_dstirq;
if (irq == 8)
return 1;
return ISA_ELCR(irq);
}
/* /*
* There are broken mptables which register ISA+high-active+level IRQs, * There are broken mptables which register ISA+high-active+level IRQs,
* these are illegal and are converted here to ISA+high-active+edge * these are illegal and are converted here to ISA+high-active+edge
...@@ -314,7 +351,7 @@ static int __init MPBIOS_polarity(int idx) ...@@ -314,7 +351,7 @@ static int __init MPBIOS_polarity(int idx)
{ {
case MP_BUS_ISA: /* ISA pin */ case MP_BUS_ISA: /* ISA pin */
{ {
polarity = 0; polarity = default_ISA_polarity(idx);
break; break;
} }
case MP_BUS_PCI: /* PCI pin */ case MP_BUS_PCI: /* PCI pin */
...@@ -371,16 +408,9 @@ static int __init MPBIOS_trigger(int idx) ...@@ -371,16 +408,9 @@ static int __init MPBIOS_trigger(int idx)
{ {
switch (mp_bus_id_to_type[bus]) switch (mp_bus_id_to_type[bus])
{ {
case MP_BUS_ISA: { case MP_BUS_ISA:
/* ISA pin, read the Edge/Level control register */ {
unsigned int irq = mp_irqs[idx].mpc_dstirq; trigger = default_ISA_trigger(idx);
if (irq < 16) {
unsigned int port = 0x4d0 + (irq >> 3);
trigger = (inb(port) >> (irq & 7)) & 1;
break;
}
printk("Broken MPtable reports ISA irq %d\n", irq);
trigger = 1;
break; break;
} }
case MP_BUS_PCI: /* PCI pin, level */ case MP_BUS_PCI: /* PCI pin, level */
...@@ -556,7 +586,7 @@ void __init setup_IO_APIC_irqs(void) ...@@ -556,7 +586,7 @@ void __init setup_IO_APIC_irqs(void)
entry.delivery_mode = dest_LowestPrio; entry.delivery_mode = dest_LowestPrio;
entry.dest_mode = 1; /* logical delivery */ entry.dest_mode = 1; /* logical delivery */
entry.mask = 0; /* enable IRQ */ entry.mask = 0; /* enable IRQ */
entry.dest.logical.logical_dest = 0xff; /* all CPUs */ entry.dest.logical.logical_dest = 0; /* but no route */
idx = find_irq_entry(pin,mp_INT); idx = find_irq_entry(pin,mp_INT);
if (idx == -1) { if (idx == -1) {
...@@ -571,6 +601,12 @@ void __init setup_IO_APIC_irqs(void) ...@@ -571,6 +601,12 @@ void __init setup_IO_APIC_irqs(void)
entry.trigger = irq_trigger(idx); entry.trigger = irq_trigger(idx);
entry.polarity = irq_polarity(idx); entry.polarity = irq_polarity(idx);
if (irq_trigger(idx)) {
entry.trigger = 1;
entry.mask = 1;
entry.dest.logical.logical_dest = 0xff;
}
irq = pin_2_irq(idx,pin); irq = pin_2_irq(idx,pin);
irq_2_pin[irq] = pin; irq_2_pin[irq] = pin;
...@@ -584,37 +620,14 @@ void __init setup_IO_APIC_irqs(void) ...@@ -584,37 +620,14 @@ void __init setup_IO_APIC_irqs(void)
if (trigger_flag_broken (idx)) if (trigger_flag_broken (idx))
printk("broken BIOS, changing pin %d to edge\n", pin); printk("broken BIOS, changing pin %d to edge\n", pin);
io_apic_write(0x10+2*pin, *(((int *)&entry)+0));
io_apic_write(0x11+2*pin, *(((int *)&entry)+1)); io_apic_write(0x11+2*pin, *(((int *)&entry)+1));
io_apic_write(0x10+2*pin, *(((int *)&entry)+0));
} }
if (!first_notcon) if (!first_notcon)
printk(" not connected.\n"); printk(" not connected.\n");
} }
void __init setup_IO_APIC_irq_ISA_default(unsigned int irq)
{
struct IO_APIC_route_entry entry;
/*
* add it to the IO-APIC irq-routing table:
*/
memset(&entry,0,sizeof(entry));
entry.delivery_mode = dest_LowestPrio; /* lowest prio */
entry.dest_mode = 1; /* logical delivery */
entry.mask = 0; /* unmask IRQ now */
entry.dest.logical.logical_dest = 0xff; /* all CPUs */
entry.vector = assign_irq_vector(irq);
entry.polarity = 0;
entry.trigger = 0;
io_apic_write(0x10+2*irq, *(((int *)&entry)+0));
io_apic_write(0x11+2*irq, *(((int *)&entry)+1));
}
/* /*
* Set up a certain pin as ExtINT delivered interrupt * Set up a certain pin as ExtINT delivered interrupt
*/ */
...@@ -630,7 +643,7 @@ void __init setup_ExtINT_pin(unsigned int pin) ...@@ -630,7 +643,7 @@ void __init setup_ExtINT_pin(unsigned int pin)
entry.delivery_mode = dest_ExtINT; entry.delivery_mode = dest_ExtINT;
entry.dest_mode = 1; /* logical delivery */ entry.dest_mode = 1; /* logical delivery */
entry.mask = 0; /* unmask IRQ now */ entry.mask = 0; /* unmask IRQ now */
entry.dest.logical.logical_dest = 0x01; /* all CPUs */ entry.dest.logical.logical_dest = 0x01; /* logical CPU #0 */
entry.vector = 0; /* it's ignored */ entry.vector = 0; /* it's ignored */
...@@ -1016,10 +1029,8 @@ static void do_edge_ioapic_IRQ(unsigned int irq, struct pt_regs * regs) ...@@ -1016,10 +1029,8 @@ static void do_edge_ioapic_IRQ(unsigned int irq, struct pt_regs * regs)
/* /*
* If there is no IRQ handler or it was disabled, exit early. * If there is no IRQ handler or it was disabled, exit early.
*/ */
if (!action) { if (!action)
printk("Unhandled edge irq %d (%x %p)\n", irq, status, desc->action);
return; return;
}
/* /*
* Edge triggered interrupts need to remember * Edge triggered interrupts need to remember
...@@ -1070,10 +1081,8 @@ static void do_level_ioapic_IRQ(unsigned int irq, struct pt_regs * regs) ...@@ -1070,10 +1081,8 @@ static void do_level_ioapic_IRQ(unsigned int irq, struct pt_regs * regs)
spin_unlock(&irq_controller_lock); spin_unlock(&irq_controller_lock);
/* Exit early if we had no action or it was disabled */ /* Exit early if we had no action or it was disabled */
if (!action) { if (!action)
printk("Unhandled level irq %d (%x)\n", irq, status);
return; return;
}
handle_IRQ_event(irq, regs, action); handle_IRQ_event(irq, regs, action);
...@@ -1152,8 +1161,9 @@ static inline void check_timer(void) ...@@ -1152,8 +1161,9 @@ static inline void check_timer(void)
pin1 = find_timer_pin(mp_INT); pin1 = find_timer_pin(mp_INT);
pin2 = find_timer_pin(mp_ExtINT); pin2 = find_timer_pin(mp_ExtINT);
enable_IO_APIC_irq(0);
if (!timer_irq_works()) { if (!timer_irq_works()) {
if (pin1 != -1) if (pin1 != -1)
printk("..MP-BIOS bug: 8254 timer not connected to IO-APIC\n"); printk("..MP-BIOS bug: 8254 timer not connected to IO-APIC\n");
printk("...trying to set up timer as ExtINT... "); printk("...trying to set up timer as ExtINT... ");
......
...@@ -664,10 +664,8 @@ static void do_8259A_IRQ(unsigned int irq, struct pt_regs * regs) ...@@ -664,10 +664,8 @@ static void do_8259A_IRQ(unsigned int irq, struct pt_regs * regs)
spin_unlock(&irq_controller_lock); spin_unlock(&irq_controller_lock);
/* Exit early if we had no action or it was disabled */ /* Exit early if we had no action or it was disabled */
if (!action) { if (!action)
printk("Unhandled irq %d (%x)\n", irq, desc->status);
return; return;
}
handle_IRQ_event(irq, regs, action); handle_IRQ_event(irq, regs, action);
......
...@@ -57,16 +57,10 @@ if [ "$CONFIG_MOUSE" = "y" ]; then ...@@ -57,16 +57,10 @@ if [ "$CONFIG_MOUSE" = "y" ]; then
tristate 'Logitech busmouse support' CONFIG_BUSMOUSE tristate 'Logitech busmouse support' CONFIG_BUSMOUSE
tristate 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE tristate 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE
tristate 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE tristate 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE
if [ "$CONFIG_PSMOUSE" != "n" ]; then tristate 'C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE
bool 'C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE
fi
tristate 'PC110 digitizer pad support' CONFIG_PC110_PAD tristate 'PC110 digitizer pad support' CONFIG_PC110_PAD
fi fi
if [ "$CONFIG_MODULES" = "y" ]; then
bool 'Support for user misc device modules' CONFIG_UMISC
fi
tristate 'QIC-02 tape support' CONFIG_QIC02_TAPE tristate 'QIC-02 tape support' CONFIG_QIC02_TAPE
if [ "$CONFIG_QIC02_TAPE" != "n" ]; then if [ "$CONFIG_QIC02_TAPE" != "n" ]; then
bool 'Do you want runtime configuration for QIC-02' CONFIG_QIC02_DYNCONF bool 'Do you want runtime configuration for QIC-02' CONFIG_QIC02_DYNCONF
......
...@@ -21,7 +21,7 @@ FONTMAPFILE = cp437.uni ...@@ -21,7 +21,7 @@ FONTMAPFILE = cp437.uni
L_TARGET := char.a L_TARGET := char.a
M_OBJS := M_OBJS :=
L_OBJS := tty_io.o n_tty.o tty_ioctl.o mem.o random.o L_OBJS := tty_io.o n_tty.o tty_ioctl.o mem.o random.o
LX_OBJS := pty.o LX_OBJS := pty.o misc.o
ifdef CONFIG_VT ifdef CONFIG_VT
L_OBJS += vt.o vc_screen.o consolemap.o consolemap_deftbl.o L_OBJS += vt.o vc_screen.o consolemap.o consolemap_deftbl.o
...@@ -136,22 +136,18 @@ else ...@@ -136,22 +136,18 @@ else
endif endif
ifeq ($(CONFIG_ATIXL_BUSMOUSE),y) ifeq ($(CONFIG_ATIXL_BUSMOUSE),y)
M = y
L_OBJS += atixlmouse.o L_OBJS += atixlmouse.o
else else
ifeq ($(CONFIG_ATIXL_BUSMOUSE),m) ifeq ($(CONFIG_ATIXL_BUSMOUSE),m)
M_OBJS += atixlmouse.o M_OBJS += atixlmouse.o
MM = m
endif endif
endif endif
ifeq ($(CONFIG_BUSMOUSE),y) ifeq ($(CONFIG_BUSMOUSE),y)
M = y
L_OBJS += busmouse.o L_OBJS += busmouse.o
else else
ifeq ($(CONFIG_BUSMOUSE),m) ifeq ($(CONFIG_BUSMOUSE),m)
M_OBJS += busmouse.o M_OBJS += busmouse.o
MM = m
endif endif
endif endif
...@@ -172,135 +168,109 @@ else ...@@ -172,135 +168,109 @@ else
endif endif
ifeq ($(CONFIG_MS_BUSMOUSE),y) ifeq ($(CONFIG_MS_BUSMOUSE),y)
M = y
L_OBJS += msbusmouse.o L_OBJS += msbusmouse.o
else else
ifeq ($(CONFIG_MS_BUSMOUSE),m) ifeq ($(CONFIG_MS_BUSMOUSE),m)
M_OBJS += msbusmouse.o M_OBJS += msbusmouse.o
MM = m endif
endif
ifeq ($(CONFIG_82C710_MOUSE),y)
L_OBJS += qpmouse.o
else
ifeq ($(CONFIG_82C710_MOUSE),m)
M_OBJS += qpmouse.o
endif endif
endif endif
ifeq ($(CONFIG_PSMOUSE),y) ifeq ($(CONFIG_PSMOUSE),y)
M = y
L_OBJS += psaux.o L_OBJS += psaux.o
else else
ifeq ($(CONFIG_PSMOUSE),m) ifeq ($(CONFIG_PSMOUSE),m)
M_OBJS += psaux.o M_OBJS += psaux.o
MM = m
endif endif
endif endif
ifeq ($(CONFIG_UMISC),y)
# To support third-party modules, misc.c must reside in the kernel
M = y
endif
ifeq ($(CONFIG_SOFT_WATCHDOG),y) ifeq ($(CONFIG_SOFT_WATCHDOG),y)
M = y
L_OBJS += softdog.o L_OBJS += softdog.o
else else
ifeq ($(CONFIG_SOFT_WATCHDOG),m) ifeq ($(CONFIG_SOFT_WATCHDOG),m)
M_OBJS += softdog.o M_OBJS += softdog.o
MM = m
endif endif
endif endif
ifeq ($(CONFIG_PCWATCHDOG),y) ifeq ($(CONFIG_PCWATCHDOG),y)
M = y
L_OBJS += pcwd.o L_OBJS += pcwd.o
else else
ifeq ($(CONFIG_PCWATCHDOG),m) ifeq ($(CONFIG_PCWATCHDOG),m)
M_OBJS += pcwd.o M_OBJS += pcwd.o
MM = m
endif endif
endif endif
ifeq ($(CONFIG_ACQUIRE_WDT),y) ifeq ($(CONFIG_ACQUIRE_WDT),y)
M = y
L_OBJS += acquirewdt.o L_OBJS += acquirewdt.o
else else
ifeq ($(CONFIG_ACQUIRE_WDT),m) ifeq ($(CONFIG_ACQUIRE_WDT),m)
M_OBJS += acquirewdt.o M_OBJS += acquirewdt.o
MM = m
endif endif
endif endif
ifeq ($(CONFIG_AMIGAMOUSE),y) ifeq ($(CONFIG_AMIGAMOUSE),y)
M = y
L_OBJS += amigamouse.o L_OBJS += amigamouse.o
else else
ifeq ($(CONFIG_AMIGAMOUSE),m) ifeq ($(CONFIG_AMIGAMOUSE),m)
M_OBJS += amigamouse.o M_OBJS += amigamouse.o
MM = m
endif endif
endif endif
ifeq ($(CONFIG_ATARIMOUSE),y) ifeq ($(CONFIG_ATARIMOUSE),y)
M = y
L_OBJS += atarimouse.o L_OBJS += atarimouse.o
else else
ifeq ($(CONFIG_ATARIMOUSE),m) ifeq ($(CONFIG_ATARIMOUSE),m)
M_OBJS += atarimouse.o M_OBJS += atarimouse.o
MM = m
endif endif
endif endif
ifeq ($(CONFIG_MACMOUSE),y) ifeq ($(CONFIG_MACMOUSE),y)
M = y
L_OBJS += macmouse.o L_OBJS += macmouse.o
else else
ifeq ($(CONFIG_MACMOUSE),m) ifeq ($(CONFIG_MACMOUSE),m)
M_OBJS += macmouse.o M_OBJS += macmouse.o
MM = m
endif endif
endif endif
ifdef CONFIG_SUN_MOUSE
M = y
endif
ifeq ($(CONFIG_PC110_PAD),y) ifeq ($(CONFIG_PC110_PAD),y)
M = y
L_OBJS += pc110pad.o L_OBJS += pc110pad.o
else else
ifeq ($(CONFIG_PC110_PAD),m) ifeq ($(CONFIG_PC110_PAD),m)
M_OBJS += pc110pad.o M_OBJS += pc110pad.o
MM = m
endif endif
endif endif
ifeq ($(CONFIG_SUN_OPENPROMIO),y) ifeq ($(CONFIG_SUN_OPENPROMIO),y)
M = y
else else
ifeq ($(CONFIG_SUN_OPENPROMIO),m) ifeq ($(CONFIG_SUN_OPENPROMIO),m)
MM = m
endif endif
endif endif
ifeq ($(CONFIG_WDT),y) ifeq ($(CONFIG_WDT),y)
M = y
L_OBJS += wdt.o L_OBJS += wdt.o
else else
ifeq ($(CONFIG_WDT),m) ifeq ($(CONFIG_WDT),m)
M_OBJS += wdt.o M_OBJS += wdt.o
MM = m
endif endif
endif endif
ifeq ($(CONFIG_RTC),y) ifeq ($(CONFIG_RTC),y)
M = y
L_OBJS += rtc.o L_OBJS += rtc.o
endif endif
ifeq ($(CONFIG_NVRAM),y) ifeq ($(CONFIG_NVRAM),y)
M = y
ifeq ($(CONFIG_PMAC)$(CONFIG_CHRP),) ifeq ($(CONFIG_PMAC)$(CONFIG_CHRP),)
L_OBJS += nvram.o L_OBJS += nvram.o
endif endif
else else
ifeq ($(CONFIG_NVRAM),m) ifeq ($(CONFIG_NVRAM),m)
MM = m
ifeq ($(CONFIG_PMAC)$(CONFIG_CHRP),) ifeq ($(CONFIG_PMAC)$(CONFIG_CHRP),)
M_OBJS += nvram.o M_OBJS += nvram.o
endif endif
...@@ -437,19 +407,6 @@ endif ...@@ -437,19 +407,6 @@ endif
ifdef CONFIG_H8 ifdef CONFIG_H8
LX_OBJS += h8.o LX_OBJS += h8.o
M = y
endif
ifdef CONFIG_APM
M = y
endif
ifdef M
LX_OBJS += misc.o
else
ifdef MM
MX_OBJS += misc.o
endif
endif endif
ifeq ($(L_I2C),y) ifeq ($(L_I2C),y)
......
...@@ -549,15 +549,7 @@ __initfunc(int chr_dev_init(void)) ...@@ -549,15 +549,7 @@ __initfunc(int chr_dev_init(void))
#ifdef CONFIG_PRINTER #ifdef CONFIG_PRINTER
lp_init(); lp_init();
#endif #endif
#if defined (CONFIG_BUSMOUSE) || defined(CONFIG_UMISC) || \
defined (CONFIG_PSMOUSE) || defined (CONFIG_MS_BUSMOUSE) || \
defined (CONFIG_ATIXL_BUSMOUSE) || defined(CONFIG_SOFT_WATCHDOG) || \
defined (CONFIG_AMIGAMOUSE) || defined (CONFIG_ATARIMOUSE) || \
defined (CONFIG_MACMOUSE) || defined (CONFIG_PCWATCHDOG) || \
defined (CONFIG_APM) || defined (CONFIG_RTC) || \
defined (CONFIG_SUN_MOUSE) || defined (CONFIG_NVRAM)
misc_init(); misc_init();
#endif
#ifdef CONFIG_SOUND #ifdef CONFIG_SOUND
soundcore_init(); soundcore_init();
#ifdef CONFIG_SOUND_OSS #ifdef CONFIG_SOUND_OSS
......
...@@ -31,8 +31,8 @@ ...@@ -31,8 +31,8 @@
Cyrus Durgin <cider@speakeasy.org> Cyrus Durgin <cider@speakeasy.org>
*/ */
#include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/config.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/errno.h> #include <linux/errno.h>
...@@ -64,10 +64,10 @@ static struct miscdevice misc_list = { 0, "head", NULL, &misc_list, &misc_list } ...@@ -64,10 +64,10 @@ static struct miscdevice misc_list = { 0, "head", NULL, &misc_list, &misc_list }
#define DYNAMIC_MINORS 64 /* like dynamic majors */ #define DYNAMIC_MINORS 64 /* like dynamic majors */
static unsigned char misc_minors[DYNAMIC_MINORS / 8]; static unsigned char misc_minors[DYNAMIC_MINORS / 8];
#ifndef MODULE
extern int adbdev_init(void); extern int adbdev_init(void);
extern int bus_mouse_init(void); extern int bus_mouse_init(void);
extern int psaux_init(void); extern int psaux_init(void);
extern int qpmouse_init(void);
extern int ms_bus_mouse_init(void); extern int ms_bus_mouse_init(void);
extern int atixl_busmouse_init(void); extern int atixl_busmouse_init(void);
extern int amiga_mouse_init(void); extern int amiga_mouse_init(void);
...@@ -101,7 +101,6 @@ static int misc_read_proc(char *buf, char **start, off_t offset, ...@@ -101,7 +101,6 @@ static int misc_read_proc(char *buf, char **start, off_t offset,
} }
#endif /* PROC_FS */ #endif /* PROC_FS */
#endif /* !MODULE */
static int misc_open(struct inode * inode, struct file * file) static int misc_open(struct inode * inode, struct file * file)
{ {
...@@ -157,7 +156,6 @@ int misc_register(struct miscdevice * misc) ...@@ -157,7 +156,6 @@ int misc_register(struct miscdevice * misc)
} }
if (misc->minor < DYNAMIC_MINORS) if (misc->minor < DYNAMIC_MINORS)
misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7); misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7);
MOD_INC_USE_COUNT;
misc->next = &misc_list; misc->next = &misc_list;
misc->prev = misc_list.prev; misc->prev = misc_list.prev;
misc->prev->next = misc; misc->prev->next = misc;
...@@ -170,7 +168,6 @@ int misc_deregister(struct miscdevice * misc) ...@@ -170,7 +168,6 @@ int misc_deregister(struct miscdevice * misc)
int i = misc->minor; int i = misc->minor;
if (!misc->next || !misc->prev) if (!misc->next || !misc->prev)
return -EINVAL; return -EINVAL;
MOD_DEC_USE_COUNT;
misc->prev->next = misc->next; misc->prev->next = misc->next;
misc->next->prev = misc->prev; misc->next->prev = misc->prev;
misc->next = NULL; misc->next = NULL;
...@@ -181,27 +178,15 @@ int misc_deregister(struct miscdevice * misc) ...@@ -181,27 +178,15 @@ int misc_deregister(struct miscdevice * misc)
return 0; return 0;
} }
#ifdef MODULE
#define misc_init init_module
void cleanup_module(void)
{
unregister_chrdev(MISC_MAJOR, "misc");
}
#endif
EXPORT_SYMBOL(misc_register); EXPORT_SYMBOL(misc_register);
EXPORT_SYMBOL(misc_deregister); EXPORT_SYMBOL(misc_deregister);
#if defined(CONFIG_PROC_FS) && !defined(MODULE) #if defined(CONFIG_PROC_FS)
static struct proc_dir_entry *proc_misc; static struct proc_dir_entry *proc_misc;
#endif #endif
__initfunc(int misc_init(void)) int __init misc_init(void)
{ {
#ifndef MODULE
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
proc_misc = create_proc_entry("misc", 0, 0); proc_misc = create_proc_entry("misc", 0, 0);
if (proc_misc) if (proc_misc)
...@@ -213,6 +198,9 @@ __initfunc(int misc_init(void)) ...@@ -213,6 +198,9 @@ __initfunc(int misc_init(void))
#ifdef CONFIG_BUSMOUSE #ifdef CONFIG_BUSMOUSE
bus_mouse_init(); bus_mouse_init();
#endif #endif
#if defined CONFIG_82C710_MOUSE
qpmouse_init(); /* This must be before psaux_init */
#endif
#if defined CONFIG_PSMOUSE #if defined CONFIG_PSMOUSE
psaux_init(); psaux_init();
#endif #endif
...@@ -285,7 +273,6 @@ __initfunc(int misc_init(void)) ...@@ -285,7 +273,6 @@ __initfunc(int misc_init(void))
#ifdef CONFIG_PMAC_PBOOK #ifdef CONFIG_PMAC_PBOOK
pmu_device_init(); pmu_device_init();
#endif #endif
#endif /* !MODULE */
if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) { if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) {
printk("unable to get major %d for misc devices\n", printk("unable to get major %d for misc devices\n",
MISC_MAJOR); MISC_MAJOR);
......
...@@ -611,20 +611,18 @@ static char * __init initialize_kbd(void) ...@@ -611,20 +611,18 @@ static char * __init initialize_kbd(void)
void __init pckbd_init_hw(void) void __init pckbd_init_hw(void)
{ {
disable_irq(KEYBOARD_IRQ); /* Get the keyboard controller registers (incomplete decode) */
request_region(0x60, 16, "keyboard");
/* Flush any pending input. */ /* Flush any pending input. */
kbd_clear_input(); kbd_clear_input();
if (kbd_startup_reset) { if (kbd_startup_reset) {
char *msg = initialize_kbd(); char *msg = initialize_kbd();
if (msg) { if (msg)
printk(KERN_WARNING "initialize_kbd: %s\n", msg); printk(KERN_WARNING "initialize_kbd: %s\n", msg);
aux_device_present = 0;
return;
}
} }
/* Ok, finally allocate the IRQ, and off we go.. */
request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, "keyboard", NULL); request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, "keyboard", NULL);
request_region(0x60, 16, "keyboard");
} }
...@@ -12,14 +12,6 @@ ...@@ -12,14 +12,6 @@
* Changed to prevent keyboard lockups on AST Power Exec. * Changed to prevent keyboard lockups on AST Power Exec.
* 28Jul93 Brad Bosch - brad@lachman.com * 28Jul93 Brad Bosch - brad@lachman.com
* *
* Modified by Johan Myreen (jem@pandora.pp.fi) 04Aug93
* to include support for QuickPort mouse.
*
* Changed references to "QuickPort" with "82C710" since "QuickPort"
* is not what this driver is all about -- QuickPort is just a
* connector type, and this driver is for the mouse port on the Chips
* & Technologies 82C710 interface chip. 15Nov93 jem@pandora.pp.fi
*
* Added support for SIGIO. 28Jul95 jem@pandora.pp.fi * Added support for SIGIO. 28Jul95 jem@pandora.pp.fi
* *
* Rearranged SIGIO support to use code from tty_io. 9Sept95 ctm@ardi.com * Rearranged SIGIO support to use code from tty_io. 9Sept95 ctm@ardi.com
...@@ -35,6 +27,18 @@ ...@@ -35,6 +27,18 @@
* 13-Jan-1998, Richard Gooch <rgooch@atnf.csiro.au> * 13-Jan-1998, Richard Gooch <rgooch@atnf.csiro.au>
*/ */
/*
* This really should be part of the pc_kbd driver - they share the same
* controller, and right now we have ridiculous synchronization problems.
* Some of the SMP bootup problems may be due to not getting synchronization
* right.
*
* I moved the C&T mouse driver to a file of its own, hopefully that will
* make it easier to eventually fix this all.
*
* Linus
*/
/* Uncomment the following line if your mouse needs initialization. */ /* Uncomment the following line if your mouse needs initialization. */
/* #define INITIALIZE_DEVICE */ /* #define INITIALIZE_DEVICE */
...@@ -78,13 +82,7 @@ struct aux_queue { ...@@ -78,13 +82,7 @@ struct aux_queue {
}; };
static struct aux_queue *queue; static struct aux_queue *queue;
static int aux_ready = 0;
static int aux_count = 0; static int aux_count = 0;
static int aux_present = 0;
/*
* Shared subroutines
*/
static unsigned int get_from_queue(void) static unsigned int get_from_queue(void)
{ {
...@@ -234,7 +232,6 @@ static void aux_interrupt(int cpl, void *dev_id, struct pt_regs * regs) ...@@ -234,7 +232,6 @@ static void aux_interrupt(int cpl, void *dev_id, struct pt_regs * regs)
head &= AUX_BUF_SIZE-1; head &= AUX_BUF_SIZE-1;
} }
queue->head = head; queue->head = head;
aux_ready = 1;
if (queue->fasync) if (queue->fasync)
kill_fasync(queue->fasync, SIGIO); kill_fasync(queue->fasync, SIGIO);
wake_up_interruptible(&queue->proc_list); wake_up_interruptible(&queue->proc_list);
...@@ -270,8 +267,6 @@ static int release_aux(struct inode * inode, struct file * file) ...@@ -270,8 +267,6 @@ static int release_aux(struct inode * inode, struct file * file)
static int open_aux(struct inode * inode, struct file * file) static int open_aux(struct inode * inode, struct file * file)
{ {
if (!aux_present)
return -ENODEV;
aux_start_atomic(); aux_start_atomic();
if (aux_count++) { if (aux_count++) {
aux_end_atomic(); aux_end_atomic();
...@@ -304,7 +299,6 @@ static int open_aux(struct inode * inode, struct file * file) ...@@ -304,7 +299,6 @@ static int open_aux(struct inode * inode, struct file * file)
pckbd_read_mask = AUX_STAT_OBF; pckbd_read_mask = AUX_STAT_OBF;
#endif #endif
aux_ready = 0;
return 0; return 0;
} }
...@@ -343,196 +337,6 @@ static ssize_t write_aux(struct file * file, const char * buffer, ...@@ -343,196 +337,6 @@ static ssize_t write_aux(struct file * file, const char * buffer,
return retval; return retval;
} }
/*
* 82C710 Interface
*/
#ifdef CONFIG_82C710_MOUSE
#define QP_DATA 0x310 /* Data Port I/O Address */
#define QP_STATUS 0x311 /* Status Port I/O Address */
#define QP_DEV_IDLE 0x01 /* Device Idle */
#define QP_RX_FULL 0x02 /* Device Char received */
#define QP_TX_IDLE 0x04 /* Device XMIT Idle */
#define QP_RESET 0x08 /* Device Reset */
#define QP_INTS_ON 0x10 /* Device Interrupt On */
#define QP_ERROR_FLAG 0x20 /* Device Error */
#define QP_CLEAR 0x40 /* Device Clear */
#define QP_ENABLE 0x80 /* Device Enable */
#define QP_IRQ 12
static int qp_present = 0;
static int qp_count = 0;
static int qp_data = QP_DATA;
static int qp_status = QP_STATUS;
static int poll_qp_status(void);
static int probe_qp(void);
/*
* Interrupt handler for the 82C710 mouse port. A character
* is waiting in the 82C710.
*/
static void qp_interrupt(int cpl, void *dev_id, struct pt_regs * regs)
{
int head = queue->head;
int maxhead = (queue->tail-1) & (AUX_BUF_SIZE-1);
add_mouse_randomness(queue->buf[head] = inb(qp_data));
if (head != maxhead) {
head++;
head &= AUX_BUF_SIZE-1;
}
queue->head = head;
aux_ready = 1;
if (queue->fasync)
kill_fasync(queue->fasync, SIGIO);
wake_up_interruptible(&queue->proc_list);
}
static int release_qp(struct inode * inode, struct file * file)
{
unsigned char status;
fasync_aux(-1, file, 0);
if (!--qp_count) {
if (!poll_qp_status())
printk("Warning: Mouse device busy in release_qp()\n");
status = inb_p(qp_status);
outb_p(status & ~(QP_ENABLE|QP_INTS_ON), qp_status);
if (!poll_qp_status())
printk("Warning: Mouse device busy in release_qp()\n");
free_irq(QP_IRQ, NULL);
MOD_DEC_USE_COUNT;
}
return 0;
}
/*
* Install interrupt handler.
* Enable the device, enable interrupts.
*/
static int open_qp(struct inode * inode, struct file * file)
{
unsigned char status;
if (!qp_present)
return -EINVAL;
if (qp_count++)
return 0;
if (request_irq(QP_IRQ, qp_interrupt, 0, "PS/2 Mouse", NULL)) {
qp_count--;
return -EBUSY;
}
status = inb_p(qp_status);
status |= (QP_ENABLE|QP_RESET);
outb_p(status, qp_status);
status &= ~(QP_RESET);
outb_p(status, qp_status);
queue->head = queue->tail = 0; /* Flush input queue */
status |= QP_INTS_ON;
outb_p(status, qp_status); /* Enable interrupts */
while (!poll_qp_status()) {
printk("Error: Mouse device busy in open_qp()\n");
qp_count--;
status &= ~(QP_ENABLE|QP_INTS_ON);
outb_p(status, qp_status);
free_irq(QP_IRQ, NULL);
return -EBUSY;
}
outb_p(AUX_ENABLE_DEV, qp_data); /* Wake up mouse */
MOD_INC_USE_COUNT;
return 0;
}
/*
* Write to the 82C710 mouse device.
*/
static ssize_t write_qp(struct file * file, const char * buffer,
size_t count, loff_t *ppos)
{
ssize_t i = count;
while (i--) {
char c;
if (!poll_qp_status())
return -EIO;
get_user(c, buffer++);
outb_p(c, qp_data);
}
file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
return count;
}
/*
* Wait for device to send output char and flush any input char.
*/
static int poll_qp_status(void)
{
int retries=0;
while ((inb(qp_status)&(QP_RX_FULL|QP_TX_IDLE|QP_DEV_IDLE))
!= (QP_DEV_IDLE|QP_TX_IDLE)
&& retries < MAX_RETRIES) {
if (inb_p(qp_status)&(QP_RX_FULL))
inb_p(qp_data);
current->state = TASK_INTERRUPTIBLE;
current->timeout = jiffies + (5*HZ + 99) / 100;
schedule();
retries++;
}
return !(retries==MAX_RETRIES);
}
/*
* Function to read register in 82C710.
*/
static inline unsigned char read_710(unsigned char index)
{
outb_p(index, 0x390); /* Write index */
return inb_p(0x391); /* Read the data */
}
/*
* See if we can find a 82C710 device. Read mouse address.
*/
__initfunc(static int probe_qp(void))
{
outb_p(0x55, 0x2fa); /* Any value except 9, ff or 36 */
outb_p(0xaa, 0x3fa); /* Inverse of 55 */
outb_p(0x36, 0x3fa); /* Address the chip */
outb_p(0xe4, 0x3fa); /* 390/4; 390 = config address */
outb_p(0x1b, 0x2fa); /* Inverse of e4 */
if (read_710(0x0f) != 0xe4) /* Config address found? */
return 0; /* No: no 82C710 here */
qp_data = read_710(0x0d)*4; /* Get mouse I/O address */
qp_status = qp_data+1;
outb_p(0x0f, 0x390);
outb_p(0x0f, 0x391); /* Close config mode */
return 1;
}
#endif
/*
* Generic part continues...
*/
/* /*
* Put bytes from input queue to buffer. * Put bytes from input queue to buffer.
*/ */
...@@ -562,7 +366,6 @@ static ssize_t read_aux(struct file * file, char * buffer, ...@@ -562,7 +366,6 @@ static ssize_t read_aux(struct file * file, char * buffer,
put_user(c, buffer++); put_user(c, buffer++);
i--; i--;
} }
aux_ready = !queue_empty();
if (count-i) { if (count-i) {
file->f_dentry->d_inode->i_atime = CURRENT_TIME; file->f_dentry->d_inode->i_atime = CURRENT_TIME;
return count-i; return count-i;
...@@ -575,7 +378,7 @@ static ssize_t read_aux(struct file * file, char * buffer, ...@@ -575,7 +378,7 @@ static ssize_t read_aux(struct file * file, char * buffer,
static unsigned int aux_poll(struct file *file, poll_table * wait) static unsigned int aux_poll(struct file *file, poll_table * wait)
{ {
poll_wait(file, &queue->proc_list, wait); poll_wait(file, &queue->proc_list, wait);
if (aux_ready) if (!queue_empty())
return POLLIN | POLLRDNORM; return POLLIN | POLLRDNORM;
return 0; return 0;
} }
...@@ -596,8 +399,7 @@ struct file_operations psaux_fops = { ...@@ -596,8 +399,7 @@ struct file_operations psaux_fops = {
}; };
/* /*
* Initialize driver. First check for a 82C710 chip; if found * Initialize driver.
* forget about the Aux port and use the *_qp functions.
*/ */
static struct miscdevice psaux_mouse = { static struct miscdevice psaux_mouse = {
PSMOUSE_MINOR, "psaux", &psaux_fops PSMOUSE_MINOR, "psaux", &psaux_fops
...@@ -605,48 +407,33 @@ static struct miscdevice psaux_mouse = { ...@@ -605,48 +407,33 @@ static struct miscdevice psaux_mouse = {
__initfunc(int psaux_init(void)) __initfunc(int psaux_init(void))
{ {
int qp_found = 0; if (aux_device_present != 0xaa)
#ifdef CONFIG_82C710_MOUSE
if ((qp_found = probe_qp())) {
printk(KERN_INFO "82C710 type pointing device detected -- driver installed.\n");
/* printk("82C710 address = %x (should be 0x310)\n", qp_data); */
qp_present = 1;
psaux_fops.write = write_qp;
psaux_fops.open = open_qp;
psaux_fops.release = release_qp;
} else
#endif
if (aux_device_present == 0xaa) {
printk(KERN_INFO "PS/2 auxiliary pointing device detected -- driver installed.\n");
aux_present = 1;
} else {
return -EIO; return -EIO;
}
printk(KERN_INFO "PS/2 auxiliary pointing device detected -- driver installed.\n");
misc_register(&psaux_mouse); misc_register(&psaux_mouse);
queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL); queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
memset(queue, 0, sizeof(*queue)); memset(queue, 0, sizeof(*queue));
queue->head = queue->tail = 0; queue->head = queue->tail = 0;
queue->proc_list = NULL; queue->proc_list = NULL;
if (!qp_found) {
aux_start_atomic(); aux_start_atomic();
#ifdef INITIALIZE_DEVICE #ifdef INITIALIZE_DEVICE
outb_p(KBD_CCMD_MOUSE_ENABLE, KBD_CNTL_REG); /* Enable Aux */ outb_p(KBD_CCMD_MOUSE_ENABLE, KBD_CNTL_REG); /* Enable Aux */
aux_write_ack(AUX_SET_SAMPLE); aux_write_ack(AUX_SET_SAMPLE);
aux_write_ack(100); /* 100 samples/sec */ aux_write_ack(100); /* 100 samples/sec */
aux_write_ack(AUX_SET_RES); aux_write_ack(AUX_SET_RES);
aux_write_ack(3); /* 8 counts per mm */ aux_write_ack(3); /* 8 counts per mm */
aux_write_ack(AUX_SET_SCALE21); /* 2:1 scaling */ aux_write_ack(AUX_SET_SCALE21); /* 2:1 scaling */
poll_aux_status(); poll_aux_status();
#endif /* INITIALIZE_DEVICE */ #endif /* INITIALIZE_DEVICE */
outb_p(KBD_CCMD_MOUSE_DISABLE, KBD_CNTL_REG); /* Disable Aux device */ outb_p(KBD_CCMD_MOUSE_DISABLE, KBD_CNTL_REG); /* Disable Aux device */
poll_aux_status(); poll_aux_status();
outb_p(KBD_CCMD_WRITE_MODE, KBD_CNTL_REG); /* Disable controller interrupts */ outb_p(KBD_CCMD_WRITE_MODE, KBD_CNTL_REG); /* Disable controller interrupts */
poll_aux_status(); poll_aux_status();
outb_p(AUX_INTS_OFF, KBD_DATA_REG); outb_p(AUX_INTS_OFF, KBD_DATA_REG);
poll_aux_status(); poll_aux_status();
aux_end_atomic(); aux_end_atomic();
}
return 0; return 0;
} }
......
/*
* linux/drivers/char/qpmouse.c
*
* Driver for a 82C710 C&T mouse interface chip.
*
* Based on the PS/2 driver by Johan Myreen.
*
* Corrections in device setup for some laptop mice & trackballs.
* 02Feb93 (troyer@saifr00.cfsat.Honeywell.COM,mch@wimsey.bc.ca)
*
* Modified by Johan Myreen (jem@pandora.pp.fi) 04Aug93
* to include support for QuickPort mouse.
*
* Changed references to "QuickPort" with "82C710" since "QuickPort"
* is not what this driver is all about -- QuickPort is just a
* connector type, and this driver is for the mouse port on the Chips
* & Technologies 82C710 interface chip. 15Nov93 jem@pandora.pp.fi
*
* Added support for SIGIO. 28Jul95 jem@pandora.pp.fi
*
* Rearranged SIGIO support to use code from tty_io. 9Sept95 ctm@ardi.com
*
* Modularised 8-Sep-95 Philip Blundell <pjb27@cam.ac.uk>
*/
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/fcntl.h>
#include <linux/errno.h>
#include <linux/timer.h>
#include <linux/malloc.h>
#include <linux/miscdevice.h>
#include <linux/random.h>
#include <linux/poll.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/semaphore.h>
#include "pc_keyb.h" /* mouse enable command.. */
/*
* We use the same minor number as the PS/2 mouse for (bad) historical
* reasons..
*/
#define PSMOUSE_MINOR 1 /* Minor device # for this mouse */
#define QP_BUF_SIZE 2048
struct qp_queue {
unsigned long head;
unsigned long tail;
struct wait_queue *proc_list;
struct fasync_struct *fasync;
unsigned char buf[QP_BUF_SIZE];
};
static struct qp_queue *queue;
static unsigned int get_from_queue(void)
{
unsigned int result;
unsigned long flags;
save_flags(flags);
cli();
result = queue->buf[queue->tail];
queue->tail = (queue->tail + 1) & (QP_BUF_SIZE-1);
restore_flags(flags);
return result;
}
static inline int queue_empty(void)
{
return queue->head == queue->tail;
}
static int fasync_qp(int fd, struct file *filp, int on)
{
int retval;
retval = fasync_helper(fd, filp, on, &queue->fasync);
if (retval < 0)
return retval;
return 0;
}
/*
* 82C710 Interface
*/
#define QP_DATA 0x310 /* Data Port I/O Address */
#define QP_STATUS 0x311 /* Status Port I/O Address */
#define QP_DEV_IDLE 0x01 /* Device Idle */
#define QP_RX_FULL 0x02 /* Device Char received */
#define QP_TX_IDLE 0x04 /* Device XMIT Idle */
#define QP_RESET 0x08 /* Device Reset */
#define QP_INTS_ON 0x10 /* Device Interrupt On */
#define QP_ERROR_FLAG 0x20 /* Device Error */
#define QP_CLEAR 0x40 /* Device Clear */
#define QP_ENABLE 0x80 /* Device Enable */
#define QP_IRQ 12
static int qp_present = 0;
static int qp_count = 0;
static int qp_data = QP_DATA;
static int qp_status = QP_STATUS;
static int poll_qp_status(void);
static int probe_qp(void);
/*
* Interrupt handler for the 82C710 mouse port. A character
* is waiting in the 82C710.
*/
static void qp_interrupt(int cpl, void *dev_id, struct pt_regs * regs)
{
int head = queue->head;
int maxhead = (queue->tail-1) & (QP_BUF_SIZE-1);
add_mouse_randomness(queue->buf[head] = inb(qp_data));
if (head != maxhead) {
head++;
head &= QP_BUF_SIZE-1;
}
queue->head = head;
if (queue->fasync)
kill_fasync(queue->fasync, SIGIO);
wake_up_interruptible(&queue->proc_list);
}
static int release_qp(struct inode * inode, struct file * file)
{
unsigned char status;
fasync_qp(-1, file, 0);
if (!--qp_count) {
if (!poll_qp_status())
printk("Warning: Mouse device busy in release_qp()\n");
status = inb_p(qp_status);
outb_p(status & ~(QP_ENABLE|QP_INTS_ON), qp_status);
if (!poll_qp_status())
printk("Warning: Mouse device busy in release_qp()\n");
free_irq(QP_IRQ, NULL);
MOD_DEC_USE_COUNT;
}
return 0;
}
/*
* Install interrupt handler.
* Enable the device, enable interrupts.
*/
static int open_qp(struct inode * inode, struct file * file)
{
unsigned char status;
if (!qp_present)
return -EINVAL;
if (qp_count++)
return 0;
if (request_irq(QP_IRQ, qp_interrupt, 0, "PS/2 Mouse", NULL)) {
qp_count--;
return -EBUSY;
}
status = inb_p(qp_status);
status |= (QP_ENABLE|QP_RESET);
outb_p(status, qp_status);
status &= ~(QP_RESET);
outb_p(status, qp_status);
queue->head = queue->tail = 0; /* Flush input queue */
status |= QP_INTS_ON;
outb_p(status, qp_status); /* Enable interrupts */
while (!poll_qp_status()) {
printk("Error: Mouse device busy in open_qp()\n");
qp_count--;
status &= ~(QP_ENABLE|QP_INTS_ON);
outb_p(status, qp_status);
free_irq(QP_IRQ, NULL);
return -EBUSY;
}
outb_p(AUX_ENABLE_DEV, qp_data); /* Wake up mouse */
MOD_INC_USE_COUNT;
return 0;
}
/*
* Write to the 82C710 mouse device.
*/
static ssize_t write_qp(struct file * file, const char * buffer,
size_t count, loff_t *ppos)
{
ssize_t i = count;
while (i--) {
char c;
if (!poll_qp_status())
return -EIO;
get_user(c, buffer++);
outb_p(c, qp_data);
}
file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
return count;
}
static unsigned int poll_qp(struct file *file, poll_table * wait)
{
poll_wait(file, &queue->proc_list, wait);
if (!queue_empty())
return POLLIN | POLLRDNORM;
return 0;
}
/*
* Wait for device to send output char and flush any input char.
*/
#define MAX_RETRIES (60)
static int poll_qp_status(void)
{
int retries=0;
while ((inb(qp_status)&(QP_RX_FULL|QP_TX_IDLE|QP_DEV_IDLE))
!= (QP_DEV_IDLE|QP_TX_IDLE)
&& retries < MAX_RETRIES) {
if (inb_p(qp_status)&(QP_RX_FULL))
inb_p(qp_data);
current->state = TASK_INTERRUPTIBLE;
current->timeout = jiffies + (5*HZ + 99) / 100;
schedule();
retries++;
}
return !(retries==MAX_RETRIES);
}
/*
* Put bytes from input queue to buffer.
*/
static ssize_t read_qp(struct file * file, char * buffer,
size_t count, loff_t *ppos)
{
struct wait_queue wait = { current, NULL };
ssize_t i = count;
unsigned char c;
if (queue_empty()) {
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
add_wait_queue(&queue->proc_list, &wait);
repeat:
current->state = TASK_INTERRUPTIBLE;
if (queue_empty() && !signal_pending(current)) {
schedule();
goto repeat;
}
current->state = TASK_RUNNING;
remove_wait_queue(&queue->proc_list, &wait);
}
while (i > 0 && !queue_empty()) {
c = get_from_queue();
put_user(c, buffer++);
i--;
}
if (count-i) {
file->f_dentry->d_inode->i_atime = CURRENT_TIME;
return count-i;
}
if (signal_pending(current))
return -ERESTARTSYS;
return 0;
}
struct file_operations qp_fops = {
NULL, /* seek */
read_qp,
write_qp,
NULL, /* readdir */
poll_qp,
NULL, /* ioctl */
NULL, /* mmap */
open_qp,
NULL, /* flush */
release_qp,
NULL,
fasync_qp,
};
/*
* Initialize driver.
*/
static struct miscdevice qp_mouse = {
PSMOUSE_MINOR, "QPmouse", &qp_fops
};
/*
* Function to read register in 82C710.
*/
static inline unsigned char read_710(unsigned char index)
{
outb_p(index, 0x390); /* Write index */
return inb_p(0x391); /* Read the data */
}
/*
* See if we can find a 82C710 device. Read mouse address.
*/
static int __init probe_qp(void)
{
outb_p(0x55, 0x2fa); /* Any value except 9, ff or 36 */
outb_p(0xaa, 0x3fa); /* Inverse of 55 */
outb_p(0x36, 0x3fa); /* Address the chip */
outb_p(0xe4, 0x3fa); /* 390/4; 390 = config address */
outb_p(0x1b, 0x2fa); /* Inverse of e4 */
if (read_710(0x0f) != 0xe4) /* Config address found? */
return 0; /* No: no 82C710 here */
qp_data = read_710(0x0d)*4; /* Get mouse I/O address */
qp_status = qp_data+1;
outb_p(0x0f, 0x390);
outb_p(0x0f, 0x391); /* Close config mode */
return 1;
}
int __init qpmouse_init(void)
{
if (!probe_qp())
return -EIO;
printk(KERN_INFO "82C710 type pointing device detected -- driver installed.\n");
/* printk("82C710 address = %x (should be 0x310)\n", qp_data); */
qp_present = 1;
misc_register(&qp_mouse);
queue = (struct qp_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
memset(queue, 0, sizeof(*queue));
queue->head = queue->tail = 0;
queue->proc_list = NULL;
return 0;
}
#ifdef MODULE
int init_module(void)
{
return qpmouse_init();
}
void cleanup_module(void)
{
misc_deregister(&qp_mouse);
kfree(queue);
}
#endif
...@@ -890,6 +890,9 @@ scsi_tape_flush(struct file * filp) ...@@ -890,6 +890,9 @@ scsi_tape_flush(struct file * filp)
kdev_t devt = inode->i_rdev; kdev_t devt = inode->i_rdev;
int dev; int dev;
if (filp->f_count > 1)
return 0;
dev = TAPE_NR(devt); dev = TAPE_NR(devt);
STp = &(scsi_tapes[dev]); STp = &(scsi_tapes[dev]);
STm = &(STp->modes[STp->current_mode]); STm = &(STp->modes[STp->current_mode]);
......
...@@ -806,8 +806,13 @@ new_dentry->d_count); ...@@ -806,8 +806,13 @@ new_dentry->d_count);
if (S_ISDIR(old_inode->i_mode)) { if (S_ISDIR(old_inode->i_mode)) {
error = fat_scan(old_inode, MSDOS_DOTDOT, &dotdot_bh, error = fat_scan(old_inode, MSDOS_DOTDOT, &dotdot_bh,
&dotdot_de, &dotdot_ino, SCAN_ANY); &dotdot_de, &dotdot_ino, SCAN_ANY);
if (error < 0) if (error < 0) {
printk(KERN_WARNING
"MSDOS: %s/%s, get dotdot failed, ret=%d\n",
old_dentry->d_parent->d_name.name,
old_dentry->d_name.name, error);
goto rename_done; goto rename_done;
}
error = -EIO; error = -EIO;
dotdot_inode = iget(sb, dotdot_ino); dotdot_inode = iget(sb, dotdot_ino);
if (!dotdot_inode) if (!dotdot_inode)
...@@ -832,7 +837,6 @@ new_dentry->d_count); ...@@ -832,7 +837,6 @@ new_dentry->d_count);
if (!list_empty(&free_inode->i_dentry)) if (!list_empty(&free_inode->i_dentry))
printk("msdos_rename_diff: free inode has aliases??\n"); printk("msdos_rename_diff: free inode has aliases??\n");
msdos_read_inode(free_inode); msdos_read_inode(free_inode);
fat_mark_buffer_dirty(sb, free_bh, 1);
/* /*
* Make sure the old dentry isn't busy, * Make sure the old dentry isn't busy,
...@@ -854,6 +858,7 @@ old_dentry->d_count); ...@@ -854,6 +858,7 @@ old_dentry->d_count);
d_delete(old_dentry); d_delete(old_dentry);
free_inode->i_mode = old_inode->i_mode; free_inode->i_mode = old_inode->i_mode;
free_inode->i_nlink = old_inode->i_nlink;
free_inode->i_size = old_inode->i_size; free_inode->i_size = old_inode->i_size;
free_inode->i_blocks = old_inode->i_blocks; free_inode->i_blocks = old_inode->i_blocks;
free_inode->i_mtime = old_inode->i_mtime; free_inode->i_mtime = old_inode->i_mtime;
...@@ -875,6 +880,7 @@ old_dentry->d_count); ...@@ -875,6 +880,7 @@ old_dentry->d_count);
*/ */
d_instantiate(old_dentry, free_inode); d_instantiate(old_dentry, free_inode);
fat_mark_buffer_dirty(sb, free_bh, 1);
fat_cache_inval_inode(old_inode); fat_cache_inval_inode(old_inode);
mark_inode_dirty(old_inode); mark_inode_dirty(old_inode);
old_de->name[0] = DELETED_FLAG; old_de->name[0] = DELETED_FLAG;
......
...@@ -89,6 +89,7 @@ extern int swap_duplicate(unsigned long); ...@@ -89,6 +89,7 @@ extern int swap_duplicate(unsigned long);
extern int swap_check_entry(unsigned long); extern int swap_check_entry(unsigned long);
extern struct page * read_swap_cache_async(unsigned long, int); extern struct page * read_swap_cache_async(unsigned long, int);
#define read_swap_cache(entry) read_swap_cache_async(entry, 1); #define read_swap_cache(entry) read_swap_cache_async(entry, 1);
extern int FASTCALL(swap_count(unsigned long));
/* /*
* Make these inline later once they are working properly. * Make these inline later once they are working properly.
*/ */
...@@ -146,14 +147,20 @@ extern inline unsigned long in_swap_cache(struct page *page) ...@@ -146,14 +147,20 @@ extern inline unsigned long in_swap_cache(struct page *page)
*/ */
static inline int is_page_shared(struct page *page) static inline int is_page_shared(struct page *page)
{ {
int count = atomic_read(&page->count); unsigned int count;
if (PageReserved(page)) if (PageReserved(page))
return 1; return 1;
if (page->inode == &swapper_inode) count = atomic_read(&page->count);
count--; if (PageSwapCache(page))
{
/* PARANOID */
if (page->inode != &swapper_inode)
panic("swap cache page has wrong inode\n");
count += swap_count(page->offset) - 2;
}
if (PageFreeAfter(page)) if (PageFreeAfter(page))
count--; count--;
return (count > 1); return count > 1;
} }
#endif /* __KERNEL__*/ #endif /* __KERNEL__*/
......
...@@ -163,9 +163,11 @@ void __free_page(struct page *page) ...@@ -163,9 +163,11 @@ void __free_page(struct page *page)
free_pages_ok(page->map_nr, 0); free_pages_ok(page->map_nr, 0);
return; return;
} }
#if 0
if (PageSwapCache(page) && atomic_read(&page->count) == 1) if (PageSwapCache(page) && atomic_read(&page->count) == 1)
printk(KERN_WARNING "VM: Releasing swap cache page at %p", printk(KERN_WARNING "VM: Releasing swap cache page at %p",
__builtin_return_address(0)); __builtin_return_address(0));
#endif
} }
void free_pages(unsigned long addr, unsigned long order) void free_pages(unsigned long addr, unsigned long order)
...@@ -182,10 +184,12 @@ void free_pages(unsigned long addr, unsigned long order) ...@@ -182,10 +184,12 @@ void free_pages(unsigned long addr, unsigned long order)
free_pages_ok(map_nr, order); free_pages_ok(map_nr, order);
return; return;
} }
#if 0
if (PageSwapCache(map) && atomic_read(&map->count) == 1) if (PageSwapCache(map) && atomic_read(&map->count) == 1)
printk(KERN_WARNING printk(KERN_WARNING
"VM: Releasing swap cache pages at %p", "VM: Releasing swap cache pages at %p",
__builtin_return_address(0)); __builtin_return_address(0));
#endif
} }
} }
......
...@@ -143,6 +143,50 @@ int swap_duplicate(unsigned long entry) ...@@ -143,6 +143,50 @@ int swap_duplicate(unsigned long entry)
goto out; goto out;
} }
int swap_count(unsigned long entry)
{
struct swap_info_struct * p;
unsigned long offset, type;
int retval = 0;
if (!entry)
goto bad_entry;
type = SWP_TYPE(entry);
if (type & SHM_SWP_TYPE)
goto out;
if (type >= nr_swapfiles)
goto bad_file;
p = type + swap_info;
offset = SWP_OFFSET(entry);
if (offset >= p->max)
goto bad_offset;
if (!p->swap_map[offset])
goto bad_unused;
retval = p->swap_map[offset];
#ifdef DEBUG_SWAP
printk("DebugVM: swap_count(entry %08lx, count %d)\n",
entry, retval);
#endif
out:
return retval;
bad_entry:
printk(KERN_ERR "swap_count: null entry!\n");
goto out;
bad_file:
printk(KERN_ERR
"swap_count: entry %08lx, nonexistent swap file!\n", entry);
goto out;
bad_offset:
printk(KERN_ERR
"swap_count: entry %08lx, offset exceeds max!\n", entry);
goto out;
bad_unused:
printk(KERN_ERR
"swap_count at %8p: entry %08lx, unused page!\n",
__builtin_return_address(0), entry);
goto out;
}
static inline void remove_from_swap_cache(struct page *page) static inline void remove_from_swap_cache(struct page *page)
{ {
...@@ -155,6 +199,7 @@ static inline void remove_from_swap_cache(struct page *page) ...@@ -155,6 +199,7 @@ static inline void remove_from_swap_cache(struct page *page)
printk ("VM: Removing swap cache page with wrong inode hash " printk ("VM: Removing swap cache page with wrong inode hash "
"on page %08lx\n", page_address(page)); "on page %08lx\n", page_address(page));
} }
#if 0
/* /*
* This is a legal case, but warn about it. * This is a legal case, but warn about it.
*/ */
...@@ -163,6 +208,7 @@ static inline void remove_from_swap_cache(struct page *page) ...@@ -163,6 +208,7 @@ static inline void remove_from_swap_cache(struct page *page)
"VM: Removing page cache on unshared page %08lx\n", "VM: Removing page cache on unshared page %08lx\n",
page_address(page)); page_address(page));
} }
#endif
#ifdef DEBUG_SWAP #ifdef DEBUG_SWAP
printk("DebugVM: remove_from_swap_cache(%08lx count %d)\n", printk("DebugVM: remove_from_swap_cache(%08lx count %d)\n",
......
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