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

Subversion Repositories or1k

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /or1k/trunk/uclinux/uClinux-2.0.x/arch/i960
    from Rev 199 to Rev 1765
    Reverse comparison

Rev 199 → Rev 1765

/empty.c
0,0 → 1,4
 
/* This file is necessary to produce an "empty" .o file */
 
extern int foo;
/kernel/time.c
0,0 → 1,169
/*
* linux/arch/i960/kernel/time.c
*
* Copyright (C) 1999 Keith Adams <kma@cse.ogi.edu>
* Oregon Graduate Institute
*
* Based on:
*
* linux/arch/m68knommu/kernel/time.c
*
* Copyright (C) 1998 D. Jeff Dionne <jeff@ryeham.ee.ryerson.ca>,
* Kenneth Albanowski <kjahds@kjahds.com>,
* The Silver Hammer Group, Ltd.
*
* Copied/hacked from:
*
* linux/arch/m68k/kernel/time.c
*
* Copyright (C) 1991, 1992, 1995 Linus Torvalds
*
* This file contains the i960-specific time handling details.
*/
 
#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>
 
 
/*
* XXX: bloody hell. We need to have figured out our machine's MHZ, and
* programmed its clock accordingly.
*/
static inline int set_rtc_mmss(unsigned long nowtime)
{
return -1;
}
 
int do_reboot = 0;
 
/*
* timer_interrupt() needs to keep up the real-time clock,
* as well as call the "do_timer()" routine every clocktick
*/
void timer_interrupt(struct pt_regs * regs)
{
/* last time the cmos clock got updated */
static long last_rtc_update=0;
 
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;
 
#ifdef CONFIG_M68328
(*((volatile unsigned short*)0xFFFFF610)) = /*0x1000;*/ 0xd7e4;
(*((volatile unsigned short*)0xFFFFF60c)) = 0x33; /* Reset */
(*((volatile unsigned short*)0xFFFFF60e)) = 0x2; /* divider */
(*((volatile unsigned long*)0xFFFFF304)) &= ~2; /* Enable interrupt */
#endif
#ifdef CONFIG_M68332
*(volatile unsigned short *)0xfffa22 = 0x0140; /* ipl 6, vec 0x40 */
*(volatile unsigned short *)0xfffa24 = 0x00a3; /* 50 Hz */
#endif
}
 
/*
* This version of gettimeofday has near microsecond resolution.
*/
void do_gettimeofday(struct timeval *tv)
{
unsigned long flags;
save_flags(flags);
cli();
*tv = xtime;
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 0
tv->tv_usec -= mach_gettimeoffset();
#endif
 
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();
}
/kernel/setup.c
0,0 → 1,185
/*
* linux/arch/i960/kernel/setup.c
*
* Copyright (C) 1999 Keith Adams <kma@cse.ogi.edu>,
* Erik Walthinsen <omega@cse.ogi.edu>
*
* Copied/hacked from code by:
*
* Copyright (C) 1998 D. Jeff Dionne <jeff@ryeham.ee.ryerson.ca>,
* Kenneth Albanowski <kjahds@kjahds.com>
* The Silver Hammer Group, Ltd.
*
* linux/arch/m68k/kernel/setup.c
*
* Copyright (C) 1995 Hamish Macdonald
*/
 
/*
* 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/setup.h>
#include <asm/irq.h>
#include <asm/machdep.h>
 
#ifdef CONFIG_BLK_DEV_INITRD
#include <linux/blk.h>
#include <asm/pgtable.h>
#endif
 
 
extern int end;
/* FIXME this needs to be looked into */
unsigned long availmem = 1024*1024;
 
unsigned long rom_length;
unsigned long memory_start;
unsigned long memory_end;
char command_line[512];
char saved_command_line[512];
 
/* setup some dummy routines */
static void dummy_waitbut(void)
{
}
 
/* machine dependent keyboard functions */
int (*mach_keyb_init) (void);
int (*mach_kbdrate) (struct kbd_repeat *) = NULL;
void (*mach_kbd_leds) (unsigned int) = NULL;
/* machine dependent irq functions */
void (*mach_init_IRQ) (void);
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;
void (*mach_process_int) (int, struct pt_regs *) = NULL;
/* machine dependent timer functions */
unsigned long (*mach_gettimeoffset) (void);
void (*mach_gettod) (int*, int*, int*, int*, int*, int*);
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 );
void (*mach_reset)( void );
void (*waitbut)(void) = dummy_waitbut;
void (*mach_debug_init)(void);
 
extern void register_console(void (*proc)(const char *));
 
#define MASK_256K 0xfffc0000
 
#ifdef CONFIG_I960VH
# define CPU "i960Vh"
#endif
#ifdef CONFIG_I960RX
# define CPU "i960Rx"
#endif
#ifdef CONFIG_I960HX
# define CPU "i960Hx"
#endif
#ifdef CONFIG_I960CX
# define CPU "i960Cx"
#endif
#ifdef CONFIG_I960JX
# define CPU "i960Jx"
#endif
 
 
 
/* set up for i960 */
void setup_arch(char **cmdline_p,
unsigned long * memory_start_p, unsigned long * memory_end_p)
{
extern int stackbase, _etext, _edata, _end;
extern void mon960_console_init(void);
 
#ifdef CONFIG_MON960_CONSOLE
extern void console_print_mon960(const char* msg);
register_console(console_print_mon960);
mon960_console_init();
#endif
 
printk("\r\n\nuClinux " CPU "\n");
printk("i960 port (C) 1999 Keith Adams, Erik Walthinsen, Oregon Graduate Institute\n");
printk("Flat model support (C) 1998 Kenneth Albanowski, D. Jeff Dionne, TSHG Ltd.\n");
 
memory_start = PAGE_ALIGN(((unsigned long)&_end));
 
init_task.mm->start_code = 0;
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(BLKMEM_MAJOR,0);
 
command_line[512-1] = '\0';
if (memcmp(command_line, "Arg!", 4))
command_line[4] = '\0';
memset(command_line, 0, 4);
 
strcpy(saved_command_line, command_line+4);
*cmdline_p = command_line+4;
#ifdef DEBUG
if (strlen(*cmdline_p))
printk("Command line: '%s'\n", *cmdline_p);
#endif
 
*memory_start_p = memory_start;
#ifdef CONFIG_CYVH
*memory_end_p = (unsigned long)&stackbase;
#endif
}
 
/* set up for i960 */
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)
{
*year = *mon = *day = *hour = *min = *sec = 0;
}
/kernel/head.c
0,0 → 1,46
/*
* FILE: head.c
* AUTHOR: kma
* DESCR: Initialization code for the i960.
*/
 
#ident "$Id: head.c,v 1.1.1.1 2001-09-10 07:43:56 simons Exp $"
 
#include <linux/autoconf.h>
#include <linux/kernel.h>
 
/*
* So here we are! Running at ipl 31, in supervisor mode, on mon960's user
* stack. Do we need to do much here? Let's just get right into start_kernel.
*/
 
int main(void)
{
long oldac;
 
extern void start_kernel(void);
 
/* 64-bit math routines need the overflow mask bit set */
__asm__ __volatile__
("modac %1, %1, %1" : "=r"(oldac) : "0"(1 << 12));
 
/* Make the i960 think it's in an interrupt handler. This has the effect
* of not switching to the interrupt stack for every interrupt. Of
* course, we wouldn't need this if there were a sensible way of
* specifying an interrupt stack short of reinitializing the CPU, but
* such is life.
*
* XXX: this has the effect of using user stacks for interrupts too.
* The world's a scary place.
*/
__asm__ __volatile__ ("modpc %1, %1, %1" : "=r"(oldac) : "0"(1<<13));
#ifdef CONFIG_CMDLINE_PROMPT
/* do crazy command-line obtainments... */
#endif
 
start_kernel();
printk("XXX: start_kernel returned!!!\n");
for(;;) ;
}
/kernel/bios32.c
0,0 → 1,149
/*
* Copyright (C) 1999 Keith Adams <kma@cse.ogi.edu>
* Oregon Graduate Institute
*
* Bios and PCI stuff.
*/
 
#include <linux/pci.h>
#include <linux/bios32.h>
#include <linux/config.h>
#include <linux/kernel.h>
#include <asm/system.h>
 
unsigned long bios32_init(unsigned long memory_start, unsigned long memory_end)
{
return memory_start;
}
 
unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end)
{
return memory_start;
}
 
unsigned long pcibios_fixup(unsigned long memory_start, unsigned long memory_end)
{
return memory_start;
}
 
#ifdef CONFIG_MON960
 
#include <asm/mon960.h>
 
/*
* mon960 system calls for pci management
*/
extern int mon960_pcibios_present(void* info);
extern int mon960_pcibios_find_device(int vendor, int dev, int idx, void* loc);
extern int mon960_pcibios_find_class(int class, int idx, void* dev);
 
int pcibios_present(void)
{
return 1;
}
 
int pcibios_find_device(unsigned short vendor, unsigned short dev,
unsigned short index, unsigned char* bus,
unsigned char* dev_fn)
{
pci_dev_info loc;
int status;
 
if ((status=mon960_pcibios_find_device(vendor, dev, index, &loc)))
return -1;
 
printk("PCI device found: %x, %x, %x\n", loc.bus, loc.dev, loc.fn);
*bus = loc.bus;
*dev_fn = loc.dev;
return 0;
}
 
int pcibios_find_class(unsigned int class, unsigned short idx,
unsigned char* bus, unsigned char* dev_fn)
{
pci_dev_info loc;
int status;
if ((status=mon960_pcibios_find_class(class, idx, &loc)))
return -1;
 
*bus = loc.bus;
*dev_fn = loc.dev;
return 0;
}
 
#define CONFIG_RDWR(op,sz,type) \
int pcibios_ ## op ## _config_ ## sz(unsigned char bus, unsigned char fn, \
unsigned char offset, type val) \
{ \
return mon960_pcibios_ ## op ## _config_ ## sz(bus, fn, 0, offset, val); \
}
 
CONFIG_RDWR(read,byte,unsigned char*);
CONFIG_RDWR(read,word,unsigned short*);
CONFIG_RDWR(read,dword,unsigned int*);
CONFIG_RDWR(write,byte,unsigned char);
CONFIG_RDWR(write,word,unsigned short);
CONFIG_RDWR(write,dword,unsigned int);
 
#endif /* CONFIG_MON960 */
 
/*
* Dealing with the ATU. We just do all accesses translated; checking
* whether we can directly use the address might not be any faster.
*/
 
/* external address = (local address & 0x03ffffff) | ATU_OMWVR */
#define OIOW_BASE 0x90000000UL /* outbound I/O space window */
#define ATU_OIOWVR ((unsigned long*) 0x125c) /* I/O window val */
 
/* Set up ATU, return local address to use */
static unsigned long program_atu(unsigned long pciaddr)
{
unsigned long retval;
unsigned long pci_hibits = pciaddr & 0xfc000000;
*ATU_OIOWVR = pci_hibits;
retval = (pciaddr & 0x03ffffff) | OIOW_BASE;
return retval;
}
 
/* Note that we synchronize ATU access with the ipl.
*
* XXX: diddling the ipl every time seems to be a performance problem. Is
* there any way to use the i960 hardware in just one memory op, instead of
* two?
*/
 
#define READ_OP(type,name) \
type name(char* addr) \
{ \
volatile type *local_addr; \
type retval; \
unsigned long oldatu = *ATU_OIOWVR; \
local_addr = (volatile type*) \
program_atu((unsigned long)addr); \
retval = *local_addr; \
*ATU_OIOWVR = oldatu; \
return retval; \
}
READ_OP(unsigned char,readb)
READ_OP(unsigned short,readw)
READ_OP(unsigned int,readl)
#undef READ_OP
 
#define WRITE_OP(type,name) \
type name(type val, char* addr) \
{ \
volatile type *local_addr; \
type retval; \
unsigned long oldatu = *ATU_OIOWVR; \
local_addr = (volatile type*) \
program_atu((unsigned long)addr); \
retval = *local_addr = val; \
*ATU_OIOWVR = oldatu; \
return retval; \
}
WRITE_OP(unsigned char,writeb)
WRITE_OP(unsigned short,writew)
WRITE_OP(unsigned int,writel)
#undef WRITE_OP
/kernel/console.c
0,0 → 1,2523
 
/*
* arch/i960/kernel/console.c
*
* Copyright (C) 1999 Keith Adams <kma@cse.ogi.edu>
* Oregon Graduate Institute
*
* based on
* 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>
*
*/
 
#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)
{
}
 
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;
}
/kernel/prcb.S
0,0 → 1,103
#include <linux/linkage.h>
/* initial PRCB */
 
.globl _prcb
.align 4 /* or .align 2 */
 
_prcb:
.word boot_flt_table # 0 - Fault Table
.word _boot_control_table # 4 - Control Table
.word 0x00001000 # 8 - AC reg mask overflow fault
.word 0x40000001 # 12 - Flt CFG- Allow Unaligned
.word boot_intr_table # 16 - Interrupt Table
.word sys_proc_table # 20 - System Procedure Table
.word 0 # 24 - Reserved
.word _intr_stack # 28 - Interrupt Stack Pointer
.word 0x00000000 # 32 - Inst. Cache - enable cache
.word 0x5 # 36 - Register Cache Config.- 5 sets cached
 
/* ROM system procedure table */
 
.equ supervisor_proc, 2
.text
.align 6 /* or .align 2 or .align 4 */
 
sys_proc_table:
.space 12 # Reserved
.word _supervisor_stack # Supervisor stack pointer
.space 32 # Preserved
.word SYMBOL_NAME(system_call) # sysproc 0
.space 258*4 # sysproc 1-258
 
/* Fault Table */
 
.equ syscall, 2
.equ fault_proc, 7
.text
.align 4
 
boot_flt_table:
 
.word (fault_proc<<2) + syscall # 0-Parallel Fault
.word 0x27f
.word (fault_proc<<2) + syscall # 1-Trace Fault
.word 0x27f
.word (fault_proc<<2) + syscall # 2-Operation Fault
.word 0x27f
.word (fault_proc<<2) + syscall # 3-Arithmetic Fault
.word 0x27f
.word (fault_proc<<2) + syscall # 4-Reserved
.word 0x27f
.word (fault_proc<<2) + syscall # 5-Constraint Fault
.word 0x27f
.word (fault_proc<<2) + syscall # 6-Reserved
.word 0x27f
.word (fault_proc<<2) + syscall # 7-Protection Fault
.word 0x27f
.word (fault_proc<<2) + syscall # 8-Reserved
.word 0x27f
.word (fault_proc<<2) + syscall # 9-Reserved
.word 0x27f
.word (fault_proc<<2) + syscall # 0xa-Type Fault
.word 0x27f
.space 21*8 # reserved
 
/* Boot Interrupt Table */
 
.text
 
boot_intr_table:
 
.word 0
.word 0, 0, 0, 0, 0, 0, 0, 0
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
.word _intr, _intr, _intr, _intr, _intr, _intr, _intr, _intr
/kernel/mon960_calls.c
0,0 → 1,56
/*
* FILE: mon960_calls.c
* AUTHOR: kma
* DESCR: system calls to mon960
*/
 
#ident "$Id: mon960_calls.c,v 1.1.1.1 2001-09-10 07:43:56 simons Exp $"
 
#include <linux/config.h>
#include <asm/mon960.h>
 
#define SYSCALL(number) \
asm("calls %0; ret" \
: : "lI"(number): "g0");
 
unsigned long mon_entry(void)
{
SYSCALL(254);
}
 
unsigned long get_prcbptr(void)
{
SYSCALL(245);
}
 
void mon960_exit(int val)
{
SYSCALL(257);
}
 
#ifdef CONFIG_PCI
 
int mon960_pcibios_present(void* info)
{ SYSCALL(100); }
int mon960_pcibios_find_device(int vnd, int dev, int idx, void* loc)
{ SYSCALL(101); }
int mon960_pcibios_find_class(int class, int idx, void* dev)
{ SYSCALL(102); }
 
#define BIOS_OP(op,sz,type,nr) \
int \
mon960_pcibios_ ## op ## _config_ ##sz(unsigned short vec, \
unsigned short dev, \
unsigned short func, \
unsigned char off, \
type val) \
{ SYSCALL(nr); }
 
BIOS_OP(read,byte,unsigned char*,104)
BIOS_OP(read,word,unsigned short*,105)
BIOS_OP(read,dword,unsigned int*,106)
BIOS_OP(write,byte,unsigned char,107)
BIOS_OP(write,word,unsigned short,108)
BIOS_OP(write,dword,unsigned int,109)
 
#endif
/kernel/ksyms.c
0,0 → 1,69
#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/setup.h>
#include <asm/pgtable.h>
#include <asm/irq.h>
#include <asm/semaphore.h>
 
asmlinkage long long __ashrdi3 (long long, int);
extern char m68k_debug_device[];
 
#ifdef CONFIG_ATARI
extern void mach_atari_syms_export (void);
#endif
#ifdef CONFIG_AMIGA
extern void mach_amiga_syms_export (void);
#endif
#ifdef CONFIG_MAC
extern void mach_mac_syms_export (void);
#endif
 
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(boot_info),
X(m68k_is040or060),
X(cache_push),
X(cache_push_v),
X(cache_clear),
X(mm_vtop),
X(mm_ptov),
X(mm_end_of_chunk),
X(kernel_map),*/
/*X(m68k_debug_device),*/
X(request_irq),
X(free_irq),
X(dump_fpu),
X(dump_thread),
X(strnlen),
X(strstr),
 
/* 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(__ashrdi3),
XNOVERS(memcpy),
XNOVERS(memset),
 
#include <linux/symtab_end.h>
};
 
void arch_syms_export(void)
{
register_symtab(&arch_symbol_table);
 
/*our_syms_export()*/
}
/kernel/mon960-head.S
0,0 → 1,35
/* mon960 head.S code: should be extremely simple, since mon960 takes care
of almost all our requirements for us. We're at ipl 31 (highest),
interrupts are off, we have a C stack frame set up for us, etc.
This is modelled after the alpha head.S (excerpt below), which
actually does some other cruft before calling start_kernel, but without
knowning the alpha instruction set I can't tell for sure what's
happening.
 
For now I'll stick with just a call, as it seems to work in other
places.
 
alpha head.S:
__start:
br $27,1f
1: ldgp $29,0($27)
lda $27,start_kernel
jsr $26,($27),start_kernel
halt
.end __start
*/
 
 
#define __ASSEMBLY__
#include <asm/system.h>
 
.align 4
.globl _stext
.globl __start
.ent __start
 
_stext:
__start:
call start_kernel
halt
.end __start
/kernel/mon960_console.c
0,0 → 1,181
/*
* FILE: mon960_console.c
* AUTHOR: kma
* DESCR: serial console for TI's 16552 serial controller
*/
 
#ident "$Id: mon960_console.c,v 1.1.1.1 2001-09-10 07:43:56 simons Exp $"
 
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/major.h>
#include <linux/interrupt.h>
#include <asm/system.h>
#include <asm/delay.h>
 
#define SER16552_LSR ((volatile unsigned char*)0xe0000014) /* line status */
#define SER16552_THR ((volatile unsigned char*)0xe0000000) /* send fifo */
#define SER16552_RBR ((volatile unsigned char*)0xe0000000) /* rcv fifo */
#define SER16552_IER ((volatile unsigned char*)0xe0000004) /* int enable */
 
#define LSR_READY 1
#define LSR_SEND_READY 0x20
#define LSR_RECEIVE_READY 0x1
#define LSR_BREAK (1 << 4)
 
#define IER_RCV_ENABLE 1
#define IER_SEND_ENABLE 2
 
static int console_refcount;
static struct tty_struct *console_table[1];
static struct termios *console_termios[1];
static struct termios *console_termios_locked[1];
static struct tty_driver console_driver;
 
/*
* The interrupt for the 16552; should only happen for reads
*/
void do_16552_intr(void)
{
unsigned char buf[16];
int ii;
struct tty_struct *tty = console_table[0];
unsigned long lsr;
 
/* Drain the fifo into the tty */
for (ii=0; (lsr = *SER16552_LSR) & LSR_RECEIVE_READY; ii++) {
/* If there was a break, enter the debugger */
#ifdef CONFIG_MON960
char garbage;
if (lsr & LSR_BREAK) {
extern void system_break(void);
system_break();
garbage = *SER16552_RBR;
ii--;
}
else
#endif
buf[ii] = *SER16552_RBR;
}
 
if (ii)
tty->ldisc.receive_buf(tty, buf, 0, ii);
}
 
#if 0
static void do_16552_bh(void)
{
printk("in 16552 bottom half!\n");
printk("umm... yeah.\n");
}
#endif
 
static inline void putc_16552(char c, int blocking)
{
unsigned long flags;
 
save_flags(flags);
cli();
top:
while (!(*SER16552_LSR & LSR_SEND_READY)) {
udelay(1000);
}
*SER16552_THR = c;
if (c == '\n') {
c = '\r';
goto top;
}
restore_flags(flags);
}
 
void console_print_mon960(const char* msg)
{
long flags;
char c;
save_flags(flags);
cli();
while (c = *msg++)
putc_16552(c, 0);
 
restore_flags(flags);
}
 
/*
* XXX: make this interrupt driven if it's coming from the user
*/
static int con_write(struct tty_struct* tty, int from_user,
const unsigned char* buf, int count)
{
int ii = count;
while (ii--)
putc_16552(*buf++, from_user);
return count;
}
 
static int con_chars_in_buffer(struct tty_struct *tty)
{
return 0; /* we're not buffering */
}
 
static int con_writeroom(struct tty_struct *tty)
{
return 8192; /* could return anything */
}
 
static void con_putchar(struct tty_struct* tty, unsigned char c)
{
putc_16552(c, 0);
}
 
static int con_open(struct tty_struct* tty, struct file* filp)
{
return 0;
}
 
/*
* register our tty driver
*/
 
void mon960_console_init(void)
{
memset(&console_driver, 0, sizeof(console_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 = 1;
console_driver.type = TTY_DRIVER_TYPE_SERIAL;
console_driver.init_termios = tty_std_termios;
console_driver.init_termios.c_lflag |= ISIG | ICANON | ECHO
| ECHOE | ECHOK ;
console_driver.init_termios.c_iflag |= ICRNL;
console_driver.init_termios.c_cflag = CS8 | CREAD | CLOCAL;
console_driver.flags = TTY_DRIVER_REAL_RAW;
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.put_char = con_putchar;
console_driver.write_room = con_writeroom;
console_driver.chars_in_buffer = con_chars_in_buffer;
 
if (tty_register_driver(&console_driver)) {
printk("Couldn't register console driver\n");
}
/*
* Enable receive interrupts
*/
*SER16552_IER = IER_RCV_ENABLE;
 
}
/kernel/syscall.c
0,0 → 1,260
/*
* FILE: syscall.c
* AUTHOR: kma
* DESCR: High-level system call path.
*/
 
#ident "$Id: syscall.c,v 1.1.1.1 2001-09-10 07:43:56 simons Exp $"
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/sem.h>
#include <linux/msg.h>
#include <linux/shm.h>
 
#include <asm/unistd.h>
#include <asm/cachectl.h>
#include <asm/dprintk.h>
#include <asm/mman.h>
 
#ifdef DEBUG
#define CHECK_STACK() \
do { \
unsigned long sp; \
\
__asm__ __volatile__("mov sp, %0" : "=r"(sp)); \
if (current->pid \
&& (!(sp > current->kernel_stack_page \
&& sp < (current->kernel_stack_page + PAGE_SIZE)))) \
panic("bad ksp: 0x%8x\ncurrent ksp: 0x%8x", sp, \
current->kernel_stack_page); \
} while(0)
#else
#define CHECK_STACK() \
do { } while (0)
#endif
 
extern void system_break(void);
extern int (*syscall_tab[])(int, int, int, int, int);
static int sys_mmap(struct pt_regs* regs);
 
asmlinkage void
csyscall(struct pt_regs* regs)
{
unsigned long num = regs->gregs[13];
extern void stack_trace(void);
extern void leave_kernel(struct pt_regs* regs);
CHECK_STACK();
#if 0
if (user_mode(regs)) {
printk("syscall %d; pc == 0x%8x\n", num, get_pc());
stack_trace();
}
#endif
if (num >= 0 && num < __NR_nocall) {
switch(num) {
/*
* system calls that need the regs
*/
case __NR_fork:
case __NR_clone:
case __NR_execve:
case __NR_sigsuspend:
regs->gregs[0] = ((int (*)(int))(syscall_tab[num]))((int)regs);
break;
 
#ifdef DEBUG /* help debug user applications */
case __NR_dbg_break:
printk("break: %s\n", regs->gregs[0]);
system_break();
break;
 
case __NR_dbg_hexprint:
printk("value: %x\n", regs->gregs[0]);
break;
#endif
case __NR_mmap:
regs->gregs[0] = sys_mmap(regs);
#if 0
dprintk("mmap: returning 0x%8x\n",
regs->gregs[0]);
#endif
break;
 
default:
regs->gregs[0] =
syscall_tab[num](regs->gregs[0],
regs->gregs[1],
regs->gregs[2],
regs->gregs[3],
regs->gregs[4]);
break;
}
} else {
regs->gregs[0] = -ENOSYS;
}
#if 0
printk("csyscall: returning %p\n", regs->gregs[0]);
stack_trace();
#endif
leave_kernel(regs);
}
 
static int
sys_mmap(struct pt_regs* regs)
{
struct file* file = 0;
unsigned long flags = regs->gregs[3];
 
if (!(flags & MAP_ANON)) {
unsigned long fd = regs->gregs[4];
if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
return -EBADF;
}
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
return do_mmap(file, regs->gregs[0], regs->gregs[1], regs->gregs[2],
flags, regs->gregs[5]);
}
 
asmlinkage int
sys_fork(struct pt_regs* regs)
{
return do_fork(SIGCHLD|CLONE_WAIT, regs->lregs[PT_SP], regs);
}
 
asmlinkage int
sys_clone(struct pt_regs* regs)
{
dprintk("in sys_clone\n");
return do_fork(regs->gregs[0], regs->gregs[1], regs);
}
 
asmlinkage int
sys_execve(struct pt_regs* regs)
{
dprintk("sys_execve: %s, %p, %p\n",
regs->gregs[0], regs->gregs[1], regs->gregs[2]);
return do_execve((void*)regs->gregs[0], (void*)regs->gregs[1],
(void*)regs->gregs[2], regs);
}
 
asmlinkage int
sys_ioperm(unsigned long from, unsigned long num, int turn_on)
{
return -EINVAL;
}
 
asmlinkage int
sys_ipc (uint call, int first, int second, int third, void* ptr, long fifth)
{
int version;
version = call >> 16;
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 = (void *) get_fs_long(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_fs_long (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_cacheflush(char* addr, int nbytes, int cache)
{
if (cache & ICACHE)
__asm__ __volatile__ ("icctl 2, g0, g0");
if (cache & DCACHE)
__asm__ __volatile__ ("dcctl 2, g0, g0");
 
return 0;
}
 
void
kthread_start(void (*func)(void*), void* arg)
{
extern long _etext, _stext;
CHECK_STACK();
if ( ((unsigned long)func > (unsigned long)&_etext)
|| ((unsigned long)func < (unsigned long)&_stext) ) {
panic("XXX: bad kthread addr: %p\n", func);
}
func(arg);
}
/kernel/signal.c
0,0 → 1,251
/*
* linux/arch/i960/kernel/signal.c
*
* Copyright (C) 1999 Keith Adams <kma@cse.ogi.edu>
* Oregon Graduate Institute
*
* Based on:
*
* linux/arch/m68k/kernel/signal.c
*
* Copyright (C) 1991, 1992 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 <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/setup.h>
#include <asm/segment.h>
#include <asm/pgtable.h>
#include <asm/traps.h>
 
 
#define _S(nr) (1<<((nr)-1))
 
#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
 
int do_signal(struct pt_regs *regs);
 
/*
* atomically swap in the new signal mask, and wait for a signal.
*/
asmlinkage int do_sigsuspend(struct pt_regs* regs)
{
int err;
sigset_t* set = (sigset_t*) regs->gregs[0];
unsigned long mask;
 
if ((err=verify_area(VERIFY_READ, set, 4)))
return -EINTR;
 
mask = current->blocked;
current->blocked = *set & _BLOCKABLE;
regs->gregs[0] = -EINTR;
for (;;) {
current->state = TASK_INTERRUPTIBLE;
schedule();
if (do_signal(regs))
return -EINTR;
}
}
 
/*
* We don't ever need this on i960; the function return path lets setup_frame
* return straight to the faulting instruction.
*/
asmlinkage int do_sigreturn(unsigned long __unused)
{
printk("killing %d for trying to sigreturn\n");
do_exit(SIGSEGV);
return -1;
}
 
#define STACK_ALIGN 16
static inline unsigned long stack_align(unsigned long sp)
{
int lobits = sp & (STACK_ALIGN -1);
 
if (sp & lobits)
sp += STACK_ALIGN - lobits;
return sp;
}
 
/*
* 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.
*
* XXX: todo: sigcontext stuff.
*/
 
asmlinkage int do_signal(struct pt_regs *regs)
{
unsigned long mask = ~current->blocked;
unsigned long handler_signal = 0;
unsigned long signr;
struct sigaction * sa;
 
while ((signr = current->signal & mask)) {
signr = ffz(~signr);
clear_bit(signr, &current->signal);
sa = current->sig->action + signr;
signr++;
if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
current->exit_code = signr;
current->state = TASK_STOPPED;
notify_parent(current, signr);
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;
/* SIGCHLD is special */
while (sys_waitpid(-1,0,WNOHANG) > 0)
;
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, signr);
schedule();
continue;
 
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGIOT: case SIGFPE: case SIGSEGV: case SIGBUS:
if (current->binfmt && current->binfmt->core_dump) {
if (current->binfmt->core_dump(signr, regs))
signr |= 0x80;
}
/* fall through */
default:
current->signal |= _S(signr & 0x7f);
current->flags |= PF_SIGNALED;
do_exit(signr);
}
}
/*
* OK, we're invoking a handler
*/
#ifdef DEBUG
printk("user-specified handler for signal: %d\n", signr);
#endif
handler_signal |= 1 << (signr-1);
mask &= ~sa->sa_mask;
}
if (! handler_signal)
return 0;
/*
* We chain user frames for the various handlers together. Since we use
* local regs to pass parameters, all RIPs go to the asm routine
* signal_head found in entry.S; if we were an MMU-full system, we would
* have to copy signal_head out to the user process's stack.
*/
{
extern void signal_head(void);
struct frame {
unsigned long pfp;
unsigned long sp;
unsigned long rip;
unsigned long* args[13];
} *userframe, *newframe;
unsigned long type;
 
#ifdef DEBUG
stack_trace();
#endif
asm("flushreg");
type = regs->lregs[PT_PFP] & 0x7;
#ifdef DEBUG
printk("pfp, type: 0x%8x, 0x%8x\n", regs->lregs[PT_PFP], type);
#endif
userframe = (struct frame*)
(((unsigned long) regs->lregs[PT_PFP]) & ~0x7);
#ifdef DEBUG
printk("userframe: 0x%8x\n", userframe);
stack_trace_from((unsigned long) userframe);
#endif
 
for (sa=current->sig->action, signr=1, mask=1;
mask;
sa++, signr++, mask<<=1) {
if (mask > handler_signal)
break;
if ((!(mask & handler_signal)) || (!sa->sa_handler))
continue;
#ifdef DEBUG
printk("userframe->rip: 0x%8x\n", userframe->rip);
#endif
newframe = stack_align(userframe->sp);
newframe->rip = (unsigned long) signal_head;
newframe->args[0] = (unsigned long) sa->sa_handler;
newframe->args[1] = signr;
#ifdef DEBUG
printk("r3,r4: 0x%8x, %d\n", sa->sa_handler, signr);
#endif
newframe->pfp = (unsigned long) userframe;
newframe->sp = (unsigned long)(newframe) + 64;
userframe = newframe;
}
#ifdef DEBUG
printk("done; look:\n");
stack_trace();
#endif
regs->lregs[PT_PFP] = (unsigned long)userframe | type;
asm("flushreg");
/*
* appropriate syscalls should return EINTR
*/
if ((type & 6) == 2 &&
(regs->gregs[0] == -ERESTARTNOHAND ||
regs->gregs[0] == -ERESTARTSYS ||
regs->gregs[0] == -ERESTARTNOINTR))
regs->gregs[0] = -EINTR;
}
 
return 1;
}
/kernel/ints.c
0,0 → 1,455
/*
* linux/arch/i960/kernel/ints.c
*
* Copyright (C) 1999 Keith Adams <kma@cse.ogi.edu>
* Oregon Graduate Institute
*
* Based on:
*
* linux/arch/i386/kernel/irq.c
*
* Copyright (C) 1992 Linux 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.
*
* N.B. that we treat "irq" as meaning, the high order four bits of the vector
* number. Since there seems to be no way to set the low bits to something other
* than 0010, this is good enough for us.
*/
 
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/kernel_stat.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/config.h>
#include <linux/ip.h>
#include <linux/tcp.h>
 
#include <asm/atomic.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/traps.h>
#include <asm/page.h>
#include <asm/ptrace.h>
#include <asm/machdep.h>
#include <asm/i960.h>
#include <asm/unistd.h>
 
#if defined(CONFIG_I960JX) || defined(CONFIG_I960VH)
#include <asm/i960jx.h>
#endif
 
/*
* device vectors; the *_HO macros are the corresponding indices into the
* low-mem isr table
*/
#define NMI_VEC 248
 
#define LED ((unsigned char*)0xe0040000)
#define LED_THRESHOLD (HZ/2)
 
#define TMR0_VEC_HO 0xd
#define TMR1_VEC_HO 0xe
#define XINT0_VEC_HO 1
#define XINT1_VEC_HO 2
#define XINT2_VEC_HO 3
#define XINT3_VEC_HO 4
#define XINT4_VEC_HO 5
#define XINT5_VEC_HO 6
#define XINT6_VEC_HO 7
#define XINT7_VEC_HO 8
 
static char* irq_names[] = {
0, /* 0 */
"xint0",
"xint1",
"xint2",
"xint3",
"serial",
"xint5",
"xint6",
"xint7",
0, 0, 0, 0,
"timer0",
"timer1",
0,
};
 
#ifdef CONFIG_PROF_IRQ
static struct irqstat {
unsigned long min;
unsigned long avg;
unsigned long max;
} irqstat[16];
#endif
 
static void* pci_dev;
static const char* pci_name;
static void (*pci_isr)(int, void *, struct pt_regs *);
 
#define __VEC(ho) (((ho) << 4) | 2)
#define TMR0_VEC __VEC(TMR0_VEC_HO)
#define TMR1_VEC __VEC(TMR1_VEC_HO)
#define XINT0_VEC __VEC(XINT0_VEC_HO)
#define XINT1_VEC __VEC(XINT1_VEC_HO)
#define XINT2_VEC __VEC(XINT2_VEC_HO)
#define XINT3_VEC __VEC(XINT3_VEC_HO)
#define XINT4_VEC __VEC(XINT4_VEC_HO)
#define SERIAL_VEC XINT4_VEC
#define PCI_VEC XINT1_VEC
#define XINT5_VEC __VEC(XINT5_VEC_HO)
#define XINT6_VEC __VEC(XINT6_VEC_HO)
#define XINT7_VEC __VEC(XINT7_VEC_HO)
 
 
void leave_kernel(struct pt_regs* regs);
static void nmi_intr(void);
static void bad_intr(unsigned char vec, struct pt_regs* regs);
static void xint(unsigned char ho, struct pt_regs* regs);
void stack_trace(void);
 
extern void intr(void);
static void program_clock(void);
 
#ifdef CONFIG_MON960
#include <asm/i960jx.h>
#include <asm/mon960.h>
 
static unsigned long get_mon960_serial_isr(void)
{
prcb_t* prcb = (prcb_t*)get_prcbptr();
unsigned long vec = (*(unsigned long*)IMAP1 & 0x0f00) >> 8;
/* on cyclone, serial isr is XINT5 */
return (unsigned long) prcb->pr_intr_tab->i_vectors[vec];
}
 
#endif
 
static void init_syscalls(void)
{
unsigned long** prcb = (unsigned long**)get_prcbptr();
unsigned long* syscall_tab = prcb[5];
extern void syscall(void);
/* we only use syscall 0, which is 12 words from the start of
* the syscall table. The entry type field of 0x2 indicates a call
* to supervisor mode. */
syscall_tab[12] = ((unsigned long) syscall) | 0x2;
return;
}
 
/*
* At entry here, we have a high ipl. We need to establish
* our isr's, and enable the clock.
*/
void init_IRQ(void)
{
unsigned long *dram = 0;
int ii;
 
/* set up the following layout in low RAM for our 15 vectors:
* 0: NMI (we have no choice about this)
* 1-8: XINT0-7
* 9-12: Invalid
* 13: Timer0. Note that Timer1 is disabled.
* 14-15: Invalid.
*
* This works out nicely, since the vector number-1 is the
* corresponding bit in IMSK; see disable_irq below.
*/
atmod((void*)IMAP0, 0xffff, 0x4321); /* xint 0-3 */
atmod((void*)IMAP1, 0xffff, 0x8756); /* xint 4-7 */
atmod((void*)IMAP2, 0xff<<16, 0xed << 16); /* Timer 0, Timer 1 */
 
/* we vector all interrupts through intr */
for (ii=0; ii < 16; ii++)
dram[ii] = (unsigned long)intr;
#ifdef CONFIG_MON960
/* reset the XINT5 interrupt handler from software */
dram[XINT5_VEC_HO] = get_mon960_serial_isr();
#endif
program_clock();
/* set 13th bit of ICON; enable vector caching */
atmod((void*)ICON, 1<<13, 1<<13);
/*
* XXX: what to mask is somewhat board dependent; we leave XINT4
* masked because Cyclone needs it to always be masked.
*/
atmod((void*)IPND, ~0, 0);
atmod((void*)IMSK, 0x30ef, 0x30ef);
/* Now set up syscalls */
init_syscalls();
}
 
#define TRR0 (volatile unsigned long*)0xff000300
#define TCR0 (volatile unsigned long*)0xff000304
#define TMR0 (volatile unsigned long*)0xff000308
 
#define TRR1 (volatile unsigned long*)0xff000310
#define TCR1 (volatile unsigned long*)0xff000314
#define TMR1 (volatile unsigned long*)0xff000318
/* some helper macros for programming the mode register, TMR0 */
 
/* the clock may decrement once per cpu cycle, once every two cycles, ...
* up to eight; set the appropriate bits in TMR0
*/
#define CLOCKSHIFT 4
#define CLOCKDIV(x) (x << CLOCKSHIFT)
#define CLOCKDIV1 CLOCKDIV(0)
#define CLOCKDIV2 CLOCKDIV(1)
#define CLOCKDIV4 CLOCKDIV(2)
#define CLOCKDIV8 CLOCKDIV(3)
 
#define CLOCK_ENABLE 2 /* set for clock to work */
#define CLOCK_AUTO_RELOAD 4 /* reload from TRR0 when we reach 0 */
#define CLOCK_SUPER_ONLY 8 /* don't let users reprogram clocks */
 
/*
* Set up timer 0 to interrupt us every so many clocks. Assumes
* interrupts are disabled.
*/
static void
program_clock(void)
{
/* 33Mhz PCI Bus assumed */
#define CYCLES_PER_HZ (33 * 1000* 1000) / HZ
*TRR0 = *TCR0 = CYCLES_PER_HZ;
*TMR0 = CLOCKDIV1 | CLOCK_ENABLE | CLOCK_AUTO_RELOAD | CLOCK_SUPER_ONLY;
#ifdef CONFIG_PROF_IRQ
disable_irq(TMR1_VEC_HO);
#endif
}
 
irq_node_t *new_irq_node(void)
{
/* XXX: write me */
return NULL;
}
 
int request_irq(unsigned int irq,
void (*handler)(int, void *, struct pt_regs *),
unsigned long flags, const char *devname, void *dev_id)
{
/* XXX: this is a stopgap; we only can handle one pci device */
if (pci_dev)
return -1;
 
pci_dev = dev_id;
pci_name = devname;
pci_isr = handler;
return 0;
}
 
void free_irq(unsigned int irq, void *dev_id)
{
pci_dev = 0;
}
 
/*
* Do we need these probe functions on the i960?
*/
unsigned long probe_irq_on (void)
{
return 0;
}
 
int probe_irq_off (unsigned long irqs)
{
return 0;
}
 
void disable_irq(unsigned int irq)
{
if (irq && irq < SYS_IRQS)
atmod((void*)IMSK, 1<<(irq-1), 0);
}
 
void enable_irq(unsigned int irq)
{
if (irq && irq < SYS_IRQS)
atmod((void*)IMSK, 1<<(irq-1), 1<<(irq-1));
}
 
#ifdef CONFIG_PROF_IRQ
#define SAMPLE_BITS 7
static inline void
update_prof_timers(int vec, unsigned long ticks)
{
struct irqstat* irq;
vec = vec >> 4;
irq = irqstat + vec;
 
if (!irq->avg) {
irq->max = ticks;
irq->min = ticks;
irq->avg = ticks;
return;
}
 
if (ticks < irq->min)
irq->min = ticks;
if (ticks > irq->max)
irq->max = ticks;
irq->avg -= irq->avg >> SAMPLE_BITS;
irq->avg += ticks >> SAMPLE_BITS;
}
#endif
 
/*
* Interrupt service routine. N.B. that XINT0, which is really a system call,
* is never routed to cintr; it ends up in syscall instead.
*/
extern void do_signal(void);
asmlinkage void cintr(unsigned char vec, struct pt_regs* regs)
{
extern void timer_interrupt(struct pt_regs* regs);
static int ticks;
#ifdef CONFIG_PROF_IRQ
unsigned long clocks;
*TCR1 = CYCLES_PER_HZ * HZ;
*TMR1 = CLOCKDIV1 | CLOCK_ENABLE;
#endif
atomic_inc(&intr_count);
kstat.interrupts[vec >> 4]++;
switch(vec) {
case NMI_VEC:
nmi_intr();
break;
 
case XINT1_VEC:
case XINT0_VEC:
case XINT2_VEC:
case XINT3_VEC:
case XINT4_VEC:
case XINT5_VEC:
case XINT6_VEC:
case XINT7_VEC:
xint(vec, regs);
break;
case TMR0_VEC:
if ((++ticks) >= LED_THRESHOLD) {
static char nm = 0;
*LED = ~ (1 << (nm++ % 8));
ticks = 0;
}
timer_interrupt(regs);
break;
default:
bad_intr(vec, regs);
break;
}
atomic_dec(&intr_count);
if (!intr_count)
leave_kernel(regs);
 
#ifdef CONFIG_PROF_IRQ
clocks = CYCLES_PER_HZ*HZ - *TCR1;
update_prof_timers(vec, clocks);
#endif
return;
}
 
/*
* Common code to interrupt and syscall paths. When leaving the kernel, and not
* returning to an interrupt context, do a whole bunch of processing.
*
* Note that if we're called from cintr, we're running at high ipl.
*
* Run the bottom half, check if scheduling is needed, and deliver signals to
* the current process, just as in every other architecture.
*/
void leave_kernel(struct pt_regs* regs)
{
bh:
if (bh_mask & bh_active) {
atomic_inc(&intr_count);
do_bottom_half();
atomic_dec(&intr_count);
}
sti();
if (user_mode(regs)) {
if (need_resched) {
schedule();
goto bh;
}
 
 
if (current->signal & ~current->blocked) {
do_signal();
}
}
}
 
static void nmi_intr(void)
{
/* XXX: write me */
}
 
static void bad_intr(unsigned char vec, struct pt_regs* regs)
{
/* XXX: write me */
printk("whoah! bad intr: %x\n", vec);
}
 
static void xint(unsigned char vec, struct pt_regs* regs)
{
/*
* This basically shouldn't happen
*/
#ifdef CONFIG_MON960_CONSOLE
if (vec == SERIAL_VEC) {
extern void do_16552_intr(void);
do_16552_intr();
return;
}
#endif
#ifdef CONFIG_PCI
if (vec == PCI_VEC && pci_dev) {
pci_isr(0, pci_dev, regs);
return;
}
#endif
printk("EEP: xint %x\n", vec);
stack_trace();
}
 
int get_irq_list(char *buf)
{
int len = 0;
int ii;
for (ii=0; ii < 16; ii++) {
if (irq_names[ii]) {
#ifdef CONFIG_PROF_IRQ
len += sprintf(buf+len, "%d\t%s\t(%08x, %08x, %08x)\n",
kstat.interrupts[ii],
(ii==2 && pci_dev)
? pci_name
: irq_names[ii],
irqstat[ii].min, irqstat[ii].avg,
irqstat[ii].max);
#else
len += sprintf(buf+len, "%d\t%s\n",
kstat.interrupts[ii],
(ii==2 && pci_dev)
? pci_name
: irq_names[ii]);
#endif
}
}
return len;
}
 
/kernel/ptrace.c
0,0 → 1,104
/*
* linux/arch/i960/kernel/ptrace.c
*
* Copyright (C) 1998 Keith Adams <kma@cse.ogi.edu>
* Oregon Graduate Institute
*
* 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.
*/
 
/*
* XXX: unimplemented
*/
#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>
 
/* 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)
{
return -1;
}
 
/*
* Write contents of register REGNO in task TASK.
*/
static inline int put_reg(struct task_struct *task, int regno,
unsigned long data)
{
return -1;
}
 
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)
{
return -1;
}
 
asmlinkage void syscall_trace(void)
{
}
/kernel/process.c
0,0 → 1,302
/*
* linux/arch/i960/kernel/process.c
*
* Copyright (C) 1999 Keith Adams <kma@cse.ogi.edu>
* Oregon Graduate Institute
*
* Based on:
*
* linux/arch/m68k/kernel/process.c
*
* Copyright (C) 1995 Hamish Macdonald
*
*/
 
/*
* This file handles the architecture-dependent parts of process handling..
*/
 
#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/setup.h>
#include <asm/dprintk.h>
 
extern void stack_trace(void);
extern void stack_trace_from(unsigned long sp);
 
asmlinkage void ret_from_exception(void);
 
/*
* The idle loop on an i960
*/
asmlinkage int sys_idle(void)
{
if (current->pid != 0)
return -EPERM;
 
sti();
/* endless idle loop with no priority at all */
current->counter = -100;
for (;;) {
__asm__ ("halt 2");
schedule();
}
}
 
static unsigned long
stack_align(unsigned long sp)
{
#define STACK_ALIGN 16 /* must be power of 2 */
if ((unsigned long) sp & (STACK_ALIGN-1)) {
(unsigned long) sp += STACK_ALIGN;
(unsigned long) sp &= ~(STACK_ALIGN-1);
}
#undef STACK_ALIGN
return sp;
}
 
#ifdef CONFIG_MON960
#include <asm/mon960.h>
#endif
 
void hard_reset_now(void)
{
#ifdef CONFIG_MON960
cli();
mon960_exit(0);
#else
printk("ermm, I don't know how to reset. Sorry.\n");
#endif
}
 
void show_regs(struct pt_regs * regs)
{
int ii;
printk("\n");
printk("PC:\t%08lx\tAC:\t%08lx\n",
regs->pc, regs->ac);
printk("pfp:\t%08lx\tg0:\t%08lx\n",
regs->lregs[0], regs->gregs[0]);
printk("sp:\t%08lx\tg1:\t%08lx\n",
regs->lregs[1], regs->gregs[1]);
printk("rip:\t%08lx\tg2:\t%08lx\n",
regs->lregs[2], regs->gregs[2]);
for (ii=3; ii < 16; ii++)
printk("r%d:\t%08lx\tg%d\t%08lx\n", ii,
regs->lregs[ii], ii, regs->gregs[ii]);
}
 
void hex_dump(unsigned long start, int len)
{
char* c = (char*) start;
int ii;
#define CHARS_IN_LINE 16
for (ii=0; ii < len; ii++) {
if (! (ii & (CHARS_IN_LINE-1))) {
printk("\n%8x: ", start + ii);
}
printk("%2x ", c[ii]);
}
printk("\n");
}
 
/*
* Free current thread data structures etc..
*/
void exit_thread(void)
{
}
 
void flush_thread(void)
{
}
 
void release_thread(struct task_struct *dead_task)
{
}
 
void switch_to(struct task_struct* prev, struct task_struct* next)
{
if (next == prev)
return;
 
#if 0
dprintk("*** switch_to: new pfp: 0x%8x\n", next->tss.pfp);
dprintk("*** switch_to: old stack:\n");
stack_trace();
dprintk("*** switch_to: new stack:\n");
stack_trace_from(next->tss.pfp);
#endif
current_set[smp_processor_id()] = next;
__asm__ __volatile__
("st pfp, (%1)\n\t" /* save current pfp */
"flushreg\n\t"
"mov %2, pfp\n\t"
"flushreg\n\t"
: "=m" (prev->tss.pfp)
:"r" (&prev->tss.pfp), "r" (next->tss.pfp));
}
 
/*
* Called from the vfork path. We need to copy enough of the caller's kernel and
* user stacks to get the child out of the kernel, and back to the level where
* vfork was called. This is, I admit, somewhat heinous, and probably a longer
* code path than one would like.
*/
void copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
struct task_struct * p, struct pt_regs * regs)
{
struct pt_regs *childregs;
extern void syscall_return(void);
unsigned long new_ustack;
 
if (!regs)
return; /* kernel_thread hack */
 
asm("flushreg");
/*
* Setting up child's ustack: allocate it just below caller's ustack,
* copy in caller's ustack, and relocate sp's. When returning to the
* child, we skip the syscall_frame and go straight back to the caller
* frame.
*
* low addresses
* _______________
* | caller_frame |
* |_______________|
* | syscall_frame |
* |_______________|
* | child_caller_frame
* |_______________|
* ...
* _______________
* | regs | (top o' kernel stack)
* ...
*
* high addresses
*/
{
struct i960_frame *syscall_frame, *caller_frame;
struct i960_frame *child_caller_frame;
unsigned long frame_len, offset;
 
syscall_frame = (struct i960_frame*)
(regs->lregs[PT_PFP] & ~0xf);
caller_frame = (struct i960_frame*)syscall_frame->pfp;
dprintk("new_ustack: 0x%8x\n", syscall_frame->sp);
new_ustack = stack_align(syscall_frame->sp);
dprintk("new_ustack: 0x%8x\n", new_ustack);
child_caller_frame = (struct i960_frame*) new_ustack;
frame_len = caller_frame->sp - (unsigned long)(caller_frame);
dprintk("frame len: 0x%8x\n", frame_len);
memcpy((void*)new_ustack, caller_frame, frame_len);
 
offset = new_ustack - (unsigned long)caller_frame;
child_caller_frame->sp += offset;
/*
* XXX: you should never return from the function that called
* vfork; right now, you'll just walk off with a bad stack,
* but eventually we might want to catch this case and force
* an exit.
*/
child_caller_frame->pfp = 0;
}
 
/*
* We build a near-copy of the top frame of the caller's syscall stack
* in the child's kstack; the child's sp points to the child stack. Its
* pfp heads to the frame in the child's ustack that we created above.
*/
childregs = (struct pt_regs*)p->kernel_stack_page;
*childregs = *regs; /* bitwise copy */
childregs->lregs[PT_PFP] = new_ustack | 2; /* return to user */
childregs->lregs[PT_SP] = (unsigned long)(childregs + 1);
childregs->gregs[0] = 0; /* Child gets a retval of zero */
childregs->gregs[15] = (unsigned long) &childregs->lregs[0];
/* we reload the pfp from the thread struct in switch_to */
p->tss.pfp = (unsigned long)&childregs->lregs;
#ifdef DEBUG
dprintk("child stack:\n");
stack_trace_from(p->tss.pfp);
#endif
}
 
/* Fill in the fpu structure for a core dump. */
 
int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)
{
return 0;
}
 
/*
* fill in the user structure for a core dump..
*/
void dump_thread(struct pt_regs * regs, struct user * dump)
{
/* XXX: write this */
}
 
/*
* start a thread
*/
void start_thread(struct pt_regs * regs, unsigned long ip, unsigned long sp)
{
struct i960_frame* frame;
/* align the stack */
sp = stack_align(sp);
/*
* build a little stack frame at sp; start running
*/
frame = (struct i960_frame*) sp;
frame->sp = ((unsigned long)sp) + 16*4;
frame->rip = ip;
frame->pfp = 0;
#ifdef DEBUG
dprintk("before:\n");
stack_trace();
#endif
regs->lregs[PT_PFP] = (sp | 0x7); /* returning from interrupt */
regs->pc = (1<<13); /* bit 13: interrupted mode */
regs->ac = (1<<15) | (1<<12); /* bits 15 and 12: precise faults, no overflow interrupts */
/*
* g12 contains the "data" bias. the code expects text and data to
* be allocated contiguously, and g12 points to code. Since data/bss
* might be allocated separately from text, we point g12 at
* data_start - text_len
*/
regs->gregs[12] = current->mm->start_data -
(current->mm->end_code - current->mm->start_code);
regs->gregs[13] = current->mm->env_start - 12;
regs->gregs[14] = 0;
dprintk("set first arg: 0x%8x\n", regs->gregs[0]);
/* make memory coherent; the stack cache flush might be gratuitous */
asm("flushreg
dcctl 3, g0, g0
icctl 2, g0, g0");
#ifdef DEBUG
dprintk("set data seg to: 0x%8x\n", regs->gregs[12]);
dprintk("set start to %p\n", ip);
stack_trace();
#endif
}
 
/kernel/entry.S
0,0 → 1,358
/*
*
* linux/arch/m68knommu/kernel/entry.S
*
* Copyright (C) 1999 Keith Adams <kma@cse.ogi.edu>,
* Oregon Graduate Institute
*
*/
 
/*
* syscall, interrupt, and fault entry points
*/
 
#include <asm/i960.h>
#include <asm/unistd.h>
#define ALL_ONES 0xffffffff
 
#include <linux/sys.h>
#include <linux/config.h>
#include <linux/linkage.h>
#include <asm/setup.h>
#include <asm/segment.h>
#ifdef CONFIG_I960VH
#include <asm/i960jx.h>
#endif
 
 
.globl SYMBOL_NAME(atmod)
SYMBOL_NAME_LABEL(atmod)
atmod g0, g1, g2
mov g2, g0
ret
 
/*
* The birthplace of kernel threads. Once here, we find the function to call
* in register r3, and its argument in r4. See kernel_thread in asm/unistd.h
* for why this exists.
*/
.globl SYMBOL_NAME(kthread_trampoline)
SYMBOL_NAME_LABEL(kthread_trampoline)
mov r3, g0
mov r4, g1
call SYMBOL_NAME(kthread_start)
ldconst 0, g0
b SYMBOL_NAME(do_exit)
/* no ret */
 
/*
* signal handlers start here in signal_head.
*/
.globl SYMBOL_NAME(signal_head)
SYMBOL_NAME_LABEL(signal_head)
mov g0, r5
mov r4, g0
callx (r3)
mov r5, g0
ret
 
#define USER_AC 0x3b001000
#define USER_PC 0x00002000 /* bit 13 set: interrupted mode */
#define KSP_OFFSET 0x58
 
#if 0
#define CKPT(x,y) \
ldconst x, g0; \
mov y, g1; \
call SYMBOL_NAME(ckpt);
#endif
 
/* XXX: todo: emulate an interrupt: put PC and AC on stack */
/*
* This is branched to by intr and syscall; it switches to the kernel stack,
* and returns to the ip in r6. The choice of registers lets us economize
* on store operations.
*
* Be sure to branch here, rather than call; we can't use a single frame of
* the shared intr/syscall stacks.
*
* Observe weird register conventions (because we can't alter g* regs):
* ip after switch: r6
* r3 in new stack: r7 (for intr/fault)
* PC to be seen in new stack: r8
*/
.align 4
switch_to_kstack:
ld SYMBOL_NAME(current_set), r3
ld KSP_OFFSET(r3), r3
ldconst 64, r5
addo r3, r5, r3 # get some space on stack (for PC/AC)
/*
* r3 now points to the address of the new stack frame. We build an image of
* the new stack frame in regs r4-r7. The intr needs to
* remember its intr vector, so we also put r7 on the stack, in the r3
* position.
*/
 
mov pfp, r4 # newframe->pfp = current pfp
addo r5, r3, r5 # newframe->sp = newframe + 64
# newframe->rip = rip (passed in r6)
# newframe->r3 = r7
stq r4, (r3)
 
/* Store AC, PC as if in interrupt context */
modac 0, 0, r9
stl r8, -16(r3) # current ac, pc passed in r8
flushreg
mov r3, pfp
flushreg
ret # returns to ip from r6
 
/*
* System calls all end up here.
*/
.globl SYMBOL_NAME(syscall)
.align 4
SYMBOL_NAME_LABEL(syscall)
/*
* first, examine pfp; if its 1st and 2nd bits are 1 and 0 respectively,
* we're coming from user mode, so we need to switch stacks.
*/
 
bbs 2, pfp, 1f # if bit 2 is set, we're cool
bbc 1, pfp, 1f # same if bit 1 is clear
/* uh-oh, we're coming from user mode: switch stacks */
lda 1f, r6
ldconst USER_PC, r8
b switch_to_kstack
 
1:
SAVE_ALL(r3)
subo 16, fp, g0
call SYMBOL_NAME(csyscall)
RESTORE_ALL(r3)
ret
 
/*
* This is the main interrupt handler; it is also the entry point for
* system calls.
*/
.globl SYMBOL_NAME(intr)
.align 4
SYMBOL_NAME_LABEL(intr)
ld -16(fp), r3
ldob -8(fp), r7
bbs 1, r3, 1f # if we're supervisor, forget it
/* uh-oh, switch stacks */
lda 2f, r6
mov r3, r8
b switch_to_kstack
 
1:
mov r7, r3
2:
/*
* by now we're on a valid stack, and the interrupt vector number is in
* r3.
*/
SAVE_ALL(r4)
mov r3, g0 # 1st arg is intr vector
flushreg # get regs on stack
subo 16, fp, g1 # 2nd arg is pointer to pt_regs
call SYMBOL_NAME(cintr)
RESTORE_ALL(r3)
ret # back to user-level
 
/*
* Again, if we're coming from user mode, switch to kstack. We get this info
* from the fault record, 16 bytes below the current fp. We play games similar
* to intr to hold onto the fault record...
*/
.globl SYMBOL_NAME(fault)
SYMBOL_NAME_LABEL(fault)
subo 16, fp, r7
ld (r7), r3 # r3 gets pc of faulting instr
bbs 1, r3, 1f # if it was a supervisor fault, don't switch
 
lda 2f, r6
ldconst USER_PC, r8
b switch_to_kstack
1:
mov r7, r3
2:
SAVE_ALL(r4)
mov r3, g0
subo 16, fp, g1
call SYMBOL_NAME(cfault)
RESTORE_ALL(r4)
ret
 
/*
* The table of system calls.
*/
.globl SYMBOL_NAME(syscall_tab)
SYMBOL_NAME_LABEL(syscall_tab)
.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(do_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(do_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(sys_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(sys_ni_syscall)
.long SYMBOL_NAME(sys_ni_syscall) /* 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(do_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)
/kernel/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
*/
 
#ident "$Id: semaphore.c,v 1.1.1.1 2001-09-10 07:43:56 simons Exp $"
#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);
}
 
 
/*
* 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);
}
 
/kernel/traps.c
0,0 → 1,251
/*
* linux/arch/i960/kernel/traps.c
*
* Copyright (C) 1999 Keith Adams <kma@cse.ogi.edu>
* Oregon Graduate Institute
*
* Based on:
*
* linux/arch/m68k/kernel/traps.c
*
* Copyright (C) 1993, 1994 by Hamish Macdonald
*
* 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.
*/
 
/*
* 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/setup.h>
#include <asm/system.h>
#include <asm/segment.h>
#include <asm/traps.h>
#include <asm/pgtable.h>
#include <asm/machdep.h>
#include <asm/i960jx.h>
#include <asm/mon960.h>
 
/* set fault handlers in fault table, syscall table */
void trap_init (void)
{
int ii;
unsigned long** prcb = (unsigned long**) get_prcbptr();
unsigned long* syscall_tab = prcb[5];
unsigned long* fault_tab = prcb[0];
extern void fault(void);
 
/* faults use syscall table entry 1 (0 is for syscalls) */
syscall_tab[13] = ((unsigned long) fault) | 0x2;
for (ii=0; ii < 20; ii += 2) {
/* leave trace trap to mon960; don't mess with reserved
* fields. */
if (ii == 2 || ii == 8 || ii == 12 || ii == 16 || ii == 18)
continue;
 
fault_tab[ii] = (1 << 2) | 2; /* use syscall #1 */
fault_tab[ii+1] = 0x27f; /* magic number */
}
}
 
void cfault(unsigned long* fault_rec, struct pt_regs* regs)
{
int ii;
unsigned long wd = fault_rec[2];
unsigned char type = (wd >> 16);
unsigned char subtype = (unsigned char)(wd);
char* nm = "<no fault>";
int sig = 0;
 
switch(type) {
case 3:
/* arithmetic fault */
nm = "arithmetic error";
sig = SIGFPE;
break;
case 5:
/* constraint error? */
nm = "constraint error";
break;
case 2:
switch(subtype) {
case 1:
nm = "illegal instruction";
sig = SIGILL;
break;
case 2:
nm = "accessed bad address";
sig = SIGSEGV;
break;
case 3:
nm = "unaligned";
sig = SIGBUS;
break;
case 4:
nm = "invalid operand";
sig = SIGILL;
break;
}
break;
case 7:
nm = "protection fault";
sig = SIGILL;
break;
case 1:
nm = "trace fault";
/* bugger: we need to do better tracing */
break;
 
case 0xa:
nm = "type.mismatch";
sig = SIGILL;
break;
}
 
if (user_mode(regs)) {
extern void leave_kernel(struct pt_regs* regs);
if (sig) {
current-> signal |= (1 << (sig -1));
}
leave_kernel(regs);
return;
}
 
cli();
/* Amuse the user. */
printk("\n"
" \\|/ ____ \\|/\n"
" \"@'/ ,. \\`@\"\n"
" /_| \\__/ |_\\\n"
" \\__U_/\n");
 
printk("kernel fault: %s\n", nm);
for (ii=0; ii < 4; ii++)
printk("fault_rec: 0x%8x\n", fault_rec[ii]);
 
show_regs(regs);
stack_trace();
#ifdef CONFIG_MON960
system_break();
#else
for (;;) ;
#endif
}
 
void die_if_kernel(char* msg, struct pt_regs* regs, long err)
{
if (user_mode(regs))
return;
 
/* Amuse the user. */
printk(
" \\|/ ____ \\|/\n"
" \"@'/ ,. \\`@\"\n"
" /_| \\__/ |_\\\n"
" \\__U_/\n");
 
printk("%s: %04lx\n", msg, err & 0xffff);
show_regs(regs);
stack_trace();
cli();
for (;;) ;
}
 
/*
* Print a quick n' dirty stack trace
*/
struct frameo {
struct frameo* pfp;
unsigned long sp;
void* rip;
};
 
void stack_trace(void)
{
unsigned long fp;
__asm__ __volatile__ ("flushreg; mov pfp, %0" : "=r"(fp));
stack_trace_from(fp);
}
 
void stack_trace_from(unsigned long ulfp)
{
int ii;
long flags;
struct frameo* fp = (struct frameo*) ulfp;
save_flags(flags);
cli();
printk("trace: fp == %p\n", fp);
for (ii=1; fp && (ii < 50); ii++, fp=fp->pfp) {
unsigned long type = ((unsigned long)fp) & 0xf;
fp = ((unsigned long)fp) & ~0xf;
switch(type) {
case 1:
printk("<f>");
break;
case 2:
case 3:
printk("<s>");
break;
case 7:
printk("<i>");
}
printk("\t%8x", fp->rip);
if (! (ii & 0x3))
printk("\n");
}
if (!fp) {
printk("<bottom of stack>\n");
}
printk("\n");
restore_flags(flags);
}
 
void ckpt(int num, unsigned long val)
{
printk("--------reached ckpt: %d\tval:0x%8x\n", num, val);
#if 0
struct pt_regs* regs;
asm("flushreg; subo 16, fp, %0" : "=r"(regs));
 
show_regs(regs);
#endif
printk("current stack trace:\n");
stack_trace();
printk("new stack strace:\n");
stack_trace_from(val);
printk("offset of ksp: 0x%8x\n",
&(((struct task_struct*)0)->kernel_stack_page));
printk("current ksp: 0x%8x\n", current->kernel_stack_page);
}
 
void system_break(void)
{
long flags;
 
save_flags(flags);
cli();
mon_entry();
restore_flags(flags);
}
/kernel/Makefile
0,0 → 1,25
#
# 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__ -traditional $(EXTRA_CFLAGS) -c $< -o $*.o
 
all: head.o entry.o kernel.o
O_TARGET := kernel.o
O_OBJS := entry.o process.o traps.o ints.o signal.o ptrace.o \
setup.o bios32.o time.o ksyms.o semaphore.o syscall.o
 
ifdef CONFIG_MON960
O_OBJS += mon960_calls.o
ifdef CONFIG_MON960_CONSOLE
O_OBJS += mon960_console.o
endif
endif
 
include $(TOPDIR)/Rules.make
/boot/Makefile
0,0 → 1,5
clean:
rm -f *.[oa]
 
dep depend:
echo Nope
/defconfig
0,0 → 1,182
#
# Automatically generated by make menuconfig: don't edit
#
CONFIG_UCLINUX=y
 
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
 
#
# Loadable module support
#
# CONFIG_MODULES is not set
 
#
# Platform dependant setup
#
# CONFIG_I960JX is not set
# CONFIG_I960KX is not set
# CONFIG_I960MC is not set
# CONFIG_I960CX is not set
# CONFIG_I960JX is not set
# CONFIG_I960HX is not set
CONFIG_I960VH=y
CONFIG_CYVH=y
CONFIG_CYVH_4MB=y
# CONFIG_CYVH_8MB is not set
# CONFIG_CYVH_16MB is not set
# CONFIG_CYVH_32MB is not set
CONFIG_MON960=y
 
#
# General setup
#
# CONFIG_MATH_EMULATION is not set
CONFIG_NET=y
# CONFIG_MAX_16M is not set
CONFIG_PCI=y
# CONFIG_PCI_OPTIMIZE is not set
CONFIG_SYSVIPC=y
CONFIG_REDUCED_MEMORY=y
CONFIG_BINFMT_FLAT=y
 
#
# Floppy, IDE, and other block devices
#
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_IDE is not set
# CONFIG_BLK_DEV_HD_ONLY is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_MD is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_RD_RELEASE_BLOCKS=y
# CONFIG_BLK_DEV_INITRD is not set
CONFIG_BLK_DEV_KROM=y
CONFIG_BLK_DEV_BLKMEM=y
# CONFIG_BLK_DEV_XD is not set
# CONFIG_PARIDE is not set
# CONFIG_BLK_DEV_HD is not set
 
#
# Networking options
#
# CONFIG_FIREWALL is not set
# CONFIG_NET_ALIAS is not set
CONFIG_INET=y
# CONFIG_IP_FORWARD is not set
# CONFIG_IP_MULTICAST is not set
# CONFIG_SYN_COOKIES is not set
# CONFIG_IP_ACCT is not set
# CONFIG_IP_ROUTER is not set
# CONFIG_NET_IPIP is not set
# CONFIG_INET_PCTCP is not set
# CONFIG_INET_RARP is not set
# CONFIG_NO_PATH_MTU_DISCOVERY is not set
CONFIG_IP_NOSR=y
# CONFIG_SKB_LARGE is not set
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_AX25 is not set
# CONFIG_BRIDGE is not set
# CONFIG_NETLINK is not set
 
#
# SCSI support
#
# CONFIG_SCSI is not set
 
#
# Network device support
#
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
# CONFIG_EQUALIZER is not set
# CONFIG_DLCI is not set
# CONFIG_PLIP is not set
CONFIG_PPP=y
CONFIG_SLIP=y
CONFIG_SLIP_COMPRESSED=y
# CONFIG_SLIP_SMART is not set
# CONFIG_SLIP_MODE_SLIP6 is not set
# CONFIG_NET_RADIO is not set
CONFIG_NET_ETHERNET=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NET_VENDOR_SMC is not set
CONFIG_NET_PCI=y
# CONFIG_PCNET32 is not set
CONFIG_EEXPRESS_PRO100B=y
# CONFIG_DE4X5 is not set
# CONFIG_DEC_ELCP is not set
# CONFIG_DGRS is not set
# CONFIG_NE2K_PCI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_RTL8139 is not set
# CONFIG_EPIC is not set
# CONFIG_TLAN is not set
# CONFIG_NET_ISA is not set
# CONFIG_NET_EISA is not set
# CONFIG_NET_POCKET is not set
# CONFIG_TR is not set
# CONFIG_FDDI is not set
# CONFIG_ARCNET is not set
 
#
# ISDN subsystem
#
# CONFIG_ISDN is not set
 
#
# Filesystems
#
# CONFIG_IMMUNIX_MMFS is not set
# CONFIG_QUOTA is not set
# CONFIG_MINIX_FS is not set
# CONFIG_EXT_FS is not set
CONFIG_EXT2_FS=y
# CONFIG_EXT2_CASELESS_ASCII7 is not set
# CONFIG_XIA_FS is not set
# CONFIG_NLS is not set
CONFIG_PROC_FS=y
# CONFIG_NFS_FS is not set
# CONFIG_SMB_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AFFS_FS is not set
CONFIG_ROMFS_FS=y
# CONFIG_ROMFS_CASELESS_ASCII7 is not set
# CONFIG_UFS_FS is not set
 
#
# Character devices
#
CONFIG_SERIAL=y
# CONFIG_SERIAL_CONSOLE is not set
# CONFIG_DIGI is not set
# CONFIG_CYCLADES is not set
# CONFIG_STALDRV is not set
# CONFIG_RISCOM8 is not set
# CONFIG_PRINTER is not set
# CONFIG_SPECIALIX is not set
# CONFIG_MOUSE is not set
# CONFIG_UMISC is not set
# CONFIG_QIC02_TAPE is not set
# CONFIG_FTAPE is not set
# CONFIG_APM is not set
# CONFIG_WATCHDOG is not set
# CONFIG_RTC is not set
# CONFIG_CONSOLE is not set
# CONFIG_KEYBOARD is not set
 
#
# Sound
#
# CONFIG_SOUND is not set
 
#
# Kernel hacking
#
# CONFIG_DEBUG_MALLOC is not set
# CONFIG_PROFILE is not set
/eval960.ld
0,0 → 1,26
/*----------------------------------------------------------*/
/* Linker Directive File (init_jx.ld) */
/*----------------------------------------------------------*/
MEMORY
{
data: o=0xA3C00000,l=0x40000 /* for 4 MB dram on eval board */
/* data: o=0xA3800000,l=0x80000 for 8 MB dram on eval board */
/* data: o=0xA3000000,l=0x100000 for 16 MB dram on eval board */
/* data: o=0xA2C00000,l=0x200000 for 32 MB dram on eval board */
}
 
SECTIONS
{
.text :
{
*(.text)
.=ALIGN(0x10);
} > data
.data :
{
} > data
.bss :
{
} > data
}
 
/lib/bzero.c
0,0 → 1,78
 
#include <linux/types.h>
#include <linux/string.h>
 
/* Optimization used unaligned access, so it had to go. */
 
void bzero(void * s, size_t count) {
memset(s, '\0', count);
}
 
#if 0
void * memset(void * s, int c, size_t count)
{
void *xs = s;
size_t temp, temp1;
 
if (!count)
return xs;
c &= 0xff;
c |= c << 8;
c |= c << 16;
if ((long) s & 1)
{
char *cs = s;
*cs++ = c;
s = cs;
count--;
}
if (count > 2 && (long) s & 2)
{
short *ss = s;
*ss++ = c;
s = ss;
count -= 2;
}
temp = count >> 2;
if (temp)
{
long *ls = s;
 
__asm__ __volatile__("movel %1,%2\n\t"
"andw #7,%2\n\t"
"lsrl #3,%1\n\t"
"negw %2\n\t"
"jmp %%pc@(2f,%2:w:2)\n\t"
"1:\t"
"movel %3,%0@+\n\t"
"movel %3,%0@+\n\t"
"movel %3,%0@+\n\t"
"movel %3,%0@+\n\t"
"movel %3,%0@+\n\t"
"movel %3,%0@+\n\t"
"movel %3,%0@+\n\t"
"movel %3,%0@+\n\t"
"2:\t"
"dbra %1,1b\n\t"
"clrw %1\n\t"
"subql #1,%1\n\t"
"jpl 1b\n\t"
: "=a" (ls), "=d" (temp), "=&d" (temp1)
: "d" (c), "0" (ls), "1" (temp)
);
s = ls;
}
if (count & 2)
{
short *ss = s;
*ss++ = c;
s = ss;
}
if (count & 1)
{
char *cs = s;
*cs = c;
}
return xs;
}
#endif
/lib/checksum.c
0,0 → 1,172
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system.
*
* IP/TCP/UDP checksumming routines
*
* Authors: Keith Adams, <kma@cse.ogi.edu>
* Jorge Cwik, <jorge@laser.satlink.net>
* Arnt Gulbrandsen, <agulbra@nvg.unit.no>
* Tom May, <ftom@netcom.com>
* Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de>
* Lots of code moved from tcp.c and ip.c; see those files
* for more names.
*
*/
#include <net/checksum.h>
 
#if 1
static unsigned long do_csum(const unsigned char * buff, int len)
{
int odd, count;
unsigned long result = 0;
 
if (len <= 0)
goto out;
odd = 1 & (unsigned long) buff;
if (odd) {
result = *buff;
len--;
buff++;
}
count = len >> 1; /* nr of 16-bit words.. */
if (count) {
if (2 & (unsigned long) buff) {
result += *(unsigned short *) buff;
count--;
len -= 2;
buff += 2;
}
count >>= 1; /* nr of 32-bit words.. */
if (count) {
#if 1
unsigned long carry = 0;
do {
unsigned long w = *(unsigned long *) buff;
count--;
buff += 4;
result += carry;
result += w;
carry = (w > result);
} while (count);
result += carry;
#else
asm("cmpo 0, 1"); /* clear carry */
do {
unsigned long w = *(unsigned long*) buff;
count--;
buff += 4;
asm("addc 0, %0, %0\n\t" /* r += carry */
"cmpo 0, 1\n\t" /* reset c */
"addc %1, %0, %0" /* r += w */
: "=&r"(result)
: "r"(w), "0"(result));
} while (count);
asm("addc 0, %0, %0" /* result += carry */
: "=r"(result) : "0"(result));
#endif
result = (result & 0xffff) + (result >> 16);
}
if (len & 2) {
result += *(unsigned short *) buff;
buff += 2;
}
}
if (len & 1)
result += *buff;
 
result = from32to16(result);
if (odd)
return ntohs(result);
out:
return result;
}
#else
 
/*
* Naive implementation stolen from Stevens
*/
static unsigned long do_csum(const unsigned char * buff, int len)
{
long sum=0;
while (len > 1) {
sum += *((unsigned short*)buff)++;
if (sum & (1<<31))
sum = (sum & 0xffff);
len -= 2;
}
if (len)
sum += (unsigned short) *buff;
while (sum >> 16)
sum = (sum & 0xffff) + (sum >> 16);
 
return sum;
}
#endif
 
/*
* This is a version of ip_compute_csum() optimized for IP headers,
* which always checksum on 4 octet boundaries.
*/
unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl)
{
return ~do_csum(iph,ihl*4);
}
 
/*
* computes the checksum of a memory block at buff, length len,
* and adds in "sum" (32-bit)
*
* returns a 32-bit number suitable for feeding into itself
* or csum_tcpudp_magic
*
* this function must be called with even lengths, except
* for the last fragment, which may be odd
*
* it's best to have buff aligned on a 32-bit boundary
*/
unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
{
unsigned int result = do_csum(buff, len);
 
/* add in old sum, and carry.. */
result += sum;
/* 16+c bits -> 16 bits */
result = (result & 0xffff) + (result >> 16);
return result;
}
 
/*
* this routine is used for miscellaneous IP-like checksums, mainly
* in icmp.c
*/
unsigned short ip_compute_csum(const unsigned char * buff, int len)
{
return ~do_csum(buff,len);
}
 
 
/*
* copy from fs while checksumming, otherwise like csum_partial
*/
 
unsigned int
csum_partial_copy_fromuser(const char *src, char *dst, int len, int sum)
{
memcpy(dst, src, len);
return csum_partial(dst, len, sum);
}
/*
* copy from ds while checksumming, otherwise like csum_partial
*/
 
unsigned int
csum_partial_copy(const char *src, char *dst, int len, int sum)
{
memcpy(dst, src, len);
return csum_partial(dst, len, sum);
}
/lib/abs.c
0,0 → 1,12
/*
* FILE: abs.c
* AUTHOR: kma
* DESCR: absolute value; we need this
*/
 
#ident "$Id: abs.c,v 1.1.1.1 2001-09-10 07:43:56 simons Exp $"
 
int abs(int j)
{
return (j<0)? -j : j;
}
/lib/__adddi3.S
0,0 → 1,41
/*
* Copyright (C) 1999 Keith Adams <kma@cse.ogi.edu>
* Oregon Graduate Institute
*/
 
#include <linux/linkage.h>
 
/*
* 64-bit math routines that gcc needs but doesn't have.
*/
 
/*
* 64-bit addition.
*
* registers:
* g0 = low word of arg 1, g1 = hi word of arg 1
* g2 = low word of arg 2, g3 = hi word of arg 2
* it wants result in g0-g1
*/
#define AC_OVERFLOW_BIT 8
.globl SYMBOL_NAME(__adddi3)
SYMBOL_NAME_LABEL(__adddi3)
cmpo 1, 0
addc g0, g2, g0
addc g1, g3, g1
ret
 
/*
* 64-bit subtraction: a-b = c
*
* registers in:
* g0-g1 = a; g2-g3 = b
* registers out:
* g0-g1 = c
*/
.globl SYMBOL_NAME(__subdi3)
SYMBOL_NAME_LABEL(__subdi3)
cmpo 1, 0
subc g2, g0, g0
subc g3, g1, g1
ret
/lib/Makefile
0,0 → 1,11
#
# Makefile for m68k-specific library files..
#
 
.S.o:
$(CC) $(AFLAGS) -D__ASSEMBLY__ -traditional -c $< -o $@
 
L_TARGET = lib.a
L_OBJS = abs.o ashrdi3.o checksum.o __adddi3.o
 
include $(TOPDIR)/Rules.make
/lib/ashrdi3.c
0,0 → 1,65
/* ashrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
 
This file is part of GNU CC.
 
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
 
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
 
#include <linux/stddef.h>
 
#define BITS_PER_UNIT 8
 
typedef int SItype __attribute__ ((mode (SI)));
typedef unsigned int USItype __attribute__ ((mode (SI)));
typedef int DItype __attribute__ ((mode (DI)));
typedef int word_type __attribute__ ((mode (__word__)));
 
struct DIstruct {SItype high, low;};
 
typedef union
{
struct DIstruct s;
DItype ll;
} DIunion;
 
DItype
__ashrdi3 (DItype u, word_type b)
{
DIunion w;
word_type bm;
DIunion uu;
 
if (b == 0)
return u;
 
uu.ll = u;
 
bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
if (bm <= 0)
{
/* w.s.high = 1..1 or 0..0 */
w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
w.s.low = uu.s.high >> -bm;
}
else
{
USItype carries = (USItype)uu.s.high << bm;
w.s.high = uu.s.high >> b;
w.s.low = ((USItype)uu.s.low >> b) | carries;
}
 
return w.ll;
}
/mm/init.c
0,0 → 1,226
/*
* linux/arch/i960/mm/init.c
*
* Copyright (C) 1999 Keith Adams <kma@cse.ogi.edu>
* Oregon Graduate Institute
*
* Based on:
*
* linux/arch/m68knommu/mm/init.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/mm/init.c
*
* Copyright (C) 1995 Hamish Macdonald
*/
 
#include <linux/config.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/types.h>
#ifdef CONFIG_BLK_DEV_RAM
#include <linux/blk.h>
#endif
 
#include <asm/setup.h>
#include <asm/segment.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/machdep.h>
 
#ifndef PAGE_OFFSET
#define PAGE_OFFSET 0
#endif
 
extern void die_if_kernel(char *,struct pt_regs *,long);
extern void show_net_buffers(void);
 
/*
* BAD_PAGE is the page that is used for page faults when linux
* is out-of-memory. Older versions of linux just did a
* do_exit(), but using this instead means there is less risk
* for a process dying in kernel mode, possibly leaving a inode
* unused etc..
*
* BAD_PAGETABLE is the accompanying page-table: it is initialized
* to point to BAD_PAGE entries.
*
* ZERO_PAGE is a special page that is used for zero-initialized
* data and COW.
*/
static unsigned long empty_bad_page_table;
 
static unsigned long empty_bad_page;
 
unsigned long empty_zero_page;
 
extern unsigned long rom_length;
 
void show_mem(void)
{
unsigned long i;
int free = 0, total = 0, reserved = 0, nonshared = 0, shared = 0;
 
printk("\nMem-info:\n");
show_free_areas();
printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
i = high_memory >> PAGE_SHIFT;
while (i-- > 0) {
total++;
if (PageReserved(mem_map+i))
reserved++;
else if (!mem_map[i].count)
free++;
else if (mem_map[i].count == 1)
nonshared++;
else
shared += mem_map[i].count-1;
}
printk("%d pages of RAM\n",total);
printk("%d free pages\n",free);
printk("%d reserved pages\n",reserved);
printk("%d pages nonshared\n",nonshared);
printk("%d pages shared\n",shared);
show_buffers();
#ifdef CONFIG_NET
show_net_buffers();
#endif
}
 
extern unsigned long free_area_init(unsigned long, unsigned long);
 
/*
* paging_init() sets up the 'virtual' memory environment.
* The parameters are pointers to where to stick the starting and ending
* addresses of available kernel virtual memory.
*/
unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
{
 
#ifdef DEBUG
printk ("memory available is %ldKB\n", (end_mem - start_mem) >> 10);
#endif
 
/*
* virtual address after end of kernel
* "availmem" is setup by the code in head.S.
*/
/*start_mem = availmem;*/
 
#ifdef DEBUG
printk ("start_mem is %#lx\nvirtual_end is %#lx\n",
start_mem, end_mem);
#endif
 
/*
* initialize the bad page table and bad page to point
* to a couple of allocated pages
*/
empty_bad_page_table = start_mem;
start_mem += PAGE_SIZE;
empty_bad_page = start_mem;
start_mem += PAGE_SIZE;
empty_zero_page = start_mem;
start_mem += PAGE_SIZE;
memset((void *)empty_zero_page, 0, PAGE_SIZE);
 
/*
* Set up SFC/DFC registers (user data space)
*/
/* on NO_MM systems this is rather a nop */
set_fs (USER_DS);
 
#ifdef DEBUG
printk ("before free_area_init\n");
 
printk ("free_area_init -> start_mem is %#lx\nvirtual_end is %#lx\n",
start_mem, end_mem);
#endif
 
return PAGE_ALIGN(free_area_init (start_mem, end_mem));
}
 
void mem_init(unsigned long start_mem, unsigned long end_mem)
{
int codek = 0;
int datapages = 0;
unsigned long tmp;
extern char _etext, _stext, _sdata;
unsigned long len = end_mem-(unsigned long)&_sdata;
 
#ifdef DEBUG
printk("Mem_init: start=%lx, end=%lx\n", start_mem, end_mem);
#endif
 
end_mem &= PAGE_MASK;
high_memory = end_mem;
 
start_mem = PAGE_ALIGN(start_mem);
while (start_mem < high_memory) {
clear_bit(PG_reserved, &mem_map[MAP_NR(start_mem)].flags);
start_mem += PAGE_SIZE;
}
 
for (tmp = PAGE_OFFSET ; tmp < end_mem ; tmp += PAGE_SIZE) {
 
#ifdef MAX_DMA_ADDRESS
if (VTOP (tmp) >= MAX_DMA_ADDRESS)
clear_bit(PG_DMA, &mem_map[MAP_NR(tmp)].flags);
#endif
 
if (PageReserved(mem_map+MAP_NR(tmp))) {
datapages++;
continue;
}
mem_map[MAP_NR(tmp)].count = 1;
#ifdef CONFIG_BLK_DEV_INITRD
if (!initrd_start ||
(tmp < (initrd_start & PAGE_MASK) || tmp >= initrd_end))
#endif
free_page(tmp);
}
codek = (&_etext - &_stext) >> 10;
tmp = nr_free_pages << PAGE_SHIFT;
printk("Memory available: %luk/%luk RAM, %luk/%luk ROM (%dk kernel data, %dk code)\n",
tmp >> 10,
len >> 10,
(rom_length >> 10) - codek,
rom_length >> 10,
datapages << (PAGE_SHIFT-10),
codek
);
}
 
void si_meminfo(struct sysinfo *val)
{
unsigned long i;
 
i = (high_memory - PAGE_OFFSET) >> PAGE_SHIFT;
val->totalram = 0;
val->sharedram = 0;
val->freeram = nr_free_pages << PAGE_SHIFT;
val->bufferram = buffermem;
while (i-- > 0) {
if (PageReserved(mem_map+i))
continue;
val->totalram++;
if (!mem_map[i].count)
continue;
val->sharedram += mem_map[i].count-1;
}
val->totalram <<= PAGE_SHIFT;
val->sharedram <<= PAGE_SHIFT;
return;
}
 
/mm/memory.c
0,0 → 1,1067
/*
* linux/arch/m68knommu/mm/memory.c
*
* Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>,
* The Silver Hammer Group, Ltd.
*
* Based on:
*
* linux/arch/m68k/mm/memory.c
*
* Copyright (C) 1995 Hamish Macdonald
*/
 
#include <linux/config.h>
#include <linux/mm.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/malloc.h>
 
#include <asm/setup.h>
#include <asm/segment.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/traps.h>
 
#ifndef NO_MM
 
extern pte_t *kernel_page_table (unsigned long *memavailp);
 
/* Strings for `extern inline' functions in <asm/pgtable.h>. If put
directly into these functions, they are output for every file that
includes pgtable.h */
 
const char PgtabStr_bad_pmd[] = "Bad pmd in pte_alloc: %08lx\n";
const char PgtabStr_bad_pgd[] = "Bad pgd in pmd_alloc: %08lx\n";
const char PgtabStr_bad_pmdk[] = "Bad pmd in pte_alloc_kernel: %08lx\n";
const char PgtabStr_bad_pgdk[] = "Bad pgd in pmd_alloc_kernel: %08lx\n";
 
static struct ptable_desc {
struct ptable_desc *prev;
struct ptable_desc *next;
unsigned long page;
unsigned char alloced;
} ptable_list = { &ptable_list, &ptable_list, 0, 0xff };
 
#define PD_NONEFREE(dp) ((dp)->alloced == 0xff)
#define PD_ALLFREE(dp) ((dp)->alloced == 0)
#define PD_TABLEFREE(dp,i) (!((dp)->alloced & (1<<(i))))
#define PD_MARKUSED(dp,i) ((dp)->alloced |= (1<<(i)))
#define PD_MARKFREE(dp,i) ((dp)->alloced &= ~(1<<(i)))
 
#define PTABLE_SIZE (PTRS_PER_PMD * sizeof(pmd_t))
 
pmd_t *get_pointer_table (void)
{
pmd_t *pmdp = NULL;
unsigned long flags;
struct ptable_desc *dp = ptable_list.next;
int i;
 
/*
* For a pointer table for a user process address space, a
* table is taken from a page allocated for the purpose. Each
* page can hold 8 pointer tables. The page is remapped in
* virtual address space to be noncacheable.
*/
if (PD_NONEFREE (dp)) {
 
if (!(dp = kmalloc (sizeof(struct ptable_desc),GFP_KERNEL))) {
return 0;
}
 
if (!(dp->page = __get_free_page (GFP_KERNEL))) {
kfree (dp);
return 0;
}
 
nocache_page (dp->page);
 
dp->alloced = 0;
/* put at head of list */
save_flags(flags);
cli();
dp->next = ptable_list.next;
dp->prev = ptable_list.next->prev;
ptable_list.next->prev = dp;
ptable_list.next = dp;
restore_flags(flags);
}
 
for (i = 0; i < 8; i++)
if (PD_TABLEFREE (dp, i)) {
PD_MARKUSED (dp, i);
pmdp = (pmd_t *)(dp->page + PTABLE_SIZE*i);
break;
}
 
if (PD_NONEFREE (dp)) {
/* move to end of list */
save_flags(flags);
cli();
dp->prev->next = dp->next;
dp->next->prev = dp->prev;
 
dp->next = ptable_list.next->prev;
dp->prev = ptable_list.prev;
ptable_list.prev->next = dp;
ptable_list.prev = dp;
restore_flags(flags);
}
 
memset (pmdp, 0, PTABLE_SIZE);
 
return pmdp;
}
 
void free_pointer_table (pmd_t *ptable)
{
struct ptable_desc *dp;
unsigned long page = (unsigned long)ptable & PAGE_MASK;
int index = ((unsigned long)ptable - page)/PTABLE_SIZE;
unsigned long flags;
 
for (dp = ptable_list.next; dp->page && dp->page != page; dp = dp->next)
;
 
if (!dp->page)
panic ("unable to find desc for ptable %p on list!", ptable);
 
if (PD_TABLEFREE (dp, index))
panic ("table already free!");
 
PD_MARKFREE (dp, index);
 
if (PD_ALLFREE (dp)) {
/* all tables in page are free, free page */
save_flags(flags);
cli();
dp->prev->next = dp->next;
dp->next->prev = dp->prev;
restore_flags(flags);
cache_page (dp->page);
free_page (dp->page);
kfree (dp);
return;
} else {
/*
* move this descriptor the the front of the list, since
* it has one or more free tables.
*/
save_flags(flags);
cli();
dp->prev->next = dp->next;
dp->next->prev = dp->prev;
 
dp->next = ptable_list.next;
dp->prev = ptable_list.next->prev;
ptable_list.next->prev = dp;
ptable_list.next = dp;
restore_flags(flags);
}
}
 
/* maximum pages used for kpointer tables */
#define KPTR_PAGES 4
/* # of reserved slots */
#define RESERVED_KPTR 4
extern pmd_tablepage kernel_pmd_table; /* reserved in head.S */
 
static struct kpointer_pages {
pmd_tablepage *page[KPTR_PAGES];
u_char alloced[KPTR_PAGES];
} kptr_pages;
 
void init_kpointer_table(void) {
short i = KPTR_PAGES-1;
 
/* first page is reserved in head.S */
kptr_pages.page[i] = &kernel_pmd_table;
kptr_pages.alloced[i] = ~(0xff>>RESERVED_KPTR);
for (i--; i>=0; i--) {
kptr_pages.page[i] = NULL;
kptr_pages.alloced[i] = 0;
}
}
 
pmd_t *get_kpointer_table (void)
{
/* For pointer tables for the kernel virtual address space,
* use the page that is reserved in head.S that can hold up to
* 8 pointer tables. 3 of these tables are always reserved
* (kernel_pg_dir, swapper_pg_dir and kernel pointer table for
* the first 16 MB of RAM). In addition, the 4th pointer table
* in this page is reserved. On Amiga and Atari, it is used to
* map in the hardware registers. It may be used for other
* purposes on other 68k machines. This leaves 4 pointer tables
* available for use by the kernel. 1 of them are usually used
* for the vmalloc tables. This allows mapping of 3 * 32 = 96 MB
* of physical memory. But these pointer tables are also used
* for other purposes, like kernel_map(), so further pages can
* now be allocated.
*/
pmd_tablepage *page;
pmd_table *table;
long nr, offset = -8;
short i;
 
for (i=KPTR_PAGES-1; i>=0; i--) {
asm volatile("bfffo %1{%2,#8},%0"
: "=d" (nr)
: "d" ((u_char)~kptr_pages.alloced[i]), "d" (offset));
if (nr)
break;
}
if (i < 0) {
printk("No space for kernel pointer table!\n");
return NULL;
}
if (!(page = kptr_pages.page[i])) {
if (!(page = (pmd_tablepage *)__get_free_page(GFP_KERNEL))) {
printk("No space for kernel pointer table!\n");
return NULL;
}
nocache_page((u_long)(kptr_pages.page[i] = page));
}
asm volatile("bfset %0@{%1,#1}"
: /* no output */
: "a" (&kptr_pages.alloced[i]), "d" (nr-offset));
table = &(*page)[nr-offset];
memset(table, 0, sizeof(pmd_table));
return ((pmd_t *)table);
}
 
void free_kpointer_table (pmd_t *pmdp)
{
pmd_table *table = (pmd_table *)pmdp;
pmd_tablepage *page = (pmd_tablepage *)((u_long)table & PAGE_MASK);
long nr;
short i;
 
for (i=KPTR_PAGES-1; i>=0; i--) {
if (kptr_pages.page[i] == page)
break;
}
nr = ((u_long)table - (u_long)page) / sizeof(pmd_table);
if (!table || i < 0 || (i == KPTR_PAGES-1 && nr < RESERVED_KPTR)) {
printk("Attempt to free invalid kernel pointer table: %p\n", table);
return;
}
asm volatile("bfclr %0@{%1,#1}"
: /* no output */
: "a" (&kptr_pages.alloced[i]), "d" (nr));
if (!kptr_pages.alloced[i]) {
kptr_pages.page[i] = 0;
cache_page ((u_long)page);
free_page ((u_long)page);
}
}
 
static unsigned long transp_transl_matches( unsigned long regval,
unsigned long vaddr )
{
unsigned long base, mask;
 
/* enabled? */
if (!(regval & 0x8000))
return( 0 );
 
if (CPU_IS_030) {
/* function code match? */
base = (regval >> 4) & 7;
mask = ~(regval & 7);
if ((SUPER_DATA & mask) != (base & mask))
return( 0 );
}
else {
/* must not be user-only */
if ((regval & 0x6000) == 0)
return( 0 );
}
 
/* address match? */
base = regval & 0xff000000;
mask = ~((regval << 8) & 0xff000000);
return( (vaddr & mask) == (base & mask) );
}
 
/*
* The following two routines map from a physical address to a kernel
* virtual address and vice versa.
*/
unsigned long mm_vtop (unsigned long vaddr)
{
int i;
unsigned long voff = vaddr;
unsigned long offset = 0;
 
for (i = 0; i < boot_info.num_memory; i++)
{
if (voff < offset + boot_info.memory[i].size) {
#ifdef DEBUGPV
printk ("VTOP(%lx)=%lx\n", vaddr,
boot_info.memory[i].addr + voff - offset);
#endif
return boot_info.memory[i].addr + voff - offset;
} else
offset += boot_info.memory[i].size;
}
 
/* not in one of the memory chunks; test for applying transparent
* translation */
 
if (CPU_IS_030) {
unsigned long ttreg;
register unsigned long *ttregptr __asm__( "a2" ) = &ttreg;
 
asm volatile( ".long 0xf0120a00;" /* pmove %/tt0,%a0@ */
: "=g" (ttreg) : "a" (ttregptr) );
if (transp_transl_matches( ttreg, vaddr ))
return vaddr;
 
asm volatile( ".long 0xf0120a00" /* pmove %/tt1,%a0@ */
: "=g" (ttreg) : "a" (ttregptr) );
if (transp_transl_matches( ttreg, vaddr ))
return vaddr;
}
else if (CPU_IS_040_OR_060) {
register unsigned long ttreg __asm__( "d0" );
asm volatile( ".long 0x4e7a0006" /* movec %dtt0,%d0 */
: "=d" (ttreg) );
if (transp_transl_matches( ttreg, vaddr ))
return vaddr;
asm volatile( ".long 0x4e7a0007" /* movec %dtt1,%d0 */
: "=d" (ttreg) );
if (transp_transl_matches( ttreg, vaddr ))
return vaddr;
}
 
/* no match, too, so get the actual physical address from the MMU. */
 
if (CPU_IS_060) {
unsigned long fs = get_fs();
unsigned long paddr;
 
set_fs (SUPER_DATA);
 
/* The PLPAR instruction causes an access error if the translation
* is not possible. We don't catch that here, so a bad kernel trap
* will be reported in this case. */
asm volatile ("movel %1,%/a0\n\t"
".word 0xf5c8\n\t" /* plpar (a0) */
"movel %/a0,%0"
: "=g" (paddr)
: "g" (vaddr)
: "a0" );
set_fs (fs);
 
return paddr;
 
} else if (CPU_IS_040) {
unsigned long mmusr;
unsigned long fs = get_fs();
 
set_fs (SUPER_DATA);
 
asm volatile ("movel %1,%/a0\n\t"
".word 0xf568\n\t" /* ptestr (a0) */
".long 0x4e7a8805\n\t" /* movec mmusr, a0 */
"movel %/a0,%0"
: "=g" (mmusr)
: "g" (vaddr)
: "a0", "d0");
set_fs (fs);
 
if (mmusr & MMU_R_040)
return (mmusr & PAGE_MASK) | (vaddr & (PAGE_SIZE-1));
 
panic ("VTOP040: bad virtual address %08lx (%lx)", vaddr, mmusr);
} else {
volatile unsigned short temp;
unsigned short mmusr;
unsigned long *descaddr;
 
asm volatile ("ptestr #5,%2@,#7,%0\n\t"
"pmove %/psr,%1@"
: "=a&" (descaddr)
: "a" (&temp), "a" (vaddr));
mmusr = temp;
 
if (mmusr & (MMU_I|MMU_B|MMU_L))
panic ("VTOP030: bad virtual address %08lx (%x)", vaddr, mmusr);
 
descaddr = (unsigned long *)PTOV(descaddr);
 
switch (mmusr & MMU_NUM) {
case 1:
return (*descaddr & 0xfe000000) | (vaddr & 0x01ffffff);
case 2:
return (*descaddr & 0xfffc0000) | (vaddr & 0x0003ffff);
case 3:
return (*descaddr & PAGE_MASK) | (vaddr & (PAGE_SIZE-1));
default:
panic ("VTOP: bad levels (%u) for virtual address %08lx",
mmusr & MMU_NUM, vaddr);
}
}
 
panic ("VTOP: bad virtual address %08lx", vaddr);
}
 
unsigned long mm_ptov (unsigned long paddr)
{
int i;
unsigned long offset = 0;
 
for (i = 0; i < boot_info.num_memory; i++)
{
if (paddr >= boot_info.memory[i].addr &&
paddr < (boot_info.memory[i].addr
+ boot_info.memory[i].size)) {
#ifdef DEBUGPV
printk ("PTOV(%lx)=%lx\n", paddr,
(paddr - boot_info.memory[i].addr) + offset);
#endif
return (paddr - boot_info.memory[i].addr) + offset;
} else
offset += boot_info.memory[i].size;
}
 
/*
* assume that the kernel virtual address is the same as the
* physical address.
*
* This should be reasonable in most situations:
* 1) They shouldn't be dereferencing the virtual address
* unless they are sure that it is valid from kernel space.
* 2) The only usage I see so far is converting a page table
* reference to some non-FASTMEM address space when freeing
* mmaped "/dev/mem" pages. These addresses are just passed
* to "free_page", which ignores addresses that aren't in
* the memory list anyway.
*
*/
 
/*
* if on an amiga and address is in first 16M, move it
* to the ZTWO_ADDR range
*/
if (MACH_IS_AMIGA && paddr < 16*1024*1024)
return ZTWO_VADDR(paddr);
return paddr;
}
 
/* invalidate page in both caches */
#define clear040(paddr) __asm__ __volatile__ ("movel %0,%/a0\n\t"\
"nop\n\t"\
".word 0xf4d0"\
/* CINVP I/D (a0) */\
: : "g" ((paddr))\
: "a0")
 
/* invalidate page in i-cache */
#define cleari040(paddr) __asm__ __volatile__ ("movel %0,%/a0\n\t"\
/* CINVP I (a0) */\
"nop\n\t"\
".word 0xf490"\
: : "g" ((paddr))\
: "a0")
 
/* push page in both caches */
#define push040(paddr) __asm__ __volatile__ ("movel %0,%/a0\n\t"\
"nop\n\t"\
".word 0xf4f0"\
/* CPUSHP I/D (a0) */\
: : "g" ((paddr))\
: "a0")
 
/* push and invalidate page in both caches */
#define pushcl040(paddr) do { push040((paddr));\
if (CPU_IS_060) clear040((paddr));\
} while(0)
 
/* push page in both caches, invalidate in i-cache */
#define pushcli040(paddr) do { push040((paddr));\
if (CPU_IS_060) cleari040((paddr));\
} while(0)
 
/* push page defined by virtual address in both caches */
#define pushv040(vaddr) __asm__ __volatile__ ("movel %0,%/a0\n\t"\
/* ptestr (a0) */\
"nop\n\t"\
".word 0xf568\n\t"\
/* movec mmusr,d0 */\
".long 0x4e7a0805\n\t"\
"andw #0xf000,%/d0\n\t"\
"movel %/d0,%/a0\n\t"\
/* CPUSHP I/D (a0) */\
"nop\n\t"\
".word 0xf4f0"\
: : "g" ((vaddr))\
: "a0", "d0")
 
/* push page defined by virtual address in both caches */
#define pushv060(vaddr) __asm__ __volatile__ ("movel %0,%/a0\n\t"\
/* plpar (a0) */\
".word 0xf5c8\n\t"\
/* CPUSHP I/D (a0) */\
".word 0xf4f0"\
: : "g" ((vaddr))\
: "a0")
 
 
/*
* 040: Hit every page containing an address in the range paddr..paddr+len-1.
* (Low order bits of the ea of a CINVP/CPUSHP are "don't care"s).
* Hit every page until there is a page or less to go. Hit the next page,
* and the one after that if the range hits it.
*/
/* ++roman: A little bit more care is required here: The CINVP instruction
* invalidates cache entries WITHOUT WRITING DIRTY DATA BACK! So the beginning
* and the end of the region must be treated differently if they are not
* exactly at the beginning or end of a page boundary. Else, maybe too much
* data becomes invalidated and thus lost forever. CPUSHP does what we need:
* it invalidates the page after pushing dirty data to memory. (Thanks to Jes
* for discovering the problem!)
*/
/* ... but on the '060, CPUSH doesn't invalidate (for us, since we have set
* the DPI bit in the CACR; would it cause problems with temporarily changing
* this?). So we have to push first and then additionally to invalidate.
*/
 
/*
* cache_clear() semantics: Clear any cache entries for the area in question,
* without writing back dirty entries first. This is useful if the data will
* be overwritten anyway, e.g. by DMA to memory. The range is defined by a
* _physical_ address.
*/
 
void cache_clear (unsigned long paddr, int len)
{
if (CPU_IS_040_OR_060) {
/*
* cwe need special treatment for the first page, in case it
* is not page-aligned.
*/
if (paddr & (PAGE_SIZE - 1)){
pushcl040(paddr);
if (len <= PAGE_SIZE){
if (((paddr + len - 1) ^ paddr) & PAGE_MASK) {
pushcl040(paddr + len - 1);
}
return;
}else{
len -=PAGE_SIZE;
paddr += PAGE_SIZE;
}
}
while (len > PAGE_SIZE) {
#if 0
pushcl040(paddr);
#else
clear040(paddr);
#endif
len -= PAGE_SIZE;
paddr += PAGE_SIZE;
}
if (len > 0) {
pushcl040(paddr);
if (((paddr + len - 1) ^ paddr) & PAGE_MASK) {
/* a page boundary gets crossed at the end */
pushcl040(paddr + len - 1);
}
}
}
else /* 68030 or 68020 */
asm volatile ("movec %/cacr,%/d0\n\t"
"oriw %0,%/d0\n\t"
"movec %/d0,%/cacr"
: : "i" (FLUSH_I_AND_D)
: "d0");
}
 
 
/*
* cache_push() semantics: Write back any dirty cache data in the given area,
* and invalidate the range in the instruction cache. It needs not (but may)
* invalidate those entries also in the data cache. The range is defined by a
* _physical_ address.
*/
 
void cache_push (unsigned long paddr, int len)
{
if (CPU_IS_040_OR_060) {
/*
* on 68040 or 68060, push cache lines for pages in the range;
* on the '040 this also invalidates the pushed lines, but not on
* the '060!
*/
while (len > PAGE_SIZE) {
pushcli040(paddr);
len -= PAGE_SIZE;
paddr += PAGE_SIZE;
}
if (len > 0) {
pushcli040(paddr);
if (((paddr + len - 1) ^ paddr) & PAGE_MASK) {
/* a page boundary gets crossed at the end */
pushcli040(paddr + len - 1);
}
}
}
/*
* 68030/68020 have no writeback cache. On the other hand,
* cache_push is actually a superset of cache_clear (the lines
* get written back and invalidated), so we should make sure
* to perform the corresponding actions. After all, this is getting
* called in places where we've just loaded code, or whatever, so
* flushing the icache is appropriate; flushing the dcache shouldn't
* be required.
*/
else /* 68030 or 68020 */
asm volatile ("movec %/cacr,%/d0\n\t"
"oriw %0,%/d0\n\t"
"movec %/d0,%/cacr"
: : "i" (FLUSH_I)
: "d0");
}
 
 
/*
* cache_push_v() semantics: Write back any dirty cache data in the given
* area, and invalidate those entries at least in the instruction cache. This
* is intended to be used after data has been written that can be executed as
* code later. The range is defined by a _user_mode_ _virtual_ address (or,
* more exactly, the space is defined by the %sfc/%dfc register.)
*/
 
void cache_push_v (unsigned long vaddr, int len)
{
if (CPU_IS_040) {
/* on 68040, push cache lines for pages in the range */
while (len > PAGE_SIZE) {
pushv040(vaddr);
len -= PAGE_SIZE;
vaddr += PAGE_SIZE;
}
if (len > 0) {
pushv040(vaddr);
if (((vaddr + len - 1) ^ vaddr) & PAGE_MASK) {
/* a page boundary gets crossed at the end */
pushv040(vaddr + len - 1);
}
}
}
else if (CPU_IS_060) {
/* on 68040, push cache lines for pages in the range */
while (len > PAGE_SIZE) {
pushv060(vaddr);
len -= PAGE_SIZE;
vaddr += PAGE_SIZE;
}
if (len > 0) {
pushv060(vaddr);
if (((vaddr + len - 1) ^ vaddr) & PAGE_MASK) {
/* a page boundary gets crossed at the end */
pushv060(vaddr + len - 1);
}
}
}
/* 68030/68020 have no writeback cache; still need to clear icache. */
else /* 68030 or 68020 */
asm volatile ("movec %/cacr,%/d0\n\t"
"oriw %0,%/d0\n\t"
"movec %/d0,%/cacr"
: : "i" (FLUSH_I)
: "d0");
}
 
#undef clear040
#undef cleari040
#undef push040
#undef pushcl040
#undef pushcli040
#undef pushv040
#undef pushv060
 
unsigned long mm_phys_to_virt (unsigned long addr)
{
return PTOV (addr);
}
 
int mm_end_of_chunk (unsigned long addr, int len)
{
int i;
 
for (i = 0; i < boot_info.num_memory; i++)
if (boot_info.memory[i].addr + boot_info.memory[i].size
== addr + len)
return 1;
return 0;
}
 
/* Map some physical address range into the kernel address space. The
* code is copied and adapted from map_chunk().
*/
 
unsigned long kernel_map(unsigned long paddr, unsigned long size,
int nocacheflag, unsigned long *memavailp )
{
#define STEP_SIZE (256*1024)
 
static unsigned long vaddr = 0xe0000000; /* safe place */
unsigned long physaddr, retaddr;
pte_t *ktablep = NULL;
pmd_t *kpointerp;
pgd_t *page_dir;
int pindex; /* index into pointer table */
int prot;
/* Round down 'paddr' to 256 KB and adjust size */
physaddr = paddr & ~(STEP_SIZE-1);
size += paddr - physaddr;
retaddr = vaddr + (paddr - physaddr);
paddr = physaddr;
/* Round up the size to 256 KB. It doesn't hurt if too much is
* mapped... */
size = (size + STEP_SIZE - 1) & ~(STEP_SIZE-1);
 
if (CPU_IS_040_OR_060) {
prot = _PAGE_PRESENT | _PAGE_GLOBAL040;
switch( nocacheflag ) {
case KERNELMAP_FULL_CACHING:
prot |= _PAGE_CACHE040;
break;
case KERNELMAP_NOCACHE_SER:
default:
prot |= _PAGE_NOCACHE_S;
break;
case KERNELMAP_NOCACHE_NONSER:
prot |= _PAGE_NOCACHE;
break;
case KERNELMAP_NO_COPYBACK:
prot |= _PAGE_CACHE040W;
/* prot |= 0; */
break;
}
} else
prot = _PAGE_PRESENT |
((nocacheflag == KERNELMAP_FULL_CACHING ||
nocacheflag == KERNELMAP_NO_COPYBACK) ? 0 : _PAGE_NOCACHE030);
page_dir = pgd_offset_k(vaddr);
if (pgd_present(*page_dir)) {
kpointerp = (pmd_t *)pgd_page(*page_dir);
pindex = (vaddr >> 18) & 0x7f;
if (pindex != 0 && CPU_IS_040_OR_060) {
if (pmd_present(*kpointerp))
ktablep = (pte_t *)pmd_page(*kpointerp);
else {
ktablep = kernel_page_table (memavailp);
/* Make entries invalid */
memset( ktablep, 0, sizeof(long)*PTRS_PER_PTE);
pmd_set(kpointerp,ktablep);
}
ktablep += (pindex & 15)*64;
}
}
else {
/* we need a new pointer table */
kpointerp = get_kpointer_table ();
pgd_set(page_dir, (pmd_t *)kpointerp);
memset( kpointerp, 0, PTRS_PER_PMD*sizeof(pmd_t));
pindex = 0;
}
 
for (physaddr = paddr; physaddr < paddr + size; vaddr += STEP_SIZE) {
 
if (pindex > 127) {
/* we need a new pointer table */
kpointerp = get_kpointer_table ();
pgd_set(pgd_offset_k(vaddr), (pmd_t *)kpointerp);
memset( kpointerp, 0, PTRS_PER_PMD*sizeof(pmd_t));
pindex = 0;
}
 
if (CPU_IS_040_OR_060) {
int i;
unsigned long ktable;
 
/*
* 68040, use page tables pointed to by the
* kernel pointer table.
*/
 
if ((pindex & 15) == 0) {
/* Need new page table every 4M on the '040 */
ktablep = kernel_page_table (memavailp);
/* Make entries invalid */
memset( ktablep, 0, sizeof(long)*PTRS_PER_PTE);
}
 
ktable = VTOP(ktablep);
 
/*
* initialize section of the page table mapping
* this 1M portion.
*/
for (i = 0; i < 64; i++) {
pte_val(*ktablep++) = physaddr | prot;
physaddr += PAGE_SIZE;
}
 
/*
* make the kernel pointer table point to the
* kernel page table.
*/
 
((unsigned long *)kpointerp)[pindex++] = ktable | _PAGE_TABLE;
 
} else {
/*
* 68030, use early termination page descriptors.
* Each one points to 64 pages (256K).
*/
((unsigned long *)kpointerp)[pindex++] = physaddr | prot;
physaddr += 64 * PAGE_SIZE;
}
}
 
return( retaddr );
}
 
 
static inline void set_cmode_pte( pmd_t *pmd, unsigned long address,
unsigned long size, unsigned cmode )
{ pte_t *pte;
unsigned long end;
 
if (pmd_none(*pmd))
return;
 
pte = pte_offset( pmd, address );
address &= ~PMD_MASK;
end = address + size;
if (end >= PMD_SIZE)
end = PMD_SIZE;
 
for( ; address < end; pte++ ) {
pte_val(*pte) = (pte_val(*pte) & ~_PAGE_NOCACHE) | cmode;
address += PAGE_SIZE;
}
}
 
 
static inline void set_cmode_pmd( pgd_t *dir, unsigned long address,
unsigned long size, unsigned cmode )
{
pmd_t *pmd;
unsigned long end;
 
if (pgd_none(*dir))
return;
 
pmd = pmd_offset( dir, address );
address &= ~PGDIR_MASK;
end = address + size;
if (end > PGDIR_SIZE)
end = PGDIR_SIZE;
 
if ((pmd_val(*pmd) & _DESCTYPE_MASK) == _PAGE_PRESENT) {
/* 68030 early termination descriptor */
pmd_val(*pmd) = (pmd_val(*pmd) & ~_PAGE_NOCACHE) | cmode;
return;
}
else {
/* "normal" tables */
for( ; address < end; pmd++ ) {
set_cmode_pte( pmd, address, end - address, cmode );
address = (address + PMD_SIZE) & PMD_MASK;
}
}
}
 
 
/*
* Set new cache mode for some kernel address space.
* The caller must push data for that range itself, if such data may already
* be in the cache.
*/
 
void kernel_set_cachemode( unsigned long address, unsigned long size,
unsigned cmode )
{
pgd_t *dir = pgd_offset_k( address );
unsigned long end = address + size;
if (CPU_IS_040_OR_060) {
switch( cmode ) {
case KERNELMAP_FULL_CACHING:
cmode = _PAGE_CACHE040;
break;
case KERNELMAP_NOCACHE_SER:
default:
cmode = _PAGE_NOCACHE_S;
break;
case KERNELMAP_NOCACHE_NONSER:
cmode = _PAGE_NOCACHE;
break;
case KERNELMAP_NO_COPYBACK:
cmode = _PAGE_CACHE040W;
break;
}
} else
cmode = ((cmode == KERNELMAP_FULL_CACHING ||
cmode == KERNELMAP_NO_COPYBACK) ?
0 : _PAGE_NOCACHE030);
 
for( ; address < end; dir++ ) {
set_cmode_pmd( dir, address, end - address, cmode );
address = (address + PGDIR_SIZE) & PGDIR_MASK;
}
flush_tlb_all();
}
 
#else /* !NO_MM */
 
/*
* The following two routines map from a physical address to a kernel
* virtual address and vice versa.
*/
unsigned long mm_vtop (unsigned long vaddr)
{
return vaddr;
}
 
unsigned long mm_ptov (unsigned long paddr)
{
return paddr;
}
 
 
/*
* 040: Hit every page containing an address in the range paddr..paddr+len-1.
* (Low order bits of the ea of a CINVP/CPUSHP are "don't care"s).
* Hit every page until there is a page or less to go. Hit the next page,
* and the one after that if the range hits it.
*/
/* ++roman: A little bit more care is required here: The CINVP instruction
* invalidates cache entries WITHOUT WRITING DIRTY DATA BACK! So the beginning
* and the end of the region must be treated differently if they are not
* exactly at the beginning or end of a page boundary. Else, maybe too much
* data becomes invalidated and thus lost forever. CPUSHP does what we need:
* it invalidates the page after pushing dirty data to memory. (Thanks to Jes
* for discovering the problem!)
*/
/* ... but on the '060, CPUSH doesn't invalidate (for us, since we have set
* the DPI bit in the CACR; would it cause problems with temporarily changing
* this?). So we have to push first and then additionally to invalidate.
*/
 
/*
* cache_clear() semantics: Clear any cache entries for the area in question,
* without writing back dirty entries first. This is useful if the data will
* be overwritten anyway, e.g. by DMA to memory. The range is defined by a
* _physical_ address.
*/
 
void cache_clear (unsigned long paddr, int len)
{
}
 
 
/*
* cache_push() semantics: Write back any dirty cache data in the given area,
* and invalidate the range in the instruction cache. It needs not (but may)
* invalidate those entries also in the data cache. The range is defined by a
* _physical_ address.
*/
 
void cache_push (unsigned long paddr, int len)
{
}
 
 
/*
* cache_push_v() semantics: Write back any dirty cache data in the given
* area, and invalidate those entries at least in the instruction cache. This
* is intended to be used after data has been written that can be executed as
* code later. The range is defined by a _user_mode_ _virtual_ address (or,
* more exactly, the space is defined by the %sfc/%dfc register.)
*/
 
void cache_push_v (unsigned long vaddr, int len)
{
}
 
unsigned long mm_phys_to_virt (unsigned long addr)
{
return PTOV (addr);
}
 
/* Map some physical address range into the kernel address space. The
* code is copied and adapted from map_chunk().
*/
 
unsigned long kernel_map(unsigned long paddr, unsigned long size,
int nocacheflag, unsigned long *memavailp )
{
return paddr;
}
 
 
void kernel_set_cachemode( unsigned long address, unsigned long size,
unsigned cmode )
{
}
 
unsigned long alloc_kernel_stack()
{
unsigned long rval = __get_free_page(GFP_KERNEL);
#ifdef DEBUG
printk("+++ alloc_kernel_stack: 0x%8x\n", rval);
stack_trace();
show_free_areas();
#endif
return rval;
}
 
void free_kernel_stack(unsigned long ksp)
{
#ifdef DEBUG
printk("--- free_kernel_stack: 0x%8x\n", ksp);
show_free_areas();
#endif
free_page(ksp);
#ifdef DEBUG
printk(" page freed\n");
show_free_areas();
#endif
}
 
#ifdef CONFIG_CYVH
#define ROMA_START 0xfec00000
#define ROMB_START 0xfee00000
#define ROMA_END ROMB_START
#define ROMB_END 0xff000000
#endif
 
int is_in_rom(unsigned long addr)
{
#if 0
return ((addr >= ROMA_START) && (addr < ROMA_END))
|| ((addr >= ROMB_START) && (addr < ROMB_END));
#else
extern int __data_rom_start, __data_rom_end;
return (addr >= (unsigned long)&__data_rom_start)
&& (addr < (unsigned long)&__data_rom_end);
#endif
}
 
#endif
/mm/fault.c
0,0 → 1,57
/*
* linux/arch/m68knommu/mm/fault.c
*
* Copyright (C) 1998 D. Jeff Dionne <jeff@ryeham.ee.ryerson.ca>,
* The Silver Hammer Group, Ltd.
*
* Based on:
*
* linux/arch/m68k/mm/fault.c
*
* Copyright (C) 1995 Hamish Macdonald
*/
 
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/kernel.h>
#include <linux/ptrace.h>
 
#include <asm/system.h>
#include <asm/pgtable.h>
 
extern void die_if_kernel(char *, struct pt_regs *, long);
 
/*
* This routine handles page faults. It determines the problem, and
* then passes it off to one of the appropriate routines.
*
* error_code:
* bit 0 == 0 means no page found, 1 means protection fault
* bit 1 == 0 means read, 1 means write
*
* If this routine detects a bad access, it returns 1, otherwise it
* returns 0.
*/
asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
unsigned long error_code)
{
#ifdef DEBUG
printk("page fault!\n");
show_regs(regs);
#endif
 
/*
* Oops. The kernel tried to access some bad page. We'll have to
* terminate things with extreme prejudice.
*/
if ((unsigned long) address < PAGE_SIZE) {
printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
} else
printk(KERN_ALERT "Unable to handle kernel access");
printk(" at virtual address %08lx\n",address);
die_if_kernel("Oops", regs, error_code);
do_exit(SIGKILL);
 
return 1;
}
 
/mm/Makefile
0,0 → 1,13
#
# Makefile for the linux m68k-specific parts of the memory manager.
#
# 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 definition is now in the main makefile...
 
O_TARGET := mm.o
O_OBJS := init.o fault.o memory.o
 
include $(TOPDIR)/Rules.make
/config.in
0,0 → 1,134
#
# For a description of the syntax of this configuration file,
# see the Configure script.
#
mainmenu_name "uClinux/i960 (w/o MMU) Kernel Configuration"
 
define_bool CONFIG_UCLINUX y
define_bool CONFIG_64BIT_MATH n
 
mainmenu_option next_comment
comment 'Code maturity level options'
bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
endmenu
 
mainmenu_option next_comment
comment 'Loadable module support'
bool 'Enable loadable module support' CONFIG_MODULES
if [ "$CONFIG_MODULES" = "y" ]; then
bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
bool 'Kernel daemon support (e.g. autoload of modules)' CONFIG_KERNELD
fi
endmenu
 
bool 'Prompt for command-line options at boot-time' CONFIG_CMDLINE_PROMPT
 
mainmenu_option next_comment
comment 'Platform dependant setup'
 
choice 'CPU' \
"i960Sx CONFIG_I960JX
i960Kx CONFIG_I960KX
i960MC CONFIG_I960MC
i960Cx CONFIG_I960CX
i960Jx CONFIG_I960JX
i960Hx CONFIG_I960HX
i960VH CONFIG_I960VH" i960VH
 
comment 'Platform'
 
if [ "$CONFIG_I960VH" = "y" ]; then
bool ' Cyclone evaluation board with VH processor' CONFIG_CYVH
if [ "$CONFIG_CYVH" = "y" ];then
choice ' Installed RAM' \
"4MB CONFIG_CYVH_4MB \
8MB CONFIG_CYVH_8MB \
16MB CONFIG_CYVH_16MB \
32MB CONFIG_CYVH_32MB" 4MB
bool ' Use Mon960 to bootstrap kernel' CONFIG_MON960
if [ "$CONFIG_MON960" = "y" ]; then
bool ' Use Mon960 for a console' CONFIG_MON960_CONSOLE
fi
fi
fi
 
endmenu
 
mainmenu_option next_comment
comment 'General setup'
 
bool 'Kernel math emulation' CONFIG_MATH_EMULATION
bool 'Networking support' CONFIG_NET
bool 'Limit memory to low 16MB' CONFIG_MAX_16M
if [ "$CONFIG_CYVH" = "y" ];then
bool 'PCI bios support' CONFIG_PCI
if [ "$CONFIG_PCI" = "y" ]; then
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
bool ' PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE
fi
fi
fi
bool 'System V IPC' CONFIG_SYSVIPC
bool 'Reduced memory footprint' CONFIG_REDUCED_MEMORY
tristate 'Kernel support for flat binaries' CONFIG_BINFMT_FLAT
 
endmenu
 
source drivers/block/Config.in
 
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
fi
 
mainmenu_option next_comment
comment 'SCSI support'
 
tristate 'SCSI support' CONFIG_SCSI
 
if [ "$CONFIG_SCSI" != "n" ]; then
source drivers/scsi/Config.in
fi
endmenu
 
if [ "$CONFIG_NET" = "y" ]; then
mainmenu_option next_comment
comment 'Network device support'
 
bool 'Network device support' CONFIG_NETDEVICES
if [ "$CONFIG_NETDEVICES" = "y" ]; then
source drivers/net/Config.in
fi
endmenu
fi
 
mainmenu_option next_comment
comment 'ISDN subsystem'
 
tristate 'ISDN support' CONFIG_ISDN
if [ "$CONFIG_ISDN" != "n" ]; then
source drivers/isdn/Config.in
fi
endmenu
 
source fs/Config.in
 
source drivers/char/Config.in
 
mainmenu_option next_comment
comment 'Sound'
tristate 'Sound card support' CONFIG_SOUND
if [ "$CONFIG_SOUND" != "n" ]; then
source drivers/sound/Config.in
fi
endmenu
 
mainmenu_option next_comment
comment 'Kernel hacking'
 
bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
bool 'Kernel IRQ profiling' CONFIG_PROF_IRQ
if [ "$CONFIG_PROF_IRQ" = "y" ]; then
int ' Profile shift count CONFIG_PROF_SHIFT 2
fi
endmenu
/init_cyvh.ld
0,0 → 1,46
#include <linux/config.h>
/*
* This is the linker directive file to link an application to run
* under mon960 on the CY board with a Cx, Jx, or Hx processor.
* Programs linked with this file are downloaded to DRAM after the
* data area used by mon960.
* malloc() uses the symbols _heap_base and _heap_end to manage the heap.
* _heap_base is located at the end of program memory (.text + .data +.bss).
* _heap_size is defined as 0x20000.
* The C runtime stack starts at _heap_end and grows up.
* There must be enough room after the program memory in the dram for
* the program's heap and stack.
*/
 
 
MEMORY
{
#ifdef CONFIG_CYVH_4MB
data: o=0xA3C08000,l=0x7f8000 /* for 4 MB dram on eval board */
#endif
#ifdef CONFIG_CYVH_8MB
data: o=0xA3808000,l=0xff8000 /* for 8 MB dram on eval board */
#endif
#ifdef CONFIG_CYVH_16MB
data: o=0xA3008000,l=0x1ff8000 /* for 16 MB dram on eval board */
#endif
#ifdef CONFIG_CYVH_32MB
data: o=0xA2008000,l=0x3ff8000 /* for 32 MB dram on eval board */
#endif
}
 
SECTIONS
{
.text :
{
*(.text)
.=ALIGN(0x10);
} > data
.data :
{
} > data
.bss :
{
} > data
}
 
/Makefile
0,0 → 1,76
#
# i960/Makefile
#
# This file is included by the global makefile so that you can add your own
# architecture-specific flags and dependencies. Remember to do have actions
# for "archclean" and "archdep" for cleaning up and making dependencies for
# this architecture
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
# Copyright (C) 1999 Keith Adams <kma@cse.ogi.edu>,
# Erik Walthinsen <omega@cse.ogi.edu>,
# Oregon Graduate Institute
#
# based on uClinux for the m68knommu (pilot/shglcore) by:
# Copyright (C) 1998,1999 D. Jeff Dionne <jeff@ryeham.ee.ryerson.ca>,
# Kenneth Albanowski <kjahds@kjahds.com>,
# The Silver Hammer Group, Ltd.
#
# Based on arch/m68k/Makefile:
# Copyright (C) 1994 by Hamish Macdonald
#
 
# test for cross compiling
COMPILE_ARCH = $(shell uname -m)
CROSS_COMPILE=y
XAS =gas960
XLD =gld960
XCC =gcc960
XAR =gar960
XNM =gnm960
XSTRIP =gstrip960
 
# even though i960 is COFF, don't define __COFF__; gcc960 still uses the
# _ prefixes, so __COFF__ makes linkage.h do the wrong thing
CFLAGS += -pipe $(DBG_FLAGS) -DNO_MM -DNO_FPU -DNO_FORGET -DUTS_SYSNAME='"uClinux-i960"' -DMAGIC_ROM_PTR -mabi
AFLAGS += -pipe -DNO_MM -DNO_FPU -DUTS_SYSNAME='"uClinux-i960"'
 
ifeq ($(CONFIG_CYVH),y)
LINKFLAGS = -T arch/$(ARCH)/init_cyjx.ld
endif
 
ifeq ($(CONFIG_I960VH),y)
GCC960ARCH=-AJF
CFLAGS += $(GCC960ARCH)
AFLAGS += $(GCC960ARCH)
endif
 
HEAD := arch/$(ARCH)/kernel/head.o
 
SUBDIRS=arch/$(ARCH)/kernel arch/$(ARCH)/mm arch/$(ARCH)/lib
ARCHIVES=arch/$(ARCH)/kernel/kernel.o arch/$(ARCH)/mm/mm.o
LIBS=arch/$(ARCH)/lib/lib.a $(LIBGCC)
 
ifeq ($(CONFIG_ROMFS_FS),y)
ARCHIVES+=arch/$(ARCH)/romfs/romfs.o
endif
 
MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
 
debug:
$(MAKE) coff DBG_FLAGS="-DDEBUG"
 
coff: vmlinux
cof960 -Fcoff -JS vmlinux
 
bootstrap:
@$(MAKEBOOT) bootstrap
 
archclean:
@$(MAKEBOOT) clean
 
archdep:
$(MAKEBOOT) dep
/init_cyjx.ld
0,0 → 1,66
/*
* This is the linker directive file to link an application to run
* under mon960 on the CY board with a Cx, Jx, or Hx processor.
* Programs linked with this file are downloaded to DRAM after the
* data area used by mon960.
* malloc() uses the symbols _heap_base and _heap_end to manage the heap.
* _heap_base is located at the end of program memory (.text + .data +.bss).
* _heap_size is defined as 0x20000.
* The C runtime stack starts at _heap_end and grows up.
* There must be enough room after the program memory in the dram for
* the program's heap and stack.
*/
 
MEMORY
{
dram : org = 0xA3C08000, len = 0x1ff8000 /* 4M less monitor */
isram : org = 0x00000100, len = 0x300
}
 
 
SECTIONS
{
.text :
{
} >dram
 
.data :
{
} >dram
 
.bss :
{
} >dram
 
 
/* For R4.0 of the compiler & libraries, the following lines */
/* should not be enclosed in comments. */
/*
SFP_AC :
{
fpem_CA_AC = .;
} >isram
*/
}
 
/* Bounds of heap: */
/* The heap may be placed in a separate memory region, if desired. */
 
/* _stackbase marks the base of the kernel's initial stack. We put it way at
* the top of memory. */
__stext = __Btext;
__etext = __Etext;
__sdata = __Bdata;
__edata = __Edata;
__end = _end;
_stackbase = 0xa3ff0000;
 
ENTRY(_main)
/* Don't use low-level libs anymore */
/*
STARTUP ("crt960*")
HLL ()
SYSLIB ("libmn*")
SYSLIB ("libll*")
*/
FLOAT

powered by: WebSVN 2.1.0

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