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
6b3dcb38
Commit
6b3dcb38
authored
Oct 27, 2002
by
Alan Cox
Committed by
Linus Torvalds
Oct 27, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] core voyager arch/i386/machine support
parent
12de40fe
Changes
12
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
4441 additions
and
0 deletions
+4441
-0
arch/i386/mach-voyager/Makefile
arch/i386/mach-voyager/Makefile
+17
-0
arch/i386/mach-voyager/do_timer.h
arch/i386/mach-voyager/do_timer.h
+22
-0
arch/i386/mach-voyager/entry_arch.h
arch/i386/mach-voyager/entry_arch.h
+26
-0
arch/i386/mach-voyager/irq_vectors.h
arch/i386/mach-voyager/irq_vectors.h
+71
-0
arch/i386/mach-voyager/setup.c
arch/i386/mach-voyager/setup.c
+43
-0
arch/i386/mach-voyager/setup_arch_post.h
arch/i386/mach-voyager/setup_arch_post.h
+73
-0
arch/i386/mach-voyager/setup_arch_pre.h
arch/i386/mach-voyager/setup_arch_pre.h
+10
-0
arch/i386/mach-voyager/voyager_basic.c
arch/i386/mach-voyager/voyager_basic.c
+312
-0
arch/i386/mach-voyager/voyager_cat.c
arch/i386/mach-voyager/voyager_cat.c
+1178
-0
arch/i386/mach-voyager/voyager_smp.c
arch/i386/mach-voyager/voyager_smp.c
+1989
-0
arch/i386/mach-voyager/voyager_thread.c
arch/i386/mach-voyager/voyager_thread.c
+178
-0
include/asm-i386/voyager.h
include/asm-i386/voyager.h
+522
-0
No files found.
arch/i386/mach-voyager/Makefile
0 → 100644
View file @
6b3dcb38
#
# Makefile for the linux kernel.
#
# Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file).
#
# Note 2! The CFLAGS definitions are now in the main makefile...
EXTRA_CFLAGS
+=
-I
../kernel
export-objs
:=
obj-y
:=
setup.o voyager_basic.o voyager_thread.o
obj-$(CONFIG_SMP)
+=
voyager_smp.o voyager_cat.o
include
$(TOPDIR)/Rules.make
arch/i386/mach-voyager/do_timer.h
0 → 100644
View file @
6b3dcb38
/* defines for inline arch setup functions */
#include <asm/voyager.h>
static
inline
void
do_timer_interrupt_hook
(
struct
pt_regs
*
regs
)
{
do_timer
(
regs
);
voyager_timer_interrupt
(
regs
);
}
static
inline
int
do_timer_overflow
(
int
count
)
{
/* can't read the ISR, just assume 1 tick
overflow */
if
(
count
>
LATCH
||
count
<
0
)
{
printk
(
KERN_ERR
"VOYAGER PROBLEM: count is %d, latch is %d
\n
"
,
count
,
LATCH
);
count
=
LATCH
;
}
count
-=
LATCH
;
return
count
;
}
arch/i386/mach-voyager/entry_arch.h
0 → 100644
View file @
6b3dcb38
/* -*- mode: c; c-basic-offset: 8 -*- */
/* Copyright (C) 2002
*
* Author: James.Bottomley@HansenPartnership.com
*
* linux/arch/i386/voyager/entry_arch.h
*
* This file builds the VIC and QIC CPI gates
*/
/* initialise the voyager interrupt gates
*
* This uses the macros in irq.h to set up assembly jump gates. The
* calls are then redirected to the same routine with smp_ prefixed */
BUILD_INTERRUPT
(
vic_sys_interrupt
,
VIC_SYS_INT
)
BUILD_INTERRUPT
(
vic_cmn_interrupt
,
VIC_CMN_INT
)
BUILD_INTERRUPT
(
vic_cpi_interrupt
,
VIC_CPI_LEVEL0
);
/* do all the QIC interrupts */
BUILD_INTERRUPT
(
qic_timer_interrupt
,
QIC_TIMER_CPI
);
BUILD_INTERRUPT
(
qic_invalidate_interrupt
,
QIC_INVALIDATE_CPI
);
BUILD_INTERRUPT
(
qic_reschedule_interrupt
,
QIC_RESCHEDULE_CPI
);
BUILD_INTERRUPT
(
qic_enable_irq_interrupt
,
QIC_ENABLE_IRQ_CPI
);
BUILD_INTERRUPT
(
qic_call_function_interrupt
,
QIC_CALL_FUNCTION_CPI
);
arch/i386/mach-voyager/irq_vectors.h
0 → 100644
View file @
6b3dcb38
/* -*- mode: c; c-basic-offset: 8 -*- */
/* Copyright (C) 2002
*
* Author: James.Bottomley@HansenPartnership.com
*
* linux/arch/i386/voyager/irq_vectors.h
*
* This file provides definitions for the VIC and QIC CPIs
*/
#ifndef _ASM_IRQ_VECTORS_H
#define _ASM_IRQ_VECTORS_H
/*
* IDT vectors usable for external interrupt sources start
* at 0x20:
*/
#define FIRST_EXTERNAL_VECTOR 0x20
#define SYSCALL_VECTOR 0x80
/*
* Vectors 0x20-0x2f are used for ISA interrupts.
*/
/* These define the CPIs we use in linux */
#define VIC_CPI_LEVEL0 0
#define VIC_CPI_LEVEL1 1
/* now the fake CPIs */
#define VIC_TIMER_CPI 2
#define VIC_INVALIDATE_CPI 3
#define VIC_RESCHEDULE_CPI 4
#define VIC_ENABLE_IRQ_CPI 5
#define VIC_CALL_FUNCTION_CPI 6
/* Now the QIC CPIs: Since we don't need the two initial levels,
* these are 2 less than the VIC CPIs */
#define QIC_CPI_OFFSET 1
#define QIC_TIMER_CPI (VIC_TIMER_CPI - QIC_CPI_OFFSET)
#define QIC_INVALIDATE_CPI (VIC_INVALIDATE_CPI - QIC_CPI_OFFSET)
#define QIC_RESCHEDULE_CPI (VIC_RESCHEDULE_CPI - QIC_CPI_OFFSET)
#define QIC_ENABLE_IRQ_CPI (VIC_ENABLE_IRQ_CPI - QIC_CPI_OFFSET)
#define QIC_CALL_FUNCTION_CPI (VIC_CALL_FUNCTION_CPI - QIC_CPI_OFFSET)
#define VIC_START_FAKE_CPI VIC_TIMER_CPI
#define VIC_END_FAKE_CPI VIC_CALL_FUNCTION_CPI
/* this is the SYS_INT CPI. */
#define VIC_SYS_INT 8
#define VIC_CMN_INT 15
/* This is the boot CPI for alternate processors. It gets overwritten
* by the above once the system has activated all available processors */
#define VIC_CPU_BOOT_CPI VIC_CPI_LEVEL0
#define VIC_CPU_BOOT_ERRATA_CPI (VIC_CPI_LEVEL0 + 8)
#define NR_IRQS 224
#ifndef __ASSEMBLY__
extern
asmlinkage
void
vic_cpi_interrupt
(
void
);
extern
asmlinkage
void
vic_sys_interrupt
(
void
);
extern
asmlinkage
void
vic_cmn_interrupt
(
void
);
extern
asmlinkage
void
qic_timer_interrupt
(
void
);
extern
asmlinkage
void
qic_invalidate_interrupt
(
void
);
extern
asmlinkage
void
qic_reschedule_interrupt
(
void
);
extern
asmlinkage
void
qic_enable_irq_interrupt
(
void
);
extern
asmlinkage
void
qic_call_function_interrupt
(
void
);
#endif
/* !__ASSEMBLY__ */
#endif
/* _ASM_IRQ_VECTORS_H */
arch/i386/mach-voyager/setup.c
0 → 100644
View file @
6b3dcb38
/*
* Machine specific setup for generic
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/arch_hooks.h>
void
__init
pre_intr_init_hook
(
void
)
{
init_ISA_irqs
();
}
/*
* IRQ2 is cascade interrupt to second interrupt controller
*/
static
struct
irqaction
irq2
=
{
no_action
,
0
,
0
,
"cascade"
,
NULL
,
NULL
};
void
__init
intr_init_hook
(
void
)
{
#ifdef CONFIG_SMP
smp_intr_init
();
#endif
setup_irq
(
2
,
&
irq2
);
}
void
__init
pre_setup_arch_hook
(
void
)
{
}
void
__init
trap_init_hook
(
void
)
{
}
static
struct
irqaction
irq0
=
{
timer_interrupt
,
SA_INTERRUPT
,
0
,
"timer"
,
NULL
,
NULL
};
void
__init
time_init_hook
(
void
)
{
setup_irq
(
0
,
&
irq0
);
}
arch/i386/mach-voyager/setup_arch_post.h
0 → 100644
View file @
6b3dcb38
/* Hook for machine specific memory setup.
*
* This is included late in kernel/setup.c so that it can make use of all of
* the static functions. */
static
inline
char
*
__init
machine_specific_memory_setup
(
void
)
{
char
*
who
;
who
=
"NOT VOYAGER"
;
if
(
voyager_level
==
5
)
{
__u32
addr
,
length
;
int
i
;
who
=
"Voyager-SUS"
;
e820
.
nr_map
=
0
;
for
(
i
=
0
;
voyager_memory_detect
(
i
,
&
addr
,
&
length
);
i
++
)
{
add_memory_region
(
addr
,
length
,
E820_RAM
);
}
return
who
;
}
else
if
(
voyager_level
==
4
)
{
__u32
tom
;
__u16
catbase
=
inb
(
VOYAGER_SSPB_RELOCATION_PORT
)
<<
8
;
/* select the DINO config space */
outb
(
VOYAGER_DINO
,
VOYAGER_CAT_CONFIG_PORT
);
/* Read DINO top of memory register */
tom
=
((
inb
(
catbase
+
0x4
)
&
0xf0
)
<<
16
)
+
((
inb
(
catbase
+
0x5
)
&
0x7f
)
<<
24
);
if
(
inb
(
catbase
)
!=
VOYAGER_DINO
)
{
printk
(
KERN_ERR
"Voyager: Failed to get DINO for L4, setting tom to EXT_MEM_K
\n
"
);
tom
=
(
EXT_MEM_K
)
<<
10
;
}
who
=
"Voyager-TOM"
;
add_memory_region
(
0
,
0x9f000
,
E820_RAM
);
/* map from 1M to top of memory */
add_memory_region
(
1
*
1024
*
1024
,
tom
-
1
*
1024
*
1024
,
E820_RAM
);
/* FIXME: Should check the ASICs to see if I need to
* take out the 8M window. Just do it at the moment
* */
add_memory_region
(
8
*
1024
*
1024
,
8
*
1024
*
1024
,
E820_RESERVED
);
return
who
;
}
who
=
"BIOS-e820"
;
/*
* Try to copy the BIOS-supplied E820-map.
*
* Otherwise fake a memory map; one section from 0k->640k,
* the next section from 1mb->appropriate_mem_k
*/
sanitize_e820_map
(
E820_MAP
,
&
E820_MAP_NR
);
if
(
copy_e820_map
(
E820_MAP
,
E820_MAP_NR
)
<
0
)
{
unsigned
long
mem_size
;
/* compare results from other methods and take the greater */
if
(
ALT_MEM_K
<
EXT_MEM_K
)
{
mem_size
=
EXT_MEM_K
;
who
=
"BIOS-88"
;
}
else
{
mem_size
=
ALT_MEM_K
;
who
=
"BIOS-e801"
;
}
e820
.
nr_map
=
0
;
add_memory_region
(
0
,
LOWMEMSIZE
(),
E820_RAM
);
add_memory_region
(
HIGH_MEMORY
,
mem_size
<<
10
,
E820_RAM
);
}
return
who
;
}
arch/i386/mach-voyager/setup_arch_pre.h
0 → 100644
View file @
6b3dcb38
#include <asm/voyager.h>
#define VOYAGER_BIOS_INFO ((struct voyager_bios_info *)(PARAM+0x40))
/* Hook to call BIOS initialisation function */
/* for voyager, pass the voyager BIOS/SUS info area to the detection
* routines */
#define ARCH_SETUP voyager_detect(VOYAGER_BIOS_INFO);
arch/i386/mach-voyager/voyager_basic.c
0 → 100644
View file @
6b3dcb38
/* Copyright (C) 1999,2001
*
* Author: J.E.J.Bottomley@HansenPartnership.com
*
* linux/arch/i386/kernel/voyager.c
*
* This file contains all the voyager specific routines for getting
* initialisation of the architecture to function. For additional
* features see:
*
* voyager_cat.c - Voyager CAT bus interface
* voyager_smp.c - Voyager SMP hal (emulates linux smp.c)
*/
#include <linux/config.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/ptrace.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/reboot.h>
#include <asm/io.h>
#include <asm/pgalloc.h>
#include <asm/voyager.h>
#include <asm/vic.h>
#include <linux/pm.h>
#include <linux/irq.h>
#include <asm/tlbflush.h>
#include <asm/arch_hooks.h>
/*
* Power off function, if any
*/
void
(
*
pm_power_off
)(
void
);
int
reboot_thru_bios
;
int
voyager_level
=
0
;
struct
voyager_SUS
*
voyager_SUS
=
NULL
;
void
voyager_detect
(
struct
voyager_bios_info
*
bios
)
{
if
(
bios
->
len
!=
0xff
)
{
int
class
=
(
bios
->
class_1
<<
8
)
|
(
bios
->
class_2
&
0xff
);
printk
(
"Voyager System detected.
\n
"
" Class %x, Revision %d.%d
\n
"
,
class
,
bios
->
major
,
bios
->
minor
);
if
(
class
==
VOYAGER_LEVEL4
)
voyager_level
=
4
;
else
if
(
class
<
VOYAGER_LEVEL5_AND_ABOVE
)
voyager_level
=
3
;
else
voyager_level
=
5
;
printk
(
" Architecture Level %d
\n
"
,
voyager_level
);
if
(
voyager_level
<
4
)
printk
(
"
\n
**WARNING**: Voyager HAL only supports Levels 4 and 5 Architectures at the moment
\n\n
"
);
/* install the power off handler */
pm_power_off
=
voyager_power_off
;
}
else
{
printk
(
"
\n\n
**WARNING**: No Voyager Subsystem Found
\n
"
);
}
}
void
voyager_system_interrupt
(
int
cpl
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
printk
(
"Voyager: detected system interrupt
\n
"
);
}
/* Routine to read information from the extended CMOS area */
__u8
voyager_extended_cmos_read
(
__u16
addr
)
{
outb
(
addr
&
0xff
,
0x74
);
outb
((
addr
>>
8
)
&
0xff
,
0x75
);
return
inb
(
0x76
);
}
/* internal definitions for the SUS Click Map of memory */
#define CLICK_ENTRIES 16
#define CLICK_SIZE 4096
/* click to byte conversion for Length */
typedef
struct
ClickMap
{
struct
Entry
{
__u32
Address
;
__u32
Length
;
}
Entry
[
CLICK_ENTRIES
];
}
ClickMap_t
;
/* This routine is pretty much an awful hack to read the bios clickmap by
* mapping it into page 0. There are usually three regions in the map:
* Base Memory
* Extended Memory
* zero length marker for end of map
*
* Returns are 0 for failure and 1 for success on extracting region.
*/
int
__init
voyager_memory_detect
(
int
region
,
__u32
*
start
,
__u32
*
length
)
{
int
i
;
int
retval
=
0
;
__u8
cmos
[
4
];
ClickMap_t
*
map
;
unsigned
long
map_addr
;
unsigned
long
old
;
if
(
region
>=
CLICK_ENTRIES
)
{
printk
(
"Voyager: Illegal ClickMap region %d
\n
"
,
region
);
return
0
;
}
for
(
i
=
0
;
i
<
sizeof
(
cmos
);
i
++
)
cmos
[
i
]
=
voyager_extended_cmos_read
(
VOYAGER_MEMORY_CLICKMAP
+
i
);
map_addr
=
*
(
unsigned
long
*
)
cmos
;
/* steal page 0 for this */
old
=
pg0
[
0
];
pg0
[
0
]
=
((
map_addr
&
PAGE_MASK
)
|
_PAGE_RW
|
_PAGE_PRESENT
);
local_flush_tlb
();
/* now clear everything out but page 0 */
map
=
(
ClickMap_t
*
)(
map_addr
&
(
~
PAGE_MASK
));
/* zero length is the end of the clickmap */
if
(
map
->
Entry
[
region
].
Length
!=
0
)
{
*
length
=
map
->
Entry
[
region
].
Length
*
CLICK_SIZE
;
*
start
=
map
->
Entry
[
region
].
Address
;
retval
=
1
;
}
/* replace the mapping */
pg0
[
0
]
=
old
;
local_flush_tlb
();
return
retval
;
}
void
voyager_dump
()
{
/* get here via a sysrq */
#ifdef CONFIG_SMP
voyager_smp_dump
();
#endif
}
/* voyager specific handling code for timer interrupts. Used to hand
* off the timer tick to the SMP code, since the VIC doesn't have an
* internal timer (The QIC does, but that's another story). */
void
voyager_timer_interrupt
(
struct
pt_regs
*
regs
)
{
if
((
jiffies
&
0x3ff
)
==
0
)
{
/* There seems to be something flaky in either
* hardware or software that is resetting the timer 0
* count to something much higher than it should be
* This seems to occur in the boot sequence, just
* before root is mounted. Therefore, every 10
* seconds or so, we sanity check the timer zero count
* and kick it back to where it should be.
*
* FIXME: This is the most awful hack yet seen. I
* should work out exactly what is interfering with
* the timer count settings early in the boot sequence
* and swiftly introduce it to something sharp and
* pointy. */
__u16
val
;
extern
spinlock_t
i8253_lock
;
spin_lock
(
&
i8253_lock
);
outb_p
(
0x00
,
0x43
);
val
=
inb_p
(
0x40
);
val
|=
inb
(
0x40
)
<<
8
;
spin_unlock
(
&
i8253_lock
);
if
(
val
>
LATCH
)
{
printk
(
"
\n
VOYAGER: countdown timer value too high (%d), resetting
\n\n
"
,
val
);
spin_lock
(
&
i8253_lock
);
outb
(
0x34
,
0x43
);
outb_p
(
LATCH
&
0xff
,
0x40
);
/* LSB */
outb
(
LATCH
>>
8
,
0x40
);
/* MSB */
spin_unlock
(
&
i8253_lock
);
}
}
#ifdef CONFIG_SMP
smp_vic_timer_interrupt
(
regs
);
#endif
}
void
voyager_power_off
(
void
)
{
printk
(
"VOYAGER Power Off
\n
"
);
if
(
voyager_level
==
5
)
{
voyager_cat_power_off
();
}
else
if
(
voyager_level
==
4
)
{
/* This doesn't apparently work on most L4 machines,
* but the specs say to do this to get automatic power
* off. Unfortunately, if it doesn't power off the
* machine, it ends up doing a cold restart, which
* isn't really intended, so comment out the code */
#if 0
int port;
/* enable the voyager Configuration Space */
outb((inb(VOYAGER_MC_SETUP) & 0xf0) | 0x8,
VOYAGER_MC_SETUP);
/* the port for the power off flag is an offset from the
floating base */
port = (inb(VOYAGER_SSPB_RELOCATION_PORT) << 8) + 0x21;
/* set the power off flag */
outb(inb(port) | 0x1, port);
#endif
}
/* and wait for it to happen */
for
(;;)
{
__asm
(
"cli"
);
__asm
(
"hlt"
);
}
}
/* copied from process.c */
static
inline
void
kb_wait
(
void
)
{
int
i
;
for
(
i
=
0
;
i
<
0x10000
;
i
++
)
if
((
inb_p
(
0x64
)
&
0x02
)
==
0
)
break
;
}
void
machine_restart
(
char
*
cmd
)
{
printk
(
"Voyager Warm Restart
\n
"
);
kb_wait
();
if
(
voyager_level
==
5
)
{
/* write magic values to the RTC to inform system that
* shutdown is beginning */
outb
(
0x8f
,
0x70
);
outb
(
0x5
,
0x71
);
udelay
(
50
);
outb
(
0xfe
,
0x64
);
/* pull reset low */
}
else
if
(
voyager_level
==
4
)
{
__u16
catbase
=
inb
(
VOYAGER_SSPB_RELOCATION_PORT
)
<<
8
;
__u8
basebd
=
inb
(
VOYAGER_MC_SETUP
);
outb
(
basebd
|
0x08
,
VOYAGER_MC_SETUP
);
outb
(
0x02
,
catbase
+
0x21
);
}
for
(;;)
{
asm
(
"cli"
);
asm
(
"hlt"
);
}
}
void
mca_nmi_hook
(
void
)
{
__u8
dumpval
__attribute__
((
unused
))
=
inb
(
0xf823
);
__u8
swnmi
__attribute__
((
unused
))
=
inb
(
0xf813
);
extern
void
show_stack
(
unsigned
long
*
);
/* FIXME: assume dump switch pressed */
/* check to see if the dump switch was pressed */
VDEBUG
((
"VOYAGER: dumpval = 0x%x, swnmi = 0x%x
\n
"
,
dumpval
,
swnmi
));
/* clear swnmi */
outb
(
0xff
,
0xf813
);
/* tell SUS to ignore dump */
if
(
voyager_level
==
5
&&
voyager_SUS
!=
NULL
)
{
if
(
voyager_SUS
->
SUS_mbox
==
VOYAGER_DUMP_BUTTON_NMI
)
{
voyager_SUS
->
kernel_mbox
=
VOYAGER_NO_COMMAND
;
voyager_SUS
->
kernel_flags
|=
VOYAGER_OS_IN_PROGRESS
;
udelay
(
1000
);
voyager_SUS
->
kernel_mbox
=
VOYAGER_IGNORE_DUMP
;
voyager_SUS
->
kernel_flags
&=
~
VOYAGER_OS_IN_PROGRESS
;
}
}
printk
(
KERN_ERR
"VOYAGER: Dump switch pressed, printing CPU%d tracebacks
\n
"
,
smp_processor_id
());
show_stack
(
NULL
);
show_state
();
}
void
machine_halt
(
void
)
{
/* treat a halt like a power off */
machine_power_off
();
}
void
machine_power_off
(
void
)
{
if
(
pm_power_off
)
pm_power_off
();
}
arch/i386/mach-voyager/voyager_cat.c
0 → 100644
View file @
6b3dcb38
This diff is collapsed.
Click to expand it.
arch/i386/mach-voyager/voyager_smp.c
0 → 100644
View file @
6b3dcb38
This diff is collapsed.
Click to expand it.
arch/i386/mach-voyager/voyager_thread.c
0 → 100644
View file @
6b3dcb38
/* -*- mode: c; c-basic-offset: 8 -*- */
/* Copyright (C) 2001
*
* Author: J.E.J.Bottomley@HansenPartnership.com
*
* linux/arch/i386/kernel/voyager_thread.c
*
* This module provides the machine status monitor thread for the
* voyager architecture. This allows us to monitor the machine
* environment (temp, voltage, fan function) and the front panel and
* internal UPS. If a fault is detected, this thread takes corrective
* action (usually just informing init)
* */
#include <linux/module.h>
#include <linux/config.h>
#include <linux/mm.h>
#include <linux/kernel_stat.h>
#include <linux/delay.h>
#include <linux/mc146818rtc.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/bootmem.h>
#include <linux/kmod.h>
#include <linux/completion.h>
#include <linux/sched.h>
#include <asm/desc.h>
#include <asm/voyager.h>
#include <asm/vic.h>
#include <asm/pgalloc.h>
#include <asm/mtrr.h>
#include <asm/msr.h>
#include <linux/irq.h>
#define THREAD_NAME "kvoyagerd"
/* external variables */
int
kvoyagerd_running
=
0
;
DECLARE_MUTEX_LOCKED
(
kvoyagerd_sem
);
static
int
thread
(
void
*
);
static
__u8
set_timeout
=
0
;
/* Start the machine monitor thread. Return 1 if OK, 0 if fail */
static
int
__init
voyager_thread_start
(
void
)
{
if
(
kernel_thread
(
thread
,
NULL
,
CLONE_KERNEL
)
<
0
)
{
/* This is serious, but not fatal */
printk
(
KERN_ERR
"Voyager: Failed to create system monitor thread!!!
\n
"
);
return
1
;
}
return
0
;
}
static
int
execute_helper
(
void
*
string
)
{
int
ret
;
char
*
envp
[]
=
{
"HOME=/"
,
"TERM=linux"
,
"PATH=/sbin:/usr/sbin:/bin:/usr/bin"
,
NULL
,
};
char
*
argv
[]
=
{
"/bin/bash"
,
"-c"
,
(
char
*
)
string
,
NULL
,
};
if
((
ret
=
exec_usermodehelper
(
argv
[
0
],
argv
,
envp
))
<
0
)
{
printk
(
KERN_ERR
"Voyager failed to execute
\"
%s
\"\n
"
,
(
char
*
)
string
);
}
return
ret
;
}
static
void
execute
(
char
*
string
)
{
if
(
kernel_thread
(
execute_helper
,
(
void
*
)
string
,
CLONE_VFORK
|
SIGCHLD
)
<
0
)
{
printk
(
KERN_ERR
"Voyager failed to fork before exec of
\"
%s
\"\n
"
,
string
);
}
}
static
void
check_from_kernel
(
void
)
{
if
(
voyager_status
.
switch_off
)
{
/* FIXME: This should be configureable via proc */
execute
(
"umask 600; echo 0 > /etc/initrunlvl; kill -HUP 1"
);
}
else
if
(
voyager_status
.
power_fail
)
{
VDEBUG
((
"Voyager daemon detected AC power failure
\n
"
));
/* FIXME: This should be configureable via proc */
execute
(
"umask 600; echo F > /etc/powerstatus; kill -PWR 1"
);
set_timeout
=
1
;
}
}
static
void
check_continuing_condition
(
void
)
{
if
(
voyager_status
.
power_fail
)
{
__u8
data
;
voyager_cat_psi
(
VOYAGER_PSI_SUBREAD
,
VOYAGER_PSI_AC_FAIL_REG
,
&
data
);
if
((
data
&
0x1f
)
==
0
)
{
/* all power restored */
printk
(
KERN_NOTICE
"VOYAGER AC power restored, cancelling shutdown
\n
"
);
/* FIXME: should be user configureable */
execute
(
"umask 600; echo O > /etc/powerstatus; kill -PWR 1"
);
set_timeout
=
0
;
}
}
}
static
void
wakeup
(
unsigned
long
unused
)
{
up
(
&
kvoyagerd_sem
);
}
static
int
thread
(
void
*
unused
)
{
struct
timer_list
wakeup_timer
;
kvoyagerd_running
=
1
;
reparent_to_init
();
daemonize
();
set_timeout
=
0
;
init_timer
(
&
wakeup_timer
);
strcpy
(
current
->
comm
,
THREAD_NAME
);
sigfillset
(
&
current
->
blocked
);
current
->
tty
=
NULL
;
/* get rid of controlling tty */
printk
(
KERN_NOTICE
"Voyager starting monitor thread
\n
"
);
for
(;;)
{
down_interruptible
(
&
kvoyagerd_sem
);
VDEBUG
((
"Voyager Daemon awoken
\n
"
));
if
(
voyager_status
.
request_from_kernel
==
0
)
{
/* probably awoken from timeout */
check_continuing_condition
();
}
else
{
check_from_kernel
();
voyager_status
.
request_from_kernel
=
0
;
}
if
(
set_timeout
)
{
del_timer
(
&
wakeup_timer
);
wakeup_timer
.
expires
=
HZ
+
jiffies
;
wakeup_timer
.
function
=
wakeup
;
add_timer
(
&
wakeup_timer
);
}
}
}
static
void
__exit
voyager_thread_stop
(
void
)
{
/* FIXME: do nothing at the moment */
}
module_init
(
voyager_thread_start
);
//module_exit(voyager_thread_stop);
include/asm-i386/voyager.h
0 → 100644
View file @
6b3dcb38
This diff is collapsed.
Click to expand it.
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