OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /or1k_old/trunk/rc203soc/sw/uClinux/arch/or32/kernel
    from Rev 1765 to Rev 1782
    Reverse comparison

Rev 1765 → Rev 1782

/time.c
0,0 → 1,161
/*
* linux/arch/or32/kernel/time.c
*
* Copied/hacked from:
*
* linux/arch/m68knommu/kernel/time.c
*
* Copyright (C) 1991, 1992, 1995 Linus Torvalds
*
* This file contains the m68k-specific time handling details.
* Most of the stuff is located in the machine specific files.
*/
 
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/string.h>
#include <linux/mm.h>
 
#include <asm/machdep.h>
#include <asm/segment.h>
#include <asm/io.h>
 
#include <linux/timex.h>
 
 
static inline int set_rtc_mmss(unsigned long nowtime)
{
if (mach_set_clock_mmss)
return mach_set_clock_mmss (nowtime);
return -1;
}
 
/*
* timer_interrupt() needs to keep up the real-time clock,
* as well as call the "do_timer()" routine every clocktick
*/
/* void timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
*/
void timer_interrupt(struct pt_regs * regs)
{
/* last time the cmos clock got updated */
static long last_rtc_update=0;
/* may need to kick the hardware timer */
if (mach_tick)
mach_tick();
 
do_timer(regs);
 
/*
* If we have an externally synchronized Linux clock, then update
* CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
* called as close as possible to 500 ms before the new second starts.
*/
if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 &&
xtime.tv_usec > 500000 - (tick >> 1) &&
xtime.tv_usec < 500000 + (tick >> 1)) {
if (set_rtc_mmss(xtime.tv_sec) == 0)
last_rtc_update = xtime.tv_sec;
else
last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
}
 
}
 
/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
* Assumes input in normal date format, i.e. 1980-12-31 23:59:59
* => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
*
* [For the Julian calendar (which was used in Russia before 1917,
* Britain & colonies before 1752, anywhere else before 1582,
* and is still in use by some communities) leave out the
* -year/100+year/400 terms, and add 10.]
*
* This algorithm was first published by Gauss (I think).
*
* WARNING: this function will overflow on 2106-02-07 06:28:16 on
* machines were long is 32-bit! (However, as time_t is signed, we
* will already get problems at other places on 2038-01-19 03:14:08)
*/
static inline unsigned long mktime(unsigned int year, unsigned int mon,
unsigned int day, unsigned int hour,
unsigned int min, unsigned int sec)
{
if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */
mon += 12; /* Puts Feb last since it has leap day */
year -= 1;
}
return (((
(unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) +
year*365 - 719499
)*24 + hour /* now have hours */
)*60 + min /* now have minutes */
)*60 + sec; /* finally seconds */
}
 
void time_init(void)
{
unsigned int year, mon, day, hour, min, sec;
 
extern void arch_gettod(int *year, int *mon, int *day, int *hour,
int *min, int *sec);
 
arch_gettod (&year, &mon, &day, &hour, &min, &sec);
 
if ((year += 1900) < 1970)
year += 100;
xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
xtime.tv_usec = 0;
 
if (mach_sched_init)
mach_sched_init(timer_interrupt);
}
 
/*
* This version of gettimeofday has near microsecond resolution.
*/
void do_gettimeofday(struct timeval *tv)
{
unsigned long flags;
save_flags(flags);
cli();
*tv = xtime;
if (mach_gettimeoffset) {
tv->tv_usec += mach_gettimeoffset();
if (tv->tv_usec >= 1000000) {
tv->tv_usec -= 1000000;
tv->tv_sec++;
}
}
restore_flags(flags);
}
 
void do_settimeofday(struct timeval *tv)
{
cli();
/* This is revolting. We need to set the xtime.tv_usec
* correctly. However, the value in this location is
* is value at the last tick.
* Discover what correction gettimeofday
* would have done, and then undo it!
*/
if (mach_gettimeoffset)
tv->tv_usec -= mach_gettimeoffset();
 
if (tv->tv_usec < 0) {
tv->tv_usec += 1000000;
tv->tv_sec--;
}
 
xtime = *tv;
time_state = TIME_BAD;
time_maxerror = MAXPHASE;
time_esterror = MAXPHASE;
sti();
}
 
/setup.c
0,0 → 1,262
/*
* linux/arch/or32/kernel/setup.c
*
* Based on m86k
*/
 
/*
* This file handles the architecture-dependent parts of system setup
*/
 
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/fb.h>
#include <linux/console.h>
#include <linux/genhd.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/major.h>
 
#include <asm/irq.h>
#include <asm/machdep.h>
 
#ifdef CONFIG_BLK_DEV_INITRD
#include <linux/blk.h>
#include <asm/pgtable.h>
#endif
 
extern void register_console(void (*proc)(const char *));
#ifdef CONFIG_CONSOLE
extern struct consw *conswitchp;
#ifdef CONFIG_FRAMEBUFFER
extern struct consw fb_con;
#endif
#endif
 
#ifdef CONFIG_BLK_DEV_INITRD
extern unsigned long _initrd_start;
extern unsigned long _initrd_end;
#endif
 
unsigned long rom_length;
unsigned long memory_start;
unsigned long memory_end;
 
#ifdef CONFIG_CONSOLE
char command_line[512] = "CONSOLE=/dev/tty MOUSE_TYPE=ps2 MOUSE_PORT=/dev/ttyS0";
#else
char command_line[512] = "CONSOLE=/dev/ttyS0";
#endif
char saved_command_line[512];
char console_device[16];
 
char console_default[] = "CONSOLE=/dev/tty";
 
/* setup some dummy routines */
static void dummy_waitbut(void)
{
}
 
void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *)) = NULL;
void (*mach_tick)( void ) = NULL;
/* machine dependent keyboard functions */
int (*mach_keyb_init) (void) = NULL;
int (*mach_kbdrate) (struct kbd_repeat *) = NULL;
void (*mach_kbd_leds) (unsigned int) = NULL;
/* machine dependent irq functions */
void (*mach_init_IRQ) (void) = NULL;
void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
int (*mach_request_irq) (unsigned int, void (*)(int, void *, struct pt_regs *),
unsigned long, const char *, void *);
int (*mach_free_irq) (unsigned int, void *);
void (*mach_enable_irq) (unsigned int) = NULL;
void (*mach_disable_irq) (unsigned int) = NULL;
int (*mach_get_irq_list) (char *) = NULL;
int (*mach_process_int) (int, struct pt_regs *) = NULL;
void (*mach_trap_init) (void);
/* machine dependent timer functions */
unsigned long (*mach_gettimeoffset) (void) = NULL;
void (*mach_gettod) (int*, int*, int*, int*, int*, int*) = NULL;
int (*mach_hwclk) (int, struct hwclk_time*) = NULL;
int (*mach_set_clock_mmss) (unsigned long) = NULL;
void (*mach_mksound)( unsigned int count, unsigned int ticks ) = NULL;
void (*mach_reset)( void ) = NULL;
void (*waitbut)(void) = dummy_waitbut;
void (*mach_debug_init)(void) = NULL;
 
 
#ifdef CONFIG_OR32
#define CPU "OR32"
#endif
 
/*
* Setup the console. There may be a console defined in
* the command line arguments, so we look there first. If the
* command line arguments don't exist then we default to the
* first serial port. If we are going to use a console then
* setup its device name and the UART for it.
*/
void setup_console(void)
{
char *sp, *cp;
int i;
extern void rs_console_init(void);
extern void rs_console_print(const char *b);
#ifdef CONFIG_SERIAL
extern int rs_console_setup(char *arg);
#endif
/* Quickly check if any command line arguments for CONSOLE. */
for (sp = NULL, i = 0; (i < sizeof(command_line)-8); i++) {
if (command_line[i] == 0)
break;
if (command_line[i] == 'C') {
if (!strncmp(&command_line[i], "CONSOLE=", 8)) {
sp = &command_line[i + 8];
break;
}
}
}
 
#if 0
/* If no CONSOLE defined then default one */
if (sp == NULL) {
strcpy(command_line, console_default);
sp = command_line + 8;
}
#endif
 
/* If console specified then copy it into name buffer */
for (cp = sp, i = 0; (i < (sizeof(console_device) - 1)); i++) {
if ((*sp == 0) || (*sp == ' ') || (*sp == ','))
break;
console_device[i] = *sp++;
}
console_device[i] = 0;
 
#ifdef CONFIG_SERIAL
/* If a serial console then init it */
if (rs_console_setup(cp)) {
rs_console_init();
register_console(rs_console_print);
}
#endif
}
 
#if defined( CONFIG_GEN) && defined( CONFIG_OR32 )
#define CAT_ROMARRAY
#endif
 
void setup_arch(char **cmdline_p,
unsigned long * memory_start_p, unsigned long * memory_end_p)
{
extern int _stext, _etext;
extern int _sdata, _edata;
extern int _sbss, _ebss, _end;
extern int _ramstart, _ramend;
 
#ifdef CAT_ROMARRAY
extern int __data_rom_start;
extern int __data_start;
#endif
 
memory_start = (unsigned long)&_end;
memory_end = (unsigned long)&_ramend - 4096; /* <- stack area */
config_BSP(&command_line[0], sizeof(command_line));
setup_console();
printk("\nOpenRisc 1000 support (C) www.opencores.org\n");
printk("\r\n\nuClinux/" CPU "\n");
printk("Flat model support (C) 1998,1999 Kenneth Albanowski, D. Jeff Dionne\n");
 
#ifdef DEBUG
printk("KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x "
"BSS=0x%06x-0x%06x\n", (int) &_stext, (int) &_etext,
(int) &_sdata, (int) &_edata,
(int) &_sbss, (int) &_ebss);
printk("KERNEL -> ROMFS=0x%06x-0x%06x MEM=0x%06x-0x%06x "
"STACK=0x%06x-0x%06x\n",
(int) &_ebss, (int) memory_start,
(int) memory_start, (int) memory_end,
(int) memory_end, (int) &_ramend);
#endif
 
init_task.mm->start_code = (unsigned long) &_stext;
init_task.mm->end_code = (unsigned long) &_etext;
init_task.mm->end_data = (unsigned long) &_edata;
init_task.mm->brk = (unsigned long) &_end;
 
ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
 
/* Keep a copy of command line */
*cmdline_p = &command_line[0];
 
memcpy(saved_command_line, command_line, sizeof(saved_command_line));
saved_command_line[sizeof(saved_command_line)-1] = 0;
 
#ifdef DEBUG
if (strlen(*cmdline_p))
printk("Command line: '%s'\n", *cmdline_p);
else
printk("No Command line passed\n");
#endif
*memory_start_p = memory_start;
*memory_end_p = memory_end;
/*rom_length = (unsigned long)&_flashend - (unsigned long)&_romvec;*/
#ifdef CONFIG_BLK_DEV_INITRD
initrd_start = (unsigned long)&_initrd_start;
initrd_end = (unsigned long)&_initrd_end;
#endif
 
 
#ifdef CONFIG_CONSOLE
#ifdef CONFIG_FRAMEBUFFER
conswitchp = &fb_con;
#else
conswitchp = 0;
#endif
#endif
 
#ifdef DEBUG
printk("Done setup_arch\n");
#endif
 
}
 
int get_cpuinfo(char * buffer)
{
char *cpu, *mmu, *fpu;
u_long clockfreq, clockfactor;
 
cpu = CPU;
mmu = "none";
fpu = "none";
clockfactor = 16;
 
clockfreq = loops_per_sec*clockfactor;
 
return(sprintf(buffer, "CPU:\t\t%s\n"
"MMU:\t\t%s\n"
"FPU:\t\t%s\n"
"Clocking:\t%lu.%1luMHz\n"
"BogoMips:\t%lu.%02lu\n"
"Calibration:\t%lu loops\n",
cpu, mmu, fpu,
clockfreq/1000000,(clockfreq/100000)%10,
loops_per_sec/500000,(loops_per_sec/5000)%100,
loops_per_sec));
 
}
 
void arch_gettod(int *year, int *mon, int *day, int *hour,
int *min, int *sec)
{
if (mach_gettod)
mach_gettod(year, mon, day, hour, min, sec);
else
*year = *mon = *day = *hour = *min = *sec = 0;
}
 
/bios32.c
0,0 → 1,201
/*****************************************************************************/
 
/*
* bios32.c -- PCI access code for embedded CO-MEM Lite PCI controller.
*
* (C) Copyright 1999-2000, Greg Ungerer (gerg@moreton.com.au).
*/
 
/*****************************************************************************/
 
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/bios32.h>
#include <linux/pci.h>
#include <asm/anchor.h>
 
/*****************************************************************************/
#ifdef CONFIG_PCI
/*****************************************************************************/
 
unsigned long pcibios_init(unsigned long mem_start, unsigned long mem_end)
{
volatile unsigned long *rp;
int slot;
 
#if 0
printk("%s(%d): pcibios_init()\n", __FILE__, __LINE__);
#endif
 
/*
* Do some sort of basic check to see if the CO-MEM part
* is present...
*/
rp = (volatile unsigned long *) COMEM_BASE;
if ((rp[COMEM_LBUSCFG] & 0xffff) != 0x0b50) {
printk("PCI: no PCI bus present\n");
return(mem_start);
}
 
/*
* Do a quick scan of the PCI bus and see what is here.
*/
for (slot = COMEM_MINIDSEL; (slot <= COMEM_MAXIDSEL); slot++) {
rp[COMEM_DAHBASE] = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << slot);
rp[COMEM_PCIBUS] = 0; /* Clear bus */
printk("PCI: slot %d --> %08x\n", slot, rp[COMEM_PCIBUS]);
}
 
return(mem_start);
}
 
/*****************************************************************************/
 
unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end)
{
return(mem_start);
}
 
/*****************************************************************************/
 
int pcibios_present(void)
{
return(1);
}
 
/*****************************************************************************/
 
int pcibios_read_config_dword(unsigned char bus, unsigned char dev,
unsigned char offset, unsigned int *val)
{
#if 0
printk("%s(%d): pcibios_read_config_dword(bus=%x,dev=%x,offset=%x,"
"val=%x)\n", __FILE__, __LINE__, bus, dev, offset, val);
#endif
*val = 0xffffffff;
return(PCIBIOS_SUCCESSFUL);
}
 
/*****************************************************************************/
 
int pcibios_read_config_word(unsigned char bus, unsigned char dev,
unsigned char offset, unsigned short *val)
{
#if 0
printk("%s(%d): pcibios_read_config_word(bus=%x,dev=%x,offset=%x)\n",
__FILE__, __LINE__, bus, dev, offset);
#endif
*val = 0xffff;
return(PCIBIOS_SUCCESSFUL);
}
 
/*****************************************************************************/
 
int pcibios_read_config_byte(unsigned char bus, unsigned char dev,
unsigned char offset, unsigned char *val)
{
#if 0
printk("%s(%d): pcibios_read_config_byte(bus=%x,dev=%x,offset=%x)\n",
__FILE__, __LINE__, bus, dev, offset);
#endif
*val = 0xff;
return(PCIBIOS_SUCCESSFUL);
}
 
/*****************************************************************************/
 
int pcibios_write_config_dword(unsigned char bus, unsigned char dev,
unsigned char offset, unsigned int val)
{
#if 0
printk("%s(%d): pcibios_write_config_dword(bus=%x,dev=%x,offset=%x)\n",
__FILE__, __LINE__, bus, dev, offset);
#endif
return(PCIBIOS_SUCCESSFUL);
}
 
/*****************************************************************************/
 
int pcibios_write_config_word(unsigned char bus, unsigned char dev,
unsigned char offset, unsigned short val)
{
#if 0
printk("%s(%d): pcibios_write_config_word(bus=%x,dev=%x,offset=%x)\n",
__FILE__, __LINE__, bus, dev, offset);
#endif
return(PCIBIOS_SUCCESSFUL);
}
 
/*****************************************************************************/
 
int pcibios_write_config_byte(unsigned char bus, unsigned char dev,
unsigned char offset, unsigned char val)
{
#if 0
printk("%s(%d): pcibios_write_config_byte(bus=%x,dev=%x,offset=%x)\n",
__FILE__, __LINE__, bus, dev, offset);
#endif
return(PCIBIOS_SUCCESSFUL);
}
 
/*****************************************************************************/
 
int pcibios_find_device(unsigned short vendor, unsigned short devid,
unsigned short index, unsigned char *bus, unsigned char *dev)
{
unsigned int vendev, val;
unsigned char devnr;
 
#if 0
printk("%s(%d): pcibios_find_device(vendor=%04x,devid=%04x,"
"index=%d)\n", __FILE__, __LINE__, vendor, devid, index);
#endif
 
if (vendor == 0xffff)
return(PCIBIOS_BAD_VENDOR_ID);
 
vendev = (devid << 16) | vendor;
for (devnr = 0; (devnr < 32); devnr++) {
pcibios_read_config_dword(0, devnr, PCI_VENDOR_ID, &val);
if (vendev == val) {
if (index-- == 0) {
*bus = 0;
*dev = devnr;
return(PCIBIOS_SUCCESSFUL);
}
}
}
 
return(PCIBIOS_DEVICE_NOT_FOUND);
}
 
/*****************************************************************************/
 
int pcibios_find_class(unsigned int class, unsigned short index,
unsigned char *bus, unsigned char *dev)
{
unsigned int val;
unsigned char devnr;
 
#if 0
printk("%s(%d): pcibios_find_class(class=%04x,index=%d)\n",
__FILE__, __LINE__, class, index);
#endif
 
for (devnr = 0; (devnr < 32); devnr++) {
pcibios_read_config_dword(0, devnr, PCI_CLASS_REVISION, &val);
if ((val >> 8) == class) {
if (index-- == 0) {
*bus = 0;
*dev = devnr;
return(PCIBIOS_SUCCESSFUL);
}
}
}
 
return(PCIBIOS_DEVICE_NOT_FOUND);
}
 
/*****************************************************************************/
#endif /* CONFIG_PCI */
/console.c
0,0 → 1,2658
 
/*
* arch/or32/kernel/console.c
*
* Copyright (C) 2001,2002 Simon Srot <srot@opencores.org>,
* www.opencores.org
*
* Based on:
*
* arch/m68knommu/kernel/console.c
*
*
* linux/drivers/char/console.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
*/
/*
* console.c
*
* This module exports the console io functions:
*
* 'void do_keyboard_interrupt(void)'
*
* 'int vc_allocate(unsigned int console)'
* 'int vc_cons_allocated(unsigned int console)'
* 'int vc_resize(unsigned long lines, unsigned long cols)'
* 'int vc_resize_con(unsigned long lines, unsigned long cols,
* unsigned int currcons)'
* 'void vc_disallocate(unsigned int currcons)'
*
* 'unsigned long con_init(unsigned long)'
* 'int con_open(struct tty_struct *tty, struct file * filp)'
* 'void con_write(struct tty_struct * tty)'
* 'void console_print(const char * b)'
* 'void update_screen(int new_console)'
*
* 'void do_blank_screen(int)'
* 'void do_unblank_screen(void)'
* 'void poke_blanked_console(void)'
*
* 'unsigned short *screen_pos(int currcons, int w_offset, int viewed)'
* 'void complement_pos(int currcons, int offset)'
* 'void invert_screen(int currcons, int offset, int count, int shift)'
*
* 'void scrollback(int lines)'
* 'void scrollfront(int lines)'
*
* 'int con_get_font(char *)'
* 'int con_set_font(char *)'
*
* 'void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry)'
* 'int mouse_reporting(void)'
*
* 'unsigned long get_video_num_lines(unsigned int console)'
* 'unsigned long get_video_num_columns(unsigned int console)'
* 'unsigned long get_video_size_row(unsigned int console)'
*
* Hopefully this will be a rather complete VT102 implementation.
*
* Beeping thanks to John T Kohl.
*
* Virtual Consoles, Screen Blanking, Screen Dumping, Color, Graphics
* Chars, and VT100 enhancements by Peter MacDonald.
*
* Copy and paste function by Andrew Haylett,
* some enhancements by Alessandro Rubini.
*
* User definable mapping table and font loading by Eugene G. Crosser,
* <crosser@pccross.msk.su>
*
* Code to check for different video-cards mostly by Galen Hunt,
* <g-hunt@ee.utah.edu>
*
* Rudimentary ISO 10646/Unicode/UTF-8 character set support by
* Markus Kuhn, <mskuhn@immd4.informatik.uni-erlangen.de>.
*
* Dynamic allocation of consoles, aeb@cwi.nl, May 1994
* Resizing of consoles, aeb, 940926
*
* Code for xterm like mouse click reporting by Peter Orbaek 20-Jul-94
* <poe@daimi.aau.dk>
*
* 680x0 LINUX support by Arno Griffioen (arno@usn.nl)
*
* 9-Apr-94: Arno Griffioen: fixed scrolling and delete-char bug.
* Scrolling code moved to amicon.c
*
* 18-Apr-94: David Carter [carter@cs.bris.ac.uk]. 680x0 LINUX modified
* Integrated support for new low level driver `amicon_ocs.c'
*
*/
 
#define BLANK 0x0020
#define CAN_LOAD_EGA_FONTS /* undefine if the user must not do this */
 
/* A bitmap for codes <32. A bit of 1 indicates that the code
* corresponding to that bit number invokes some special action
* (such as cursor movement) and should not be displayed as a
* glyph unless the disp_ctrl mode is explicitly enabled.
*/
#define CTRL_ACTION 0x0d00ff81
#define CTRL_ALWAYS 0x0800f501 /* Cannot be overridden by disp_ctrl */
 
/*
* Here is the default bell parameters: 750HZ, 1/8th of a second
*/
#define DEFAULT_BELL_PITCH 750
#define DEFAULT_BELL_DURATION (HZ/8)
 
/*
* NOTE!!! We sometimes disable and enable interrupts for a short while
* (to put a word in video IO), but this will work even for keyboard
* interrupts. We know interrupts aren't enabled when getting a keyboard
* interrupt, as we use trap-gates. Hopefully all is well.
*/
 
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/console.h>
#include <linux/kd.h>
#include <linux/malloc.h>
#include <linux/major.h>
#include <linux/mm.h>
#include <linux/ioport.h>
 
#include <asm/io.h>
#include <asm/segment.h>
#include <asm/system.h>
#include <asm/bitops.h>
 
#include "../../../drivers/char/kbd_kern.h"
#include "../../../drivers/char/vt_kern.h"
#include "../../../drivers/char/consolemap.h"
#include "../../../drivers/char/selection.h"
 
 
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
 
struct tty_driver console_driver;
static int console_refcount;
static struct tty_struct *console_table[MAX_NR_CONSOLES];
static struct termios *console_termios[MAX_NR_CONSOLES];
static struct termios *console_termios_locked[MAX_NR_CONSOLES];
 
static void vc_init(unsigned int console, int do_clear);
 
static void update_attr(int currcons);
static void gotoxy(int currcons, int new_x, int new_y);
static void save_cur(int currcons);
static void blank_screen(void);
static void unblank_screen(void);
extern void change_console(unsigned int);
static inline void set_cursor(int currcons);
static void reset_terminal(int currcons, int do_clear);
extern void reset_vc(unsigned int new_console);
extern void vt_init(void);
extern void register_console(void (*proc)(const char *));
extern void vesa_blank(void);
extern void vesa_unblank(void);
extern void compute_shiftstate(void);
void poke_blanked_console(void);
void do_blank_screen(int);
 
unsigned long video_num_lines;
unsigned long video_num_columns;
unsigned long video_size_row;
 
static int printable = 0; /* Is console ready for printing? */
unsigned long video_font_height; /* Height of current screen font */
unsigned long video_scan_lines; /* Number of scan lines on screen */
unsigned long default_font_height; /* Height of default screen font */
int video_mode_512ch = 0; /* 512-character mode */
static unsigned short console_charmask = 0x0ff;
 
static unsigned short *vc_scrbuf[MAX_NR_CONSOLES];
 
/* used by kbd_bh - set by keyboard_interrupt */
int do_poke_blanked_console = 0;
int console_blanked = 0;
static int blankinterval = 10*60*HZ;
static int vesa_off_interval = 0;
static int vesa_blank_mode = 0; /* 0:none 1:suspendV 2:suspendH 3:powerdown */
 
static struct vc {
struct vc_data *d;
 
/* might add scrmem, vt_struct, kbd at some time,
to have everything in one place - the disadvantage
would be that vc_cons etc can no longer be static */
} vc_cons [MAX_NR_CONSOLES];
struct consw *conswitchp;
 
#define cols (vc_cons[currcons].d->vc_cols)
#define rows (vc_cons[currcons].d->vc_rows)
#define size_row (vc_cons[currcons].d->vc_size_row)
#define screenbuf_size (vc_cons[currcons].d->vc_screenbuf_size)
#define cons_num (vc_cons[currcons].d->vc_num)
#define origin (vc_cons[currcons].d->vc_origin)
#define scr_end (vc_cons[currcons].d->vc_scr_end)
#define pos (vc_cons[currcons].d->vc_pos)
#define top (vc_cons[currcons].d->vc_top)
#define bottom (vc_cons[currcons].d->vc_bottom)
#define x (vc_cons[currcons].d->vc_x)
#define y (vc_cons[currcons].d->vc_y)
#define vc_state (vc_cons[currcons].d->vc_state)
#define npar (vc_cons[currcons].d->vc_npar)
#define par (vc_cons[currcons].d->vc_par)
#define ques (vc_cons[currcons].d->vc_ques)
#define attr (vc_cons[currcons].d->vc_attr)
#define saved_x (vc_cons[currcons].d->vc_saved_x)
#define saved_y (vc_cons[currcons].d->vc_saved_y)
#define translate (vc_cons[currcons].d->vc_translate)
#define G0_charset (vc_cons[currcons].d->vc_G0_charset)
#define G1_charset (vc_cons[currcons].d->vc_G1_charset)
#define saved_G0 (vc_cons[currcons].d->vc_saved_G0)
#define saved_G1 (vc_cons[currcons].d->vc_saved_G1)
#define utf (vc_cons[currcons].d->vc_utf)
#define utf_count (vc_cons[currcons].d->vc_utf_count)
#define utf_char (vc_cons[currcons].d->vc_utf_char)
#define video_mem_start (vc_cons[currcons].d->vc_video_mem_start)
#define video_mem_end (vc_cons[currcons].d->vc_video_mem_end)
#define video_erase_char (vc_cons[currcons].d->vc_video_erase_char)
#define disp_ctrl (vc_cons[currcons].d->vc_disp_ctrl)
#define toggle_meta (vc_cons[currcons].d->vc_toggle_meta)
#define decscnm (vc_cons[currcons].d->vc_decscnm)
#define decom (vc_cons[currcons].d->vc_decom)
#define decawm (vc_cons[currcons].d->vc_decawm)
#define deccm (vc_cons[currcons].d->vc_deccm)
#define decim (vc_cons[currcons].d->vc_decim)
#define deccolm (vc_cons[currcons].d->vc_deccolm)
#define need_wrap (vc_cons[currcons].d->vc_need_wrap)
#define has_scrolled (vc_cons[currcons].d->vc_has_scrolled)
#define kmalloced (vc_cons[currcons].d->vc_kmalloced)
#define report_mouse (vc_cons[currcons].d->vc_report_mouse)
#define can_do_color (vc_cons[currcons].d->vc_can_do_color)
#define color (vc_cons[currcons].d->vc_color)
#define s_color (vc_cons[currcons].d->vc_s_color)
#define def_color (vc_cons[currcons].d->vc_def_color)
#define foreground (color & 0x0f)
#define background (color & 0xf0)
#define charset (vc_cons[currcons].d->vc_charset)
#define s_charset (vc_cons[currcons].d->vc_s_charset)
#define intensity (vc_cons[currcons].d->vc_intensity)
#define underline (vc_cons[currcons].d->vc_underline)
#define blink (vc_cons[currcons].d->vc_blink)
#define reverse (vc_cons[currcons].d->vc_reverse)
#define s_intensity (vc_cons[currcons].d->vc_s_intensity)
#define s_underline (vc_cons[currcons].d->vc_s_underline)
#define s_blink (vc_cons[currcons].d->vc_s_blink)
#define s_reverse (vc_cons[currcons].d->vc_s_reverse)
#define ulcolor (vc_cons[currcons].d->vc_ulcolor)
#define halfcolor (vc_cons[currcons].d->vc_halfcolor)
#define tab_stop (vc_cons[currcons].d->vc_tab_stop)
#define bell_pitch (vc_cons[currcons].d->vc_bell_pitch)
#define bell_duration (vc_cons[currcons].d->vc_bell_duration)
#define sw (vc_cons[currcons].d->vc_sw)
 
#define vcmode (vt_cons[currcons]->vc_mode)
#if 0 /* XXX */
#define vtmode (vt_cons[currcons]->vt_mode)
#define vtpid (vt_cons[currcons]->vt_pid)
#define vtnewvt (vt_cons[currcons]->vt_newvt)
#endif
 
#define structsize (sizeof(struct vc_data) + sizeof(struct vt_struct))
 
int vc_cons_allocated(unsigned int i)
{
return (i < MAX_NR_CONSOLES && vc_cons[i].d);
}
 
int vc_allocate(unsigned int currcons) /* return 0 on success */
{
if (currcons >= MAX_NR_CONSOLES)
return -ENODEV;
if (!vc_cons[currcons].d) {
long p, q;
 
/* prevent users from taking too much memory */
if (currcons >= MAX_NR_USER_CONSOLES && !suser())
return -EPERM;
 
/* due to the granularity of kmalloc, we waste some memory here */
/* the alloc is done in two steps, to optimize the common situation
of a 25x80 console (structsize=216, screenbuf_size=4000) */
p = (long) kmalloc(structsize, GFP_KERNEL);
if (!p)
return -ENOMEM;
vc_cons[currcons].d = (struct vc_data *) p;
vt_cons[currcons] = (struct vt_struct *)(p+sizeof(struct vc_data));
 
/* ++Geert: sw->con_init determines console size */
sw = conswitchp;
cons_num = currcons;
sw->con_init (vc_cons[currcons].d);
size_row = cols<<1;
screenbuf_size = rows*size_row;
 
q = (long) kmalloc(screenbuf_size, GFP_KERNEL);
if (!q) {
kfree_s((char *) p, structsize);
vc_cons[currcons].d = NULL;
return -ENOMEM;
}
vc_scrbuf[currcons] = (unsigned short *) q;
kmalloced = 1;
vc_init (currcons, 1);
}
return 0;
}
 
/*
* Change # of rows and columns (0 means the size of fg_console)
* [this is to be used together with some user program
* like resize that changes the hardware videomode]
*/
int vc_resize(unsigned long lines, unsigned long columns)
{
unsigned long cc, ll, ss, sr;
unsigned long occ, oll, oss, osr;
unsigned short *p;
unsigned int currcons = fg_console, i;
unsigned short *newscreens[MAX_NR_CONSOLES];
long ol, nl, rlth, rrem;
 
cc = (columns ? columns : cols);
ll = (lines ? lines : rows);
sr = cc << 1;
ss = sr * ll;
 
/*
* Some earlier version had all consoles of potentially
* different sizes, but that was really messy.
* So now we only change if there is room for all consoles
* of the same size.
*/
for (currcons = 0; currcons < MAX_NR_CONSOLES; currcons++) {
if (!vc_cons_allocated(currcons))
newscreens[currcons] = 0;
else {
p = (unsigned short *) kmalloc(ss, GFP_USER);
if (!p) {
for (i = 0; i< currcons; i++)
if (newscreens[i])
kfree_s(newscreens[i], ss);
return -ENOMEM;
}
newscreens[currcons] = p;
}
}
 
#if 0 /* XXX */
get_scrmem(fg_console);
#endif
 
for (currcons = 0; currcons < MAX_NR_CONSOLES; currcons++) {
if (!vc_cons_allocated(currcons))
continue;
 
oll = rows;
occ = cols;
osr = size_row;
oss = screenbuf_size;
 
rows = ll;
cols = cc;
size_row = sr;
screenbuf_size = ss;
 
rlth = MIN(osr, sr);
rrem = sr - rlth;
ol = origin;
nl = (long) newscreens[currcons];
if (ll < oll)
ol += (oll - ll) * osr;
 
update_attr(currcons);
while (ol < scr_end) {
/* ++Geert: TODO: Because the attributes have different meanings
on monochrome and color, they should really be converted if
can_do_color changes... */
memcpyw((unsigned short *) nl, (unsigned short *) ol, rlth);
if (rrem)
memsetw((void *)(nl + rlth), video_erase_char, rrem);
ol += osr;
nl += sr;
}
 
if (kmalloced)
kfree_s(vc_scrbuf[currcons], oss);
vc_scrbuf[currcons] = newscreens[currcons];
kmalloced = 1;
screenbuf_size = ss;
 
origin = (long) video_mem_start = vc_scrbuf[currcons];
scr_end = video_mem_end = ((long) video_mem_start) + ss;
 
if (scr_end > nl)
memsetw((void *) nl, video_erase_char, scr_end - nl);
 
/* do part of a reset_terminal() */
top = 0;
bottom = rows;
gotoxy(currcons, x, y);
save_cur(currcons);
}
 
#if 0 /* XXX */
set_scrmem(fg_console, 0);
set_origin(fg_console);
#endif /* XXX */
update_screen(fg_console);
set_cursor(fg_console);
 
return 0;
}
 
/*
* ++Geert: Change # of rows and columns for one specific console.
* Of course it's not messy to have all consoles of potentially different sizes,
* except on PCish hardware :-)
*
* This is called by the low level console driver (arch/m68k/console/fbcon.c or
* arch/m68k/console/txtcon.c)
*/
void vc_resize_con(unsigned long lines, unsigned long columns,
unsigned int currcons)
{
unsigned long cc, ll, ss, sr;
unsigned long occ, oll, oss, osr;
unsigned short *newscreen;
long ol, nl, rlth, rrem;
struct winsize ws;
 
if (!columns || !lines || currcons >= MAX_NR_CONSOLES)
return;
 
cc = columns;
ll = lines;
sr = cc << 1;
ss = sr * ll;
 
if (!vc_cons_allocated(currcons))
newscreen = 0;
else if (!(newscreen = (unsigned short *) kmalloc(ss, GFP_USER)))
return;
 
if (vc_cons_allocated(currcons)) {
oll = rows;
occ = cols;
osr = size_row;
oss = screenbuf_size;
 
rows = ll;
cols = cc;
size_row = sr;
screenbuf_size = ss;
 
rlth = MIN(osr, sr);
rrem = sr - rlth;
ol = origin;
nl = (long) newscreen;
if (ll < oll)
ol += (oll - ll) * osr;
 
update_attr(currcons);
while (ol < scr_end) {
/* ++Geert: TODO: Because the attributes have different meanings
on monochrome and color, they should really be converted if
can_do_color changes... */
memcpyw((unsigned short *) nl, (unsigned short *) ol, rlth);
if (rrem)
memsetw((void *)(nl + rlth), video_erase_char, rrem);
ol += osr;
nl += sr;
}
 
if (kmalloced)
kfree_s(vc_scrbuf[currcons], oss);
vc_scrbuf[currcons] = newscreen;
kmalloced = 1;
screenbuf_size = ss;
 
origin = (long) video_mem_start = vc_scrbuf[currcons];
scr_end = video_mem_end = ((long)video_mem_start) + ss;
 
if (scr_end > nl)
memsetw((void *) nl, video_erase_char, scr_end - nl);
 
/* do part of a reset_terminal() */
top = 0;
bottom = rows;
gotoxy(currcons, x, y);
save_cur(currcons);
 
ws.ws_row = rows;
ws.ws_col = cols;
if (memcmp(&ws, &console_table[currcons]->winsize, sizeof (struct winsize)) &&
console_table[currcons]->pgrp > 0)
kill_pg(console_table[currcons]->pgrp, SIGWINCH, 1);
console_table[currcons]->winsize = ws;
}
 
if (currcons == fg_console && vt_cons[fg_console]->vc_mode == KD_TEXT)
update_screen(fg_console);
}
 
void vc_disallocate(unsigned int currcons)
{
if (vc_cons_allocated(currcons)) {
if (kmalloced)
kfree_s(vc_scrbuf[currcons], screenbuf_size);
if (currcons >= MIN_NR_CONSOLES)
kfree_s(vc_cons[currcons].d, structsize);
vc_cons[currcons].d = 0;
}
}
 
 
#define set_kbd(x) set_vc_kbd_mode(kbd_table+currcons,x)
#define clr_kbd(x) clr_vc_kbd_mode(kbd_table+currcons,x)
#define is_kbd(x) vc_kbd_mode(kbd_table+currcons,x)
 
#define decarm VC_REPEAT
#define decckm VC_CKMODE
#define kbdapplic VC_APPLIC
#define lnm VC_CRLF
 
/*
* this is what the terminal answers to a ESC-Z or csi0c query.
*/
#define VT100ID "\033[?1;2c"
#define VT102ID "\033[?6c"
 
static unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
8,12,10,14, 9,13,11,15 };
 
/*
* gotoxy() must verify all boundaries, because the arguments
* might also be negative. If the given position is out of
* bounds, the cursor is placed at the nearest margin.
*/
static void gotoxy(int currcons, int new_x, int new_y)
{
int min_y, max_y;
 
if (new_x < 0)
x = 0;
else
if (new_x >= cols)
x = cols - 1;
else
x = new_x;
if (decom) {
min_y = top;
max_y = bottom;
} else {
min_y = 0;
max_y = rows;
}
if (new_y < min_y)
y = min_y;
else if (new_y >= max_y)
y = max_y - 1;
else
y = new_y;
pos = video_mem_start + y * cols + x;
need_wrap = 0;
}
 
/* for absolute user moves, when decom is set */
static void gotoxay(int currcons, int new_x, int new_y)
{
gotoxy(currcons, new_x, decom ? (top+new_y) : new_y);
}
 
static void hide_cursor(int currcons)
{
sw->con_cursor(vc_cons[currcons].d,CM_ERASE);
return;
}
 
static void set_cursor(int currcons)
{
if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
return;
if (deccm)
sw->con_cursor(vc_cons[currcons].d,CM_DRAW);
else
hide_cursor(currcons);
return;
}
 
void no_scroll(char *str, int *ints)
{
/*
* no_scroll currently does nothing on the m68k.
*/
}
 
/*
* Arno:
* Why do we need these? The keyboard code doesn't seem to do anything
* with them either...
*/
void scrollfront(int l)
{
return;
}
 
void scrollback(int l)
{
return;
}
 
static void scrup(int currcons, unsigned int t, unsigned int b,
int nr)
{
unsigned short *p;
int i;
 
if (b > rows || t >= b)
return;
 
memmove (video_mem_start + t * cols,
video_mem_start + (t + nr) * cols,
(b - t - nr) * cols * 2);
 
p = video_mem_start + (b - nr) * cols;
for (i = nr * cols; i > 0; i--)
*p++ = video_erase_char;
 
if (currcons != fg_console)
return;
/*
* Arno:
* Scrolling has now been moved to amicon.c where it should have
* been all along.
*/
sw->con_scroll(vc_cons[currcons].d, t, b, SM_UP, nr);
 
return;
}
 
static void scrdown(int currcons, unsigned int t, unsigned int b,
int nr)
{
unsigned short *p;
int i;
 
if (b > rows || t >= b)
return;
 
memmove (video_mem_start + (t + nr) * cols,
video_mem_start + t * cols,
(b - t - nr) * cols * 2);
 
p = video_mem_start + t * cols;
for (i = nr * cols; i > 0; i--)
*p++ = video_erase_char;
 
if (currcons != fg_console)
return;
/*
* Arno:
* Scrolling has now been moved to amicon.c where it should have
* been all along.
*/
sw->con_scroll(vc_cons[currcons].d, t, b, SM_DOWN, nr);
 
return;
}
 
static void lf(int currcons)
{
/* don't scroll if above bottom of scrolling region, or
* if below scrolling region
*/
if (y+1 == bottom)
scrup(currcons,top,bottom, 1);
else if (y < rows-1) {
y++;
pos += cols;
}
need_wrap = 0;
}
 
static void ri(int currcons)
{
/* don't scroll if below top of scrolling region, or
* if above scrolling region
*/
if (y == top)
scrdown(currcons,top,bottom, 1);
else if (y > 0) {
y--;
pos -= cols;
}
need_wrap = 0;
}
 
static inline void cr(int currcons)
{
pos -= x;
need_wrap = x = 0;
}
 
static inline void bs(int currcons)
{
if (x) {
pos--;
x--;
need_wrap = 0;
}
}
 
static inline void del(int currcons)
{
/* ignored */
}
 
static void csi_J(int currcons, int vpar)
{
unsigned long count;
unsigned short *start;
 
switch (vpar) {
case 0: /* erase from cursor to end of display */
count = (video_mem_start
+ cols * rows
- pos);
start = pos;
if (currcons != fg_console)
break;
/* 680x0 do in two stages */
sw->con_clear(vc_cons[currcons].d,y,x,1,cols-x);
sw->con_clear(vc_cons[currcons].d,y+1,0,rows-y-1, cols);
break;
case 1: /* erase from start to cursor */
count = pos - video_mem_start + 1;
start = video_mem_start;
if (currcons != fg_console)
break;
/* 680x0 do in two stages */
sw->con_clear(vc_cons[currcons].d,0,0,y, cols);
sw->con_clear(vc_cons[currcons].d,y,0,1,x + 1);
break;
case 2: /* erase whole display */
count = cols * rows;
start = video_mem_start;
if (currcons != fg_console)
break;
sw->con_clear(vc_cons[currcons].d,0,0,rows, cols);
break;
default:
return;
}
while (count-- > 0)
*start++ = video_erase_char;
need_wrap = 0;
}
 
static void csi_K(int currcons, int vpar)
{
unsigned long count;
unsigned short *start;
 
switch (vpar) {
case 0: /* erase from cursor to end of line */
count = cols - x;
start = pos;
if (currcons != fg_console)
break;
sw->con_clear(vc_cons[currcons].d,y,x,1,cols-x);
break;
case 1: /* erase from start of line to cursor */
start = pos - x;
count = x + 1;
if (currcons != fg_console)
break;
sw->con_clear(vc_cons[currcons].d,y,0,1,x + 1);
break;
case 2: /* erase whole line */
start = pos - x;
count = cols;
if (currcons != fg_console)
break;
sw->con_clear(vc_cons[currcons].d,y,0,1,cols);
break;
default:
return;
}
while (count-- > 0)
*start++ = video_erase_char;
need_wrap = 0;
}
 
static void csi_X(int currcons, int vpar) /* erase the following vpar positions */
{ /* not vt100? */
unsigned long count;
unsigned short * start;
 
if (!vpar)
vpar++;
 
start=pos;
count=(vpar > cols-x) ? (cols-x) : vpar;
 
if (currcons == fg_console)
sw->con_clear(vc_cons[currcons].d,y,x,1,count);
 
while (count-- > 0)
*start++ = video_erase_char;
need_wrap = 0;
}
 
/*
* Arno:
* On 680x0 attributes are currently not used. This piece of code
* seems hardware independent, but uses the EGA/VGA way of representing
* attributes.
* TODO: modify for 680x0 and add attribute processing to putc code.
*
* ++roman: I completely changed the attribute format for monochrome
* mode (!can_do_color). The formerly used MDA (monochrome display
* adapter) format didn't allow the combination of certain effects.
* Now the attribute is just a bit vector:
* Bit 0..1: intensity (0..2)
* Bit 2 : underline
* Bit 3 : reverse
* Bit 7 : blink
*/
static void update_attr(int currcons)
{
if (!can_do_color) {
/* Special treatment for monochrome */
attr = intensity |
(underline ? 4 : 0) |
((reverse ^ decscnm) ? 8 : 0) |
(blink ? 0x80 : 0);
video_erase_char = ' ' | ((reverse ^ decscnm) ? 0x800 : 0);
return;
}
 
attr = color;
if (underline)
attr = (attr & 0xf0) | ulcolor;
else if (intensity == 0)
attr = (attr & 0xf0) | halfcolor;
if (reverse ^ decscnm)
attr = reverse_video_char(attr);
if (blink)
attr ^= 0x80;
if (intensity == 2)
attr ^= 0x08;
if (decscnm)
video_erase_char = (reverse_video_char(color) << 8) | ' ';
else
video_erase_char = (color << 8) | ' ';
}
 
static void default_attr(int currcons)
{
intensity = 1;
underline = 0;
reverse = 0;
blink = 0;
color = def_color;
}
 
static void csi_m(int currcons)
{
int i;
 
for (i=0;i<=npar;i++)
switch (par[i]) {
case 0: /* all attributes off */
default_attr(currcons);
break;
case 1:
intensity = 2;
break;
case 2:
intensity = 0;
break;
case 4:
underline = 1;
break;
case 5:
blink = 1;
break;
case 7:
reverse = 1;
break;
case 10: /* ANSI X3.64-1979 (SCO-ish?)
* Select primary font, don't display
* control chars if defined, don't set
* bit 8 on output.
*/
translate = set_translate(charset == 0
? G0_charset
: G1_charset);
disp_ctrl = 0;
toggle_meta = 0;
break;
case 11: /* ANSI X3.64-1979 (SCO-ish?)
* Select first alternate font, let's
* chars < 32 be displayed as ROM chars.
*/
translate = set_translate(IBMPC_MAP);
disp_ctrl = 1;
toggle_meta = 0;
break;
case 12: /* ANSI X3.64-1979 (SCO-ish?)
* Select second alternate font, toggle
* high bit before displaying as ROM char.
*/
translate = set_translate(IBMPC_MAP);
disp_ctrl = 1;
toggle_meta = 1;
break;
case 21:
case 22:
intensity = 1;
break;
case 24:
underline = 0;
break;
case 25:
blink = 0;
break;
case 27:
reverse = 0;
break;
case 38: /* ANSI X3.64-1979 (SCO-ish?)
* Enables underscore, white foreground
* with white underscore (Linux - use
* default foreground).
*/
color = (def_color & 0x0f) | background;
underline = 1;
break;
case 39: /* ANSI X3.64-1979 (SCO-ish?)
* Disable underline option.
* Reset colour to default? It did this
* before...
*/
color = (def_color & 0x0f) | background;
underline = 0;
break;
case 49:
color = (def_color & 0xf0) | foreground;
break;
default:
if (par[i] >= 30 && par[i] <= 37)
color = color_table[par[i]-30]
| background;
else if (par[i] >= 40 && par[i] <= 47)
color = (color_table[par[i]-40]<<4)
| foreground;
break;
}
update_attr(currcons);
}
 
static void respond_string(const char * p, struct tty_struct * tty)
{
while (*p) {
tty_insert_flip_char(tty, *p, 0);
p++;
}
tty_schedule_flip(tty);
}
 
static void cursor_report(int currcons, struct tty_struct * tty)
{
char buf[40];
 
sprintf(buf, "\033[%ld;%ldR", y + (decom ? top+1 : 1), x+1);
respond_string(buf, tty);
}
 
static inline void status_report(struct tty_struct * tty)
{
respond_string("\033[0n", tty); /* Terminal ok */
}
 
static inline void respond_ID(struct tty_struct * tty)
{
respond_string(VT102ID, tty);
}
 
void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry)
{
char buf[8];
 
sprintf(buf, "\033[M%c%c%c", (char)(' ' + butt), (char)('!' + mrx),
(char)('!' + mry));
respond_string(buf, tty);
}
 
/* invoked via ioctl(TIOCLINUX) */
int mouse_reporting(void)
{
int currcons = fg_console;
 
return report_mouse;
}
 
static inline unsigned short *screenpos(int currcons, int offset, int viewed)
{
unsigned short *p = (unsigned short *)(origin + offset);
#if 0
if (viewed && currcons == fg_console)
p -= (__real_origin - __origin);
#endif
return p;
}
 
/* Note: inverting the screen twice should revert to the original state */
void invert_screen(int currcons, int offset, int count, int viewed)
{
unsigned short *p;
unsigned short xx, yy, oldattr;
 
count /= 2;
p = screenpos(currcons, offset, viewed);
xx = (offset >> 1) % cols;
yy = (offset >> 1) / cols;
oldattr = attr;
if (can_do_color)
while (count--) {
unsigned short old = scr_readw(p);
unsigned short new = reverse_video_short(old);
scr_writew(new, p);
p++;
if (currcons != fg_console)
continue;
attr = new >> 8;
sw->con_putc(vc_cons[currcons].d, new & 0xff, yy, xx);
if (++xx == cols)
xx = 0, ++yy;
}
else
while (count--) {
unsigned short old = scr_readw(p);
unsigned short new = old ^ 0x800;
scr_writew(new, p);
p++;
if (currcons != fg_console)
continue;
attr = new >> 8;
sw->con_putc(vc_cons[currcons].d, new & 0xff, yy, xx);
if (++xx == cols)
xx = 0, ++yy;
}
attr = oldattr;
}
 
/* used by selection: complement pointer position */
void complement_pos(int currcons, int offset)
{
static unsigned short *p = NULL;
static unsigned short old = 0;
static unsigned short oldx = 0, oldy = 0;
unsigned short new, oldattr;
 
oldattr = attr;
if (p) {
scr_writew(old, p);
if (currcons == fg_console) {
attr = old >> 8;
sw->con_putc(vc_cons[currcons].d, old & 0xff, oldy, oldx);
attr = oldattr;
}
}
if (offset == -1)
p = NULL;
else {
p = screenpos(currcons, offset, 1);
old = scr_readw(p);
oldx = (offset >> 1) % cols;
oldy = (offset >> 1) / cols;
if (can_do_color)
new = old ^ 0x7700;
else
new = old ^ 0x800;
scr_writew(new, p);
if (currcons == fg_console) {
attr = new >> 8;
sw->con_putc(vc_cons[currcons].d, new & 0xff, oldy, oldx);
attr = oldattr;
}
}
}
 
/* used by selection */
unsigned short screen_word(int currcons, int offset, int viewed)
{
return scr_readw(screenpos(currcons, offset, viewed));
}
 
/* used by selection - convert a screen word to a glyph number */
int scrw2glyph(unsigned short scr_word)
{
return ( video_mode_512ch )
? ((scr_word & 0x0800) >> 3) + (scr_word & 0x00ff)
: scr_word & 0x00ff;
}
 
/* used by vcs - note the word offset */
unsigned short *screen_pos(int currcons, int w_offset, int viewed)
{
return screenpos(currcons, 2 * w_offset, viewed);
}
 
void getconsxy(int currcons, char *p)
{
p[0] = x;
p[1] = y;
}
 
void putconsxy(int currcons, char *p)
{
gotoxy(currcons, p[0], p[1]);
set_cursor(currcons);
}
 
static void set_mode(int currcons, int on_off)
{
int i;
 
for (i=0; i<=npar; i++)
if (ques) switch(par[i]) { /* DEC private modes set/reset */
case 1: /* Cursor keys send ^[Ox/^[[x */
if (on_off)
set_kbd(decckm);
else
clr_kbd(decckm);
break;
case 3: /* 80/132 mode switch unimplemented */
deccolm = on_off;
#if 0
(void) vc_resize(rows, deccolm ? 132 : 80);
/* this alone does not suffice; some user mode
utility has to change the hardware regs */
#endif
break;
case 5: /* Inverted screen on/off */
if (decscnm != on_off) {
decscnm = on_off;
invert_screen(currcons, 0, screenbuf_size, 0);
update_attr(currcons);
}
break;
case 6: /* Origin relative/absolute */
decom = on_off;
gotoxay(currcons,0,0);
break;
case 7: /* Autowrap on/off */
decawm = on_off;
break;
case 8: /* Autorepeat on/off */
if (on_off)
set_kbd(decarm);
else
clr_kbd(decarm);
break;
case 9:
report_mouse = on_off ? 1 : 0;
break;
case 25: /* Cursor on/off */
deccm = on_off;
set_cursor(currcons);
break;
case 1000:
report_mouse = on_off ? 2 : 0;
break;
} else switch(par[i]) { /* ANSI modes set/reset */
case 3: /* Monitor (display ctrls) */
disp_ctrl = on_off;
break;
case 4: /* Insert Mode on/off */
decim = on_off;
break;
case 20: /* Lf, Enter == CrLf/Lf */
if (on_off)
set_kbd(lnm);
else
clr_kbd(lnm);
break;
}
}
 
static void setterm_command(int currcons)
{
switch(par[0]) {
case 1: /* set color for underline mode */
if (can_do_color && par[1] < 16) {
ulcolor = color_table[par[1]];
if (underline)
update_attr(currcons);
}
break;
case 2: /* set color for half intensity mode */
if (can_do_color && par[1] < 16) {
halfcolor = color_table[par[1]];
if (intensity == 0)
update_attr(currcons);
}
break;
case 8: /* store colors as defaults */
def_color = attr;
default_attr(currcons);
update_attr(currcons);
break;
case 9: /* set blanking interval */
blankinterval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
poke_blanked_console();
break;
case 10: /* set bell frequency in Hz */
if (npar >= 1)
bell_pitch = par[1];
else
bell_pitch = DEFAULT_BELL_PITCH;
break;
case 11: /* set bell duration in msec */
if (npar >= 1)
bell_duration = (par[1] < 2000) ?
par[1]*HZ/1000 : 0;
else
bell_duration = DEFAULT_BELL_DURATION;
break;
case 12: /* bring specified console to the front */
if (par[1] >= 1 && vc_cons_allocated(par[1]-1))
update_screen(par[1]-1);
break;
case 13: /* unblank the screen */
unblank_screen();
break;
case 14: /* set vesa powerdown interval */
vesa_off_interval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
break;
}
}
 
static void insert_char(int currcons)
{
int i;
unsigned short *p = pos;
 
for (i = cols - x - 2; i >= 0; i--)
p[i + 1] = p[i];
*pos = video_erase_char;
need_wrap = 0;
 
if (currcons != fg_console)
return;
 
/* Arno:
* Move the remainder of the line (-1 character) one spot to the right
*/
sw->con_bmove(vc_cons[currcons].d,y,x,y,x+1,1,(cols-x-1));
/*
* Print the erase char on the current position
*/
sw->con_putc(vc_cons[currcons].d,(video_erase_char & 0x00ff),y,x);
}
 
static void csi_at(int currcons, unsigned int nr)
{
int i;
unsigned short *p;
 
if (nr > cols - x)
nr = cols - x;
else if (!nr)
nr = 1;
 
p = pos + cols - x - nr;
while (--p >= pos)
p[nr] = *p;
for (i = 0; i < nr; i++)
*++p = video_erase_char;
need_wrap = 0;
 
if (currcons != fg_console)
return;
 
sw->con_bmove (vc_cons[currcons].d, y, x, y, x + nr,
1, cols - x - nr);
while (nr--)
sw->con_putc (vc_cons[currcons].d, video_erase_char & 0x00ff,
y, x + nr);
}
 
static void csi_L(int currcons, unsigned int nr)
{
if (nr > rows)
nr = rows;
else if (!nr)
nr = 1;
scrdown (currcons, y, bottom, nr);
need_wrap = 0;
}
 
static void csi_P(int currcons, unsigned int nr)
{
int i;
unsigned short *p, *end;
 
if (nr > cols - x)
nr = cols - x;
else if (!nr)
nr = 1;
 
p = pos;
end = pos + cols - x - nr;
while (p < end)
*p = p[nr], p++;
for (i = 0; i < nr; i++)
*p++ = video_erase_char;
need_wrap = 0;
 
if (currcons != fg_console)
return;
 
sw->con_bmove (vc_cons[currcons].d, y, x + nr, y, x,
1, cols - x - nr);
 
while (nr--)
sw->con_putc (vc_cons[currcons].d, video_erase_char & 0x00ff,
y, cols - 1 - nr);
}
 
static void csi_M(int currcons, unsigned int nr)
{
if (nr > rows)
nr = rows;
else if (!nr)
nr=1;
scrup (currcons, y, bottom, nr);
need_wrap = 0;
}
 
static void save_cur(int currcons)
{
saved_x = x;
saved_y = y;
s_intensity = intensity;
s_underline = underline;
s_blink = blink;
s_reverse = reverse;
s_charset = charset;
s_color = color;
saved_G0 = G0_charset;
saved_G1 = G1_charset;
}
 
static void restore_cur(int currcons)
{
gotoxy(currcons,saved_x,saved_y);
intensity = s_intensity;
underline = s_underline;
blink = s_blink;
reverse = s_reverse;
charset = s_charset;
color = s_color;
G0_charset = saved_G0;
G1_charset = saved_G1;
translate = set_translate(charset ? G1_charset : G0_charset);
update_attr(currcons);
need_wrap = 0;
}
 
enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
EShash, ESsetG0, ESsetG1, ESpercent, ESignore, ESnonstd,
ESpalette };
 
static void reset_terminal(int currcons, int do_clear)
{
top = 0;
bottom = rows;
vc_state = ESnormal;
ques = 0;
translate = set_translate(LAT1_MAP);
G0_charset = LAT1_MAP;
G1_charset = GRAF_MAP;
charset = 0;
need_wrap = 0;
report_mouse = 0;
utf = 0;
utf_count = 0;
 
disp_ctrl = 0;
toggle_meta = 0;
 
decscnm = 0;
decom = 0;
decawm = 1;
deccm = 1;
decim = 0;
 
set_kbd(decarm);
clr_kbd(decckm);
clr_kbd(kbdapplic);
clr_kbd(lnm);
kbd_table[currcons].lockstate = 0;
kbd_table[currcons].slockstate = 0;
kbd_table[currcons].ledmode = LED_SHOW_FLAGS;
kbd_table[currcons].ledflagstate = kbd_table[currcons].default_ledflagstate;
set_leds();
 
default_attr(currcons);
update_attr(currcons);
 
tab_stop[0] = 0x01010100;
tab_stop[1] =
tab_stop[2] =
tab_stop[3] =
tab_stop[4] = 0x01010101;
 
bell_pitch = DEFAULT_BELL_PITCH;
bell_duration = DEFAULT_BELL_DURATION;
 
gotoxy(currcons,0,0);
save_cur(currcons);
if (do_clear)
csi_J(currcons,2);
}
 
/*
* Turn the Scroll-Lock LED on when the tty is stopped
*/
static void con_stop(struct tty_struct *tty)
{
int console_num;
if (!tty)
return;
console_num = MINOR(tty->device) - (tty->driver.minor_start);
if (!vc_cons_allocated(console_num))
return;
set_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
set_leds();
}
 
/*
* Turn the Scroll-Lock LED off when the console is started
*/
static void con_start(struct tty_struct *tty)
{
int console_num;
if (!tty)
return;
console_num = MINOR(tty->device) - (tty->driver.minor_start);
if (!vc_cons_allocated(console_num))
return;
clr_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
set_leds();
}
 
static int con_write(struct tty_struct * tty, int from_user,
const unsigned char *buf, int count)
{
int c, tc, ok, n = 0;
unsigned int currcons;
struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
 
currcons = vt->vc_num;
if (!vc_cons_allocated(currcons)) {
/* could this happen? */
static int error = 0;
if (!error) {
error = 1;
printk("con_write: tty %d not allocated\n", currcons+1);
}
return 0;
}
 
/* undraw cursor first */
if (currcons == fg_console)
hide_cursor(currcons);
/* clear the selection */
if (currcons == sel_cons)
clear_selection();
 
disable_bh(CONSOLE_BH);
while (count) {
enable_bh(CONSOLE_BH);
c = from_user ? get_user(buf) : *buf;
buf++; n++; count--;
disable_bh(CONSOLE_BH);
 
if (utf) {
/* Combine UTF-8 into Unicode */
/* Incomplete characters silently ignored */
if(c > 0x7f) {
if (utf_count > 0 && (c & 0xc0) == 0x80) {
utf_char = (utf_char << 6) | (c & 0x3f);
utf_count--;
if (utf_count == 0)
tc = c = utf_char;
else continue;
} else {
if ((c & 0xe0) == 0xc0) {
utf_count = 1;
utf_char = (c & 0x1f);
} else if ((c & 0xf0) == 0xe0) {
utf_count = 2;
utf_char = (c & 0x0f);
} else if ((c & 0xf8) == 0xf0) {
utf_count = 3;
utf_char = (c & 0x07);
} else if ((c & 0xfc) == 0xf8) {
utf_count = 4;
utf_char = (c & 0x03);
} else if ((c & 0xfe) == 0xfc) {
utf_count = 5;
utf_char = (c & 0x01);
} else
utf_count = 0;
continue;
}
} else {
tc = c;
utf_count = 0;
}
} else { /* no utf */
tc = translate[toggle_meta ? (c|0x80) : c];
}
 
/* If the original code was a control character we
* only allow a glyph to be displayed if the code is
* not normally used (such as for cursor movement) or
* if the disp_ctrl mode has been explicitly enabled.
* Certain characters (as given by the CTRL_ALWAYS
* bitmap) are always displayed as control characters,
* as the console would be pretty useless without
* them; to display an arbitrary font position use the
* direct-to-font zone in UTF-8 mode.
*/
ok = tc && (c >= 32 ||
(!utf && !(((disp_ctrl ? CTRL_ALWAYS
: CTRL_ACTION) >> c) & 1)))
&& (c != 127 || disp_ctrl);
 
if (vc_state == ESnormal && ok) {
/* Now try to find out how to display it */
tc = conv_uni_to_pc(tc);
if ( tc == -4 ) {
/* If we got -4 (not found) then see if we have
defined a replacement character (U+FFFD) */
tc = conv_uni_to_pc(0xfffd);
} else if ( tc == -3 ) {
/* Bad hash table -- hope for the best */
tc = c;
}
if (tc & ~console_charmask)
continue; /* Conversion failed */
 
if (need_wrap) {
cr(currcons);
lf(currcons);
}
#if 1 /* XXX */
/* DPC: 1994-04-12
* Speed up overstrike mode, using new putcs.
*
* P.S. I hate 8 spaces per tab! Use Emacs!
*/
/* Only use this for the foreground console,
where we really draw the chars */
 
if (count > 2 &&
!decim && !utf && currcons == fg_console) {
static char putcs_buf[256];
char *p = putcs_buf;
int putcs_count = 1;
ushort nextx = x + 1;
 
*p++ = tc;
*pos++ = tc | (attr << 8);
if (nextx == cols) {
sw->con_putc(vc_cons[currcons].d,
*putcs_buf, y, x);
pos--;
need_wrap = decawm;
continue;
}
/* TAB TAB TAB - Arghh!!!! */
while (count)
{
enable_bh(CONSOLE_BH);
c = from_user ? get_user(buf) : *buf;
disable_bh(CONSOLE_BH);
tc = translate[toggle_meta ? (c|0x80) : c];
if (!tc ||
!(c >= 32
|| !(((disp_ctrl ? CTRL_ALWAYS
: CTRL_ACTION) >> c) & 1)))
break;
tc = conv_uni_to_pc(tc);
if (tc == -4)
tc = conv_uni_to_pc(0xfffd);
else if (tc == -3)
tc = c;
 
buf++; n++; count--;
if (tc & ~console_charmask)
continue; /* Conversion failed */
 
*p++ = tc;
*pos++ = tc | (attr << 8);
++putcs_count;
++nextx;
if (nextx == cols ||
putcs_count == sizeof (putcs_buf))
break;
}
sw->con_putcs(vc_cons[currcons].d,
putcs_buf, putcs_count, y, x);
if (nextx == cols) {
pos--;
x = cols-1;
need_wrap = decawm;
} else
x += putcs_count;
continue;
}
/* DPC: End of putcs support */
#endif
if (decim)
insert_char(currcons);
*pos = (attr << 8) + tc;
if (currcons == fg_console)
sw->con_putc(vc_cons[currcons].d,tc,y,x);
if (x == cols - 1)
need_wrap = decawm;
else {
pos++;
x++;
}
continue;
}
 
/*
* Control characters can be used in the _middle_
* of an escape sequence.
*/
switch (c) {
case 7:
if (bell_duration)
kd_mksound(bell_pitch, bell_duration);
continue;
case 8:
bs(currcons);
continue;
case 9:
pos -= x;
while (x < cols - 1) {
x++;
if (tab_stop[x >> 5] & (1 << (x & 31)))
break;
}
pos += x;
continue;
case 10: case 11: case 12:
lf(currcons);
if (!is_kbd(lnm))
continue;
case 13:
cr(currcons);
continue;
case 14:
charset = 1;
translate = set_translate(G1_charset);
disp_ctrl = 1;
continue;
case 15:
charset = 0;
translate = set_translate(G0_charset);
disp_ctrl = 0;
continue;
case 24: case 26:
vc_state = ESnormal;
continue;
case 27:
vc_state = ESesc;
continue;
case 127:
del(currcons);
continue;
case 128+27:
vc_state = ESsquare;
continue;
}
switch(vc_state) {
case ESesc:
vc_state = ESnormal;
switch (c) {
case '[':
vc_state = ESsquare;
continue;
case ']':
vc_state = ESnonstd;
continue;
case '%':
vc_state = ESpercent;
continue;
case 'E':
cr(currcons);
lf(currcons);
continue;
case 'M':
ri(currcons);
continue;
case 'D':
lf(currcons);
continue;
case 'H':
tab_stop[x >> 5] |= (1 << (x & 31));
continue;
case 'Z':
respond_ID(tty);
continue;
case '7':
save_cur(currcons);
continue;
case '8':
restore_cur(currcons);
continue;
case '(':
vc_state = ESsetG0;
continue;
case ')':
vc_state = ESsetG1;
continue;
case '#':
vc_state = EShash;
continue;
case 'c':
reset_terminal(currcons,1);
continue;
case '>': /* Numeric keypad */
clr_kbd(kbdapplic);
continue;
case '=': /* Appl. keypad */
set_kbd(kbdapplic);
continue;
}
continue;
case ESnonstd:
if (c=='P') { /* palette escape sequence */
for (npar=0; npar<NPAR; npar++)
par[npar] = 0 ;
npar = 0 ;
vc_state = ESpalette;
continue;
} else if (c=='R') { /* reset palette */
#if 0
reset_palette (currcons);
#endif
vc_state = ESnormal;
} else
vc_state = ESnormal;
continue;
case ESpalette:
if ( (c>='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) {
par[npar++] = (c>'9' ? (c&0xDF)-'A'+10 : c-'0') ;
if (npar==7) {
#if 0
int i = par[0]*3, j = 1;
palette[i] = 16*par[j++];
palette[i++] += par[j++];
palette[i] = 16*par[j++];
palette[i++] += par[j++];
palette[i] = 16*par[j++];
palette[i] += par[j];
set_palette() ;
#endif
vc_state = ESnormal;
}
} else
vc_state = ESnormal;
continue;
case ESsquare:
for(npar = 0 ; npar < NPAR ; npar++)
par[npar] = 0;
npar = 0;
vc_state = ESgetpars;
if (c == '[') { /* Function key */
vc_state=ESfunckey;
continue;
}
ques = (c=='?');
if (ques)
continue;
case ESgetpars:
if (c==';' && npar<NPAR-1) {
npar++;
continue;
} else if (c>='0' && c<='9') {
par[npar] *= 10;
par[npar] += c-'0';
continue;
} else vc_state=ESgotpars;
case ESgotpars:
vc_state = ESnormal;
switch(c) {
case 'h':
set_mode(currcons,1);
continue;
case 'l':
set_mode(currcons,0);
continue;
case 'n':
if (!ques)
if (par[0] == 5)
status_report(tty);
else if (par[0] == 6)
cursor_report(currcons,tty);
continue;
}
if (ques) {
ques = 0;
continue;
}
switch(c) {
case 'G': case '`':
if (par[0]) par[0]--;
gotoxy(currcons,par[0],y);
continue;
case 'A':
if (!par[0]) par[0]++;
gotoxy(currcons,x,y-par[0]);
continue;
case 'B': case 'e':
if (!par[0]) par[0]++;
gotoxy(currcons,x,y+par[0]);
continue;
case 'C': case 'a':
if (!par[0]) par[0]++;
gotoxy(currcons,x+par[0],y);
continue;
case 'D':
if (!par[0]) par[0]++;
gotoxy(currcons,x-par[0],y);
continue;
case 'E':
if (!par[0]) par[0]++;
gotoxy(currcons,0,y+par[0]);
continue;
case 'F':
if (!par[0]) par[0]++;
gotoxy(currcons,0,y-par[0]);
continue;
case 'd':
if (par[0]) par[0]--;
gotoxay(currcons,x,par[0]);
continue;
case 'H': case 'f':
if (par[0]) par[0]--;
if (par[1]) par[1]--;
gotoxay(currcons,par[1],par[0]);
continue;
case 'J':
csi_J(currcons,par[0]);
continue;
case 'K':
csi_K(currcons,par[0]);
continue;
case 'L':
csi_L(currcons,par[0]);
continue;
case 'M':
csi_M(currcons,par[0]);
continue;
case 'P':
csi_P(currcons,par[0]);
continue;
case 'c':
if (!par[0])
respond_ID(tty);
continue;
case 'g':
if (!par[0])
tab_stop[x >> 5] &= ~(1 << (x & 31));
else if (par[0] == 3) {
tab_stop[0] =
tab_stop[1] =
tab_stop[2] =
tab_stop[3] =
tab_stop[4] = 0;
}
continue;
case 'm':
csi_m(currcons);
continue;
case 'q': /* DECLL - but only 3 leds */
/* map 0,1,2,3 to 0,1,2,4 */
if (par[0] < 4)
setledstate(kbd_table + currcons,
(par[0] < 3) ? par[0] : 4);
continue;
case 'r':
if (!par[0])
par[0]++;
if (!par[1])
par[1] = rows;
/* Minimum allowed region is 2 lines */
if (par[0] < par[1] &&
par[1] <= rows) {
top=par[0]-1;
bottom=par[1];
gotoxay(currcons,0,0);
}
continue;
case 's':
save_cur(currcons);
continue;
case 'u':
restore_cur(currcons);
continue;
case 'X':
csi_X(currcons, par[0]);
continue;
case '@':
csi_at(currcons,par[0]);
continue;
case ']': /* setterm functions */
setterm_command(currcons);
continue;
}
continue;
case ESpercent:
vc_state = ESnormal;
switch (c) {
case '@': /* defined in ISO 2022 */
utf = 0;
continue;
case 'G': /* prelim official escape code */
case '8': /* retained for compatibility */
utf = 1;
continue;
}
continue;
case ESfunckey:
vc_state = ESnormal;
continue;
case EShash:
vc_state = ESnormal;
if (c == '8') {
/* DEC screen alignment test. kludge :-) */
video_erase_char =
(video_erase_char & 0xff00) | 'E';
/* Arno:
* Doesn't work, because csi_J(c,2)
* calls con_clear and doesn't print
* the erase char..
*/
csi_J(currcons, 2);
video_erase_char =
(video_erase_char & 0xff00) | ' ';
}
continue;
case ESsetG0:
if (c == '0')
G0_charset = GRAF_MAP;
else if (c == 'B')
G0_charset = LAT1_MAP;
else if (c == 'U')
G0_charset = IBMPC_MAP;
else if (c == 'K')
G0_charset = USER_MAP;
if (charset == 0)
translate = set_translate(G0_charset);
vc_state = ESnormal;
continue;
case ESsetG1:
if (c == '0')
G1_charset = GRAF_MAP;
else if (c == 'B')
G1_charset = LAT1_MAP;
else if (c == 'U')
G1_charset = IBMPC_MAP;
else if (c == 'K')
G1_charset = USER_MAP;
if (charset == 1)
translate = set_translate(G1_charset);
vc_state = ESnormal;
continue;
default:
vc_state = ESnormal;
}
}
if (vcmode != KD_GRAPHICS)
set_cursor(currcons);
enable_bh(CONSOLE_BH);
return n;
}
 
static int con_write_room(struct tty_struct *tty)
{
if (tty->stopped)
return 0;
return 4096; /* No limit, really; we're not buffering */
}
 
static int con_chars_in_buffer(struct tty_struct *tty)
{
return 0; /* we're not buffering */
}
 
void poke_blanked_console(void)
{
timer_active &= ~(1<<BLANK_TIMER);
if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
return;
if (console_blanked) {
timer_table[BLANK_TIMER].fn = unblank_screen;
timer_table[BLANK_TIMER].expires = 0;
timer_active |= 1<<BLANK_TIMER;
} else if (blankinterval) {
timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
timer_active |= 1<<BLANK_TIMER;
}
}
 
/* DPC: New version of console_print using putcs */
 
void console_print(const char * b)
{
int currcons = fg_console;
unsigned char c;
const char *start = b;
ushort count = 0;
ushort myx = x;
static int printing = 0;
 
if (!printable || printing)
return; /* console not yet initialized */
printing = 1;
 
if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1))
currcons = kmsg_redirect - 1;
 
if (!vc_cons_allocated(currcons)) {
/* impossible */
printk("console_print: tty %d not allocated ??\n", currcons+1);
printing = 0;
return;
}
 
/* undraw cursor first */
hide_cursor(currcons);
 
/* Contrived structure to try to emulate original need_wrap behaviour
* Problems caused when we have need_wrap set on '\n' character */
while ((c = *(b++)) != 0) {
if (c == 10 || c == 13 || c == 8 || need_wrap) {
if ((count = b - start - 1) > 0) {
sw->con_putcs(vc_cons[currcons].d, start, count ,
y, x);
x += count;
if (need_wrap)
x--;
}
 
if (c == 8) { /* backspace */
bs(currcons);
start = b;
myx = x;
continue;
}
if (c != 13)
lf(currcons);
cr(currcons);
 
if (c == 10 || c == 13) {
start = b; myx = x; continue;
}
 
start = b-1; myx = x;
}
 
*pos = c | (attr << 8);
if (myx == cols - 1) {
need_wrap = 1;
continue;
}
pos++;
myx++;
}
 
if ((count = b - start -1) > 0) {
sw->con_putcs(vc_cons[currcons].d, start, count ,
y, x);
x += count;
if (x == cols)
{
x--;
need_wrap = 1;
}
}
set_cursor(currcons);
poke_blanked_console();
printing = 0;
}
 
/* You didn't see this... */
void console_printn(const char * b, int n)
{
int i;
char buf[2];
buf[1] = '\0';
for(i=0;i<n;i++) {
buf[0] = *b++;
console_print(buf);
}
}
 
/*
* con_throttle and con_unthrottle are only used for
* paste_selection(), which has to stuff in a large number of
* characters...
*/
static void con_throttle(struct tty_struct *tty)
{
}
 
static void con_unthrottle(struct tty_struct *tty)
{
struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
 
wake_up_interruptible(&vt->paste_wait);
}
 
static void vc_init(unsigned int currcons, int do_clear)
{
long base = (long) vc_scrbuf[currcons];
 
pos = (unsigned short *)(origin = (ulong)video_mem_start = base);
scr_end = base + screenbuf_size;
video_mem_end = base + screenbuf_size;
reset_vc(currcons);
def_color = 0x07; /* white */
ulcolor = 0x0f; /* bold white */
halfcolor = 0x08; /* grey */
vt_cons[currcons]->paste_wait = 0;
reset_terminal(currcons, do_clear);
}
 
/*
* This is the console switching bottom half handler.
*
* Doing console switching in a bottom half handler allows
* us to do the switches asynchronously (needed when we want
* to switch due to a keyboard interrupt), while still giving
* us the option to easily disable it to avoid races when we
* need to write to the console.
*/
static void console_bh(void)
{
if (want_console >= 0) {
if (want_console != fg_console) {
change_console(want_console);
/* we only changed when the console had already
been allocated - a new console is not created
in an interrupt routine */
}
want_console = -1;
}
if (do_poke_blanked_console) { /* do not unblank for a LED change */
do_poke_blanked_console = 0;
poke_blanked_console();
}
}
 
/*
* unsigned long con_init(unsigned long);
*
* This routine initializes console interrupts, and does nothing
* else. If you want the screen to clear, call tty_write with
* the appropriate escape-sequence.
*
* Reads the information preserved by setup.s to determine the current display
* type and sets everything accordingly.
*/
unsigned long con_init(unsigned long kmem_start)
{
 
#ifdef CONFIG_FRAMEBUFFER
 
#if 0 /* Disable console unless some buttons are pressed */
{
int i;
for(i=0;i<200000;i++) {
__asm__("nop");
if ((*(volatile unsigned char*)0xFFFFF419) & (8|1))
break;
}
if (!((*(volatile unsigned char*)0xFFFFF419) & (8|1)))
return;
}
}
#endif
char *display_desc = "????";
unsigned int currcons = 0;
extern int serial_debug;
memset(&console_driver, 0, sizeof(struct tty_driver));
console_driver.magic = TTY_DRIVER_MAGIC;
console_driver.name = "tty";
console_driver.name_base = 1;
console_driver.major = TTY_MAJOR;
console_driver.minor_start = 1;
console_driver.num = MAX_NR_CONSOLES;
console_driver.type = TTY_DRIVER_TYPE_CONSOLE;
console_driver.init_termios = tty_std_termios;
console_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
console_driver.refcount = &console_refcount;
console_driver.table = console_table;
console_driver.termios = console_termios;
console_driver.termios_locked = console_termios_locked;
 
console_driver.open = con_open;
console_driver.write = con_write;
console_driver.write_room = con_write_room;
console_driver.chars_in_buffer = con_chars_in_buffer;
console_driver.ioctl = vt_ioctl;
console_driver.stop = con_stop;
console_driver.start = con_start;
console_driver.throttle = con_throttle;
console_driver.unthrottle = con_unthrottle;
if (tty_register_driver(&console_driver))
panic("Couldn't register console driver\n");
 
kmem_start = conswitchp->con_startup (kmem_start, &display_desc);
/*conswitchp->con_set_font (&display_desc, 0, 0, "MINI4x6");*/
timer_table[BLANK_TIMER].fn = blank_screen;
timer_table[BLANK_TIMER].expires = 0;
if (blankinterval) {
timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
timer_active |= 1<<BLANK_TIMER;
}
 
/* Due to kmalloc roundup allocating statically is more efficient -
so provide MIN_NR_CONSOLES for people with very little memory */
for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
vc_cons[currcons].d = (struct vc_data *) kmem_start;
kmem_start += sizeof(struct vc_data);
vt_cons[currcons] = (struct vt_struct *) kmem_start;
kmem_start += sizeof(struct vt_struct);
 
/* ++Geert: sw->con_init determines console size */
sw = conswitchp;
cons_num = currcons;
sw->con_init (vc_cons[currcons].d);
size_row = cols<<1;
screenbuf_size = rows*size_row;
 
vc_scrbuf[currcons] = (unsigned short *) kmem_start;
kmem_start += screenbuf_size;
kmalloced = 0;
vc_init(currcons, currcons);
}
 
currcons = fg_console = 0;
 
gotoxy(currcons,0, 0);
printable = 1;
sw->con_cursor(vc_cons[currcons].d, CM_DRAW);
printable = 1;
 
/* If "serdebug" cmd line option was present, don't register for printk */
if (!serial_debug)
register_console(console_print);
 
printk("Console driver: %s %s %ldx%ld, %d virtual console%s (max %d)\n",
can_do_color ? "colour":"mono",
display_desc,
cols,rows,
MIN_NR_CONSOLES, (MIN_NR_CONSOLES == 1) ? "" : "s", MAX_NR_CONSOLES);
 
init_bh(CONSOLE_BH, console_bh);
#endif
return kmem_start;
}
 
void vesa_powerdown_screen(void)
{
int currcons = fg_console;
 
timer_active &= ~(1<<BLANK_TIMER);
timer_table[BLANK_TIMER].fn = unblank_screen;
 
/* Power down if currently suspended (1 or 2),
* suspend if currently blanked (0),
* else do nothing (i.e. already powered down (3)).
* Called only if powerdown features are allowed.
*/
switch (vesa_blank_mode) {
case 0:
sw->con_blank(2);
break;
case 1:
case 2:
sw->con_blank(4);
break;
}
}
 
void do_blank_screen(int nopowersave)
{
#if 0
int currcons;
 
if (console_blanked)
return;
 
if (!vc_cons_allocated(fg_console)) {
/* impossible */
printk("blank_screen: tty %d not allocated ??\n", fg_console+1);
return;
}
 
/* don't blank graphics */
if (vt_cons[fg_console]->vc_mode == KD_TEXT) {
if (vesa_off_interval && !nopowersave) {
timer_table[BLANK_TIMER].fn = vesa_powerdown_screen;
timer_table[BLANK_TIMER].expires = jiffies + vesa_off_interval;
timer_active |= (1<<BLANK_TIMER);
} else {
timer_active &= ~(1<<BLANK_TIMER);
timer_table[BLANK_TIMER].fn = unblank_screen;
}
 
/* try not to lose information by blanking,
and not to waste memory */
currcons = fg_console;
has_scrolled = 0;
sw->con_blank(1);
if (!nopowersave)
sw->con_blank(vesa_blank_mode + 1);
}
else
hide_cursor(fg_console);
console_blanked = fg_console + 1;
#endif
}
 
void do_unblank_screen(void)
{
#if 0
int currcons;
 
if (!console_blanked)
return;
if (!vc_cons_allocated(fg_console)) {
/* impossible */
printk("unblank_screen: tty %d not allocated ??\n", fg_console+1);
return;
}
timer_table[BLANK_TIMER].fn = blank_screen;
if (blankinterval) {
timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
timer_active |= 1<<BLANK_TIMER;
}
 
currcons = fg_console;
console_blanked = 0;
if (sw->con_blank (0))
/* Low-level driver cannot restore -> do it ourselves */
update_screen( fg_console );
set_cursor (fg_console);
#endif
}
 
void update_screen(int new_console)
{
int currcons = fg_console;
int xx, yy, startx, attr_save;
char buf[256], *bufp;
unsigned short *p;
static int lock = 0;
 
if (/* new_console == fg_console || */ lock)
return;
if (!vc_cons_allocated(new_console)) {
/* strange ... */
printk("update_screen: tty %d not allocated ??\n", new_console+1);
return;
}
lock = 1;
 
clear_selection();
 
currcons = fg_console = new_console;
sw->con_cursor (vc_cons[currcons].d, CM_ERASE);
sw->con_switch (vc_cons[new_console].d);
/* Update the screen contents */
p = video_mem_start;
attr_save = attr;
for (yy = 0; yy < rows; yy++)
{
bufp = buf;
for (startx = xx = 0; xx < cols; xx++)
{
if (attr != ((*p >> 8) & 0xff))
{
if (bufp > buf)
sw->con_putcs (vc_cons[currcons].d, buf, bufp - buf,
yy, startx);
startx = xx;
bufp = buf;
attr = (*p >> 8) & 0xff;
}
*bufp++ = *p++;
if (bufp == buf + sizeof (buf))
{
sw->con_putcs (vc_cons[currcons].d, buf, bufp - buf,
yy, startx);
startx = xx + 1;
bufp = buf;
}
}
if (bufp > buf)
sw->con_putcs (vc_cons[currcons].d, buf, bufp - buf,
yy, startx);
}
set_cursor (currcons);
attr = attr_save;
set_leds();
compute_shiftstate();
lock = 0;
}
 
/*
* If a blank_screen is due to a timer, then a power save is allowed.
* If it is related to console_switching, then avoid vesa_blank().
*/
static void blank_screen(void)
{
do_blank_screen(0);
}
 
static void unblank_screen(void)
{
do_unblank_screen();
}
 
/*
* Allocate the console screen memory.
*/
int con_open(struct tty_struct *tty, struct file * filp)
{
unsigned int currcons;
int i;
 
currcons = MINOR(tty->device) - tty->driver.minor_start;
i = vc_allocate(currcons);
if (i)
return i;
 
vt_cons[currcons]->vc_num = currcons;
tty->driver_data = vt_cons[currcons];
if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
tty->winsize.ws_row = rows;
tty->winsize.ws_col = cols;
}
 
return 0;
}
 
/*
* PIO_FONT support.
*
* Currently we only support 8 pixels wide fonts, at a maximum height
* of 32 pixels. Userspace fontdata is stored with 32 bytes reserved
* for each character which is kinda wasty, but this is done in order
* to maintain compatibility with the EGA/VGA fonts. It is upto the
* actual low-level console-driver convert data into its favorite
* format (maybe we should add a `fontoffset' field to the `display'
* structure so we wont have to convert the fontdata all the time.
* /Jes
*/
 
#define cmapsz 8192
 
static int set_get_font(char * arg, int set, int ch512)
{
#ifdef CAN_LOAD_EGA_FONTS
int i, unit, size;
char *charmap;
 
if (arg){
i = verify_area(set ? VERIFY_READ : VERIFY_WRITE,
(void *)arg, ch512 ? 2*cmapsz : cmapsz);
if (i)
return i;
}else
return -EINVAL;
 
 
size = ch512 ? 2*cmapsz : cmapsz;
 
charmap = (char *)kmalloc(size, GFP_USER);
 
if (set){
memcpy_fromfs(charmap, arg, size);
 
for (unit = 32; unit > 0; unit--)
for (i = 0; i < (ch512 ? 512 : 256); i++)
if (charmap[32*i+unit-1])
goto nonzero;
nonzero:
i = conswitchp->con_set_font(vc_cons[fg_console].d, 8,
unit, charmap);
}else{
memset(charmap, 0, size);
i = conswitchp->con_get_font(vc_cons[fg_console].d,
&unit, &unit, charmap);
memcpy_tofs(arg, charmap, size);
}
kfree(charmap);
 
return i;
#else
return -EINVAL;
#endif
}
 
/*
* Load palette into the EGA/VGA DAC registers. arg points to a colour
* map, 3 bytes per colour, 16 colours, range from 0 to 255.
*/
 
int con_set_cmap (unsigned char *arg)
{
return -EINVAL;
}
 
int con_get_cmap (unsigned char *arg)
{
return -EINVAL;
}
 
void reset_palette(int currcons)
{
}
 
void set_palette(void)
{
}
 
/*
* Load font into the EGA/VGA character generator. arg points to a 8192
* byte map, 32 bytes per character. Only first H of them are used for
* 8xH fonts (0 < H <= 32).
*/
 
int con_set_font (char *arg, int ch512)
{
int i;
 
i = set_get_font (arg,1,ch512);
if ( !i ) {
hashtable_contents_valid = 0;
video_mode_512ch = ch512;
console_charmask = ch512 ? 0x1ff : 0x0ff;
}
return i;
}
 
int con_get_font (char *arg)
{
return set_get_font (arg,0,video_mode_512ch);
}
 
/*
* Adjust the screen to fit a font of a certain height
*
* Returns < 0 for error, 0 if nothing changed, and the number
* of lines on the adjusted console if changed.
*/
int con_adjust_height(unsigned long fontheight)
{
return -EINVAL;
}
 
void set_vesa_blanking(int arg)
{
char *argp = (char *)arg + 1;
unsigned int mode = get_fs_byte(argp);
vesa_blank_mode = (mode < 4) ? mode : 0;
}
 
unsigned long get_video_num_lines(unsigned int currcons)
{
return(rows);
}
 
unsigned long get_video_num_columns(unsigned int currcons)
{
return(cols);
}
 
unsigned long get_video_size_row(unsigned int currcons)
{
return(size_row);
}
 
/*
* Report the current status of the vc. This is exported to modules (ARub)
*/
 
int con_get_info(int *mode, int *shift, int *col, int *row,
struct tty_struct **tty)
{
extern int shift_state;
extern struct tty_driver console_driver;
struct tty_struct **console_table=console_driver.table;
 
if (mode) *mode = vt_cons[fg_console]->vc_mode;
if (shift) *shift = shift_state;
if (col) *col = video_num_columns;
if (row) *row = video_num_lines;
if (tty) *tty = console_table[fg_console];
return fg_console;
}
/ksyms.c
0,0 → 1,40
#include <linux/config.h>
#include <linux/module.h>
#include <linux/linkage.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/user.h>
#include <linux/elfcore.h>
 
#include <asm/pgtable.h>
#include <asm/irq.h>
#include <asm/semaphore.h>
 
extern void dump_thread(struct pt_regs *, struct user *);
extern int dump_fpu(elf_fpregset_t *);
 
static struct symbol_table arch_symbol_table = {
#include <linux/symtab_begin.h>
/* platform dependent support */
 
X(memcmp),
X(request_irq),
X(free_irq),
X(dump_fpu),
X(dump_thread),
X(strnlen),
 
/* The following are special because they're not called
explicitly (the C compiler generates them). Fortunately,
their interface isn't gonna change any time soon now, so
it's OK to leave it out of version control. */
XNOVERS(memcpy),
 
#include <linux/symtab_end.h>
};
 
void arch_syms_export(void)
{
register_symtab(&arch_symbol_table);
}
/mk_defs.c
0,0 → 1,136
/*
* This program is used to generate definitions needed by
* assembly language modules.
*/
#define MK_DEFS
#include <stdio.h>
 
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/head.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/ptrace.h>
#include <linux/mman.h>
#include <linux/mm.h>
 
extern int errno;
 
main(int argc, char *argv[])
{
FILE *out;
struct task_struct task;
struct thread_struct tss;
struct pt_regs regs;
if (!(out = fopen(argv[1], "w")))
{
fprintf(stderr, "Can't create output file: %s\n", strerror(errno));
exit(1);
}
fprintf(out, "/*\n");
fprintf(out, " * WARNING! This file is automatically generated - DO NOT EDIT!\n");
fprintf(out, " */\n");
put_line(out, "STATE", (int)&task.state-(int)&task);
put_line(out, "COUNTER", (int)&task.counter-(int)&task);
put_line(out, "BLOCKED", (int)&task.blocked-(int)&task);
put_line(out, "SIGNAL", (int)&task.signal-(int)&task);
put_line(out, "KERNEL_STACK_PAGE", (int)&task.kernel_stack_page-(int)&task);
put_line(out, "TSS", (int)&task.tss-(int)&task);
put_line(out, "KSP", (int)&tss.ksp-(int)&tss);
put_line(out, "LAST_PC", (int)&tss.last_pc-(int)&tss);
put_line(out, "USER_STACK", (int)&tss.user_stack-(int)&tss);
put_line(out, "PT_REGS", (int)&tss.regs-(int)&tss);
put_line(out, "PF_TRACESYS", PF_TRACESYS);
put_line(out, "TASK_FLAGS", (int)&task.flags-(int)&task);
put_line(out, "MMU_SEG0", (int)&tss.segs[0]-(int)&tss);
put_line(out, "MMU_SEG1", (int)&tss.segs[1]-(int)&tss);
put_line(out, "MMU_SEG2", (int)&tss.segs[2]-(int)&tss);
put_line(out, "MMU_SEG3", (int)&tss.segs[3]-(int)&tss);
put_line(out, "MMU_SEG4", (int)&tss.segs[4]-(int)&tss);
put_line(out, "MMU_SEG5", (int)&tss.segs[5]-(int)&tss);
put_line(out, "MMU_SEG6", (int)&tss.segs[6]-(int)&tss);
put_line(out, "MMU_SEG7", (int)&tss.segs[7]-(int)&tss);
put_line(out, "MMU_SEG8", (int)&tss.segs[8]-(int)&tss);
put_line(out, "MMU_SEG9", (int)&tss.segs[9]-(int)&tss);
put_line(out, "MMU_SEG10", (int)&tss.segs[10]-(int)&tss);
put_line(out, "MMU_SEG11", (int)&tss.segs[11]-(int)&tss);
put_line(out, "MMU_SEG12", (int)&tss.segs[12]-(int)&tss);
put_line(out, "MMU_SEG13", (int)&tss.segs[13]-(int)&tss);
put_line(out, "MMU_SEG14", (int)&tss.segs[14]-(int)&tss);
put_line(out, "MMU_SEG15", (int)&tss.segs[15]-(int)&tss);
put_line(out, "TSS_FPR0", (int)&tss.fpr[0]-(int)&tss);
put_line(out, "TSS_FPR1", (int)&tss.fpr[1]-(int)&tss);
put_line(out, "TSS_FPR2", (int)&tss.fpr[2]-(int)&tss);
put_line(out, "TSS_FPR3", (int)&tss.fpr[3]-(int)&tss);
put_line(out, "TSS_FPR4", (int)&tss.fpr[4]-(int)&tss);
put_line(out, "TSS_FPR5", (int)&tss.fpr[5]-(int)&tss);
put_line(out, "TSS_FPR6", (int)&tss.fpr[6]-(int)&tss);
put_line(out, "TSS_FPR7", (int)&tss.fpr[7]-(int)&tss);
put_line(out, "TSS_FPR8", (int)&tss.fpr[8]-(int)&tss);
put_line(out, "TSS_FPR9", (int)&tss.fpr[9]-(int)&tss);
put_line(out, "TSS_FPR10", (int)&tss.fpr[10]-(int)&tss);
put_line(out, "TSS_FPR11", (int)&tss.fpr[11]-(int)&tss);
put_line(out, "TSS_FPR12", (int)&tss.fpr[12]-(int)&tss);
put_line(out, "TSS_FPR13", (int)&tss.fpr[13]-(int)&tss);
put_line(out, "TSS_FPR14", (int)&tss.fpr[14]-(int)&tss);
put_line(out, "TSS_FPR15", (int)&tss.fpr[15]-(int)&tss);
put_line(out, "TSS_FPR16", (int)&tss.fpr[16]-(int)&tss);
put_line(out, "TSS_FPR17", (int)&tss.fpr[17]-(int)&tss);
put_line(out, "TSS_FPR18", (int)&tss.fpr[18]-(int)&tss);
put_line(out, "TSS_FPR19", (int)&tss.fpr[19]-(int)&tss);
put_line(out, "TSS_FPR20", (int)&tss.fpr[20]-(int)&tss);
put_line(out, "TSS_FPR21", (int)&tss.fpr[21]-(int)&tss);
put_line(out, "TSS_FPR22", (int)&tss.fpr[22]-(int)&tss);
put_line(out, "TSS_FPR23", (int)&tss.fpr[23]-(int)&tss);
put_line(out, "TSS_FPR24", (int)&tss.fpr[24]-(int)&tss);
put_line(out, "TSS_FPR25", (int)&tss.fpr[25]-(int)&tss);
put_line(out, "TSS_FPR26", (int)&tss.fpr[26]-(int)&tss);
put_line(out, "TSS_FPR27", (int)&tss.fpr[27]-(int)&tss);
put_line(out, "TSS_FPR28", (int)&tss.fpr[28]-(int)&tss);
put_line(out, "TSS_FPR29", (int)&tss.fpr[29]-(int)&tss);
put_line(out, "TSS_FPR30", (int)&tss.fpr[30]-(int)&tss);
put_line(out, "TSS_FPR31", (int)&tss.fpr[31]-(int)&tss);
/* Interrupt register frame */
put_line(out, "INT_FRAME_SIZE", sizeof(regs));
put_line(out, "SP", (int)&regs.sp-(int)&regs);
put_line(out, "PC", (int)&regs.pc-(int)&regs);
put_line(out, "GPR2", (int)&regs.gprs[0]-(int)&regs);
put_line(out, "GPR3", (int)&regs.gprs[1]-(int)&regs);
put_line(out, "GPR4", (int)&regs.gprs[2]-(int)&regs);
put_line(out, "GPR5", (int)&regs.gprs[3]-(int)&regs);
put_line(out, "GPR6", (int)&regs.gprs[4]-(int)&regs);
put_line(out, "GPR7", (int)&regs.gprs[5]-(int)&regs);
put_line(out, "GPR8", (int)&regs.gprs[6]-(int)&regs);
put_line(out, "GPR9", (int)&regs.gprs[7]-(int)&regs);
put_line(out, "GPR10", (int)&regs.gprs[8]-(int)&regs);
put_line(out, "GPR11", (int)&regs.gprs[9]-(int)&regs);
put_line(out, "GPR12", (int)&regs.gprs[10]-(int)&regs);
put_line(out, "GPR13", (int)&regs.gprs[11]-(int)&regs);
put_line(out, "GPR14", (int)&regs.gprs[12]-(int)&regs);
put_line(out, "GPR15", (int)&regs.gprs[13]-(int)&regs);
put_line(out, "GPR16", (int)&regs.gprs[14]-(int)&regs);
put_line(out, "GPR17", (int)&regs.gprs[15]-(int)&regs);
put_line(out, "GPR18", (int)&regs.gprs[16]-(int)&regs);
put_line(out, "GPR19", (int)&regs.gprs[17]-(int)&regs);
put_line(out, "GPR20", (int)&regs.gprs[18]-(int)&regs);
put_line(out, "GPR21", (int)&regs.gprs[19]-(int)&regs);
put_line(out, "GPR22", (int)&regs.gprs[20]-(int)&regs);
put_line(out, "GPR23", (int)&regs.gprs[21]-(int)&regs);
put_line(out, "GPR24", (int)&regs.gprs[22]-(int)&regs);
put_line(out, "GPR25", (int)&regs.gprs[23]-(int)&regs);
put_line(out, "GPR26", (int)&regs.gprs[24]-(int)&regs);
put_line(out, "GPR27", (int)&regs.gprs[25]-(int)&regs);
put_line(out, "GPR28", (int)&regs.gprs[26]-(int)&regs);
put_line(out, "GPR29", (int)&regs.gprs[27]-(int)&regs);
put_line(out, "GPR30", (int)&regs.gprs[28]-(int)&regs);
put_line(out, "GPR31", (int)&regs.gprs[29]-(int)&regs);
put_line(out, "SR", (int)&regs.sr-(int)&regs);
exit(0);
}
 
put_line(FILE *out, char *name, int offset)
{
fprintf(out, "#define %s %d\n", name, offset);
}
/misc.S
0,0 → 1,278
#include <asm/spr_defs.h>
#include <asm/board.h>
 
.text
/*
* Enable interrupts
* sti()
*/
.global _sti
_sti:
l.mfspr r3,r0,SPR_SR
l.ori r3,r3,(SPR_SR_IEE | SPR_SR_TEE)
l.mtspr r0,r3,SPR_SR
l.jr r9
l.nop
 
/*
* Disable interrupts
* cli()
*/
.global _cli
_cli:
l.addi r4,r0,-1
l.xori r4,r4,(SPR_SR_IEE | SPR_SR_TEE)
l.mfspr r3,r0,SPR_SR
l.and r3,r3,r4
l.mtspr r0,r3,SPR_SR
l.jr r9
l.nop
 
/*
* Get 'flags' (aka status register)
* __save_flags(long *ptr)
*/
.global ___save_flags
___save_flags:
l.mfspr r4,r0,SPR_SR
l.sw 0(r3),r4
l.jr r9
l.nop
 
/*
* Restore 'flags'
* __restore_flags(long val)
*/
.global ___restore_flags
___restore_flags:
l.mtspr r0,r3,SPR_SR
l.jr r9
l.nop
 
/*
* SPR write
* mtspr(long add, long val)
*/
.global _mtspr
_mtspr:
l.mtspr r3,r4,0
l.jr r9
l.nop
 
/*
* SPR read
* mtspr(long add)
*/
.global _mfspr
_mfspr:
l.mfspr r11,r3,0
l.jr r9
l.nop
 
/*
* Instruction cache enable
* ic_enable()
*/
.global _ic_enable
_ic_enable:
/* Disable IC */
l.mfspr r13,r0,SPR_SR
l.addi r11,r0,-1
l.xori r11,r11,SPR_SR_ICE
l.and r11,r13,r11
l.mtspr r0,r11,SPR_SR
 
/* Invalidate IC */
l.addi r13,r0,0
l.addi r11,r0,IC_SIZE
1:
l.mtspr r0,r13,SPR_ICBIR
l.sfne r13,r11
l.bf 1b
l.addi r13,r13,IC_LINE
 
/* Enable IC */
l.mfspr r13,r0,SPR_SR
l.ori r13,r13,SPR_SR_ICE
l.mtspr r0,r13,SPR_SR
l.nop
l.nop
l.nop
l.nop
l.nop
 
l.jr r9
l.nop
/*
* Instruction cache disable
* ic_disable()
*/
.global _ic_disable
_ic_disable:
/* Disable IC */
l.mfspr r13,r0,SPR_SR
l.addi r11,r0,-1
l.xori r11,r11,SPR_SR_ICE
l.and r11,r13,r11
l.mtspr r0,r11,SPR_SR
 
l.jr r9
l.nop
 
/*
* Instruction cache invalidate
* ic_flush()
*/
.global _ic_invalidate
_ic_invalidate:
/* Disable IC */
l.mfspr r13,r0,SPR_SR
l.addi r11,r0,-1
l.xori r11,r11,SPR_SR_ICE
l.and r11,r13,r11
l.mtspr r0,r11,SPR_SR
 
/* Invalidate IC */
l.addi r13,r0,0
l.addi r11,r0,IC_SIZE
1:
l.mtspr r0,r13,SPR_ICBIR
l.sfne r13,r11
l.bf 1b
l.addi r13,r13,IC_LINE
 
/* Enable IC */
l.mfspr r13,r0,SPR_SR
l.ori r13,r13,SPR_SR_ICE
l.mtspr r0,r13,SPR_SR
l.nop
l.nop
l.nop
l.nop
l.nop
 
l.jr r9
l.nop
 
/*
* Data cache enable
* dc_enable()
*/
.global _dc_enable
_dc_enable:
/* Disable DC */
l.mfspr r13,r0,SPR_SR
l.addi r11,r0,-1
l.xori r11,r11,SPR_SR_DCE
l.and r11,r13,r11
l.mtspr r0,r11,SPR_SR
 
/* Flush DC */
l.addi r13,r0,0
l.addi r11,r0,DC_SIZE
1:
l.mtspr r0,r13,SPR_DCBIR
l.sfne r13,r11
l.bf 1b
l.addi r13,r13,DC_LINE
 
/* Enable DC */
l.mfspr r13,r0,SPR_SR
l.ori r13,r13,SPR_SR_DCE
l.mtspr r0,r13,SPR_SR
 
l.jr r9
l.nop
/*
* Data cache disable
* dc_disable()
*/
.global _dc_disable
_dc_disable:
/* Disable DC */
l.mfspr r13,r0,SPR_SR
l.addi r11,r0,-1
l.xori r11,r11,SPR_SR_DCE
l.and r11,r13,r11
l.mtspr r0,r11,SPR_SR
 
l.jr r9
l.nop
/*
* Invalidate data cache line
* dc_line_invalidate(long ph_add)
*/
.global _dc_line_invalidate
_dc_line_invalidate:
l.mfspr r4,r0,SPR_SR
l.addi r5,r0,-1
l.xori r5,r5,SPR_SR_DCE
l.and r5,r4,r5
l.mtspr r0,r5,SPR_SR
l.mtspr r0,r3,SPR_DCBIR
l.mtspr r0,r4,SPR_SR
l.jr r9
l.nop
 
/*
* Data MMU enable
* dmmu_enable()
*/
.global _dmmu_enable
_dmmu_enable:
/* Invalidate all sets */
l.addi r11,r0,DMMU_SET_NB
l.addi r13,r0,0
1:
l.mtspr r13,r0,SPR_DTLBMR_BASE(0)
l.addi r11,r11,-1
l.sfeqi r11,0
l.bnf 1b
l.addi r13,r13,1
l.mfspr r11,r0,SPR_SR
l.ori r11,r11,SPR_SR_DME
l.mtspr r0,r11,SPR_SR
l.jr r9
l.nop
 
/*
* Instruction MMU enable
* immu_enable()
*/
.global _immu_enable
_immu_enable:
/* Invalidate all sets */
l.addi r11,r0,IMMU_SET_NB
l.addi r13,r0,0
1:
l.mtspr r13,r0,SPR_ITLBMR_BASE(0)
l.addi r11,r11,-1
l.sfeqi r11,0
l.bnf 1b
l.addi r13,r13,1
l.mfspr r11,r0,SPR_SR
l.ori r11,r11,SPR_SR_IME
l.mtspr r0,r11,SPR_SR
l.nop
l.nop
l.nop
l.nop
l.jr r9
l.nop
 
/*
* Print utility
* __print(const char *fmt, ...)
*/
.global __print
__print:
l.lwz r3,0(r1)
l.addi r4,r1,4
# l.sys 202
l.nop 3
l.jr r9
l.nop
 
/signal.c
0,0 → 1,262
/*
* linux/arch/ppc/kernel/signal.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
* Adapted for PowerPC by Gary Thomas
*/
 
#include <linux/config.h>
 
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/wait.h>
#include <linux/ptrace.h>
#include <linux/unistd.h>
 
#include <asm/segment.h>
#include <asm/pgtable.h>
#include <asm/traps.h>
 
/*
#define DEBUG
*/
 
#define offsetof(type, member) ((size_t)(&((type *)0)->member))
 
#define _S(nr) (1<<((nr)-1))
 
#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
 
asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs);
 
/*
* atomically swap in the new signal mask, and wait for a signal.
*/
asmlinkage int sys_sigsuspend(unsigned long set, int p2, int p3, int p4, int p6, int p7, struct pt_regs *regs)
{
unsigned long mask;
mask = current->blocked;
current->blocked = set & _BLOCKABLE;
regs->gprs[1] = -EINTR;
#if 0
printk("Task: %x[%d] - SIGSUSPEND at %x, Mask: %x\n", current, current->pid, regs->nip,
set);
#endif
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
if (do_signal(mask,regs))
return -EINTR;
}
}
 
/*
* This sets regs->esp even though we don't actually use sigstacks yet..
*/
asmlinkage int sys_sigreturn(struct pt_regs *regs)
{
struct sigcontext_struct *sc;
struct pt_regs *int_regs;
int signo;
sc = (struct sigcontext_struct *)regs->sp;
current->blocked = sc->oldmask & _BLOCKABLE;
int_regs = sc->regs;
signo = sc->signal;
sc++; /* Pop signal 'context' */
if (sc == (struct sigcontext_struct *)(int_regs))
{ /* Last stacked signal */
int i;
#if 1
memcpy(regs, int_regs, sizeof(*regs));
#else
/* Don't mess up 'my' stack frame */
for(i = 0; i < 30; i++)
if(i != 7)
regs->gprs[i] = int_regs->gprs[i];
regs->sp = int_regs->sp;
#endif
if ((int)regs->orig_gpr3 >= 0 &&
((int)regs->result == -ERESTARTNOHAND ||
(int)regs->result == -ERESTARTSYS ||
(int)regs->result == -ERESTARTNOINTR))
{
regs->gprs[1] = regs->orig_gpr3;
regs->pc -= 8; /* Back up & retry system call */
regs->result = 0;
}
return (regs->result);
} else
{ /* More signals to go */
regs->sp = (unsigned long)sc;
regs->gprs[1] = sc->signal; /* r3 */
regs->gprs[2] = (unsigned long)sc->regs; /* r4 */
regs->gprs[7] = (unsigned long)((sc->regs)+1); /* r9 - link register */
regs->pc = sc->handler;
return (sc->signal);
}
}
 
/*
* Note that 'init' is a special process: it doesn't get signals it doesn't
* want to handle. Thus you cannot kill init even with a SIGKILL even by
* mistake.
*
* Note that we go through the signals twice: once to check the signals that
* the kernel can handle, and then we build all the user-level signal handling
* stack-frames in one go after that.
*/
asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
{
unsigned long mask = ~current->blocked;
unsigned long handler_signal = 0;
unsigned long *frame = NULL;
unsigned long *trampoline;
unsigned long *regs_ptr;
unsigned long nip = 0;
unsigned long signr;
int bitno;
struct sigcontext_struct *sc;
struct sigaction * sa;
unsigned long flags;
 
save_flags(flags);
cli();
 
while ((signr = current->signal & mask)) {
#if 0
signr = ffz(~signr); /* Compute bit # */
#else
for (bitno = 0; bitno < 32; bitno++)
{
if (signr & (1<<bitno)) break;
}
signr = bitno;
#endif
current->signal &= ~(1<<signr); /* Clear bit */
sa = current->sig->action + signr;
signr++;
if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
current->exit_code = signr;
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
schedule();
if (!(signr = current->exit_code))
continue;
current->exit_code = 0;
if (signr == SIGSTOP)
continue;
if (_S(signr) & current->blocked) {
current->signal |= _S(signr);
continue;
}
sa = current->sig->action + signr - 1;
}
if (sa->sa_handler == SIG_IGN) {
if (signr != SIGCHLD)
continue;
/* check for SIGCHLD: it's special */
while (sys_waitpid(-1,NULL,WNOHANG) > 0)
/* nothing */;
continue;
}
if (sa->sa_handler == SIG_DFL) {
if (current->pid == 1)
continue;
switch (signr) {
case SIGCONT: case SIGCHLD: case SIGWINCH:
continue;
 
case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU:
if (current->flags & PF_PTRACED)
continue;
current->state = TASK_STOPPED;
current->exit_code = signr;
if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
SA_NOCLDSTOP))
notify_parent(current, SIGCHLD);
schedule();
continue;
 
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGIOT: case SIGFPE: case SIGSEGV:
if (current->binfmt && current->binfmt->core_dump) {
if (current->binfmt->core_dump(signr, regs))
signr |= 0x80;
}
/* fall through */
default:
current->signal |= _S(signr & 0x7f);
do_exit(signr);
}
}
/*
* OK, we're invoking a handler
*/
if ((int)regs->orig_gpr3 >= 0) {
if ((int)regs->result == -ERESTARTNOHAND ||
((int)regs->result == -ERESTARTSYS && !(sa->sa_flags & SA_RESTART)))
(int)regs->result = -EINTR;
}
handler_signal |= 1 << (signr-1);
mask &= ~sa->sa_mask;
}
if (!handler_signal) /* no handler will be called - return 0 */
{
restore_flags(flags);
return 0;
}
nip = regs->pc;
frame = (unsigned long *) regs->sp;
/* Build trampoline code on stack */
frame -= 3;
trampoline = frame;
trampoline[0] = 0x9d607777; /* l.addi r11,r0,0x7777 */
trampoline[1] = 0x20000001; /* l.sys 1 */
trampoline[2] = 0x15000000; /* l.nop 0 */
frame -= sizeof(*regs) / sizeof(long);
regs_ptr = frame;
memcpy(regs_ptr, regs, sizeof(*regs));
signr = 1;
sa = current->sig->action;
for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
if (mask > handler_signal)
break;
if (!(mask & handler_signal))
continue;
frame -= sizeof(struct sigcontext_struct) / sizeof(long);
sc = (struct sigcontext_struct *)frame;
nip = (unsigned long) sa->sa_handler;
#if 0 /* Old compiler */
nip = *(unsigned long *)nip;
#endif
if (sa->sa_flags & SA_ONESHOT)
sa->sa_handler = NULL;
sc->handler = nip;
sc->oldmask = current->blocked;
sc->regs = (struct pt_regs *)regs_ptr;
sc->signal = signr;
current->blocked |= sa->sa_mask;
regs->gprs[1] = signr; /* r3 = signr */
regs->gprs[2] = (unsigned long)regs_ptr; /* r4 = regs_ptr */
}
regs->gprs[7] = (unsigned long)trampoline; /* r9 = trampoline (r9 is link register) */
regs->pc = nip;
regs->sp = (unsigned long)sc;
/* The DATA cache must be flushed here to insure coherency */
/* between the DATA & INSTRUCTION caches. Since we just */
/* created an instruction stream using the DATA [cache] space */
/* and since the instruction cache will not look in the DATA */
/* cache for new data, we have to force the data to go on to */
/* memory and flush the instruction cache to force it to look */
/* there. The following function performs this magic */
#if ICACHE
ic_invalidate();
#endif
restore_flags(flags);
return 1;
}
/process.c
0,0 → 1,189
/*
* This file handles the architecture-dependent parts of process handling..
* Based on m86k.
*/
 
#include <linux/config.h>
#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/user.h>
#include <linux/a.out.h>
 
#include <asm/segment.h>
#include <asm/system.h>
#include <asm/traps.h>
#include <asm/machdep.h>
#include <asm/board.h>
 
asmlinkage void ret_from_exception(void);
 
/*
* The idle loop on an or32..
*/
asmlinkage int sys_idle(void)
{
if (current->pid != 0)
return -EPERM;
 
 
/* endless idle loop with no priority at all */
current->counter = -100;
for (;;) {
schedule();
}
}
 
void hard_reset_now(void)
{
HARD_RESET_NOW();
}
 
void show_regs(struct pt_regs * regs)
{
printk("\n");
printk("PC: %08lx Status: %08lx\n",
regs->pc, regs->sr);
printk("R0 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
0L, regs->sp, regs->gprs[0], regs->gprs[1],
regs->gprs[2], regs->gprs[3], regs->gprs[4], regs->gprs[5]);
printk("R8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
regs->gprs[6], regs->gprs[7], regs->gprs[8], regs->gprs[9],
regs->gprs[10], regs->gprs[11], regs->gprs[12], regs->gprs[13]);
printk("R16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
regs->gprs[14], regs->gprs[15], regs->gprs[16], regs->gprs[17],
regs->gprs[18], regs->gprs[19], regs->gprs[20], regs->gprs[21]);
printk("R24: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
regs->gprs[22], regs->gprs[23], regs->gprs[24], regs->gprs[25],
regs->gprs[26], regs->gprs[27], regs->gprs[28], regs->gprs[29]);
}
 
/*
* Free current thread data structures etc..
*/
void exit_thread(void)
{
}
 
void flush_thread(void)
{
set_fs(USER_DS);
current->tss.fs = USER_DS;
}
 
asmlinkage int sys_fork(int p1, int p2, int p3, int p4, int p5, struct pt_regs *regs)
{
return do_fork(SIGCHLD|CLONE_WAIT, regs->sp, regs);
}
 
asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, struct pt_regs *regs)
{
unsigned long clone_flags = (unsigned long)p1;
return do_fork(clone_flags, regs->sp, regs);
}
 
void release_thread(struct task_struct *dead_task)
{
}
 
void copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
struct task_struct * p, struct pt_regs * regs)
{
struct pt_regs * childregs;
 
/* Copy registers */
childregs = ((struct pt_regs *) (p->kernel_stack_page + PAGE_SIZE)) - 1;
*childregs = *regs; /* STRUCT COPY */
childregs->gprs[9] = 0x0; /* Result from fork() */
p->tss.ksp = childregs;
 
/* If this is kernel thread, than we can use kernel stack also as
"user" stack, if not, we use user stack from parent which should be a sleep
till we execute execve or exit (that is why sys_fork has CLONE_WAIT
flag allway set ) */
if(regs->sr & SPR_SR_SM) {
childregs->sp = (unsigned long)(childregs+1);
p->tss.usp = (unsigned long)(childregs+1);
}
else {
childregs->sp = usp;
p->tss.usp = usp;
}
}
 
/* Fill in the fpu structure for a core dump. */
 
int dump_fpu (struct pt_regs *regs, struct user_or32fp_struct *fpu)
{
return 0;
}
 
void switch_to(struct task_struct *prev, struct task_struct *new)
{
struct pt_regs *regs;
struct thread_struct *new_tss, *old_tss;
long flags;
 
save_flags(flags);
cli();
 
regs = (struct pt_regs *)new->tss.ksp;
new_tss = &new->tss;
old_tss = &current->tss;
current_set[0] = new; /* FIX ME! */
_switch(old_tss, new_tss);
restore_flags(flags);
}
 
/*
* fill in the user structure for a core dump..
*/
void dump_thread(struct pt_regs * regs, struct user * dump)
{
/* changed the size calculations - should hopefully work better. lbt */
dump->magic = CMAGIC;
dump->start_code = 0;
dump->start_stack = regs->sp & ~(PAGE_SIZE - 1);
dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
dump->u_dsize = ((unsigned long) (current->mm->brk +
(PAGE_SIZE-1))) >> PAGE_SHIFT;
dump->u_dsize -= dump->u_tsize;
dump->u_ssize = 0;
 
 
dump->u_ar0 = (struct pt_regs *)(((int)(&dump->regs)) -((int)(dump)));
dump->regs = *regs;
/* dump floating point stuff */
dump->u_fpvalid = dump_fpu (regs, &dump->or32fp);
}
 
/*
* sys_execve() executes a new program.
*/
asmlinkage int sys_execve(char *name, char **argv, char **envp,
int dummy1, int dummy2, unsigned long sp)
{
int error;
char * filename;
struct pt_regs *regs = (struct pt_regs *) sp;
 
_print("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
error = getname(name, &filename);
_print("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
if (error)
return error;
_print("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
error = do_execve(filename, argv, envp, regs);
_print("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
putname(filename);
#if ICACHE
ic_invalidate();
#endif
_print("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
return error;
}
/ptrace.c
0,0 → 1,356
/*
* linux/arch/m68knommu/kernel/ptrace.c
*
* Copyright (C) 1998 D. Jeff Dionne <jeff@ryeham.ee.ryerson.ca>,
* Kenneth Albanowski <kjahds@kjahds.com>,
* The Silver Hammer Group, Ltd.
*
* Based on:
*
* linux/arch/m68k/kernel/ptrace
*
* Copyright (C) 1994 by Hamish Macdonald
* Taken from linux/kernel/ptrace.c and modified for M680x0.
* linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
*
* 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.
*/
 
#include <stddef.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
 
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/user.h>
 
#include <asm/segment.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/system.h>
 
/*
* does not yet catch signals sent when the child dies.
* in exit.c or in signal.c.
*/
 
/* determines which bits in the SR the user has access to. */
/* 1 = access 0 = no access */
#define SR_MASK 0x001f
 
/* sets the trace bits. */
#define TRACE_BITS 0x8000
 
/* Mapping from PT_xxx to the stack offset at which the register is
saved. Notice that usp has no stack-slot and needs to be treated
specially (see get_reg/put_reg below). */
static int regoff[] = {0,0,0,0,0,0};
 
/* change a pid into a task struct. */
static inline struct task_struct * get_task(int pid)
{
int i;
 
for (i = 1; i < NR_TASKS; i++) {
if (task[i] != NULL && (task[i]->pid == pid))
return task[i];
}
return NULL;
}
 
/*
* Get contents of register REGNO in task TASK.
*/
static inline long get_reg(struct task_struct *task, int regno)
{
unsigned long *addr;
/* SIMON */
#if 0
if (regno == PT_USP)
addr = &task->tss.usp;
else if (regno < sizeof(regoff)/sizeof(regoff[0]))
addr = (unsigned long *)(task->tss.esp0 + regoff[regno]);
else
return 0;
#endif
return *addr;
}
 
/*
* Write contents of register REGNO in task TASK.
*/
static inline int put_reg(struct task_struct *task, int regno,
unsigned long data)
{
/* SIMON */
#if 0
unsigned long *addr;
if (regno == PT_USP)
addr = &task->tss.usp;
else if (regno < sizeof(regoff)/sizeof(regoff[0]))
addr = (unsigned long *) (task->tss.esp0 + regoff[regno]);
else
return -1;
*addr = data;
#endif
return 0;
}
 
inline
static unsigned long get_long(struct task_struct * tsk,
struct vm_area_struct * vma, unsigned long addr)
{
return *(unsigned long*)addr;
}
 
inline
static void put_long(struct task_struct * tsk, struct vm_area_struct * vma, unsigned long addr,
unsigned long data)
{
*(unsigned long*)addr = data;
}
 
 
inline
static int read_long(struct task_struct * tsk, unsigned long addr,
unsigned long * result)
{
*result = *(unsigned long *)addr;
return 0;
}
 
inline
static int write_long(struct task_struct * tsk, unsigned long addr,
unsigned long data)
{
*(unsigned long *)addr = data;
return 0;
}
 
asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
{
/* SIMON */
#if 0
struct task_struct *child;
struct user * dummy;
dummy = NULL;
 
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
if (current->flags & PF_PTRACED)
return -EPERM;
/* set the ptrace bit in the process flags. */
current->flags |= PF_PTRACED;
return 0;
}
if (pid == 1) /* you may not mess with init */
return -EPERM;
if (!(child = get_task(pid)))
return -ESRCH;
if (request == PTRACE_ATTACH) {
if (child == current)
return -EPERM;
if ((!child->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->suid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
(current->gid != child->gid)) && !suser())
return -EPERM;
/* the same process cannot be attached many times */
if (child->flags & PF_PTRACED)
return -EPERM;
child->flags |= PF_PTRACED;
if (child->p_pptr != current) {
REMOVE_LINKS(child);
child->p_pptr = current;
SET_LINKS(child);
}
send_sig(SIGSTOP, child, 1);
return 0;
}
if (!(child->flags & PF_PTRACED))
return -ESRCH;
if (child->state != TASK_STOPPED) {
if (request != PTRACE_KILL)
return -ESRCH;
}
if (child->p_pptr != current)
return -ESRCH;
 
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: {
unsigned long tmp;
int res;
 
res = read_long(child, addr, &tmp);
if (res < 0)
return res;
res = verify_area(VERIFY_WRITE, (void *) data, sizeof(long));
if (!res)
put_user(tmp, (unsigned long *) data);
return res;
}
 
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
unsigned long tmp;
int res;
if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
return -EIO;
res = verify_area(VERIFY_WRITE, (void *) data,
sizeof(long));
if (res)
return res;
tmp = 0; /* Default return condition */
addr = addr >> 2; /* temporary hack. */
if (addr < 19) {
tmp = get_reg(child, addr);
if (addr == PT_SR)
tmp >>= 16;
}
else if (addr >= 21 && addr < 49)
tmp = child->tss.fp[addr - 21];
else if (addr == 49)
tmp = child->mm->start_code;
else if (addr == 50)
tmp = child->mm->start_data;
else
return -EIO;
put_user(tmp,(unsigned long *) data);
return 0;
}
 
/* when I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
return write_long(child,addr,data);
 
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
return -EIO;
 
addr = addr >> 2; /* temporary hack. */
if (addr == PT_ORIG_D0)
return -EIO;
if (addr == PT_SR) {
data &= SR_MASK;
data <<= 16;
data |= get_reg(child, PT_SR) & ~(SR_MASK << 16);
}
if (addr < 19) {
if (put_reg(child, addr, data))
return -EIO;
return 0;
}
if (addr >= 21 && addr < 48)
{
child->tss.fp[addr - 21] = data;
return 0;
}
return -EIO;
 
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
case PTRACE_CONT: { /* restart after signal. */
long tmp;
 
if ((unsigned long) data >= NSIG)
return -EIO;
if (request == PTRACE_SYSCALL)
child->flags |= PF_TRACESYS;
else
child->flags &= ~PF_TRACESYS;
child->exit_code = data;
wake_up_process(child);
/* make sure the single step bit is not set. */
tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
put_reg(child, PT_SR, tmp);
return 0;
}
 
/*
* make the child exit. Best I can do is send it a sigkill.
* perhaps it should be put in the status that it wants to
* exit.
*/
case PTRACE_KILL: {
long tmp;
 
if (child->state == TASK_ZOMBIE) /* already dead */
return 0;
wake_up_process(child);
child->exit_code = SIGKILL;
/* make sure the single step bit is not set. */
tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
put_reg(child, PT_SR, tmp);
return 0;
}
 
case PTRACE_SINGLESTEP: { /* set the trap flag. */
long tmp;
 
if ((unsigned long) data >= NSIG)
return -EIO;
child->flags &= ~PF_TRACESYS;
tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16);
put_reg(child, PT_SR, tmp);
 
wake_up_process(child);
child->exit_code = data;
/* give it a chance to run. */
return 0;
}
 
case PTRACE_DETACH: { /* detach a process that was attached. */
long tmp;
 
if ((unsigned long) data >= NSIG)
return -EIO;
child->flags &= ~(PF_PTRACED|PF_TRACESYS);
wake_up_process(child);
child->exit_code = data;
REMOVE_LINKS(child);
child->p_pptr = child->p_opptr;
SET_LINKS(child);
/* make sure the single step bit is not set. */
tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
put_reg(child, PT_SR, tmp);
return 0;
}
 
default:
return -EIO;
}
#endif
return 0;
}
 
asmlinkage void syscall_trace(void)
{
if ((current->flags & (PF_PTRACED|PF_TRACESYS))
!= (PF_PTRACED|PF_TRACESYS))
return;
current->exit_code = SIGTRAP;
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
schedule();
/*
* this isn't the same as continuing with a signal, but it will do
* for normal use. strace only continues with a signal if the
* stopping signal is not SIGTRAP. -brl
*/
if (current->exit_code)
current->signal |= (1 << (current->exit_code - 1));
current->exit_code = 0;
return;
}
/entry.S
0,0 → 1,368
 
#include <linux/sys.h>
#include <linux/config.h>
#include <linux/linkage.h>
#include <asm/segment.h>
 
LENOSYS = 38
 
/*
* these are offsets into the task-struct
*/
LTASK_STATE = 0
LTASK_COUNTER = 4
LTASK_PRIORITY = 8
LTASK_SIGNAL = 12
LTASK_BLOCKED = 16
LTASK_FLAGS = 20
 
/* the following macro is used when enabling interrupts */
#define ALLOWINT 0xf8ff
#define MAX_NOINT_IPL 0
 
LD0 = 0x1C
LORIG_D0 = 0x20
LSR = 0x28
LFORMATVEC = 0x2E
 
/*
* This defines the normal kernel pt-regs layout.
*
* regs are a2-a6 and d6-d7 preserved by C code
* the kernel doesn't mess with usp unless it needs to
*/
#define SAVE_ALL \
clrl %sp@-; /* stk_adj */ \
movel %d0,%sp@-; /* orig d0 */ \
movel %d0,%sp@-; /* d0 */ \
moveml %d1-%d5/%a0-%a1,%sp@-
 
/* moveml %sp@+,%a0-%a1/%d1-%d5; */
 
#define RESTORE_ALL \
moveml %sp@+,%d1-%d5/%a0-%a1; \
movel %sp@+,%d0; \
addql #4,%sp; /* orig d0 */ \
addl %sp@+,%sp; /* stk adj */ \
rte
 
#define SWITCH_STACK_SIZE (7*4+4) /* includes return address */
 
#define SAVE_SWITCH_STACK \
moveml %a2-%a6/%d6-%d7,%sp@-
 
#define RESTORE_SWITCH_STACK \
moveml %sp@+,%a2-%a6/%d6-%d7
 
.globl SYMBOL_NAME(system_call), SYMBOL_NAME(buserr), SYMBOL_NAME(trap)
.globl SYMBOL_NAME(resume), SYMBOL_NAME(ret_from_exception)
.globl SYMBOL_NAME(ret_from_signal)
.globl SYMBOL_NAME(trap3)
.globl SYMBOL_NAME(trap4)
.globl SYMBOL_NAME(trap5)
.globl SYMBOL_NAME(inthandler1)
.globl SYMBOL_NAME(inthandler1)
.globl SYMBOL_NAME(inthandler1)
.globl SYMBOL_NAME(inthandler2)
.globl SYMBOL_NAME(inthandler3)
.globl SYMBOL_NAME(inthandler4)
.globl SYMBOL_NAME(inthandler5)
.globl SYMBOL_NAME(inthandler6)
.globl SYMBOL_NAME(inthandler7)
.globl SYMBOL_NAME(inthandler8)
.globl SYMBOL_NAME(inthandler)
.globl SYMBOL_NAME(inthandler_wrap)
.globl SYMBOL_NAME(timerhandler)
.globl SYMBOL_NAME(serialhandler)
.globl SYMBOL_NAME(sys_call_table)
.globl SYMBOL_NAME(sys_fork), SYMBOL_NAME(sys_clone)
.globl SYMBOL_NAME(ret_from_interrupt), SYMBOL_NAME(bad_interrupt)
 
 
.text
ENTRY(buserr)
 
ENTRY(trap)
 
ENTRY(trap3)
 
ENTRY(trap4)
 
ENTRY(trap5)
 
ENTRY(trap6)
 
ENTRY(trap7)
 
ENTRY(trap8)
 
ENTRY(trap9)
 
ENTRY(trap10)
 
ENTRY(trap11)
 
ENTRY(trap12)
 
ENTRY(trap13)
 
ENTRY(trap14)
 
ENTRY(trap15)
 
ENTRY(trap33)
 
ENTRY(trap34)
 
ENTRY(trap35)
 
ENTRY(trap36)
 
ENTRY(trap37)
 
ENTRY(trap38)
 
ENTRY(trap39)
 
ENTRY(trap40)
 
ENTRY(trap41)
 
ENTRY(trap42)
 
ENTRY(trap43)
 
ENTRY(trap44)
 
ENTRY(trap45)
 
 
SYMBOL_NAME_LABEL(timerhandler)
 
 
SYMBOL_NAME_LABEL(serialhandler)
 
 
SYMBOL_NAME_LABEL(inthandler1)
 
 
SYMBOL_NAME_LABEL(inthandler2)
 
 
SYMBOL_NAME_LABEL(inthandler3)
 
 
SYMBOL_NAME_LABEL(inthandler4)
 
 
SYMBOL_NAME_LABEL(inthandler5)
 
 
SYMBOL_NAME_LABEL(inthandler6)
 
 
SYMBOL_NAME_LABEL(inthandler7)
 
 
SYMBOL_NAME_LABEL(inthandler8)
 
 
SYMBOL_NAME_LABEL(inthandler_wrap)
 
 
SYMBOL_NAME_LABEL(inthandler)
 
 
SYMBOL_NAME_LABEL(ret_from_interrupt)
 
 
SYMBOL_NAME_LABEL(bad_interrupt)
 
 
SYMBOL_NAME_LABEL(resume)
 
 
.text
ALIGN
SYMBOL_NAME_LABEL(sys_call_table)
.long SYMBOL_NAME(sys_setup) /* 0 */
.long SYMBOL_NAME(sys_exit)
.long SYMBOL_NAME(sys_fork)
.long SYMBOL_NAME(sys_read)
.long SYMBOL_NAME(sys_write)
.long SYMBOL_NAME(sys_open) /* 5 */
.long SYMBOL_NAME(sys_close)
.long SYMBOL_NAME(sys_waitpid)
.long SYMBOL_NAME(sys_creat)
.long SYMBOL_NAME(sys_link)
.long SYMBOL_NAME(sys_unlink) /* 10 */
.long SYMBOL_NAME(sys_execve)
.long SYMBOL_NAME(sys_chdir)
.long SYMBOL_NAME(sys_time)
.long SYMBOL_NAME(sys_mknod)
.long SYMBOL_NAME(sys_chmod) /* 15 */
.long SYMBOL_NAME(sys_chown)
.long SYMBOL_NAME(sys_break)
.long SYMBOL_NAME(sys_stat)
.long SYMBOL_NAME(sys_lseek)
.long SYMBOL_NAME(sys_getpid) /* 20 */
.long SYMBOL_NAME(sys_mount)
.long SYMBOL_NAME(sys_umount)
.long SYMBOL_NAME(sys_setuid)
.long SYMBOL_NAME(sys_getuid)
.long SYMBOL_NAME(sys_stime) /* 25 */
.long SYMBOL_NAME(sys_ptrace)
.long SYMBOL_NAME(sys_alarm)
.long SYMBOL_NAME(sys_fstat)
.long SYMBOL_NAME(sys_pause)
.long SYMBOL_NAME(sys_utime) /* 30 */
.long SYMBOL_NAME(sys_stty)
.long SYMBOL_NAME(sys_gtty)
.long SYMBOL_NAME(sys_access)
.long SYMBOL_NAME(sys_nice)
.long SYMBOL_NAME(sys_ftime) /* 35 */
.long SYMBOL_NAME(sys_sync)
.long SYMBOL_NAME(sys_kill)
.long SYMBOL_NAME(sys_rename)
.long SYMBOL_NAME(sys_mkdir)
.long SYMBOL_NAME(sys_rmdir) /* 40 */
.long SYMBOL_NAME(sys_dup)
.long SYMBOL_NAME(sys_pipe)
.long SYMBOL_NAME(sys_times)
.long SYMBOL_NAME(sys_prof)
.long SYMBOL_NAME(sys_brk) /* 45 */
.long SYMBOL_NAME(sys_setgid)
.long SYMBOL_NAME(sys_getgid)
.long SYMBOL_NAME(sys_signal)
.long SYMBOL_NAME(sys_geteuid)
.long SYMBOL_NAME(sys_getegid) /* 50 */
.long SYMBOL_NAME(sys_acct)
.long SYMBOL_NAME(sys_phys)
.long SYMBOL_NAME(sys_lock)
.long SYMBOL_NAME(sys_ioctl)
.long SYMBOL_NAME(sys_fcntl) /* 55 */
.long SYMBOL_NAME(sys_mpx)
.long SYMBOL_NAME(sys_setpgid)
.long SYMBOL_NAME(sys_ulimit)
.long SYMBOL_NAME(sys_olduname)
.long SYMBOL_NAME(sys_umask) /* 60 */
.long SYMBOL_NAME(sys_chroot)
.long SYMBOL_NAME(sys_ustat)
.long SYMBOL_NAME(sys_dup2)
.long SYMBOL_NAME(sys_getppid)
.long SYMBOL_NAME(sys_getpgrp) /* 65 */
.long SYMBOL_NAME(sys_setsid)
.long SYMBOL_NAME(sys_sigaction)
.long SYMBOL_NAME(sys_sgetmask)
.long SYMBOL_NAME(sys_ssetmask)
.long SYMBOL_NAME(sys_setreuid) /* 70 */
.long SYMBOL_NAME(sys_setregid)
.long SYMBOL_NAME(sys_sigsuspend)
.long SYMBOL_NAME(sys_sigpending)
.long SYMBOL_NAME(sys_sethostname)
.long SYMBOL_NAME(sys_setrlimit) /* 75 */
.long SYMBOL_NAME(sys_getrlimit)
.long SYMBOL_NAME(sys_getrusage)
.long SYMBOL_NAME(sys_gettimeofday)
.long SYMBOL_NAME(sys_settimeofday)
.long SYMBOL_NAME(sys_getgroups) /* 80 */
.long SYMBOL_NAME(sys_setgroups)
.long SYMBOL_NAME(old_select)
.long SYMBOL_NAME(sys_symlink)
.long SYMBOL_NAME(sys_lstat)
.long SYMBOL_NAME(sys_readlink) /* 85 */
.long SYMBOL_NAME(sys_uselib)
.long SYMBOL_NAME(sys_swapon)
.long SYMBOL_NAME(sys_reboot)
.long SYMBOL_NAME(old_readdir)
.long SYMBOL_NAME(old_mmap) /* 90 */
.long SYMBOL_NAME(sys_munmap)
.long SYMBOL_NAME(sys_truncate)
.long SYMBOL_NAME(sys_ftruncate)
.long SYMBOL_NAME(sys_fchmod)
.long SYMBOL_NAME(sys_fchown) /* 95 */
.long SYMBOL_NAME(sys_getpriority)
.long SYMBOL_NAME(sys_setpriority)
.long SYMBOL_NAME(sys_profil)
.long SYMBOL_NAME(sys_statfs)
.long SYMBOL_NAME(sys_fstatfs) /* 100 */
.long SYMBOL_NAME(sys_ioperm)
.long SYMBOL_NAME(sys_socketcall)
.long SYMBOL_NAME(sys_syslog)
.long SYMBOL_NAME(sys_setitimer)
.long SYMBOL_NAME(sys_getitimer) /* 105 */
.long SYMBOL_NAME(sys_newstat)
.long SYMBOL_NAME(sys_newlstat)
.long SYMBOL_NAME(sys_newfstat)
.long SYMBOL_NAME(sys_uname)
.long SYMBOL_NAME(sys_ni_syscall) /* iopl for i386 */ /* 110 */
.long SYMBOL_NAME(sys_vhangup)
.long SYMBOL_NAME(sys_idle)
.long SYMBOL_NAME(sys_ni_syscall) /* vm86 for i386 */
.long SYMBOL_NAME(sys_wait4)
.long SYMBOL_NAME(sys_swapoff) /* 115 */
.long SYMBOL_NAME(sys_sysinfo)
.long SYMBOL_NAME(sys_ipc)
.long SYMBOL_NAME(sys_fsync)
.long SYMBOL_NAME(sys_sigreturn)
.long SYMBOL_NAME(sys_clone) /* 120 */
.long SYMBOL_NAME(sys_setdomainname)
.long SYMBOL_NAME(sys_newuname)
.long SYMBOL_NAME(sys_cacheflush) /* modify_ldt for i386 */
.long SYMBOL_NAME(sys_adjtimex)
.long SYMBOL_NAME(sys_mprotect) /* 125 */
.long SYMBOL_NAME(sys_sigprocmask)
.long SYMBOL_NAME(sys_create_module)
.long SYMBOL_NAME(sys_init_module)
.long SYMBOL_NAME(sys_delete_module)
.long SYMBOL_NAME(sys_get_kernel_syms) /* 130 */
.long SYMBOL_NAME(sys_quotactl)
.long SYMBOL_NAME(sys_getpgid)
.long SYMBOL_NAME(sys_fchdir)
.long SYMBOL_NAME(sys_bdflush)
.long SYMBOL_NAME(sys_sysfs) /* 135 */
.long SYMBOL_NAME(sys_personality)
.long SYMBOL_NAME(sys_ni_syscall) /* for afs_syscall */
.long SYMBOL_NAME(sys_setfsuid)
.long SYMBOL_NAME(sys_setfsgid)
.long SYMBOL_NAME(sys_llseek) /* 140 */
.long SYMBOL_NAME(sys_getdents)
.long SYMBOL_NAME(sys_select)
.long SYMBOL_NAME(sys_flock)
.long SYMBOL_NAME(sys_msync)
.long SYMBOL_NAME(sys_readv) /* 145 */
.long SYMBOL_NAME(sys_writev)
.long SYMBOL_NAME(sys_getsid)
.long SYMBOL_NAME(sys_fdatasync)
.long SYMBOL_NAME(sys_sysctl)
.long SYMBOL_NAME(sys_mlock) /* 150 */
.long SYMBOL_NAME(sys_munlock)
.long SYMBOL_NAME(sys_mlockall)
.long SYMBOL_NAME(sys_munlockall)
.long SYMBOL_NAME(sys_sched_setparam)
.long SYMBOL_NAME(sys_sched_getparam) /* 155 */
.long SYMBOL_NAME(sys_sched_setscheduler)
.long SYMBOL_NAME(sys_sched_getscheduler)
.long SYMBOL_NAME(sys_sched_yield)
.long SYMBOL_NAME(sys_sched_get_priority_max)
.long SYMBOL_NAME(sys_sched_get_priority_min) /* 160 */
.long SYMBOL_NAME(sys_sched_rr_get_interval)
.long SYMBOL_NAME(sys_nanosleep)
.long SYMBOL_NAME(sys_mremap)
.space (NR_syscalls-163)*4
 
ENTRY(trap46)
 
ENTRY(trap47)
 
ENTRY(reschedule)
 
ENTRY(system_call)
 
SYMBOL_NAME_LABEL(ret_from_signal)
 
SYMBOL_NAME_LABEL(ret_from_exception)
 
Lsignal_return:
 
 
/head.S
0,0 → 1,1080
#include <asm/spr_defs.h>
#include <asm/ptrace.h>
#include <asm/board.h>
#include <asm/mc.h>
#include <linux/errno.h>
 
#define RAM 0
#define TEMP_R_LOC 0x00000010
 
.global __text_start
.global __main
.global ___bss_start
.global __bss_end
.global __ram_start
.global __ram_end
.global __rom_start
.global __rom_end
.global ___data_start
.global __data_end
.global ___data_rom_start
 
.global splash_bits
.global __start
.global __stext
 
.global __switch
.global _putc
 
#define SAVE_REGS(mark) \
l.addi r1,r1,-(INT_FRAME_SIZE); \
l.mfspr r3,r0,SPR_EPCR_BASE; \
l.sw PC(r1),r3; \
l.mfspr r3,r0,SPR_ESR_BASE; \
l.sw SR(r1),r3; \
l.lwz r3,(TEMP_R_LOC + 4)(r0); /* Read r1 (sp) from tmp location */ \
l.sw SP(r1),r3; \
l.sw GPR2(r1),r2; \
l.sw GPR4(r1),r4; \
l.sw GPR5(r1),r5; \
l.sw GPR6(r1),r6; \
l.sw GPR7(r1),r7; \
l.sw GPR8(r1),r8; \
l.sw GPR9(r1),r9; \
l.sw GPR10(r1),r10; \
l.sw GPR11(r1),r11; \
l.sw GPR12(r1),r12; \
l.sw GPR13(r1),r13; \
l.sw GPR14(r1),r14; \
l.sw GPR15(r1),r15; \
l.sw GPR16(r1),r16; \
l.sw GPR17(r1),r17; \
l.sw GPR18(r1),r18; \
l.sw GPR19(r1),r19; \
l.sw GPR20(r1),r20; \
l.sw GPR21(r1),r21; \
l.sw GPR22(r1),r22; \
l.sw GPR23(r1),r23; \
l.sw GPR24(r1),r24; \
l.sw GPR25(r1),r25; \
l.sw GPR26(r1),r26; \
l.sw GPR27(r1),r27; \
l.sw GPR28(r1),r28; \
l.sw GPR29(r1),r29; \
l.sw GPR30(r1),r30; \
l.sw GPR31(r1),r31; \
l.lwz r3,(TEMP_R_LOC + 0)(r0); /* Read r3 from tmp location */ \
l.sw GPR3(r1),r3; \
l.sw ORIG_GPR3(r1),r3; \
l.sw RESULT(r1),r0
 
#define SAVE_INT_REGS(mark) \
l.sw (TEMP_R_LOC + 4)(r0),r1; /* Temporary store r1 to add 4!!! */ \
l.mfspr r3,r0,SPR_SR; \
l.addi r1,r0,-1; \
l.xori r1,r1,(SPR_SR_IEE | SPR_SR_TEE); \
l.and r3,r3,r1; \
l.mtspr r0,r3,SPR_SR; \
l.lwz r1,(TEMP_R_LOC + 4)(r0); \
l.mfspr r3,r0,SPR_ESR_BASE; /* Interrupt from user/system mode */ \
l.andi r3,r3,SPR_SR_SM; \
l.sfeqi r3,SPR_SR_SM; \
l.bf 10f; /* SIMON */ /* Branch if SUPV */ \
l.nop; \
l.movhi r3,hi(_current_set); \
l.ori r3,r3,lo(_current_set); \
l.lwz r3,0(r3); \
l.sw TSS+TSS_USP(r3),r1; \
l.mfspr r1,r0,SPR_EPCR_BASE; \
l.sw TSS+TSS_PC(r3),r1; \
l.lwz r1,TSS+TSS_KSP(r3); \
l.addi r1,r1,-(INT_FRAME_SIZE); \
l.sw TSS+TSS_REGS(r3),r1; \
l.lwz r1,TSS+TSS_KSP(r3); \
10: SAVE_REGS(mark)
 
#define RETURN_FROM_INT(mark) \
90: l.addi r4,r0,-1; /* Disable interrupts */ \
l.xori r4,r4,(SPR_SR_IEE | SPR_SR_TEE); \
l.mfspr r3,r0,SPR_SR; \
l.and r3,r3,r4; \
l.mtspr r0,r3,SPR_SR; \
l.movhi r2,hi(_intr_count); \
l.ori r2,r2,lo(_intr_count); \
l.lwz r3,0(r2); \
l.sfeqi r3,0; \
l.bnf 00f; \
l.nop; \
l.movhi r4,hi(_bh_mask); \
l.ori r4,r4,lo(_bh_mask); \
l.lwz r4,0(r4); \
l.movhi r5,hi(_bh_active); \
l.ori r5,r5,lo(_bh_active); \
l.lwz r5,0(r5); \
l.and r4,r4,r5; \
l.sfeqi r4,0; \
l.bf 00f; \
l.nop; \
l.addi r3,r3,1; \
l.sw 0(r2),r3; \
l.jal _do_bottom_half; \
l.nop; \
l.movhi r2,hi(_intr_count); \
l.ori r2,r2,lo(_intr_count); \
l.lwz r3,0(r2); \
l.addi r3,r3,-1; \
l.sw 0(r2),r3; \
00: l.lwz r2,SR(r1); \
l.andi r3,r2,SPR_SR_SM; \
l.sfeqi r3,0; \
l.bnf 10f; /* SIMON */ /* Branch if SUPV */ \
l.nop; \
l.andi r3,r2,SPR_SR_ICE; \
l.sfeqi r3,0; \
l.bf 05f; /* Branch if IC disabled */ \
l.nop; \
l.jal _ic_invalidate; \
l.nop; \
05: l.movhi r3,hi(_current_set); /* need to save kernel stack pointer */ \
l.ori r3,r3,lo(_current_set); \
l.lwz r3,0(r3); \
l.addi r4,r1,INT_FRAME_SIZE; \
l.sw TSS+TSS_KSP(r3),r4; \
l.lwz r4,STATE(r3); /* If state != 0, can't run */ \
l.sfeqi r4,0; \
l.bf 06f; \
l.nop; \
l.jal _schedule; \
l.nop; \
l.j 90b; \
l.nop; \
06: l.lwz r4,COUNTER(r3); \
l.sfeqi r4,0; \
l.bnf 07f; \
l.nop; \
l.jal _schedule; \
l.nop; \
l.j 90b; \
l.nop; \
07: l.addi r5,r0,-1; \
l.lwz r4,BLOCKED(r3); /* Check for pending unblocked signals */ \
l.xor r4,r4,r5; \
l.lwz r5,SIGNAL(r3); \
l.and r5,r5,r4; \
l.sfeqi r5,0; \
l.bf 10f; \
l.nop; \
l.addi r3,r4,0; \
l.addi r4,r1,0; \
l.jal _do_signal; \
l.nop; \
10: l.lwz r3,PC(r1); \
l.movhi r4,0x2; \
l.ori r4,r4,0x6034;\
l.sfeq r3,r4;\
l.bnf 20f; \
l.nop; \
l.lwz r10,GPR10(r1); \
l.sfeqi r10,0; \
l.bnf 20f; \
l.nop; \
l.lwz r4,SR(r1); \
l.andi r4,r4,SPR_SR_F;\
l.sfeqi r4,0x00; \
l.bf 20f; \
l.nop; \
l.j _fail; \
l.nop; \
20: l.mtspr r0,r3,SPR_EPCR_BASE; \
l.lwz r3,SR(r1); \
l.mtspr r0,r3,SPR_ESR_BASE; \
l.lwz r2,GPR2(r1); \
l.lwz r3,GPR3(r1); \
l.lwz r4,GPR4(r1); \
l.lwz r5,GPR5(r1); \
l.lwz r6,GPR6(r1); \
l.lwz r7,GPR7(r1); \
l.lwz r8,GPR8(r1); \
l.lwz r9,GPR9(r1); \
l.lwz r10,GPR10(r1); \
l.lwz r11,GPR11(r1); \
l.lwz r12,GPR12(r1); \
l.lwz r13,GPR13(r1); \
l.lwz r14,GPR14(r1); \
l.lwz r15,GPR15(r1); \
l.lwz r16,GPR16(r1); \
l.lwz r17,GPR17(r1); \
l.lwz r18,GPR18(r1); \
l.lwz r19,GPR19(r1); \
l.lwz r20,GPR20(r1); \
l.lwz r21,GPR21(r1); \
l.lwz r22,GPR22(r1); \
l.lwz r23,GPR23(r1); \
l.lwz r24,GPR24(r1); \
l.lwz r25,GPR25(r1); \
l.lwz r26,GPR26(r1); \
l.lwz r27,GPR27(r1); \
l.lwz r28,GPR28(r1); \
l.lwz r29,GPR29(r1); \
l.lwz r30,GPR30(r1); \
l.lwz r31,GPR31(r1); \
l.addi r1,r1,0; \
l.lwz r1,SP(r1); \
l.rfe; \
l.nop
 
.section .bss
sys_stack:
.space 4*4096
sys_stack_top:
#if CONFIG_ROMKERNEL
.section .romvec, "ax",
.org 0x100
 
l.movhi r3,hi(MC_BASE_ADD)
l.ori r3,r3,MC_BA_MASK
l.addi r5,r0,0x00
l.sw 0(r3),r5
 
l.movhi r3,hi(__start)
l.ori r3,r3,lo(__start)
l.jr r3
l.nop
 
.org 0x200
 
l.nop
l.rfe
l.nop
 
.org 0x300
 
l.sw (TEMP_R_LOC + 0)(r0),r3; /* Temporary store r3 to add 0!!! */ \
l.movhi r3,hi(_dpfault)
l.ori r3,r3,lo(_dpfault)
l.jr r3
l.nop
 
.org 0x400
 
l.sw (TEMP_R_LOC + 0)(r0),r3; /* Temporary store r3 to add 0!!! */ \
l.movhi r3,hi(_ipfault)
l.ori r3,r3,lo(_ipfault)
l.jr r3
l.nop
 
.org 0x500
 
l.sw (TEMP_R_LOC + 0)(r0),r3; /* Temporary store r3 to add 0!!! */ \
l.movhi r3,hi(_tick)
l.ori r3,r3,lo(_tick)
l.jr r3
l.nop
 
.org 0x600
 
l.sw (TEMP_R_LOC + 0)(r0),r3; /* Temporary store r3 to add 0!!! */ \
l.movhi r3,hi(_align)
l.ori r3,r3,lo(_align)
l.jr r3
l.nop
 
.org 0x800
 
l.sw (TEMP_R_LOC + 0)(r0),r3; /* Temporary store r3 to add 0!!! */ \
l.movhi r3,hi(_ext_int)
l.ori r3,r3,lo(_ext_int)
l.jr r3
l.nop
 
.org 0x900
 
l.sw (TEMP_R_LOC + 0)(r0),r3; /* Temporary store r3 to add 0!!! */ \
l.movhi r3,hi(_dtlbmiss)
l.ori r3,r3,lo(_dtlbmiss)
l.jr r3
l.nop
 
.org 0xa00
 
l.sw (TEMP_R_LOC + 0)(r0),r3; /* Temporary store r3 to add 0!!! */ \
l.movhi r3,hi(_itlbmiss)
l.ori r3,r3,lo(_itlbmiss)
l.jr r3
l.nop
 
.org 0xb00
 
l.sw (TEMP_R_LOC + 0)(r0),r3; /* Temporary store r3 to add 0!!! */ \
l.movhi r3,hi(_sys_call)
l.ori r3,r3,lo(_sys_call)
l.jr r3
l.nop
 
.org 0xc00
 
l.sw (TEMP_R_LOC + 0)(r0),r3; /* Temporary store r3 to add 0!!! */ \
l.movhi r3,hi(_sys_call)
l.ori r3,r3,lo(_sys_call)
l.jr r3
l.nop
#endif
.section .ramvec, "ax"
.org 0x100
 
l.movhi r3,hi(__start)
l.ori r3,r3,lo(__start)
l.jr r3
l.nop
 
.org 0x200
 
l.sw (TEMP_R_LOC + 0)(r0),r3; /* Temporary store r3 to add 0!!! */ \
l.movhi r3,hi(_trap_200)
l.ori r3,r3,lo(_trap_200)
l.jr r3
l.nop
 
.org 0x300
 
l.sw (TEMP_R_LOC + 0)(r0),r3; /* Temporary store r3 to add 0!!! */ \
l.movhi r3,hi(_trap_300)
l.ori r3,r3,lo(_trap_300)
l.jr r3
l.nop
 
.org 0x400
 
l.sw (TEMP_R_LOC + 0)(r0),r3; /* Temporary store r3 to add 0!!! */ \
l.movhi r3,hi(_trap_400)
l.ori r3,r3,lo(_trap_400)
l.jr r3
l.nop
 
.org 0x500
 
l.sw (TEMP_R_LOC + 0)(r0),r3; /* Temporary store r3 to add 0!!! */ \
l.movhi r3,hi(_tick)
l.ori r3,r3,lo(_tick)
l.jr r3
l.nop
 
.org 0x600
 
l.sw (TEMP_R_LOC + 0)(r0),r3; /* Temporary store r3 to add 0!!! */ \
l.movhi r3,hi(_align)
l.ori r3,r3,lo(_align)
l.jr r3
l.nop
 
.org 0x700
 
l.sw (TEMP_R_LOC + 0)(r0),r3; /* Temporary store r3 to add 0!!! */ \
l.movhi r3,hi(_trap_700)
l.ori r3,r3,lo(_trap_700)
l.jr r3
l.nop
 
.org 0x800
 
l.sw (TEMP_R_LOC + 0)(r0),r3; /* Temporary store r3 to add 0!!! */ \
l.movhi r3,hi(_ext_int)
l.ori r3,r3,lo(_ext_int)
l.jr r3
l.nop
 
.org 0x900
 
l.sw (TEMP_R_LOC + 0)(r0),r3; /* Temporary store r3 to add 0!!! */ \
l.movhi r3,hi(_trap_900)
l.ori r3,r3,lo(_trap_900)
l.jr r3
l.nop
 
.org 0xa00
 
l.sw (TEMP_R_LOC + 0)(r0),r3; /* Temporary store r3 to add 0!!! */ \
l.movhi r3,hi(_trap_a00)
l.ori r3,r3,lo(_trap_a00)
l.jr r3
l.nop
 
.org 0xb00
 
l.sw (TEMP_R_LOC + 0)(r0),r3; /* Temporary store r3 to add 0!!! */ \
l.movhi r3,hi(_trap_b00)
l.ori r3,r3,lo(_trap_b00)
l.jr r3
l.nop
 
.org 0xc00
 
l.sw (TEMP_R_LOC + 0)(r0),r3; /* Temporary store r3 to add 0!!! */ \
l.movhi r3,hi(_sys_call)
l.ori r3,r3,lo(_sys_call)
l.jr r3
l.nop
 
 
.text
__start:
__stext:
l.addi r3,r0,SPR_SR_SM
l.mtspr r0,r3,SPR_SR
#if 1
 
/* Init uart */
l.jal _ua_init
l.nop
 
/* Jump to flash original location */
l.movhi r3,hi(__flsh_start)
l.ori r3,r3,lo(__flsh_start)
l.jr r3
l.nop
 
__flsh_start:
 
#if CONFIG_ROMKERNEL
#if MC_INIT
l.movhi r3,hi(MC_BASE_ADD)
l.ori r3,r3,lo(MC_BASE_ADD)
l.addi r4,r3,MC_CSC(0)
l.movhi r5,hi(FLASH_BASE_ADD)
l.srai r5,r5,6
l.ori r5,r5,0x0025
l.sw 0(r4),r5
l.addi r4,r3,MC_TMS(0)
l.movhi r5,hi(FLASH_TMS_VAL)
l.ori r5,r5,lo(FLASH_TMS_VAL)
l.sw 0(r4),r5
l.addi r4,r3,MC_BA_MASK
l.addi r5,r0,MC_MASK_VAL
l.sw 0(r4),r5
l.addi r4,r3,MC_CSR
l.movhi r5,hi(MC_CSR_VAL)
l.ori r5,r5,lo(MC_CSR_VAL)
l.sw 0(r4),r5
l.addi r4,r3,MC_TMS(1)
l.movhi r5,hi(SDRAM_TMS_VAL)
l.ori r5,r5,lo(SDRAM_TMS_VAL)
l.sw 0(r4),r5
l.addi r4,r3,MC_CSC(1)
l.movhi r5,hi(SDRAM_BASE_ADD)
l.srai r5,r5,6
l.ori r5,r5,0x0411
l.sw 0(r4),r5
 
#ifdef FBMEM_BASE_ADD
l.addi r4,r3,MC_CSC(2)
l.movhi r5,hi(FBMEM_BASE_ADD)
l.srai r5,r5,6
l.ori r5,r5,0x0005
l.sw 0(r4),r5
 
l.addi r4,r3,MC_TMS(2)
l.movhi r5,0xffff
l.ori r5,r5,0xffff
l.sw 0(r4),r5
#endif
#endif
#endif
#endif
 
#if ICACHE
l.jal _ic_enable
l.nop
#endif
 
#if DCACHE
l.jal _dc_enable
l.nop
#endif
 
l.movhi r1, hi(sys_stack_top) /* stack setup */
l.ori r1,r1,lo(sys_stack_top)
 
#if CONFIG_ROMKERNEL
/* Copy data segment from ROM to RAM */
l.movhi r3, hi(___data_rom_start)
l.ori r3,r3,lo(___data_rom_start)
 
l.movhi r4, hi(___data_start)
l.ori r4,r4,lo(___data_start)
 
l.movhi r5, hi(__data_end)
l.ori r5,r5,lo(__data_end)
 
/* Copy %r3 to %r4 until %r4 == %r5 */
1:
l.sfeq r3,r4
l.bf 3f
l.nop
2:
l.sfgeu r4,r5
l.bf 1f
l.nop
l.lwz r8,0(r3)
l.sw 0(r4),r8
l.addi r3,r3,4
l.j 2b
l.addi r4,r4,4
 
/* Copy ramvec segment from ROM to RAM */
1:
l.movhi r4, hi(__ramvec_start)
l.ori r4,r4,lo(__ramvec_start)
 
l.movhi r5, hi(__ramvec_end)
l.ori r5,r5,lo(__ramvec_end)
 
/* Copy %r3 to %r4 until %r4 == %r5 */
2:
l.sfgeu r4,r5
l.bf 1f
l.nop
l.lwz r8,0(r3)
l.sw 0(r4),r8
l.addi r3,r3,4
l.j 2b
l.addi r4,r4,4
#if 0
/* Copy initrd segment from ROM to RAM */
1:
l.movhi r4, hi(__initrd_start)
l.ori r4,r4,lo(__initrd_start)
 
l.movhi r5, hi(__initrd_end)
l.ori r5,r5,lo(__initrd_end)
 
/* Copy %r3 to %r4 until %r4 == %r5 */
2:
l.sfgeu r4,r5
l.bf 1f
l.nop
l.lwz r8,0(r3)
l.sw 0(r4),r8
l.addi r3,r3,4
l.j 2b
l.addi r4,r4,4
#endif
#endif
1:
3:
l.movhi r3, hi(___bss_start)
l.ori r3,r3,lo(___bss_start)
 
l.movhi r4, hi(end)
l.ori r4,r4,lo(end)
 
/* Copy 0 to %r3 until %r3 == %r4 */
1:
l.sfgeu r3,r4
l.bf 1f
l.nop
l.sw 0(r3),r0
l.j 1b
l.addi r3,r3,4
1:
 
#if IMMU
l.jal _immu_enable
l.nop
#endif
 
#if DMMU
l.jal _dmmu_enable
l.nop
#endif
 
l.j _start_kernel
l.nop
 
_exit:
l.j _exit
l.nop
 
_dpfault:
 
_ipfault:
 
_tick:
SAVE_INT_REGS(0x0500)
l.lwz r3,0(r1)
l.movhi r4,0x2
l.ori r4,r4,0x6034
l.sfeq r3,r4
l.bnf 1f
l.nop
l.sfeqi r10,0x00
l.bnf 1f
l.nop
l.lwz r3,0xc(r0)
l.addi r3,r3,1
l.sw 0xc(r0),r3
l.lwz r3,4(r1)
l.andi r3,r3,SPR_SR_F
l.sfeqi r3,0x00
l.bnf _fail
l.nop
1:
l.addi r3,r1,0
l.jal _timer_interrupt
l.nop
RETURN_FROM_INT(0x500)
 
_fail:
l.j _fail
l.nop
 
_align:
l.addi r1,r1,-128
l.sw 0x08(r1),r2
l.lwz r3,(TEMP_R_LOC + 0)(r0)
l.sw 0x0c(r1),r3
l.sw 0x10(r1),r4
l.sw 0x14(r1),r5
l.sw 0x18(r1),r6
l.sw 0x1c(r1),r7
l.sw 0x20(r1),r8
l.sw 0x24(r1),r9
l.sw 0x28(r1),r10
l.sw 0x2c(r1),r11
l.sw 0x30(r1),r12
l.sw 0x34(r1),r13
l.sw 0x38(r1),r14
l.sw 0x3c(r1),r15
l.sw 0x40(r1),r16
l.sw 0x44(r1),r17
l.sw 0x48(r1),r18
l.sw 0x4c(r1),r19
l.sw 0x50(r1),r20
l.sw 0x54(r1),r21
l.sw 0x58(r1),r22
l.sw 0x5c(r1),r23
l.sw 0x60(r1),r24
l.sw 0x64(r1),r25
l.sw 0x68(r1),r26
l.sw 0x6c(r1),r27
l.sw 0x70(r1),r28
l.sw 0x74(r1),r29
l.sw 0x78(r1),r30
l.sw 0x7c(r1),r31
l.mfspr r2,r0,SPR_EEAR_BASE /* Load the efective addres */
l.mfspr r5,r0,SPR_EPCR_BASE /* Load the insn address */
 
l.lwz r3,0(r5) /* Load insn */
l.srli r4,r3,26 /* Shift left to get the insn opcode */
 
l.sfeqi r4,0x00 /* Check if the load/store insn is in delay slot */
l.bf jmp
l.sfeqi r4,0x01
l.bf jmp
l.sfeqi r4,0x03
l.bf jmp
l.sfeqi r4,0x04
l.bf jmp
l.sfeqi r4,0x11
l.bf jr
l.sfeqi r4,0x12
l.bf jr
l.nop
l.j 1f
l.addi r5,r5,4 /* Increment PC to get return insn address */
jmp:
l.slli r4,r3,6 /* Get the signed extended jump length */
l.srai r4,r4,4
 
l.lwz r3,4(r5) /* Load the real load/store insn */
 
l.add r5,r5,r4 /* Calculate jump target address */
l.j 1f
l.srli r4,r3,26 /* Shift left to get the insn opcode */
 
jr:
l.slli r4,r3,9 /* Shift to get the reg nb */
l.andi r4,r4,0x7c
 
l.lwz r3,4(r5) /* Load the real load/store insn */
 
l.add r4,r4,r1 /* Load the jump register value from the stack */
l.lwz r5,0(r4)
 
l.srli r4,r3,26 /* Shift left to get the insn opcode */
1: l.mtspr r0,r5,SPR_EPCR_BASE
 
l.sfeqi r4,0x26
l.bf lhs
l.sfeqi r4,0x25
l.bf lhz
l.sfeqi r4,0x22
l.bf lws
l.sfeqi r4,0x21
l.bf lwz
l.sfeqi r4,0x37
l.bf sh
l.sfeqi r4,0x35
l.bf sw
l.nop
 
1: l.j 1b /* I don't know what to do */
l.nop
 
lhs: l.lbs r5,0(r2)
l.slli r5,r5,8
l.lbz r6,1(r2)
l.or r5,r5,r6
l.srli r4,r3,19
l.andi r4,r4,0x7c
l.add r4,r4,r1
l.j align_end
l.sw 0(r4),r5
lhz: l.lbz r5,0(r2)
l.slli r5,r5,8
l.lbz r6,1(r2)
l.or r5,r5,r6
l.srli r4,r3,19
l.andi r4,r4,0x7c
l.add r4,r4,r1
l.j align_end
l.sw 0(r4),r5
lws: l.lbs r5,0(r2)
l.slli r5,r5,24
l.lbz r6,1(r2)
l.slli r6,r6,16
l.or r5,r5,r6
l.lbz r6,2(r2)
l.slli r6,r6,8
l.or r5,r5,r6
l.lbz r6,3(r2)
l.or r5,r5,r6
l.srli r4,r3,19
l.andi r4,r4,0x7c
l.add r4,r4,r1
l.j align_end
l.sw 0(r4),r5
lwz: l.lbz r5,0(r2)
l.slli r5,r5,24
l.lbz r6,1(r2)
l.slli r6,r6,16
l.or r5,r5,r6
l.lbz r6,2(r2)
l.slli r6,r6,8
l.or r5,r5,r6
l.lbz r6,3(r2)
l.or r5,r5,r6
l.srli r4,r3,19
l.andi r4,r4,0x7c
l.add r4,r4,r1
l.j align_end
l.sw 0(r4),r5
sh:
l.srli r4,r3,9
l.andi r4,r4,0x7c
l.add r4,r4,r1
l.lwz r5,0(r4)
l.sb 1(r2),r5
l.srli r5,r5,8
l.j align_end
l.sb 0(r2),r5
 
sw:
l.srli r4,r3,9
l.andi r4,r4,0x7c
l.add r4,r4,r1
l.lwz r5,0(r4)
l.sb 3(r2),r5
l.srli r5,r5,8
l.sb 2(r2),r5
l.srli r5,r5,8
l.sb 1(r2),r5
l.srli r5,r5,8
l.j align_end
l.sb 0(r2),r5
 
align_end:
l.lwz r2,0x08(r1)
l.lwz r3,0x0c(r1)
l.lwz r4,0x10(r1)
l.lwz r5,0x14(r1)
l.lwz r6,0x18(r1)
l.lwz r7,0x1c(r1)
l.lwz r8,0x20(r1)
l.lwz r9,0x24(r1)
l.lwz r10,0x28(r1)
l.lwz r11,0x2c(r1)
l.lwz r12,0x30(r1)
l.lwz r13,0x34(r1)
l.lwz r14,0x38(r1)
l.lwz r15,0x3c(r1)
l.lwz r16,0x40(r1)
l.lwz r17,0x44(r1)
l.lwz r18,0x48(r1)
l.lwz r19,0x4c(r1)
l.lwz r20,0x50(r1)
l.lwz r21,0x54(r1)
l.lwz r22,0x58(r1)
l.lwz r23,0x5c(r1)
l.lwz r24,0x60(r1)
l.lwz r25,0x64(r1)
l.lwz r26,0x68(r1)
l.lwz r27,0x6c(r1)
l.lwz r28,0x70(r1)
l.lwz r29,0x74(r1)
l.lwz r30,0x78(r1)
l.lwz r31,0x7c(r1)
l.addi r1,r1,128
l.rfe
 
 
_ext_int:
SAVE_INT_REGS(0x0800)
l.lwz r3,0(r1)
l.movhi r4,0x2
l.ori r4,r4,0x6034
l.sfeq r3,r4
l.bnf 1f
l.nop
l.lwz r3,0xc(r0)
l.addi r3,r3,1
l.sw 0xc(r0),r3
l.sfeqi r10,0x00
l.bf _fail
l.nop
1:
l.addi r3,r1,0
l.jal _handle_IRQ
l.nop
RETURN_FROM_INT(0x800)
 
_dtlbmiss:
l.sw (TEMP_R_LOC + 4)(r0),r4
l.sw (TEMP_R_LOC + 8)(r0),r5
l.mfspr r3,r0,SPR_EEAR_BASE
l.srli r4,r3,DMMU_PAGE_ADD_BITS
l.andi r4,r4,DMMU_SET_ADD_MASK
l.addi r5,r0,-1
l.xori r5,r5,DMMU_PAGE_ADD_MASK
l.and r5,r3,r5
l.ori r5,r5,SPR_DTLBMR_V
l.mtspr r4,r5,SPR_DTLBMR_BASE(0)
l.movhi r5,hi(SPR_DTLBTR_PPN)
l.ori r5,r5,lo(SPR_DTLBTR_PPN)
l.and r5,r3,r5
l.ori r5,r5,DTLBTR_NO_LIMIT
l.movhi r3,0x8000
l.sfgeu r5,r3
l.bnf 1f
l.nop
l.ori r5,r5,SPR_DTLBTR_CI
1: l.mtspr r4,r5,SPR_DTLBTR_BASE(0)
l.lwz r3,(TEMP_R_LOC + 0)(r0)
l.lwz r4,(TEMP_R_LOC + 4)(r0)
l.lwz r5,(TEMP_R_LOC + 8)(r0)
l.rfe
l.nop
 
 
_itlbmiss:
l.sw (TEMP_R_LOC + 4)(r0),r4
l.sw (TEMP_R_LOC + 8)(r0),r5
l.mfspr r3,r0,SPR_EEAR_BASE
l.srli r4,r3,IMMU_PAGE_ADD_BITS
l.andi r4,r4,IMMU_SET_ADD_MASK
l.addi r5,r0,-1
l.xori r5,r5,IMMU_PAGE_ADD_MASK
l.and r5,r3,r5
l.ori r5,r5,SPR_ITLBMR_V
l.mtspr r4,r5,SPR_ITLBMR_BASE(0)
l.movhi r5,hi(SPR_ITLBTR_PPN)
l.ori r5,r5,lo(SPR_ITLBTR_PPN)
l.and r5,r3,r5
l.ori r5,r5,ITLBTR_NO_LIMIT
l.mtspr r4,r5,SPR_ITLBTR_BASE(0)
l.lwz r3,(TEMP_R_LOC + 0)(r0)
l.lwz r4,(TEMP_R_LOC + 4)(r0)
l.lwz r5,(TEMP_R_LOC + 8)(r0)
l.rfe
l.nop
 
_sys_call:
SAVE_INT_REGS(0x0c00)
/* EPCR was pointing to l.sys instruction, we have to incremet it */
/* l.lwz r2,PC(r1)
l.addi r2,r2,4
l.sw PC(r1),r2
*/
l.sfeqi r11,0x7777 /* Special case for 'sys_sigreturn' */
l.bnf 10f
l.nop
l.jal _sys_sigreturn
l.addi r3,r1,0
l.sfgtsi r11,0 /* Check for restarted system call */
l.bf 99f
l.nop
l.j 20f
l.nop
10:
l.movhi r2,hi(_sys_call_table)
l.ori r2,r2,lo(_sys_call_table)
l.slli r11,r11,2
l.add r2,r2,r11
l.lwz r2,0(r2)
l.addi r8,r1,0 /* regs pointer */
l.jalr r2
l.nop
l.sw GPR11(r1),r11 /* save return value */
20:
l.sw RESULT(r1),r11 /* save result */
l.sfgesi r11,0
l.bf 99f
l.nop
l.sfeqi r11,-ERESTARTNOHAND
l.bnf 22f
l.nop
l.addi r11,r0,EINTR
22:
l.sw RESULT(r1),r11
99:
RETURN_FROM_INT(0xc00)
 
/*
* This routine switches between two different tasks. The process
* state of one is saved on its kernel stack. Then the state
* of the other is restored from its kernel stack. The memory
* management hardware is updated to the second process's state.
* Finally, we can return to the second process, via the 'return'.
*
* Note: there are two ways to get to the "going out" portion
* of this code; either by coming in via the entry (_switch)
* or via "fork" which must set up an environment equivalent
* to the "_switch" path. If you change this (or in particular, the
* SAVE_REGS macro), you'll have to change the fork code also.
*/
__switch:
l.sw (TEMP_R_LOC + 0)(r0),r3 /* Temporary store r3 to add 0!!! */
l.sw (TEMP_R_LOC + 4)(r0),r1 /* Temporary store r1 to add 4!!! */
l.mtspr r0,r9,SPR_EPCR_BASE /* Link register to EPCR */
l.mfspr r3,r0,SPR_SR /* From SR to ESR */
l.mtspr r0,r3,SPR_ESR_BASE
SAVE_REGS(0x0FF0)
l.sw TSS_KSP(r3),r1 /* Set old stack pointer */
l.lwz r1,TSS_KSP(r4) /* Load new stack pointer */
RETURN_FROM_INT(0xFF0)
 
_ua_init:
l.movhi r3,hi(UART_BASE_ADD)
 
l.addi r4,r0,0x7
l.sb 0x2(r3),r4
 
l.addi r4,r0,0x0
l.sb 0x1(r3),r4
 
l.addi r4,r0,0x3
l.sb 0x3(r3),r4
 
l.lbz r5,3(r3)
l.ori r4,r5,0x80
l.sb 0x3(r3),r4
l.addi r4,r0,((UART_DEVISOR>>8) & 0x000000ff)
l.sb UART_DLM(r3),r4
l.addi r4,r0,((UART_DEVISOR) & 0x000000ff)
l.sb UART_DLL(r3),r4
l.sb 0x3(r3),r5
 
l.jr r9
l.nop
 
_putc:
l.movhi r4,hi(UART_BASE_ADD)
 
l.addi r6,r0,0x20
1: l.lbz r5,5(r4)
l.andi r5,r5,0x20
l.sfeq r5,r6
l.bnf 1b
l.nop
l.sb 0(r4),r3
 
l.addi r6,r0,0x60
1: l.lbz r5,5(r4)
l.andi r5,r5,0x60
l.sfeq r5,r6
l.bnf 1b
l.nop
 
l.jr r9
l.nop
 
 
_trap_200:
l.nop
l.nop
.word 0x21000001
1: l.j 1b
l.nop
 
_trap_300:
l.nop
l.nop
.word 0x21000001
1: l.j 1b
l.nop
 
_trap_400:
l.nop
l.nop
.word 0x21000001
1: l.j 1b
l.nop
 
_trap_700:
l.nop
l.nop
.word 0x21000001
1: l.j 1b
l.nop
 
_trap_900:
l.nop
l.nop
.word 0x21000001
1: l.j 1b
l.nop
 
_trap_a00:
l.nop
l.nop
.word 0x21000001
1: l.j 1b
l.nop
 
_trap_b00:
l.nop
l.nop
.word 0x21000001
1: l.j 1b
l.nop
 
.data
env:
.long 0
/semaphore.c
0,0 → 1,83
/*
* FILE: semaphore.c
* AUTHOR: kma@cse.ogi.edu
* DESCR: interrupt-safe i960 semaphore implementation; isn't ready for SMP
*/
 
#include <asm/semaphore.h>
#include <linux/sched.h>
 
extern int __down_common(struct semaphore* sem, int intrflag)
{
long flags;
int retval=0;
 
save_flags(flags);
cli();
if (--sem->count < 0) {
if (intrflag) {
interruptible_sleep_on(&sem->wait);
if (current->signal & ~current->blocked) {
retval = -1;
}
}
else
sleep_on(&sem->wait);
}
restore_flags(flags);
return retval;
}
 
void down(struct semaphore * sem)
{
__down_common(sem, 0);
}
 
 
/*
* This version waits in interruptible state so that the waiting
* process can be killed. The down_failed_interruptible routine
* returns negative for signalled and zero for semaphore acquired.
*/
extern int down_interruptible(struct semaphore * sem)
{
return __down_common(sem, 1);
return 0;
}
 
 
/*
* Primitives to spin on a lock. Needed only for SMP.
*/
extern void get_buzz_lock(int *lock_ptr)
{
#ifdef __SMP__
while (xchg(lock_ptr,1) != 0) ;
#endif
}
 
extern void give_buzz_lock(int *lock_ptr)
{
#ifdef __SMP__
*lock_ptr = 0 ;
#endif
}
 
 
/*
* We wake people up only if the semaphore was negative (== somebody was
* waiting on it).
*/
extern void up(struct semaphore * sem)
{
long flags;
save_flags(flags);
cli();
 
if (sem->count++ < 0)
wake_up(&sem->wait);
restore_flags(flags);
}
 
/traps.c
0,0 → 1,209
/*
* linux/arch/m68knommu/kernel/traps.c
*
* Copyright (C) 1998 D. Jeff Dionne <jeff@ryeham.ee.ryerson.ca>,
* Kenneth Albanowski <kjahds@kjahds.com>
* The Silver Hammer Group, Ltd.
*
* (Blame me for the icky bits -- kja)
*
* Based on:
*
* linux/arch/m68k/kernel/traps.c
*
* Copyright (C) 1993, 1994 by Hamish Macdonald
*
* 68040 fixes by Michael Rausch
* 68040 fixes by Martin Apel
* 68060 fixes by Roman Hodek
* 68060 fixes by Jesper Skov
*
* 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.
*
* Feb/1999 - Greg Ungerer (gerg@moreton.com.au) changes to support ColdFire.
*/
 
/*
* Sets up all exception vectors
*/
 
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/types.h>
#include <linux/a.out.h>
#include <linux/user.h>
#include <linux/string.h>
#include <linux/linkage.h>
 
#include <asm/system.h>
#include <asm/segment.h>
#include <asm/traps.h>
#include <asm/pgtable.h>
#include <asm/machdep.h>
 
 
void trap_init (void)
{
if (mach_trap_init)
mach_trap_init();
}
 
static inline void console_verbose(void)
{
extern int console_loglevel;
console_loglevel = 15;
if (mach_debug_init)
mach_debug_init();
}
 
 
extern void die_if_kernel(char *,struct pt_regs *,int);
asmlinkage void trap_c(int vector, struct frame *fp);
 
asmlinkage void buserr_c(struct frame *fp)
{
#if 1
extern void dump(struct pt_regs *fp);
printk("%s(%d): BUSS ERROR TRAP\n", __FILE__, __LINE__);
dump((struct pt_regs *) fp);
#endif
 
/* Only set esp0 if coming from user mode */
if (user_mode(&fp->ptregs)) {
current->tss.esp0 = (unsigned long) fp;
} else {
die_if_kernel("Kernel mode BUS error",(struct pt_regs *)fp,0);
}
 
/* insert handler here */
force_sig(SIGSEGV, current);
}
 
 
static int bad_super_trap_count = 0;
 
void bad_super_trap (int vector, struct frame *fp)
{
extern void dump(struct pt_regs *fp);
 
if (bad_super_trap_count++) {
while(1);
}
 
printk ("KERNEL: Bad trap from supervisor state, vector=%d\n", vector);
dump((struct pt_regs *) fp);
panic ("Trap from supervisor state");
}
 
asmlinkage void trap_c(int vector, struct frame *fp)
{
int sig;
#if 0
if ((fp->ptregs.sr & PS_S)
&& ((fp->ptregs.vector) >> 2) == VEC_TRACE
&& !(fp->ptregs.sr & PS_T)) {
/* traced a trapping instruction */
unsigned char *lp = ((unsigned char *)&fp->un.fmt2) + 4;
current->flags |= PF_DTRACE;
/* clear the trace bit */
(*(unsigned short *)lp) &= ~PS_T;
return;
} else if (fp->ptregs.sr & PS_S) {
bad_super_trap(vector, fp);
return;
}
 
/* send the appropriate signal to the user program */
switch (vector) {
case VEC_ADDRERR:
sig = SIGBUS;
break;
case VEC_BUSERR:
sig = SIGSEGV;
break;
case VEC_ILLEGAL:
case VEC_PRIV:
case VEC_LINE10:
case VEC_LINE11:
case VEC_COPROC:
case VEC_TRAP2:
case VEC_TRAP3:
case VEC_TRAP4:
case VEC_TRAP5:
case VEC_TRAP6:
case VEC_TRAP7:
case VEC_TRAP8:
case VEC_TRAP9:
case VEC_TRAP10:
case VEC_TRAP11:
case VEC_TRAP12:
case VEC_TRAP13:
case VEC_TRAP14:
sig = SIGILL;
break;
#ifndef NO_FPU
case VEC_FPBRUC:
case VEC_FPIR:
case VEC_FPDIVZ:
case VEC_FPUNDER:
case VEC_FPOE:
case VEC_FPOVER:
case VEC_FPNAN:
{
unsigned char fstate[216];
 
__asm__ __volatile__ ("fsave %0@" : : "a" (fstate) : "memory");
/* Set the exception pending bit in the 68882 idle frame */
if (*(unsigned short *) fstate == 0x1f38)
{
fstate[fstate[1]] |= 1 << 3;
__asm__ __volatile__ ("frestore %0@" : : "a" (fstate));
}
}
/* fall through */
#endif
case VEC_ZERODIV:
case VEC_TRAP:
sig = SIGFPE;
break;
case VEC_TRACE: /* ptrace single step */
fp->ptregs.sr &= ~PS_T;
case VEC_TRAP15: /* breakpoint */
sig = SIGTRAP;
break;
case VEC_TRAP1: /* gdbserver breakpoint */
/* kwonsk: is this right? */
fp->ptregs.pc -= 2;
sig = SIGTRAP;
break;
default:
sig = SIGILL;
break;
}
 
send_sig (sig, current, 1);
#endif
}
 
asmlinkage void set_esp0 (unsigned long ssp)
{
current->tss.esp0 = ssp;
}
 
void die_if_kernel (char *str, struct pt_regs *fp, int nr)
{
extern void dump(struct pt_regs *fp);
 
if (!(fp->sr & PS_S))
return;
 
console_verbose();
dump(fp);
 
do_exit(SIGSEGV);
}
/irq.c
0,0 → 1,290
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/kernel_stat.h>
#include <linux/errno.h>
 
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/traps.h>
#include <asm/page.h>
#include <asm/machdep.h>
 
/* table for system interrupt handlers */
static irq_handler_t irq_list[SYS_IRQS];
 
static const char *default_names[SYS_IRQS] = {
"int0", "int1", "int2", "int3", "int4", "int5", "int6", "int7"
"int8", "int9", "int10", "int11", "int12", "int13", "int14", "int15"
"int16", "int17", "int18", "int19", "int20", "int21", "int22", "int23"
"int24", "int25", "int26", "int27", "int28", "int29", "int30", "int31"
};
 
int pic_enable_irq(unsigned int irq)
{
/* Enable in the IMR */
mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (0x00000001L << irq));
 
return 0;
}
 
int pic_disable_irq(unsigned int irq)
{
/* Disable in the IMR */
mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(0x00000001L << irq));
 
return 0;
}
 
int pic_init(void)
{
/* turn off all interrupts */
mtspr(SPR_PICMR, 0);
return 0;
}
 
int pic_do_irq(struct pt_regs *fp)
{
int irq;
int mask;
 
unsigned long pend = mfspr(SPR_PICSR) & 0xfffffffc;
 
if (pend & 0x0000ffff) {
if (pend & 0x000000ff) {
if (pend & 0x0000000f) {
mask = 0x00000001;
irq = 0;
} else {
mask = 0x00000010;
irq = 4;
}
} else {
if (pend & 0x00000f00) {
mask = 0x00000100;
irq = 8;
} else {
mask = 0x00001000;
irq = 12;
}
}
} else if(pend & 0xffff0000) {
if (pend & 0x00ff0000) {
if (pend & 0x000f0000) {
mask = 0x00010000;
irq = 16;
} else {
mask = 0x00100000;
irq = 20;
}
} else {
if (pend & 0x0f000000) {
mask = 0x01000000;
irq = 24;
} else {
mask = 0x10000000;
irq = 28;
}
}
} else {
return -1;
}
 
while (! (mask & pend)) {
mask <<=1;
irq++;
}
 
mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~mask);
return irq;
}
 
void init_IRQ(void)
{
int i;
 
for (i = 0; i < SYS_IRQS; i++) {
irq_list[i].handler = NULL;
irq_list[i].flags = IRQ_FLG_STD;
irq_list[i].dev_id = NULL;
irq_list[i].devname = default_names[i];
}
 
pic_init();
}
 
asmlinkage void handle_IRQ(struct pt_regs *regs)
{
int irq;
 
while((irq = pic_do_irq(regs)) >= 0) {
 
if (irq_list[irq].handler)
irq_list[irq].handler(irq, irq_list[irq].dev_id, regs);
else
panic("No interrupt handler for autovector %d\n", irq);
}
}
 
int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
unsigned long flags, const char *devname, void *dev_id)
{
if (irq >= SYS_IRQS) {
printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname);
return -ENXIO;
}
 
if (!(irq_list[irq].flags & IRQ_FLG_STD)) {
if (irq_list[irq].flags & IRQ_FLG_LOCK) {
printk("%s: IRQ %d from %s is not replaceable\n",
__FUNCTION__, irq, irq_list[irq].devname);
return -EBUSY;
}
if (flags & IRQ_FLG_REPLACE) {
printk("%s: %s can't replace IRQ %d from %s\n",
__FUNCTION__, devname, irq, irq_list[irq].devname);
return -EBUSY;
}
}
irq_list[irq].handler = handler;
irq_list[irq].flags = flags;
irq_list[irq].dev_id = dev_id;
irq_list[irq].devname = devname;
 
pic_enable_irq(irq);
return 0;
}
 
void free_irq(unsigned int irq, void *dev_id)
{
if (irq >= SYS_IRQS) {
printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
return;
}
 
pic_disable_irq(irq);
 
irq_list[irq].handler = NULL;
irq_list[irq].flags = IRQ_FLG_STD;
irq_list[irq].dev_id = NULL;
irq_list[irq].devname = default_names[irq];
}
 
unsigned long probe_irq_on (void)
{
return 0;
}
 
int probe_irq_off (unsigned long irqs)
{
return 0;
}
 
void enable_irq(unsigned int irq)
{
if (irq >= SYS_IRQS) {
printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
return;
}
pic_enable_irq(irq);
}
 
void disable_irq(unsigned int irq)
{
if (irq >= SYS_IRQS) {
printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
return;
}
pic_disable_irq(irq);
}
 
int get_irq_list(char *buf)
{
int i, len = 0;
 
/* autovector interrupts */
for (i = 0; i < SYS_IRQS; i++) {
if (irq_list[i].handler) {
if (irq_list[i].flags & IRQ_FLG_LOCK)
len += sprintf(buf+len, "L ");
else
len += sprintf(buf+len, " ");
if (irq_list[i].flags & IRQ_FLG_PRI_HI)
len += sprintf(buf+len, "H ");
else
len += sprintf(buf+len, "L ");
len += sprintf(buf+len, "%s\n", irq_list[i].devname);
}
}
 
return len;
}
 
void dump(struct pt_regs *fp)
{
unsigned long *sp;
unsigned char *tp;
int i;
 
printk("\nCURRENT PROCESS:\n\n");
printk("COMM=%s PID=%d\n", current->comm, current->pid);
if (current->mm) {
printk("TEXT=%08x-%08x DATA=%08x-%08x BSS=%08x-%08x\n",
(int) current->mm->start_code,
(int) current->mm->end_code,
(int) current->mm->start_data,
(int) current->mm->end_data,
(int) current->mm->end_data,
(int) current->mm->brk);
printk("USER-STACK=%08x KERNEL-STACK=%08x\n\n",
(int) current->mm->start_stack,
(int) current->kernel_stack_page);
}
printk("PC: %08lx Status: %08lx\n",
fp->pc, fp->sr);
printk("R0 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
0L, fp->sp, fp->gprs[0], fp->gprs[1],
fp->gprs[2], fp->gprs[3], fp->gprs[4], fp->gprs[5]);
printk("R8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
fp->gprs[6], fp->gprs[7], fp->gprs[8], fp->gprs[9],
fp->gprs[10], fp->gprs[11], fp->gprs[12], fp->gprs[13]);
printk("R16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
fp->gprs[14], fp->gprs[15], fp->gprs[16], fp->gprs[17],
fp->gprs[18], fp->gprs[19], fp->gprs[20], fp->gprs[21]);
printk("R24: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
fp->gprs[22], fp->gprs[23], fp->gprs[24], fp->gprs[25],
fp->gprs[26], fp->gprs[27], fp->gprs[28], fp->gprs[29]);
 
printk("\nUSP: %08lx TRAPFRAME: %08x\n",
fp->sp, (unsigned int) fp);
 
printk("\nCODE:");
tp = ((unsigned char *) fp->pc) - 0x20;
for (sp = (unsigned long *) tp, i = 0; (i < 0x40); i += 4) {
if ((i % 0x10) == 0)
printk("\n%08x: ", (int) (tp + i));
printk("%08x ", (int) *sp++);
}
printk("\n");
 
printk("\nKERNEL STACK:");
tp = ((unsigned char *) fp) - 0x40;
for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) {
if ((i % 0x10) == 0)
printk("\n%08x: ", (int) (tp + i));
printk("%08x ", (int) *sp++);
}
printk("\n");
if (STACK_MAGIC != *(unsigned long *)current->kernel_stack_page)
printk("(Possibly corrupted stack page??)\n");
printk("\n");
 
printk("\nUSER STACK:");
tp = (unsigned char *) (fp->sp - 0x10);
for (sp = (unsigned long *) tp, i = 0; (i < 0x80); i += 4) {
if ((i % 0x10) == 0)
printk("\n%08x: ", (int) (tp + i));
printk("%08x ", (int) *sp++);
}
printk("\n\n");
}
/Makefile
0,0 → 1,23
#
# 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...
 
.S.o:
$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o
 
all: head.o kernel.o
 
 
O_TARGET := kernel.o
O_OBJS := setup.o process.o traps.o ptrace.o syscalls.o time.o ksyms.o irq.o misc.o entry.o signal.o semaphore.o
 
ifdef CONFIG_CONSOLE
O_OBJS += console.o
endif
 
include $(TOPDIR)/Rules.make
/.depend
0,0 → 1,180
bios32.o: \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/config.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/kernel.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/types.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/bios32.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/pci.h
console.o: \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/config.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/sched.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/timer.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/interrupt.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/tty.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/tty_flip.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/kernel.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/string.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/errno.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/console.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/kd.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/malloc.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/major.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/mm.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/ioport.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/io.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/segment.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/system.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/bitops.h \
../../../drivers/char/kbd_kern.h \
../../../drivers/char/vt_kern.h \
../../../drivers/char/consolemap.h \
../../../drivers/char/selection.h
entry.o: \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/sys.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/config.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/linkage.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/segment.h
head.o: \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/spr_defs.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/ptrace.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/board.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/mc.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/errno.h
irq.o: \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/types.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/sched.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/kernel_stat.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/errno.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/system.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/irq.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/traps.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/page.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/machdep.h
ksyms.o: \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/config.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/module.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/linkage.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/sched.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/string.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/mm.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/user.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/elfcore.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/pgtable.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/irq.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/semaphore.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/symtab_begin.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/symtab_end.h
misc.o: \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/spr_defs.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/board.h
mk_defs.o: \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/signal.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/sched.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/head.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/kernel.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/errno.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/string.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/types.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/ptrace.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/mman.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/mm.h
process.o: \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/config.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/errno.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/sched.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/kernel.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/mm.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/stddef.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/unistd.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/ptrace.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/malloc.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/user.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/a.out.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/segment.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/system.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/traps.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/machdep.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/board.h
ptrace.o: \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/kernel.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/sched.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/string.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/mm.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/errno.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/ptrace.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/user.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/segment.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/page.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/pgtable.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/system.h
semaphore.o: \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/semaphore.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/sched.h
setup.o: \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/config.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/kernel.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/sched.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/delay.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/interrupt.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/fs.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/fb.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/console.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/genhd.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/errno.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/string.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/major.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/irq.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/machdep.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/blk.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/pgtable.h
signal.o: \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/config.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/sched.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/mm.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/kernel.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/signal.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/errno.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/wait.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/ptrace.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/unistd.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/segment.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/pgtable.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/traps.h
syscalls.o: \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/errno.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/sched.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/mm.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/sem.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/msg.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/shm.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/stat.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/mman.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/segment.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/traps.h
time.o: \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/config.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/errno.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/sched.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/kernel.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/param.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/string.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/mm.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/machdep.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/segment.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/io.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/timex.h
traps.o: \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/config.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/sched.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/signal.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/kernel.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/mm.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/types.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/a.out.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/user.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/string.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/linux/linkage.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/system.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/segment.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/traps.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/pgtable.h \
/home/javier/opencores/or1k/rc203soc/sw/uClinux/include/asm/machdep.h
/syscalls.c
0,0 → 1,196
/*
* linux/arch/or32/kernel/syscalls.c
*
* Based on:
*
* linux/arch/m68knommu/kernel/sys_m68k.c
*
* This file contains various random system calls that
* have a non-standard calling sequence on the Linux/or32
* platform.
*/
 
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/sem.h>
#include <linux/msg.h>
#include <linux/shm.h>
#include <linux/stat.h>
#include <linux/mman.h>
 
#include <asm/segment.h>
#include <asm/traps.h>
 
/*
* sys_pipe() is the normal C calling standard for creating
* a pipe. It's not the way unix traditionally does this, though.
*/
asmlinkage int sys_pipe(unsigned long * fildes)
{
int fd[2];
int error;
 
error = verify_area(VERIFY_WRITE,fildes,8);
if (error)
return error;
error = do_pipe(fd);
if (error)
return error;
put_user(fd[0],0+fildes);
put_user(fd[1],1+fildes);
return 0;
}
 
/*
* Perform the select(nd, in, out, ex, tv) and mmap() system
* calls. Linux/m68k cloned Linux/i386, which didn't use to be able to
* handle more than 4 system call parameters, so these system calls
* used a memory block for parameter passing..
*/
 
asmlinkage int old_mmap(unsigned long *buffer)
{
int error;
unsigned long flags;
struct file * file = NULL;
 
error = verify_area(VERIFY_READ, buffer, 6*sizeof(long));
if (error)
return error;
flags = get_user(buffer+3);
if (!(flags & MAP_ANONYMOUS)) {
unsigned long fd = get_user(buffer+4);
if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
return -EBADF;
}
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
return do_mmap(file, get_user(buffer), get_user(buffer+1),
get_user(buffer+2), flags, get_user(buffer+5));
}
 
 
extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
 
asmlinkage int old_select(unsigned long *buffer)
{
int n;
fd_set *inp;
fd_set *outp;
fd_set *exp;
struct timeval *tvp;
 
n = verify_area(VERIFY_READ, buffer, 5*sizeof(unsigned long));
if (n)
return n;
 
n = get_user(buffer);
inp = (fd_set *) get_user(buffer+1);
outp = (fd_set *) get_user(buffer+2);
exp = (fd_set *) get_user(buffer+3);
tvp = (struct timeval *) get_user(buffer+4);
return sys_select(n, inp, outp, exp, tvp);
}
 
/*
* sys_ipc() is the de-multiplexer for the SysV IPC calls..
*
* This is really horribly ugly.
*/
asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
{
int version;
 
version = call >> 16; /* hack for backward compatibility */
call &= 0xffff;
 
if (call <= SEMCTL)
switch (call) {
case SEMOP:
return sys_semop (first, (struct sembuf *)ptr, second);
case SEMGET:
return sys_semget (first, second, third);
case SEMCTL: {
union semun fourth;
int err;
if (!ptr)
return -EINVAL;
if ((err = verify_area (VERIFY_READ, ptr, sizeof(long))))
return err;
fourth.__pad = get_user((void **)ptr);
return sys_semctl (first, second, third, fourth);
}
default:
return -EINVAL;
}
if (call <= MSGCTL)
switch (call) {
case MSGSND:
return sys_msgsnd (first, (struct msgbuf *) ptr,
second, third);
case MSGRCV:
switch (version) {
case 0: {
struct ipc_kludge tmp;
int err;
if (!ptr)
return -EINVAL;
if ((err = verify_area (VERIFY_READ, ptr, sizeof(tmp))))
return err;
memcpy_fromfs (&tmp,(struct ipc_kludge *) ptr,
sizeof (tmp));
return sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
}
case 1: default:
return sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third);
}
case MSGGET:
return sys_msgget ((key_t) first, second);
case MSGCTL:
return sys_msgctl (first, second, (struct msqid_ds *) ptr);
default:
return -EINVAL;
}
if (call <= SHMCTL)
switch (call) {
case SHMAT:
switch (version) {
case 0: default: {
ulong raddr;
int err;
if ((err = verify_area(VERIFY_WRITE, (ulong*) third, sizeof(ulong))))
return err;
err = sys_shmat (first, (char *) ptr, second, &raddr);
if (err)
return err;
put_user (raddr, (ulong *) third);
return 0;
}
case 1: /* iBCS2 emulator entry point */
if (get_fs() != get_ds())
return -EINVAL;
return sys_shmat (first, (char *) ptr, second, (ulong *) third);
}
case SHMDT:
return sys_shmdt ((char *)ptr);
case SHMGET:
return sys_shmget (first, second, third);
case SHMCTL:
return sys_shmctl (first, second, (struct shmid_ds *) ptr);
default:
return -EINVAL;
}
return -EINVAL;
}
 
asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
{
return -ENOSYS;
}
 
/* sys_cacheflush -- flush (part of) the processor cache. */
asmlinkage int
sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
{
return 0;
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.