diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-07-10 01:14:47 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-07-10 01:14:47 +0000 |
commit | cf00b9f677c32c4f0ad187bed33e7bf2209db3b8 (patch) | |
tree | 6091370501637f7d42c529bc35454aa0719f35d6 /arch/mips/sgi | |
parent | 683c16eb00d32d749c1038f5fd9032d8543e5697 (diff) |
o Support for the front panel on the Indy. The panel work now as a
user would expect it to work, like under IRIX with the exception
that the machine doesn't freeze solid as long as the button is
pressed.
o Realtime clock driver (CONFIG_SGI_DS1286) for the Indy. Includes
/proc/rtc interface which tells you everything about your RTC which
you never wanted to know. You have to configure this driver into
your kernel or you won't be able to set your RTC.
o Some cleanup of the RTC interfaces in Linux, RTC does no longer mean
PC-style RTC. The userland interface definitions are now in
<linux/rtc.h>. We still need some more cleanup until we can enable
several RTC drivers.
o Virtual aliasing fixes for ptrace(2).
o Add ptrace(2) interface definitions needed to build GDB to
<asm/ptrace.h>.
o Revert to some older routines, the newer optimized ones are buggy.
o On panic the Indy LED will be blinking fast crying to the admin
passing by [music from Rocky Horror show] ``fix me, fix me, fix
me''.
o On panic the power button will only reboot the machine, not power it
down. That's probably more what people want it to do.
o Remove some old files.
o Did I tell you that CVS is buggy?
Diffstat (limited to 'arch/mips/sgi')
-rw-r--r-- | arch/mips/sgi/kernel/indy_hpc.c | 28 | ||||
-rw-r--r-- | arch/mips/sgi/kernel/reset.c | 185 | ||||
-rw-r--r-- | arch/mips/sgi/kernel/setup.c | 18 | ||||
-rw-r--r-- | arch/mips/sgi/prom/misc.c | 8 |
4 files changed, 194 insertions, 45 deletions
diff --git a/arch/mips/sgi/kernel/indy_hpc.c b/arch/mips/sgi/kernel/indy_hpc.c index eb00fe55c..eb62c3150 100644 --- a/arch/mips/sgi/kernel/indy_hpc.c +++ b/arch/mips/sgi/kernel/indy_hpc.c @@ -3,7 +3,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: indy_hpc.c,v 1.2 1998/03/27 08:53:43 ralf Exp $ + * $Id: indy_hpc.c,v 1.2 1998/04/05 11:23:57 ralf Exp $ */ #include <linux/init.h> @@ -20,27 +20,13 @@ struct hpc3_regs *hpc3c0, *hpc3c1; struct hpc3_miscregs *hpc3mregs; /* We need software copies of these because they are write only. */ -static unsigned long write1, write2; +unsigned long sgi_hpc_write1, sgi_hpc_write2; /* Machine specific identifier knobs. */ int sgi_has_ioc2 = 0; int sgi_guiness = 0; int sgi_boardid; -void sgihpc_write1_modify(int set, int clear) -{ - write1 |= set; - write1 &= ~clear; - hpc3mregs->write1 = write1; -} - -void sgihpc_write2_modify(int set, int clear) -{ - write2 |= set; - write2 &= ~clear; - hpc3mregs->write2 = write2; -} - __initfunc(void sgihpc_init(void)) { unsigned long sid, crev, brev; @@ -96,12 +82,12 @@ __initfunc(void sgihpc_init(void)) prom_printf("\n"); #endif - write1 = (HPC3_WRITE1_PRESET | + sgi_hpc_write1 = (HPC3_WRITE1_PRESET | HPC3_WRITE1_KMRESET | HPC3_WRITE1_ERESET | HPC3_WRITE1_LC0OFF); - write2 = (HPC3_WRITE2_EASEL | + sgi_hpc_write2 = (HPC3_WRITE2_EASEL | HPC3_WRITE2_NTHRESH | HPC3_WRITE2_TPSPEED | HPC3_WRITE2_EPSEL | @@ -109,9 +95,9 @@ __initfunc(void sgihpc_init(void)) HPC3_WRITE2_U1AMODE); if(!sgi_guiness) - write1 |= HPC3_WRITE1_GRESET; - hpc3mregs->write1 = write1; - hpc3mregs->write2 = write2; + sgi_hpc_write1 |= HPC3_WRITE1_GRESET; + hpc3mregs->write1 = sgi_hpc_write1; + hpc3mregs->write2 = sgi_hpc_write2; hpc3c0->pbus_piocfgs[0][6] |= HPC3_PIOPCFG_HW; } diff --git a/arch/mips/sgi/kernel/reset.c b/arch/mips/sgi/kernel/reset.c index e465208cf..e6a58fa58 100644 --- a/arch/mips/sgi/kernel/reset.c +++ b/arch/mips/sgi/kernel/reset.c @@ -1,31 +1,200 @@ -/* - * Reset a SGI. +/* $Id: reset.c,v 1.6 1998/07/09 19:57:47 ralf Exp $ + * + * Reset a SGI. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 1997, 1998 by Ralf Baechle - * - * $Id: reset.c,v 1.3 1998/03/26 07:31:16 ralf Exp $ */ +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/notifier.h> +#include <linux/timer.h> #include <asm/io.h> +#include <asm/irq.h> #include <asm/system.h> #include <asm/reboot.h> #include <asm/sgialib.h> +#include <asm/sgihpc.h> +#include <asm/sgint23.h> + +/* + * Just powerdown if init hasn't done after POWERDOWN_TIMEOUT seconds. + * I'm not shure if this feature is a good idea, for now it's here just to + * make the power button make behave just like under IRIX. + */ +#define POWERDOWN_TIMEOUT 120 + +/* + * Blink frequency during reboot grace period and when paniced. + */ +#define POWERDOWN_FREQ (HZ / 4) +#define PANIC_FREQ (HZ / 8) + +static struct timer_list power_timer, blink_timer, debounce_timer; +static int shuting_down, has_paniced; + +static void sgi_machine_restart(char *command) __attribute__((noreturn)); +static void sgi_machine_halt(void) __attribute__((noreturn)); +static void sgi_machine_power_off(void) __attribute__((noreturn)); /* XXX How to pass the reboot command to the firmware??? */ -void sgi_machine_restart(char *command) +static void sgi_machine_restart(char *command) { + if (shuting_down) + sgi_machine_power_off(); prom_reboot(); } -void sgi_machine_halt(void) +static void sgi_machine_halt(void) { + if (shuting_down) + sgi_machine_power_off(); prom_imode(); } -void sgi_machine_power_off(void) +static void sgi_machine_power_off(void) +{ + struct indy_clock *clock = (struct indy_clock *)INDY_CLOCK_REGS; + + cli(); + + clock->cmd |= 0x08; /* Disable watchdog */ + clock->whsec = 0; + clock->wsec = 0; + + while(1) { + hpc3mregs->panel=0xfe; + /* Good bye cruel world ... */ + + /* If we're still running, we probably got sent an alarm + interrupt. Read the flag to clear it. */ + clock->halarm; + } +} + +static void power_timeout(unsigned long data) +{ + sgi_machine_power_off(); +} + +static void blink_timeout(unsigned long data) { - prom_powerdown(); + /* XXX fix this for fullhouse */ + sgi_hpc_write1 ^= (HPC3_WRITE1_LC0OFF|HPC3_WRITE1_LC1OFF); + hpc3mregs->write1 = sgi_hpc_write1; + + del_timer(&blink_timer); + blink_timer.expires = jiffies + data; + add_timer(&blink_timer); +} + +static void debounce(unsigned long data) +{ + del_timer(&debounce_timer); + if (ioc_icontrol->istat1 & 2) { /* Interrupt still being sent. */ + debounce_timer.expires = jiffies + 5; /* 0.05s */ + add_timer(&debounce_timer); + + hpc3mregs->panel = 0xf3; + + return; + } + + if (has_paniced) + prom_reboot(); + + enable_irq(9); +} + +static inline void power_button(void) +{ + if (has_paniced) + return; + + if (shuting_down || kill_proc(1, SIGINT, 1)) { + /* No init process or button pressed twice. */ + sgi_machine_power_off(); + } + + shuting_down = 1; + blink_timer.data = POWERDOWN_FREQ; + blink_timeout(POWERDOWN_FREQ); + + init_timer(&power_timer); + power_timer.function = power_timeout; + power_timer.expires = jiffies + POWERDOWN_TIMEOUT * HZ; + add_timer(&power_timer); +} + +static inline void volume_up_button(void) +{ + /* Later when we have sound support ... */ +} + +static inline void volume_down_button(void) +{ + /* Later when we have sound support ... */ +} + +static void panel_int(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned int buttons; + + buttons = hpc3mregs->panel; + hpc3mregs->panel = 3; /* power_interrupt | power_supply_on */ + + if (ioc_icontrol->istat1 & 2) { /* Wait until interrupt goes away */ + disable_irq(9); + init_timer(&debounce_timer); + debounce_timer.function = debounce; + debounce_timer.expires = jiffies + 5; + add_timer(&debounce_timer); + } + + if (!(buttons & 2)) /* Power button was pressed */ + power_button(); + if (!(buttons & 0x40)) /* Volume up button was pressed */ + volume_up_button(); + if (!(buttons & 0x10)) /* Volume down button was pressed */ + volume_down_button(); +} + +static int panic_event(struct notifier_block *this, unsigned long event, + void *ptr) +{ + if (has_paniced) + return NOTIFY_DONE; + has_paniced = 1; + + blink_timer.data = PANIC_FREQ; + blink_timeout(PANIC_FREQ); + + return NOTIFY_DONE; +} + +static struct notifier_block panic_block = { + panic_event, + NULL, + 0 +}; + +void indy_reboot_setup(void) +{ + static int setup_done; + + if (setup_done) + return; + setup_done = 1; + + _machine_restart = sgi_machine_restart; + _machine_halt = sgi_machine_halt; + _machine_power_off = sgi_machine_power_off; + + request_irq(9, panel_int, 0, "Front Panel", NULL); + init_timer(&blink_timer); + blink_timer.function = blink_timeout; + notifier_chain_register(&panic_notifier_list, &panic_block); } diff --git a/arch/mips/sgi/kernel/setup.c b/arch/mips/sgi/kernel/setup.c index 9699f812c..451c785f2 100644 --- a/arch/mips/sgi/kernel/setup.c +++ b/arch/mips/sgi/kernel/setup.c @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.9 1998/05/07 02:57:21 ralf Exp $ +/* $Id: setup.c,v 1.10 1998/06/30 00:21:58 ralf Exp $ * * setup.c: SGI specific setup, including init of the feature struct. * @@ -24,11 +24,8 @@ extern int serial_console; /* in console.c, of course */ -extern void sgi_machine_restart(char *command); -extern void sgi_machine_halt(void); -extern void sgi_machine_power_off(void); - extern struct rtc_ops indy_rtc_ops; +void indy_reboot_setup(void); static volatile struct hpc_keyb *sgi_kh = (struct hpc_keyb *) (KSEG1 + 0x1fbd9800 + 64); @@ -70,6 +67,13 @@ __initfunc(static void sgi_keyboard_setup(void)) kbd_write_output = sgi_write_output; kbd_write_command = sgi_write_command; kbd_read_status = sgi_read_status; + + /* Dirty hack, this get's called as a callback from the keyboard + driver. We piggyback the initialization of the front panel + button handling on it even though they're technically not + related with the keyboard driver in any way. Doing it from + indy_setup wouldn't work since kmalloc isn't initialized yet. */ + indy_reboot_setup(); } __initfunc(static void sgi_irq_setup(void)) @@ -84,10 +88,6 @@ __initfunc(void sgi_setup(void)) irq_setup = sgi_irq_setup; keyboard_setup = sgi_keyboard_setup; - _machine_restart = sgi_machine_restart; - _machine_halt = sgi_machine_halt; - _machine_power_off = sgi_machine_power_off; - /* Init the INDY HPC I/O controller. Need to call this before * fucking with the memory controller because it needs to know the * boardID and whether this is a Guiness or a FullHouse machine. diff --git a/arch/mips/sgi/prom/misc.c b/arch/mips/sgi/prom/misc.c index 8d7c300c7..d0072228c 100644 --- a/arch/mips/sgi/prom/misc.c +++ b/arch/mips/sgi/prom/misc.c @@ -3,7 +3,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: misc.c,v 1.5 1998/03/27 08:53:47 ralf Exp $ + * $Id: misc.c,v 1.3 1998/04/05 11:24:03 ralf Exp $ */ #include <linux/config.h> #include <linux/init.h> @@ -15,14 +15,12 @@ #include <asm/system.h> extern unsigned long mips_cputype; -extern int initialize_kbd(void); extern void *sgiwd93_host; extern void reset_wd33c93(void *instance); void prom_halt(void) { bcops->bc_disable(); - initialize_kbd(); cli(); #if CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); @@ -33,7 +31,6 @@ void prom_halt(void) void prom_powerdown(void) { bcops->bc_disable(); - initialize_kbd(); cli(); #if CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); @@ -45,7 +42,6 @@ void prom_powerdown(void) void prom_restart(void) { bcops->bc_disable(); - initialize_kbd(); cli(); #if CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); @@ -56,7 +52,6 @@ void prom_restart(void) void prom_reboot(void) { bcops->bc_disable(); - initialize_kbd(); cli(); #if CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); @@ -67,7 +62,6 @@ void prom_reboot(void) void prom_imode(void) { bcops->bc_disable(); - initialize_kbd(); cli(); #if CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); |