1/* 2 * arch/v850/kernel/sim.c -- Machine-specific stuff for GDB v850e simulator 3 * 4 * Copyright (C) 2001,02 NEC Corporation 5 * Copyright (C) 2001,02 Miles Bader <miles@gnu.org> 6 * 7 * This file is subject to the terms and conditions of the GNU General 8 * Public License. See the file COPYING in the main directory of this 9 * archive for more details. 10 * 11 * Written by Miles Bader <miles@gnu.org> 12 */ 13 14#include <linux/kernel.h> 15#include <linux/module.h> 16#include <linux/init.h> 17#include <linux/mm.h> 18#include <linux/swap.h> 19#include <linux/bootmem.h> 20#include <linux/irq.h> 21 22#include <asm/atomic.h> 23#include <asm/page.h> 24#include <asm/machdep.h> 25#include <asm/simsyscall.h> 26 27#include "mach.h" 28 29/* The name of a file containing the root filesystem. */ 30#define ROOT_FS "rootfs.image" 31 32extern void simcons_setup (void); 33extern void simcons_poll_ttys (void); 34extern void set_mem_root (void *addr, size_t len, char *cmd_line); 35 36static int read_file (const char *name, 37 unsigned long *addr, unsigned long *len, 38 const char **err); 39 40void __init mach_setup (char **cmdline) 41{ 42 const char *err; 43 unsigned long root_dev_addr, root_dev_len; 44 45 simcons_setup (); 46 47 printk (KERN_INFO "Reading root filesystem: %s", ROOT_FS); 48 49 if (read_file (ROOT_FS, &root_dev_addr, &root_dev_len, &err)) { 50 printk (" (size %luK)\n", root_dev_len / 1024); 51 set_mem_root ((void *)root_dev_addr, (size_t)root_dev_len, 52 *cmdline); 53 } else 54 printk ("...%s failed!\n", err); 55} 56 57void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len) 58{ 59 *ram_start = RAM_ADDR; 60 *ram_len = RAM_SIZE; 61} 62 63void __init mach_sched_init (struct irqaction *timer_action) 64{ 65 /* ...do magic timer initialization?... */ 66 mach_tick = simcons_poll_ttys; 67 setup_irq (0, timer_action); 68} 69 70 71static void irq_nop (unsigned irq) { } 72static unsigned irq_zero (unsigned irq) { return 0; } 73 74static struct hw_interrupt_type sim_irq_type = { 75 .typename = "IRQ", 76 .startup = irq_zero, /* startup */ 77 .shutdown = irq_nop, /* shutdown */ 78 .enable = irq_nop, /* enable */ 79 .disable = irq_nop, /* disable */ 80 .ack = irq_nop, /* ack */ 81 .end = irq_nop, /* end */ 82}; 83 84void __init mach_init_irqs (void) 85{ 86 init_irq_handlers (0, NUM_MACH_IRQS, 1, &sim_irq_type); 87} 88 89 90void mach_gettimeofday (struct timespec *tv) 91{ 92 long timeval[2], timezone[2]; 93 int rval = V850_SIM_SYSCALL (gettimeofday, timeval, timezone); 94 if (rval == 0) { 95 tv->tv_sec = timeval[0]; 96 tv->tv_nsec = timeval[1] * 1000; 97 } 98} 99 100void machine_restart (char *__unused) 101{ 102 V850_SIM_SYSCALL (write, 1, "RESTART\n", 8); 103 V850_SIM_SYSCALL (exit, 0); 104} 105 106void machine_halt (void) 107{ 108 V850_SIM_SYSCALL (write, 1, "HALT\n", 5); 109 V850_SIM_SYSCALL (exit, 0); 110} 111 112void machine_power_off (void) 113{ 114 V850_SIM_SYSCALL (write, 1, "POWER OFF\n", 10); 115 V850_SIM_SYSCALL (exit, 0); 116} 117 118 119/* Load data from a file called NAME into ram. The address and length 120 of the data image are returned in ADDR and LEN. */ 121static int __init 122read_file (const char *name, 123 unsigned long *addr, unsigned long *len, 124 const char **err) 125{ 126 int rval, fd; 127 unsigned long cur, left; 128 /* Note this is not a normal stat buffer, it's an ad-hoc 129 structure defined by the simulator. */ 130 unsigned long stat_buf[10]; 131 132 /* Stat the file to find out the length. */ 133 rval = V850_SIM_SYSCALL (stat, name, stat_buf); 134 if (rval < 0) { 135 if (err) *err = "stat"; 136 return 0; 137 } 138 *len = stat_buf[4]; 139 140 /* Open the file; `0' is O_RDONLY. */ 141 fd = V850_SIM_SYSCALL (open, name, 0); 142 if (fd < 0) { 143 if (err) *err = "open"; 144 return 0; 145 } 146 147 *addr = (unsigned long)alloc_bootmem(*len); 148 if (! *addr) { 149 V850_SIM_SYSCALL (close, fd); 150 if (err) *err = "alloc_bootmem"; 151 return 0; 152 } 153 154 cur = *addr; 155 left = *len; 156 while (left > 0) { 157 int chunk = V850_SIM_SYSCALL (read, fd, cur, left); 158 if (chunk <= 0) 159 break; 160 cur += chunk; 161 left -= chunk; 162 } 163 V850_SIM_SYSCALL (close, fd); 164 if (left > 0) { 165 /* Some read failed. */ 166 free_bootmem (*addr, *len); 167 if (err) *err = "read"; 168 return 0; 169 } 170 171 return 1; 172} 173