add idl4k kernel firmware version 1.13.0.105

This commit is contained in:
Jaroslav Kysela
2015-03-26 17:22:37 +01:00
parent 5194d2792e
commit e9070cdc77
31064 changed files with 12769984 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
#
# Makefile for the DECstation prom monitor library routines
# under Linux.
#
lib-y += init.o memory.o cmdline.o identify.o console.o
lib-$(CONFIG_32BIT) += locore.o
lib-$(CONFIG_64BIT) += call_o32.o

View File

@@ -0,0 +1,89 @@
/*
* O32 interface for the 64 (or N32) ABI.
*
* Copyright (C) 2002 Maciej W. Rozycki
*
* This program 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 of the License, or (at your option) any later version.
*/
#include <asm/asm.h>
#include <asm/regdef.h>
/* Maximum number of arguments supported. Must be even! */
#define O32_ARGC 32
/* Number of static registers we save. */
#define O32_STATC 11
/* Frame size for both of the above. */
#define O32_FRAMESZ (4 * O32_ARGC + SZREG * O32_STATC)
.text
/*
* O32 function call dispatcher, for interfacing 32-bit ROM routines.
*
* The standard 64 (N32) calling sequence is supported, with a0
* holding a function pointer, a1-a7 -- its first seven arguments
* and the stack -- remaining ones (up to O32_ARGC, including a1-a7).
* Static registers, gp and fp are preserved, v0 holds a result.
* This code relies on the called o32 function for sp and ra
* restoration and thus both this dispatcher and the current stack
* have to be placed in a KSEGx (or KUSEG) address space. Any
* pointers passed have to point to addresses within one of these
* spaces as well.
*/
NESTED(call_o32, O32_FRAMESZ, ra)
REG_SUBU sp,O32_FRAMESZ
REG_S ra,O32_FRAMESZ-1*SZREG(sp)
REG_S fp,O32_FRAMESZ-2*SZREG(sp)
REG_S gp,O32_FRAMESZ-3*SZREG(sp)
REG_S s7,O32_FRAMESZ-4*SZREG(sp)
REG_S s6,O32_FRAMESZ-5*SZREG(sp)
REG_S s5,O32_FRAMESZ-6*SZREG(sp)
REG_S s4,O32_FRAMESZ-7*SZREG(sp)
REG_S s3,O32_FRAMESZ-8*SZREG(sp)
REG_S s2,O32_FRAMESZ-9*SZREG(sp)
REG_S s1,O32_FRAMESZ-10*SZREG(sp)
REG_S s0,O32_FRAMESZ-11*SZREG(sp)
move jp,a0
sll a0,a1,zero
sll a1,a2,zero
sll a2,a3,zero
sll a3,a4,zero
sw a5,0x10(sp)
sw a6,0x14(sp)
sw a7,0x18(sp)
PTR_LA t0,O32_FRAMESZ(sp)
PTR_LA t1,0x1c(sp)
li t2,O32_ARGC-7
1:
lw t3,(t0)
REG_ADDU t0,SZREG
sw t3,(t1)
REG_SUBU t2,1
REG_ADDU t1,4
bnez t2,1b
jalr jp
REG_L s0,O32_FRAMESZ-11*SZREG(sp)
REG_L s1,O32_FRAMESZ-10*SZREG(sp)
REG_L s2,O32_FRAMESZ-9*SZREG(sp)
REG_L s3,O32_FRAMESZ-8*SZREG(sp)
REG_L s4,O32_FRAMESZ-7*SZREG(sp)
REG_L s5,O32_FRAMESZ-6*SZREG(sp)
REG_L s6,O32_FRAMESZ-5*SZREG(sp)
REG_L s7,O32_FRAMESZ-4*SZREG(sp)
REG_L gp,O32_FRAMESZ-3*SZREG(sp)
REG_L fp,O32_FRAMESZ-2*SZREG(sp)
REG_L ra,O32_FRAMESZ-1*SZREG(sp)
REG_ADDU sp,O32_FRAMESZ
jr ra
END(call_o32)

View File

@@ -0,0 +1,39 @@
/*
* cmdline.c: read the command line passed to us by the PROM.
*
* Copyright (C) 1998 Harald Koerfgen
* Copyright (C) 2002, 2004 Maciej W. Rozycki
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/types.h>
#include <asm/bootinfo.h>
#include <asm/dec/prom.h>
#undef PROM_DEBUG
void __init prom_init_cmdline(s32 argc, s32 *argv, u32 magic)
{
char *arg;
int start_arg, i;
/*
* collect args and prepare cmd_line
*/
if (!prom_is_rex(magic))
start_arg = 1;
else
start_arg = 2;
for (i = start_arg; i < argc; i++) {
arg = (void *)(long)(argv[i]);
strcat(arcs_cmdline, arg);
if (i < (argc - 1))
strcat(arcs_cmdline, " ");
}
#ifdef PROM_DEBUG
printk("arcs_cmdline: %s\n", &(arcs_cmdline[0]));
#endif
}

View File

@@ -0,0 +1,45 @@
/*
* DECstation PROM-based early console support.
*
* Copyright (C) 2004, 2007 Maciej W. Rozycki
*
* This program 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 of the License, or (at your option) any later version.
*/
#include <linux/console.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <asm/dec/prom.h>
static void __init prom_console_write(struct console *con, const char *s,
unsigned int c)
{
char buf[81];
unsigned int chunk = sizeof(buf) - 1;
while (c > 0) {
if (chunk > c)
chunk = c;
memcpy(buf, s, chunk);
buf[chunk] = '\0';
prom_printf("%s", buf);
s += chunk;
c -= chunk;
}
}
static struct console promcons __initdata = {
.name = "prom",
.write = prom_console_write,
.flags = CON_BOOT | CON_PRINTBUFFER,
.index = -1,
};
void __init register_prom_console(void)
{
register_console(&promcons);
}

View File

@@ -0,0 +1,14 @@
#ifndef DECTYPES
#define DECTYPES
#define DS2100_3100 1 /* DS2100/3100 Pmax */
#define DS5000_200 2 /* DS5000/200 3max */
#define DS5000_1XX 3 /* DS5000/1xx kmin */
#define DS5000_2X0 4 /* DS5000/2x0 3max+ */
#define DS5800 5 /* DS5800 Isis */
#define DS5400 6 /* DS5400 MIPSfair */
#define DS5000_XX 7 /* DS5000/xx maxine */
#define DS5500 11 /* DS5500 MIPSfair-2 */
#define DS5100 12 /* DS5100 MIPSmate */
#endif

View File

@@ -0,0 +1,186 @@
/*
* identify.c: machine identification code.
*
* Copyright (C) 1998 Harald Koerfgen and Paul M. Antoine
* Copyright (C) 2002, 2003, 2004, 2005 Maciej W. Rozycki
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mc146818rtc.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/types.h>
#include <asm/bootinfo.h>
#include <asm/dec/ioasic.h>
#include <asm/dec/ioasic_addrs.h>
#include <asm/dec/kn01.h>
#include <asm/dec/kn02.h>
#include <asm/dec/kn02ba.h>
#include <asm/dec/kn02ca.h>
#include <asm/dec/kn03.h>
#include <asm/dec/kn230.h>
#include <asm/dec/prom.h>
#include <asm/dec/system.h>
#include "dectypes.h"
static const char *dec_system_strings[] = {
[MACH_DSUNKNOWN] "unknown DECstation",
[MACH_DS23100] "DECstation 2100/3100",
[MACH_DS5100] "DECsystem 5100",
[MACH_DS5000_200] "DECstation 5000/200",
[MACH_DS5000_1XX] "DECstation 5000/1xx",
[MACH_DS5000_XX] "Personal DECstation 5000/xx",
[MACH_DS5000_2X0] "DECstation 5000/2x0",
[MACH_DS5400] "DECsystem 5400",
[MACH_DS5500] "DECsystem 5500",
[MACH_DS5800] "DECsystem 5800",
[MACH_DS5900] "DECsystem 5900",
};
const char *get_system_type(void)
{
#define STR_BUF_LEN 64
static char system[STR_BUF_LEN];
static int called = 0;
if (called == 0) {
called = 1;
snprintf(system, STR_BUF_LEN, "Digital %s",
dec_system_strings[mips_machtype]);
}
return system;
}
/*
* Setup essential system-specific memory addresses. We need them
* early. Semantically the functions belong to prom/init.c, but they
* are compact enough we want them inlined. --macro
*/
volatile u8 *dec_rtc_base;
EXPORT_SYMBOL(dec_rtc_base);
static inline void prom_init_kn01(void)
{
dec_kn_slot_base = KN01_SLOT_BASE;
dec_kn_slot_size = KN01_SLOT_SIZE;
dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + KN01_RTC);
}
static inline void prom_init_kn230(void)
{
dec_kn_slot_base = KN01_SLOT_BASE;
dec_kn_slot_size = KN01_SLOT_SIZE;
dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + KN01_RTC);
}
static inline void prom_init_kn02(void)
{
dec_kn_slot_base = KN02_SLOT_BASE;
dec_kn_slot_size = KN02_SLOT_SIZE;
dec_tc_bus = 1;
dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + KN02_RTC);
}
static inline void prom_init_kn02xa(void)
{
dec_kn_slot_base = KN02XA_SLOT_BASE;
dec_kn_slot_size = IOASIC_SLOT_SIZE;
dec_tc_bus = 1;
ioasic_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_IOCTL);
dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_TOY);
}
static inline void prom_init_kn03(void)
{
dec_kn_slot_base = KN03_SLOT_BASE;
dec_kn_slot_size = IOASIC_SLOT_SIZE;
dec_tc_bus = 1;
ioasic_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_IOCTL);
dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_TOY);
}
void __init prom_identify_arch(u32 magic)
{
unsigned char dec_cpunum, dec_firmrev, dec_etc, dec_systype;
u32 dec_sysid;
if (!prom_is_rex(magic)) {
dec_sysid = simple_strtoul(prom_getenv("systype"),
(char **)0, 0);
} else {
dec_sysid = rex_getsysid();
if (dec_sysid == 0) {
printk("Zero sysid returned from PROM! "
"Assuming a PMAX-like machine.\n");
dec_sysid = 1;
}
}
dec_cpunum = (dec_sysid & 0xff000000) >> 24;
dec_systype = (dec_sysid & 0xff0000) >> 16;
dec_firmrev = (dec_sysid & 0xff00) >> 8;
dec_etc = dec_sysid & 0xff;
/*
* FIXME: This may not be an exhaustive list of DECStations/Servers!
* Put all model-specific initialisation calls here.
*/
switch (dec_systype) {
case DS2100_3100:
mips_machtype = MACH_DS23100;
prom_init_kn01();
break;
case DS5100: /* DS5100 MIPSMATE */
mips_machtype = MACH_DS5100;
prom_init_kn230();
break;
case DS5000_200: /* DS5000 3max */
mips_machtype = MACH_DS5000_200;
prom_init_kn02();
break;
case DS5000_1XX: /* DS5000/100 3min */
mips_machtype = MACH_DS5000_1XX;
prom_init_kn02xa();
break;
case DS5000_2X0: /* DS5000/240 3max+ or DS5900 bigmax */
mips_machtype = MACH_DS5000_2X0;
prom_init_kn03();
if (!(ioasic_read(IO_REG_SIR) & KN03_IO_INR_3MAXP))
mips_machtype = MACH_DS5900;
break;
case DS5000_XX: /* Personal DS5000/xx maxine */
mips_machtype = MACH_DS5000_XX;
prom_init_kn02xa();
break;
case DS5800: /* DS5800 Isis */
mips_machtype = MACH_DS5800;
break;
case DS5400: /* DS5400 MIPSfair */
mips_machtype = MACH_DS5400;
break;
case DS5500: /* DS5500 MIPSfair-2 */
mips_machtype = MACH_DS5500;
break;
default:
mips_machtype = MACH_DSUNKNOWN;
break;
}
if (mips_machtype == MACH_DSUNKNOWN)
printk("This is an %s, id is %x\n",
dec_system_strings[mips_machtype], dec_systype);
else
printk("This is a %s\n", dec_system_strings[mips_machtype]);
}

View File

@@ -0,0 +1,135 @@
/*
* init.c: PROM library initialisation code.
*
* Copyright (C) 1998 Harald Koerfgen
* Copyright (C) 2002, 2004 Maciej W. Rozycki
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/linkage.h>
#include <linux/smp.h>
#include <linux/string.h>
#include <linux/types.h>
#include <asm/bootinfo.h>
#include <asm/cpu.h>
#include <asm/processor.h>
#include <asm/dec/prom.h>
int (*__rex_bootinit)(void);
int (*__rex_bootread)(void);
int (*__rex_getbitmap)(memmap *);
unsigned long *(*__rex_slot_address)(int);
void *(*__rex_gettcinfo)(void);
int (*__rex_getsysid)(void);
void (*__rex_clear_cache)(void);
int (*__prom_getchar)(void);
char *(*__prom_getenv)(char *);
int (*__prom_printf)(char *, ...);
int (*__pmax_open)(char*, int);
int (*__pmax_lseek)(int, long, int);
int (*__pmax_read)(int, void *, int);
int (*__pmax_close)(int);
/*
* Detect which PROM the DECSTATION has, and set the callback vectors
* appropriately.
*/
void __init which_prom(s32 magic, s32 *prom_vec)
{
/*
* No sign of the REX PROM's magic number means we assume a non-REX
* machine (i.e. we're on a DS2100/3100, DS5100 or DS5000/2xx)
*/
if (prom_is_rex(magic)) {
/*
* Set up prom abstraction structure with REX entry points.
*/
__rex_bootinit =
(void *)(long)*(prom_vec + REX_PROM_BOOTINIT);
__rex_bootread =
(void *)(long)*(prom_vec + REX_PROM_BOOTREAD);
__rex_getbitmap =
(void *)(long)*(prom_vec + REX_PROM_GETBITMAP);
__prom_getchar =
(void *)(long)*(prom_vec + REX_PROM_GETCHAR);
__prom_getenv =
(void *)(long)*(prom_vec + REX_PROM_GETENV);
__rex_getsysid =
(void *)(long)*(prom_vec + REX_PROM_GETSYSID);
__rex_gettcinfo =
(void *)(long)*(prom_vec + REX_PROM_GETTCINFO);
__prom_printf =
(void *)(long)*(prom_vec + REX_PROM_PRINTF);
__rex_slot_address =
(void *)(long)*(prom_vec + REX_PROM_SLOTADDR);
__rex_clear_cache =
(void *)(long)*(prom_vec + REX_PROM_CLEARCACHE);
} else {
/*
* Set up prom abstraction structure with non-REX entry points.
*/
__prom_getchar = (void *)PMAX_PROM_GETCHAR;
__prom_getenv = (void *)PMAX_PROM_GETENV;
__prom_printf = (void *)PMAX_PROM_PRINTF;
__pmax_open = (void *)PMAX_PROM_OPEN;
__pmax_lseek = (void *)PMAX_PROM_LSEEK;
__pmax_read = (void *)PMAX_PROM_READ;
__pmax_close = (void *)PMAX_PROM_CLOSE;
}
}
void __init prom_init(void)
{
extern void dec_machine_halt(void);
static char cpu_msg[] __initdata =
"Sorry, this kernel is compiled for a wrong CPU type!\n";
s32 argc = fw_arg0;
s32 *argv = (void *)fw_arg1;
u32 magic = fw_arg2;
s32 *prom_vec = (void *)fw_arg3;
/*
* Determine which PROM we have
* (and therefore which machine we're on!)
*/
which_prom(magic, prom_vec);
if (prom_is_rex(magic))
rex_clear_cache();
/* Register the early console. */
register_prom_console();
/* Were we compiled with the right CPU option? */
#if defined(CONFIG_CPU_R3000)
if ((current_cpu_type() == CPU_R4000SC) ||
(current_cpu_type() == CPU_R4400SC)) {
static char r4k_msg[] __initdata =
"Please recompile with \"CONFIG_CPU_R4x00 = y\".\n";
printk(cpu_msg);
printk(r4k_msg);
dec_machine_halt();
}
#endif
#if defined(CONFIG_CPU_R4X00)
if ((current_cpu_type() == CPU_R3000) ||
(current_cpu_type() == CPU_R3000A)) {
static char r3k_msg[] __initdata =
"Please recompile with \"CONFIG_CPU_R3000 = y\".\n";
printk(cpu_msg);
printk(r3k_msg);
dec_machine_halt();
}
#endif
prom_meminit(magic);
prom_identify_arch(magic);
prom_init_cmdline(argc, argv, magic);
}

View File

@@ -0,0 +1,30 @@
/*
* locore.S
*/
#include <asm/asm.h>
#include <asm/regdef.h>
#include <asm/mipsregs.h>
.text
/*
* Simple general exception handling routine. This one is used for the
* Memory sizing routine for pmax machines. HK
*/
NESTED(genexcept_early, 0, sp)
.set noat
.set noreorder
mfc0 k0, CP0_STATUS
la k1, mem_err
sw k0, 0(k1)
mfc0 k0, CP0_EPC
nop
addiu k0, 4 # skip the causing instruction
jr k0
rfe
END(genexcept_early)

View File

@@ -0,0 +1,118 @@
/*
* memory.c: memory initialisation code.
*
* Copyright (C) 1998 Harald Koerfgen, Frieder Streffer and Paul M. Antoine
* Copyright (C) 2000, 2002 Maciej W. Rozycki
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/bootmem.h>
#include <linux/types.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
#include <asm/dec/machtype.h>
#include <asm/dec/prom.h>
#include <asm/page.h>
#include <asm/sections.h>
volatile unsigned long mem_err; /* So we know an error occurred */
/*
* Probe memory in 4MB chunks, waiting for an error to tell us we've fallen
* off the end of real memory. Only suitable for the 2100/3100's (PMAX).
*/
#define CHUNK_SIZE 0x400000
static inline void pmax_setup_memory_region(void)
{
volatile unsigned char *memory_page, dummy;
char old_handler[0x80];
extern char genexcept_early;
/* Install exception handler */
memcpy(&old_handler, (void *)(CKSEG0 + 0x80), 0x80);
memcpy((void *)(CKSEG0 + 0x80), &genexcept_early, 0x80);
/* read unmapped and uncached (KSEG1)
* DECstations have at least 4MB RAM
* Assume less than 480MB of RAM, as this is max for 5000/2xx
* FIXME this should be replaced by the first free page!
*/
for (memory_page = (unsigned char *)CKSEG1 + CHUNK_SIZE;
mem_err == 0 && memory_page < (unsigned char *)CKSEG1 + 0x1e00000;
memory_page += CHUNK_SIZE) {
dummy = *memory_page;
}
memcpy((void *)(CKSEG0 + 0x80), &old_handler, 0x80);
add_memory_region(0, (unsigned long)memory_page - CKSEG1 - CHUNK_SIZE,
BOOT_MEM_RAM);
}
/*
* Use the REX prom calls to get hold of the memory bitmap, and thence
* determine memory size.
*/
static inline void rex_setup_memory_region(void)
{
int i, bitmap_size;
unsigned long mem_start = 0, mem_size = 0;
memmap *bm;
/* some free 64k */
bm = (memmap *)CKSEG0ADDR(0x28000);
bitmap_size = rex_getbitmap(bm);
for (i = 0; i < bitmap_size; i++) {
/* FIXME: very simplistically only add full sets of pages */
if (bm->bitmap[i] == 0xff)
mem_size += (8 * bm->pagesize);
else if (!mem_size)
mem_start += (8 * bm->pagesize);
else {
add_memory_region(mem_start, mem_size, BOOT_MEM_RAM);
mem_start += mem_size + (8 * bm->pagesize);
mem_size = 0;
}
}
if (mem_size)
add_memory_region(mem_start, mem_size, BOOT_MEM_RAM);
}
void __init prom_meminit(u32 magic)
{
if (!prom_is_rex(magic))
pmax_setup_memory_region();
else
rex_setup_memory_region();
}
void __init prom_free_prom_memory(void)
{
unsigned long end;
/*
* Free everything below the kernel itself but leave
* the first page reserved for the exception handlers.
*/
#if defined(CONFIG_DECLANCE) || defined(CONFIG_DECLANCE_MODULE)
/*
* Leave 128 KB reserved for Lance memory for
* IOASIC DECstations.
*
* XXX: save this address for use in dec_lance.c?
*/
if (IOASIC)
end = __pa(&_text) - 0x00020000;
else
#endif
end = __pa(&_text);
free_init_pages("unused PROM memory", PAGE_SIZE, end);
}