/* $Id: setup.c,v 1.25 2000/09/27 10:00:11 pkj Exp $
 *
 *  linux/arch/etrax100/kernel/setup.c
 *
 *  Copyright (C) 1995  Linus Torvalds
 *  Copyright (C) 1999  Axis Communications AB
 */

/*
 * This file handles the architecture-dependent parts of initialization
 */

#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/malloc.h>
#include <linux/ldt.h>
#include <linux/user.h>
#include <linux/a.out.h>
#include <linux/tty.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/config.h>
#ifdef CONFIG_APM
#include <linux/apm_bios.h>
#endif
#ifdef CONFIG_BLK_DEV_RAM
#include <linux/blk.h>
#endif
#include <asm/segment.h>
#include <asm/system.h>
#include <asm/smp.h>

#include <asm/types.h>

#include <asm/svinto.h>

/*
 * Setup options
 */
struct drive_info_struct { char dummy[32]; } drive_info;
struct screen_info screen_info;
#ifdef CONFIG_APM
struct apm_bios_info apm_bios_info;
#endif

unsigned char aux_device_present;

#ifdef CONFIG_BLK_DEV_RAM
extern int rd_doload;		/* 1 = load ramdisk, 0 = don't load */
extern int rd_prompt;		/* 1 = prompt for ramdisk, 0 = don't prompt */
extern int rd_image_start;	/* starting block # of image */
#endif

extern int root_mountflags;
extern char _etext, _edata, _end;

extern char empty_zero_page[PAGE_SIZE];

/*
 * This is set up by the setup-routine at boot-time
 */

/* E: These will have to change */

#if 0
#define PARAM	empty_zero_page
#define EXT_MEM_K (*(unsigned short *) (PARAM+2))
#ifdef CONFIG_APM
#define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+64))
#endif
#define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80))
#define SCREEN_INFO (*(struct screen_info *) (PARAM+0))
#define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAM+0x1F2))
#define RAMDISK_FLAGS (*(unsigned short *) (PARAM+0x1F8))
#define ORIG_ROOT_DEV (*(unsigned short *) (PARAM+0x1FC))
#define AUX_DEVICE_INFO (*(unsigned char *) (PARAM+0x1FF))
#define LOADER_TYPE (*(unsigned char *) (PARAM+0x210))
#define KERNEL_START (*(unsigned long *) (PARAM+0x214))
#define INITRD_START (*(unsigned long *) (PARAM+0x218))
#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
#define COMMAND_LINE ((char *) (PARAM+2048))

#define RAMDISK_IMAGE_START_MASK  	0x07FF
#define RAMDISK_PROMPT_FLAG		0x8000
#define RAMDISK_LOAD_FLAG		0x4000	
#endif

#define COMMAND_LINE_SIZE 256

static char command_line[COMMAND_LINE_SIZE] = { 0, };
       char saved_command_line[COMMAND_LINE_SIZE];

extern const unsigned long text_start, edata; /* set by the linker script */

extern unsigned long romfs_start, romfs_length, running_from_flash; /* from head.S */

void setup_arch(char **cmdline_p,
	unsigned long * memory_start_p, unsigned long * memory_end_p)
{
	unsigned long memory_start, memory_end;
	extern void console_print_etrax(const char *b);
#if 0
	char c = ' ', *to = command_line, *from = COMMAND_LINE;
	int len = 0;
#endif

#if (defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH))
	/* we need to initialize the Flashrom device here since we might want to flash below */

	flash_probe();
	/* this is disabled for now. because we have a real flash loader. */
#if 0 && !defined(CONFIG_SVINTO_SIM) && !defined(CONFIG_ETRAX_PB_LEDS)
	/* now check if we want to Flash this image into flash */

	if(!running_from_flash && !(*R_PORT_PA_READ & 0x2)) {
		int len;
		/* the switch was depressed, so do some erasing and flashing */
		flash_erase_all();
		len = (unsigned long)&edata - (unsigned long)&text_start;
		/* write the kernel text and data segments to flash adr 0 */
		flash_write(0, &text_start, len);
		/* write the ROM filesystem image after that */
		flash_write(0 + len, romfs_start, romfs_length);
		printk("Flashed kernel and ROMFS.\n");
	}
#endif
#endif

 	/* register an initial console printing routine for printk's */
        register_console(console_print_etrax);

	/* we should really poll for DRAM size! */
	memory_end = (unsigned long) &dram_end;

	if(running_from_flash || !romfs_length) {
		/* if we boot from flash, or if there is no rom filesystem,
		 * our free area starts directly after the BSS 
		 */
		memory_start = (unsigned long) &_end;
	} else {
		/* otherwise the free area starts after the ROM filesystem */
		printk("ROM fs in RAM, size %d bytes\n", romfs_length);
		memory_start = romfs_start + romfs_length;
	}

	/* E: Initialises the original task (this one) in a
	   task_struct to be placed in the process table */

	init_task.mm->start_code = (unsigned long) &text_start;
	init_task.mm->end_code = (unsigned long) &_etext;
	init_task.mm->end_data = (unsigned long) &_edata;
	init_task.mm->brk = (unsigned long) &_end;

	/* Save unparsed command line copy for /proc/cmdline */
	/*	memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';*/


	/* E: Parses the commandline for platform specific options */

	/*	for (;;) {
		if (c == ' ' && *(const unsigned long *)from == *(const unsigned long *)"mem=") {
			if (to != command_line) to--;
			if (!memcmp(from+4, "nopentium", 9)) {
				from += 9+4;
				x86_capability &= ~8;
			} else {
				memory_end = simple_strtoul(from+4, &from, 0);
				if ( *from == 'K' || *from == 'k' ) {
					memory_end = memory_end << 10;
					from++;
				} else if ( *from == 'M' || *from == 'm' ) {
					memory_end = memory_end << 20;
					from++;
				}
			}
	        }
		c = *(from++);
		if (!c)
			break;
		if (COMMAND_LINE_SIZE <= ++len)
			break;
		*(to++) = c;
	}
	*to = '\0';
	*/

	/* we dont use a command line yet, so just let it be an empty string */

	*cmdline_p = command_line;
	strcpy(command_line, "root=/dev/rom"); /* use the appended romdisk as root */

	/* E: Sets the static pointers to the value calculated in this procedure */
	*memory_start_p = memory_start;
	*memory_end_p = memory_end;


	/* this is only if we want to place the kernel in ram before we boot 
	   we dont, cos we have the initial romdisk instead */

#ifdef CONFIG_BLK_DEV_INITRD
	if (LOADER_TYPE) {
		initrd_start = INITRD_START;
		initrd_end = INITRD_START+INITRD_SIZE;
		if (initrd_end > memory_end) {
			printk("initrd extends beyond end of memory "
			    "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
			    initrd_end,memory_end);
			initrd_start = 0;
		}
	}
#endif

	/* give credit for the CRIS port */

	printk("Linux/CRIS-NOMMU port, Copyright (c) 1999, 2000 Axis Communications AB\n");

	/* give credit for the NO_MM patches */

	printk("Flat model support, Copyright (c) 1998 Kenneth Albanowski, "
	       "D. Jeff Dionne, TSHG Ltd.\n");

}

#ifdef CONFIG_PROC_FS
#define HAS_FPU		0x0001
#define HAS_MMU		0x0002
#define HAS_ETHERNET100	0x0004
#define HAS_TOKENRING	0x0008
#define HAS_SCSI	0x0010
#define HAS_ATA		0x0020
#define HAS_USB		0x0040
#define HAS_IRQ_BUG	0x0080

static struct cpu_info {
	char *model;
	unsigned short cache;
	unsigned short flags;
} cpu_info[] = {
	{ "Etrax 1",     0, 0 },
	{ "Etrax 2",     0, 0 },	/* Don't say it HAS_TOKENRING - there
					   are lethal bugs in that chip that
					   prevents T-R from ever working.
					   Never go there, and never lead
					   anyone into believing it can work.
					   BTW: Anyone working on a T-R network
					   driver? :-) :-) :-) :-/ */
	{ "Etrax 3",     0, HAS_TOKENRING },
	{ "Etrax 4",     0, HAS_TOKENRING | HAS_SCSI },
	{ "Unknown",     0, 0 },
	{ "Unknown",     0, 0 },
	{ "Unknown",     0, 0 },
	{ "Simulator",   8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA },
	{ "Etrax 100",   8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_IRQ_BUG },
	{ "Etrax 100",   8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA },
	{ "Unknown",     0, 0 },
};

/*
 * BUFFER is PAGE_SIZE bytes long.
 */
int get_cpuinfo(char *buffer)
{
	int revision;
	unsigned char tmp;

#ifndef CONFIG_SVINTO_SIM
	__asm__ volatile ("move vr,%0" : "=rm" (tmp));
	revision = tmp;
#else
        /* Fake a revision for the simulator */
	revision = 7;
#endif

	return sprintf(buffer,
		       "cpu\t\t: Etrax\n"
		       "cpu revision\t: %d\n"
		       "cpu model\t: %s\n"
		       "cache size\t: %d kB\n"
		       "fpu\t\t: %s\n"
		       "mmu\t\t: %s\n"
		       "ethernet\t: %s Mbps\n"
		       "token ring\t: %s\n"
		       "scsi\t\t: %s\n"
		       "ata\t\t: %s\n"
		       "usb\t\t: %s\n"
		       "irq bug\t\t: %s\n"
		       "bogomips\t: %lu.%02lu\n",

		       revision,
		       cpu_info[revision].model,
		       cpu_info[revision].cache,
		       cpu_info[revision].flags & HAS_FPU ? "yes" : "no",
		       cpu_info[revision].flags & HAS_MMU ? "yes" : "no",
		       cpu_info[revision].flags & HAS_ETHERNET100 ? "10/100" : "10",
		       cpu_info[revision].flags & HAS_TOKENRING ? "4/16 Mbps" : "no",
		       cpu_info[revision].flags & HAS_SCSI ? "yes" : "no",
		       cpu_info[revision].flags & HAS_ATA ? "yes" : "no",
		       cpu_info[revision].flags & HAS_USB ? "yes" : "no",
		       cpu_info[revision].flags & HAS_IRQ_BUG ? "yes" : "no",
		       (loops_per_sec+500) / 100000,
		       ((loops_per_sec+500) / 1000) % 100);
}
#endif /* CONFIG_PROC_FS */
