Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
6f982794
Commit
6f982794
authored
Jun 17, 2003
by
Andy Grover
Browse files
Options
Browse Files
Download
Plain Diff
Merge groveronline.com:/root/bk/linux-2.5
into groveronline.com:/root/bk/linux-acpi
parents
2d00c1cc
feb66678
Changes
14
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
1851 additions
and
55 deletions
+1851
-55
arch/i386/kernel/acpi/Makefile
arch/i386/kernel/acpi/Makefile
+1
-0
arch/i386/kernel/acpi/acpitable.c
arch/i386/kernel/acpi/acpitable.c
+553
-0
arch/i386/kernel/acpi/acpitable.h
arch/i386/kernel/acpi/acpitable.h
+260
-0
arch/i386/kernel/setup.c
arch/i386/kernel/setup.c
+10
-1
drivers/acpi/Kconfig
drivers/acpi/Kconfig
+28
-3
drivers/acpi/Makefile
drivers/acpi/Makefile
+1
-0
drivers/acpi/asus_acpi.c
drivers/acpi/asus_acpi.c
+951
-0
drivers/pci/hotplug/acpiphp.h
drivers/pci/hotplug/acpiphp.h
+6
-10
drivers/pci/hotplug/acpiphp_core.c
drivers/pci/hotplug/acpiphp_core.c
+6
-9
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/hotplug/acpiphp_glue.c
+24
-26
drivers/pci/hotplug/acpiphp_pci.c
drivers/pci/hotplug/acpiphp_pci.c
+2
-2
drivers/pci/hotplug/acpiphp_res.c
drivers/pci/hotplug/acpiphp_res.c
+2
-2
include/asm-i386/acpi.h
include/asm-i386/acpi.h
+5
-0
include/linux/acpi.h
include/linux/acpi.h
+2
-2
No files found.
arch/i386/kernel/acpi/Makefile
View file @
6f982794
obj-$(CONFIG_ACPI_HT_ONLY)
:=
acpitable.o
obj-$(CONFIG_ACPI_BOOT)
:=
boot.o
obj-$(CONFIG_ACPI_SLEEP)
+=
sleep.o wakeup.o
arch/i386/kernel/acpi/acpitable.c
0 → 100644
View file @
6f982794
/*
* acpitable.c - IA32-specific ACPI boot-time initialization (Revision: 1)
*
* Copyright (C) 1999 Andrew Henroid
* Copyright (C) 2001 Richard Schaal
* Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
* Copyright (C) 2001 Jun Nakajima <jun.nakajima@intel.com>
* Copyright (C) 2001 Arjan van de Ven <arjanv@redhat.com>
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* 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
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* $Id: acpitable.c,v 1.7 2001/11/04 12:21:18 fenrus Exp $
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/stddef.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <asm/mpspec.h>
#include <asm/io.h>
#include <asm/apic.h>
#include <asm/apicdef.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include "acpitable.h"
static
acpi_table_handler
acpi_boot_ops
[
ACPI_TABLE_COUNT
];
int
acpi_lapic
;
static
unsigned
char
__init
acpi_checksum
(
void
*
buffer
,
int
length
)
{
int
i
;
unsigned
char
*
bytebuffer
;
unsigned
char
sum
=
0
;
if
(
!
buffer
||
length
<=
0
)
return
0
;
bytebuffer
=
(
unsigned
char
*
)
buffer
;
for
(
i
=
0
;
i
<
length
;
i
++
)
sum
+=
*
(
bytebuffer
++
);
return
sum
;
}
static
void
__init
acpi_print_table_header
(
acpi_table_header
*
header
)
{
if
(
!
header
)
return
;
printk
(
KERN_INFO
"ACPI table found: %.4s v%d [%.6s %.8s %d.%d]
\n
"
,
header
->
signature
,
header
->
revision
,
header
->
oem_id
,
header
->
oem_table_id
,
header
->
oem_revision
>>
16
,
header
->
oem_revision
&
0xffff
);
return
;
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_scan_memory_for_rsdp
*
* PARAMETERS: address - Starting pointer for search
* length - Maximum length to search
*
* RETURN: Pointer to the RSDP if found and valid, otherwise NULL.
*
* DESCRIPTION: Search a block of memory for the RSDP signature
*
******************************************************************************/
static
void
*
__init
acpi_tb_scan_memory_for_rsdp
(
void
*
address
,
int
length
)
{
u32
offset
;
if
(
length
<=
0
)
return
NULL
;
/* Search from given start addr for the requested length */
offset
=
0
;
while
(
offset
<
length
)
{
/* The signature must match and the checksum must be correct */
if
(
strncmp
(
address
,
RSDP_SIG
,
sizeof
(
RSDP_SIG
)
-
1
)
==
0
&&
acpi_checksum
(
address
,
RSDP_CHECKSUM_LENGTH
)
==
0
)
{
/* If so, we have found the RSDP */
printk
(
KERN_INFO
"ACPI: RSDP located at physical address %p
\n
"
,
address
);
return
address
;
}
offset
+=
RSDP_SCAN_STEP
;
address
+=
RSDP_SCAN_STEP
;
}
/* Searched entire block, no RSDP was found */
printk
(
KERN_INFO
"ACPI: Searched entire block, no RSDP was found.
\n
"
);
return
NULL
;
}
/*******************************************************************************
*
* FUNCTION: acpi_find_root_pointer
*
* PARAMETERS: none
*
* RETURN: physical address of the RSDP
*
* DESCRIPTION: Search lower 1_mbyte of memory for the root system descriptor
* pointer structure. If it is found, set *RSDP to point to it.
*
* NOTE: The RSDP must be either in the first 1_k of the Extended
* BIOS Data Area or between E0000 and FFFFF (ACPI 1.0 section
* 5.2.2; assertion #421).
*
******************************************************************************/
static
struct
acpi_table_rsdp
*
__init
acpi_find_root_pointer
(
void
)
{
struct
acpi_table_rsdp
*
rsdp
;
/*
* Physical address is given
*/
/*
* Region 1) Search EBDA (low memory) paragraphs
*/
rsdp
=
acpi_tb_scan_memory_for_rsdp
(
__va
(
LO_RSDP_WINDOW_BASE
),
LO_RSDP_WINDOW_SIZE
);
if
(
rsdp
)
return
rsdp
;
/*
* Region 2) Search upper memory: 16-byte boundaries in E0000h-F0000h
*/
rsdp
=
acpi_tb_scan_memory_for_rsdp
(
__va
(
HI_RSDP_WINDOW_BASE
),
HI_RSDP_WINDOW_SIZE
);
if
(
rsdp
)
return
rsdp
;
printk
(
KERN_ERR
"ACPI: System description tables not found
\n
"
);
return
NULL
;
}
/*
* Temporarily use the virtual area starting from FIX_IO_APIC_BASE_END,
* to map the target physical address. The problem is that set_fixmap()
* provides a single page, and it is possible that the page is not
* sufficient.
* By using this area, we can map up to MAX_IO_APICS pages temporarily,
* i.e. until the next __va_range() call.
*
* Important Safety Note: The fixed I/O APIC page numbers are *subtracted*
* from the fixed base. That's why we start at FIX_IO_APIC_BASE_END and
* count idx down while incrementing the phys address.
*/
static
__init
char
*
__va_range
(
unsigned
long
phys
,
unsigned
long
size
)
{
unsigned
long
base
,
offset
,
mapped_size
;
int
idx
;
offset
=
phys
&
(
PAGE_SIZE
-
1
);
mapped_size
=
PAGE_SIZE
-
offset
;
set_fixmap
(
FIX_IO_APIC_BASE_END
,
phys
);
base
=
fix_to_virt
(
FIX_IO_APIC_BASE_END
);
dprintk
(
"__va_range(0x%lx, 0x%lx): idx=%d mapped at %lx
\n
"
,
phys
,
size
,
FIX_IO_APIC_BASE_END
,
base
);
/*
* Most cases can be covered by the below.
*/
idx
=
FIX_IO_APIC_BASE_END
;
while
(
mapped_size
<
size
)
{
if
(
--
idx
<
FIX_IO_APIC_BASE_0
)
return
0
;
/* cannot handle this */
phys
+=
PAGE_SIZE
;
set_fixmap
(
idx
,
phys
);
mapped_size
+=
PAGE_SIZE
;
}
return
((
unsigned
char
*
)
base
+
offset
);
}
static
int
__init
acpi_tables_init
(
void
)
{
int
result
=
-
ENODEV
;
acpi_table_header
*
header
=
NULL
;
struct
acpi_table_rsdp
*
rsdp
=
NULL
;
struct
acpi_table_rsdt
*
rsdt
=
NULL
;
struct
acpi_table_rsdt
saved_rsdt
;
int
tables
=
0
;
int
type
=
0
;
int
i
=
0
;
rsdp
=
(
struct
acpi_table_rsdp
*
)
acpi_find_root_pointer
();
if
(
!
rsdp
)
return
-
ENODEV
;
printk
(
KERN_INFO
"%.8s v%d [%.6s]
\n
"
,
rsdp
->
signature
,
rsdp
->
revision
,
rsdp
->
oem_id
);
if
(
strncmp
(
rsdp
->
signature
,
RSDP_SIG
,
strlen
(
RSDP_SIG
)))
{
printk
(
KERN_WARNING
"RSDP table signature incorrect
\n
"
);
return
-
EINVAL
;
}
rsdt
=
(
struct
acpi_table_rsdt
*
)
__va_range
(
rsdp
->
rsdt_address
,
sizeof
(
struct
acpi_table_rsdt
));
if
(
!
rsdt
)
{
printk
(
KERN_WARNING
"ACPI: Invalid root system description tables (RSDT)
\n
"
);
return
-
ENODEV
;
}
header
=
&
rsdt
->
header
;
acpi_print_table_header
(
header
);
if
(
strncmp
(
header
->
signature
,
RSDT_SIG
,
strlen
(
RSDT_SIG
)))
{
printk
(
KERN_WARNING
"ACPI: RSDT signature incorrect
\n
"
);
return
-
ENODEV
;
}
/*
* The number of tables is computed by taking the
* size of all entries (header size minus total
* size of RSDT) divided by the size of each entry
* (4-byte table pointers).
*/
tables
=
(
header
->
length
-
sizeof
(
acpi_table_header
))
/
4
;
memcpy
(
&
saved_rsdt
,
rsdt
,
sizeof
(
saved_rsdt
));
if
(
saved_rsdt
.
header
.
length
>
sizeof
(
saved_rsdt
))
{
printk
(
KERN_WARNING
"ACPI: Too big length in RSDT: %d
\n
"
,
saved_rsdt
.
header
.
length
);
return
-
ENODEV
;
}
for
(
i
=
0
;
i
<
tables
;
i
++
)
{
/* Map in header, then map in full table length. */
header
=
(
acpi_table_header
*
)
__va_range
(
saved_rsdt
.
entry
[
i
],
sizeof
(
acpi_table_header
));
if
(
!
header
)
break
;
header
=
(
acpi_table_header
*
)
__va_range
(
saved_rsdt
.
entry
[
i
],
header
->
length
);
if
(
!
header
)
break
;
acpi_print_table_header
(
header
);
if
(
acpi_checksum
(
header
,
header
->
length
))
{
printk
(
KERN_WARNING
"ACPI %s has invalid checksum
\n
"
,
acpi_table_signatures
[
i
]);
continue
;
}
for
(
type
=
0
;
type
<
ACPI_TABLE_COUNT
;
type
++
)
if
(
!
strncmp
((
char
*
)
&
header
->
signature
,
acpi_table_signatures
[
type
],
strlen
(
acpi_table_signatures
[
type
])))
break
;
if
(
type
>=
ACPI_TABLE_COUNT
)
{
printk
(
KERN_WARNING
"ACPI: Unsupported table %.4s
\n
"
,
header
->
signature
);
continue
;
}
if
(
!
acpi_boot_ops
[
type
])
continue
;
result
=
acpi_boot_ops
[
type
]
(
header
,
(
unsigned
long
)
saved_rsdt
.
entry
[
i
]);
}
return
result
;
}
static
int
total_cpus
__initdata
=
0
;
int
have_acpi_tables
;
extern
void
__init
MP_processor_info
(
struct
mpc_config_processor
*
);
static
void
__init
acpi_parse_lapic
(
struct
acpi_table_lapic
*
local_apic
)
{
struct
mpc_config_processor
proc_entry
;
int
ix
=
0
;
if
(
!
local_apic
)
return
;
printk
(
KERN_INFO
"LAPIC (acpi_id[0x%04x] id[0x%x] enabled[%d])
\n
"
,
local_apic
->
acpi_id
,
local_apic
->
id
,
local_apic
->
flags
.
enabled
);
printk
(
KERN_INFO
"CPU %d (0x%02x00)"
,
total_cpus
,
local_apic
->
id
);
if
(
local_apic
->
flags
.
enabled
)
{
printk
(
" enabled"
);
ix
=
local_apic
->
id
;
if
(
ix
>=
MAX_APICS
)
{
printk
(
KERN_WARNING
"Processor #%d INVALID - (Max ID: %d).
\n
"
,
ix
,
MAX_APICS
);
return
;
}
/*
* Fill in the info we want to save. Not concerned about
* the processor ID. Processor features aren't present in
* the table.
*/
proc_entry
.
mpc_type
=
MP_PROCESSOR
;
proc_entry
.
mpc_apicid
=
local_apic
->
id
;
proc_entry
.
mpc_cpuflag
=
CPU_ENABLED
;
if
(
proc_entry
.
mpc_apicid
==
boot_cpu_physical_apicid
)
{
printk
(
" (BSP)"
);
proc_entry
.
mpc_cpuflag
|=
CPU_BOOTPROCESSOR
;
}
proc_entry
.
mpc_cpufeature
=
(
boot_cpu_data
.
x86
<<
8
)
|
(
boot_cpu_data
.
x86_model
<<
4
)
|
boot_cpu_data
.
x86_mask
;
proc_entry
.
mpc_featureflag
=
boot_cpu_data
.
x86_capability
[
0
];
proc_entry
.
mpc_reserved
[
0
]
=
0
;
proc_entry
.
mpc_reserved
[
1
]
=
0
;
proc_entry
.
mpc_apicver
=
0x10
;
/* integrated APIC */
MP_processor_info
(
&
proc_entry
);
}
else
{
printk
(
" disabled"
);
}
printk
(
"
\n
"
);
total_cpus
++
;
return
;
}
static
void
__init
acpi_parse_ioapic
(
struct
acpi_table_ioapic
*
ioapic
)
{
if
(
!
ioapic
)
return
;
printk
(
KERN_INFO
"IOAPIC (id[0x%x] address[0x%x] global_irq_base[0x%x])
\n
"
,
ioapic
->
id
,
ioapic
->
address
,
ioapic
->
global_irq_base
);
if
(
nr_ioapics
>=
MAX_IO_APICS
)
{
printk
(
KERN_WARNING
"Max # of I/O APICs (%d) exceeded (found %d).
\n
"
,
MAX_IO_APICS
,
nr_ioapics
);
/* panic("Recompile kernel with bigger MAX_IO_APICS!\n"); */
}
}
/* Interrupt source overrides inform the machine about exceptions
to the normal "PIC" mode interrupt routing */
static
void
__init
acpi_parse_int_src_ovr
(
struct
acpi_table_int_src_ovr
*
intsrc
)
{
if
(
!
intsrc
)
return
;
printk
(
KERN_INFO
"INT_SRC_OVR (bus[%d] irq[0x%x] global_irq[0x%x] polarity[0x%x] trigger[0x%x])
\n
"
,
intsrc
->
bus
,
intsrc
->
bus_irq
,
intsrc
->
global_irq
,
intsrc
->
flags
.
polarity
,
intsrc
->
flags
.
trigger
);
}
/*
* At this point, we look at the interrupt assignment entries in the MPS
* table.
*/
static
void
__init
acpi_parse_nmi_src
(
struct
acpi_table_nmi_src
*
nmisrc
)
{
if
(
!
nmisrc
)
return
;
printk
(
KERN_INFO
"NMI_SRC (polarity[0x%x] trigger[0x%x] global_irq[0x%x])
\n
"
,
nmisrc
->
flags
.
polarity
,
nmisrc
->
flags
.
trigger
,
nmisrc
->
global_irq
);
}
static
void
__init
acpi_parse_lapic_nmi
(
struct
acpi_table_lapic_nmi
*
localnmi
)
{
if
(
!
localnmi
)
return
;
printk
(
KERN_INFO
"LAPIC_NMI (acpi_id[0x%04x] polarity[0x%x] trigger[0x%x] lint[0x%x])
\n
"
,
localnmi
->
acpi_id
,
localnmi
->
flags
.
polarity
,
localnmi
->
flags
.
trigger
,
localnmi
->
lint
);
}
static
void
__init
acpi_parse_lapic_addr_ovr
(
struct
acpi_table_lapic_addr_ovr
*
lapic_addr_ovr
)
{
if
(
!
lapic_addr_ovr
)
return
;
printk
(
KERN_INFO
"LAPIC_ADDR_OVR (address[0x%lx])
\n
"
,
(
unsigned
long
)
lapic_addr_ovr
->
address
);
}
static
void
__init
acpi_parse_plat_int_src
(
struct
acpi_table_plat_int_src
*
plintsrc
)
{
if
(
!
plintsrc
)
return
;
printk
(
KERN_INFO
"PLAT_INT_SRC (polarity[0x%x] trigger[0x%x] type[0x%x] id[0x%04x] eid[0x%x] iosapic_vector[0x%x] global_irq[0x%x]
\n
"
,
plintsrc
->
flags
.
polarity
,
plintsrc
->
flags
.
trigger
,
plintsrc
->
type
,
plintsrc
->
id
,
plintsrc
->
eid
,
plintsrc
->
iosapic_vector
,
plintsrc
->
global_irq
);
}
static
int
__init
acpi_parse_madt
(
acpi_table_header
*
header
,
unsigned
long
phys
)
{
struct
acpi_table_madt
*
madt
;
acpi_madt_entry_header
*
entry_header
;
int
table_size
;
madt
=
(
struct
acpi_table_madt
*
)
__va_range
(
phys
,
header
->
length
);
if
(
!
madt
)
return
-
EINVAL
;
table_size
=
(
int
)
(
header
->
length
-
sizeof
(
*
madt
));
entry_header
=
(
acpi_madt_entry_header
*
)
((
void
*
)
madt
+
sizeof
(
*
madt
));
while
(
entry_header
&&
(
table_size
>
0
))
{
switch
(
entry_header
->
type
)
{
case
ACPI_MADT_LAPIC
:
acpi_parse_lapic
((
struct
acpi_table_lapic
*
)
entry_header
);
break
;
case
ACPI_MADT_IOAPIC
:
acpi_parse_ioapic
((
struct
acpi_table_ioapic
*
)
entry_header
);
break
;
case
ACPI_MADT_INT_SRC_OVR
:
acpi_parse_int_src_ovr
((
struct
acpi_table_int_src_ovr
*
)
entry_header
);
break
;
case
ACPI_MADT_NMI_SRC
:
acpi_parse_nmi_src
((
struct
acpi_table_nmi_src
*
)
entry_header
);
break
;
case
ACPI_MADT_LAPIC_NMI
:
acpi_parse_lapic_nmi
((
struct
acpi_table_lapic_nmi
*
)
entry_header
);
break
;
case
ACPI_MADT_LAPIC_ADDR_OVR
:
acpi_parse_lapic_addr_ovr
((
struct
acpi_table_lapic_addr_ovr
*
)
entry_header
);
break
;
case
ACPI_MADT_PLAT_INT_SRC
:
acpi_parse_plat_int_src
((
struct
acpi_table_plat_int_src
*
)
entry_header
);
break
;
default:
printk
(
KERN_WARNING
"Unsupported MADT entry type 0x%x
\n
"
,
entry_header
->
type
);
break
;
}
table_size
-=
entry_header
->
length
;
entry_header
=
(
acpi_madt_entry_header
*
)
((
void
*
)
entry_header
+
entry_header
->
length
);
}
if
(
!
total_cpus
)
{
printk
(
"ACPI: No Processors found in the APCI table.
\n
"
);
return
-
EINVAL
;
}
printk
(
KERN_INFO
"%d CPUs total
\n
"
,
total_cpus
);
if
(
madt
->
lapic_address
)
mp_lapic_addr
=
madt
->
lapic_address
;
else
mp_lapic_addr
=
APIC_DEFAULT_PHYS_BASE
;
printk
(
KERN_INFO
"Local APIC address %x
\n
"
,
madt
->
lapic_address
);
return
0
;
}
/*
* Configure the processor info using MADT in the ACPI tables. If we fail to
* configure that, then we use the MPS tables.
*/
void
__init
acpi_boot_init
(
void
)
{
memset
(
&
acpi_boot_ops
,
0
,
sizeof
(
acpi_boot_ops
));
acpi_boot_ops
[
ACPI_APIC
]
=
acpi_parse_madt
;
/*
* Only do this when requested, either because of CPU/Bios type or from the command line
*/
if
(
!
acpi_tables_init
())
acpi_lapic
=
1
;
}
arch/i386/kernel/acpi/acpitable.h
0 → 100644
View file @
6f982794
/*
* acpitable.c - IA32-specific ACPI boot-time initialization (Revision: 1)
*
* Copyright (C) 1999 Andrew Henroid
* Copyright (C) 2001 Richard Schaal
* Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
* Copyright (C) 2001 Jun Nakajima <jun.nakajima@intel.com>
* Copyright (C) 2001 Arjan van de Ven <arjanv@redhat.com>
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* 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
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* $Id: acpitable.h,v 1.3 2001/11/03 22:41:34 fenrus Exp $
*/
/*
* The following codes are cut&pasted from drivers/acpi. Part of the code
* there can be not updated or delivered yet.
* To avoid conflicts when CONFIG_ACPI is defined, the following codes are
* modified so that they are self-contained in this file.
* -- jun
*/
#ifndef _HEADER_ACPITABLE_H_
#define _HEADER_ACPITABLE_H_
#define dprintk printk
typedef
unsigned
int
ACPI_TBLPTR
;
typedef
struct
{
/* ACPI common table header */
char
signature
[
4
];
/* identifies type of table */
u32
length
;
/* length of table,
in bytes, * including header */
u8
revision
;
/* specification minor version # */
u8
checksum
;
/* to make sum of entire table == 0 */
char
oem_id
[
6
];
/* OEM identification */
char
oem_table_id
[
8
];
/* OEM table identification */
u32
oem_revision
;
/* OEM revision number */
char
asl_compiler_id
[
4
];
/* ASL compiler vendor ID */
u32
asl_compiler_revision
;
/* ASL compiler revision number */
}
acpi_table_header
__attribute__
((
packed
));;
enum
{
ACPI_APIC
=
0
,
ACPI_BOOT
,
ACPI_DBGP
,
ACPI_DSDT
,
ACPI_ECDT
,
ACPI_ETDT
,
ACPI_FACP
,
ACPI_FACS
,
ACPI_OEMX
,
ACPI_PSDT
,
ACPI_SBST
,
ACPI_SLIT
,
ACPI_SPCR
,
ACPI_SRAT
,
ACPI_SSDT
,
ACPI_SPMI
,
ACPI_XSDT
,
ACPI_TABLE_COUNT
};
static
char
*
acpi_table_signatures
[
ACPI_TABLE_COUNT
]
=
{
"APIC"
,
"BOOT"
,
"DBGP"
,
"DSDT"
,
"ECDT"
,
"ETDT"
,
"FACP"
,
"FACS"
,
"OEM"
,
"PSDT"
,
"SBST"
,
"SLIT"
,
"SPCR"
,
"SRAT"
,
"SSDT"
,
"SPMI"
,
"XSDT"
};
struct
acpi_table_madt
{
acpi_table_header
header
;
u32
lapic_address
;
struct
{
u32
pcat_compat
:
1
;
u32
reserved
:
31
;
}
flags
__attribute__
((
packed
));
}
__attribute__
((
packed
));;
enum
{
ACPI_MADT_LAPIC
=
0
,
ACPI_MADT_IOAPIC
,
ACPI_MADT_INT_SRC_OVR
,
ACPI_MADT_NMI_SRC
,
ACPI_MADT_LAPIC_NMI
,
ACPI_MADT_LAPIC_ADDR_OVR
,
ACPI_MADT_IOSAPIC
,
ACPI_MADT_LSAPIC
,
ACPI_MADT_PLAT_INT_SRC
,
ACPI_MADT_ENTRY_COUNT
};
#define RSDP_SIG "RSD PTR "
#define RSDT_SIG "RSDT"
#define ACPI_DEBUG_PRINT(pl)
#define ACPI_MEMORY_MODE 0x01
#define ACPI_LOGICAL_ADDRESSING 0x00
#define ACPI_PHYSICAL_ADDRESSING 0x01
#define LO_RSDP_WINDOW_BASE 0
/* Physical Address */
#define HI_RSDP_WINDOW_BASE 0xE0000
/* Physical Address */
#define LO_RSDP_WINDOW_SIZE 0x400
#define HI_RSDP_WINDOW_SIZE 0x20000
#define RSDP_SCAN_STEP 16
#define RSDP_CHECKSUM_LENGTH 20
typedef
int
(
*
acpi_table_handler
)
(
acpi_table_header
*
header
,
unsigned
long
);
struct
acpi_table_rsdp
{
char
signature
[
8
];
u8
checksum
;
char
oem_id
[
6
];
u8
revision
;
u32
rsdt_address
;
}
__attribute__
((
packed
));
struct
acpi_table_rsdt
{
acpi_table_header
header
;
u32
entry
[
ACPI_TABLE_COUNT
];
}
__attribute__
((
packed
));
typedef
struct
{
u8
type
;
u8
length
;
}
acpi_madt_entry_header
__attribute__
((
packed
));
typedef
struct
{
u16
polarity
:
2
;
u16
trigger
:
2
;
u16
reserved
:
12
;
}
acpi_madt_int_flags
__attribute__
((
packed
));
struct
acpi_table_lapic
{
acpi_madt_entry_header
header
;
u8
acpi_id
;
u8
id
;
struct
{
u32
enabled
:
1
;
u32
reserved
:
31
;
}
flags
__attribute__
((
packed
));
}
__attribute__
((
packed
));
struct
acpi_table_ioapic
{
acpi_madt_entry_header
header
;
u8
id
;
u8
reserved
;
u32
address
;
u32
global_irq_base
;
}
__attribute__
((
packed
));
struct
acpi_table_int_src_ovr
{
acpi_madt_entry_header
header
;
u8
bus
;
u8
bus_irq
;
u32
global_irq
;
acpi_madt_int_flags
flags
;
}
__attribute__
((
packed
));
struct
acpi_table_nmi_src
{
acpi_madt_entry_header
header
;
acpi_madt_int_flags
flags
;
u32
global_irq
;
}
__attribute__
((
packed
));
struct
acpi_table_lapic_nmi
{
acpi_madt_entry_header
header
;
u8
acpi_id
;
acpi_madt_int_flags
flags
;
u8
lint
;
}
__attribute__
((
packed
));
struct
acpi_table_lapic_addr_ovr
{
acpi_madt_entry_header
header
;
u8
reserved
[
2
];
u64
address
;
}
__attribute__
((
packed
));
struct
acpi_table_iosapic
{
acpi_madt_entry_header
header
;
u8
id
;
u8
reserved
;
u32
global_irq_base
;
u64
address
;
}
__attribute__
((
packed
));
struct
acpi_table_lsapic
{
acpi_madt_entry_header
header
;
u8
acpi_id
;
u8
id
;
u8
eid
;
u8
reserved
[
3
];
struct
{
u32
enabled
:
1
;
u32
reserved
:
31
;
}
flags
;
}
__attribute__
((
packed
));
struct
acpi_table_plat_int_src
{
acpi_madt_entry_header
header
;
acpi_madt_int_flags
flags
;
u8
type
;
u8
id
;
u8
eid
;
u8
iosapic_vector
;
u32
global_irq
;
u32
reserved
;
}
__attribute__
((
packed
));
/*
* ACPI Table Descriptor. One per ACPI table
*/
typedef
struct
acpi_table_desc
{
struct
acpi_table_desc
*
prev
;
struct
acpi_table_desc
*
next
;
struct
acpi_table_desc
*
installed_desc
;
acpi_table_header
*
pointer
;
void
*
base_pointer
;
u8
*
aml_pointer
;
u64
physical_address
;
u32
aml_length
;
u32
length
;
u32
count
;
u16
table_id
;
u8
type
;
u8
allocation
;
u8
loaded_into_namespace
;
}
acpi_table_desc
__attribute__
((
packed
));;
#endif
arch/i386/kernel/setup.c
View file @
6f982794
...
...
@@ -61,7 +61,12 @@ struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
unsigned
long
mmu_cr4_features
;
EXPORT_SYMBOL_GPL
(
mmu_cr4_features
);
int
acpi_disabled
__initdata
=
0
;
#ifdef CONFIG_ACPI_HT_ONLY
int
acpi_disabled
=
1
;
#else
int
acpi_disabled
=
0
;
#endif
EXPORT_SYMBOL
(
acpi_disabled
);
int
MCA_bus
;
/* for MCA, but anyone else can use it if they want */
...
...
@@ -515,6 +520,10 @@ static void __init parse_cmdline_early (char ** cmdline_p)
if
(
c
==
' '
&&
!
memcmp
(
from
,
"acpi=off"
,
8
))
acpi_disabled
=
1
;
/* "acpismp=force" turns on ACPI again */
else
if
(
!
memcmp
(
from
,
"acpismp=force"
,
14
))
acpi_disabled
=
0
;
/*
* highmem=size forces highmem to be exactly 'size' bytes.
* This works even on boxes that have no highmem otherwise.
...
...
drivers/acpi/Kconfig
View file @
6f982794
...
...
@@ -49,12 +49,12 @@ config ACPI_HT_ONLY
Full ACPI support (CONFIG_ACPI) is preferred. Use this option
only if you wish to limit ACPI's role to processor enumeration.
There is no command-line option to disable this, but the kernel
will fall back to the MPS table if the MADT is not present
.
In this configuration, ACPI defaults to off. It must be enabled
on the command-line with the "acpismp=force" option
.
config ACPI_BOOT
bool
depends on IA64 && (!IA64_HP_SIM || IA64_SGI_SN) || X86 && ACPI && !ACPI_HT_ONLY
|| X86 && ACPI
depends on IA64 && (!IA64_HP_SIM || IA64_SGI_SN) || X86 && ACPI && !ACPI_HT_ONLY
default y
config ACPI_SLEEP
...
...
@@ -135,6 +135,31 @@ config ACPI_NUMA
bool "NUMA support" if NUMA && (IA64 && !IA64_HP_SIM || X86 && ACPI && !ACPI_HT_ONLY && !X86_64)
default y if IA64 && IA64_SGI_SN
config ACPI_ASUS
tristate "ASUS/Medion Laptop Extras"
depends on X86 && ACPI && !ACPI_HT_ONLY
---help---
This driver provides support for extra features of ACPI-compatible
ASUS laptops. As some of Medion laptops are made by ASUS, it may also
support some Medion laptops (such as 9675 for example). It makes all
the extra buttons generate standard ACPI events that go through
/proc/acpi/events, and (on some models) adds support for changing the
display brightness and output, switching the LCD backlight on and off,
and most importantly, allows you to blink those fancy LEDs intended
for reporting mail and wireless status.
All settings are changed via /proc/acpi/asus directory entries. Owner
and group for these entries can be set with asus_uid and asus_gid
parameters.
More information and a userspace daemon for handling the extra buttons
at <http://sourceforge.net/projects/acpi4asus/>.
If you have an ACPI-compatible ASUS laptop, say Y or M here. This
driver is still under development, so if your laptop is unsupported or
something works not quite as expected, please use the mailing list
available on the above page (acpi4asus-user@lists.sourceforge.net)
config ACPI_TOSHIBA
tristate "Toshiba Laptop Extras"
depends on X86 && ACPI && !ACPI_HT_ONLY
...
...
drivers/acpi/Makefile
View file @
6f982794
...
...
@@ -44,5 +44,6 @@ obj-$(CONFIG_ACPI_THERMAL) += thermal.o
obj-$(CONFIG_ACPI_SYSTEM)
+=
system.o event.o
obj-$(CONFIG_ACPI_DEBUG)
+=
debug.o
obj-$(CONFIG_ACPI_NUMA)
+=
numa.o
obj-$(CONFIG_ACPI_ASUS)
+=
asus_acpi.o
obj-$(CONFIG_ACPI_TOSHIBA)
+=
toshiba_acpi.o
obj-$(CONFIG_ACPI_BUS)
+=
scan.o
drivers/acpi/asus_acpi.c
0 → 100644
View file @
6f982794
/*
* asus_acpi.c - Asus Laptop ACPI Extras
*
*
* Copyright (C) 2002, 2003 Julien Lerouge, Karol Kozimor
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* The development page for this driver is located at
* http://sourceforge.net/projects/acpi4asus/
*
* Credits:
* Johann Wiesner - Small compile fixes
* John Belmonte - ACPI code for Toshiba laptop was a good starting point.
*
* TODO
* add Fn key status
* Add mode selection on module loading (parameter) -> still necessary ?
* Complete display switching -- may require dirty hacks?
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <acpi/acpi_drivers.h>
#include <acpi/acpi_bus.h>
#define ASUS_ACPI_VERSION "0.24a"
#define PROC_ASUS "asus" //the directory
#define PROC_MLED "mled"
#define PROC_WLED "wled"
#define PROC_INFOS "info"
#define PROC_LCD "lcd"
#define PROC_BRN "brn"
#define PROC_DISP "disp"
#define ACPI_HOTK_NAME "Asus Laptop ACPI Extras Driver"
#define ACPI_HOTK_CLASS "hotkey"
#define ACPI_HOTK_DEVICE_NAME "Hotkey"
#define ACPI_HOTK_HID "ATK0100"
/*
* Some events we use, same for all Asus
*/
#define BR_UP 0x10
#define BR_DOWN 0x20
/*
* Flags for hotk status
*/
#define MLED_ON 0x01 //is MLED ON ?
#define WLED_ON 0x02
MODULE_AUTHOR
(
"Julien Lerouge, Karol Kozimor"
);
MODULE_DESCRIPTION
(
ACPI_HOTK_NAME
);
MODULE_LICENSE
(
"GPL"
);
static
uid_t
asus_uid
=
0
;
static
gid_t
asus_gid
=
0
;
MODULE_PARM
(
asus_uid
,
"i"
);
MODULE_PARM_DESC
(
uid
,
"UID for entries in /proc/acpi/asus.
\n
"
);
MODULE_PARM
(
asus_gid
,
"i"
);
MODULE_PARM_DESC
(
gid
,
"GID for entries in /proc/acpi/asus.
\n
"
);
/* For each model, all features implemented */
struct
model_data
{
char
*
name
;
//name of the laptop
char
*
mt_mled
;
//method to handle mled
char
*
mled_status
;
//node to handle mled reading
char
*
mt_wled
;
//method to handle wled
char
*
wled_status
;
//node to handle wled reading
char
*
mt_lcd_switch
;
//method to turn LCD ON/OFF
char
*
lcd_status
;
//node to read LCD panel state
char
*
brightness_up
;
//method to set brightness up
char
*
brightness_down
;
//guess what ?
char
*
brightness_set
;
//method to set absolute brightness
char
*
brightness_get
;
//method to get absolute brightness
char
*
brightness_status
;
//node to get brightness
char
*
display_set
;
//method to set video output
char
*
display_get
;
//method to get video output
};
/*
* This is the main structure, we can use it to store anything interesting
* about the hotk device
*/
struct
asus_hotk
{
struct
acpi_device
*
device
;
//the device we are in
acpi_handle
handle
;
//the handle of the hotk device
char
status
;
//status of the hotk, for LEDs, ...
struct
model_data
*
methods
;
//methods available on the laptop
u8
brightness
;
//brighness level
enum
{
L2X
=
0
,
//L200D -> TODO check Q11 (Fn+F8)
// Calling this method simply hang the
// computer, ISMI method hangs the laptop.
L3X
,
//L3C
L3D
,
//L3400D
M2X
,
//M2400E
S1X
,
//S1300A -> TODO special keys do not work ?
D1X
,
//D1
L1X
,
//L1400B
A1X
,
//A1340D, A1300F
J1X
,
//S200 (J1)
//TODO A1370D does not seems to have a ATK device
// L8400 model doesn't have ATK
END_MODEL
,
}
model
;
//Models currently supported
u16
event_count
[
128
];
//count for each event TODO make this better
};
/* Here we go */
#define L3X_PREFIX "\\_SB.PCI0.PX40.ECD0."
#define S1X_PREFIX "\\_SB.PCI0.PX40."
#define L1X_PREFIX S1X_PREFIX
#define A1X_PREFIX "\\_SB.PCI0.ISA.EC0."
#define J1X_PREFIX A1X_PREFIX
static
struct
model_data
model_conf
[
END_MODEL
]
=
{
/*
* name| mled |mled read| wled |wled read| lcd sw |lcd read |
* br up|br down | br set | br read | br status|set disp | get disp
*
* br set and read shall be in hotk device !
* same for set disp
*
* TODO I have seen a SWBX and AIBX method on some models, like L1400B,
* it seems to be a kind of switch, but what for ?
*
*/
{
"L2X"
,
"MLED"
,
"
\\
SGP6"
,
"WLED"
,
"
\\
RCP3"
,
"
\\
Q10"
,
"
\\
SGP0"
,
"
\\
Q0E"
,
"
\\
Q0F"
,
NULL
,
NULL
,
NULL
,
"SDSP"
,
"
\\
INFB"
},
{
"L3X"
,
"MLED"
,
NULL
,
"WLED"
,
NULL
,
L3X_PREFIX
"_Q10"
,
"
\\
GL32"
,
L3X_PREFIX
"_Q0F"
,
L3X_PREFIX
"_Q0E"
,
"SPLV"
,
"GPLV"
,
"
\\
BLVL"
,
"SDSP"
,
"
\\
_SB.PCI0.PCI1.VGAC.NMAP"
},
{
"L3D"
,
"MLED"
,
"
\\
MALD"
,
"WLED"
,
NULL
,
"
\\
Q10"
,
"
\\
BKLG"
,
"
\\
Q0E"
,
"
\\
Q0F"
,
"SPLV"
,
"GPLV"
,
"
\\
BLVL"
,
"SDSP"
,
"
\\
INFB"
},
{
"M2X"
,
"MLED"
,
NULL
,
"WLED"
,
NULL
,
"
\\
Q10"
,
"
\\
GP06"
,
"
\\
Q0E"
,
"
\\
Q0F"
,
"SPLV"
,
"GPLV"
,
NULL
,
"SDSP"
,
"
\\
INFB"
},
{
"S1X"
,
"MLED"
,
"
\\
EMLE"
,
"WLED"
,
NULL
,
S1X_PREFIX
"Q10"
,
"
\\
PNOF"
,
S1X_PREFIX
"Q0F"
,
S1X_PREFIX
"Q0E"
,
"SPLV"
,
"GPLV"
,
"
\\
BRIT"
,
NULL
,
NULL
},
{
"D1X"
,
"MLED"
,
NULL
,
NULL
,
NULL
,
"
\\
Q0D"
,
"
\\
GP11"
,
"
\\
Q0C"
,
"
\\
Q0B"
,
NULL
,
NULL
,
"
\\
BLVL"
,
"SDSP"
,
"
\\
INFB"
},
{
"L1X"
,
"MLED"
,
NULL
,
"WLED"
,
NULL
,
L1X_PREFIX
"Q10"
,
"
\\
PNOF"
,
L1X_PREFIX
"Q0F"
,
L1X_PREFIX
"Q0E"
,
"SPLV"
,
"GPLV"
,
"
\\
BRIT"
,
NULL
,
NULL
},
{
"A1X"
,
"MLED"
,
"
\\
MAIL"
,
NULL
,
NULL
,
A1X_PREFIX
"_Q10"
,
"
\\
BKLI"
,
A1X_PREFIX
"_Q0E"
,
A1X_PREFIX
"_Q0F"
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
},
{
"J1X"
,
"MLED"
,
"
\\
MAIL"
,
NULL
,
NULL
,
J1X_PREFIX
"_Q10"
,
"
\\
BKLI"
,
J1X_PREFIX
"_Q0B"
,
J1X_PREFIX
"_Q0A"
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
}
};
/* procdir we use */
static
struct
proc_dir_entry
*
asus_proc_dir
=
NULL
;
/*
* This header is made available to allow proper configuration given model,
* revision number , ... this info cannot go in struct asus_hotk because it is
* available before the hotk
*/
static
struct
acpi_table_header
*
asus_info
=
NULL
;
/*
* The hotkey driver declaration
*/
static
int
asus_hotk_add
(
struct
acpi_device
*
device
);
static
int
asus_hotk_remove
(
struct
acpi_device
*
device
,
int
type
);
static
struct
acpi_driver
asus_hotk_driver
=
{
.
name
=
ACPI_HOTK_NAME
,
.
class
=
ACPI_HOTK_CLASS
,
.
ids
=
ACPI_HOTK_HID
,
.
ops
=
{
.
add
=
asus_hotk_add
,
.
remove
=
asus_hotk_remove
,
},
};
/*
* This function evaluates an ACPI method, given an int as parameter, the
* method is searched within the scope of the handle, can be NULL. The output
* of the method is written is output, which can also be NULL
*
* returns 1 if write is successful, 0 else.
*/
static
int
write_acpi_int
(
acpi_handle
handle
,
const
char
*
method
,
int
val
,
struct
acpi_buffer
*
output
)
{
struct
acpi_object_list
params
;
//list of input parameters (an int here)
union
acpi_object
in_obj
;
//the only param we use
acpi_status
status
;
params
.
count
=
1
;
params
.
pointer
=
&
in_obj
;
in_obj
.
type
=
ACPI_TYPE_INTEGER
;
in_obj
.
integer
.
value
=
val
;
status
=
acpi_evaluate_object
(
handle
,
(
char
*
)
method
,
&
params
,
output
);
return
(
status
==
AE_OK
);
}
static
int
read_acpi_int
(
acpi_handle
handle
,
const
char
*
method
,
int
*
val
)
{
struct
acpi_buffer
output
;
union
acpi_object
out_obj
;
acpi_status
status
;
output
.
length
=
sizeof
(
out_obj
);
output
.
pointer
=
&
out_obj
;
status
=
acpi_evaluate_object
(
handle
,
(
char
*
)
method
,
NULL
,
&
output
);
*
val
=
out_obj
.
integer
.
value
;
return
(
status
==
AE_OK
)
&&
(
out_obj
.
type
==
ACPI_TYPE_INTEGER
);
}
/*
* We write our info in page, we begin at offset off and cannot write more
* than count bytes. We set eof to 1 if we handle those 2 values. We return the
* number of bytes written in page
*/
static
int
proc_read_info
(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
void
*
data
)
{
int
len
=
0
;
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
char
buf
[
16
];
//enough for all info
/*
* We use the easy way, we don't care of off and count, so we don't set eof
* to 1
*/
len
+=
sprintf
(
page
,
ACPI_HOTK_NAME
" "
ASUS_ACPI_VERSION
"
\n
"
);
len
+=
sprintf
(
page
+
len
,
"Model reference : %s
\n
"
,
hotk
->
methods
->
name
);
if
(
asus_info
)
{
snprintf
(
buf
,
5
,
"%s"
,
asus_info
->
signature
);
len
+=
sprintf
(
page
+
len
,
"ACPI signature : %s
\n
"
,
buf
);
snprintf
(
buf
,
16
,
"%d"
,
asus_info
->
length
);
len
+=
sprintf
(
page
+
len
,
"Table length : %s
\n
"
,
buf
);
snprintf
(
buf
,
16
,
"%d"
,
asus_info
->
revision
);
len
+=
sprintf
(
page
+
len
,
"ACPI minor version : %s
\n
"
,
buf
);
snprintf
(
buf
,
16
,
"%d"
,
asus_info
->
checksum
);
len
+=
sprintf
(
page
+
len
,
"Checksum : %s
\n
"
,
buf
);
snprintf
(
buf
,
7
,
"%s"
,
asus_info
->
oem_id
);
len
+=
sprintf
(
page
+
len
,
"OEM identification : %s
\n
"
,
buf
);
snprintf
(
buf
,
9
,
"%s"
,
asus_info
->
oem_table_id
);
len
+=
sprintf
(
page
+
len
,
"OEM table id : %s
\n
"
,
buf
);
snprintf
(
buf
,
16
,
"%x"
,
asus_info
->
oem_revision
);
len
+=
sprintf
(
page
+
len
,
"OEM rev number : 0x%s
\n
"
,
buf
);
snprintf
(
buf
,
5
,
"%s"
,
asus_info
->
asl_compiler_id
);
len
+=
sprintf
(
page
+
len
,
"ASL comp vendor ID : %s
\n
"
,
buf
);
snprintf
(
buf
,
16
,
"%x"
,
asus_info
->
asl_compiler_revision
);
len
+=
sprintf
(
page
+
len
,
"ASL comp rev number: 0x%s
\n
"
,
buf
);
}
return
len
;
}
/*
* proc file handlers
*/
static
int
proc_read_mled
(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
void
*
data
)
{
int
len
=
0
;
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
int
led_status
=
0
;
/*
* We use the easy way, we don't care of off and count, so we don't set eof
* to 1
*/
if
(
hotk
->
methods
->
mled_status
)
{
if
(
read_acpi_int
(
NULL
,
hotk
->
methods
->
mled_status
,
&
led_status
))
len
=
sprintf
(
page
,
"%d
\n
"
,
led_status
);
else
printk
(
KERN_NOTICE
"Asus ACPI: Error reading MLED "
"status
\n
"
);
}
else
{
len
=
sprintf
(
page
,
"%d
\n
"
,
(
hotk
->
status
&
MLED_ON
)
?
1
:
0
);
}
return
len
;
}
static
int
proc_write_mled
(
struct
file
*
file
,
const
char
*
buffer
,
unsigned
long
count
,
void
*
data
)
{
int
value
;
int
led_out
=
0
;
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
/* scan expression. Multiple expressions may be delimited with ; */
if
(
sscanf
(
buffer
,
"%i"
,
&
value
)
==
1
)
led_out
=
~
value
&
1
;
hotk
->
status
=
(
value
)
?
(
hotk
->
status
|
MLED_ON
)
:
(
hotk
->
status
&
~
MLED_ON
);
/* We don't have to check mt_mled exists if we are here :) */
if
(
!
write_acpi_int
(
hotk
->
handle
,
hotk
->
methods
->
mt_mled
,
led_out
,
NULL
))
printk
(
KERN_NOTICE
"Asus ACPI: MLED write failed
\n
"
);
return
count
;
}
/*
* We write our info in page, we begin at offset off and cannot write more
* than count bytes. We set eof to 1 if we handle those 2 values. We return the
* number of bytes written in page
*/
static
int
proc_read_wled
(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
void
*
data
)
{
int
len
=
0
;
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
int
led_status
;
if
(
hotk
->
methods
->
wled_status
)
{
if
(
read_acpi_int
(
NULL
,
hotk
->
methods
->
mled_status
,
&
led_status
))
len
=
sprintf
(
page
,
"%d
\n
"
,
led_status
);
else
printk
(
KERN_NOTICE
"Asus ACPI: Error reading WLED "
"status
\n
"
);
}
else
{
len
=
sprintf
(
page
,
"%d
\n
"
,
(
hotk
->
status
&
WLED_ON
)
?
1
:
0
);
}
return
len
;
}
static
int
proc_write_wled
(
struct
file
*
file
,
const
char
*
buffer
,
unsigned
long
count
,
void
*
data
)
{
int
value
;
int
led_out
=
0
;
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
/* scan expression. Multiple expressions may be delimited with ; */
if
(
sscanf
(
buffer
,
"%i"
,
&
value
)
==
1
)
led_out
=
value
&
1
;
hotk
->
status
=
(
value
)
?
(
hotk
->
status
|
WLED_ON
)
:
(
hotk
->
status
&
~
WLED_ON
);
/* We don't have to check if mt_wled exists if we are here :) */
if
(
!
write_acpi_int
(
hotk
->
handle
,
hotk
->
methods
->
mt_wled
,
led_out
,
NULL
))
printk
(
KERN_NOTICE
"Asus ACPI: WLED write failed
\n
"
);
return
count
;
}
static
int
get_lcd_state
(
struct
asus_hotk
*
hotk
)
{
int
lcd
=
0
;
/* We don't have to check anything, if we are here */
if
(
!
read_acpi_int
(
NULL
,
hotk
->
methods
->
lcd_status
,
&
lcd
))
printk
(
KERN_NOTICE
"Asus ACPI: Error reading LCD status
\n
"
);
if
(
hotk
->
model
==
L2X
)
lcd
=
~
lcd
;
return
(
lcd
&
1
);
}
static
int
proc_read_lcd
(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
void
*
data
)
{
return
sprintf
(
page
,
"%d
\n
"
,
get_lcd_state
((
struct
asus_hotk
*
)
data
));
}
static
int
proc_write_lcd
(
struct
file
*
file
,
const
char
*
buffer
,
unsigned
long
count
,
void
*
data
)
{
int
value
;
int
lcd
=
0
;
acpi_status
status
=
0
;
int
lcd_status
=
0
;
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
/* scan expression. Multiple expressions may be delimited with ; */
if
(
sscanf
(
buffer
,
"%i"
,
&
value
)
==
1
)
lcd
=
value
&
1
;
lcd_status
=
get_lcd_state
(
hotk
);
if
(
lcd_status
!=
lcd
)
{
/* switch */
status
=
acpi_evaluate_object
(
NULL
,
hotk
->
methods
->
mt_lcd_switch
,
NULL
,
NULL
);
if
(
ACPI_FAILURE
(
status
))
printk
(
KERN_NOTICE
"Asus ACPI: Error switching LCD
\n
"
);
}
return
count
;
}
/*
* Change the brightness level
*/
static
void
set_brightness
(
int
value
,
struct
asus_hotk
*
hotk
)
{
acpi_status
status
=
0
;
/* ATKD laptop */
if
(
hotk
->
methods
->
brightness_set
)
{
if
(
!
write_acpi_int
(
hotk
->
handle
,
hotk
->
methods
->
brightness_set
,
value
,
NULL
))
printk
(
KERN_NOTICE
"Asus ACPI: Error changing brightness
\n
"
);
return
;
}
/* HOTK laptop if we are here, act as appropriate */
value
-=
hotk
->
brightness
;
while
(
value
!=
0
)
{
status
=
acpi_evaluate_object
(
NULL
,
(
value
>
0
)
?
hotk
->
methods
->
brightness_up
:
hotk
->
methods
->
brightness_down
,
NULL
,
NULL
);
(
value
>
0
)
?
value
--
:
value
++
;
if
(
ACPI_FAILURE
(
status
))
printk
(
KERN_NOTICE
"Asus ACPI: Error changing brightness
\n
"
);
}
return
;
}
static
int
read_brightness
(
struct
asus_hotk
*
hotk
)
{
int
value
;
if
(
hotk
->
methods
->
brightness_get
)
{
/* ATKD laptop */
if
(
!
read_acpi_int
(
hotk
->
handle
,
hotk
->
methods
->
brightness_get
,
&
value
))
printk
(
KERN_NOTICE
"Asus ACPI: Error reading brightness
\n
"
);
}
else
if
(
hotk
->
methods
->
brightness_status
)
{
/* For D1 for example */
if
(
!
read_acpi_int
(
NULL
,
hotk
->
methods
->
brightness_status
,
&
value
))
printk
(
KERN_NOTICE
"Asus ACPI: Error reading brightness
\n
"
);
}
else
/* HOTK laptop */
value
=
hotk
->
brightness
;
return
value
;
}
static
int
proc_read_brn
(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
void
*
data
)
{
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
return
sprintf
(
page
,
"%d
\n
"
,
read_brightness
(
hotk
));
}
static
int
proc_write_brn
(
struct
file
*
file
,
const
char
*
buffer
,
unsigned
long
count
,
void
*
data
)
{
int
value
;
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
/* scan expression. Multiple expressions may be delimited with ; */
if
(
sscanf
(
buffer
,
"%d"
,
&
value
)
==
1
)
{
value
=
(
0
<
value
)
?
((
15
<
value
)
?
15
:
value
)
:
0
;
/* 0 <= value <= 15 */
set_brightness
(
value
,
hotk
);
}
else
{
printk
(
KERN_NOTICE
"Asus ACPI: Error reading user input
\n
"
);
}
return
count
;
}
static
void
set_display
(
int
value
,
struct
asus_hotk
*
hotk
)
{
/* no sanity check needed for now */
if
(
!
write_acpi_int
(
hotk
->
handle
,
hotk
->
methods
->
display_set
,
value
,
NULL
))
printk
(
KERN_NOTICE
"Asus ACPI: Error setting display
\n
"
);
return
;
}
/*
* Now, *this* one could be more user-friendly, but so far, no-one has
* complained. The significance of bits is the same as in proc_write_disp()
*/
static
int
proc_read_disp
(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
void
*
data
)
{
int
value
=
0
;
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
if
(
!
read_acpi_int
(
hotk
->
handle
,
hotk
->
methods
->
display_get
,
&
value
))
printk
(
KERN_NOTICE
"Asus ACPI: Error reading display status
\n
"
);
return
sprintf
(
page
,
"%d
\n
"
,
value
);
}
/*
* Preliminary support for display switching. As of now: 0x01 should activate
* the LCD output, 0x02 should do for CRT, and 0x04 for TV-Out. Any combination
* (bitwise) of these will suffice. I never actually tested 3 displays hooked up
* simultaneously, so be warned.
*/
static
int
proc_write_disp
(
struct
file
*
file
,
const
char
*
buffer
,
unsigned
long
count
,
void
*
data
)
{
int
value
;
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
/* scan expression. Multiple expressions may be delimited with ; */
if
(
sscanf
(
buffer
,
"%d"
,
&
value
)
==
1
)
set_display
(
value
,
hotk
);
else
{
printk
(
KERN_NOTICE
"Asus ACPI: Error reading user input
\n
"
);
}
return
count
;
}
static
int
asus_hotk_add_fs
(
struct
acpi_device
*
device
)
{
struct
proc_dir_entry
*
proc
;
struct
asus_hotk
*
hotk
=
acpi_driver_data
(
device
);
mode_t
mode
;
/*
* If parameter uid or gid is not changed, keep the default setting for
* our proc entries (-rw-rw-rw-) else, it means we care about security,
* and then set to -rw-rw----
*/
if
((
asus_uid
==
0
)
&&
(
asus_gid
==
0
)){
mode
=
S_IFREG
|
S_IRUGO
|
S_IWUGO
;
}
else
{
mode
=
S_IFREG
|
S_IRUSR
|
S_IRGRP
|
S_IWUSR
|
S_IWGRP
;
}
acpi_device_dir
(
device
)
=
asus_proc_dir
;
if
(
!
acpi_device_dir
(
device
))
return
(
-
ENODEV
);
proc
=
create_proc_entry
(
PROC_INFOS
,
mode
,
acpi_device_dir
(
device
));
if
(
proc
)
{
proc
->
read_proc
=
proc_read_info
;
proc
->
data
=
acpi_driver_data
(
device
);
proc
->
owner
=
THIS_MODULE
;
proc
->
uid
=
asus_uid
;
proc
->
gid
=
asus_gid
;;
}
else
{
printk
(
KERN_NOTICE
" Unable to create "
PROC_INFOS
" fs entry
\n
"
);
}
if
(
hotk
->
methods
->
mt_wled
)
{
proc
=
create_proc_entry
(
PROC_WLED
,
mode
,
acpi_device_dir
(
device
));
if
(
proc
)
{
proc
->
write_proc
=
proc_write_wled
;
proc
->
read_proc
=
proc_read_wled
;
proc
->
data
=
acpi_driver_data
(
device
);
proc
->
owner
=
THIS_MODULE
;
proc
->
uid
=
asus_uid
;
proc
->
gid
=
asus_gid
;;
}
else
{
printk
(
KERN_NOTICE
" Unable to create "
PROC_WLED
" fs entry
\n
"
);
}
}
if
(
hotk
->
methods
->
mt_mled
)
{
proc
=
create_proc_entry
(
PROC_MLED
,
mode
,
acpi_device_dir
(
device
));
if
(
proc
)
{
proc
->
write_proc
=
proc_write_mled
;
proc
->
read_proc
=
proc_read_mled
;
proc
->
data
=
acpi_driver_data
(
device
);
proc
->
owner
=
THIS_MODULE
;
proc
->
uid
=
asus_uid
;
proc
->
gid
=
asus_gid
;;
}
else
{
printk
(
KERN_NOTICE
" Unable to create "
PROC_MLED
" fs entry
\n
"
);
}
}
/*
* We need both read node and write method as LCD switch is also accessible
* from keyboard
*/
if
(
hotk
->
methods
->
mt_lcd_switch
&&
hotk
->
methods
->
lcd_status
)
{
proc
=
create_proc_entry
(
PROC_LCD
,
mode
,
acpi_device_dir
(
device
));
if
(
proc
)
{
proc
->
write_proc
=
proc_write_lcd
;
proc
->
read_proc
=
proc_read_lcd
;
proc
->
data
=
acpi_driver_data
(
device
);
proc
->
owner
=
THIS_MODULE
;
proc
->
uid
=
asus_uid
;
proc
->
gid
=
asus_gid
;;
}
else
{
printk
(
KERN_NOTICE
" Unable to create "
PROC_LCD
" fs entry
\n
"
);
}
}
if
((
hotk
->
methods
->
brightness_up
&&
hotk
->
methods
->
brightness_down
)
||
(
hotk
->
methods
->
brightness_get
&&
hotk
->
methods
->
brightness_get
))
{
proc
=
create_proc_entry
(
PROC_BRN
,
mode
,
acpi_device_dir
(
device
));
if
(
proc
)
{
proc
->
write_proc
=
proc_write_brn
;
proc
->
read_proc
=
proc_read_brn
;
proc
->
data
=
acpi_driver_data
(
device
);
proc
->
owner
=
THIS_MODULE
;
proc
->
uid
=
asus_uid
;
proc
->
gid
=
asus_gid
;;
}
else
{
printk
(
KERN_NOTICE
" Unable to create "
PROC_BRN
" fs entry
\n
"
);
}
}
if
(
hotk
->
methods
->
display_set
)
{
proc
=
create_proc_entry
(
PROC_DISP
,
mode
,
acpi_device_dir
(
device
));
if
(
proc
)
{
proc
->
write_proc
=
proc_write_disp
;
proc
->
read_proc
=
proc_read_disp
;
proc
->
data
=
acpi_driver_data
(
device
);
proc
->
owner
=
THIS_MODULE
;
proc
->
uid
=
asus_uid
;
proc
->
gid
=
asus_gid
;;
}
else
{
printk
(
KERN_NOTICE
" Unable to create "
PROC_DISP
" fs entry
\n
"
);
}
}
return
(
AE_OK
);
}
static
void
asus_hotk_notify
(
acpi_handle
handle
,
u32
event
,
void
*
data
)
{
/* TODO Find a better way to handle events count. Here, in data, we receive
* the hotk, so we can make anything !!
*/
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
if
(
!
hotk
)
return
;
if
((
event
&
~
((
u32
)
BR_UP
))
<
16
)
{
hotk
->
brightness
=
(
event
&
~
((
u32
)
BR_UP
));
}
else
if
((
event
&
~
((
u32
)
BR_DOWN
))
<
16
)
{
hotk
->
brightness
=
(
event
&
~
((
u32
)
BR_DOWN
));
}
acpi_bus_generate_event
(
hotk
->
device
,
event
,
hotk
->
event_count
[
event
%
128
]
++
);
return
;
}
/*
* This function is used to initialize the hotk with right values. In this
* method, we can make all the detection we want, and modify the hotk struct
*/
static
int
asus_hotk_get_info
(
struct
asus_hotk
*
hotk
)
{
struct
acpi_buffer
buffer
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
union
acpi_object
*
model
=
NULL
;
/*
* We have to write 0 on init this far for all ASUS models
*/
if
(
!
write_acpi_int
(
hotk
->
handle
,
"INIT"
,
0
,
&
buffer
))
{
printk
(
KERN_NOTICE
" Hotkey initialization failed
\n
"
);
return
-
ENODEV
;
}
/*
* Here, we also use asus_info to make decision. For example, on INIT
* method, S1X and L1X models both reports to be L84F, but they don't
* have the same methods (L1X has WLED, S1X don't)
*/
model
=
(
union
acpi_object
*
)
buffer
.
pointer
;
if
(
model
->
type
==
ACPI_TYPE_STRING
)
{
printk
(
KERN_NOTICE
" %s model detected, "
,
model
->
string
.
pointer
);
}
hotk
->
model
=
END_MODEL
;
if
(
strncmp
(
model
->
string
.
pointer
,
"L3D"
,
3
)
==
0
)
hotk
->
model
=
L3D
;
/*
* L2B has same settings that L3X, except for GL32, but as
* there is no node to get the LCD status, and as GL32 is never
* used anywhere else, I assume it's safe, even if lcd get is
* broken for this model (TODO fix it ?)
*/
else
if
(
strncmp
(
model
->
string
.
pointer
,
"L3"
,
2
)
==
0
||
strncmp
(
model
->
string
.
pointer
,
"L2B"
,
3
)
==
0
)
hotk
->
model
=
L3X
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"M2"
,
2
)
==
0
)
hotk
->
model
=
M2X
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"L2"
,
2
)
==
0
)
hotk
->
model
=
L2X
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"L8"
,
2
)
==
0
)
/* S1300A reports L84F, but L1400B too */
if
(
strncmp
(
asus_info
->
oem_table_id
,
"L1"
,
2
)
==
0
)
hotk
->
model
=
L1X
;
else
hotk
->
model
=
S1X
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"D1"
,
2
)
==
0
)
hotk
->
model
=
D1X
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"A1"
,
2
)
==
0
)
hotk
->
model
=
A1X
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"J1"
,
2
)
==
0
)
hotk
->
model
=
J1X
;
if
(
hotk
->
model
==
END_MODEL
)
{
/* By default use the same values, as I don't know others */
printk
(
"unsupported, trying default values, contact the "
"developers
\n
"
);
hotk
->
model
=
L2X
;
}
else
{
printk
(
"supported
\n
"
);
}
hotk
->
methods
=
&
model_conf
[
hotk
->
model
];
acpi_os_free
(
model
);
return
AE_OK
;
}
static
int
asus_hotk_check
(
struct
asus_hotk
*
hotk
)
{
int
result
=
0
;
if
(
!
hotk
)
return
(
-
EINVAL
);
result
=
acpi_bus_get_status
(
hotk
->
device
);
if
(
result
)
return
(
result
);
if
(
hotk
->
device
->
status
.
present
)
{
result
=
asus_hotk_get_info
(
hotk
);
}
else
{
printk
(
KERN_NOTICE
" Hotkey device not present, aborting
\n
"
);
return
(
-
EINVAL
);
}
return
(
result
);
}
static
int
asus_hotk_add
(
struct
acpi_device
*
device
)
{
struct
asus_hotk
*
hotk
=
NULL
;
acpi_status
status
=
AE_OK
;
int
result
;
if
(
!
device
)
return
(
-
EINVAL
);
hotk
=
(
struct
asus_hotk
*
)
kmalloc
(
sizeof
(
struct
asus_hotk
),
GFP_KERNEL
);
if
(
!
hotk
)
return
(
-
ENOMEM
);
memset
(
hotk
,
0
,
sizeof
(
struct
asus_hotk
));
hotk
->
handle
=
device
->
handle
;
sprintf
(
acpi_device_name
(
device
),
"%s"
,
ACPI_HOTK_DEVICE_NAME
);
sprintf
(
acpi_device_class
(
device
),
"%s"
,
ACPI_HOTK_CLASS
);
acpi_driver_data
(
device
)
=
hotk
;
hotk
->
device
=
device
;
result
=
asus_hotk_check
(
hotk
);
if
(
result
)
goto
end
;
result
=
asus_hotk_add_fs
(
device
);
if
(
result
)
goto
end
;
/*
* We install the handler, it will receive the hotk in parameter, so, we
* could add other data to the hotk struct
*/
status
=
acpi_install_notify_handler
(
hotk
->
handle
,
ACPI_SYSTEM_NOTIFY
,
asus_hotk_notify
,
hotk
);
if
(
ACPI_FAILURE
(
status
))
{
printk
(
KERN_NOTICE
" Error installing notify handler
\n
"
);
}
else
{
printk
(
KERN_DEBUG
" Notify Handler installed successfully
\n
"
);
}
/* For HOTK laptops: init the hotk->brightness value */
if
((
!
hotk
->
methods
->
brightness_get
)
&&
(
!
hotk
->
methods
->
brightness_status
)
&&
(
hotk
->
methods
->
brightness_up
&&
hotk
->
methods
->
brightness_down
))
{
status
=
acpi_evaluate_object
(
NULL
,
hotk
->
methods
->
brightness_down
,
NULL
,
NULL
);
if
(
ACPI_FAILURE
(
status
))
printk
(
KERN_NOTICE
" Error changing brightness
\n
"
);
status
=
acpi_evaluate_object
(
NULL
,
hotk
->
methods
->
brightness_up
,
NULL
,
NULL
);
if
(
ACPI_FAILURE
(
status
))
printk
(
KERN_NOTICE
" Error changing brightness
\n
"
);
}
end:
if
(
result
)
{
kfree
(
hotk
);
}
return
(
result
);
}
static
int
asus_hotk_remove
(
struct
acpi_device
*
device
,
int
type
)
{
acpi_status
status
=
0
;
struct
asus_hotk
*
hotk
=
NULL
;
if
(
!
device
||
!
acpi_driver_data
(
device
))
return
(
-
EINVAL
);
hotk
=
(
struct
asus_hotk
*
)
acpi_driver_data
(
device
);
status
=
acpi_remove_notify_handler
(
hotk
->
handle
,
ACPI_SYSTEM_NOTIFY
,
asus_hotk_notify
);
if
(
ACPI_FAILURE
(
status
))
printk
(
KERN_NOTICE
"Error removing notify handler
\n
"
);
kfree
(
hotk
);
return
(
0
);
}
static
int
__init
asus_acpi_init
(
void
)
{
int
result
=
0
;
acpi_status
status
=
0
;
struct
acpi_buffer
dsdt
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
printk
(
KERN_NOTICE
"Asus Laptop ACPI Extras version %s
\n
"
,
ASUS_ACPI_VERSION
);
/*
* Here is the code to know the model we are running on. We need to
* know this before calling the acpi_bus_register_driver function, in
* case the HID for the laptop we are running on is different from
* ACPI_HOTK_HID, which I have never seen yet :)
*
* This information is then available in the global var asus_info
*/
status
=
acpi_get_table
(
ACPI_TABLE_DSDT
,
1
,
&
dsdt
);
if
(
ACPI_FAILURE
(
status
))
{
printk
(
KERN_NOTICE
" Couldn't get the DSDT table header
\n
"
);
}
else
{
asus_info
=
(
struct
acpi_table_header
*
)
dsdt
.
pointer
;
}
asus_proc_dir
=
proc_mkdir
(
PROC_ASUS
,
acpi_root_dir
);
if
(
!
asus_proc_dir
)
return
(
-
ENODEV
);
asus_proc_dir
->
owner
=
THIS_MODULE
;
result
=
acpi_bus_register_driver
(
&
asus_hotk_driver
);
if
(
result
<
0
)
{
printk
(
KERN_NOTICE
" Error registering "
ACPI_HOTK_NAME
"
\n
"
);
remove_proc_entry
(
PROC_ASUS
,
acpi_root_dir
);
return
(
-
ENODEV
);
}
return
(
0
);
}
static
void
__exit
asus_acpi_exit
(
void
)
{
acpi_bus_unregister_driver
(
&
asus_hotk_driver
);
remove_proc_entry
(
PROC_ASUS
,
acpi_root_dir
);
acpi_os_free
(
asus_info
);
return
;
}
module_init
(
asus_acpi_init
);
module_exit
(
asus_acpi_exit
);
drivers/pci/hotplug/acpiphp.h
View file @
6f982794
...
...
@@ -5,8 +5,8 @@
* Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (c) 2001 IBM Corp.
* Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
* Copyright (c) 2002
Takayoshi Kochi (t-kouchi@c
q.jp.nec.com)
* Copyright (c) 2002 NEC Corporation
* Copyright (c) 2002
,2003 Takayoshi Kochi (t-kochi@b
q.jp.nec.com)
* Copyright (c) 2002
,2003
NEC Corporation
*
* All rights reserved.
*
...
...
@@ -26,8 +26,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Send feedback to <gregkh@us.ibm.com>,
* <h-aono@ap.jp.nec.com>,
* <t-kouchi@cq.jp.nec.com>
* <t-kochi@bq.jp.nec.com>
*
*/
...
...
@@ -35,6 +34,7 @@
#define _ACPIPHP_H
#include <linux/acpi.h>
#include <linux/kobject.h>
/* for KOBJ_NAME_LEN */
#include "pci_hotplug.h"
#define dbg(format, arg...) \
...
...
@@ -49,7 +49,7 @@
#define SLOT_MAGIC 0x67267322
/* name size which is used for entries in pcihpfs */
#define SLOT_NAME_SIZE
32
/* ACPI{_SUN}-{BUS}:{DEV
} */
#define SLOT_NAME_SIZE
KOBJ_NAME_LEN
/* {_SUN
} */
struct
acpiphp_bridge
;
struct
acpiphp_slot
;
...
...
@@ -212,11 +212,7 @@ struct acpiphp_func {
#define FUNC_HAS_PS2 (0x00000040)
#define FUNC_HAS_PS3 (0x00000080)
/* not yet */
#define SLOT_SUPPORT_66MHZ (0x00010000)
#define SLOT_SUPPORT_100MHZ (0x00020000)
#define SLOT_SUPPORT_133MHZ (0x00040000)
#define SLOT_SUPPORT_PCIX (0x00080000)
#define FUNC_EXISTS (0x10000000)
/* to make sure we call _EJ0 only for existing funcs */
/* function prototypes */
...
...
drivers/pci/hotplug/acpiphp_core.c
View file @
6f982794
...
...
@@ -5,8 +5,8 @@
* Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (c) 2001 IBM Corp.
* Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
* Copyright (c) 2002
Takayoshi Kochi (t-kouchi@c
q.jp.nec.com)
* Copyright (c) 2002 NEC Corporation
* Copyright (c) 2002
,2003 Takayoshi Kochi (t-kochi@b
q.jp.nec.com)
* Copyright (c) 2002
,2003
NEC Corporation
*
* All rights reserved.
*
...
...
@@ -26,8 +26,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Send feedback to <gregkh@us.ibm.com>,
* <h-aono@ap.jp.nec.com>,
* <t-kouchi@cq.jp.nec.com>
* <t-kochi@bq.jp.nec.com>
*
*/
...
...
@@ -57,7 +56,7 @@ int acpiphp_debug;
static
int
num_slots
;
#define DRIVER_VERSION "0.4"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <gregkh@us.ibm.com>, Takayoshi Kochi <t-ko
uchi@c
q.jp.nec.com>"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <gregkh@us.ibm.com>, Takayoshi Kochi <t-ko
chi@b
q.jp.nec.com>"
#define DRIVER_DESC "ACPI Hot Plug PCI Controller Driver"
MODULE_AUTHOR
(
DRIVER_AUTHOR
);
...
...
@@ -376,10 +375,8 @@ static int init_acpi (void)
*/
static
void
make_slot_name
(
struct
slot
*
slot
)
{
snprintf
(
slot
->
hotplug_slot
->
name
,
SLOT_NAME_SIZE
,
"ACPI%d-%02x:%02x"
,
slot
->
acpi_slot
->
sun
,
slot
->
acpi_slot
->
bridge
->
bus
,
slot
->
acpi_slot
->
device
);
snprintf
(
slot
->
hotplug_slot
->
name
,
SLOT_NAME_SIZE
,
"%u"
,
slot
->
acpi_slot
->
sun
);
}
/**
...
...
drivers/pci/hotplug/acpiphp_glue.c
View file @
6f982794
/*
* ACPI PCI HotPlug glue functions to ACPI CA subsystem
*
* Copyright (c) 2002
Takayoshi Kochi (t-kouchi@c
q.jp.nec.com)
* Copyright (c) 2002
,2003 Takayoshi Kochi (t-kochi@b
q.jp.nec.com)
* Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
* Copyright (c) 2002 NEC Corporation
* Copyright (c) 2002
,2003
NEC Corporation
*
* All rights reserved.
*
...
...
@@ -22,7 +22,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Send feedback to <t-ko
uchi@c
q.jp.nec.com>
* Send feedback to <t-ko
chi@b
q.jp.nec.com>
*
*/
...
...
@@ -204,7 +204,6 @@ register_slot (acpi_handle handle, u32 lvl, void *context, void **rv)
if
(
ACPI_FAILURE
(
status
))
{
err
(
"failed to register interrupt notify handler
\n
"
);
kfree
(
newfunc
);
return
status
;
}
...
...
@@ -617,9 +616,8 @@ find_p2p_bridge (acpi_handle handle, u32 lvl, void *context, void **rv)
/* find hot-pluggable slots, and then find P2P bridge */
static
int
add_bridge
s
(
struct
acpi_device
*
devic
e
)
static
int
add_bridge
(
acpi_handle
handl
e
)
{
acpi_handle
*
handle
=
device
->
handle
;
acpi_status
status
;
unsigned
long
tmp
;
int
seg
,
bus
;
...
...
@@ -673,6 +671,12 @@ static int add_bridges(struct acpi_device *device)
}
static
void
remove_bridge
(
acpi_handle
handle
)
{
/* No-op for now .. */
}
static
int
power_on_slot
(
struct
acpiphp_slot
*
slot
)
{
acpi_status
status
;
...
...
@@ -725,9 +729,7 @@ static int power_off_slot (struct acpiphp_slot *slot)
list_for_each
(
l
,
&
slot
->
funcs
)
{
func
=
list_entry
(
l
,
struct
acpiphp_func
,
sibling
);
if
(
func
->
flags
&
FUNC_HAS_PS3
)
{
dbg
(
"%s: executing _PS3 on %s
\n
"
,
__FUNCTION__
,
func
->
pci_dev
->
slot_name
);
if
(
func
->
flags
&
(
FUNC_HAS_PS3
|
FUNC_EXISTS
))
{
status
=
acpi_evaluate_object
(
func
->
handle
,
"_PS3"
,
NULL
,
NULL
);
if
(
ACPI_FAILURE
(
status
))
{
warn
(
"%s: _PS3 failed
\n
"
,
__FUNCTION__
);
...
...
@@ -740,10 +742,8 @@ static int power_off_slot (struct acpiphp_slot *slot)
list_for_each
(
l
,
&
slot
->
funcs
)
{
func
=
list_entry
(
l
,
struct
acpiphp_func
,
sibling
);
if
(
func
->
flags
&
FUNC_HAS_EJ0
)
{
dbg
(
"%s: executing _EJ0 on %s
\n
"
,
__FUNCTION__
,
func
->
pci_dev
->
slot_name
);
/* We don't want to call _EJ0 on non-existing functions. */
if
(
func
->
flags
&
(
FUNC_HAS_EJ0
|
FUNC_EXISTS
))
{
/* _EJ0 method take one argument */
arg_list
.
count
=
1
;
arg_list
.
pointer
=
&
arg
;
...
...
@@ -756,6 +756,7 @@ static int power_off_slot (struct acpiphp_slot *slot)
retval
=
-
1
;
goto
err_exit
;
}
func
->
flags
&=
(
~
FUNC_EXISTS
);
}
}
...
...
@@ -835,6 +836,8 @@ static int enable_device (struct acpiphp_slot *slot)
retval
=
acpiphp_configure_function
(
func
);
if
(
retval
)
goto
err_exit
;
func
->
flags
|=
FUNC_EXISTS
;
}
slot
->
flags
|=
SLOT_ENABLED
;
...
...
@@ -1029,13 +1032,10 @@ static void handle_hotplug_event_func (acpi_handle handle, u32 type, void *conte
}
}
static
struct
acpi_driver
acpi_pci_hp_driver
=
{
.
name
=
"pci_hp"
,
.
class
=
""
,
.
ids
=
ACPI_PCI_HOST_HID
,
.
ops
=
{
.
add
=
add_bridges
,
}
static
struct
acpi_pci_driver
acpi_pci_hp_driver
=
{
.
add
=
add_bridge
,
.
remove
=
remove_bridge
,
};
/**
...
...
@@ -1044,17 +1044,15 @@ static struct acpi_driver acpi_pci_hp_driver = {
*/
int
acpiphp_glue_init
(
void
)
{
acpi_status
status
;
int
num
;
if
(
list_empty
(
&
pci_root_buses
))
return
-
1
;
status
=
acpi_bus
_register_driver
(
&
acpi_pci_hp_driver
);
num
=
acpi_pci
_register_driver
(
&
acpi_pci_hp_driver
);
if
(
ACPI_FAILURE
(
status
))
{
err
(
"%s: acpi_walk_namespace() failed
\n
"
,
__FUNCTION__
);
if
(
num
<=
0
)
return
-
1
;
}
return
0
;
}
...
...
drivers/pci/hotplug/acpiphp_pci.c
View file @
6f982794
...
...
@@ -4,7 +4,7 @@
* Copyright (c) 1995,2001 Compaq Computer Corporation
* Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (c) 2001,2002 IBM Corp.
* Copyright (c) 2002 Takayoshi Kochi (t-ko
uchi@c
q.jp.nec.com)
* Copyright (c) 2002 Takayoshi Kochi (t-ko
chi@b
q.jp.nec.com)
* Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
* Copyright (c) 2002 NEC Corporation
*
...
...
@@ -25,7 +25,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Send feedback to <t-ko
uchi@c
q.jp.nec.com>
* Send feedback to <t-ko
chi@b
q.jp.nec.com>
*
*/
...
...
drivers/pci/hotplug/acpiphp_res.c
View file @
6f982794
...
...
@@ -5,7 +5,7 @@
* Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (c) 2001 IBM Corp.
* Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
* Copyright (c) 2002 Takayoshi Kochi (t-ko
uchi@c
q.jp.nec.com)
* Copyright (c) 2002 Takayoshi Kochi (t-ko
chi@b
q.jp.nec.com)
* Copyright (c) 2002 NEC Corporation
*
* All rights reserved.
...
...
@@ -25,7 +25,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Send feedback to <gregkh@us.ibm.com>,
<h-aono@ap
.jp.nec.com>
* Send feedback to <gregkh@us.ibm.com>,
<t-kochi@bq
.jp.nec.com>
*
*/
...
...
include/asm-i386/acpi.h
View file @
6f982794
...
...
@@ -106,6 +106,10 @@
:"0"(n_hi), "1"(n_lo))
#ifdef CONFIG_ACPI_HT_ONLY
extern
int
acpi_lapic
;
#define acpi_ioapic 0
#else
#ifndef CONFIG_ACPI_BOOT
#define acpi_lapic 0
#define acpi_ioapic 0
...
...
@@ -120,6 +124,7 @@ extern int acpi_ioapic;
#else
#define acpi_ioapic 0
#endif
#endif
/* Fixmap pages to reserve for ACPI boot-time tables (see fixmap.h) */
#define FIX_ACPI_PAGES 4
...
...
include/linux/acpi.h
View file @
6f982794
...
...
@@ -403,8 +403,8 @@ int acpi_pci_irq_init (void);
struct
acpi_pci_driver
{
struct
acpi_pci_driver
*
next
;
int
(
*
add
)(
acpi_handle
*
handle
);
void
(
*
remove
)(
acpi_handle
*
handle
);
int
(
*
add
)(
acpi_handle
handle
);
void
(
*
remove
)(
acpi_handle
handle
);
};
int
acpi_pci_register_driver
(
struct
acpi_pci_driver
*
driver
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment