Commit 7f40154f authored by James Bottomley's avatar James Bottomley

Massive merge by hand for changes duplicated independently

by Doug Ledford, hch and alan.
parents 0d47aeb4 0c152879
BeOS filesystem for Linux
Document last updated: Dec 6, 2001
WARNING
=======
Make sure you understand that this is alpha software. This means that the
implementation is neither complete nor well-tested.
I DISCLAIM ALL RESPONSIBILTY FOR ANY POSSIBLE BAD EFFECTS OF THIS CODE!
LICENSE
=====
This software is covered by the GNU General Public License.
See the file COPYING for the complete text of the license.
Or the GNU website: <http://www.gnu.org/licenses/licenses.html>
AUTHOR
=====
Current maintainer: Will Dyson <will_dyson@pobox.com>
Has been working on the code since Aug 13, 2001. See the changelog for details.
Original Author: Makoto Kato <m_kato@ga2.so-net.ne.jp>
His orriginal code can still be found at: <http://hp.vector.co.jp/authors/VA008030/bfs/>
Does anyone know of a more current email address for Makoto? He doesn't respond
to the address given above...
WHAT IS THIS DRIVER?
==================
This module implements the native filesystem of BeOS <http://www.be.com/>
for the linux 2.4.1 and later kernels. Currently it is a read-only implementation.
Which is it, BFS or BEFS?
================
Be, Inc said, "BeOS Filesystem is officially called BFS, not BeFS".
But Unixware Boot Filesystem is called bfs, too. And they are already in the
kernel.
Because of this nameing conflict, on Linux the BeOS filesystem is called befs.
HOW TO INSTALL
==============
step 1. Install the BeFS patch into the source code tree of linux.
Apply the patchfile to your kernel source tree.
Assuming that your kernel source is in /foo/bar/linux and the patchfile is called
patch-befs-xxx, you would do the following:
cd /foo/bar/linux
patch -p1 < /path/to/patch-befs-xxx
if the patching step fails (i.e. there are rejected hunks), you can try to
figure it out yourself (it shouldn't be hard), or mail the maintainer
(Will Dyson <will_dyson@pobox.com>) for help.
step 2. Configuretion & make kernel
The linux kernel has many compile-time options. Most of them are beyond the
scope of this document. I suggest the Kernel-HOWTO document as a good general
reference on this topic. <http://www.linux.com/howto/Kernel-HOWTO.html>
However, to use the BeFS module, you must enable it at configure time.
cd /foo/bar/linux
make menuconfig (or xconfig)
The BeFS module is not a standard part of the linux kernel, so you must first
enable support for experimental code under the "Code maturity level" menu.
Then, under the "Filesystems" menu will be an option called "BeFS filesystem (experimental)",
or something like that. Enable that option (it is fine to make it a module).
Save your kernel configuration and then build your kernel.
step 3. Install
See the kernel howto <http://www.linux.com/howto/Kernel-HOWTO.html> for
instructions on this critical step.
USING BFS
=========
To use the BeOS filesystem, use filesystem type 'befs'.
ex)
mount -t befs /dev/fd0 /beos
MOUNT OPTIONS
=============
uid=nnn All files in the partition will be owned by user id nnn.
gid=nnn All files in the partition will be in group nnn.
iocharset=xxx Use xxx as the name of the NLS translation table.
debug The driver will output debugging information to the syslog.
HOW TO GET LASTEST VERSION
==========================
The latest version is currently available at:
<http://befs-driver.sourceforge.net/>
ANY KNOWN BUGS?
===========
As of Jan 20, 2002:
None
SPECIAL THANKS
==============
Dominic Giampalo ... Writing "Practical file system design with Be filesystem"
Hiroyuki Yamada ... Testing LinuxPPC.
Running Linux on the Voyager Architecture
=========================================
For full details and current project status, see
http://www.hansenpartnership.com/voyager
The voyager architecture was designed by NCR in the mid 80s to be a
fully SMP capable RAS computing architecture built around intel's 486
chip set. The voyager came in three levels of architectural
sophistication: 3,4 and 5 --- 1 and 2 never made it out of prototype.
The linux patches support only the Level 5 voyager architecture (any
machine class 3435 and above).
The Voyager Architecture
------------------------
Voyager machines consist of a Baseboard with a 386 diagnostic
processor, a Power Supply Interface (PSI) a Primary and possibly
Secondary Microchannel bus and between 2 and 20 voyager slots. The
voyager slots can be populated with memory and cpu cards (up to 4GB
memory and from 1 486 to 32 Pentium Pro processors). Internally, the
voyager has a dual arbitrated system bus and a configuration and test
bus (CAT). The voyager bus speed is 40MHz. Therefore (since all
voyager cards are dual ported for each system bus) the maximum
transfer rate is 320Mb/s but only if you have your slot configuration
tuned (only memory cards can communicate with both busses at once, CPU
cards utilise them one at a time).
Voyager SMP
-----------
Since voyager was the first intel based SMP system, it is slightly
more primitive than the Intel IO-APIC approach to SMP. Voyager allows
arbitrary interrupt routing (including processor affinity routing) of
all 16 PC type interrupts. However it does this by using a modified
5259 master/slave chip set instead of an APIC bus. Additionally,
voyager supports Cross Processor Interrupts (CPI) equivalent to the
APIC IPIs. There are two routed voyager interrupt lines provided to
each slot.
Processor Cards
---------------
These come in single, dyadic and quad configurations (the quads are
problematic--see later). The maximum configuration is 8 quad cards
for 32 way SMP.
Quad Processors
---------------
Because voyager only supplies two interrupt lines to each Processor
card, the Quad processors have to be configured (and Bootstrapped) in
as a pair of Master/Slave processors.
In fact, most Quad cards only accept one VIC interrupt line, so they
have one interrupt handling processor (called the VIC extended
processor) and three non-interrupt handling processors.
Current Status
--------------
The System will boot on Mono, Dyad and Quad cards. There was
originally a Quad boot problem which has been fixed by proper gdt
alignment in the initial boot loader. If you still cannot get your
voyager system to boot, email me at:
<J.E.J.Bottomley@HansenPartnership.com>
The Quad cards now support using the separate Quad CPI vectors instead
of going through the VIC mailbox system.
The Level 4 architecture (3430 and 3360 Machines) should also work
fine.
Dump Switch
-----------
The voyager dump switch sends out a broadcast NMI which the voyager
code intercepts and does a task dump.
Power Switch
------------
The front panel power switch is intercepted by the kernel and should
cause a system shutdown and power off.
A Note About Mixed CPU Systems
------------------------------
Linux isn't designed to handle mixed CPU systems very well. In order
to get everything going you *must* make sure that your lowest
capability CPU is used for booting. Also, mixing CPU classes
(e.g. 486 and 586) is really not going to work very well at all.
......@@ -40,6 +40,7 @@
* Nov 2000, Version 1.14
* Oct 2001, Version 1.15
* Jan 2002, Version 1.16
* Oct 2002, Version 1.16ac
*
* History:
* 0.6b: first version in official kernel, Linux 1.3.46
......@@ -177,6 +178,9 @@
* CONFIG_APM_CPU_IDLE now just affects the default value of
* idle_threshold (sfr).
* Change name of kernel apm daemon (as it no longer idles) (sfr).
* 1.16ac: Fix up SMP support somewhat. You can now force SMP on and we
* make _all_ APM calls on the CPU#0. Fix unsafe sign bug.
* TODO: determine if its "boot CPU" or "CPU0" we want to lock to.
*
* APM 1.1 Reference:
*
......@@ -250,6 +254,7 @@ extern int (*console_blank_hook)(int);
* powering off
* [no-]debug log some debugging messages
* [no-]power[-_]off power off on shutdown
* [no-]smp Use apm even on an SMP box
* bounce[-_]interval=<n> number of ticks to ignore suspend
* bounces
* idle[-_]threshold=<n> System idle percentage above which to
......@@ -396,6 +401,7 @@ static long clock_cmos_diff;
static int got_clock_diff;
#endif
static int debug;
static int smp;
static int apm_disabled = -1;
#ifdef CONFIG_SMP
static int power_off;
......@@ -422,7 +428,7 @@ static struct apm_user * user_list;
static spinlock_t user_list_lock = SPIN_LOCK_UNLOCKED;
static struct desc_struct bad_bios_desc = { 0, 0x00409200 };
static char driver_version[] = "1.16"; /* no spaces */
static char driver_version[] = "1.16ac"; /* no spaces */
/*
* APM event names taken from the APM 1.2 specification. These are
......@@ -498,6 +504,38 @@ static void apm_error(char *str, int err)
str, err);
}
/*
* Lock APM functionality to physical CPU 0
*/
#ifdef CONFIG_SMP
static unsigned long apm_save_cpus(void)
{
unsigned long x = current->cpus_allowed;
/* Some bioses don't like being called from CPU != 0 */
set_cpus_allowed(current, 1 << 0);
if (unlikely(smp_processor_id() != 0))
BUG();
return x;
}
static inline void apm_restore_cpus(unsigned long mask)
{
set_cpus_allowed(current, mask);
}
#else
/*
* No CPU lockdown needed on a uniprocessor
*/
#define apm_save_cpus() 0
#define apm_restore_cpus(x) (void)(x)
#endif
/*
* These are the actual BIOS calls. Depending on APM_ZERO_SEGS and
* apm_info.allow_ints, we are being really paranoid here! Not only
......@@ -571,9 +609,12 @@ static u8 apm_bios_call(u32 func, u32 ebx_in, u32 ecx_in,
{
APM_DECL_SEGS
unsigned long flags;
unsigned long cpus;
int cpu;
struct desc_struct save_desc_40;
cpus = apm_save_cpus();
cpu = get_cpu();
save_desc_40 = cpu_gdt_table[cpu][0x40 / 8];
cpu_gdt_table[cpu][0x40 / 8] = bad_bios_desc;
......@@ -601,6 +642,8 @@ static u8 apm_bios_call(u32 func, u32 ebx_in, u32 ecx_in,
local_irq_restore(flags);
cpu_gdt_table[cpu][0x40 / 8] = save_desc_40;
put_cpu();
apm_restore_cpus(cpus);
return *eax & 0xff;
}
......@@ -623,9 +666,13 @@ static u8 apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax)
u8 error;
APM_DECL_SEGS
unsigned long flags;
unsigned long cpus;
int cpu;
struct desc_struct save_desc_40;
cpus = apm_save_cpus();
cpu = get_cpu();
save_desc_40 = cpu_gdt_table[cpu][0x40 / 8];
cpu_gdt_table[cpu][0x40 / 8] = bad_bios_desc;
......@@ -657,6 +704,7 @@ static u8 apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax)
local_irq_restore(flags);
cpu_gdt_table[smp_processor_id()][0x40 / 8] = save_desc_40;
put_cpu();
apm_restore_cpus(cpus);
return error;
}
......@@ -772,7 +820,11 @@ static int apm_do_idle(void)
if (apm_bios_call_simple(APM_FUNC_IDLE, 0, 0, &eax)) {
static unsigned long t;
if (time_after(jiffies, t + 10 * HZ)) {
/* This always fails on some SMP boards running UP kernels.
* Only report the failure the first 5 times.
*/
if (++t < 5)
{
printk(KERN_DEBUG "apm_do_idle failed (%d)\n",
(eax >> 8) & 0xff);
t = jiffies;
......@@ -912,14 +964,16 @@ static void apm_power_off(void)
#ifdef CONFIG_SMP
/* Some bioses don't like being called from CPU != 0 */
if (smp_processor_id() != 0) {
current->cpus_allowed = 1;
schedule();
set_cpus_allowed(current, 1 << 0);
if (unlikely(smp_processor_id() != 0))
BUG();
}
#endif
if (apm_info.realmode_power_off)
{
(void)apm_save_cpus();
machine_real_restart(po_bios_call, sizeof(po_bios_call));
}
else
(void) set_system_power_state(APM_STATE_OFF);
}
......@@ -1096,6 +1150,19 @@ static int apm_console_blank(int blank)
}
if ((error == APM_SUCCESS) || (error == APM_NO_ERROR))
return 1;
if (error == APM_NOT_ENGAGED) {
static int tried;
int eng_error;
if (tried++ == 0) {
eng_error = apm_engage_power_management(APM_DEVICE_ALL, 1);
if (eng_error) {
apm_error("set display", error);
apm_error("engage interface", eng_error);
return 0;
} else
return apm_console_blank(blank);
}
}
apm_error("set display", error);
return 0;
}
......@@ -1424,7 +1491,7 @@ static ssize_t do_read(struct file *fp, char *buf, size_t count, loff_t *ppos)
as = fp->private_data;
if (check_apm_user(as, "read"))
return -EIO;
if (count < sizeof(apm_event_t))
if ((int)count < sizeof(apm_event_t))
return -EINVAL;
if ((queue_empty(as)) && (fp->f_flags & O_NONBLOCK))
return -EAGAIN;
......@@ -1693,8 +1760,7 @@ static int apm(void *unused)
* Method suggested by Ingo Molnar.
*/
if (smp_processor_id() != 0) {
current->cpus_allowed = 1;
schedule();
set_cpus_allowed(current, 1 << 0);
if (unlikely(smp_processor_id() != 0))
BUG();
}
......@@ -1746,7 +1812,7 @@ static int apm(void *unused)
}
}
if (debug) {
if (debug && (num_online_cpus() == 1 || smp )) {
error = apm_get_power_status(&bx, &cx, &dx);
if (error)
printk(KERN_INFO "apm: power status not available\n");
......@@ -1790,7 +1856,7 @@ static int apm(void *unused)
pm_power_off = apm_power_off;
register_sysrq_key('o', &sysrq_poweroff_op);
if (num_online_cpus() == 1) {
if (num_online_cpus() == 1 || smp) {
#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
console_blank_hook = apm_console_blank;
#endif
......@@ -1832,6 +1898,11 @@ static int __init apm_setup(char *str)
if ((strncmp(str, "power-off", 9) == 0) ||
(strncmp(str, "power_off", 9) == 0))
power_off = !invert;
if (strncmp(str, "smp", 3) == 0)
{
smp = !invert;
idle_threshold = 100;
}
if ((strncmp(str, "allow-ints", 10) == 0) ||
(strncmp(str, "allow_ints", 10) == 0))
apm_info.allow_ints = !invert;
......@@ -1934,7 +2005,7 @@ static int __init apm_init(void)
printk(KERN_NOTICE "apm: disabled on user request.\n");
return -ENODEV;
}
if ((num_online_cpus() > 1) && !power_off) {
if ((num_online_cpus() > 1) && !power_off && !smp) {
printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
return -ENODEV;
}
......@@ -1980,6 +2051,14 @@ static int __init apm_init(void)
(apm_info.bios.cseg_16_len - 1) & 0xffff);
_set_limit((char *)&cpu_gdt_table[i][APM_DS >> 3],
(apm_info.bios.dseg_len - 1) & 0xffff);
/* workaround for broken BIOSes */
if (apm_info.bios.cseg_len <= apm_info.bios.offset)
_set_limit((char *)&cpu_gdt_table[i][APM_CS >> 3], 64 * 1024 -1);
if (apm_info.bios.dseg_len <= 0x40) { /* 0x40 * 4kB == 64kB */
/* for the BIOS that assumes granularity = 1 */
cpu_gdt_table[i][APM_DS >> 3].b |= 0x800000;
printk(KERN_NOTICE "apm: we set the granularity of dseg.\n");
}
}
#endif
}
......@@ -1990,7 +2069,7 @@ static int __init apm_init(void)
kernel_thread(apm, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD);
if (num_online_cpus() > 1) {
if (num_online_cpus() > 1 && !smp ) {
printk(KERN_NOTICE
"apm: disabled - APM is not SMP safe (power off active).\n");
return 0;
......@@ -2058,3 +2137,7 @@ MODULE_PARM_DESC(idle_threshold,
MODULE_PARM(idle_period, "i");
MODULE_PARM_DESC(idle_period,
"Period (in sec/100) over which to caculate the idle percentage");
MODULE_PARM(smp, "i");
MODULE_PARM_DESC(smp,
"Set this to enable APM use on an SMP platform. Use with caution on older systems");
......@@ -194,10 +194,9 @@ struct resource mca_standard_resources[] = {
#define MCA_STANDARD_RESOURCES (sizeof(mca_standard_resources)/sizeof(struct resource))
void __init mca_init(void)
int __init mca_init(void)
{
unsigned int i, j;
unsigned long flags;
/* WARNING: Be careful when making changes here. Putting an adapter
* and the motherboard simultaneously into setup mode may result in
......@@ -209,16 +208,16 @@ void __init mca_init(void)
/* Make sure the MCA bus is present */
if(!MCA_bus)
return;
printk("Micro Channel bus detected.\n");
return -ENODEV;
printk(KERN_INFO "Micro Channel bus detected.\n");
/* Allocate MCA_info structure (at address divisible by 8) */
mca_info = (struct MCA_info *)kmalloc(sizeof(struct MCA_info), GFP_KERNEL);
if(mca_info == NULL) {
printk("Failed to allocate memory for mca_info!");
return;
printk(KERN_ERR "Failed to allocate memory for mca_info!");
return -ENOMEM;
}
memset(mca_info, 0, sizeof(struct MCA_info));
......@@ -320,6 +319,8 @@ void __init mca_init(void)
#ifdef CONFIG_PROC_FS
mca_do_proc_init();
#endif
return 0;
}
subsys_initcall(mca_init);
......@@ -329,16 +330,16 @@ subsys_initcall(mca_init);
static void mca_handle_nmi_slot(int slot, int check_flag)
{
if(slot < MCA_MAX_SLOT_NR) {
printk("NMI: caused by MCA adapter in slot %d (%s)\n", slot+1,
printk(KERN_CRIT "NMI: caused by MCA adapter in slot %d (%s)\n", slot+1,
mca_info->slot[slot].name);
} else if(slot == MCA_INTEGSCSI) {
printk("NMI: caused by MCA integrated SCSI adapter (%s)\n",
printk(KERN_CRIT "NMI: caused by MCA integrated SCSI adapter (%s)\n",
mca_info->slot[slot].name);
} else if(slot == MCA_INTEGVIDEO) {
printk("NMI: caused by MCA integrated video adapter (%s)\n",
printk(KERN_CRIT "NMI: caused by MCA integrated video adapter (%s)\n",
mca_info->slot[slot].name);
} else if(slot == MCA_MOTHERBOARD) {
printk("NMI: caused by motherboard (%s)\n",
printk(KERN_CRIT "NMI: caused by motherboard (%s)\n",
mca_info->slot[slot].name);
}
......@@ -350,7 +351,7 @@ static void mca_handle_nmi_slot(int slot, int check_flag)
pos6 = mca_read_pos(slot, 6);
pos7 = mca_read_pos(slot, 7);
printk("NMI: POS 6 = 0x%x, POS 7 = 0x%x\n", pos6, pos7);
printk(KERN_CRIT "NMI: POS 6 = 0x%x, POS 7 = 0x%x\n", pos6, pos7);
}
} /* mca_handle_nmi_slot */
......@@ -367,13 +368,12 @@ void mca_handle_nmi(void)
* adapter was responsible for the error.
*/
for(i = 0; i < MCA_NUMADAPTERS; i++) {
for(i = 0; i < MCA_NUMADAPTERS; i++)
{
/* Bit 7 of POS 5 is reset when this adapter has a hardware
* error. Bit 7 it reset if there's error information
* available in POS 6 and 7.
*/
pos5 = mca_read_pos(i, 5);
if(!(pos5 & 0x80)) {
......@@ -381,7 +381,6 @@ void mca_handle_nmi(void)
return;
}
}
mca_nmi_hook();
} /* mca_handle_nmi */
......
#
# 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
/* 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;
}
/* -*- 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);
/* -*- 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 */
/*
* 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);
}
/* 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;
}
#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);
/* 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("\nVOYAGER: 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();
}
This diff is collapsed.
This diff is collapsed.
/* -*- 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);
......@@ -157,6 +157,11 @@ CONFIG_PCMCIA
and ds.o. If you want to compile it as a module, say M here and
read <file:Documentation/modules.txt>.
CONFIG_KALLSYMS
Say Y here to let the kernel print out symbolic crash information and
symbolic stack backtraces. This increases the size of the kernel
somewhat, as all symbols have to be loaded into the kernel image.
CONFIG_KCORE_ELF
If you enabled support for /proc file system then the file
/proc/kcore will contain the kernel core image. This can be used
......
......@@ -33,44 +33,48 @@ ifeq ($(CONFIG_ITANIUM_BSTEP_SPECIFIC),y)
CFLAGS += -mb-step
endif
HEAD := arch/$(ARCH)/kernel/head.o arch/ia64/kernel/init_task.o
HEAD := arch/$(ARCH)/kernel/head.o arch/$(ARCH)/kernel/init_task.o
core-$(CONFIG_IA64_GENERIC) += arch/$(ARCH)/hp/ arch/$(ARCH)/dig/
core-$(CONFIG_IA64_HP_SIM) += arch/$(ARCH)/hp/
core-$(CONFIG_IA64_HP_ZX1) += arch/$(ARCH)/hp/ arch/$(ARCH)/dig/
core-$(CONFIG_IA64_SGI_SN) += arch/$(ARCH)/sn/kernel arch/$(ARCH)/sn/io
libs-y += arch/$(ARCH)/lib/
core-y += arch/$(ARCH)/kernel/ arch/$(ARCH)/mm/
core-$(CONFIG_IA32_SUPPORT) += arch/$(ARCH)/ia32/
core-$(CONFIG_IA64_DIG) += arch/$(ARCH)/dig/
core-$(CONFIG_IA64_GENERIC) += arch/$(ARCH)/dig/ arch/$(ARCH)/hp/common/ arch/$(ARCH)/hp/zx1/ \
arch/$(ARCH)/hp/sim/
core-$(CONFIG_IA64_HP_ZX1) += arch/$(ARCH)/dig/
core-$(CONFIG_IA64_SGI_SN) += arch/$(ARCH)/sn/kernel arch/$(ARCH)/sn/io \
arch/$(ARCH)/sn/fakeprom
drivers-$(CONFIG_PCI) += arch/$(ARCH)/pci/
drivers-$(CONFIG_IA64_HP_SIM) += arch/$(ARCH)/hp/sim/
drivers-$(CONFIG_IA64_HP_ZX1) += arch/$(ARCH)/hp/common/ arch/$(ARCH)/hp/zx1/
ifdef CONFIG_IA64_SGI_SN
CFLAGS += -DBRINGUP
SUBDIRS += arch/$(ARCH)/sn/fakeprom
endif
core-$(CONFIG_IA32_SUPPORT) += arch/$(ARCH)/ia32/
makeboot = $(call descend,arch/ia64/boot,$(1))
maketool = $(call descend,arch/ia64/tools,$(1))
libs-y += arch/$(ARCH)/lib/
core-y += arch/$(ARCH)/kernel/ arch/$(ARCH)/mm/
drivers-$(CONFIG_PCI) += arch/$(ARCH)/pci/
drivers-$(CONFIG_IA64_HP_ZX1) += arch/$(ARCH)/hp/common/ arch/$(ARCH)/hp/zx1/
.PHONY: compressed archclean archmrproper $(TOPDIR)/include/asm-ia64/offsets.h
all: compressed boot
MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
boot: vmlinux
+@$(call makeboot,all)
compressed: vmlinux
$(OBJCOPY) $(OBJCOPYFLAGS) vmlinux vmlinux-tmp
gzip vmlinux-tmp
mv vmlinux-tmp.gz vmlinux.gz
rawboot:
@$(MAKEBOOT) rawboot
archclean:
@$(MAKEBOOT) clean
$(MAKE) -rR -f scripts/Makefile.clean obj=arch/$(ARCH)/boot
archmrproper:
@$(MAKE) -C arch/$(ARCH)/tools mrproper
prepare: $(TOPDIR)/include/asm-ia64/offsets.h
$(TOPDIR)/include/asm-ia64/offsets.h: include/asm include/linux/version.h \
include/config/MARKER
@$(MAKE) -C arch/$(ARCH)/tools $@
+@$(call maketool,$@)
......@@ -8,9 +8,9 @@
# Copyright (C) 1998 by David Mosberger-Tang <davidm@hpl.hp.com>
#
LINKFLAGS = -static -T bootloader.lds
LINKFLAGS = -static -T $(src)/bootloader.lds
OBJECTS = bootloader.o
OBJS = $(obj)/bootloader.o
targets-$(CONFIG_IA64_HP_SIM) += bootloader
targets-$(CONFIG_IA64_GENERIC) += bootloader
......@@ -19,8 +19,8 @@ CFLAGS := $(CFLAGS) $(CFLAGS_KERNEL)
all: $(targets-y)
bootloader: $(OBJECTS)
$(LD) $(LINKFLAGS) $(OBJECTS) $(TOPDIR)/lib/lib.a $(TOPDIR)/arch/$(ARCH)/lib/lib.a \
bootloader: $(OBJS)
$(LD) $(LINKFLAGS) $(OBJS) $(TOPDIR)/lib/lib.a $(TOPDIR)/arch/$(ARCH)/lib/lib.a \
-o bootloader
clean:
......
......@@ -66,6 +66,10 @@ fi
if [ "$CONFIG_IA64_GENERIC" = "y" -o "$CONFIG_IA64_DIG" = "y" -o "$CONFIG_IA64_HP_ZX1" = "y" ];
then
bool ' Enable NUMA support' CONFIG_NUMA
if [ "$CONFIG_NUMA" = "y" ]; then
define_bool CONFIG_DISCONTIGMEM y
fi
bool ' Enable IA-64 Machine Check Abort' CONFIG_IA64_MCA
define_bool CONFIG_PM y
define_bool CONFIG_IOSAPIC y
......@@ -267,6 +271,7 @@ choice 'Physical memory granularity' \
bool 'Kernel debugging' CONFIG_DEBUG_KERNEL
if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then
bool ' Load all symbols for debugging/kksymoops' CONFIG_KALLSYMS
bool ' Print possible IA64 hazards to console' CONFIG_IA64_PRINT_HAZARDS
bool ' Disable VHPT' CONFIG_DISABLE_VHPT
bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ
......
This diff is collapsed.
# arch/ia64/hp/Makefile
# Copyright (c) 2002 Matthew Wilcox for Hewlett Packard
obj-$(CONFIG_IA64_GENERIC) += sim/ zx1/ common/
obj-$(CONFIG_IA64_HP_SIM) += sim/
include $(TOPDIR)/Rules.make
......@@ -359,7 +359,9 @@ simscsi_queuecommand (Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *))
break;
case MODE_SENSE:
printk("MODE_SENSE\n");
/* sd.c uses this to determine whether disk does write-caching. */
memset(sc->request_buffer, 0, 128);
sc->result = GOOD;
break;
case START_STOP:
......@@ -389,6 +391,4 @@ simscsi_queuecommand (Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *))
static Scsi_Host_Template driver_template = SIMSCSI;
#define __initcall(fn) late_initcall(fn)
#include "../drivers/scsi/scsi_module.c"
......@@ -752,8 +752,7 @@ static int get_async_struct(int line, struct async_struct **ret_info)
info->flags = sstate->flags;
info->xmit_fifo_size = sstate->xmit_fifo_size;
info->line = line;
info->tqueue.routine = do_softint;
info->tqueue.data = info;
INIT_WORK(&info->work, do_softint, info);
info->state = sstate;
if (sstate->info) {
kfree(info);
......
......@@ -26,6 +26,12 @@
#include <linux/if_ppp.h>
#include <linux/ixjuser.h>
#include <linux/i2o-dev.h>
#include <scsi/scsi.h>
/* Ugly hack. */
#undef __KERNEL__
#include <scsi/scsi_ioctl.h>
#define __KERNEL__
#include <scsi/sg.h>
#include <asm/ia32.h>
......@@ -60,6 +66,235 @@ put_dirent32 (struct dirent *d, struct linux32_dirent *d32)
|| put_user(d->d_reclen, &d32->d_reclen)
|| copy_to_user(d32->d_name, d->d_name, namelen + 1));
}
/*
* The transform code for the SG_IO ioctl was brazenly lifted from
* the Sparc64 port in the file `arch/sparc64/kernel/ioctl32.c'.
* Thanks to Jakub Jelinek & Eddie C. Dost.
*/
typedef struct sg_io_hdr32 {
int interface_id; /* [i] 'S' for SCSI generic (required) */
int dxfer_direction; /* [i] data transfer direction */
char cmd_len; /* [i] SCSI command length ( <= 16 bytes) */
char mx_sb_len; /* [i] max length to write to sbp */
short iovec_count; /* [i] 0 implies no scatter gather */
int dxfer_len; /* [i] byte count of data transfer */
int dxferp; /* [i], [*io] points to data transfer memory
or scatter gather list */
int cmdp; /* [i], [*i] points to command to perform */
int sbp; /* [i], [*o] points to sense_buffer memory */
int timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */
int flags; /* [i] 0 -> default, see SG_FLAG... */
int pack_id; /* [i->o] unused internally (normally) */
int usr_ptr; /* [i->o] unused internally */
char status; /* [o] scsi status */
char masked_status; /* [o] shifted, masked scsi status */
char msg_status; /* [o] messaging level data (optional) */
char sb_len_wr; /* [o] byte count actually written to sbp */
short host_status; /* [o] errors from host adapter */
short driver_status; /* [o] errors from software driver */
int resid; /* [o] dxfer_len - actual_transferred */
int duration; /* [o] time taken by cmd (unit: millisec) */
int info; /* [o] auxiliary information */
} sg_io_hdr32_t; /* 64 bytes long (on IA32) */
struct iovec32 { unsigned int iov_base; int iov_len; };
static int alloc_sg_iovec(sg_io_hdr_t *sgp, int uptr32)
{
struct iovec32 *uiov = (struct iovec32 *) P(uptr32);
sg_iovec_t *kiov;
int i;
sgp->dxferp = kmalloc(sgp->iovec_count *
sizeof(sg_iovec_t), GFP_KERNEL);
if (!sgp->dxferp)
return -ENOMEM;
memset(sgp->dxferp, 0,
sgp->iovec_count * sizeof(sg_iovec_t));
kiov = (sg_iovec_t *) sgp->dxferp;
for (i = 0; i < sgp->iovec_count; i++) {
int iov_base32;
if (__get_user(iov_base32, &uiov->iov_base) ||
__get_user(kiov->iov_len, &uiov->iov_len))
return -EFAULT;
kiov->iov_base = kmalloc(kiov->iov_len, GFP_KERNEL);
if (!kiov->iov_base)
return -ENOMEM;
if (copy_from_user(kiov->iov_base,
(void *) P(iov_base32),
kiov->iov_len))
return -EFAULT;
uiov++;
kiov++;
}
return 0;
}
static int copy_back_sg_iovec(sg_io_hdr_t *sgp, int uptr32)
{
struct iovec32 *uiov = (struct iovec32 *) P(uptr32);
sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp;
int i;
for (i = 0; i < sgp->iovec_count; i++) {
int iov_base32;
if (__get_user(iov_base32, &uiov->iov_base))
return -EFAULT;
if (copy_to_user((void *) P(iov_base32),
kiov->iov_base,
kiov->iov_len))
return -EFAULT;
uiov++;
kiov++;
}
return 0;
}
static void free_sg_iovec(sg_io_hdr_t *sgp)
{
sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp;
int i;
for (i = 0; i < sgp->iovec_count; i++) {
if (kiov->iov_base) {
kfree(kiov->iov_base);
kiov->iov_base = NULL;
}
kiov++;
}
kfree(sgp->dxferp);
sgp->dxferp = NULL;
}
static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
{
sg_io_hdr32_t *sg_io32;
sg_io_hdr_t sg_io64;
int dxferp32, cmdp32, sbp32;
mm_segment_t old_fs;
int err = 0;
sg_io32 = (sg_io_hdr32_t *)arg;
err = __get_user(sg_io64.interface_id, &sg_io32->interface_id);
err |= __get_user(sg_io64.dxfer_direction, &sg_io32->dxfer_direction);
err |= __get_user(sg_io64.cmd_len, &sg_io32->cmd_len);
err |= __get_user(sg_io64.mx_sb_len, &sg_io32->mx_sb_len);
err |= __get_user(sg_io64.iovec_count, &sg_io32->iovec_count);
err |= __get_user(sg_io64.dxfer_len, &sg_io32->dxfer_len);
err |= __get_user(sg_io64.timeout, &sg_io32->timeout);
err |= __get_user(sg_io64.flags, &sg_io32->flags);
err |= __get_user(sg_io64.pack_id, &sg_io32->pack_id);
sg_io64.dxferp = NULL;
sg_io64.cmdp = NULL;
sg_io64.sbp = NULL;
err |= __get_user(cmdp32, &sg_io32->cmdp);
sg_io64.cmdp = kmalloc(sg_io64.cmd_len, GFP_KERNEL);
if (!sg_io64.cmdp) {
err = -ENOMEM;
goto out;
}
if (copy_from_user(sg_io64.cmdp,
(void *) P(cmdp32),
sg_io64.cmd_len)) {
err = -EFAULT;
goto out;
}
err |= __get_user(sbp32, &sg_io32->sbp);
sg_io64.sbp = kmalloc(sg_io64.mx_sb_len, GFP_KERNEL);
if (!sg_io64.sbp) {
err = -ENOMEM;
goto out;
}
if (copy_from_user(sg_io64.sbp,
(void *) P(sbp32),
sg_io64.mx_sb_len)) {
err = -EFAULT;
goto out;
}
err |= __get_user(dxferp32, &sg_io32->dxferp);
if (sg_io64.iovec_count) {
int ret;
if ((ret = alloc_sg_iovec(&sg_io64, dxferp32))) {
err = ret;
goto out;
}
} else {
sg_io64.dxferp = kmalloc(sg_io64.dxfer_len, GFP_KERNEL);
if (!sg_io64.dxferp) {
err = -ENOMEM;
goto out;
}
if (copy_from_user(sg_io64.dxferp,
(void *) P(dxferp32),
sg_io64.dxfer_len)) {
err = -EFAULT;
goto out;
}
}
/* Unused internally, do not even bother to copy it over. */
sg_io64.usr_ptr = NULL;
if (err)
return -EFAULT;
old_fs = get_fs();
set_fs (KERNEL_DS);
err = sys_ioctl (fd, cmd, (unsigned long) &sg_io64);
set_fs (old_fs);
if (err < 0)
goto out;
err = __put_user(sg_io64.pack_id, &sg_io32->pack_id);
err |= __put_user(sg_io64.status, &sg_io32->status);
err |= __put_user(sg_io64.masked_status, &sg_io32->masked_status);
err |= __put_user(sg_io64.msg_status, &sg_io32->msg_status);
err |= __put_user(sg_io64.sb_len_wr, &sg_io32->sb_len_wr);
err |= __put_user(sg_io64.host_status, &sg_io32->host_status);
err |= __put_user(sg_io64.driver_status, &sg_io32->driver_status);
err |= __put_user(sg_io64.resid, &sg_io32->resid);
err |= __put_user(sg_io64.duration, &sg_io32->duration);
err |= __put_user(sg_io64.info, &sg_io32->info);
err |= copy_to_user((void *)P(sbp32), sg_io64.sbp, sg_io64.mx_sb_len);
if (sg_io64.dxferp) {
if (sg_io64.iovec_count)
err |= copy_back_sg_iovec(&sg_io64, dxferp32);
else
err |= copy_to_user((void *)P(dxferp32),
sg_io64.dxferp,
sg_io64.dxfer_len);
}
if (err)
err = -EFAULT;
out:
if (sg_io64.cmdp)
kfree(sg_io64.cmdp);
if (sg_io64.sbp)
kfree(sg_io64.sbp);
if (sg_io64.dxferp) {
if (sg_io64.iovec_count) {
free_sg_iovec(&sg_io64);
} else {
kfree(sg_io64.dxferp);
}
}
return err;
}
asmlinkage long
sys32_ioctl (unsigned int fd, unsigned int cmd, unsigned int arg)
......@@ -271,6 +506,9 @@ sys32_ioctl (unsigned int fd, unsigned int cmd, unsigned int arg)
default:
return sys_ioctl(fd, cmd, (unsigned long)arg);
case IOCTL_NR(SG_IO):
return(sg_ioctl_trans(fd, cmd, arg));
}
printk("%x:unimplemented IA32 ioctl system call\n", cmd);
return -EINVAL;
......
This diff is collapsed.
......@@ -2842,20 +2842,6 @@ putreg (struct task_struct *child, int regno, unsigned int value)
}
}
static inline void
ia32f2ia64f (void *dst, void *src)
{
asm volatile ("ldfe f6=[%1];; stf.spill [%0]=f6" :: "r"(dst), "r"(src) : "memory");
return;
}
static inline void
ia64f2ia32f (void *dst, void *src)
{
asm volatile ("ldf.fill f6=[%1];; stfe [%0]=f6" :: "r"(dst), "r"(src) : "memory");
return;
}
static void
put_fpreg (int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp,
int tos)
......
This diff is collapsed.
This diff is collapsed.
......@@ -2,7 +2,7 @@
* PAL & SAL emulation.
*
* Copyright (C) 1998-2001 Hewlett-Packard Co
* Copyright (C) 1998-2001 David Mosberger-Tang <davidm@hpl.hp.com>
* David Mosberger-Tang <davidm@hpl.hp.com>
*
* For the HP simulator, this file gets include in boot/bootloader.c.
* For SoftSDV, this file gets included in sys_softsdv.c.
......
......@@ -133,12 +133,8 @@ find_iosapic (unsigned int gsi)
return -1;
}
/*
* Translate GSI number to the corresponding IA-64 interrupt vector. If no
* entry exists, return -1.
*/
int
gsi_to_vector (unsigned int gsi)
static inline int
_gsi_to_vector (unsigned int gsi)
{
struct iosapic_intr_info *info;
......@@ -148,6 +144,26 @@ gsi_to_vector (unsigned int gsi)
return -1;
}
/*
* Translate GSI number to the corresponding IA-64 interrupt vector. If no
* entry exists, return -1.
*/
inline int
gsi_to_vector (unsigned int gsi)
{
return _gsi_to_vector(gsi);
}
int
gsi_to_irq (unsigned int gsi)
{
/*
* XXX fix me: this assumes an identity mapping vetween IA-64 vector and Linux irq
* numbers...
*/
return _gsi_to_vector(gsi);
}
static void
set_rte (unsigned int vector, unsigned int dest)
{
......@@ -157,7 +173,7 @@ set_rte (unsigned int vector, unsigned int dest)
int rte_index;
char redir;
DBG(KERN_DEBUG"IOSAPIC: routing vector %d to %x\n", vector, dest);
DBG(KERN_DEBUG"IOSAPIC: routing vector %d to 0x%x\n", vector, dest);
rte_index = iosapic_intr_info[vector].rte_index;
if (rte_index < 0)
......
......@@ -116,8 +116,8 @@ ENTRY(vhpt_miss)
;;
(p8) dep r25=r18,r25,2,6
(p8) shr r22=r22,HPAGE_SHIFT-PAGE_SHIFT
;;
#endif
;;
cmp.eq p6,p7=5,r17 // is IFA pointing into to region 5?
shr.u r18=r22,PGDIR_SHIFT // get bits 33-63 of the faulting address
;;
......
......@@ -1012,28 +1012,13 @@ ia64_log_prt_oem_data (int header_len, int sect_len, u8 *p_data, prfunc_t prfunc
void
ia64_log_rec_header_print (sal_log_record_header_t *lh, prfunc_t prfunc)
{
char str_buf[32];
sprintf(str_buf, "%2d.%02d",
(lh->revision.major >> 4) * 10 + (lh->revision.major & 0xf),
(lh->revision.minor >> 4) * 10 + (lh->revision.minor & 0xf));
prfunc("+Err Record ID: %d SAL Rev: %s\n", lh->id, str_buf);
sprintf(str_buf, "%02d/%02d/%04d/ %02d:%02d:%02d",
(lh->timestamp.slh_month >> 4) * 10 +
(lh->timestamp.slh_month & 0xf),
(lh->timestamp.slh_day >> 4) * 10 +
(lh->timestamp.slh_day & 0xf),
(lh->timestamp.slh_century >> 4) * 1000 +
(lh->timestamp.slh_century & 0xf) * 100 +
(lh->timestamp.slh_year >> 4) * 10 +
(lh->timestamp.slh_year & 0xf),
(lh->timestamp.slh_hour >> 4) * 10 +
(lh->timestamp.slh_hour & 0xf),
(lh->timestamp.slh_minute >> 4) * 10 +
(lh->timestamp.slh_minute & 0xf),
(lh->timestamp.slh_second >> 4) * 10 +
(lh->timestamp.slh_second & 0xf));
prfunc("+Time: %s Severity %d\n", str_buf, lh->severity);
prfunc("+Err Record ID: %d SAL Rev: %2x.%02x\n", lh->id,
lh->revision.major, lh->revision.minor);
prfunc("+Time: %02x/%02x/%02x%02x %02x:%02x:%02x Severity %d\n",
lh->timestamp.slh_month, lh->timestamp.slh_day,
lh->timestamp.slh_century, lh->timestamp.slh_year,
lh->timestamp.slh_hour, lh->timestamp.slh_minute,
lh->timestamp.slh_second, lh->severity);
}
/*
......
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.
......@@ -54,8 +54,8 @@ trap_init (void)
if (ia64_boot_param->fpswa) {
/* FPSWA fixup: make the interface pointer a kernel virtual address: */
fpswa_interface = __va(ia64_boot_param->fpswa);
major = fpswa_interface->revision & 0xffff;
minor = fpswa_interface->revision >> 16;
major = fpswa_interface->revision >> 16;
minor = fpswa_interface->revision & 0xffff;
}
printk("fpswa interface at %lx (rev %d.%d)\n", ia64_boot_param->fpswa, major, minor);
}
......@@ -69,7 +69,6 @@ bust_spinlocks (int yes)
{
int loglevel_save = console_loglevel;
spin_lock_init(&timerlist_lock);
if (yes) {
oops_in_progress = 1;
return;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment