Commit 09f1c96e authored by Linus Torvalds's avatar Linus Torvalds

Import 2.4.0-test4pre5

parent 79e75677
......@@ -386,7 +386,7 @@
announces it. The <function>parport_announce_port</function>
function walks down the list of parallel port device drivers
(<structname>struct parport_driver</structname>s) calling the
<function>attach</function> function of each.
<function>attach</function> function of each (which may block).
</para>
<para>
......@@ -394,7 +394,7 @@
registering a port with the
<function>parport_unregister_port</function> function, and device
drivers are notified using the <function>detach</function>
callback.
callback (which may not block).
</para>
<para>
......@@ -656,9 +656,31 @@ struct parport_driver {
to the <function>attach</function> function when it is called, or
alternatively can be found from the list of detected parallel ports
directly with the (now deprecated)
<function>parport_enumerate</function> function.
<function>parport_enumerate</function> function. A better way of
doing this is with <function>parport_find_number</function> or
<function>parport_find_base</function> functions, which find ports
by number and by base I/O address respectively.
</para>
<funcsynopsis>
<funcsynopsisinfo>
#include &lt;parport.h&gt;
</funcsynopsisinfo>
<funcprototype>
<funcdef>struct parport *<function>parport_find_number</function></funcdef>
<paramdef>int <parameter>number</parameter></paramdef>
</funcprototype>
</funcsynopsis>
<funcsynopsis>
<funcsynopsisinfo>
#include &lt;parport.h&gt;
</funcsynopsisinfo>
<funcprototype>
<funcdef>struct parport *<function>parport_find_base</function></funcdef>
<paramdef>unsigned long <parameter>base</parameter></paramdef>
</funcprototype>
</funcsynopsis>
<para>
The next three parameters, <parameter>pf</parameter>,
<parameter>kf</parameter>, and <parameter>irq_func</parameter>, are
......@@ -2202,6 +2224,9 @@ ssize_t write_printer (int fd, const void *ptr, size_t count)
!Fdrivers/parport/daisy.c parport_find_class
!Fdrivers/parport/share.c parport_register_driver
!Fdrivers/parport/share.c parport_unregister_driver
!Fdrivers/parport/share.c parport_get_port
!Fdrivers/parport/share.c parport_put_port
!Fdrivers/parport/share.c parport_find_number parport_find_base
!Fdrivers/parport/share.c parport_register_device
!Fdrivers/parport/share.c parport_unregister_device
!Fdrivers/parport/daisy.c parport_open
......
June 2000 Kernel Parameters v2.4.0
July 2000 Kernel Parameters v2.4.0
~~~~~~~~~~~~~~~~~
The following is a consolidated list of the kernel parameters as implemented
......@@ -80,6 +80,8 @@ running once the system is up.
AM53C974= [HW,SCSI]
amijoy= [HW,JOY] Amiga joystick support
apm= [APM] Advanced Power Management.
applicom= [HW]
......@@ -139,6 +141,12 @@ running once the system is up.
dasd= [HW,NET]
db9= [HW,JOY]
db9_2= [HW,JOY]
db9_3= [HW,JOY]
debug [KNL] Enable kernel debugging (events log level).
decnet= [HW,NET]
......@@ -179,6 +187,12 @@ running once the system is up.
ftape= [HW] Floppy Tape subsystem debugging options.
gc= [HW,JOY]
gc_2= [HW,JOY]
gc_3= [HW,JOY]
gdth= [HW,SCSI]
gscd= [HW,CD]
......@@ -194,10 +208,6 @@ running once the system is up.
hisax= [HW,ISDN]
in2000= [HW,SCSI]
init= [KNL]
ibmmcascsi= [HW,MCA,SCSI] IBM MicroChannel SCSI adapter.
icn= [HW,ISDN]
......@@ -208,40 +218,20 @@ running once the system is up.
idebus= [HW] (E)IDE subsystem : VLB/PCI bus speed.
idle= [HW]
in2000= [HW,SCSI]
init= [KNL]
ip= [PNP]
isp16= [HW,CD]
iucv= [HW,NET]
js_am= [HW,JOY]
js_an= [HW,JOY]
js_as= [HW.JOY]
js_console= [HW,JOY]
js_console2= [HW,JOY]
js_console3= [HW,JOY]
js_db9= [HW,JOY]
js_db9_2= [HW,JOY]
js_db9_3= [HW,JOY]
js_l4= [HW,JOY]
js_pci= [HW,JOY,PCI]
js= [HW,JOY] Analog joystick
js_tg= [HW,JOY]
js_tg_2= [HW,JOY]
js_tg_3= [HW,JOY]
kbd-reset [VT]
load_ramdisk= [RAM] List of ramdisks to load from floppy.
......@@ -354,6 +344,8 @@ running once the system is up.
nosync [HW, M68K] Disables sync negotiation for all devices.
notsc [BUGS=ix86] Disable Time Stamp Counter
nowb [ARM]
opl3= [HW,SOUND]
......@@ -484,6 +476,12 @@ running once the system is up.
tdfx= [HW,DRM]
tgfx= [HW,JOY]
tgfx_2= [HW,JOY]
tgfx_3= [HW,JOY]
tmc8xx= [HW,SCSI]
tmscsim= [HW,SCSI]
......
......@@ -15,6 +15,14 @@ bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
bool 'Prompt for obsolete code/drivers' CONFIG_OBSOLETE
endmenu
mainmenu_option next_comment
comment 'Loadable module support'
bool 'Enable loadable module support' CONFIG_MODULES
if [ "$CONFIG_MODULES" = "y" ]; then
bool ' Set version information on all module symbols' CONFIG_MODVERSIONS
bool ' Kernel module loader' CONFIG_KMOD
fi
endmenu
mainmenu_option next_comment
comment 'System Type'
......@@ -157,17 +165,6 @@ else
fi
endmenu
mainmenu_option next_comment
comment 'Loadable module support'
bool 'Enable loadable module support' CONFIG_MODULES
if [ "$CONFIG_MODULES" = "y" ]; then
bool ' Set version information on all symbols for modules' CONFIG_MODVERSIONS
bool ' Kernel module loader' CONFIG_KMOD
fi
endmenu
mainmenu_option next_comment
comment 'General setup'
source drivers/pci/Config.in
......
......@@ -15,6 +15,15 @@ comment 'Code maturity level options'
bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
endmenu
mainmenu_option next_comment
comment 'Loadable module support'
bool 'Enable loadable module support' CONFIG_MODULES
if [ "$CONFIG_MODULES" = "y" ]; then
bool ' Set version information on all module symbols' CONFIG_MODVERSIONS
bool ' Kernel module loader' CONFIG_KMOD
fi
endmenu
mainmenu_option next_comment
comment 'Processor type and features'
choice 'Processor family' \
......@@ -145,15 +154,6 @@ if [ "$CONFIG_SMP" = "y" -a "$CONFIG_X86_CMPXCHG" = "y" ]; then
fi
endmenu
mainmenu_option next_comment
comment 'Loadable module support'
bool 'Enable loadable module support' CONFIG_MODULES
if [ "$CONFIG_MODULES" = "y" ]; then
bool ' Set version information on all module symbols' CONFIG_MODVERSIONS
bool ' Kernel module loader' CONFIG_KMOD
fi
endmenu
mainmenu_option next_comment
comment 'General setup'
......
......@@ -392,6 +392,8 @@ void smp_send_reschedule(int cpu)
* Structure and data for smp_call_function(). This is designed to minimise
* static memory requirements. It also looks cleaner.
*/
static spinlock_t call_lock = SPIN_LOCK_UNLOCKED;
static volatile struct call_data_struct {
void (*func) (void *info);
void *info;
......@@ -422,9 +424,8 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
{
struct call_data_struct data;
int ret, cpus = smp_num_cpus-1;
static spinlock_t lock = SPIN_LOCK_UNLOCKED;
if(cpus == 0)
if (!cpus)
return 0;
data.func = func;
......@@ -434,21 +435,21 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
if (wait)
atomic_set(&data.finished, 0);
spin_lock_bh(&lock);
spin_lock_bh(&call_lock);
call_data = &data;
/* Send a message to all other CPUs and wait for them to respond */
send_IPI_allbutself(CALL_FUNCTION_VECTOR);
/* Wait for response */
/* FIXME: lock-up detection, backtrace on lock-up */
while(atomic_read(&data.started) != cpus)
while (atomic_read(&data.started) != cpus)
barrier();
ret = 0;
if (wait)
while (atomic_read(&data.finished) != cpus)
barrier();
spin_unlock_bh(&lock);
spin_unlock_bh(&call_lock);
return 0;
}
......
......@@ -3,6 +3,20 @@
#
mainmenu_name "Kernel configuration of Linux for IA-64 machines"
mainmenu_option next_comment
comment 'Code maturity level options'
bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
endmenu
mainmenu_option next_comment
comment 'Loadable module support'
bool 'Enable loadable module support' CONFIG_MODULES
if [ "$CONFIG_MODULES" = "y" ]; then
bool ' Set version information on all module symbols' CONFIG_MODVERSIONS
bool ' Kernel module loader' CONFIG_KMOD
fi
endmenu
mainmenu_option next_comment
comment 'General setup'
......@@ -67,20 +81,6 @@ else
define_bool CONFIG_PCMCIA n
fi
mainmenu_option next_comment
comment 'Code maturity level options'
bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
endmenu
mainmenu_option next_comment
comment 'Loadable module support'
bool 'Enable loadable module support' CONFIG_MODULES
if [ "$CONFIG_MODULES" = "y" ]; then
bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
bool 'Kernel module loader' CONFIG_KMOD
fi
endmenu
source drivers/parport/Config.in
endmenu
......
......@@ -12,6 +12,15 @@ comment 'Code maturity level options'
bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
endmenu
mainmenu_option next_comment
comment 'Loadable module support'
bool 'Enable loadable module support' CONFIG_MODULES
if [ "$CONFIG_MODULES" = "y" ]; then
bool ' Set version information on all module symbols' CONFIG_MODVERSIONS
bool ' Kernel module loader' CONFIG_KMOD
fi
endmenu
mainmenu_option next_comment
comment 'Platform dependent setup'
......@@ -136,15 +145,6 @@ fi
endmenu
mainmenu_option next_comment
comment 'Loadable module support'
bool 'Enable loadable module support' CONFIG_MODULES
if [ "$CONFIG_MODULES" = "y" ]; then
bool ' Set version information on all symbols for modules' CONFIG_MODVERSIONS
bool ' Kernel module loader' CONFIG_KMOD
fi
endmenu
source drivers/mtd/Config.in
source drivers/block/Config.in
......
/*
* Reset a Cobalt Qube.
*/
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <asm/io.h>
......
......@@ -9,6 +9,15 @@ comment 'Code maturity level options'
bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
endmenu
mainmenu_option next_comment
comment 'Loadable module support'
bool 'Enable loadable module support' CONFIG_MODULES
if [ "$CONFIG_MODULES" = "y" ]; then
bool ' Set version information on all module symbols' CONFIG_MODVERSIONS
bool ' Kernel module loader' CONFIG_KMOD
fi
endmenu
mainmenu_option next_comment
comment 'Machine selection'
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
......@@ -159,12 +168,6 @@ comment 'General setup'
source drivers/parport/Config.in
bool 'Enable loadable module support' CONFIG_MODULES
if [ "$CONFIG_MODULES" = "y" ]; then
bool ' Set version information on all symbols for modules' CONFIG_MODVERSIONS
bool ' Kernel module loader' CONFIG_KMOD
fi
if [ "$CONFIG_DECSTATION" = "y" ]; then
bool 'TURBOchannel support' CONFIG_TC
# if [ "$CONFIG_TC" = "y" ]; then
......
This diff is collapsed.
......@@ -49,6 +49,7 @@ EXPORT_SYMBOL_NOVERS(memcmp);
EXPORT_SYMBOL_NOVERS(memset);
EXPORT_SYMBOL_NOVERS(memcpy);
EXPORT_SYMBOL_NOVERS(memmove);
EXPORT_SYMBOL(simple_strtol);
EXPORT_SYMBOL_NOVERS(strcat);
EXPORT_SYMBOL_NOVERS(strchr);
EXPORT_SYMBOL_NOVERS(strlen);
......
......@@ -91,6 +91,15 @@ SECTIONS
_end = . ;
PROVIDE (end = .);
}
/* Sections to be discarded */
/DISCARD/ :
{
*(.text.exit)
*(.data.exit)
*(.exitcall.exit)
}
/* These are needed for ELF backends which have not yet been
converted to the new style linker. */
.stab 0 : { *(.stab) }
......
......@@ -91,6 +91,15 @@ SECTIONS
_end = . ;
PROVIDE (end = .);
}
/* Sections to be discarded */
/DISCARD/ :
{
*(.text.exit)
*(.data.exit)
*(.exitcall.exit)
}
/* These are needed for ELF backends which have not yet been
converted to the new style linker. */
.stab 0 : { *(.stab) }
......
......@@ -35,10 +35,8 @@
#include <asm/stackframe.h>
#include <asm/system.h>
#include <asm/cpu.h>
#include <linux/sched.h>
#include <linux/bootmem.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
#include <asm/mc146818rtc.h>
char arcs_cmdline[CL_SIZE] = {0, };
......
......@@ -35,10 +35,8 @@
#include <asm/stackframe.h>
#include <asm/system.h>
#include <asm/cpu.h>
#include <linux/sched.h>
#include <linux/bootmem.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
#include <asm/mc146818rtc.h>
#include <asm/orion.h>
......
......@@ -10,6 +10,15 @@ comment 'Code maturity level options'
bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
endmenu
mainmenu_option next_comment
comment 'Loadable module support'
bool 'Enable loadable module support' CONFIG_MODULES
if [ "$CONFIG_MODULES" = "y" ]; then
bool ' Set version information on all module symbols' CONFIG_MODVERSIONS
bool ' Kernel module loader' CONFIG_KMOD
fi
endmenu
mainmenu_option next_comment
comment 'Machine selection'
bool 'Support for SGI IP22' CONFIG_SGI_IP22
......@@ -109,14 +118,6 @@ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
endmenu
mainmenu_option next_comment
comment 'Loadable module support'
bool 'Enable loadable module support' CONFIG_MODULES
if [ "$CONFIG_MODULES" = "y" ]; then
bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
bool 'Kernel module loader' CONFIG_KMOD
fi
source drivers/pci/Config.in
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
......
......@@ -100,10 +100,6 @@ NESTED(kernel_entry, 16, sp) # kernel entry point
ARC64_TWIDDLE_PC
/* Note that all firmware passed argument registers still
have their values. */
jal prom_init # initialize firmware
CLI # disable interrupts
mfc0 t0, CP0_STATUS
......@@ -127,6 +123,10 @@ NESTED(kernel_entry, 16, sp) # kernel entry point
dsrl32 t0, t0, 0
mtc0 t0, CP0_WATCHHI
#endif
/* Note that all firmware passed argument registers still
have their values. */
jal prom_init # initialize firmware
jal start_kernel
1: b 1b # just in case ...
END(kernel_entry)
......
......@@ -46,6 +46,7 @@ EXPORT_SYMBOL_NOVERS(memcmp);
EXPORT_SYMBOL_NOVERS(memset);
EXPORT_SYMBOL_NOVERS(memcpy);
EXPORT_SYMBOL_NOVERS(memmove);
EXPORT_SYMBOL(simple_strtol);
EXPORT_SYMBOL_NOVERS(strcat);
EXPORT_SYMBOL_NOVERS(strchr);
EXPORT_SYMBOL_NOVERS(strlen);
......
/* $Id: process.c,v 1.4 2000/01/16 01:34:01 ralf Exp $
*
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1994 - 1999 by Ralf Baechle and others.
* Copyright (C) 1999 Silicon Graphics, Inc.
* Copyright (C) 1994 - 1999, 2000 by Ralf Baechle and others.
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
#include <linux/errno.h>
#include <linux/sched.h>
......
/* $Id: r4k_tlb.S,v 1.3 2000/06/30 00:48:29 kanoj Exp $
*
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
......
......@@ -4,8 +4,8 @@
* for more details.
*
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright (C) 1994 - 1999 Ralf Baechle
* Copyright (C) 1999 Silicon Graphics, Inc.
* Copyright (C) 1994 - 2000 Ralf Baechle
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
#include <linux/sched.h>
#include <linux/mm.h>
......
......@@ -83,6 +83,15 @@ SECTIONS
*(COMMON)
_end = . ;
}
/* Sections to be discarded */
/DISCARD/ :
{
*(.text.exit)
*(.data.exit)
*(.exitcall.exit)
}
/* These are needed for ELF backends which have not yet been
converted to the new style linker. */
.stab 0 : { *(.stab) }
......
......@@ -92,6 +92,15 @@ SECTIONS
*(COMMON)
_end = . ;
}
/* Sections to be discarded */
/DISCARD/ :
{
*(.text.exit)
*(.data.exit)
*(.exitcall.exit)
}
/* These are needed for ELF backends which have not yet been
converted to the new style linker. */
.stab 0 : { *(.stab) }
......
......@@ -26,6 +26,7 @@
#include <asm/pci/bridge.h>
#include <asm/paccess.h>
#include <asm/sn/sn0/ip27.h>
#include <asm/sn/sn0/hubio.h>
/* Check against user dumbness. */
#ifdef CONFIG_VT
......
......@@ -11,6 +11,15 @@ comment 'Code maturity level options'
bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
endmenu
mainmenu_option next_comment
comment 'Loadable module support'
bool 'Enable loadable module support' CONFIG_MODULES
if [ "$CONFIG_MODULES" = "y" ]; then
bool ' Set version information on all module symbols' CONFIG_MODVERSIONS
bool ' Kernel module loader' CONFIG_KMOD
fi
endmenu
mainmenu_option next_comment
comment 'Platform support'
define_bool CONFIG_PPC y
......@@ -76,15 +85,6 @@ if [ "$CONFIG_4xx" = "y" -o "$CONFIG_8xx" = "y" ]; then
fi
endmenu
mainmenu_option next_comment
comment 'Loadable module support'
bool 'Enable loadable module support' CONFIG_MODULES
if [ "$CONFIG_MODULES" = "y" ]; then
bool ' Set version information on all module symbols' CONFIG_MODVERSIONS
bool ' Kernel module loader' CONFIG_KMOD
fi
endmenu
mainmenu_option next_comment
comment 'General setup'
......
......@@ -13,21 +13,21 @@ comment 'Code maturity level options'
bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
endmenu
mainmenu_option next_comment
comment 'Processor type and features'
bool 'Symmetric multi-processing support' CONFIG_SMP
bool 'IEEE FPU emulation' CONFIG_IEEEFPU_EMULATION
endmenu
mainmenu_option next_comment
comment 'Loadable module support'
bool 'Enable loadable module support' CONFIG_MODULES
if [ "$CONFIG_MODULES" = "y" ]; then
bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
bool 'Kernel module loader' CONFIG_KMOD
bool ' Set version information on all module symbols' CONFIG_MODVERSIONS
bool ' Kernel module loader' CONFIG_KMOD
fi
endmenu
mainmenu_option next_comment
comment 'Processor type and features'
bool 'Symmetric multi-processing support' CONFIG_SMP
bool 'IEEE FPU emulation' CONFIG_IEEEFPU_EMULATION
endmenu
mainmenu_option next_comment
comment 'General setup'
bool 'Fast IRQ handling' CONFIG_FAST_IRQ
......
......@@ -13,6 +13,15 @@ comment 'Code maturity level options'
bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
endmenu
mainmenu_option next_comment
comment 'Loadable module support'
bool 'Enable loadable module support' CONFIG_MODULES
if [ "$CONFIG_MODULES" = "y" ]; then
bool ' Set version information on all module symbols' CONFIG_MODVERSIONS
bool ' Kernel module loader' CONFIG_KMOD
fi
endmenu
mainmenu_option next_comment
comment 'Processor type and features'
choice 'SuperH system type' \
......@@ -47,15 +56,6 @@ else
fi
endmenu
mainmenu_option next_comment
comment 'Loadable module support'
bool 'Enable loadable module support' CONFIG_MODULES
if [ "$CONFIG_MODULES" = "y" ]; then
bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
bool 'Kernel module loader' CONFIG_KMOD
fi
endmenu
mainmenu_option next_comment
comment 'General setup'
......
/* $Id: timod.c,v 1.8 2000/07/12 00:51:06 davem Exp $
/* $Id: timod.c,v 1.9 2000/07/12 23:21:02 davem Exp $
* timod.c: timod emulation.
*
* Copyright (C) 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz)
......
......@@ -11,7 +11,7 @@ O_TARGET := acpi.o
O_OBJS :=
M_OBJS :=
ACPI_OBJS := osd.o
ACPI_OBJS := driver.o ec.o cpu.o os.o sys.o tables.o
ACPI_OBJS += $(patsubst %.c,%.o,$(wildcard */*.c))
EXTRA_CFLAGS += -I./include -D_LINUX
......
/*
* cpu.c - Processor handling
*
* Copyright (C) 2000 Andrew Henroid
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/pm.h>
#include <linux/acpi.h>
#include "acpi.h"
#include "driver.h"
unsigned long acpi_c2_exit_latency = ACPI_INFINITE;
unsigned long acpi_c3_exit_latency = ACPI_INFINITE;
unsigned long acpi_c2_enter_latency = ACPI_INFINITE;
unsigned long acpi_c3_enter_latency = ACPI_INFINITE;
static unsigned long acpi_pblk = ACPI_INVALID;
static int acpi_c2_tested = 0;
static int acpi_c3_tested = 0;
/*
* Clear busmaster activity flag
*/
static inline void
acpi_clear_bm_activity(struct acpi_facp *facp)
{
acpi_write_pm1_status(facp, ACPI_BM);
}
/*
* Returns 1 if there has been busmaster activity
*/
static inline int
acpi_bm_activity(struct acpi_facp *facp)
{
return acpi_read_pm1_status(facp) & ACPI_BM;
}
/*
* Set system to sleep through busmaster requests
*/
static void
acpi_sleep_on_busmaster(struct acpi_facp *facp)
{
u32 pm1_cntr = acpi_read_pm1_control(facp);
if (pm1_cntr & ACPI_BM_RLD) {
pm1_cntr &= ~ACPI_BM_RLD;
acpi_write_pm1_control(facp, pm1_cntr);
}
}
/*
* Set system to wake on busmaster requests
*/
static void
acpi_wake_on_busmaster(struct acpi_facp *facp)
{
u32 pm1_cntr = acpi_read_pm1_control(facp);
if (!(pm1_cntr & ACPI_BM_RLD)) {
pm1_cntr |= ACPI_BM_RLD;
acpi_write_pm1_control(facp, pm1_cntr);
}
acpi_clear_bm_activity(facp);
}
/* The ACPI timer is just the low 24 bits */
#define TIME_BEGIN(tmr) inl(tmr)
#define TIME_END(tmr, begin) ((inl(tmr) - (begin)) & 0x00ffffff)
/*
* Idle loop (uniprocessor only)
*/
static void
acpi_idle(void)
{
static int sleep_level = 1;
struct acpi_facp *facp = &acpi_facp;
if (!facp
|| facp->hdr.signature != ACPI_FACP_SIG
|| !facp->pm_tmr
|| !acpi_pblk)
goto not_initialized;
/*
* start from the previous sleep level..
*/
if (sleep_level == 1)
goto sleep1;
if (sleep_level == 2)
goto sleep2;
sleep3:
sleep_level = 3;
if (!acpi_c3_tested) {
printk(KERN_DEBUG "ACPI C3 works\n");
acpi_c3_tested = 1;
}
acpi_wake_on_busmaster(facp);
if (facp->pm2_cnt)
goto sleep3_with_arbiter;
for (;;) {
unsigned long time;
unsigned int pm_tmr = facp->pm_tmr;
__cli();
if (current->need_resched)
goto out;
if (acpi_bm_activity(facp))
goto sleep2;
time = TIME_BEGIN(pm_tmr);
inb(acpi_pblk + ACPI_P_LVL3);
/* Dummy read, force synchronization with the PMU */
inl(pm_tmr);
time = TIME_END(pm_tmr, time);
__sti();
if (time < acpi_c3_exit_latency)
goto sleep2;
}
sleep3_with_arbiter:
for (;;) {
unsigned long time;
u8 arbiter;
unsigned int pm2_cntr = facp->pm2_cnt;
unsigned int pm_tmr = facp->pm_tmr;
__cli();
if (current->need_resched)
goto out;
if (acpi_bm_activity(facp))
goto sleep2;
time = TIME_BEGIN(pm_tmr);
arbiter = inb(pm2_cntr) & ~ACPI_ARB_DIS;
/* Disable arbiter, park on CPU */
outb(arbiter | ACPI_ARB_DIS, pm2_cntr);
inb(acpi_pblk + ACPI_P_LVL3);
/* Dummy read, force synchronization with the PMU */
inl(pm_tmr);
time = TIME_END(pm_tmr, time);
/* Enable arbiter again.. */
outb(arbiter, pm2_cntr);
__sti();
if (time < acpi_c3_exit_latency)
goto sleep2;
}
sleep2:
sleep_level = 2;
if (!acpi_c2_tested) {
printk(KERN_DEBUG "ACPI C2 works\n");
acpi_c2_tested = 1;
}
acpi_wake_on_busmaster(facp); /* Required to track BM activity.. */
for (;;) {
unsigned long time;
unsigned int pm_tmr = facp->pm_tmr;
__cli();
if (current->need_resched)
goto out;
time = TIME_BEGIN(pm_tmr);
inb(acpi_pblk + ACPI_P_LVL2);
/* Dummy read, force synchronization with the PMU */
inl(pm_tmr);
time = TIME_END(pm_tmr, time);
__sti();
if (time < acpi_c2_exit_latency)
goto sleep1;
if (acpi_bm_activity(facp)) {
acpi_clear_bm_activity(facp);
continue;
}
if (time > acpi_c3_enter_latency)
goto sleep3;
}
sleep1:
sleep_level = 1;
acpi_sleep_on_busmaster(facp);
for (;;) {
unsigned long time;
unsigned int pm_tmr = facp->pm_tmr;
__cli();
if (current->need_resched)
goto out;
time = TIME_BEGIN(pm_tmr);
safe_halt();
time = TIME_END(pm_tmr, time);
if (time > acpi_c2_enter_latency)
goto sleep2;
}
not_initialized:
for (;;) {
__cli();
if (current->need_resched)
goto out;
safe_halt();
}
out:
__sti();
}
/*
* Get processor information
*/
static ACPI_STATUS
acpi_find_cpu(ACPI_HANDLE handle, u32 level, void *ctx, void **value)
{
ACPI_OBJECT obj;
ACPI_CX_STATE lat[4];
ACPI_CPU_THROTTLING_STATE throttle[ACPI_MAX_THROTTLE];
ACPI_BUFFER buf;
int i, count;
buf.length = sizeof(obj);
buf.pointer = &obj;
if (!ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buf)))
return AE_OK;
printk(KERN_INFO "ACPI: PBLK %d @ 0x%04x:%d\n",
obj.processor.proc_id,
obj.processor.pblk_address,
obj.processor.pblk_length);
if (acpi_pblk != ACPI_INVALID
|| !obj.processor.pblk_address
|| obj.processor.pblk_length != 6)
return AE_OK;
acpi_pblk = obj.processor.pblk_address;
buf.length = sizeof(lat);
buf.pointer = lat;
if (!ACPI_SUCCESS(acpi_get_processor_cx_info(handle, &buf)))
return AE_OK;
if (lat[2].latency < MAX_CX_STATE_LATENCY) {
printk(KERN_INFO "ACPI: C2 supported\n");
acpi_c2_exit_latency = lat[2].latency;
}
if (lat[3].latency < MAX_CX_STATE_LATENCY) {
printk(KERN_INFO "ACPI: C3 supported\n");
acpi_c3_exit_latency = lat[3].latency;
}
memset(throttle, 0, sizeof(throttle));
buf.length = sizeof(throttle);
buf.pointer = throttle;
if (!ACPI_SUCCESS(acpi_get_processor_throttling_info(handle, &buf)))
return AE_OK;
for (i = 0, count = 0; i < ACPI_MAX_THROTTLE; i++) {
if (throttle[i].percent_of_clock)
count++;
}
count--;
if (count > 0)
printk(KERN_INFO "ACPI: %d throttling states\n", count);
return AE_OK;
}
int
acpi_cpu_init(void)
{
acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
ACPI_ROOT_OBJECT,
ACPI_INT32_MAX,
acpi_find_cpu,
NULL,
NULL);
#ifdef CONFIG_SMP
if (smp_num_cpus == 1)
pm_idle = acpi_idle;
#else
pm_idle = acpi_idle;
#endif
return 0;
}
/*
* driver.c - ACPI driver
*
* Copyright (C) 2000 Andrew Henroid
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/sysctl.h>
#include <linux/pm.h>
#include <linux/acpi.h>
#include <asm/uaccess.h>
#include "acpi.h"
#include "driver.h"
struct acpi_run_entry
{
void (*callback)(void*);
void *context;
struct tq_struct task;
};
static spinlock_t acpi_event_lock = SPIN_LOCK_UNLOCKED;
static volatile u32 acpi_event_status = 0;
static volatile acpi_sstate_t acpi_event_state = ACPI_S0;
static DECLARE_WAIT_QUEUE_HEAD(acpi_event_wait);
static volatile int acpi_thread_pid = -1;
static DECLARE_TASK_QUEUE(acpi_thread_run);
static DECLARE_WAIT_QUEUE_HEAD(acpi_thread_wait);
static struct ctl_table_header *acpi_sysctl = NULL;
/*
* Examine/modify value
*/
static int
acpi_do_ulong(ctl_table * ctl,
int write,
struct file *file,
void *buffer,
size_t * len)
{
char str[2 * sizeof(unsigned long) + 4], *strend;
unsigned long val;
int size;
if (!write) {
if (file->f_pos) {
*len = 0;
return 0;
}
val = *(unsigned long *) ctl->data;
size = sprintf(str, "0x%08lx\n", val);
if (*len >= size) {
copy_to_user(buffer, str, size);
*len = size;
}
else
*len = 0;
}
else {
size = sizeof(str) - 1;
if (size > *len)
size = *len;
copy_from_user(str, buffer, size);
str[size] = '\0';
val = simple_strtoul(str, &strend, 0);
if (strend == str)
return -EINVAL;
*(unsigned long *) ctl->data = val;
}
file->f_pos += *len;
return 0;
}
/*
* Handle ACPI event
*/
static u32
acpi_event(void *context)
{
unsigned long flags;
int event = (int) context;
int mask = 0;
switch (event) {
case ACPI_EVENT_POWER_BUTTON: mask = ACPI_PWRBTN; break;
case ACPI_EVENT_SLEEP_BUTTON: mask = ACPI_SLPBTN; break;
default: return AE_ERROR;
}
if (mask) {
// notify process waiting on /dev/acpi
spin_lock_irqsave(&acpi_event_lock, flags);
acpi_event_status |= mask;
spin_unlock_irqrestore(&acpi_event_lock, flags);
acpi_event_state = acpi_sleep_state;
wake_up_interruptible(&acpi_event_wait);
}
return AE_OK;
}
/*
* Wait for next event
*/
static int
acpi_do_event(ctl_table * ctl,
int write,
struct file *file,
void *buffer,
size_t * len)
{
u32 event_status = 0;
acpi_sstate_t event_state = 0;
char str[27];
int size;
if (write)
return -EPERM;
if (*len < sizeof(str)) {
*len = 0;
return 0;
}
for (;;) {
unsigned long flags;
// we need an atomic exchange here
spin_lock_irqsave(&acpi_event_lock, flags);
event_status = acpi_event_status;
acpi_event_status = 0;
spin_unlock_irqrestore(&acpi_event_lock, flags);
event_state = acpi_event_state;
if (event_status)
break;
// wait for an event to arrive
interruptible_sleep_on(&acpi_event_wait);
if (signal_pending(current))
return -ERESTARTSYS;
}
size = sprintf(str,
"0x%08x 0x%08x 0x%01x\n",
event_status,
0,
event_state);
copy_to_user(buffer, str, size);
*len = size;
file->f_pos += size;
return 0;
}
/*
* Enter system sleep state
*/
static int
acpi_do_sleep(ctl_table * ctl,
int write,
struct file *file,
void *buffer,
size_t * len)
{
if (!write) {
if (file->f_pos) {
*len = 0;
return 0;
}
}
else {
#ifdef CONFIG_ACPI_S1_SLEEP
int status = acpi_enter_sx(ACPI_S1);
if (status)
return status;
#endif
}
file->f_pos += *len;
return 0;
}
/*
* Run queued callback
*/
static void
acpi_run_exec(void *context)
{
struct acpi_run_entry *entry
= (struct acpi_run_entry*) context;
(*entry->callback)(entry->context);
kfree(entry);
}
/*
* Queue for execution by the ACPI thread
*/
int
acpi_run(void (*callback)(void*), void *context)
{
struct acpi_run_entry *entry;
entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
if (!entry)
return -1;
memset(entry, 0, sizeof(entry));
entry->callback = callback;
entry->context = context;
entry->task.routine = acpi_run_exec;
entry->task.data = entry;
queue_task(&entry->task, &acpi_thread_run);
if (waitqueue_active(&acpi_thread_wait))
wake_up(&acpi_thread_wait);
return 0;
}
static struct ctl_table acpi_table[] =
{
{ACPI_P_LVL2_LAT, "c2_exit_latency",
&acpi_c2_exit_latency, sizeof(acpi_c2_exit_latency),
0644, NULL, &acpi_do_ulong},
{ACPI_ENTER_LVL2_LAT, "c2_enter_latency",
&acpi_c2_enter_latency, sizeof(acpi_c2_enter_latency),
0644, NULL, &acpi_do_ulong},
{ACPI_P_LVL3_LAT, "c3_exit_latency",
&acpi_c3_exit_latency, sizeof(acpi_c3_exit_latency),
0644, NULL, &acpi_do_ulong},
{ACPI_ENTER_LVL3_LAT, "c3_enter_latency",
&acpi_c3_enter_latency, sizeof(acpi_c3_enter_latency),
0644, NULL, &acpi_do_ulong},
{ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &acpi_do_sleep},
{ACPI_EVENT, "event", NULL, 0, 0400, NULL, &acpi_do_event},
{0}
};
static struct ctl_table acpi_dir_table[] =
{
{CTL_ACPI, "acpi", NULL, 0, 0555, acpi_table},
{0}
};
/*
* Initialize and run interpreter within a kernel thread
*/
static int
acpi_thread(void *context)
{
/*
* initialize
*/
exit_files(current);
daemonize();
strcpy(current->comm, "acpi");
if (!ACPI_SUCCESS(acpi_initialize(NULL))) {
printk(KERN_ERR "ACPI: initialize failed\n");
return -ENODEV;
}
if (acpi_load_tables())
return -ENODEV;
if (PM_IS_ACTIVE()) {
printk(KERN_NOTICE "ACPI: APM is already active.\n");
acpi_terminate();
return -ENODEV;
}
pm_active = 1;
if (!ACPI_SUCCESS(acpi_enable())) {
printk(KERN_ERR "ACPI: enable failed\n");
acpi_terminate();
return -ENODEV;
}
acpi_cpu_init();
acpi_sys_init();
acpi_ec_init();
if (!ACPI_SUCCESS(acpi_install_fixed_event_handler(
ACPI_EVENT_POWER_BUTTON,
acpi_event,
(void *) ACPI_EVENT_POWER_BUTTON))) {
printk(KERN_ERR "ACPI: power button enable failed\n");
}
if (!ACPI_SUCCESS(acpi_install_fixed_event_handler(
ACPI_EVENT_SLEEP_BUTTON,
acpi_event,
(void *) ACPI_EVENT_SLEEP_BUTTON))) {
printk(KERN_ERR "ACPI: sleep button enable failed\n");
}
acpi_sysctl = register_sysctl_table(acpi_dir_table, 1);
/*
* run
*/
for (;;) {
interruptible_sleep_on(&acpi_thread_wait);
if (signal_pending(current))
break;
do {
run_task_queue(&acpi_thread_run);
} while (acpi_thread_run);
}
/*
* terminate
*/
unregister_sysctl_table(acpi_sysctl);
acpi_terminate();
acpi_thread_pid = -1;
return 0;
}
/*
* Start the interpreter
*/
int __init
acpi_init(void)
{
acpi_thread_pid = kernel_thread(acpi_thread,
NULL,
(CLONE_FS | CLONE_FILES
| CLONE_SIGHAND | SIGCHLD));
return ((acpi_thread_pid >= 0) ? 0:-ENODEV);
}
/*
* Terminate the interpreter
*/
void __exit
acpi_exit(void)
{
int count;
if (!kill_proc(acpi_thread_pid, SIGTERM, 1)) {
// wait until thread terminates (at most 5 seconds)
count = 5 * HZ;
while (acpi_thread_pid >= 0 && --count) {
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(1);
}
}
pm_idle = NULL;
pm_power_off = NULL;
pm_active = 0;
}
module_init(acpi_init);
module_exit(acpi_exit);
/*
* driver.h - ACPI driver
*
* Copyright (C) 2000 Andrew Henroid
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __DRIVER_H
#define __DRIVER_H
#include <linux/tqueue.h>
#include <linux/wait.h>
#include <linux/pm.h>
#include <linux/acpi.h>
#include <asm/io.h>
#define ACPI_MAX_THROTTLE 10
#define ACPI_INVALID ~0UL
#define ACPI_INFINITE ~0UL
/*
* cpu.c
*/
int acpi_cpu_init(void);
extern unsigned long acpi_c2_exit_latency;
extern unsigned long acpi_c3_exit_latency;
extern unsigned long acpi_c2_enter_latency;
extern unsigned long acpi_c3_enter_latency;
/*
* driver.c
*/
int acpi_run(void (*callback)(void*), void *context);
/*
* ec.c
*/
int acpi_ec_init(void);
int acpi_ec_read(int addr, int *value);
int acpi_ec_write(int addr, int value);
/*
* sys.c
*/
int acpi_sys_init(void);
int acpi_enter_sx(acpi_sstate_t state);
extern volatile acpi_sstate_t acpi_sleep_state;
/*
* tables.c
*/
extern struct acpi_facp acpi_facp;
int acpi_load_tables(void);
/*
* access ACPI registers
*/
extern inline u32
acpi_read_pm1_control(struct acpi_facp *facp)
{
u32 value = 0;
if (facp->pm1a_cnt)
value = inw(facp->pm1a_cnt);
if (facp->pm1b_cnt)
value |= inw(facp->pm1b_cnt);
return value;
}
extern inline void
acpi_write_pm1_control(struct acpi_facp *facp, u32 value)
{
if (facp->pm1a_cnt)
outw(value, facp->pm1a_cnt);
if (facp->pm1b_cnt)
outw(value, facp->pm1b_cnt);
}
extern inline u32
acpi_read_pm1_status(struct acpi_facp *facp)
{
u32 value = 0;
if (facp->pm1a_evt)
value = inw(facp->pm1a_evt);
if (facp->pm1b_evt)
value |= inw(facp->pm1b_evt);
return value;
}
extern inline void
acpi_write_pm1_status(struct acpi_facp *facp, u32 value)
{
if (facp->pm1a_evt)
outw(value, facp->pm1a_evt);
if (facp->pm1b_evt)
outw(value, facp->pm1b_evt);
}
#endif /* __DRIVER_H */
/*
* ec.c - Embedded controller support
*
* Copyright (C) 2000 Andrew Henroid
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/pm.h>
#include <linux/acpi.h>
#include <linux/delay.h>
#include <asm/io.h>
#include "acpi.h"
#include "driver.h"
enum
{
ACPI_EC_HID = 0x090cd041,
};
enum
{
ACPI_EC_SMI = 0x40,
ACPI_EC_SCI = 0x20,
ACPI_EC_BURST = 0x10,
ACPI_EC_CMD = 0x08,
ACPI_EC_IBF = 0x02,
ACPI_EC_OBF = 0x01
};
enum
{
ACPI_EC_READ = 0x80,
ACPI_EC_WRITE = 0x81,
ACPI_EC_BURST_ENABLE = 0x82,
ACPI_EC_BURST_DISABLE = 0x83,
ACPI_EC_QUERY = 0x84,
};
static int acpi_ec_data = 0;
static int acpi_ec_status = 0;
static DECLARE_WAIT_QUEUE_HEAD(acpi_ec_wait);
/*
* handle GPE
*/
static void
acpi_ec_gpe(void *context)
{
printk(KERN_INFO "ACPI: EC GPE\n");
if (waitqueue_active(&acpi_ec_wait))
wake_up_interruptible(&acpi_ec_wait);
}
/*
* wait for read/write status to clear
*/
static void
acpi_ec_wait_control(void)
{
udelay(1);
while(inb(acpi_ec_status) & ACPI_EC_IBF)
udelay(10);
}
/*
* read a byte from the EC
*/
int
acpi_ec_read(int addr, int *value)
{
if (!acpi_ec_data || !acpi_ec_status)
return -1;
outb(ACPI_EC_READ, acpi_ec_status);
acpi_ec_wait_control();
outb(addr, acpi_ec_data);
acpi_ec_wait_control();
interruptible_sleep_on(&acpi_ec_wait);
*value = inb(acpi_ec_data);
return 0;
}
/*
* write a byte to the EC
*/
int
acpi_ec_write(int addr, int value)
{
if (!acpi_ec_data || !acpi_ec_status)
return -1;
outb(ACPI_EC_WRITE, acpi_ec_status);
acpi_ec_wait_control();
outb(addr, acpi_ec_data);
acpi_ec_wait_control();
outb(value, acpi_ec_data);
acpi_ec_wait_control();
interruptible_sleep_on(&acpi_ec_wait);
return 0;
}
/*
* Get processor information
*/
static ACPI_STATUS
acpi_find_ec(ACPI_HANDLE handle, u32 level, void *ctx, void **value)
{
ACPI_BUFFER buf;
ACPI_OBJECT obj;
RESOURCE *res;
int gpe;
buf.length = sizeof(obj);
buf.pointer = &obj;
if (!ACPI_SUCCESS(acpi_evaluate_object(handle, "_HID", NULL, &buf))
|| obj.type != ACPI_TYPE_NUMBER
|| obj.number.value != ACPI_EC_HID)
return AE_OK;
buf.length = 0;
buf.pointer = NULL;
if (acpi_get_current_resources(handle, &buf) != AE_BUFFER_OVERFLOW)
return AE_OK;
buf.pointer = kmalloc(buf.length, GFP_KERNEL);
if (!buf.pointer)
return AE_OK;
if (!ACPI_SUCCESS(acpi_get_current_resources(handle, &buf))) {
kfree(buf.pointer);
return AE_OK;
}
res = (RESOURCE*) buf.pointer;
acpi_ec_data = (int) res->data.io.min_base_address;
res = (RESOURCE*)((u8*) buf.pointer + res->length);
acpi_ec_status = (int) res->data.io.min_base_address;
kfree(buf.pointer);
buf.length = sizeof(obj);
buf.pointer = &obj;
if (!ACPI_SUCCESS(acpi_evaluate_object(handle, "_GPE", NULL, &buf))
|| obj.type != ACPI_TYPE_NUMBER)
return AE_OK;
gpe = (int) obj.number.value;
printk(KERN_INFO "ACPI: found EC @ (0x%02x,0x%02x,%d)\n",
acpi_ec_data, acpi_ec_status, gpe);
if (!ACPI_SUCCESS(acpi_install_gpe_handler(
gpe,
(ACPI_EVENT_LEVEL_TRIGGERED
| ACPI_EVENT_EDGE_TRIGGERED),
acpi_ec_gpe,
NULL)))
return AE_OK;
return AE_OK;
}
int
acpi_ec_init(void)
{
acpi_walk_namespace(ACPI_TYPE_DEVICE,
ACPI_ROOT_OBJECT,
ACPI_INT32_MAX,
acpi_find_ec,
NULL,
NULL);
return 0;
}
/*
* os.c - OS-dependent functions
*
* Copyright (C) 2000 Andrew Henroid
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/pci.h>
#include <linux/acpi.h>
#include <asm/io.h>
#include <asm/delay.h>
#include "acpi.h"
#include "driver.h"
static int acpi_irq_irq = 0;
static OSD_HANDLER acpi_irq_handler = NULL;
static void *acpi_irq_context = NULL;
char *
strupr(char *str)
{
char *s = str;
while (*s) {
*s = TOUPPER(*s);
s++;
}
return str;
}
ACPI_STATUS
acpi_os_initialize(void)
{
return AE_OK;
}
ACPI_STATUS
acpi_os_terminate(void)
{
if (acpi_irq_handler) {
acpi_os_remove_interrupt_handler(acpi_irq_irq,
acpi_irq_handler);
}
return AE_OK;
}
s32
acpi_os_printf(const char *fmt,...)
{
s32 size;
va_list args;
va_start(args, fmt);
size = acpi_os_vprintf(fmt, args);
va_end(args);
return size;
}
s32
acpi_os_vprintf(const char *fmt, va_list args)
{
static char buffer[512];
int size = vsprintf(buffer, fmt, args);
printk(KERN_DEBUG "ACPI: %s", buffer);
return size;
}
void *
acpi_os_allocate(u32 size)
{
return kmalloc(size, GFP_KERNEL);
}
void *
acpi_os_callocate(u32 size)
{
void *ptr = acpi_os_allocate(size);
if (ptr)
memset(ptr, 0, size);
return ptr;
}
void
acpi_os_free(void *ptr)
{
kfree(ptr);
}
ACPI_STATUS
acpi_os_map_memory(void *phys, u32 size, void **virt)
{
if ((unsigned long) phys < virt_to_phys(high_memory)) {
*virt = phys_to_virt((unsigned long) phys);
return AE_OK;
}
*virt = ioremap((unsigned long) phys, size);
if (!*virt)
return AE_ERROR;
return AE_OK;
}
void
acpi_os_unmap_memory(void *virt, u32 size)
{
if (virt >= high_memory)
iounmap(virt);
}
static void
acpi_irq(int irq, void *dev_id, struct pt_regs *regs)
{
(*acpi_irq_handler)(acpi_irq_context);
}
ACPI_STATUS
acpi_os_install_interrupt_handler(u32 irq, OSD_HANDLER handler, void *context)
{
acpi_irq_irq = irq;
acpi_irq_handler = handler;
acpi_irq_context = context;
if (request_irq(irq,
acpi_irq,
SA_INTERRUPT | SA_SHIRQ,
"acpi",
acpi_irq)) {
printk(KERN_ERR "ACPI: SCI (IRQ%d) allocation failed\n", irq);
return AE_ERROR;
}
return AE_OK;
}
ACPI_STATUS
acpi_os_remove_interrupt_handler(u32 irq, OSD_HANDLER handler)
{
if (acpi_irq_handler) {
free_irq(irq, acpi_irq);
acpi_irq_handler = NULL;
}
return AE_OK;
}
/*
* Running in interpreter thread context, safe to sleep
*/
void
acpi_os_sleep(u32 sec, u32 ms)
{
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(HZ * sec + (ms * HZ) / 1000);
}
void
acpi_os_sleep_usec(u32 us)
{
udelay(us);
}
u8
acpi_os_in8(ACPI_IO_ADDRESS port)
{
return inb(port);
}
u16
acpi_os_in16(ACPI_IO_ADDRESS port)
{
return inw(port);
}
u32
acpi_os_in32(ACPI_IO_ADDRESS port)
{
return inl(port);
}
void
acpi_os_out8(ACPI_IO_ADDRESS port, u8 val)
{
outb(val, port);
}
void
acpi_os_out16(ACPI_IO_ADDRESS port, u16 val)
{
outw(val, port);
}
void
acpi_os_out32(ACPI_IO_ADDRESS port, u32 val)
{
outl(val, port);
}
ACPI_STATUS
acpi_os_read_pci_cfg_byte(
u32 bus,
u32 func,
u32 addr,
u8 * val)
{
int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff);
struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn);
if (!val || !dev || pci_read_config_byte(dev, addr, val))
return AE_ERROR;
return AE_OK;
}
ACPI_STATUS
acpi_os_read_pci_cfg_word(
u32 bus,
u32 func,
u32 addr,
u16 * val)
{
int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff);
struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn);
if (!val || !dev || pci_read_config_word(dev, addr, val))
return AE_ERROR;
return AE_OK;
}
ACPI_STATUS
acpi_os_read_pci_cfg_dword(
u32 bus,
u32 func,
u32 addr,
u32 * val)
{
int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff);
struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn);
if (!val || !dev || pci_read_config_dword(dev, addr, val))
return AE_ERROR;
return AE_OK;
}
ACPI_STATUS
acpi_os_write_pci_cfg_byte(
u32 bus,
u32 func,
u32 addr,
u8 val)
{
int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff);
struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn);
if (!dev || pci_write_config_byte(dev, addr, val))
return AE_ERROR;
return AE_OK;
}
ACPI_STATUS
acpi_os_write_pci_cfg_word(
u32 bus,
u32 func,
u32 addr,
u16 val)
{
int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff);
struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn);
if (!dev || pci_write_config_word(dev, addr, val))
return AE_ERROR;
return AE_OK;
}
ACPI_STATUS
acpi_os_write_pci_cfg_dword(
u32 bus,
u32 func,
u32 addr,
u32 val)
{
int devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff);
struct pci_dev *dev = pci_find_slot(bus & 0xffff, devfn);
if (!dev || pci_write_config_dword(dev, addr, val))
return AE_ERROR;
return AE_OK;
}
/*
* Queue for interpreter thread
*/
ACPI_STATUS
acpi_os_queue_for_execution(
u32 priority,
OSD_EXECUTION_CALLBACK callback,
void *context)
{
if (acpi_run(callback, context))
return AE_ERROR;
return AE_OK;
}
/*
* Semaphores are unused, interpreter access is single threaded
*/
ACPI_STATUS
acpi_os_create_semaphore(u32 max_units, u32 init, ACPI_HANDLE * handle)
{
*handle = (ACPI_HANDLE) 0;
return AE_OK;
}
ACPI_STATUS
acpi_os_delete_semaphore(ACPI_HANDLE handle)
{
return AE_OK;
}
ACPI_STATUS
acpi_os_wait_semaphore(ACPI_HANDLE handle, u32 units, u32 timeout)
{
return AE_OK;
}
ACPI_STATUS
acpi_os_signal_semaphore(ACPI_HANDLE handle, u32 units)
{
return AE_OK;
}
ACPI_STATUS
acpi_os_breakpoint(char *msg)
{
acpi_os_printf("breakpoint: %s", msg);
return AE_OK;
}
void
acpi_os_dbg_trap(char *msg)
{
acpi_os_printf("trap: %s", msg);
}
void
acpi_os_dbg_assert(void *failure, void *file, u32 line, char *msg)
{
acpi_os_printf("assert: %s", msg);
}
u32
acpi_os_get_line(char *buffer)
{
return 0;
}
/*
* We just have to assume we're dealing with valid memory
*/
BOOLEAN
acpi_os_readable(void *ptr, u32 len)
{
return 1;
}
BOOLEAN
acpi_os_writable(void *ptr, u32 len)
{
return 1;
}
This diff is collapsed.
/*
* sys.c - System management (suspend, ...)
*
* Copyright (C) 2000 Andrew Henroid
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/pm.h>
#include <linux/acpi.h>
#include "acpi.h"
#include "driver.h"
#define ACPI_SLP_TYP(typa, typb) (((int)(typa) << 8) | (int)(typb))
#define ACPI_SLP_TYPA(value) \
((((value) >> 8) << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK)
#define ACPI_SLP_TYPB(value) \
((((value) & 0xff) << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK)
struct acpi_enter_sx_ctx
{
wait_queue_head_t wait;
int state;
};
volatile acpi_sstate_t acpi_sleep_state = ACPI_S0;
static unsigned long acpi_slptyp[ACPI_S5 + 1] = {ACPI_INVALID,};
/*
* Enter system sleep state
*/
static void
acpi_enter_sx_async(void *context)
{
struct acpi_enter_sx_ctx *ctx = (struct acpi_enter_sx_ctx*) context;
struct acpi_facp *facp = &acpi_facp;
ACPI_OBJECT_LIST arg_list;
ACPI_OBJECT arg;
u16 value;
/*
* _PSW methods could be run here to enable wake-on keyboard, LAN, etc.
*/
// run the _PTS method
memset(&arg_list, 0, sizeof(arg_list));
arg_list.count = 1;
arg_list.pointer = &arg;
memset(&arg, 0, sizeof(arg));
arg.type = ACPI_TYPE_NUMBER;
arg.number.value = ctx->state;
acpi_evaluate_object(NULL, "\\_PTS", &arg_list, NULL);
// clear wake status
acpi_write_pm1_status(facp, ACPI_WAK);
acpi_sleep_state = ctx->state;
// set ACPI_SLP_TYPA/b and ACPI_SLP_EN
__cli();
if (facp->pm1a_cnt) {
value = inw(facp->pm1a_cnt) & ~ACPI_SLP_TYP_MASK;
value |= (ACPI_SLP_TYPA(acpi_slptyp[ctx->state])
| ACPI_SLP_EN);
outw(value, facp->pm1a_cnt);
}
if (facp->pm1b_cnt) {
value = inw(facp->pm1b_cnt) & ~ACPI_SLP_TYP_MASK;
value |= (ACPI_SLP_TYPB(acpi_slptyp[ctx->state])
| ACPI_SLP_EN);
outw(value, facp->pm1b_cnt);
}
__sti();
if (ctx->state != ACPI_S1) {
printk(KERN_ERR "ACPI: S%d failed\n", ctx->state);
goto out;
}
// wait until S1 is entered
while (!(acpi_read_pm1_status(facp) & ACPI_WAK))
safe_halt();
// run the _WAK method
memset(&arg_list, 0, sizeof(arg_list));
arg_list.count = 1;
arg_list.pointer = &arg;
memset(&arg, 0, sizeof(arg));
arg.type = ACPI_TYPE_NUMBER;
arg.number.value = ctx->state;
acpi_evaluate_object(NULL, "\\_WAK", &arg_list, NULL);
out:
acpi_sleep_state = ACPI_S0;
if (waitqueue_active(&ctx->wait))
wake_up_interruptible(&ctx->wait);
}
/*
* Enter soft-off (S5)
*/
static void
acpi_power_off(void)
{
struct acpi_enter_sx_ctx ctx;
if (acpi_facp.hdr.signature != ACPI_FACP_SIG
|| acpi_slptyp[ACPI_S5] == ACPI_INVALID)
return;
init_waitqueue_head(&ctx.wait);
ctx.state = ACPI_S5;
acpi_enter_sx_async(&ctx);
}
/*
* Enter system sleep state and wait for completion
*/
int
acpi_enter_sx(acpi_sstate_t state)
{
struct acpi_enter_sx_ctx ctx;
if (acpi_facp.hdr.signature != ACPI_FACP_SIG
|| acpi_slptyp[state] == ACPI_INVALID)
return -EINVAL;
init_waitqueue_head(&ctx.wait);
ctx.state = state;
if (acpi_os_queue_for_execution(0, acpi_enter_sx_async, &ctx))
return -1;
interruptible_sleep_on(&ctx.wait);
if (signal_pending(current))
return -ERESTARTSYS;
return 0;
}
int
acpi_sys_init(void)
{
u8 sx, typa, typb;
for (sx = ACPI_S0; sx <= ACPI_S5; sx++) {
int ca_sx = (sx <= ACPI_S4) ? sx : (sx + 1);
if (ACPI_SUCCESS(
acpi_hw_obtain_sleep_type_register_data(ca_sx,
&typa,
&typb)))
acpi_slptyp[sx] = ACPI_SLP_TYP(typa, typb);
else
acpi_slptyp[sx] = ACPI_INVALID;
}
if (acpi_slptyp[ACPI_S1] != ACPI_INVALID)
printk(KERN_INFO "ACPI: S1 supported\n");
if (acpi_slptyp[ACPI_S5] != ACPI_INVALID)
printk(KERN_INFO "ACPI: S5 supported\n");
pm_power_off = acpi_power_off;
return 0;
}
/*
* tables.c - ACPI tables, chipset, and errata handling
*
* Copyright (C) 2000 Andrew Henroid
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/pm.h>
#include <linux/acpi.h>
#include "acpi.h"
#include "driver.h"
struct acpi_facp acpi_facp;
#define ACPI_DUMMY_CHECKSUM 9
#define ACPI_DUMMY_PBLK 51
static u8 acpi_dummy_dsdt[] =
{
0x44, 0x53, 0x44, 0x54, // "DSDT"
0x38, 0x00, 0x00, 0x00, // length
0x01, // revision
0x00, // checksum
0x4c, 0x49, 0x4e, 0x55, 0x58, 0x00, // "LINUX"
0x44, 0x55, 0x4d, 0x4d, 0x59, 0x00, 0x00, 0x00, // "DUMMY"
0x01, 0x00, 0x00, 0x00, // OEM rev
0x4c, 0x4e, 0x55, 0x58, // "LNUX"
0x01, 0x00, 0x00, 0x00, // creator rev
0x10, // Scope
0x13, // PkgLength
0x5c, 0x5f, 0x50, 0x52, 0x5f, // \_PR_
0x5b, 0x83, // Processor
0x0b, // PkgLength
0x43, 0x50, 0x55, 0x30, // CPU0
0x00, // ID
0x00, 0x00, 0x00, 0x00, // PBLK
0x06 // PBLK size
};
/*
* Calculate and set ACPI table checksum
*/
static void
acpi_set_checksum(u8 *table, int size)
{
int i, sum = 0;
for (i = 0; i < size; i++)
sum += (int) table[i];
sum = (0x100 - ((sum - table[ACPI_DUMMY_CHECKSUM]) & 0xff));
table[ACPI_DUMMY_CHECKSUM] = sum;
}
/*
* Init PIIX4 device, create a fake FACP
*/
static int
acpi_init_piix4(struct pci_dev *dev)
{
u32 base, pblk;
u16 cmd;
u8 pmregmisc;
pci_read_config_word(dev, PCI_COMMAND, &cmd);
if (!(cmd & PCI_COMMAND_IO))
return -ENODEV;
pci_read_config_byte(dev, ACPI_PIIX4_PMREGMISC, &pmregmisc);
if (!(pmregmisc & ACPI_PIIX4_PMIOSE))
return -ENODEV;
base = pci_resource_start (dev, PCI_BRIDGE_RESOURCES);
if (!base)
return -ENODEV;
printk(KERN_INFO "ACPI: found \"%s\" at 0x%04x\n", dev->name, base);
memset(&acpi_facp, 0, sizeof(acpi_facp));
acpi_facp.hdr.signature = ACPI_FACP_SIG;
acpi_facp.hdr.length = sizeof(acpi_facp);
acpi_facp.int_model = ACPI_PIIX4_INT_MODEL;
acpi_facp.sci_int = ACPI_PIIX4_SCI_INT;
acpi_facp.smi_cmd = ACPI_PIIX4_SMI_CMD;
acpi_facp.acpi_enable = ACPI_PIIX4_ACPI_ENABLE;
acpi_facp.acpi_disable = ACPI_PIIX4_ACPI_DISABLE;
acpi_facp.s4bios_req = ACPI_PIIX4_S4BIOS_REQ;
acpi_facp.pm1a_evt = base + ACPI_PIIX4_PM1_EVT;
acpi_facp.pm1a_cnt = base + ACPI_PIIX4_PM1_CNT;
acpi_facp.pm2_cnt = ACPI_PIIX4_PM2_CNT;
acpi_facp.pm_tmr = base + ACPI_PIIX4_PM_TMR;
acpi_facp.gpe0 = base + ACPI_PIIX4_GPE0;
acpi_facp.pm1_evt_len = ACPI_PIIX4_PM1_EVT_LEN;
acpi_facp.pm1_cnt_len = ACPI_PIIX4_PM1_CNT_LEN;
acpi_facp.pm2_cnt_len = ACPI_PIIX4_PM2_CNT_LEN;
acpi_facp.pm_tm_len = ACPI_PIIX4_PM_TM_LEN;
acpi_facp.gpe0_len = ACPI_PIIX4_GPE0_LEN;
acpi_facp.p_lvl2_lat = (__u16) ACPI_INFINITE_LAT;
acpi_facp.p_lvl3_lat = (__u16) ACPI_INFINITE_LAT;
acpi_set_checksum((u8*) &acpi_facp, sizeof(acpi_facp));
acpi_load_table((ACPI_TABLE_HEADER*) &acpi_facp);
pblk = base + ACPI_PIIX4_P_BLK;
memcpy(acpi_dummy_dsdt + ACPI_DUMMY_PBLK, &pblk, sizeof(pblk));
acpi_set_checksum(acpi_dummy_dsdt, sizeof(acpi_dummy_dsdt));
acpi_load_table((ACPI_TABLE_HEADER*) acpi_dummy_dsdt);
return 0;
}
/*
* Init VIA ACPI device and create a fake FACP
*/
static int
acpi_init_via(struct pci_dev *dev)
{
u32 base, pblk;
u8 tmp, irq;
pci_read_config_byte(dev, 0x41, &tmp);
if (!(tmp & 0x80))
return -ENODEV;
base = pci_resource_start(dev, PCI_BRIDGE_RESOURCES);
if (!base) {
base = pci_resource_start(dev, PCI_BASE_ADDRESS_4);
if (!base)
return -ENODEV;
}
pci_read_config_byte(dev, 0x42, &irq);
printk(KERN_INFO "ACPI: found \"%s\" at 0x%04x\n", dev->name, base);
memset(&acpi_facp, 0, sizeof(acpi_facp));
acpi_facp.hdr.signature = ACPI_FACP_SIG;
acpi_facp.hdr.length = sizeof(acpi_facp);
acpi_facp.int_model = ACPI_VIA_INT_MODEL;
acpi_facp.sci_int = irq;
acpi_facp.smi_cmd = base + ACPI_VIA_SMI_CMD;
acpi_facp.acpi_enable = ACPI_VIA_ACPI_ENABLE;
acpi_facp.acpi_disable = ACPI_VIA_ACPI_DISABLE;
acpi_facp.pm1a_evt = base + ACPI_VIA_PM1_EVT;
acpi_facp.pm1a_cnt = base + ACPI_VIA_PM1_CNT;
acpi_facp.pm_tmr = base + ACPI_VIA_PM_TMR;
acpi_facp.gpe0 = base + ACPI_VIA_GPE0;
acpi_facp.pm1_evt_len = ACPI_VIA_PM1_EVT_LEN;
acpi_facp.pm1_cnt_len = ACPI_VIA_PM1_CNT_LEN;
acpi_facp.pm_tm_len = ACPI_VIA_PM_TM_LEN;
acpi_facp.gpe0_len = ACPI_VIA_GPE0_LEN;
acpi_facp.p_lvl2_lat = (__u16) ACPI_INFINITE_LAT;
acpi_facp.p_lvl3_lat = (__u16) ACPI_INFINITE_LAT;
acpi_facp.duty_offset = ACPI_VIA_DUTY_OFFSET;
acpi_facp.duty_width = ACPI_VIA_DUTY_WIDTH;
acpi_facp.day_alarm = ACPI_VIA_DAY_ALARM;
acpi_facp.mon_alarm = ACPI_VIA_MON_ALARM;
acpi_facp.century = ACPI_VIA_CENTURY;
acpi_set_checksum((u8*) &acpi_facp, sizeof(acpi_facp));
acpi_load_table((ACPI_TABLE_HEADER*) &acpi_facp);
pblk = base + ACPI_VIA_P_BLK;
memcpy(acpi_dummy_dsdt + ACPI_DUMMY_PBLK, &pblk, sizeof(pblk));
acpi_set_checksum(acpi_dummy_dsdt, sizeof(acpi_dummy_dsdt));
acpi_load_table((ACPI_TABLE_HEADER*) acpi_dummy_dsdt);
return 0;
}
typedef enum
{
CH_UNKNOWN = 0,
CH_INTEL_PIIX4,
CH_VIA_586,
CH_VIA_686A,
} acpi_chip_t;
/* indexed by value of each enum in acpi_chip_t */
const static struct
{
int (*chip_init)(struct pci_dev *dev);
} acpi_chip_info[] =
{
{NULL,},
{acpi_init_piix4},
{acpi_init_via},
{acpi_init_via},
};
static struct pci_device_id acpi_pci_tbl[] =
{
{0x8086, 0x7113, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_INTEL_PIIX4},
{0x1106, 0x3040, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_VIA_586},
{0x1106, 0x3057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_VIA_686A},
{0,} /* terminate list */
};
static int
acpi_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
return acpi_chip_info[id->driver_data].chip_init(dev);
}
static struct pci_driver acpi_driver =
{
name: "acpi",
id_table: acpi_pci_tbl,
probe: acpi_probe,
};
static int acpi_driver_registered = 0;
/*
* Locate a known ACPI chipset
*/
static int
acpi_find_chipset(void)
{
if (pci_register_driver(&acpi_driver) < 1)
return -ENODEV;
acpi_driver_registered = 1;
return 0;
}
/*
* Fetch the FACP information
*/
static int
acpi_fetch_facp(void)
{
ACPI_BUFFER buffer;
memset(&acpi_facp, 0, sizeof(acpi_facp));
buffer.pointer = &acpi_facp;
buffer.length = sizeof(acpi_facp);
if (!ACPI_SUCCESS(acpi_get_table(ACPI_TABLE_FACP, 1, &buffer))) {
printk(KERN_ERR "ACPI: missing FACP\n");
return -ENODEV;
}
if (acpi_facp.p_lvl2_lat
&& acpi_facp.p_lvl2_lat <= ACPI_MAX_P_LVL2_LAT) {
acpi_c2_exit_latency
= ACPI_uS_TO_TMR_TICKS(acpi_facp.p_lvl2_lat);
acpi_c2_enter_latency
= ACPI_uS_TO_TMR_TICKS(ACPI_TMR_HZ / 1000);
}
if (acpi_facp.p_lvl3_lat
&& acpi_facp.p_lvl3_lat <= ACPI_MAX_P_LVL3_LAT) {
acpi_c3_exit_latency
= ACPI_uS_TO_TMR_TICKS(acpi_facp.p_lvl3_lat);
acpi_c3_enter_latency
= ACPI_uS_TO_TMR_TICKS(acpi_facp.p_lvl3_lat * 5);
}
return 0;
}
/*
* Find and load ACPI tables
*/
int
acpi_load_tables(void)
{
if (ACPI_SUCCESS(acpi_load_firmware_tables()))
{
printk(KERN_INFO "ACPI: support found\n");
}
else if (acpi_find_chipset()) {
acpi_terminate();
return -1;
}
if (acpi_fetch_facp()) {
acpi_terminate();
return -1;
}
if (!ACPI_SUCCESS(acpi_load_namespace())) {
printk(KERN_ERR "ACPI: namespace load failed\n");
acpi_terminate();
return -1;
}
return 0;
}
......@@ -792,8 +792,7 @@ int generic_make_request (request_queue_t *q, int rw, struct buffer_head * bh)
device. Currently the only restriction is that all buffers must belong to
the same device */
static void __ll_rw_block(int rw, int nr, struct buffer_head * bhs[],
int haslock)
void ll_rw_block(int rw, int nr, struct buffer_head * bhs[])
{
struct buffer_head *bh;
request_queue_t *q;
......@@ -840,13 +839,9 @@ static void __ll_rw_block(int rw, int nr, struct buffer_head * bhs[],
bh = bhs[i];
/* Only one thread can actually submit the I/O. */
if (haslock) {
if (!buffer_locked(bh))
BUG();
} else {
if (test_and_set_bit(BH_Lock, &bh->b_state))
continue;
}
if (test_and_set_bit(BH_Lock, &bh->b_state))
continue;
set_bit(BH_Req, &bh->b_state);
/*
......@@ -865,15 +860,6 @@ static void __ll_rw_block(int rw, int nr, struct buffer_head * bhs[],
buffer_IO_error(bhs[i]);
}
void ll_rw_block(int rw, int nr, struct buffer_head * bh[])
{
__ll_rw_block(rw, nr, bh, 0);
}
void ll_rw_block_locked(int rw, int nr, struct buffer_head * bh[])
{
__ll_rw_block(rw, nr, bh, 1);
}
#ifdef CONFIG_STRAM_SWAP
extern int stram_device_init (void);
......
......@@ -3412,7 +3412,7 @@ int md_do_sync(mddev_t *mddev, mdp_disk_t *spare)
currspeed = (j-mddev->resync_mark_cnt)/((jiffies-mddev->resync_mark)/HZ +1) +1;
if (currspeed > sysctl_speed_limit_min) {
current->priority = 19;
current->nice = 19;
if ((currspeed > sysctl_speed_limit_max) ||
!is_mddev_idle(mddev)) {
......@@ -3422,7 +3422,7 @@ int md_do_sync(mddev_t *mddev, mdp_disk_t *spare)
goto repeat;
}
} else
current->priority = -20;
current->nice = -20;
}
fsync_dev(read_disk);
printk(KERN_INFO "md: md%d: sync done.\n",mdidx(mddev));
......
......@@ -13,10 +13,11 @@
1.02 GRG 1998.05.05 init_proto, release_proto, ktti
1.03 GRG 1998.08.15 eliminate compiler warning
1.04 GRG 1998.11.28 added support for FRIQ
1.05 TMW 2000.06.06 use parport_find_number instead of
parport_enumerate
*/
#define PI_VERSION "1.04"
#define PI_VERSION "1.05"
#include <linux/module.h>
#include <linux/config.h>
......@@ -238,22 +239,25 @@ static void pi_register_parport( PIA *pi, int verbose)
{
#ifdef CONFIG_PARPORT
struct parport *pp;
pp = parport_enumerate();
struct parport *port;
while((pp)&&(pp->base != pi->port)) pp = pp->next;
port = parport_find_base (pi->port);
if (!port) return;
if (!pp) return;
pi->pardev = parport_register_device(port,
pi->device,NULL,
pi_wake_up,NULL,
0,(void *)pi);
parport_put_port (port);
if (!pi->pardev) return;
pi->pardev = (void *) parport_register_device(
pp,pi->device,NULL,pi_wake_up,NULL,0,(void *)pi);
init_waitqueue_head(&pi->parq);
if (verbose) printk("%s: 0x%x is %s\n",pi->device,pi->port,pp->name);
if (verbose) printk("%s: 0x%x is %s\n",pi->device,pi->port,
port->name);
pi->parname = (char *)pp->name;
pi->parname = (char *)port->name;
#endif
}
......@@ -406,6 +410,7 @@ int init_module(void)
{ int k;
for (k=0;k<MAX_PROTOS;k++) protocols[k] = 0;
printk("paride: version %s installed\n",PI_VERSION);
return 0;
}
......
This diff is collapsed.
......@@ -75,7 +75,7 @@ static void i2c_parport_attach(struct parport *port)
struct parport_i2c_bus *b = kmalloc(sizeof(struct parport_i2c_bus),
GFP_KERNEL);
b->i2c = parport_i2c_bus_template;
b->i2c.data = port;
b->i2c.data = parport_get_port (port);
strncpy(b->i2c.name, port->name, 32);
spin_lock(&bus_list_lock);
b->next = bus_list;
......
This diff is collapsed.
This diff is collapsed.
2000-06-30 Gunther Mayer <gunther.mayer@braunschweig.okersurf.de>
2000-07-12 Tim Waugh <twaugh@redhat.com>
* share.c: Documentation for parport_{get,port}_port,
parport_find_{number,base}.
2000-07-12 Tim Waugh <twaugh@redhat.com>
* share.c (parport_unregister_device): Remove unneeded locking
(test cad==dev).
(parport_claim): Likewise.
(parport_find_number): New function.
2000-07-12 Tim Waugh <twaugh@redhat.com>
* share.c (parport_register_port): Hold the parportlist_lock while
looking for a free parport number.
(parport_register_driver): Make sure that attach can block.
(attach_driver_chain): Likewise.
2000-07-12 Tim Waugh <twaugh@redhat.com>
* share.c (call_driver_chain): Do reference counting things.
(parport_get_port): New function.
(parport_put_port): New function.
(parport_register_port): Initialise reference count to zero.
(parport_unregister_port): Check reference count rather than
driver list to see if we can free the port.
2000-07-12 Tim Waugh <twaugh@redhat.com>
* share.c: Clarifications in doc comments.
2000-07-12 Tim Waugh <twaugh@redhat.com>
* share.c (parport_unregister_port): Fix typo in comment.
2000-07-11 Gunther Mayer <gunther.mayer@braunschweig.okersurf.de>
* parport_pc.c: Support for the full range of Timedia cards.
......
......@@ -180,6 +180,10 @@ EXPORT_SYMBOL(parport_unregister_driver);
EXPORT_SYMBOL(parport_register_device);
EXPORT_SYMBOL(parport_unregister_device);
EXPORT_SYMBOL(parport_enumerate);
EXPORT_SYMBOL(parport_get_port);
EXPORT_SYMBOL(parport_put_port);
EXPORT_SYMBOL(parport_find_number);
EXPORT_SYMBOL(parport_find_base);
EXPORT_SYMBOL(parport_negotiate);
EXPORT_SYMBOL(parport_write);
EXPORT_SYMBOL(parport_read);
......
This diff is collapsed.
......@@ -138,6 +138,10 @@ static struct dev_info device_list[] =
{"iomega", "jaz 1GB", "J.86", BLIST_NOTQ | BLIST_NOLUN},
{"TOSHIBA","CDROM","*", BLIST_ISROM},
{"MegaRAID", "LD", "*", BLIST_FORCELUN},
{"DGC", "RAID", "*", BLIST_SPARSELUN}, // Dell PV 650F (tgt @ LUN 0)
{"DGC", "DISK", "*", BLIST_SPARSELUN}, // Dell PV 650F (no tgt @ LUN 0)
{"DELL", "PV530F", "*", BLIST_SPARSELUN}, // Dell PV 530F
{"SONY", "TSL", "*", BLIST_FORCELUN}, // DDS3 & DDS4 autoloaders
/*
* Must be at end of list...
......
This diff is collapsed.
......@@ -33,7 +33,7 @@ obj- :=
# Each configuration option enables a list of files.
obj-$(CONFIG_DUMMY_CONSOLE) += dummycon.o
obj-$(CONFIG_SGI_NEWPORT_CONSOLE) += newport_con.o vga_font.o
obj-$(CONFIG_SGI_NEWPORT_CONSOLE) += newport_con.o
obj-$(CONFIG_PROM_CONSOLE) += promcon.o promcon_tbl.o
obj-$(CONFIG_VGA_CONSOLE) += vgacon.o
obj-$(CONFIG_MDA_CONSOLE) += mdacon.o
......
This diff is collapsed.
......@@ -933,6 +933,9 @@ void d_move(struct dentry * dentry, struct dentry * target)
/**
* d_path - return the path of a dentry
* @dentry: dentry to report
* @vfsmnt: vfsmnt to which the dentry belongs
* @root: root dentry
* @rootmnt: vfsmnt to which the root dentry belongs
* @buffer: buffer to return value in
* @buflen: buffer length
*
......
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