You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,59 @@
|
||||
menu "Kernel hacking"
|
||||
|
||||
source "lib/Kconfig.debug"
|
||||
|
||||
config EARLY_PRINTK
|
||||
bool
|
||||
depends on ALPHA_GENERIC || ALPHA_SRM
|
||||
default y
|
||||
|
||||
config DEBUG_RWLOCK
|
||||
bool "Read-write spinlock debugging"
|
||||
depends on DEBUG_KERNEL
|
||||
help
|
||||
If you say Y here then read-write lock processing will count how many
|
||||
times it has tried to get the lock and issue an error message after
|
||||
too many attempts. If you suspect a rwlock problem or a kernel
|
||||
hacker asks for this option then say Y. Otherwise say N.
|
||||
|
||||
config DEBUG_SEMAPHORE
|
||||
bool "Semaphore debugging"
|
||||
depends on DEBUG_KERNEL
|
||||
help
|
||||
If you say Y here then semaphore processing will issue lots of
|
||||
verbose debugging messages. If you suspect a semaphore problem or a
|
||||
kernel hacker asks for this option then say Y. Otherwise say N.
|
||||
|
||||
config ALPHA_LEGACY_START_ADDRESS
|
||||
bool "Legacy kernel start address"
|
||||
depends on ALPHA_GENERIC
|
||||
default n
|
||||
---help---
|
||||
The 2.4 kernel changed the kernel start address from 0x310000
|
||||
to 0x810000 to make room for the Wildfire's larger SRM console.
|
||||
Recent consoles on Titan and Marvel machines also require the
|
||||
extra room.
|
||||
|
||||
If you're using aboot 0.7 or later, the bootloader will examine the
|
||||
ELF headers to determine where to transfer control. Unfortunately,
|
||||
most older bootloaders -- APB or MILO -- hardcoded the kernel start
|
||||
address rather than examining the ELF headers, and the result is a
|
||||
hard lockup.
|
||||
|
||||
Say Y if you have a broken bootloader. Say N if you do not, or if
|
||||
you wish to run on Wildfire, Titan, or Marvel.
|
||||
|
||||
config ALPHA_LEGACY_START_ADDRESS
|
||||
bool
|
||||
depends on !ALPHA_GENERIC && !ALPHA_TITAN && !ALPHA_MARVEL && !ALPHA_WILDFIRE
|
||||
default y
|
||||
|
||||
config MATHEMU
|
||||
tristate "Kernel FP software completion" if DEBUG_KERNEL && !SMP
|
||||
default y if !DEBUG_KERNEL || SMP
|
||||
help
|
||||
This option is required for IEEE compliant floating point arithmetic
|
||||
on the Alpha. The only time you would ever not say Y is to say M in
|
||||
order to debug the code. Say Y unless you know what you are doing.
|
||||
|
||||
endmenu
|
||||
@@ -0,0 +1,130 @@
|
||||
#
|
||||
# alpha/Makefile
|
||||
#
|
||||
# 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) 1994 by Linus Torvalds
|
||||
#
|
||||
|
||||
NM := $(NM) -B
|
||||
|
||||
LDFLAGS_vmlinux := -static -N #-relax
|
||||
CHECKFLAGS += -D__alpha__ -m64
|
||||
cflags-y := -pipe -mno-fp-regs -ffixed-8
|
||||
|
||||
# Determine if we can use the BWX instructions with GAS.
|
||||
old_gas := $(shell if $(AS) --version 2>&1 | grep 'version 2.7' > /dev/null; then echo y; else echo n; fi)
|
||||
|
||||
ifeq ($(old_gas),y)
|
||||
$(error The assembler '$(AS)' does not support the BWX instruction)
|
||||
endif
|
||||
|
||||
# Determine if GCC understands the -mcpu= option.
|
||||
have_mcpu := $(call cc-option-yn, -mcpu=ev5)
|
||||
have_mcpu_pca56 := $(call cc-option-yn, -mcpu=pca56)
|
||||
have_mcpu_ev6 := $(call cc-option-yn, -mcpu=ev6)
|
||||
have_mcpu_ev67 := $(call cc-option-yn, -mcpu=ev67)
|
||||
have_msmall_data := $(call cc-option-yn, -msmall-data)
|
||||
|
||||
cflags-$(have_msmall_data) += -msmall-data
|
||||
|
||||
# Turn on the proper cpu optimizations.
|
||||
ifeq ($(have_mcpu),y)
|
||||
mcpu_done := n
|
||||
# If GENERIC, make sure to turn off any instruction set extensions that
|
||||
# the host compiler might have on by default. Given that EV4 and EV5
|
||||
# have the same instruction set, prefer EV5 because an EV5 schedule is
|
||||
# more likely to keep an EV4 processor busy than vice-versa.
|
||||
ifeq ($(CONFIG_ALPHA_GENERIC),y)
|
||||
mcpu := ev5
|
||||
mcpu_done := y
|
||||
endif
|
||||
ifeq ($(mcpu_done)$(CONFIG_ALPHA_SX164)$(have_mcpu_pca56),nyy)
|
||||
mcpu := pca56
|
||||
mcpu_done := y
|
||||
endif
|
||||
ifeq ($(mcpu_done)$(CONFIG_ALPHA_POLARIS)$(have_mcpu_pca56),nyy)
|
||||
mcpu := pca56
|
||||
mcpu_done := y
|
||||
endif
|
||||
ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV4),ny)
|
||||
mcpu := ev4
|
||||
mcpu_done := y
|
||||
endif
|
||||
ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV56),ny)
|
||||
mcpu := ev56
|
||||
mcpu_done := y
|
||||
endif
|
||||
ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV5),ny)
|
||||
mcpu := ev5
|
||||
mcpu_done := y
|
||||
endif
|
||||
ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV67)$(have_mcpu_ev67),nyy)
|
||||
mcpu := ev67
|
||||
mcpu_done := y
|
||||
endif
|
||||
ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV6),ny)
|
||||
ifeq ($(have_mcpu_ev6),y)
|
||||
mcpu := ev6
|
||||
else
|
||||
ifeq ($(have_mcpu_pca56),y)
|
||||
mcpu := pca56
|
||||
else
|
||||
mcpu=ev56
|
||||
endif
|
||||
endif
|
||||
mcpu_done := y
|
||||
endif
|
||||
cflags-$(mcpu_done) += -mcpu=$(mcpu)
|
||||
endif
|
||||
|
||||
|
||||
# For TSUNAMI, we must have the assembler not emulate our instructions.
|
||||
# The same is true for IRONGATE, POLARIS, PYXIS.
|
||||
# BWX is most important, but we don't really want any emulation ever.
|
||||
CFLAGS += $(cflags-y) -Wa,-mev6
|
||||
|
||||
head-y := arch/alpha/kernel/head.o
|
||||
|
||||
core-y += arch/alpha/kernel/ arch/alpha/mm/
|
||||
core-$(CONFIG_MATHEMU) += arch/alpha/math-emu/
|
||||
drivers-$(CONFIG_OPROFILE) += arch/alpha/oprofile/
|
||||
libs-y += arch/alpha/lib/
|
||||
|
||||
# export what is needed by arch/alpha/boot/Makefile
|
||||
LIBS_Y := $(patsubst %/, %/lib.a, $(libs-y))
|
||||
export LIBS_Y
|
||||
|
||||
boot := arch/alpha/boot
|
||||
|
||||
#Default target when executing make with no arguments
|
||||
all boot: $(boot)/vmlinux.gz
|
||||
|
||||
$(boot)/vmlinux.gz: vmlinux
|
||||
$(Q)$(MAKE) $(build)=$(boot) $@
|
||||
|
||||
bootimage bootpfile bootpzfile: vmlinux
|
||||
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
|
||||
|
||||
|
||||
prepare: include/asm-$(ARCH)/asm_offsets.h
|
||||
|
||||
arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
|
||||
include/config/MARKER
|
||||
|
||||
include/asm-$(ARCH)/asm_offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
|
||||
$(call filechk,gen-asm-offsets)
|
||||
|
||||
archclean:
|
||||
$(Q)$(MAKE) $(clean)=$(boot)
|
||||
|
||||
CLEAN_FILES += include/asm-$(ARCH)/asm_offsets.h
|
||||
|
||||
define archhelp
|
||||
echo '* boot - Compressed kernel image (arch/alpha/boot/vmlinux.gz)'
|
||||
echo ' bootimage - SRM bootable image (arch/alpha/boot/bootimage)'
|
||||
echo ' bootpfile - BOOTP bootable image (arch/alpha/boot/bootpfile)'
|
||||
echo ' bootpzfile - compressed kernel BOOTP image (arch/alpha/boot/bootpzfile)'
|
||||
endef
|
||||
@@ -0,0 +1,116 @@
|
||||
#
|
||||
# arch/alpha/boot/Makefile
|
||||
#
|
||||
# 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) 1994 by Linus Torvalds
|
||||
#
|
||||
|
||||
hostprogs-y := tools/mkbb tools/objstrip
|
||||
targets := vmlinux.gz vmlinux \
|
||||
vmlinux.nh tools/lxboot tools/bootlx tools/bootph \
|
||||
tools/bootpzh bootloader bootpheader bootpzheader
|
||||
OBJSTRIP := $(obj)/tools/objstrip
|
||||
|
||||
# SRM bootable image. Copy to offset 512 of a partition.
|
||||
$(obj)/bootimage: $(addprefix $(obj)/tools/,mkbb lxboot bootlx) $(obj)/vmlinux.nh
|
||||
( cat $(obj)/tools/lxboot $(obj)/tools/bootlx $(obj)/vmlinux.nh ) > $@
|
||||
$(obj)/tools/mkbb $@ $(obj)/tools/lxboot
|
||||
@echo ' Bootimage $@ is ready'
|
||||
|
||||
# BOOTP bootable image. Define INITRD during make to append initrd image.
|
||||
$(obj)/bootpfile: $(obj)/tools/bootph $(obj)/vmlinux.nh
|
||||
cat $(obj)/tools/bootph $(obj)/vmlinux.nh > $@
|
||||
ifdef INITRD
|
||||
cat $(INITRD) >> $@
|
||||
endif
|
||||
|
||||
# Compressed kernel BOOTP bootable image.
|
||||
# Define INITRD during make to append initrd image.
|
||||
$(obj)/bootpzfile: $(obj)/tools/bootpzh $(obj)/vmlinux.nh.gz
|
||||
cat $(obj)/tools/bootpzh $(obj)/vmlinux.nh.gz > $@
|
||||
ifdef INITRD
|
||||
cat $(INITRD) >> $@
|
||||
endif
|
||||
|
||||
# Compressed kernel image
|
||||
$(obj)/vmlinux.gz: $(obj)/vmlinux FORCE
|
||||
$(call if_changed,gzip)
|
||||
@echo ' Kernel $@ is ready'
|
||||
|
||||
$(obj)/main.o: $(obj)/ksize.h
|
||||
$(obj)/bootp.o: $(obj)/ksize.h
|
||||
$(obj)/bootpz.o: $(obj)/kzsize.h
|
||||
|
||||
$(obj)/ksize.h: $(obj)/vmlinux.nh FORCE
|
||||
echo "#define KERNEL_SIZE `ls -l $(obj)/vmlinux.nh | awk '{print $$5}'`" > $@T
|
||||
ifdef INITRD
|
||||
[ -f $(INITRD) ] || exit 1
|
||||
echo "#define INITRD_IMAGE_SIZE `ls -l $(INITRD) | awk '{print $$5}'`" >> $@T
|
||||
endif
|
||||
cmp -s $@T $@ || mv -f $@T $@
|
||||
rm -f $@T
|
||||
|
||||
$(obj)/kzsize.h: $(obj)/vmlinux.nh.gz FORCE
|
||||
echo "#define KERNEL_SIZE `ls -l $(obj)/vmlinux.nh | awk '{print $$5}'`" > $@T
|
||||
echo "#define KERNEL_Z_SIZE `ls -l $(obj)/vmlinux.nh.gz | awk '{print $$5}'`" >> $@T
|
||||
ifdef INITRD
|
||||
[ -f $(INITRD) ] || exit 1
|
||||
echo "#define INITRD_IMAGE_SIZE `ls -l $(INITRD) | awk '{print $$5}'`" >> $@T
|
||||
endif
|
||||
cmp -s $@T $@ || mv -f $@T $@
|
||||
rm -f $@T
|
||||
|
||||
quiet_cmd_strip = STRIP $@
|
||||
cmd_strip = $(STRIP) -o $@ $<
|
||||
|
||||
$(obj)/vmlinux: vmlinux FORCE
|
||||
$(call if_changed,strip)
|
||||
|
||||
quiet_cmd_objstrip = OBJSTRIP $@
|
||||
cmd_objstrip = $(OBJSTRIP) $(OSFLAGS_$(@F)) $< $@
|
||||
|
||||
OSFLAGS_vmlinux.nh := -v
|
||||
OSFLAGS_lxboot := -p
|
||||
OSFLAGS_bootlx := -vb
|
||||
OSFLAGS_bootph := -vb
|
||||
OSFLAGS_bootpzh := -vb
|
||||
|
||||
$(obj)/vmlinux.nh: vmlinux $(OBJSTRIP) FORCE
|
||||
$(call if_changed,objstrip)
|
||||
|
||||
$(obj)/vmlinux.nh.gz: $(obj)/vmlinux.nh FORCE
|
||||
$(call if_changed,gzip)
|
||||
|
||||
$(obj)/tools/lxboot: $(obj)/bootloader $(OBJSTRIP) FORCE
|
||||
$(call if_changed,objstrip)
|
||||
|
||||
$(obj)/tools/bootlx: $(obj)/bootloader $(OBJSTRIP) FORCE
|
||||
$(call if_changed,objstrip)
|
||||
|
||||
$(obj)/tools/bootph: $(obj)/bootpheader $(OBJSTRIP) FORCE
|
||||
$(call if_changed,objstrip)
|
||||
|
||||
$(obj)/tools/bootpzh: $(obj)/bootpzheader $(OBJSTRIP) FORCE
|
||||
$(call if_changed,objstrip)
|
||||
|
||||
LDFLAGS_bootloader := -static -uvsprintf -T #-N -relax
|
||||
LDFLAGS_bootpheader := -static -uvsprintf -T #-N -relax
|
||||
LDFLAGS_bootpzheader := -static -uvsprintf -T #-N -relax
|
||||
|
||||
OBJ_bootlx := $(obj)/head.o $(obj)/main.o
|
||||
OBJ_bootph := $(obj)/head.o $(obj)/bootp.o
|
||||
OBJ_bootpzh := $(obj)/head.o $(obj)/bootpz.o $(obj)/misc.o
|
||||
|
||||
$(obj)/bootloader: $(obj)/bootloader.lds $(OBJ_bootlx) FORCE
|
||||
$(call if_changed,ld)
|
||||
|
||||
$(obj)/bootpheader: $(obj)/bootloader.lds $(OBJ_bootph) $(LIBS_Y) FORCE
|
||||
$(call if_changed,ld)
|
||||
|
||||
$(obj)/bootpzheader: $(obj)/bootloader.lds $(OBJ_bootpzh) $(LIBS_Y) FORCE
|
||||
$(call if_changed,ld)
|
||||
|
||||
$(obj)/misc.o: lib/inflate.c
|
||||
@@ -0,0 +1,24 @@
|
||||
OUTPUT_FORMAT("elf64-alpha")
|
||||
ENTRY(__start)
|
||||
printk = srm_printk;
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x20000000;
|
||||
.text : { *(.text) }
|
||||
_etext = .;
|
||||
PROVIDE (etext = .);
|
||||
.rodata : { *(.rodata) *(.rodata.*) }
|
||||
.data : { *(.data) CONSTRUCTORS }
|
||||
.got : { *(.got) }
|
||||
.sdata : { *(.sdata) }
|
||||
_edata = .;
|
||||
PROVIDE (edata = .);
|
||||
.sbss : { *(.sbss) *(.scommon) }
|
||||
.bss : { *(.bss) *(COMMON) }
|
||||
_end = . ;
|
||||
PROVIDE (end = .);
|
||||
|
||||
.mdebug 0 : { *(.mdebug) }
|
||||
.note 0 : { *(.note) }
|
||||
.comment 0 : { *(.comment) }
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* arch/alpha/boot/bootp.c
|
||||
*
|
||||
* Copyright (C) 1997 Jay Estabrook
|
||||
*
|
||||
* This file is used for creating a bootp file for the Linux/AXP kernel
|
||||
*
|
||||
* based significantly on the arch/alpha/boot/main.c of Linus Torvalds
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/console.h>
|
||||
#include <asm/hwrpb.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "ksize.h"
|
||||
|
||||
extern unsigned long switch_to_osf_pal(unsigned long nr,
|
||||
struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa,
|
||||
unsigned long *vptb);
|
||||
|
||||
extern void move_stack(unsigned long new_stack);
|
||||
|
||||
struct hwrpb_struct *hwrpb = INIT_HWRPB;
|
||||
static struct pcb_struct pcb_va[1];
|
||||
|
||||
/*
|
||||
* Find a physical address of a virtual object..
|
||||
*
|
||||
* This is easy using the virtual page table address.
|
||||
*/
|
||||
|
||||
static inline void *
|
||||
find_pa(unsigned long *vptb, void *ptr)
|
||||
{
|
||||
unsigned long address = (unsigned long) ptr;
|
||||
unsigned long result;
|
||||
|
||||
result = vptb[address >> 13];
|
||||
result >>= 32;
|
||||
result <<= 13;
|
||||
result |= address & 0x1fff;
|
||||
return (void *) result;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function moves into OSF/1 pal-code, and has a temporary
|
||||
* PCB for that. The kernel proper should replace this PCB with
|
||||
* the real one as soon as possible.
|
||||
*
|
||||
* The page table muckery in here depends on the fact that the boot
|
||||
* code has the L1 page table identity-map itself in the second PTE
|
||||
* in the L1 page table. Thus the L1-page is virtually addressable
|
||||
* itself (through three levels) at virtual address 0x200802000.
|
||||
*/
|
||||
|
||||
#define VPTB ((unsigned long *) 0x200000000)
|
||||
#define L1 ((unsigned long *) 0x200802000)
|
||||
|
||||
void
|
||||
pal_init(void)
|
||||
{
|
||||
unsigned long i, rev;
|
||||
struct percpu_struct * percpu;
|
||||
struct pcb_struct * pcb_pa;
|
||||
|
||||
/* Create the dummy PCB. */
|
||||
pcb_va->ksp = 0;
|
||||
pcb_va->usp = 0;
|
||||
pcb_va->ptbr = L1[1] >> 32;
|
||||
pcb_va->asn = 0;
|
||||
pcb_va->pcc = 0;
|
||||
pcb_va->unique = 0;
|
||||
pcb_va->flags = 1;
|
||||
pcb_va->res1 = 0;
|
||||
pcb_va->res2 = 0;
|
||||
pcb_pa = find_pa(VPTB, pcb_va);
|
||||
|
||||
/*
|
||||
* a0 = 2 (OSF)
|
||||
* a1 = return address, but we give the asm the vaddr of the PCB
|
||||
* a2 = physical addr of PCB
|
||||
* a3 = new virtual page table pointer
|
||||
* a4 = KSP (but the asm sets it)
|
||||
*/
|
||||
srm_printk("Switching to OSF PAL-code .. ");
|
||||
|
||||
i = switch_to_osf_pal(2, pcb_va, pcb_pa, VPTB);
|
||||
if (i) {
|
||||
srm_printk("failed, code %ld\n", i);
|
||||
__halt();
|
||||
}
|
||||
|
||||
percpu = (struct percpu_struct *)
|
||||
(INIT_HWRPB->processor_offset + (unsigned long) INIT_HWRPB);
|
||||
rev = percpu->pal_revision = percpu->palcode_avail[2];
|
||||
|
||||
srm_printk("Ok (rev %lx)\n", rev);
|
||||
|
||||
tbia(); /* do it directly in case we are SMP */
|
||||
}
|
||||
|
||||
static inline void
|
||||
load(unsigned long dst, unsigned long src, unsigned long count)
|
||||
{
|
||||
memcpy((void *)dst, (void *)src, count);
|
||||
}
|
||||
|
||||
/*
|
||||
* Start the kernel.
|
||||
*/
|
||||
static inline void
|
||||
runkernel(void)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"bis %0,%0,$27\n\t"
|
||||
"jmp ($27)"
|
||||
: /* no outputs: it doesn't even return */
|
||||
: "r" (START_ADDR));
|
||||
}
|
||||
|
||||
extern char _end;
|
||||
#define KERNEL_ORIGIN \
|
||||
((((unsigned long)&_end) + 511) & ~511)
|
||||
|
||||
void
|
||||
start_kernel(void)
|
||||
{
|
||||
/*
|
||||
* Note that this crufty stuff with static and envval
|
||||
* and envbuf is because:
|
||||
*
|
||||
* 1. Frequently, the stack is short, and we don't want to overrun;
|
||||
* 2. Frequently the stack is where we are going to copy the kernel to;
|
||||
* 3. A certain SRM console required the GET_ENV output to stack.
|
||||
* ??? A comment in the aboot sources indicates that the GET_ENV
|
||||
* destination must be quadword aligned. Might this explain the
|
||||
* behaviour, rather than requiring output to the stack, which
|
||||
* seems rather far-fetched.
|
||||
*/
|
||||
static long nbytes;
|
||||
static char envval[256] __attribute__((aligned(8)));
|
||||
static unsigned long initrd_start;
|
||||
|
||||
srm_printk("Linux/AXP bootp loader for Linux " UTS_RELEASE "\n");
|
||||
if (INIT_HWRPB->pagesize != 8192) {
|
||||
srm_printk("Expected 8kB pages, got %ldkB\n",
|
||||
INIT_HWRPB->pagesize >> 10);
|
||||
return;
|
||||
}
|
||||
if (INIT_HWRPB->vptb != (unsigned long) VPTB) {
|
||||
srm_printk("Expected vptb at %p, got %p\n",
|
||||
VPTB, (void *)INIT_HWRPB->vptb);
|
||||
return;
|
||||
}
|
||||
pal_init();
|
||||
|
||||
/* The initrd must be page-aligned. See below for the
|
||||
cause of the magic number 5. */
|
||||
initrd_start = ((START_ADDR + 5*KERNEL_SIZE + PAGE_SIZE) |
|
||||
(PAGE_SIZE-1)) + 1;
|
||||
#ifdef INITRD_IMAGE_SIZE
|
||||
srm_printk("Initrd positioned at %#lx\n", initrd_start);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Move the stack to a safe place to ensure it won't be
|
||||
* overwritten by kernel image.
|
||||
*/
|
||||
move_stack(initrd_start - PAGE_SIZE);
|
||||
|
||||
nbytes = callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval));
|
||||
if (nbytes < 0 || nbytes >= sizeof(envval)) {
|
||||
nbytes = 0;
|
||||
}
|
||||
envval[nbytes] = '\0';
|
||||
srm_printk("Loading the kernel...'%s'\n", envval);
|
||||
|
||||
/* NOTE: *no* callbacks or printouts from here on out!!! */
|
||||
|
||||
/* This is a hack, as some consoles seem to get virtual 20000000 (ie
|
||||
* where the SRM console puts the kernel bootp image) memory
|
||||
* overlapping physical memory where the kernel wants to be put,
|
||||
* which causes real problems when attempting to copy the former to
|
||||
* the latter... :-(
|
||||
*
|
||||
* So, we first move the kernel virtual-to-physical way above where
|
||||
* we physically want the kernel to end up, then copy it from there
|
||||
* to its final resting place... ;-}
|
||||
*
|
||||
* Sigh... */
|
||||
|
||||
#ifdef INITRD_IMAGE_SIZE
|
||||
load(initrd_start, KERNEL_ORIGIN+KERNEL_SIZE, INITRD_IMAGE_SIZE);
|
||||
#endif
|
||||
load(START_ADDR+(4*KERNEL_SIZE), KERNEL_ORIGIN, KERNEL_SIZE);
|
||||
load(START_ADDR, START_ADDR+(4*KERNEL_SIZE), KERNEL_SIZE);
|
||||
|
||||
memset((char*)ZERO_PGE, 0, PAGE_SIZE);
|
||||
strcpy((char*)ZERO_PGE, envval);
|
||||
#ifdef INITRD_IMAGE_SIZE
|
||||
((long *)(ZERO_PGE+256))[0] = initrd_start;
|
||||
((long *)(ZERO_PGE+256))[1] = INITRD_IMAGE_SIZE;
|
||||
#endif
|
||||
|
||||
runkernel();
|
||||
}
|
||||
@@ -0,0 +1,469 @@
|
||||
/*
|
||||
* arch/alpha/boot/bootpz.c
|
||||
*
|
||||
* Copyright (C) 1997 Jay Estabrook
|
||||
*
|
||||
* This file is used for creating a compressed BOOTP file for the
|
||||
* Linux/AXP kernel
|
||||
*
|
||||
* based significantly on the arch/alpha/boot/main.c of Linus Torvalds
|
||||
* and the decompression code from MILO.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/console.h>
|
||||
#include <asm/hwrpb.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "kzsize.h"
|
||||
|
||||
/* FIXME FIXME FIXME */
|
||||
#define MALLOC_AREA_SIZE 0x200000 /* 2MB for now */
|
||||
/* FIXME FIXME FIXME */
|
||||
|
||||
|
||||
/*
|
||||
WARNING NOTE
|
||||
|
||||
It is very possible that turning on additional messages may cause
|
||||
kernel image corruption due to stack usage to do the printing.
|
||||
|
||||
*/
|
||||
|
||||
#undef DEBUG_CHECK_RANGE
|
||||
#undef DEBUG_ADDRESSES
|
||||
#undef DEBUG_LAST_STEPS
|
||||
|
||||
extern unsigned long switch_to_osf_pal(unsigned long nr,
|
||||
struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa,
|
||||
unsigned long *vptb);
|
||||
|
||||
extern int decompress_kernel(void* destination, void *source,
|
||||
size_t ksize, size_t kzsize);
|
||||
|
||||
extern void move_stack(unsigned long new_stack);
|
||||
|
||||
struct hwrpb_struct *hwrpb = INIT_HWRPB;
|
||||
static struct pcb_struct pcb_va[1];
|
||||
|
||||
/*
|
||||
* Find a physical address of a virtual object..
|
||||
*
|
||||
* This is easy using the virtual page table address.
|
||||
*/
|
||||
#define VPTB ((unsigned long *) 0x200000000)
|
||||
|
||||
static inline unsigned long
|
||||
find_pa(unsigned long address)
|
||||
{
|
||||
unsigned long result;
|
||||
|
||||
result = VPTB[address >> 13];
|
||||
result >>= 32;
|
||||
result <<= 13;
|
||||
result |= address & 0x1fff;
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
check_range(unsigned long vstart, unsigned long vend,
|
||||
unsigned long kstart, unsigned long kend)
|
||||
{
|
||||
unsigned long vaddr, kaddr;
|
||||
|
||||
#ifdef DEBUG_CHECK_RANGE
|
||||
srm_printk("check_range: V[0x%lx:0x%lx] K[0x%lx:0x%lx]\n",
|
||||
vstart, vend, kstart, kend);
|
||||
#endif
|
||||
/* do some range checking for detecting an overlap... */
|
||||
for (vaddr = vstart; vaddr <= vend; vaddr += PAGE_SIZE)
|
||||
{
|
||||
kaddr = (find_pa(vaddr) | PAGE_OFFSET);
|
||||
if (kaddr >= kstart && kaddr <= kend)
|
||||
{
|
||||
#ifdef DEBUG_CHECK_RANGE
|
||||
srm_printk("OVERLAP: vaddr 0x%lx kaddr 0x%lx"
|
||||
" [0x%lx:0x%lx]\n",
|
||||
vaddr, kaddr, kstart, kend);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function moves into OSF/1 pal-code, and has a temporary
|
||||
* PCB for that. The kernel proper should replace this PCB with
|
||||
* the real one as soon as possible.
|
||||
*
|
||||
* The page table muckery in here depends on the fact that the boot
|
||||
* code has the L1 page table identity-map itself in the second PTE
|
||||
* in the L1 page table. Thus the L1-page is virtually addressable
|
||||
* itself (through three levels) at virtual address 0x200802000.
|
||||
*/
|
||||
|
||||
#define L1 ((unsigned long *) 0x200802000)
|
||||
|
||||
void
|
||||
pal_init(void)
|
||||
{
|
||||
unsigned long i, rev;
|
||||
struct percpu_struct * percpu;
|
||||
struct pcb_struct * pcb_pa;
|
||||
|
||||
/* Create the dummy PCB. */
|
||||
pcb_va->ksp = 0;
|
||||
pcb_va->usp = 0;
|
||||
pcb_va->ptbr = L1[1] >> 32;
|
||||
pcb_va->asn = 0;
|
||||
pcb_va->pcc = 0;
|
||||
pcb_va->unique = 0;
|
||||
pcb_va->flags = 1;
|
||||
pcb_va->res1 = 0;
|
||||
pcb_va->res2 = 0;
|
||||
pcb_pa = (struct pcb_struct *)find_pa((unsigned long)pcb_va);
|
||||
|
||||
/*
|
||||
* a0 = 2 (OSF)
|
||||
* a1 = return address, but we give the asm the vaddr of the PCB
|
||||
* a2 = physical addr of PCB
|
||||
* a3 = new virtual page table pointer
|
||||
* a4 = KSP (but the asm sets it)
|
||||
*/
|
||||
srm_printk("Switching to OSF PAL-code... ");
|
||||
|
||||
i = switch_to_osf_pal(2, pcb_va, pcb_pa, VPTB);
|
||||
if (i) {
|
||||
srm_printk("failed, code %ld\n", i);
|
||||
__halt();
|
||||
}
|
||||
|
||||
percpu = (struct percpu_struct *)
|
||||
(INIT_HWRPB->processor_offset + (unsigned long) INIT_HWRPB);
|
||||
rev = percpu->pal_revision = percpu->palcode_avail[2];
|
||||
|
||||
srm_printk("OK (rev %lx)\n", rev);
|
||||
|
||||
tbia(); /* do it directly in case we are SMP */
|
||||
}
|
||||
|
||||
/*
|
||||
* Start the kernel.
|
||||
*/
|
||||
static inline void
|
||||
runkernel(void)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"bis %0,%0,$27\n\t"
|
||||
"jmp ($27)"
|
||||
: /* no outputs: it doesn't even return */
|
||||
: "r" (START_ADDR));
|
||||
}
|
||||
|
||||
/* Must record the SP (it is virtual) on entry, so we can make sure
|
||||
not to overwrite it during movement or decompression. */
|
||||
unsigned long SP_on_entry;
|
||||
|
||||
/* Calculate the kernel image address based on the end of the BOOTP
|
||||
bootstrapper (ie this program).
|
||||
*/
|
||||
extern char _end;
|
||||
#define KERNEL_ORIGIN \
|
||||
((((unsigned long)&_end) + 511) & ~511)
|
||||
|
||||
/* Round address to next higher page boundary. */
|
||||
#define NEXT_PAGE(a) (((a) | (PAGE_SIZE - 1)) + 1)
|
||||
|
||||
#ifdef INITRD_IMAGE_SIZE
|
||||
# define REAL_INITRD_SIZE INITRD_IMAGE_SIZE
|
||||
#else
|
||||
# define REAL_INITRD_SIZE 0
|
||||
#endif
|
||||
|
||||
/* Defines from include/asm-alpha/system.h
|
||||
|
||||
BOOT_ADDR Virtual address at which the consoles loads
|
||||
the BOOTP image.
|
||||
|
||||
KERNEL_START KSEG address at which the kernel is built to run,
|
||||
which includes some initial data pages before the
|
||||
code.
|
||||
|
||||
START_ADDR KSEG address of the entry point of kernel code.
|
||||
|
||||
ZERO_PGE KSEG address of page full of zeroes, but
|
||||
upon entry to kerne cvan be expected
|
||||
to hold the parameter list and possible
|
||||
INTRD information.
|
||||
|
||||
These are used in the local defines below.
|
||||
*/
|
||||
|
||||
|
||||
/* Virtual addresses for the BOOTP image. Note that this includes the
|
||||
bootstrapper code as well as the compressed kernel image, and
|
||||
possibly the INITRD image.
|
||||
|
||||
Oh, and do NOT forget the STACK, which appears to be placed virtually
|
||||
beyond the end of the loaded image.
|
||||
*/
|
||||
#define V_BOOT_IMAGE_START BOOT_ADDR
|
||||
#define V_BOOT_IMAGE_END SP_on_entry
|
||||
|
||||
/* Virtual addresses for just the bootstrapper part of the BOOTP image. */
|
||||
#define V_BOOTSTRAPPER_START BOOT_ADDR
|
||||
#define V_BOOTSTRAPPER_END KERNEL_ORIGIN
|
||||
|
||||
/* Virtual addresses for just the data part of the BOOTP
|
||||
image. This may also include the INITRD image, but always
|
||||
includes the STACK.
|
||||
*/
|
||||
#define V_DATA_START KERNEL_ORIGIN
|
||||
#define V_INITRD_START (KERNEL_ORIGIN + KERNEL_Z_SIZE)
|
||||
#define V_INTRD_END (V_INITRD_START + REAL_INITRD_SIZE)
|
||||
#define V_DATA_END V_BOOT_IMAGE_END
|
||||
|
||||
/* KSEG addresses for the uncompressed kernel.
|
||||
|
||||
Note that the end address includes workspace for the decompression.
|
||||
Note also that the DATA_START address is ZERO_PGE, to which we write
|
||||
just before jumping to the kernel image at START_ADDR.
|
||||
*/
|
||||
#define K_KERNEL_DATA_START ZERO_PGE
|
||||
#define K_KERNEL_IMAGE_START START_ADDR
|
||||
#define K_KERNEL_IMAGE_END (START_ADDR + KERNEL_SIZE)
|
||||
|
||||
/* Define to where we may have to decompress the kernel image, before
|
||||
we move it to the final position, in case of overlap. This will be
|
||||
above the final position of the kernel.
|
||||
|
||||
Regardless of overlap, we move the INITRD image to the end of this
|
||||
copy area, because there needs to be a buffer area after the kernel
|
||||
for "bootmem" anyway.
|
||||
*/
|
||||
#define K_COPY_IMAGE_START NEXT_PAGE(K_KERNEL_IMAGE_END)
|
||||
/* Reserve one page below INITRD for the new stack. */
|
||||
#define K_INITRD_START \
|
||||
NEXT_PAGE(K_COPY_IMAGE_START + KERNEL_SIZE + PAGE_SIZE)
|
||||
#define K_COPY_IMAGE_END \
|
||||
(K_INITRD_START + REAL_INITRD_SIZE + MALLOC_AREA_SIZE)
|
||||
#define K_COPY_IMAGE_SIZE \
|
||||
NEXT_PAGE(K_COPY_IMAGE_END - K_COPY_IMAGE_START)
|
||||
|
||||
void
|
||||
start_kernel(void)
|
||||
{
|
||||
int must_move = 0;
|
||||
|
||||
/* Initialize these for the decompression-in-place situation,
|
||||
which is the smallest amount of work and most likely to
|
||||
occur when using the normal START_ADDR of the kernel
|
||||
(currently set to 16MB, to clear all console code.
|
||||
*/
|
||||
unsigned long uncompressed_image_start = K_KERNEL_IMAGE_START;
|
||||
unsigned long uncompressed_image_end = K_KERNEL_IMAGE_END;
|
||||
|
||||
unsigned long initrd_image_start = K_INITRD_START;
|
||||
|
||||
/*
|
||||
* Note that this crufty stuff with static and envval
|
||||
* and envbuf is because:
|
||||
*
|
||||
* 1. Frequently, the stack is short, and we don't want to overrun;
|
||||
* 2. Frequently the stack is where we are going to copy the kernel to;
|
||||
* 3. A certain SRM console required the GET_ENV output to stack.
|
||||
* ??? A comment in the aboot sources indicates that the GET_ENV
|
||||
* destination must be quadword aligned. Might this explain the
|
||||
* behaviour, rather than requiring output to the stack, which
|
||||
* seems rather far-fetched.
|
||||
*/
|
||||
static long nbytes;
|
||||
static char envval[256] __attribute__((aligned(8)));
|
||||
register unsigned long asm_sp asm("30");
|
||||
|
||||
SP_on_entry = asm_sp;
|
||||
|
||||
srm_printk("Linux/Alpha BOOTPZ Loader for Linux " UTS_RELEASE "\n");
|
||||
|
||||
/* Validity check the HWRPB. */
|
||||
if (INIT_HWRPB->pagesize != 8192) {
|
||||
srm_printk("Expected 8kB pages, got %ldkB\n",
|
||||
INIT_HWRPB->pagesize >> 10);
|
||||
return;
|
||||
}
|
||||
if (INIT_HWRPB->vptb != (unsigned long) VPTB) {
|
||||
srm_printk("Expected vptb at %p, got %p\n",
|
||||
VPTB, (void *)INIT_HWRPB->vptb);
|
||||
return;
|
||||
}
|
||||
|
||||
/* PALcode (re)initialization. */
|
||||
pal_init();
|
||||
|
||||
/* Get the parameter list from the console environment variable. */
|
||||
nbytes = callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval));
|
||||
if (nbytes < 0 || nbytes >= sizeof(envval)) {
|
||||
nbytes = 0;
|
||||
}
|
||||
envval[nbytes] = '\0';
|
||||
|
||||
#ifdef DEBUG_ADDRESSES
|
||||
srm_printk("START_ADDR 0x%lx\n", START_ADDR);
|
||||
srm_printk("KERNEL_ORIGIN 0x%lx\n", KERNEL_ORIGIN);
|
||||
srm_printk("KERNEL_SIZE 0x%x\n", KERNEL_SIZE);
|
||||
srm_printk("KERNEL_Z_SIZE 0x%x\n", KERNEL_Z_SIZE);
|
||||
#endif
|
||||
|
||||
/* Since all the SRM consoles load the BOOTP image at virtual
|
||||
* 0x20000000, we have to ensure that the physical memory
|
||||
* pages occupied by that image do NOT overlap the physical
|
||||
* address range where the kernel wants to be run. This
|
||||
* causes real problems when attempting to cdecompress the
|
||||
* former into the latter... :-(
|
||||
*
|
||||
* So, we may have to decompress/move the kernel/INITRD image
|
||||
* virtual-to-physical someplace else first before moving
|
||||
* kernel /INITRD to their final resting places... ;-}
|
||||
*
|
||||
* Sigh...
|
||||
*/
|
||||
|
||||
/* First, check to see if the range of addresses occupied by
|
||||
the bootstrapper part of the BOOTP image include any of the
|
||||
physical pages into which the kernel will be placed for
|
||||
execution.
|
||||
|
||||
We only need check on the final kernel image range, since we
|
||||
will put the INITRD someplace that we can be sure is not
|
||||
in conflict.
|
||||
*/
|
||||
if (check_range(V_BOOTSTRAPPER_START, V_BOOTSTRAPPER_END,
|
||||
K_KERNEL_DATA_START, K_KERNEL_IMAGE_END))
|
||||
{
|
||||
srm_printk("FATAL ERROR: overlap of bootstrapper code\n");
|
||||
__halt();
|
||||
}
|
||||
|
||||
/* Next, check to see if the range of addresses occupied by
|
||||
the compressed kernel/INITRD/stack portion of the BOOTP
|
||||
image include any of the physical pages into which the
|
||||
decompressed kernel or the INITRD will be placed for
|
||||
execution.
|
||||
*/
|
||||
if (check_range(V_DATA_START, V_DATA_END,
|
||||
K_KERNEL_IMAGE_START, K_COPY_IMAGE_END))
|
||||
{
|
||||
#ifdef DEBUG_ADDRESSES
|
||||
srm_printk("OVERLAP: cannot decompress in place\n");
|
||||
#endif
|
||||
uncompressed_image_start = K_COPY_IMAGE_START;
|
||||
uncompressed_image_end = K_COPY_IMAGE_END;
|
||||
must_move = 1;
|
||||
|
||||
/* Finally, check to see if the range of addresses
|
||||
occupied by the compressed kernel/INITRD part of
|
||||
the BOOTP image include any of the physical pages
|
||||
into which that part is to be copied for
|
||||
decompression.
|
||||
*/
|
||||
while (check_range(V_DATA_START, V_DATA_END,
|
||||
uncompressed_image_start,
|
||||
uncompressed_image_end))
|
||||
{
|
||||
#if 0
|
||||
uncompressed_image_start += K_COPY_IMAGE_SIZE;
|
||||
uncompressed_image_end += K_COPY_IMAGE_SIZE;
|
||||
initrd_image_start += K_COPY_IMAGE_SIZE;
|
||||
#else
|
||||
/* Keep as close as possible to end of BOOTP image. */
|
||||
uncompressed_image_start += PAGE_SIZE;
|
||||
uncompressed_image_end += PAGE_SIZE;
|
||||
initrd_image_start += PAGE_SIZE;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
srm_printk("Starting to load the kernel with args '%s'\n", envval);
|
||||
|
||||
#ifdef DEBUG_ADDRESSES
|
||||
srm_printk("Decompressing the kernel...\n"
|
||||
"...from 0x%lx to 0x%lx size 0x%x\n",
|
||||
V_DATA_START,
|
||||
uncompressed_image_start,
|
||||
KERNEL_SIZE);
|
||||
#endif
|
||||
decompress_kernel((void *)uncompressed_image_start,
|
||||
(void *)V_DATA_START,
|
||||
KERNEL_SIZE, KERNEL_Z_SIZE);
|
||||
|
||||
/*
|
||||
* Now, move things to their final positions, if/as required.
|
||||
*/
|
||||
|
||||
#ifdef INITRD_IMAGE_SIZE
|
||||
|
||||
/* First, we always move the INITRD image, if present. */
|
||||
#ifdef DEBUG_ADDRESSES
|
||||
srm_printk("Moving the INITRD image...\n"
|
||||
" from 0x%lx to 0x%lx size 0x%x\n",
|
||||
V_INITRD_START,
|
||||
initrd_image_start,
|
||||
INITRD_IMAGE_SIZE);
|
||||
#endif
|
||||
memcpy((void *)initrd_image_start, (void *)V_INITRD_START,
|
||||
INITRD_IMAGE_SIZE);
|
||||
|
||||
#endif /* INITRD_IMAGE_SIZE */
|
||||
|
||||
/* Next, we may have to move the uncompressed kernel to the
|
||||
final destination.
|
||||
*/
|
||||
if (must_move) {
|
||||
#ifdef DEBUG_ADDRESSES
|
||||
srm_printk("Moving the uncompressed kernel...\n"
|
||||
"...from 0x%lx to 0x%lx size 0x%x\n",
|
||||
uncompressed_image_start,
|
||||
K_KERNEL_IMAGE_START,
|
||||
(unsigned)KERNEL_SIZE);
|
||||
#endif
|
||||
/*
|
||||
* Move the stack to a safe place to ensure it won't be
|
||||
* overwritten by kernel image.
|
||||
*/
|
||||
move_stack(initrd_image_start - PAGE_SIZE);
|
||||
|
||||
memcpy((void *)K_KERNEL_IMAGE_START,
|
||||
(void *)uncompressed_image_start, KERNEL_SIZE);
|
||||
}
|
||||
|
||||
/* Clear the zero page, then move the argument list in. */
|
||||
#ifdef DEBUG_LAST_STEPS
|
||||
srm_printk("Preparing ZERO_PGE...\n");
|
||||
#endif
|
||||
memset((char*)ZERO_PGE, 0, PAGE_SIZE);
|
||||
strcpy((char*)ZERO_PGE, envval);
|
||||
|
||||
#ifdef INITRD_IMAGE_SIZE
|
||||
|
||||
#ifdef DEBUG_LAST_STEPS
|
||||
srm_printk("Preparing INITRD info...\n");
|
||||
#endif
|
||||
/* Finally, set the INITRD paramenters for the kernel. */
|
||||
((long *)(ZERO_PGE+256))[0] = initrd_image_start;
|
||||
((long *)(ZERO_PGE+256))[1] = INITRD_IMAGE_SIZE;
|
||||
|
||||
#endif /* INITRD_IMAGE_SIZE */
|
||||
|
||||
#ifdef DEBUG_LAST_STEPS
|
||||
srm_printk("Doing 'runkernel()'...\n");
|
||||
#endif
|
||||
runkernel();
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* arch/alpha/boot/head.S
|
||||
*
|
||||
* initial bootloader stuff..
|
||||
*/
|
||||
|
||||
#include <asm/system.h>
|
||||
|
||||
.set noreorder
|
||||
.globl __start
|
||||
.ent __start
|
||||
__start:
|
||||
br $29,2f
|
||||
2: ldgp $29,0($29)
|
||||
jsr $26,start_kernel
|
||||
call_pal PAL_halt
|
||||
.end __start
|
||||
|
||||
.align 5
|
||||
.globl wrent
|
||||
.ent wrent
|
||||
wrent:
|
||||
.prologue 0
|
||||
call_pal PAL_wrent
|
||||
ret ($26)
|
||||
.end wrent
|
||||
|
||||
.align 5
|
||||
.globl wrkgp
|
||||
.ent wrkgp
|
||||
wrkgp:
|
||||
.prologue 0
|
||||
call_pal PAL_wrkgp
|
||||
ret ($26)
|
||||
.end wrkgp
|
||||
|
||||
.align 5
|
||||
.globl switch_to_osf_pal
|
||||
.ent switch_to_osf_pal
|
||||
switch_to_osf_pal:
|
||||
subq $30,128,$30
|
||||
.frame $30,128,$26
|
||||
stq $26,0($30)
|
||||
stq $1,8($30)
|
||||
stq $2,16($30)
|
||||
stq $3,24($30)
|
||||
stq $4,32($30)
|
||||
stq $5,40($30)
|
||||
stq $6,48($30)
|
||||
stq $7,56($30)
|
||||
stq $8,64($30)
|
||||
stq $9,72($30)
|
||||
stq $10,80($30)
|
||||
stq $11,88($30)
|
||||
stq $12,96($30)
|
||||
stq $13,104($30)
|
||||
stq $14,112($30)
|
||||
stq $15,120($30)
|
||||
.prologue 0
|
||||
|
||||
stq $30,0($17) /* save KSP in PCB */
|
||||
|
||||
bis $30,$30,$20 /* a4 = KSP */
|
||||
br $17,1f
|
||||
|
||||
ldq $26,0($30)
|
||||
ldq $1,8($30)
|
||||
ldq $2,16($30)
|
||||
ldq $3,24($30)
|
||||
ldq $4,32($30)
|
||||
ldq $5,40($30)
|
||||
ldq $6,48($30)
|
||||
ldq $7,56($30)
|
||||
ldq $8,64($30)
|
||||
ldq $9,72($30)
|
||||
ldq $10,80($30)
|
||||
ldq $11,88($30)
|
||||
ldq $12,96($30)
|
||||
ldq $13,104($30)
|
||||
ldq $14,112($30)
|
||||
ldq $15,120($30)
|
||||
addq $30,128,$30
|
||||
ret ($26)
|
||||
1: call_pal PAL_swppal
|
||||
.end switch_to_osf_pal
|
||||
|
||||
.align 3
|
||||
.globl tbi
|
||||
.ent tbi
|
||||
tbi:
|
||||
.prologue 0
|
||||
call_pal PAL_tbi
|
||||
ret ($26)
|
||||
.end tbi
|
||||
|
||||
.align 3
|
||||
.globl halt
|
||||
.ent halt
|
||||
halt:
|
||||
.prologue 0
|
||||
call_pal PAL_halt
|
||||
.end halt
|
||||
|
||||
/* $16 - new stack page */
|
||||
.align 3
|
||||
.globl move_stack
|
||||
.ent move_stack
|
||||
move_stack:
|
||||
.prologue 0
|
||||
lda $0, 0x1fff($31)
|
||||
and $0, $30, $1 /* Stack offset */
|
||||
or $1, $16, $16 /* New stack pointer */
|
||||
mov $30, $1
|
||||
mov $16, $2
|
||||
1: ldq $3, 0($1) /* Move the stack */
|
||||
addq $1, 8, $1
|
||||
stq $3, 0($2)
|
||||
and $0, $1, $4
|
||||
addq $2, 8, $2
|
||||
bne $4, 1b
|
||||
mov $16, $30
|
||||
ret ($26)
|
||||
.end move_stack
|
||||
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* arch/alpha/boot/main.c
|
||||
*
|
||||
* Copyright (C) 1994, 1995 Linus Torvalds
|
||||
*
|
||||
* This file is the bootloader for the Linux/AXP kernel
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/console.h>
|
||||
#include <asm/hwrpb.h>
|
||||
#include <asm/pgtable.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "ksize.h"
|
||||
|
||||
extern int vsprintf(char *, const char *, va_list);
|
||||
extern unsigned long switch_to_osf_pal(unsigned long nr,
|
||||
struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa,
|
||||
unsigned long *vptb);
|
||||
struct hwrpb_struct *hwrpb = INIT_HWRPB;
|
||||
static struct pcb_struct pcb_va[1];
|
||||
|
||||
/*
|
||||
* Find a physical address of a virtual object..
|
||||
*
|
||||
* This is easy using the virtual page table address.
|
||||
*/
|
||||
|
||||
static inline void *
|
||||
find_pa(unsigned long *vptb, void *ptr)
|
||||
{
|
||||
unsigned long address = (unsigned long) ptr;
|
||||
unsigned long result;
|
||||
|
||||
result = vptb[address >> 13];
|
||||
result >>= 32;
|
||||
result <<= 13;
|
||||
result |= address & 0x1fff;
|
||||
return (void *) result;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function moves into OSF/1 pal-code, and has a temporary
|
||||
* PCB for that. The kernel proper should replace this PCB with
|
||||
* the real one as soon as possible.
|
||||
*
|
||||
* The page table muckery in here depends on the fact that the boot
|
||||
* code has the L1 page table identity-map itself in the second PTE
|
||||
* in the L1 page table. Thus the L1-page is virtually addressable
|
||||
* itself (through three levels) at virtual address 0x200802000.
|
||||
*/
|
||||
|
||||
#define VPTB ((unsigned long *) 0x200000000)
|
||||
#define L1 ((unsigned long *) 0x200802000)
|
||||
|
||||
void
|
||||
pal_init(void)
|
||||
{
|
||||
unsigned long i, rev;
|
||||
struct percpu_struct * percpu;
|
||||
struct pcb_struct * pcb_pa;
|
||||
|
||||
/* Create the dummy PCB. */
|
||||
pcb_va->ksp = 0;
|
||||
pcb_va->usp = 0;
|
||||
pcb_va->ptbr = L1[1] >> 32;
|
||||
pcb_va->asn = 0;
|
||||
pcb_va->pcc = 0;
|
||||
pcb_va->unique = 0;
|
||||
pcb_va->flags = 1;
|
||||
pcb_va->res1 = 0;
|
||||
pcb_va->res2 = 0;
|
||||
pcb_pa = find_pa(VPTB, pcb_va);
|
||||
|
||||
/*
|
||||
* a0 = 2 (OSF)
|
||||
* a1 = return address, but we give the asm the vaddr of the PCB
|
||||
* a2 = physical addr of PCB
|
||||
* a3 = new virtual page table pointer
|
||||
* a4 = KSP (but the asm sets it)
|
||||
*/
|
||||
srm_printk("Switching to OSF PAL-code .. ");
|
||||
|
||||
i = switch_to_osf_pal(2, pcb_va, pcb_pa, VPTB);
|
||||
if (i) {
|
||||
srm_printk("failed, code %ld\n", i);
|
||||
__halt();
|
||||
}
|
||||
|
||||
percpu = (struct percpu_struct *)
|
||||
(INIT_HWRPB->processor_offset + (unsigned long) INIT_HWRPB);
|
||||
rev = percpu->pal_revision = percpu->palcode_avail[2];
|
||||
|
||||
srm_printk("Ok (rev %lx)\n", rev);
|
||||
|
||||
tbia(); /* do it directly in case we are SMP */
|
||||
}
|
||||
|
||||
static inline long openboot(void)
|
||||
{
|
||||
char bootdev[256];
|
||||
long result;
|
||||
|
||||
result = callback_getenv(ENV_BOOTED_DEV, bootdev, 255);
|
||||
if (result < 0)
|
||||
return result;
|
||||
return callback_open(bootdev, result & 255);
|
||||
}
|
||||
|
||||
static inline long close(long dev)
|
||||
{
|
||||
return callback_close(dev);
|
||||
}
|
||||
|
||||
static inline long load(long dev, unsigned long addr, unsigned long count)
|
||||
{
|
||||
char bootfile[256];
|
||||
extern char _end;
|
||||
long result, boot_size = &_end - (char *) BOOT_ADDR;
|
||||
|
||||
result = callback_getenv(ENV_BOOTED_FILE, bootfile, 255);
|
||||
if (result < 0)
|
||||
return result;
|
||||
result &= 255;
|
||||
bootfile[result] = '\0';
|
||||
if (result)
|
||||
srm_printk("Boot file specification (%s) not implemented\n",
|
||||
bootfile);
|
||||
return callback_read(dev, count, addr, boot_size/512 + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Start the kernel.
|
||||
*/
|
||||
static void runkernel(void)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"bis %1,%1,$30\n\t"
|
||||
"bis %0,%0,$26\n\t"
|
||||
"ret ($26)"
|
||||
: /* no outputs: it doesn't even return */
|
||||
: "r" (START_ADDR),
|
||||
"r" (PAGE_SIZE + INIT_STACK));
|
||||
}
|
||||
|
||||
void start_kernel(void)
|
||||
{
|
||||
long i;
|
||||
long dev;
|
||||
int nbytes;
|
||||
char envval[256];
|
||||
|
||||
srm_printk("Linux/AXP bootloader for Linux " UTS_RELEASE "\n");
|
||||
if (INIT_HWRPB->pagesize != 8192) {
|
||||
srm_printk("Expected 8kB pages, got %ldkB\n", INIT_HWRPB->pagesize >> 10);
|
||||
return;
|
||||
}
|
||||
pal_init();
|
||||
dev = openboot();
|
||||
if (dev < 0) {
|
||||
srm_printk("Unable to open boot device: %016lx\n", dev);
|
||||
return;
|
||||
}
|
||||
dev &= 0xffffffff;
|
||||
srm_printk("Loading vmlinux ...");
|
||||
i = load(dev, START_ADDR, KERNEL_SIZE);
|
||||
close(dev);
|
||||
if (i != KERNEL_SIZE) {
|
||||
srm_printk("Failed (%lx)\n", i);
|
||||
return;
|
||||
}
|
||||
|
||||
nbytes = callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval));
|
||||
if (nbytes < 0) {
|
||||
nbytes = 0;
|
||||
}
|
||||
envval[nbytes] = '\0';
|
||||
strcpy((char*)ZERO_PGE, envval);
|
||||
|
||||
srm_printk(" Ok\nNow booting the kernel\n");
|
||||
runkernel();
|
||||
for (i = 0 ; i < 0x100000000 ; i++)
|
||||
/* nothing */;
|
||||
__halt();
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* misc.c
|
||||
*
|
||||
* This is a collection of several routines from gzip-1.0.3
|
||||
* adapted for Linux.
|
||||
*
|
||||
* malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
|
||||
*
|
||||
* Modified for ARM Linux by Russell King
|
||||
*
|
||||
* Nicolas Pitre <nico@visuaide.com> 1999/04/14 :
|
||||
* For this code to run directly from Flash, all constant variables must
|
||||
* be marked with 'const' and all other variables initialized at run-time
|
||||
* only. This way all non constant variables will end up in the bss segment,
|
||||
* which should point to addresses in RAM and cleared to 0 on start.
|
||||
* This allows for a much quicker boot time.
|
||||
*
|
||||
* Modified for Alpha, from the ARM version, by Jay Estabrook 2003.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#define memzero(s,n) memset ((s),0,(n))
|
||||
#define puts srm_printk
|
||||
extern long srm_printk(const char *, ...)
|
||||
__attribute__ ((format (printf, 1, 2)));
|
||||
|
||||
/*
|
||||
* gzip delarations
|
||||
*/
|
||||
#define OF(args) args
|
||||
#define STATIC static
|
||||
|
||||
typedef unsigned char uch;
|
||||
typedef unsigned short ush;
|
||||
typedef unsigned long ulg;
|
||||
|
||||
#define WSIZE 0x8000 /* Window size must be at least 32k, */
|
||||
/* and a power of two */
|
||||
|
||||
static uch *inbuf; /* input buffer */
|
||||
static uch *window; /* Sliding window buffer */
|
||||
|
||||
static unsigned insize; /* valid bytes in inbuf */
|
||||
static unsigned inptr; /* index of next byte to be processed in inbuf */
|
||||
static unsigned outcnt; /* bytes in output buffer */
|
||||
|
||||
/* gzip flag byte */
|
||||
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
|
||||
#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
|
||||
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
|
||||
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
|
||||
#define COMMENT 0x10 /* bit 4 set: file comment present */
|
||||
#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
|
||||
#define RESERVED 0xC0 /* bit 6,7: reserved */
|
||||
|
||||
#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
|
||||
|
||||
/* Diagnostic functions */
|
||||
#ifdef DEBUG
|
||||
# define Assert(cond,msg) {if(!(cond)) error(msg);}
|
||||
# define Trace(x) fprintf x
|
||||
# define Tracev(x) {if (verbose) fprintf x ;}
|
||||
# define Tracevv(x) {if (verbose>1) fprintf x ;}
|
||||
# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
|
||||
# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
|
||||
#else
|
||||
# define Assert(cond,msg)
|
||||
# define Trace(x)
|
||||
# define Tracev(x)
|
||||
# define Tracevv(x)
|
||||
# define Tracec(c,x)
|
||||
# define Tracecv(c,x)
|
||||
#endif
|
||||
|
||||
static int fill_inbuf(void);
|
||||
static void flush_window(void);
|
||||
static void error(char *m);
|
||||
static void gzip_mark(void **);
|
||||
static void gzip_release(void **);
|
||||
|
||||
static char *input_data;
|
||||
static int input_data_size;
|
||||
|
||||
static uch *output_data;
|
||||
static ulg output_ptr;
|
||||
static ulg bytes_out;
|
||||
|
||||
static void *malloc(int size);
|
||||
static void free(void *where);
|
||||
static void error(char *m);
|
||||
static void gzip_mark(void **);
|
||||
static void gzip_release(void **);
|
||||
|
||||
extern int end;
|
||||
static ulg free_mem_ptr;
|
||||
static ulg free_mem_ptr_end;
|
||||
|
||||
#define HEAP_SIZE 0x2000
|
||||
|
||||
#include "../../../lib/inflate.c"
|
||||
|
||||
static void *malloc(int size)
|
||||
{
|
||||
void *p;
|
||||
|
||||
if (size <0) error("Malloc error");
|
||||
if (free_mem_ptr <= 0) error("Memory error");
|
||||
|
||||
free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
|
||||
|
||||
p = (void *)free_mem_ptr;
|
||||
free_mem_ptr += size;
|
||||
|
||||
if (free_mem_ptr >= free_mem_ptr_end)
|
||||
error("Out of memory");
|
||||
return p;
|
||||
}
|
||||
|
||||
static void free(void *where)
|
||||
{ /* gzip_mark & gzip_release do the free */
|
||||
}
|
||||
|
||||
static void gzip_mark(void **ptr)
|
||||
{
|
||||
*ptr = (void *) free_mem_ptr;
|
||||
}
|
||||
|
||||
static void gzip_release(void **ptr)
|
||||
{
|
||||
free_mem_ptr = (long) *ptr;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Fill the input buffer. This is called only when the buffer is empty
|
||||
* and at least one byte is really needed.
|
||||
*/
|
||||
int fill_inbuf(void)
|
||||
{
|
||||
if (insize != 0)
|
||||
error("ran out of input data");
|
||||
|
||||
inbuf = input_data;
|
||||
insize = input_data_size;
|
||||
|
||||
inptr = 1;
|
||||
return inbuf[0];
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Write the output window window[0..outcnt-1] and update crc and bytes_out.
|
||||
* (Used for the decompressed data only.)
|
||||
*/
|
||||
void flush_window(void)
|
||||
{
|
||||
ulg c = crc;
|
||||
unsigned n;
|
||||
uch *in, *out, ch;
|
||||
|
||||
in = window;
|
||||
out = &output_data[output_ptr];
|
||||
for (n = 0; n < outcnt; n++) {
|
||||
ch = *out++ = *in++;
|
||||
c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
|
||||
}
|
||||
crc = c;
|
||||
bytes_out += (ulg)outcnt;
|
||||
output_ptr += (ulg)outcnt;
|
||||
outcnt = 0;
|
||||
/* puts("."); */
|
||||
}
|
||||
|
||||
static void error(char *x)
|
||||
{
|
||||
puts("\n\n");
|
||||
puts(x);
|
||||
puts("\n\n -- System halted");
|
||||
|
||||
while(1); /* Halt */
|
||||
}
|
||||
|
||||
unsigned int
|
||||
decompress_kernel(void *output_start,
|
||||
void *input_start,
|
||||
size_t ksize,
|
||||
size_t kzsize)
|
||||
{
|
||||
output_data = (uch *)output_start;
|
||||
input_data = (uch *)input_start;
|
||||
input_data_size = kzsize; /* use compressed size */
|
||||
|
||||
/* FIXME FIXME FIXME */
|
||||
free_mem_ptr = (ulg)output_start + ksize;
|
||||
free_mem_ptr_end = (ulg)output_start + ksize + 0x200000;
|
||||
/* FIXME FIXME FIXME */
|
||||
|
||||
/* put in temp area to reduce initial footprint */
|
||||
window = malloc(WSIZE);
|
||||
|
||||
makecrc();
|
||||
/* puts("Uncompressing Linux..."); */
|
||||
gunzip();
|
||||
/* puts(" done, booting the kernel.\n"); */
|
||||
return output_ptr;
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
/* This utility makes a bootblock suitable for the SRM console/miniloader */
|
||||
|
||||
/* Usage:
|
||||
* mkbb <device> <lxboot>
|
||||
*
|
||||
* Where <device> is the name of the device to install the bootblock on,
|
||||
* and <lxboot> is the name of a bootblock to merge in. This bootblock
|
||||
* contains the offset and size of the bootloader. It must be exactly
|
||||
* 512 bytes long.
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Minimal definition of disklabel, so we don't have to include
|
||||
* asm/disklabel.h (confuses make)
|
||||
*/
|
||||
#ifndef MAXPARTITIONS
|
||||
#define MAXPARTITIONS 8 /* max. # of partitions */
|
||||
#endif
|
||||
|
||||
#ifndef u8
|
||||
#define u8 unsigned char
|
||||
#endif
|
||||
|
||||
#ifndef u16
|
||||
#define u16 unsigned short
|
||||
#endif
|
||||
|
||||
#ifndef u32
|
||||
#define u32 unsigned int
|
||||
#endif
|
||||
|
||||
struct disklabel {
|
||||
u32 d_magic; /* must be DISKLABELMAGIC */
|
||||
u16 d_type, d_subtype;
|
||||
u8 d_typename[16];
|
||||
u8 d_packname[16];
|
||||
u32 d_secsize;
|
||||
u32 d_nsectors;
|
||||
u32 d_ntracks;
|
||||
u32 d_ncylinders;
|
||||
u32 d_secpercyl;
|
||||
u32 d_secprtunit;
|
||||
u16 d_sparespertrack;
|
||||
u16 d_sparespercyl;
|
||||
u32 d_acylinders;
|
||||
u16 d_rpm, d_interleave, d_trackskew, d_cylskew;
|
||||
u32 d_headswitch, d_trkseek, d_flags;
|
||||
u32 d_drivedata[5];
|
||||
u32 d_spare[5];
|
||||
u32 d_magic2; /* must be DISKLABELMAGIC */
|
||||
u16 d_checksum;
|
||||
u16 d_npartitions;
|
||||
u32 d_bbsize, d_sbsize;
|
||||
struct d_partition {
|
||||
u32 p_size;
|
||||
u32 p_offset;
|
||||
u32 p_fsize;
|
||||
u8 p_fstype;
|
||||
u8 p_frag;
|
||||
u16 p_cpg;
|
||||
} d_partitions[MAXPARTITIONS];
|
||||
};
|
||||
|
||||
|
||||
typedef union __bootblock {
|
||||
struct {
|
||||
char __pad1[64];
|
||||
struct disklabel __label;
|
||||
} __u1;
|
||||
struct {
|
||||
unsigned long __pad2[63];
|
||||
unsigned long __checksum;
|
||||
} __u2;
|
||||
char bootblock_bytes[512];
|
||||
unsigned long bootblock_quadwords[64];
|
||||
} bootblock;
|
||||
|
||||
#define bootblock_label __u1.__label
|
||||
#define bootblock_checksum __u2.__checksum
|
||||
|
||||
main(int argc, char ** argv)
|
||||
{
|
||||
bootblock bootblock_from_disk;
|
||||
bootblock bootloader_image;
|
||||
int dev, fd;
|
||||
int i;
|
||||
int nread;
|
||||
|
||||
/* Make sure of the arg count */
|
||||
if(argc != 3) {
|
||||
fprintf(stderr, "Usage: %s device lxboot\n", argv[0]);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* First, open the device and make sure it's accessible */
|
||||
dev = open(argv[1], O_RDWR);
|
||||
if(dev < 0) {
|
||||
perror(argv[1]);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Now open the lxboot and make sure it's reasonable */
|
||||
fd = open(argv[2], O_RDONLY);
|
||||
if(fd < 0) {
|
||||
perror(argv[2]);
|
||||
close(dev);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Read in the lxboot */
|
||||
nread = read(fd, &bootloader_image, sizeof(bootblock));
|
||||
if(nread != sizeof(bootblock)) {
|
||||
perror("lxboot read");
|
||||
fprintf(stderr, "expected %d, got %d\n", sizeof(bootblock), nread);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Read in the bootblock from disk. */
|
||||
nread = read(dev, &bootblock_from_disk, sizeof(bootblock));
|
||||
if(nread != sizeof(bootblock)) {
|
||||
perror("bootblock read");
|
||||
fprintf(stderr, "expected %d, got %d\n", sizeof(bootblock), nread);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Swap the bootblock's disklabel into the bootloader */
|
||||
bootloader_image.bootblock_label = bootblock_from_disk.bootblock_label;
|
||||
|
||||
/* Calculate the bootblock checksum */
|
||||
bootloader_image.bootblock_checksum = 0;
|
||||
for(i = 0; i < 63; i++) {
|
||||
bootloader_image.bootblock_checksum +=
|
||||
bootloader_image.bootblock_quadwords[i];
|
||||
}
|
||||
|
||||
/* Write the whole thing out! */
|
||||
lseek(dev, 0L, SEEK_SET);
|
||||
if(write(dev, &bootloader_image, sizeof(bootblock)) != sizeof(bootblock)) {
|
||||
perror("bootblock write");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
close(dev);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,281 @@
|
||||
/*
|
||||
* arch/alpha/boot/tools/objstrip.c
|
||||
*
|
||||
* Strip the object file headers/trailers from an executable (ELF or ECOFF).
|
||||
*
|
||||
* Copyright (C) 1996 David Mosberger-Tang.
|
||||
*/
|
||||
/*
|
||||
* Converts an ECOFF or ELF object file into a bootable file. The
|
||||
* object file must be a OMAGIC file (i.e., data and bss follow immediately
|
||||
* behind the text). See DEC "Assembly Language Programmer's Guide"
|
||||
* documentation for details. The SRM boot process is documented in
|
||||
* the Alpha AXP Architecture Reference Manual, Second Edition by
|
||||
* Richard L. Sites and Richard T. Witek.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <linux/a.out.h>
|
||||
#include <linux/coff.h>
|
||||
#include <linux/param.h>
|
||||
#include <linux/string.h>
|
||||
#ifdef __ELF__
|
||||
# include <linux/elf.h>
|
||||
#endif
|
||||
|
||||
/* bootfile size must be multiple of BLOCK_SIZE: */
|
||||
#define BLOCK_SIZE 512
|
||||
|
||||
const char * prog_name;
|
||||
|
||||
|
||||
void
|
||||
usage (void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: %s [-v] -p file primary\n"
|
||||
" %s [-vb] file [secondary]\n", prog_name, prog_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
size_t nwritten, tocopy, n, mem_size, fil_size, pad = 0;
|
||||
int fd, ofd, i, j, verbose = 0, primary = 0;
|
||||
char buf[8192], *inname;
|
||||
struct exec * aout; /* includes file & aout header */
|
||||
long offset;
|
||||
#ifdef __ELF__
|
||||
struct elfhdr *elf;
|
||||
struct elf_phdr *elf_phdr; /* program header */
|
||||
unsigned long long e_entry;
|
||||
#endif
|
||||
|
||||
prog_name = argv[0];
|
||||
|
||||
for (i = 1; i < argc && argv[i][0] == '-'; ++i) {
|
||||
for (j = 1; argv[i][j]; ++j) {
|
||||
switch (argv[i][j]) {
|
||||
case 'v':
|
||||
verbose = ~verbose;
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
pad = BLOCK_SIZE;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
primary = 1; /* make primary bootblock */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= argc) {
|
||||
usage();
|
||||
}
|
||||
inname = argv[i++];
|
||||
|
||||
fd = open(inname, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
perror("open");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ofd = 1;
|
||||
if (i < argc) {
|
||||
ofd = open(argv[i++], O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
if (fd == -1) {
|
||||
perror("open");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (primary) {
|
||||
/* generate bootblock for primary loader */
|
||||
|
||||
unsigned long bb[64], sum = 0;
|
||||
struct stat st;
|
||||
off_t size;
|
||||
int i;
|
||||
|
||||
if (ofd == 1) {
|
||||
usage();
|
||||
}
|
||||
|
||||
if (fstat(fd, &st) == -1) {
|
||||
perror("fstat");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
size = (st.st_size + BLOCK_SIZE - 1) & ~(BLOCK_SIZE - 1);
|
||||
memset(bb, 0, sizeof(bb));
|
||||
strcpy((char *) bb, "Linux SRM bootblock");
|
||||
bb[60] = size / BLOCK_SIZE; /* count */
|
||||
bb[61] = 1; /* starting sector # */
|
||||
bb[62] = 0; /* flags---must be 0 */
|
||||
for (i = 0; i < 63; ++i) {
|
||||
sum += bb[i];
|
||||
}
|
||||
bb[63] = sum;
|
||||
if (write(ofd, bb, sizeof(bb)) != sizeof(bb)) {
|
||||
perror("boot-block write");
|
||||
exit(1);
|
||||
}
|
||||
printf("%lu\n", size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* read and inspect exec header: */
|
||||
|
||||
if (read(fd, buf, sizeof(buf)) < 0) {
|
||||
perror("read");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef __ELF__
|
||||
elf = (struct elfhdr *) buf;
|
||||
|
||||
if (elf->e_ident[0] == 0x7f && strncmp(elf->e_ident + 1, "ELF", 3) == 0) {
|
||||
if (elf->e_type != ET_EXEC) {
|
||||
fprintf(stderr, "%s: %s is not an ELF executable\n",
|
||||
prog_name, inname);
|
||||
exit(1);
|
||||
}
|
||||
if (!elf_check_arch(elf)) {
|
||||
fprintf(stderr, "%s: is not for this processor (e_machine=%d)\n",
|
||||
prog_name, elf->e_machine);
|
||||
exit(1);
|
||||
}
|
||||
if (elf->e_phnum != 1) {
|
||||
fprintf(stderr,
|
||||
"%s: %d program headers (forgot to link with -N?)\n",
|
||||
prog_name, elf->e_phnum);
|
||||
}
|
||||
|
||||
e_entry = elf->e_entry;
|
||||
|
||||
lseek(fd, elf->e_phoff, SEEK_SET);
|
||||
if (read(fd, buf, sizeof(*elf_phdr)) != sizeof(*elf_phdr)) {
|
||||
perror("read");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
elf_phdr = (struct elf_phdr *) buf;
|
||||
offset = elf_phdr->p_offset;
|
||||
mem_size = elf_phdr->p_memsz;
|
||||
fil_size = elf_phdr->p_filesz;
|
||||
|
||||
/* work around ELF bug: */
|
||||
if (elf_phdr->p_vaddr < e_entry) {
|
||||
unsigned long delta = e_entry - elf_phdr->p_vaddr;
|
||||
offset += delta;
|
||||
mem_size -= delta;
|
||||
fil_size -= delta;
|
||||
elf_phdr->p_vaddr += delta;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
fprintf(stderr, "%s: extracting %#016lx-%#016lx (at %lx)\n",
|
||||
prog_name, (long) elf_phdr->p_vaddr,
|
||||
elf_phdr->p_vaddr + fil_size, offset);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
aout = (struct exec *) buf;
|
||||
|
||||
if (!(aout->fh.f_flags & COFF_F_EXEC)) {
|
||||
fprintf(stderr, "%s: %s is not in executable format\n",
|
||||
prog_name, inname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (aout->fh.f_opthdr != sizeof(aout->ah)) {
|
||||
fprintf(stderr, "%s: %s has unexpected optional header size\n",
|
||||
prog_name, inname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (N_MAGIC(*aout) != OMAGIC) {
|
||||
fprintf(stderr, "%s: %s is not an OMAGIC file\n",
|
||||
prog_name, inname);
|
||||
exit(1);
|
||||
}
|
||||
offset = N_TXTOFF(*aout);
|
||||
fil_size = aout->ah.tsize + aout->ah.dsize;
|
||||
mem_size = fil_size + aout->ah.bsize;
|
||||
|
||||
if (verbose) {
|
||||
fprintf(stderr, "%s: extracting %#016lx-%#016lx (at %lx)\n",
|
||||
prog_name, aout->ah.text_start,
|
||||
aout->ah.text_start + fil_size, offset);
|
||||
}
|
||||
}
|
||||
|
||||
if (lseek(fd, offset, SEEK_SET) != offset) {
|
||||
perror("lseek");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
fprintf(stderr, "%s: copying %lu byte from %s\n",
|
||||
prog_name, (unsigned long) fil_size, inname);
|
||||
}
|
||||
|
||||
tocopy = fil_size;
|
||||
while (tocopy > 0) {
|
||||
n = tocopy;
|
||||
if (n > sizeof(buf)) {
|
||||
n = sizeof(buf);
|
||||
}
|
||||
tocopy -= n;
|
||||
if ((size_t) read(fd, buf, n) != n) {
|
||||
perror("read");
|
||||
exit(1);
|
||||
}
|
||||
do {
|
||||
nwritten = write(ofd, buf, n);
|
||||
if ((ssize_t) nwritten == -1) {
|
||||
perror("write");
|
||||
exit(1);
|
||||
}
|
||||
n -= nwritten;
|
||||
} while (n > 0);
|
||||
}
|
||||
|
||||
if (pad) {
|
||||
mem_size = ((mem_size + pad - 1) / pad) * pad;
|
||||
}
|
||||
|
||||
tocopy = mem_size - fil_size;
|
||||
if (tocopy > 0) {
|
||||
fprintf(stderr,
|
||||
"%s: zero-filling bss and aligning to %lu with %lu bytes\n",
|
||||
prog_name, pad, (unsigned long) tocopy);
|
||||
|
||||
memset(buf, 0x00, sizeof(buf));
|
||||
do {
|
||||
n = tocopy;
|
||||
if (n > sizeof(buf)) {
|
||||
n = sizeof(buf);
|
||||
}
|
||||
nwritten = write(ofd, buf, n);
|
||||
if ((ssize_t) nwritten == -1) {
|
||||
perror("write");
|
||||
exit(1);
|
||||
}
|
||||
tocopy -= nwritten;
|
||||
} while (tocopy > 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,104 @@
|
||||
#
|
||||
# Makefile for the linux kernel.
|
||||
#
|
||||
|
||||
extra-y := head.o vmlinux.lds
|
||||
EXTRA_AFLAGS := $(CFLAGS)
|
||||
EXTRA_CFLAGS := -Werror -Wno-sign-compare
|
||||
|
||||
obj-y := entry.o traps.o process.o init_task.o osf_sys.o irq.o \
|
||||
irq_alpha.o signal.o setup.o ptrace.o time.o semaphore.o \
|
||||
alpha_ksyms.o systbls.o err_common.o io.o
|
||||
|
||||
obj-$(CONFIG_VGA_HOSE) += console.o
|
||||
obj-$(CONFIG_SMP) += smp.o
|
||||
obj-$(CONFIG_PCI) += pci.o pci_iommu.o
|
||||
obj-$(CONFIG_SRM_ENV) += srm_env.o
|
||||
obj-$(CONFIG_MODULES) += module.o
|
||||
|
||||
ifdef CONFIG_ALPHA_GENERIC
|
||||
|
||||
obj-y += core_apecs.o core_cia.o core_irongate.o core_lca.o \
|
||||
core_mcpcia.o core_polaris.o core_t2.o \
|
||||
core_tsunami.o
|
||||
|
||||
obj-y += sys_alcor.o sys_cabriolet.o sys_dp264.o sys_eb64p.o sys_eiger.o \
|
||||
sys_jensen.o sys_miata.o sys_mikasa.o sys_nautilus.o \
|
||||
sys_noritake.o sys_rawhide.o sys_ruffian.o sys_rx164.o \
|
||||
sys_sable.o sys_sio.o sys_sx164.o sys_takara.o
|
||||
|
||||
ifndef CONFIG_ALPHA_LEGACY_START_ADDRESS
|
||||
obj-y += core_marvel.o core_titan.o core_wildfire.o
|
||||
obj-y += sys_marvel.o sys_titan.o sys_wildfire.o
|
||||
obj-y += err_ev7.o err_titan.o err_marvel.o
|
||||
endif
|
||||
|
||||
obj-y += irq_pyxis.o irq_i8259.o irq_srm.o
|
||||
obj-y += err_ev6.o
|
||||
obj-y += es1888.o smc37c669.o smc37c93x.o ns87312.o gct.o
|
||||
obj-y += srmcons.o
|
||||
|
||||
else
|
||||
|
||||
# Misc support
|
||||
obj-$(CONFIG_ALPHA_SRM) += srmcons.o
|
||||
|
||||
# Core logic support
|
||||
obj-$(CONFIG_ALPHA_APECS) += core_apecs.o
|
||||
obj-$(CONFIG_ALPHA_CIA) += core_cia.o
|
||||
obj-$(CONFIG_ALPHA_IRONGATE) += core_irongate.o
|
||||
obj-$(CONFIG_ALPHA_LCA) += core_lca.o
|
||||
obj-$(CONFIG_ALPHA_MARVEL) += core_marvel.o gct.o
|
||||
obj-$(CONFIG_ALPHA_MCPCIA) += core_mcpcia.o
|
||||
obj-$(CONFIG_ALPHA_POLARIS) += core_polaris.o
|
||||
obj-$(CONFIG_ALPHA_T2) += core_t2.o
|
||||
obj-$(CONFIG_ALPHA_TSUNAMI) += core_tsunami.o
|
||||
obj-$(CONFIG_ALPHA_TITAN) += core_titan.o
|
||||
obj-$(CONFIG_ALPHA_WILDFIRE) += core_wildfire.o
|
||||
|
||||
# Board support
|
||||
obj-$(CONFIG_ALPHA_ALCOR) += sys_alcor.o irq_i8259.o irq_srm.o
|
||||
obj-$(CONFIG_ALPHA_CABRIOLET) += sys_cabriolet.o irq_i8259.o irq_srm.o \
|
||||
ns87312.o
|
||||
obj-$(CONFIG_ALPHA_EB164) += sys_cabriolet.o irq_i8259.o irq_srm.o \
|
||||
ns87312.o
|
||||
obj-$(CONFIG_ALPHA_EB66P) += sys_cabriolet.o irq_i8259.o irq_srm.o \
|
||||
ns87312.o
|
||||
obj-$(CONFIG_ALPHA_LX164) += sys_cabriolet.o irq_i8259.o irq_srm.o \
|
||||
smc37c93x.o
|
||||
obj-$(CONFIG_ALPHA_PC164) += sys_cabriolet.o irq_i8259.o irq_srm.o \
|
||||
smc37c93x.o
|
||||
obj-$(CONFIG_ALPHA_DP264) += sys_dp264.o irq_i8259.o es1888.o smc37c669.o
|
||||
obj-$(CONFIG_ALPHA_SHARK) += sys_dp264.o irq_i8259.o es1888.o smc37c669.o
|
||||
obj-$(CONFIG_ALPHA_TITAN) += sys_titan.o irq_i8259.o smc37c669.o
|
||||
obj-$(CONFIG_ALPHA_EB64P) += sys_eb64p.o irq_i8259.o
|
||||
obj-$(CONFIG_ALPHA_EB66) += sys_eb64p.o irq_i8259.o
|
||||
obj-$(CONFIG_ALPHA_EIGER) += sys_eiger.o irq_i8259.o
|
||||
obj-$(CONFIG_ALPHA_JENSEN) += sys_jensen.o pci-noop.o irq_i8259.o
|
||||
obj-$(CONFIG_ALPHA_MARVEL) += sys_marvel.o
|
||||
obj-$(CONFIG_ALPHA_MIATA) += sys_miata.o irq_pyxis.o irq_i8259.o \
|
||||
es1888.o smc37c669.o
|
||||
obj-$(CONFIG_ALPHA_MIKASA) += sys_mikasa.o irq_i8259.o irq_srm.o
|
||||
obj-$(CONFIG_ALPHA_NAUTILUS) += sys_nautilus.o irq_i8259.o irq_srm.o
|
||||
obj-$(CONFIG_ALPHA_NORITAKE) += sys_noritake.o irq_i8259.o
|
||||
obj-$(CONFIG_ALPHA_RAWHIDE) += sys_rawhide.o irq_i8259.o
|
||||
obj-$(CONFIG_ALPHA_RUFFIAN) += sys_ruffian.o irq_pyxis.o irq_i8259.o
|
||||
obj-$(CONFIG_ALPHA_RX164) += sys_rx164.o irq_i8259.o
|
||||
obj-$(CONFIG_ALPHA_SABLE) += sys_sable.o
|
||||
obj-$(CONFIG_ALPHA_LYNX) += sys_sable.o
|
||||
obj-$(CONFIG_ALPHA_BOOK1) += sys_sio.o irq_i8259.o irq_srm.o ns87312.o
|
||||
obj-$(CONFIG_ALPHA_AVANTI) += sys_sio.o irq_i8259.o irq_srm.o ns87312.o
|
||||
obj-$(CONFIG_ALPHA_NONAME) += sys_sio.o irq_i8259.o irq_srm.o ns87312.o
|
||||
obj-$(CONFIG_ALPHA_P2K) += sys_sio.o irq_i8259.o irq_srm.o ns87312.o
|
||||
obj-$(CONFIG_ALPHA_XL) += sys_sio.o irq_i8259.o irq_srm.o ns87312.o
|
||||
obj-$(CONFIG_ALPHA_SX164) += sys_sx164.o irq_pyxis.o irq_i8259.o \
|
||||
irq_srm.o smc37c669.o
|
||||
obj-$(CONFIG_ALPHA_TAKARA) += sys_takara.o irq_i8259.o ns87312.o
|
||||
obj-$(CONFIG_ALPHA_WILDFIRE) += sys_wildfire.o irq_i8259.o
|
||||
|
||||
# Error support
|
||||
obj-$(CONFIG_ALPHA_MARVEL) += err_ev7.o err_marvel.o
|
||||
obj-$(CONFIG_ALPHA_NAUTILUS) += err_ev6.o
|
||||
obj-$(CONFIG_ALPHA_TITAN) += err_ev6.o err_titan.o
|
||||
|
||||
endif # GENERIC
|
||||
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* linux/arch/alpha/kernel/ksyms.c
|
||||
*
|
||||
* Export the alpha-specific functions that are needed for loadable
|
||||
* modules.
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/user.h>
|
||||
#include <linux/elfcore.h>
|
||||
#include <linux/socket.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/in6.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/console.h>
|
||||
#include <asm/hwrpb.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/checksum.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <asm/fpu.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/machvec.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/semaphore.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/vga.h>
|
||||
|
||||
#define __KERNEL_SYSCALLS__
|
||||
#include <asm/unistd.h>
|
||||
|
||||
extern struct hwrpb_struct *hwrpb;
|
||||
extern void dump_thread(struct pt_regs *, struct user *);
|
||||
extern spinlock_t rtc_lock;
|
||||
|
||||
/* these are C runtime functions with special calling conventions: */
|
||||
extern void __divl (void);
|
||||
extern void __reml (void);
|
||||
extern void __divq (void);
|
||||
extern void __remq (void);
|
||||
extern void __divlu (void);
|
||||
extern void __remlu (void);
|
||||
extern void __divqu (void);
|
||||
extern void __remqu (void);
|
||||
|
||||
EXPORT_SYMBOL(alpha_mv);
|
||||
EXPORT_SYMBOL(enable_irq);
|
||||
EXPORT_SYMBOL(disable_irq);
|
||||
EXPORT_SYMBOL(disable_irq_nosync);
|
||||
EXPORT_SYMBOL(probe_irq_mask);
|
||||
EXPORT_SYMBOL(screen_info);
|
||||
EXPORT_SYMBOL(perf_irq);
|
||||
EXPORT_SYMBOL(callback_getenv);
|
||||
EXPORT_SYMBOL(callback_setenv);
|
||||
EXPORT_SYMBOL(callback_save_env);
|
||||
#ifdef CONFIG_ALPHA_GENERIC
|
||||
EXPORT_SYMBOL(alpha_using_srm);
|
||||
#endif /* CONFIG_ALPHA_GENERIC */
|
||||
|
||||
/* platform dependent support */
|
||||
EXPORT_SYMBOL(strcat);
|
||||
EXPORT_SYMBOL(strcmp);
|
||||
EXPORT_SYMBOL(strcpy);
|
||||
EXPORT_SYMBOL(strlen);
|
||||
EXPORT_SYMBOL(strncmp);
|
||||
EXPORT_SYMBOL(strncpy);
|
||||
EXPORT_SYMBOL(strnlen);
|
||||
EXPORT_SYMBOL(strncat);
|
||||
EXPORT_SYMBOL(strstr);
|
||||
EXPORT_SYMBOL(strpbrk);
|
||||
EXPORT_SYMBOL(strchr);
|
||||
EXPORT_SYMBOL(strrchr);
|
||||
EXPORT_SYMBOL(memcmp);
|
||||
EXPORT_SYMBOL(memmove);
|
||||
EXPORT_SYMBOL(memscan);
|
||||
EXPORT_SYMBOL(__memcpy);
|
||||
EXPORT_SYMBOL(__memset);
|
||||
EXPORT_SYMBOL(__memsetw);
|
||||
EXPORT_SYMBOL(__constant_c_memset);
|
||||
EXPORT_SYMBOL(copy_page);
|
||||
EXPORT_SYMBOL(clear_page);
|
||||
|
||||
EXPORT_SYMBOL(__direct_map_base);
|
||||
EXPORT_SYMBOL(__direct_map_size);
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
EXPORT_SYMBOL(pci_alloc_consistent);
|
||||
EXPORT_SYMBOL(pci_free_consistent);
|
||||
EXPORT_SYMBOL(pci_map_single);
|
||||
EXPORT_SYMBOL(pci_map_page);
|
||||
EXPORT_SYMBOL(pci_unmap_single);
|
||||
EXPORT_SYMBOL(pci_unmap_page);
|
||||
EXPORT_SYMBOL(pci_map_sg);
|
||||
EXPORT_SYMBOL(pci_unmap_sg);
|
||||
EXPORT_SYMBOL(pci_dma_supported);
|
||||
EXPORT_SYMBOL(pci_dac_dma_supported);
|
||||
EXPORT_SYMBOL(pci_dac_page_to_dma);
|
||||
EXPORT_SYMBOL(pci_dac_dma_to_page);
|
||||
EXPORT_SYMBOL(pci_dac_dma_to_offset);
|
||||
EXPORT_SYMBOL(alpha_gendev_to_pci);
|
||||
#endif
|
||||
EXPORT_SYMBOL(dma_set_mask);
|
||||
|
||||
EXPORT_SYMBOL(dump_thread);
|
||||
EXPORT_SYMBOL(dump_elf_thread);
|
||||
EXPORT_SYMBOL(dump_elf_task);
|
||||
EXPORT_SYMBOL(dump_elf_task_fp);
|
||||
EXPORT_SYMBOL(hwrpb);
|
||||
EXPORT_SYMBOL(start_thread);
|
||||
EXPORT_SYMBOL(alpha_read_fp_reg);
|
||||
EXPORT_SYMBOL(alpha_read_fp_reg_s);
|
||||
EXPORT_SYMBOL(alpha_write_fp_reg);
|
||||
EXPORT_SYMBOL(alpha_write_fp_reg_s);
|
||||
|
||||
/* In-kernel system calls. */
|
||||
EXPORT_SYMBOL(kernel_thread);
|
||||
EXPORT_SYMBOL(sys_open);
|
||||
EXPORT_SYMBOL(sys_dup);
|
||||
EXPORT_SYMBOL(sys_exit);
|
||||
EXPORT_SYMBOL(sys_write);
|
||||
EXPORT_SYMBOL(sys_read);
|
||||
EXPORT_SYMBOL(sys_lseek);
|
||||
EXPORT_SYMBOL(execve);
|
||||
EXPORT_SYMBOL(sys_setsid);
|
||||
EXPORT_SYMBOL(sys_wait4);
|
||||
|
||||
/* Networking helper routines. */
|
||||
EXPORT_SYMBOL(csum_tcpudp_magic);
|
||||
EXPORT_SYMBOL(ip_compute_csum);
|
||||
EXPORT_SYMBOL(ip_fast_csum);
|
||||
EXPORT_SYMBOL(csum_partial_copy_nocheck);
|
||||
EXPORT_SYMBOL(csum_partial_copy_from_user);
|
||||
EXPORT_SYMBOL(csum_ipv6_magic);
|
||||
|
||||
#ifdef CONFIG_MATHEMU_MODULE
|
||||
extern long (*alpha_fp_emul_imprecise)(struct pt_regs *, unsigned long);
|
||||
extern long (*alpha_fp_emul) (unsigned long pc);
|
||||
EXPORT_SYMBOL(alpha_fp_emul_imprecise);
|
||||
EXPORT_SYMBOL(alpha_fp_emul);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ALPHA_BROKEN_IRQ_MASK
|
||||
EXPORT_SYMBOL(__min_ipl);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The following are specially called from the uaccess assembly stubs.
|
||||
*/
|
||||
EXPORT_SYMBOL(__copy_user);
|
||||
EXPORT_SYMBOL(__do_clear_user);
|
||||
EXPORT_SYMBOL(__strncpy_from_user);
|
||||
EXPORT_SYMBOL(__strnlen_user);
|
||||
|
||||
/* Semaphore helper functions. */
|
||||
EXPORT_SYMBOL(__down_failed);
|
||||
EXPORT_SYMBOL(__down_failed_interruptible);
|
||||
EXPORT_SYMBOL(__up_wakeup);
|
||||
EXPORT_SYMBOL(down);
|
||||
EXPORT_SYMBOL(down_interruptible);
|
||||
EXPORT_SYMBOL(down_trylock);
|
||||
EXPORT_SYMBOL(up);
|
||||
|
||||
/*
|
||||
* SMP-specific symbols.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
EXPORT_SYMBOL(synchronize_irq);
|
||||
EXPORT_SYMBOL(flush_tlb_mm);
|
||||
EXPORT_SYMBOL(flush_tlb_range);
|
||||
EXPORT_SYMBOL(flush_tlb_page);
|
||||
EXPORT_SYMBOL(smp_imb);
|
||||
EXPORT_SYMBOL(cpu_data);
|
||||
EXPORT_SYMBOL(smp_num_cpus);
|
||||
EXPORT_SYMBOL(smp_call_function);
|
||||
EXPORT_SYMBOL(smp_call_function_on_cpu);
|
||||
EXPORT_SYMBOL(_atomic_dec_and_lock);
|
||||
#ifdef CONFIG_DEBUG_SPINLOCK
|
||||
EXPORT_SYMBOL(_raw_spin_unlock);
|
||||
EXPORT_SYMBOL(debug_spin_lock);
|
||||
EXPORT_SYMBOL(debug_spin_trylock);
|
||||
#endif
|
||||
#ifdef CONFIG_DEBUG_RWLOCK
|
||||
EXPORT_SYMBOL(_raw_write_lock);
|
||||
EXPORT_SYMBOL(_raw_read_lock);
|
||||
#endif
|
||||
EXPORT_SYMBOL(cpu_present_mask);
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
/*
|
||||
* NUMA specific symbols
|
||||
*/
|
||||
#ifdef CONFIG_DISCONTIGMEM
|
||||
EXPORT_SYMBOL(node_data);
|
||||
#endif /* CONFIG_DISCONTIGMEM */
|
||||
|
||||
EXPORT_SYMBOL(rtc_lock);
|
||||
|
||||
/*
|
||||
* The following are special because they're not called
|
||||
* explicitly (the C compiler or assembler generates them in
|
||||
* response to division operations). Fortunately, their
|
||||
* interface isn't gonna change any time soon now, so it's OK
|
||||
* to leave it out of version control.
|
||||
*/
|
||||
# undef memcpy
|
||||
# undef memset
|
||||
EXPORT_SYMBOL(__divl);
|
||||
EXPORT_SYMBOL(__divlu);
|
||||
EXPORT_SYMBOL(__divq);
|
||||
EXPORT_SYMBOL(__divqu);
|
||||
EXPORT_SYMBOL(__reml);
|
||||
EXPORT_SYMBOL(__remlu);
|
||||
EXPORT_SYMBOL(__remq);
|
||||
EXPORT_SYMBOL(__remqu);
|
||||
EXPORT_SYMBOL(memcpy);
|
||||
EXPORT_SYMBOL(memset);
|
||||
EXPORT_SYMBOL(memchr);
|
||||
|
||||
EXPORT_SYMBOL(get_wchan);
|
||||
|
||||
#ifdef CONFIG_ALPHA_IRONGATE
|
||||
EXPORT_SYMBOL(irongate_ioremap);
|
||||
EXPORT_SYMBOL(irongate_iounmap);
|
||||
#endif
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Generate definitions needed by assembly language modules.
|
||||
* This code generates raw asm output which is post-processed to extract
|
||||
* and format the required data.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#define DEFINE(sym, val) \
|
||||
asm volatile("\n->" #sym " %0 " #val : : "i" (val))
|
||||
|
||||
#define BLANK() asm volatile("\n->" : : )
|
||||
|
||||
void foo(void)
|
||||
{
|
||||
DEFINE(TI_TASK, offsetof(struct thread_info, task));
|
||||
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
|
||||
DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
|
||||
BLANK();
|
||||
|
||||
DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked));
|
||||
DEFINE(TASK_UID, offsetof(struct task_struct, uid));
|
||||
DEFINE(TASK_EUID, offsetof(struct task_struct, euid));
|
||||
DEFINE(TASK_GID, offsetof(struct task_struct, gid));
|
||||
DEFINE(TASK_EGID, offsetof(struct task_struct, egid));
|
||||
DEFINE(TASK_REAL_PARENT, offsetof(struct task_struct, real_parent));
|
||||
DEFINE(TASK_TGID, offsetof(struct task_struct, tgid));
|
||||
BLANK();
|
||||
|
||||
DEFINE(SIZEOF_PT_REGS, sizeof(struct pt_regs));
|
||||
DEFINE(PT_PTRACED, PT_PTRACED);
|
||||
DEFINE(CLONE_VM, CLONE_VM);
|
||||
DEFINE(CLONE_UNTRACED, CLONE_UNTRACED);
|
||||
DEFINE(SIGCHLD, SIGCHLD);
|
||||
BLANK();
|
||||
|
||||
DEFINE(HAE_CACHE, offsetof(struct alpha_machine_vector, hae_cache));
|
||||
DEFINE(HAE_REG, offsetof(struct alpha_machine_vector, hae_register));
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* linux/arch/alpha/kernel/console.c
|
||||
*
|
||||
* Architecture-specific specific support for VGA device on
|
||||
* non-0 I/O hose
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/console.h>
|
||||
#include <asm/vga.h>
|
||||
#include <asm/machvec.h>
|
||||
|
||||
#ifdef CONFIG_VGA_HOSE
|
||||
|
||||
/*
|
||||
* Externally-visible vga hose bases
|
||||
*/
|
||||
unsigned long __vga_hose_io_base = 0; /* base for default hose */
|
||||
unsigned long __vga_hose_mem_base = 0; /* base for default hose */
|
||||
|
||||
static struct pci_controller * __init
|
||||
default_vga_hose_select(struct pci_controller *h1, struct pci_controller *h2)
|
||||
{
|
||||
if (h2->index < h1->index)
|
||||
return h2;
|
||||
|
||||
return h1;
|
||||
}
|
||||
|
||||
void __init
|
||||
set_vga_hose(struct pci_controller *hose)
|
||||
{
|
||||
if (hose) {
|
||||
__vga_hose_io_base = hose->io_space->start;
|
||||
__vga_hose_mem_base = hose->mem_space->start;
|
||||
}
|
||||
}
|
||||
|
||||
void __init
|
||||
locate_and_init_vga(void *(*sel_func)(void *, void *))
|
||||
{
|
||||
struct pci_controller *hose = NULL;
|
||||
struct pci_dev *dev = NULL;
|
||||
|
||||
if (!sel_func) sel_func = (void *)default_vga_hose_select;
|
||||
|
||||
for(dev=NULL; (dev=pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, dev));) {
|
||||
if (!hose) hose = dev->sysdata;
|
||||
else hose = sel_func(hose, dev->sysdata);
|
||||
}
|
||||
|
||||
/* Did we already inititialize the correct one? */
|
||||
if (conswitchp == &vga_con &&
|
||||
__vga_hose_io_base == hose->io_space->start &&
|
||||
__vga_hose_mem_base == hose->mem_space->start)
|
||||
return;
|
||||
|
||||
/* Set the VGA hose and init the new console */
|
||||
set_vga_hose(hose);
|
||||
take_over_console(&vga_con, 0, MAX_NR_CONSOLES-1, 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,418 @@
|
||||
/*
|
||||
* linux/arch/alpha/kernel/core_apecs.c
|
||||
*
|
||||
* Rewritten for Apecs from the lca.c from:
|
||||
*
|
||||
* Written by David Mosberger (davidm@cs.arizona.edu) with some code
|
||||
* taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit
|
||||
* bios code.
|
||||
*
|
||||
* Code common to all APECS core logic chips.
|
||||
*/
|
||||
|
||||
#define __EXTERN_INLINE inline
|
||||
#include <asm/io.h>
|
||||
#include <asm/core_apecs.h>
|
||||
#undef __EXTERN_INLINE
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/smp.h>
|
||||
|
||||
#include "proto.h"
|
||||
#include "pci_impl.h"
|
||||
|
||||
/*
|
||||
* NOTE: Herein lie back-to-back mb instructions. They are magic.
|
||||
* One plausible explanation is that the i/o controller does not properly
|
||||
* handle the system transaction. Another involves timing. Ho hum.
|
||||
*/
|
||||
|
||||
/*
|
||||
* BIOS32-style PCI interface:
|
||||
*/
|
||||
|
||||
#define DEBUG_CONFIG 0
|
||||
|
||||
#if DEBUG_CONFIG
|
||||
# define DBGC(args) printk args
|
||||
#else
|
||||
# define DBGC(args)
|
||||
#endif
|
||||
|
||||
#define vuip volatile unsigned int *
|
||||
|
||||
/*
|
||||
* Given a bus, device, and function number, compute resulting
|
||||
* configuration space address and setup the APECS_HAXR2 register
|
||||
* accordingly. It is therefore not safe to have concurrent
|
||||
* invocations to configuration space access routines, but there
|
||||
* really shouldn't be any need for this.
|
||||
*
|
||||
* Type 0:
|
||||
*
|
||||
* 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
|
||||
* 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | | | | | | | | | | | | | | | | | | | | | | | |F|F|F|R|R|R|R|R|R|0|0|
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*
|
||||
* 31:11 Device select bit.
|
||||
* 10:8 Function number
|
||||
* 7:2 Register number
|
||||
*
|
||||
* Type 1:
|
||||
*
|
||||
* 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
|
||||
* 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*
|
||||
* 31:24 reserved
|
||||
* 23:16 bus number (8 bits = 128 possible buses)
|
||||
* 15:11 Device number (5 bits)
|
||||
* 10:8 function number
|
||||
* 7:2 register number
|
||||
*
|
||||
* Notes:
|
||||
* The function number selects which function of a multi-function device
|
||||
* (e.g., SCSI and Ethernet).
|
||||
*
|
||||
* The register selects a DWORD (32 bit) register offset. Hence it
|
||||
* doesn't get shifted by 2 bits as we want to "drop" the bottom two
|
||||
* bits.
|
||||
*/
|
||||
|
||||
static int
|
||||
mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where,
|
||||
unsigned long *pci_addr, unsigned char *type1)
|
||||
{
|
||||
unsigned long addr;
|
||||
u8 bus = pbus->number;
|
||||
|
||||
DBGC(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x,"
|
||||
" pci_addr=0x%p, type1=0x%p)\n",
|
||||
bus, device_fn, where, pci_addr, type1));
|
||||
|
||||
if (bus == 0) {
|
||||
int device = device_fn >> 3;
|
||||
|
||||
/* type 0 configuration cycle: */
|
||||
|
||||
if (device > 20) {
|
||||
DBGC(("mk_conf_addr: device (%d) > 20, returning -1\n",
|
||||
device));
|
||||
return -1;
|
||||
}
|
||||
|
||||
*type1 = 0;
|
||||
addr = (device_fn << 8) | (where);
|
||||
} else {
|
||||
/* type 1 configuration cycle: */
|
||||
*type1 = 1;
|
||||
addr = (bus << 16) | (device_fn << 8) | (where);
|
||||
}
|
||||
*pci_addr = addr;
|
||||
DBGC(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
conf_read(unsigned long addr, unsigned char type1)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int stat0, value;
|
||||
unsigned int haxr2 = 0;
|
||||
|
||||
local_irq_save(flags); /* avoid getting hit by machine check */
|
||||
|
||||
DBGC(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1));
|
||||
|
||||
/* Reset status register to avoid losing errors. */
|
||||
stat0 = *(vuip)APECS_IOC_DCSR;
|
||||
*(vuip)APECS_IOC_DCSR = stat0;
|
||||
mb();
|
||||
DBGC(("conf_read: APECS DCSR was 0x%x\n", stat0));
|
||||
|
||||
/* If Type1 access, must set HAE #2. */
|
||||
if (type1) {
|
||||
haxr2 = *(vuip)APECS_IOC_HAXR2;
|
||||
mb();
|
||||
*(vuip)APECS_IOC_HAXR2 = haxr2 | 1;
|
||||
DBGC(("conf_read: TYPE1 access\n"));
|
||||
}
|
||||
|
||||
draina();
|
||||
mcheck_expected(0) = 1;
|
||||
mcheck_taken(0) = 0;
|
||||
mb();
|
||||
|
||||
/* Access configuration space. */
|
||||
|
||||
/* Some SRMs step on these registers during a machine check. */
|
||||
asm volatile("ldl %0,%1; mb; mb" : "=r"(value) : "m"(*(vuip)addr)
|
||||
: "$9", "$10", "$11", "$12", "$13", "$14", "memory");
|
||||
|
||||
if (mcheck_taken(0)) {
|
||||
mcheck_taken(0) = 0;
|
||||
value = 0xffffffffU;
|
||||
mb();
|
||||
}
|
||||
mcheck_expected(0) = 0;
|
||||
mb();
|
||||
|
||||
#if 1
|
||||
/*
|
||||
* david.rusling@reo.mts.dec.com. This code is needed for the
|
||||
* EB64+ as it does not generate a machine check (why I don't
|
||||
* know). When we build kernels for one particular platform
|
||||
* then we can make this conditional on the type.
|
||||
*/
|
||||
draina();
|
||||
|
||||
/* Now look for any errors. */
|
||||
stat0 = *(vuip)APECS_IOC_DCSR;
|
||||
DBGC(("conf_read: APECS DCSR after read 0x%x\n", stat0));
|
||||
|
||||
/* Is any error bit set? */
|
||||
if (stat0 & 0xffe0U) {
|
||||
/* If not NDEV, print status. */
|
||||
if (!(stat0 & 0x0800)) {
|
||||
printk("apecs.c:conf_read: got stat0=%x\n", stat0);
|
||||
}
|
||||
|
||||
/* Reset error status. */
|
||||
*(vuip)APECS_IOC_DCSR = stat0;
|
||||
mb();
|
||||
wrmces(0x7); /* reset machine check */
|
||||
value = 0xffffffff;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If Type1 access, must reset HAE #2 so normal IO space ops work. */
|
||||
if (type1) {
|
||||
*(vuip)APECS_IOC_HAXR2 = haxr2 & ~1;
|
||||
mb();
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static void
|
||||
conf_write(unsigned long addr, unsigned int value, unsigned char type1)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int stat0;
|
||||
unsigned int haxr2 = 0;
|
||||
|
||||
local_irq_save(flags); /* avoid getting hit by machine check */
|
||||
|
||||
/* Reset status register to avoid losing errors. */
|
||||
stat0 = *(vuip)APECS_IOC_DCSR;
|
||||
*(vuip)APECS_IOC_DCSR = stat0;
|
||||
mb();
|
||||
|
||||
/* If Type1 access, must set HAE #2. */
|
||||
if (type1) {
|
||||
haxr2 = *(vuip)APECS_IOC_HAXR2;
|
||||
mb();
|
||||
*(vuip)APECS_IOC_HAXR2 = haxr2 | 1;
|
||||
}
|
||||
|
||||
draina();
|
||||
mcheck_expected(0) = 1;
|
||||
mb();
|
||||
|
||||
/* Access configuration space. */
|
||||
*(vuip)addr = value;
|
||||
mb();
|
||||
mb(); /* magic */
|
||||
mcheck_expected(0) = 0;
|
||||
mb();
|
||||
|
||||
#if 1
|
||||
/*
|
||||
* david.rusling@reo.mts.dec.com. This code is needed for the
|
||||
* EB64+ as it does not generate a machine check (why I don't
|
||||
* know). When we build kernels for one particular platform
|
||||
* then we can make this conditional on the type.
|
||||
*/
|
||||
draina();
|
||||
|
||||
/* Now look for any errors. */
|
||||
stat0 = *(vuip)APECS_IOC_DCSR;
|
||||
|
||||
/* Is any error bit set? */
|
||||
if (stat0 & 0xffe0U) {
|
||||
/* If not NDEV, print status. */
|
||||
if (!(stat0 & 0x0800)) {
|
||||
printk("apecs.c:conf_write: got stat0=%x\n", stat0);
|
||||
}
|
||||
|
||||
/* Reset error status. */
|
||||
*(vuip)APECS_IOC_DCSR = stat0;
|
||||
mb();
|
||||
wrmces(0x7); /* reset machine check */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If Type1 access, must reset HAE #2 so normal IO space ops work. */
|
||||
if (type1) {
|
||||
*(vuip)APECS_IOC_HAXR2 = haxr2 & ~1;
|
||||
mb();
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static int
|
||||
apecs_read_config(struct pci_bus *bus, unsigned int devfn, int where,
|
||||
int size, u32 *value)
|
||||
{
|
||||
unsigned long addr, pci_addr;
|
||||
unsigned char type1;
|
||||
long mask;
|
||||
int shift;
|
||||
|
||||
if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1))
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
mask = (size - 1) * 8;
|
||||
shift = (where & 3) * 8;
|
||||
addr = (pci_addr << 5) + mask + APECS_CONF;
|
||||
*value = conf_read(addr, type1) >> (shift);
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static int
|
||||
apecs_write_config(struct pci_bus *bus, unsigned int devfn, int where,
|
||||
int size, u32 value)
|
||||
{
|
||||
unsigned long addr, pci_addr;
|
||||
unsigned char type1;
|
||||
long mask;
|
||||
|
||||
if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1))
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
mask = (size - 1) * 8;
|
||||
addr = (pci_addr << 5) + mask + APECS_CONF;
|
||||
conf_write(addr, value << ((where & 3) * 8), type1);
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
struct pci_ops apecs_pci_ops =
|
||||
{
|
||||
.read = apecs_read_config,
|
||||
.write = apecs_write_config,
|
||||
};
|
||||
|
||||
void
|
||||
apecs_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
|
||||
{
|
||||
wmb();
|
||||
*(vip)APECS_IOC_TBIA = 0;
|
||||
mb();
|
||||
}
|
||||
|
||||
void __init
|
||||
apecs_init_arch(void)
|
||||
{
|
||||
struct pci_controller *hose;
|
||||
|
||||
/*
|
||||
* Create our single hose.
|
||||
*/
|
||||
|
||||
pci_isa_hose = hose = alloc_pci_controller();
|
||||
hose->io_space = &ioport_resource;
|
||||
hose->mem_space = &iomem_resource;
|
||||
hose->index = 0;
|
||||
|
||||
hose->sparse_mem_base = APECS_SPARSE_MEM - IDENT_ADDR;
|
||||
hose->dense_mem_base = APECS_DENSE_MEM - IDENT_ADDR;
|
||||
hose->sparse_io_base = APECS_IO - IDENT_ADDR;
|
||||
hose->dense_io_base = 0;
|
||||
|
||||
/*
|
||||
* Set up the PCI to main memory translation windows.
|
||||
*
|
||||
* Window 1 is direct access 1GB at 1GB
|
||||
* Window 2 is scatter-gather 8MB at 8MB (for isa)
|
||||
*/
|
||||
hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0);
|
||||
hose->sg_pci = NULL;
|
||||
__direct_map_base = 0x40000000;
|
||||
__direct_map_size = 0x40000000;
|
||||
|
||||
*(vuip)APECS_IOC_PB1R = __direct_map_base | 0x00080000;
|
||||
*(vuip)APECS_IOC_PM1R = (__direct_map_size - 1) & 0xfff00000U;
|
||||
*(vuip)APECS_IOC_TB1R = 0;
|
||||
|
||||
*(vuip)APECS_IOC_PB2R = hose->sg_isa->dma_base | 0x000c0000;
|
||||
*(vuip)APECS_IOC_PM2R = (hose->sg_isa->size - 1) & 0xfff00000;
|
||||
*(vuip)APECS_IOC_TB2R = virt_to_phys(hose->sg_isa->ptes) >> 1;
|
||||
|
||||
apecs_pci_tbi(hose, 0, -1);
|
||||
|
||||
/*
|
||||
* Finally, clear the HAXR2 register, which gets used
|
||||
* for PCI Config Space accesses. That is the way
|
||||
* we want to use it, and we do not want to depend on
|
||||
* what ARC or SRM might have left behind...
|
||||
*/
|
||||
*(vuip)APECS_IOC_HAXR2 = 0;
|
||||
mb();
|
||||
}
|
||||
|
||||
void
|
||||
apecs_pci_clr_err(void)
|
||||
{
|
||||
unsigned int jd;
|
||||
|
||||
jd = *(vuip)APECS_IOC_DCSR;
|
||||
if (jd & 0xffe0L) {
|
||||
*(vuip)APECS_IOC_SEAR;
|
||||
*(vuip)APECS_IOC_DCSR = jd | 0xffe1L;
|
||||
mb();
|
||||
*(vuip)APECS_IOC_DCSR;
|
||||
}
|
||||
*(vuip)APECS_IOC_TBIA = (unsigned int)APECS_IOC_TBIA;
|
||||
mb();
|
||||
*(vuip)APECS_IOC_TBIA;
|
||||
}
|
||||
|
||||
void
|
||||
apecs_machine_check(unsigned long vector, unsigned long la_ptr,
|
||||
struct pt_regs * regs)
|
||||
{
|
||||
struct el_common *mchk_header;
|
||||
struct el_apecs_procdata *mchk_procdata;
|
||||
struct el_apecs_sysdata_mcheck *mchk_sysdata;
|
||||
|
||||
mchk_header = (struct el_common *)la_ptr;
|
||||
|
||||
mchk_procdata = (struct el_apecs_procdata *)
|
||||
(la_ptr + mchk_header->proc_offset
|
||||
- sizeof(mchk_procdata->paltemp));
|
||||
|
||||
mchk_sysdata = (struct el_apecs_sysdata_mcheck *)
|
||||
(la_ptr + mchk_header->sys_offset);
|
||||
|
||||
|
||||
/* Clear the error before any reporting. */
|
||||
mb();
|
||||
mb(); /* magic */
|
||||
draina();
|
||||
apecs_pci_clr_err();
|
||||
wrmces(0x7); /* reset machine check pending flag */
|
||||
mb();
|
||||
|
||||
process_mcheck_info(vector, la_ptr, regs, "APECS",
|
||||
(mcheck_expected(0)
|
||||
&& (mchk_sysdata->epic_dcsr & 0x0c00UL)));
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,416 @@
|
||||
/*
|
||||
* linux/arch/alpha/kernel/core_irongate.c
|
||||
*
|
||||
* Based on code written by David A. Rusling (david.rusling@reo.mts.dec.com).
|
||||
*
|
||||
* Copyright (C) 1999 Alpha Processor, Inc.,
|
||||
* (David Daniel, Stig Telfer, Soohoon Lee)
|
||||
*
|
||||
* Code common to all IRONGATE core logic chips.
|
||||
*/
|
||||
|
||||
#define __EXTERN_INLINE inline
|
||||
#include <asm/io.h>
|
||||
#include <asm/core_irongate.h>
|
||||
#undef __EXTERN_INLINE
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/initrd.h>
|
||||
#include <linux/bootmem.h>
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/pci.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/tlbflush.h>
|
||||
|
||||
#include "proto.h"
|
||||
#include "pci_impl.h"
|
||||
|
||||
/*
|
||||
* BIOS32-style PCI interface:
|
||||
*/
|
||||
|
||||
#define DEBUG_CONFIG 0
|
||||
|
||||
#if DEBUG_CONFIG
|
||||
# define DBG_CFG(args) printk args
|
||||
#else
|
||||
# define DBG_CFG(args)
|
||||
#endif
|
||||
|
||||
igcsr32 *IronECC;
|
||||
|
||||
/*
|
||||
* Given a bus, device, and function number, compute resulting
|
||||
* configuration space address accordingly. It is therefore not safe
|
||||
* to have concurrent invocations to configuration space access
|
||||
* routines, but there really shouldn't be any need for this.
|
||||
*
|
||||
* addr[31:24] reserved
|
||||
* addr[23:16] bus number (8 bits = 128 possible buses)
|
||||
* addr[15:11] Device number (5 bits)
|
||||
* addr[10: 8] function number
|
||||
* addr[ 7: 2] register number
|
||||
*
|
||||
* For IRONGATE:
|
||||
* if (bus = addr[23:16]) == 0
|
||||
* then
|
||||
* type 0 config cycle:
|
||||
* addr_on_pci[31:11] = id selection for device = addr[15:11]
|
||||
* addr_on_pci[10: 2] = addr[10: 2] ???
|
||||
* addr_on_pci[ 1: 0] = 00
|
||||
* else
|
||||
* type 1 config cycle (pass on with no decoding):
|
||||
* addr_on_pci[31:24] = 0
|
||||
* addr_on_pci[23: 2] = addr[23: 2]
|
||||
* addr_on_pci[ 1: 0] = 01
|
||||
* fi
|
||||
*
|
||||
* Notes:
|
||||
* The function number selects which function of a multi-function device
|
||||
* (e.g., SCSI and Ethernet).
|
||||
*
|
||||
* The register selects a DWORD (32 bit) register offset. Hence it
|
||||
* doesn't get shifted by 2 bits as we want to "drop" the bottom two
|
||||
* bits.
|
||||
*/
|
||||
|
||||
static int
|
||||
mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where,
|
||||
unsigned long *pci_addr, unsigned char *type1)
|
||||
{
|
||||
unsigned long addr;
|
||||
u8 bus = pbus->number;
|
||||
|
||||
DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, "
|
||||
"pci_addr=0x%p, type1=0x%p)\n",
|
||||
bus, device_fn, where, pci_addr, type1));
|
||||
|
||||
*type1 = (bus != 0);
|
||||
|
||||
addr = (bus << 16) | (device_fn << 8) | where;
|
||||
addr |= IRONGATE_CONF;
|
||||
|
||||
*pci_addr = addr;
|
||||
DBG_CFG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
irongate_read_config(struct pci_bus *bus, unsigned int devfn, int where,
|
||||
int size, u32 *value)
|
||||
{
|
||||
unsigned long addr;
|
||||
unsigned char type1;
|
||||
|
||||
if (mk_conf_addr(bus, devfn, where, &addr, &type1))
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
switch (size) {
|
||||
case 1:
|
||||
*value = __kernel_ldbu(*(vucp)addr);
|
||||
break;
|
||||
case 2:
|
||||
*value = __kernel_ldwu(*(vusp)addr);
|
||||
break;
|
||||
case 4:
|
||||
*value = *(vuip)addr;
|
||||
break;
|
||||
}
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static int
|
||||
irongate_write_config(struct pci_bus *bus, unsigned int devfn, int where,
|
||||
int size, u32 value)
|
||||
{
|
||||
unsigned long addr;
|
||||
unsigned char type1;
|
||||
|
||||
if (mk_conf_addr(bus, devfn, where, &addr, &type1))
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
switch (size) {
|
||||
case 1:
|
||||
__kernel_stb(value, *(vucp)addr);
|
||||
mb();
|
||||
__kernel_ldbu(*(vucp)addr);
|
||||
break;
|
||||
case 2:
|
||||
__kernel_stw(value, *(vusp)addr);
|
||||
mb();
|
||||
__kernel_ldwu(*(vusp)addr);
|
||||
break;
|
||||
case 4:
|
||||
*(vuip)addr = value;
|
||||
mb();
|
||||
*(vuip)addr;
|
||||
break;
|
||||
}
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
struct pci_ops irongate_pci_ops =
|
||||
{
|
||||
.read = irongate_read_config,
|
||||
.write = irongate_write_config,
|
||||
};
|
||||
|
||||
int
|
||||
irongate_pci_clr_err(void)
|
||||
{
|
||||
unsigned int nmi_ctl=0;
|
||||
unsigned int IRONGATE_jd;
|
||||
|
||||
again:
|
||||
IRONGATE_jd = IRONGATE0->stat_cmd;
|
||||
printk("Iron stat_cmd %x\n", IRONGATE_jd);
|
||||
IRONGATE0->stat_cmd = IRONGATE_jd; /* write again clears error bits */
|
||||
mb();
|
||||
IRONGATE_jd = IRONGATE0->stat_cmd; /* re-read to force write */
|
||||
|
||||
IRONGATE_jd = *IronECC;
|
||||
printk("Iron ECC %x\n", IRONGATE_jd);
|
||||
*IronECC = IRONGATE_jd; /* write again clears error bits */
|
||||
mb();
|
||||
IRONGATE_jd = *IronECC; /* re-read to force write */
|
||||
|
||||
/* Clear ALI NMI */
|
||||
nmi_ctl = inb(0x61);
|
||||
nmi_ctl |= 0x0c;
|
||||
outb(nmi_ctl, 0x61);
|
||||
nmi_ctl &= ~0x0c;
|
||||
outb(nmi_ctl, 0x61);
|
||||
|
||||
IRONGATE_jd = *IronECC;
|
||||
if (IRONGATE_jd & 0x300) goto again;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define IRONGATE_3GB 0xc0000000UL
|
||||
|
||||
/* On Albacore (aka UP1500) with 4Gb of RAM we have to reserve some
|
||||
memory for PCI. At this point we just reserve memory above 3Gb. Most
|
||||
of this memory will be freed after PCI setup is done. */
|
||||
static void __init
|
||||
albacore_init_arch(void)
|
||||
{
|
||||
unsigned long memtop = max_low_pfn << PAGE_SHIFT;
|
||||
unsigned long pci_mem = (memtop + 0x1000000UL) & ~0xffffffUL;
|
||||
struct percpu_struct *cpu;
|
||||
int pal_rev, pal_var;
|
||||
|
||||
cpu = (struct percpu_struct*)((char*)hwrpb + hwrpb->processor_offset);
|
||||
pal_rev = cpu->pal_revision & 0xffff;
|
||||
pal_var = (cpu->pal_revision >> 16) & 0xff;
|
||||
|
||||
/* Consoles earlier than A5.6-18 (OSF PALcode v1.62-2) set up
|
||||
the CPU incorrectly (leave speculative stores enabled),
|
||||
which causes memory corruption under certain conditions.
|
||||
Issue a warning for such consoles. */
|
||||
if (alpha_using_srm &&
|
||||
(pal_rev < 0x13e || (pal_rev == 0x13e && pal_var < 2)))
|
||||
printk(KERN_WARNING "WARNING! Upgrade to SRM A5.6-19 "
|
||||
"or later\n");
|
||||
|
||||
if (pci_mem > IRONGATE_3GB)
|
||||
pci_mem = IRONGATE_3GB;
|
||||
IRONGATE0->pci_mem = pci_mem;
|
||||
alpha_mv.min_mem_address = pci_mem;
|
||||
if (memtop > pci_mem) {
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
extern unsigned long initrd_start, initrd_end;
|
||||
extern void *move_initrd(unsigned long);
|
||||
|
||||
/* Move the initrd out of the way. */
|
||||
if (initrd_end && __pa(initrd_end) > pci_mem) {
|
||||
unsigned long size;
|
||||
|
||||
size = initrd_end - initrd_start;
|
||||
free_bootmem_node(NODE_DATA(0), __pa(initrd_start),
|
||||
PAGE_ALIGN(size));
|
||||
if (!move_initrd(pci_mem))
|
||||
printk("irongate_init_arch: initrd too big "
|
||||
"(%ldK)\ndisabling initrd\n",
|
||||
size / 1024);
|
||||
}
|
||||
#endif
|
||||
reserve_bootmem_node(NODE_DATA(0), pci_mem, memtop - pci_mem);
|
||||
printk("irongate_init_arch: temporarily reserving "
|
||||
"region %08lx-%08lx for PCI\n", pci_mem, memtop - 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void __init
|
||||
irongate_setup_agp(void)
|
||||
{
|
||||
/* Disable the GART window. AGPGART doesn't work due to yet
|
||||
unresolved memory coherency issues... */
|
||||
IRONGATE0->agpva = IRONGATE0->agpva & ~0xf;
|
||||
alpha_agpgart_size = 0;
|
||||
}
|
||||
|
||||
void __init
|
||||
irongate_init_arch(void)
|
||||
{
|
||||
struct pci_controller *hose;
|
||||
int amd761 = (IRONGATE0->dev_vendor >> 16) > 0x7006; /* Albacore? */
|
||||
|
||||
IronECC = amd761 ? &IRONGATE0->bacsr54_eccms761 : &IRONGATE0->dramms;
|
||||
|
||||
irongate_pci_clr_err();
|
||||
|
||||
if (amd761)
|
||||
albacore_init_arch();
|
||||
|
||||
irongate_setup_agp();
|
||||
|
||||
/*
|
||||
* Create our single hose.
|
||||
*/
|
||||
|
||||
pci_isa_hose = hose = alloc_pci_controller();
|
||||
hose->io_space = &ioport_resource;
|
||||
hose->mem_space = &iomem_resource;
|
||||
hose->index = 0;
|
||||
|
||||
/* This is for userland consumption. For some reason, the 40-bit
|
||||
PIO bias that we use in the kernel through KSEG didn't work for
|
||||
the page table based user mappings. So make sure we get the
|
||||
43-bit PIO bias. */
|
||||
hose->sparse_mem_base = 0;
|
||||
hose->sparse_io_base = 0;
|
||||
hose->dense_mem_base
|
||||
= (IRONGATE_MEM & 0xffffffffffUL) | 0x80000000000UL;
|
||||
hose->dense_io_base
|
||||
= (IRONGATE_IO & 0xffffffffffUL) | 0x80000000000UL;
|
||||
|
||||
hose->sg_isa = hose->sg_pci = NULL;
|
||||
__direct_map_base = 0;
|
||||
__direct_map_size = 0xffffffff;
|
||||
}
|
||||
|
||||
/*
|
||||
* IO map and AGP support
|
||||
*/
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/agp_backend.h>
|
||||
#include <linux/agpgart.h>
|
||||
#include <asm/pgalloc.h>
|
||||
|
||||
#define GET_PAGE_DIR_OFF(addr) (addr >> 22)
|
||||
#define GET_PAGE_DIR_IDX(addr) (GET_PAGE_DIR_OFF(addr))
|
||||
|
||||
#define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12)
|
||||
#define GET_GATT(addr) (gatt_pages[GET_PAGE_DIR_IDX(addr)])
|
||||
|
||||
void __iomem *
|
||||
irongate_ioremap(unsigned long addr, unsigned long size)
|
||||
{
|
||||
struct vm_struct *area;
|
||||
unsigned long vaddr;
|
||||
unsigned long baddr, last;
|
||||
u32 *mmio_regs, *gatt_pages, *cur_gatt, pte;
|
||||
unsigned long gart_bus_addr;
|
||||
|
||||
if (!alpha_agpgart_size)
|
||||
return (void __iomem *)(addr + IRONGATE_MEM);
|
||||
|
||||
gart_bus_addr = (unsigned long)IRONGATE0->bar0 &
|
||||
PCI_BASE_ADDRESS_MEM_MASK;
|
||||
|
||||
/*
|
||||
* Check for within the AGP aperture...
|
||||
*/
|
||||
do {
|
||||
/*
|
||||
* Check the AGP area
|
||||
*/
|
||||
if (addr >= gart_bus_addr && addr + size - 1 <
|
||||
gart_bus_addr + alpha_agpgart_size)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Not found - assume legacy ioremap
|
||||
*/
|
||||
return (void __iomem *)(addr + IRONGATE_MEM);
|
||||
} while(0);
|
||||
|
||||
mmio_regs = (u32 *)(((unsigned long)IRONGATE0->bar1 &
|
||||
PCI_BASE_ADDRESS_MEM_MASK) + IRONGATE_MEM);
|
||||
|
||||
gatt_pages = (u32 *)(phys_to_virt(mmio_regs[1])); /* FIXME */
|
||||
|
||||
/*
|
||||
* Adjust the limits (mappings must be page aligned)
|
||||
*/
|
||||
if (addr & ~PAGE_MASK) {
|
||||
printk("AGP ioremap failed... addr not page aligned (0x%lx)\n",
|
||||
addr);
|
||||
return (void __iomem *)(addr + IRONGATE_MEM);
|
||||
}
|
||||
last = addr + size - 1;
|
||||
size = PAGE_ALIGN(last) - addr;
|
||||
|
||||
#if 0
|
||||
printk("irongate_ioremap(0x%lx, 0x%lx)\n", addr, size);
|
||||
printk("irongate_ioremap: gart_bus_addr 0x%lx\n", gart_bus_addr);
|
||||
printk("irongate_ioremap: gart_aper_size 0x%lx\n", gart_aper_size);
|
||||
printk("irongate_ioremap: mmio_regs %p\n", mmio_regs);
|
||||
printk("irongate_ioremap: gatt_pages %p\n", gatt_pages);
|
||||
|
||||
for(baddr = addr; baddr <= last; baddr += PAGE_SIZE)
|
||||
{
|
||||
cur_gatt = phys_to_virt(GET_GATT(baddr) & ~1);
|
||||
pte = cur_gatt[GET_GATT_OFF(baddr)] & ~1;
|
||||
printk("irongate_ioremap: cur_gatt %p pte 0x%x\n",
|
||||
cur_gatt, pte);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Map it
|
||||
*/
|
||||
area = get_vm_area(size, VM_IOREMAP);
|
||||
if (!area) return NULL;
|
||||
|
||||
for(baddr = addr, vaddr = (unsigned long)area->addr;
|
||||
baddr <= last;
|
||||
baddr += PAGE_SIZE, vaddr += PAGE_SIZE)
|
||||
{
|
||||
cur_gatt = phys_to_virt(GET_GATT(baddr) & ~1);
|
||||
pte = cur_gatt[GET_GATT_OFF(baddr)] & ~1;
|
||||
|
||||
if (__alpha_remap_area_pages(vaddr,
|
||||
pte, PAGE_SIZE, 0)) {
|
||||
printk("AGP ioremap: FAILED to map...\n");
|
||||
vfree(area->addr);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
flush_tlb_all();
|
||||
|
||||
vaddr = (unsigned long)area->addr + (addr & ~PAGE_MASK);
|
||||
#if 0
|
||||
printk("irongate_ioremap(0x%lx, 0x%lx) returning 0x%lx\n",
|
||||
addr, size, vaddr);
|
||||
#endif
|
||||
return (void __iomem *)vaddr;
|
||||
}
|
||||
|
||||
void
|
||||
irongate_iounmap(volatile void __iomem *xaddr)
|
||||
{
|
||||
unsigned long addr = (unsigned long) xaddr;
|
||||
if (((long)addr >> 41) == -2)
|
||||
return; /* kseg map, nothing to do */
|
||||
if (addr)
|
||||
return vfree((void *)(PAGE_MASK & addr));
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user