diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-01-07 02:33:00 +0000 |
---|---|---|
committer | <ralf@linux-mips.org> | 1997-01-07 02:33:00 +0000 |
commit | beb116954b9b7f3bb56412b2494b562f02b864b1 (patch) | |
tree | 120e997879884e1b9d93b265221b939d2ef1ade1 /arch/sparc/boot | |
parent | 908d4681a1dc3792ecafbe64265783a86c4cccb6 (diff) |
Import of Linux/MIPS 2.1.14
Diffstat (limited to 'arch/sparc/boot')
-rw-r--r-- | arch/sparc/boot/Makefile | 12 | ||||
-rw-r--r-- | arch/sparc/boot/README | 21 | ||||
-rw-r--r-- | arch/sparc/boot/bare.S | 160 | ||||
-rw-r--r-- | arch/sparc/boot/bare.h | 18 | ||||
-rw-r--r-- | arch/sparc/boot/empirical.h | 8 | ||||
-rw-r--r-- | arch/sparc/boot/init_me.c | 69 |
6 files changed, 288 insertions, 0 deletions
diff --git a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile new file mode 100644 index 000000000..b9d54e652 --- /dev/null +++ b/arch/sparc/boot/Makefile @@ -0,0 +1,12 @@ +# $Id: Makefile,v 1.3 1996/08/04 08:40:58 ecd Exp $ +# Makefile for the Sparc low level /boot module. +# +# Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + +all: boot + +boot: + @echo "Nothing special to be done for 'boot' on Linux/SPARC." + +dep: + diff --git a/arch/sparc/boot/README b/arch/sparc/boot/README new file mode 100644 index 000000000..189a72d29 --- /dev/null +++ b/arch/sparc/boot/README @@ -0,0 +1,21 @@ +This directory will contain the code necessary to compile and link the +/boot program which is necessary to boot on the Sparc. This program +is real ugly and it knows too much. It must be able to not only boot +off of the root partition but also be able to netboot. This means +that it knows about RPC and NFS (bleech, yuck, eeewwwww!!) so that it +can remote mount the root directory to fetch the kernel. Also it must +be able to ARP for its IP address and who its boot server is. I +think I'm getting sick. + +Regardless for now I will concentrate on the low-level stuff necessary +to get the thing going. This means the low-level entry code, etc. +The prom knows how to get "us" if we have the proper boot blocks, +actually the boot blocks live in our logical partition on a hard drive +whereas over NFS this isn't applicable. We have the boot blocks in +our data area either way because we can be dual purpose. + +More will come.... + +Hopefully I can write this such that it will work on almost all SUN +machines in existence. We'll see ;( + diff --git a/arch/sparc/boot/bare.S b/arch/sparc/boot/bare.S new file mode 100644 index 000000000..ab3508591 --- /dev/null +++ b/arch/sparc/boot/bare.S @@ -0,0 +1,160 @@ +/* $Id: bare.S,v 1.4 1996/04/23 01:53:40 davem Exp $ + * base.S: Ugly low-level boot program entry code. The job of this + * module is to parse the boot flags, try to mount the remote + * root filesystem and load the kernel into virtual memory. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#include "bare.h" +#include <asm/ptrace.h> + + .data + .globl C_LABEL(romvec) + .globl C_LABEL(idp_ptr) + +C_LABEL(romvec): + .word 0 +C_LABEL(idp_ptr): + .word 0 + + .text + .align 8 + .globl C_LABEL(first_adr_in_text) + +C_LABEL(first_adr_in_text): + + /* Grrr, boot block, scratching my head... */ + .globl C_LABEL(b_block) /* Start of actual boot block */ + .globl C_LABEL(b_block_size) /* In bytes */ + .globl C_LABEL(b_block_cksum) /* Checksum of boot block bytes */ + + b start_of_execution /* XXX Hack */ + nop + + .align 8 +C_LABEL(b_block): + .skip (BOOTBLOCK_NENTRIES * BOOTBLOCK_ENTSIZE) + +C_LABEL(b_block_size): + .word 0 + +C_LABEL(b_block_cksum): + .word 0 + +/* Ok, the prom has left in %o0 the PROM pointer. We leave it here + * for when we jump into the kernel. So save out of this window before + * you dick with %o0. As far as I know we could be loaded *anywhere*, so + * we relocate ourselves to the "linked" location. Self modifying code rules. + */ + +start_of_execution: + sethi %hi(C_LABEL(first_adr_in_text)), %o1 ! This is our top + or %o1, %lo(C_LABEL(first_adr_in_text)), %o1 ! of stack too. + sub %o1, REGWIN_SZ, %o1 + add %o1, 0x7, %o1 + andn %o1, 0x7, %o1 + save %o1, 0x0, %sp ! save is an add +here: + call there + sethi %hi(here), %o4 +there: + sub %o7, here-C_LABEL(first_adr_in_text), %o5 + or %o4, %lo(here), %o4 + cmp %o4, %o7 + be loaded_ok + nop + + /* Gotta relocate, compute our size sans bss segment. */ + set C_LABEL(edata)+4, %o3 + set C_LABEL(first_adr_in_text), %o2 + sub %o3, %o2, %o3 +rel_loop: + ld [%o5], %o4 + add %o5, 0x4, %o5 + st %o4, [%o2] + subcc %o3, 0x4, %o3 + bg rel_loop + add %o2, 0x4, %o2 + + /* Pray that we are now in a sane place in memory */ + sethi %hi(loaded_ok), %o2 + or %o2, %lo(loaded_ok), %o2 + jmp %o2 + nop + +loaded_ok: + /* Save the PROM pointer */ + sethi %hi(C_LABEL(romvec)), %o1 + or %o1, %lo(C_LABEL(romvec)), %o1 + st %i0, [%o1] + + /* Build a PSR we can live with */ + rd %psr, %o1 + +#if 0 + andn %o1, PSR_PIL, %o1 + sethi %hi(SANE_PSR), %g4 + or %g4, %lo(SANE_PSR), %g4 + or %o1, %g4, %o1 +#endif + + /* V8 book says this works to calculate num_windows */ + sethi %hi(0xffffffff), %g2 + rd %wim, %g3 + or %g2, %lo(0xffffffff), %g2 + wr %g2, 0x0, %wim + WRITE_PAUSE + + rd %wim, %g4 + WRITE_PAUSE + + wr %g3, 0x0, %wim + WRITE_PAUSE + + /* Restore old %psr */ + wr %o1, 0x0, %psr + WRITE_PAUSE + + or %g0, 0x0, %g3 +1: + srl %g4, 0x1, %g4 + subcc %g4, 0x0, %g0 + bne 1b + add %g3, 0x1, %g3 + + /* %g3 now contains nwindows */ + sethi %hi(C_LABEL(nwindows)), %o4 + st %g3, [%o4 + %lo(C_LABEL(nwindows))] + + /* Now zero out our bss segment, lord knows the nasty prom monster + * didn't do it for us. + */ + sethi %hi(C_LABEL(end)), %g1 + or %g1, %lo(C_LABEL(end)), %g1 + add %g1, 0x4, %g1 + sethi %hi(C_LABEL(edata)), %g2 + or %g2, %lo(C_LABEL(edata)), %g2 + + /* Slow, inefficient, who cares, this is messy boot code */ +bzero_bss_loop: + st %g0, [%g2] + add %g2, 0x4, %g2 + cmp %g2, %g1 + bl bzero_bss_loop + nop + + call C_LABEL(init_me) ! Fun with empirical constants and prom + nop + + /* Dump back into the prom */ +get_me_out_of_here: + set C_LABEL(romvec), %g2 + ld [%g2], %g2 + ld [%g2 + 0x74], %g2 + restore + call %g2 + nop + + + diff --git a/arch/sparc/boot/bare.h b/arch/sparc/boot/bare.h new file mode 100644 index 000000000..b84178c45 --- /dev/null +++ b/arch/sparc/boot/bare.h @@ -0,0 +1,18 @@ +/* $Id: bare.h,v 1.2 1995/11/25 00:57:41 davem Exp $ + * bare.h: Defines for the low level entry code of the BOOT program. + * We include in the head.h stuff that the real kernel uses + * and this saves a lot of repetition here. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#include <asm/head.h> +#include <asm/psr.h> +#include <asm/cprefix.h> + +#define SANE_PIL (0xd00) /* No interrupts except clock and unmaskable NMI's */ +#define SANE_PSR (SANE_PIL|PSR_S|PSR_ET) + +#define BOOTBLOCK_NENTRIES 0x40 /* Number of entries in the boot block */ +#define BOOTBLOCK_ENTSIZE 0x04 /* Size in bytes of each boot block entry */ + diff --git a/arch/sparc/boot/empirical.h b/arch/sparc/boot/empirical.h new file mode 100644 index 000000000..e13b8c80a --- /dev/null +++ b/arch/sparc/boot/empirical.h @@ -0,0 +1,8 @@ +/* $Id: empirical.h,v 1.2 1996/04/23 01:53:42 davem Exp $ + * empirical.h: Nasty hacks.... + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#define DEF_BOGO 25 + diff --git a/arch/sparc/boot/init_me.c b/arch/sparc/boot/init_me.c new file mode 100644 index 000000000..ad26a1969 --- /dev/null +++ b/arch/sparc/boot/init_me.c @@ -0,0 +1,69 @@ +/* $Id: init_me.c,v 1.3 1996/04/21 10:30:09 davem Exp $ + * init_me.c: Initialize empirical constants and gather some info from + * the boot prom. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#include <asm/openprom.h> /* For property declarations and the prom structs */ +#include <asm/oplib.h> +#include <asm/vac-ops.h> + +#include "empirical.h" /* Don't ask... */ + +#define DEBUG_INIT_ME /* Tell me what's going on */ + +unsigned int nwindows; /* Set in bare.S */ +unsigned int nwindowsm1; +unsigned int pac_or_vac; /* 0 means "dunno" 1 means "VAC" 2 means "PAC" */ +unsigned int pvac_size; /* Use the same two variables for a PAC and VAC */ +unsigned int pvac_linesize; +unsigned int pac_size; +int num_segmaps; +int num_contexts; +unsigned int BOGOMIPS; /* bogosity without the VAC cache on */ +unsigned int BOGOMIPS_WCACHE; /* bogosity with the VAC cache */ +unsigned int delay_factor; + +extern int prom_node_root; +void (*printk)(const char *str, ...); + +void init_me(void) +{ + unsigned int grrr; + + printk = romvec->pv_printf; + prom_node_root = prom_nextnode(0); + prom_getprop(prom_node_root, "mmu-npmg", &num_segmaps, + sizeof(unsigned int)); + + pvac_size = prom_getint_default(prom_node_root, "vac-size", 65536); + + pvac_linesize = prom_getint_default(prom_node_root, "vac-linesize", 16); + + grrr = prom_getint_default(prom_node_root, "mips-on", 0); + if(!grrr) { + grrr = prom_getint_default(prom_node_root, "clock-frequency", 0); + if(grrr > 15000000 && grrr < 100000000) { + BOGOMIPS = 3; + BOGOMIPS_WCACHE = grrr / 1000000; + } else { + BOGOMIPS = DEF_BOGO; + BOGOMIPS_WCACHE = DEF_BOGO; + } + } else (BOGOMIPS_WCACHE = grrr, + BOGOMIPS = prom_getint(prom_node_root, "mips-off")); + +#ifdef DEBUG_INIT_ME + (*(romvec->pv_printf))("\nBOGOMIPS %d\n", (int) BOGOMIPS); + (*(romvec->pv_printf))("BOGOMIPS_WCACHE %d\n", (int) BOGOMIPS_WCACHE); + (*(romvec->pv_printf))("pvac_size %d\n", (int) pvac_size); + (*(romvec->pv_printf))("pvac_linesize %d\n", (int) pvac_linesize); + (*(romvec->pv_printf))("num_segmaps %d\n", (int) num_segmaps); +#endif + + delay_factor = (BOGOMIPS > 3) ? ((BOGOMIPS - 2) >> 1) : 11; + + (*(romvec->pv_printf))("\nLILO: \n"); + return; +} |