/* 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/module.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 <linux/sysrq.h>
#include <asm/io.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>
#include <asm/i8253.h>

/*
 * Power off function, if any
 */
void (*pm_power_off)(void);

int voyager_level = 0;

struct voyager_SUS *voyager_SUS = NULL;

#ifdef CONFIG_SMP
static void
voyager_dump(int dummy1, struct pt_regs *dummy2, struct tty_struct *dummy3)
{
	/* get here via a sysrq */
	voyager_smp_dump();
}

static struct sysrq_key_op sysrq_voyager_dump_op = {
	.handler	= voyager_dump,
	.help_msg	= "Voyager",
	.action_msg	= "Dump Voyager Status",
};
#endif

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;
#ifdef CONFIG_SMP
		register_sysrq_key('v', &sysrq_voyager_dump_op);
#endif
	} 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;
}

/* 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;

		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");
	}
}

EXPORT_SYMBOL(machine_restart);

void
mca_nmi_hook(void)
{
	__u8 dumpval __attribute__((unused)) = inb(0xf823);
	__u8 swnmi __attribute__((unused)) = inb(0xf813);

	/* 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, NULL);
	show_state();
}



void
machine_halt(void)
{
	/* treat a halt like a power off */
	machine_power_off();
}

EXPORT_SYMBOL(machine_halt);

void machine_power_off(void)
{
	if (pm_power_off)
		pm_power_off();
}

EXPORT_SYMBOL(machine_power_off);
