This commit is contained in:
Ronald G. Minnich 2000-10-16 23:59:01 +00:00
parent 69e023b385
commit fe28715943
10 changed files with 1298 additions and 0 deletions

View file

@ -0,0 +1,159 @@
CPUFLAGS=-DPM133 -Di386 -Di486 -Di686 -Di586 -D__KERNEL__
# Well, we have old silicon
CPUFLAGS += -DPM133_REV_CD_CE
CPUFLAGS += -DINTEL_BRIDGE_CONFIG
CPUFLAGS += -DINTEL_PPRO_MTRR
CPUFLAGS += -DPM133_NVRAM -DPM133_KEYBOARD
CPUFLAGS += -DNEWPCI
CPUFLAGS += -DSERIAL_CONSOLE
# If you enable FIXED_AND_VARIABLE it never makes it to the kernel!
# you have to only enable variable.
#CPUFLAGS += -DENABLE_FIXED_AND_VARIABLE_MTRRS
CPUFLAGS += -DRAMTEST
# This makes it fail sooner ...
#CPUFLAGS += -DINBUF_COPY
CPUFLAGS += -DCMD_LINE='"ro root=/dev/hda1 console=ttyS0,115200 single "'
TOP=../..
INCLUDES=-I $(TOP)/src/include
CFLAGS=$(INCLUDES) -O2 $(CPUFLAGS) -Ilinux/include -Wall
OBJECTS=crt0.o hardwaremain.o linuxbiosmain.o
OBJECTS += mainboard.o mtrr.o subr.o fill_inbuf.o params.o
OBJECTS += southbridge.o northbridge.o
#OBJECTS += pci.o
OBJECTS += printk.o vsprintf.o
OBJECTS += newpci.o linuxpci.o
OBJECTS += cpuid.o
#OBJECTS += intel_irq_tables.o
OBJECTS += serial_subr.o
OBJECTS += mpspec.o
OBJECTS += microcode.o
OBJECTS += keyboard.o
LINUX=/usr/src/linux-2.4.0/lobos
LINK = ld -T ldscript.ld -o $@ $(OBJECTS)
CC=cc $(CFLAGS)
CCASM=cc -I$(TOP)/chip/intel $(CFLAGS)
all: romimage
floppy: all
mcopy -o romimage a:
# here's the problem: we shouldn't assume we come up with more than
# 64K of FLASH up. SO we need a working linuxbios at the tail, and it will
# enable all flash and then gunzip the linuxbios. As a result,
# we need the vmlinux.bin.gz padded out and then cat the linuxbios.rom
# at then end. We always copy it to /tmp so that a waiting root shell
# can put it on the floppy (see ROOTDOIT)
romimage: linuxbios.rom vmlinux.bin.gz.block
cat vmlinux.bin.gz.block linuxbios.rom > romimage
cp romimage /tmp
linuxbios.rom: linuxbios.strip mkrom
./mkrom -s 64 -f -o linuxbios.rom linuxbios.strip
linuxbios.strip: linuxbios
objcopy -O binary -R .note -R .comment -S linuxbios linuxbios.strip
linuxbios: $(OBJECTS) vmlinux.bin.gz
@rm -f biosobject
$(LINK)
nm -n linuxbios > linuxbios.map
# crt0 actually includes .inc files.
# For self-documenting purposes, we put the FULL PATH of the
# .inc files (relative to $TOP/src) in crt0.S.
# So, for example, earlymtrr.inc is included as cpu/p6/earlymtrr.inc
# To make this work, add the extra -I $(TOP)/src here.
crt0.s: crt0.S
$(CCASM) -I $(TOP)/src -E crt0.S > crt0.s
crt0.o : crt0.s
$(CCASM) -c crt0.s
mkrom: $(TOP)/mkrom/mkrom.c
cc -o mkrom $<
linuxbiosmain.o: $(TOP)/src/lib/linuxbiosmain.c
cc $(CFLAGS) -c $<
mainboard.o: $(TOP)/src/mainboard/via/vt5292/mainboard.c
cc $(CFLAGS) -c $<
fill_inbuf.o: $(TOP)/src/lib/fill_inbuf.c
cc $(CFLAGS) -c $<
params.o: $(TOP)/src/lib/params.c
cc $(CFLAGS) $(LINUXINCLUDE) -c $<
hardwaremain.o: $(TOP)/src/lib/hardwaremain.c
cc $(CFLAGS) -c $<
southbridge.o: $(TOP)/src/southbridge/via/vt82c686/southbridge.c
cc $(CFLAGS) -c $<
northbridge.o: $(TOP)/src/northbridge/via/vt8601/northbridge.c
cc $(CFLAGS) -c $<
pci.o: $(TOP)/src/lib/pci.c
cc $(CFLAGS) -c $<
# not on this machine, not yet.
#intel_irq_tables.o: ../../chip/intel/intel_irq_tables.c
# cc $(CFLAGS) -o $@ -c $<
mtrr.o: $(TOP)/src/cpu/p6/mtrr.c
cc $(CFLAGS) -c $<
subr.o: $(TOP)/src/lib/subr.c
cc $(CFLAGS) -c $<
keyboard.o: $(TOP)/src/pc80/keyboard.c
cc $(CFLAGS) -c $<
cpuid.o: $(TOP)/src/cpu/p5/cpuid.c
cc $(CFLAGS) -c $<
mpspec.o: $(TOP)/src/cpu/p6/mpspec.c
$(CC) $(CFLAGS) -c $<
microcode.o: $(TOP)/src/cpu/p6/microcode.c
$(CC) $(CFLAGS) -c $<
serial_subr.o: $(TOP)/chip/intel/serial_subr.c
cc $(CFLAGS) -c $<
printk.o: $(TOP)/lib/printk.c
cc $(CFLAGS) -c $<
vsprintf.o: $(TOP)/lib/vsprintf.c
cc $(CFLAGS) -c $<
newpci.o: $(TOP)/lib/newpci.c
cc $(CFLAGS) -c $<
linuxpci.o: $(TOP)/lib/linuxpci.c
cc $(CFLAGS) -c $<
vmlinux.bin.gz.block: vmlinux.bin.gz
dd conv=sync bs=448k if=vmlinux.bin.gz of=vmlinux.bin.gz.block
vmlinux.bin.gz: vmlinux.bin
gzip -f -3 vmlinux.bin
vmlinux.bin: $(LINUX)/vmlinux
objcopy -O binary -R .note -R .comment -S $< vmlinux.bin
alltags:
gctags ../inflate/*.c ../../lib/*.c ../../chip/intel/*.c
etags ../inflate/*.c ../../lib/*.c ../../chip/intel/*.c
clean::
rm -f linuxbios.* vmlinux.* *.o mkrom xa? *~ linuxbios romimage crt0.s
rm -f a.out *.s *.l
rm -f TAGS tags

View file

@ -0,0 +1,108 @@
/*
* $ $
*
*/
#include <asm.h>
#include <intel.h>
#include <pciconf.h>
/*
* This is the entry code (the mkrom(8) utility makes a jumpvector
* to this adddess.
*
* When we get here we are in x86 real mode.
*
* %cs = 0xf000 %ip = 0x0000
* %ds = 0x0000 %es = 0x0000
* %dx = 0x0yxx (y = 3 for i386, 5 for pentium, 6 for P6,
* where x is undefined)
* %fl = 0x0002
*/
.text
.code16
#include "intel_start32.S"
/* turn on serial */
#include "VIA_VT82C686A.S"
#include "serial.S"
TTYS0_TX_STRING($ttyS0_test)
/* initialize the RAM */
/* different for each motherboard */
#include "intel_pm133ram.S"
#ifdef RAMTEST
#include "ramtest.S"
#include <cpu/p6/earlymtrr.inc>
mov $0x00000000, %eax
mov $0x0009ffff, %ebx
mov $16, %ecx
CALLSP(ramtest)
#endif
/*
* Copy data into RAM and clear the BSS. Since these segments
* isn't really that big we just copy/clear using bytes, not
* double words.
*/
intel_chip_post_macro(0x11) /* post 11 */
TTYS0_TX_STRING($str_after_ram)
cld /* clear direction flag */
leal EXT(_ldata), %esi
leal EXT(_data), %edi
movl $EXT(_eldata), %ecx
subl %esi, %ecx
jz .Lnodata /* should not happen */
rep
movsb
.Lnodata:
intel_chip_post_macro(0x12) /* post 12 */
TTYS0_TX_STRING($str_after_copy)
/** clear stack */
xorl %edi, %edi
movl $_PDATABASE, %ecx
xorl %eax, %eax
rep
stosb
/** clear bss */
leal EXT(_bss), %edi
movl $EXT(_ebss), %ecx
subl %edi, %ecx
jz .Lnobss
xorl %eax, %eax
rep
stosb
.Lnobss:
/*
* Now we are finished. Memory is up, data is copied and
* bss is cleared. Now we call the ``main´´ routine and
* let it do the rest.
*/
intel_chip_post_macro(0xfe) /* post fe */
TTYS0_TX_STRING($str_pre_main)
/* set new stack */
movl $_PDATABASE, %esp
/* memory is up. Let's do the rest in C -- much easier. */
call EXT(intel_main)
/*NOTREACHED*/
.Lhlt: hlt
jmp .Lhlt
ttyS0_test: .string "\r\n\r\nHello world!!\r\n"
str_after_ram: .string "Ram Initialize?\r\n"
str_after_copy: .string "after copy?\r\n"
str_pre_main: .string "before main\r\n"
newline: .string "\r\n"

View file

@ -0,0 +1,116 @@
/*
* Bootstrap code for the STPC Consumer
* Copyright (c) 1999 by Net Insight AB. All Rights Reserved.
*
* $Id$
*
*/
/* oh, barf. This won't work if all you use is .o's. -- RGM */
/*
* Written by Johan Rydberg, based on work by Daniel Kahlin.
*/
/*
* We use ELF as output format. So that we can
* debug the code in some form.
*/
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
/*
* Memory map:
*
* 0x00000 (4*4096 bytes) : stack
* 0x04000 (4096 bytes) : private data
* 0x05000 : data space
* 0x90000 : kernel stack
* 0xf0000 (64 Kbyte) : EPROM
*/
MEMORY
{
ram (rwx) : ORIGIN = 0x00000000, LENGTH = 128M /* 128 MB memory is
* max for STPC */
rom (rx) : ORIGIN = 0x000f0000, LENGTH = 128K /* 128 K EPROM */
}
_PDATABASE = 0x04000;
_RAMBASE = 0x05000;
_KERNSTK = 0x90000;
/* should be parameterized but is not, yuck! */
/*
_ROMBASE = 0xe0000;
*/
_ROMBASE = 0xf0000;
/*
* Entry point is not really nececary, since the mkrom(8)
* tool creates a entry point that jumps to $0xc000:0x0000.
*/
/* baloney, but ... RGM*/
ENTRY(_start)
SECTIONS {
/*
* First we place the code and read only data (typically const declared).
* This get placed in rom.
*/
.text _ROMBASE : {
_text = .;
*(.text);
*(.rodata);
_etext = .;
}
_pdata = .;
/*
.pdata _PDATABASE : AT ( LOADADDR(.text) + SIZEOF(.text) +
SIZEOF(.rodata)) {
*/
.pdata _PDATABASE : AT ( _etext ) {
*(.pdata);
}
_epdata = LOADADDR(.pdata) + SIZEOF(.pdata);
/*
* After the code we place initialized data (typically initialized
* global variables). This gets copied into ram by startup code.
* __data_start and __data_end shows where in ram this should be placed,
* whereas __data_loadstart and __data_loadend shows where in rom to
* copy from.
*/
.data _RAMBASE : AT ( LOADADDR(.pdata) + SIZEOF(.pdata) ) {
_data = .;
*(.data)
*(.sdata)
*(.sdata2)
*(.got)
_edata = .;
}
_ldata = LOADADDR(.data);
_eldata = LOADADDR(.data) + SIZEOF(.data);
/*
* bss does not contain data, it is just a space that should be zero
* initialized on startup. (typically uninitialized global variables)
* crt0.S fills between __bss_start and __bss_end with zeroes.
*/
.bss ( ADDR(.data) + SIZEOF(.data) ) : {
_bss = .;
*(.bss)
*(.sbss)
*(COMMON)
_ebss = .;
_heap = .;
}
}
/*
* This provides the start and end address for the whole image
*/
_image = LOADADDR(.text);
_eimage = LOADADDR(.data) + SIZEOF(.data);
/* EOF */

284
src/lib/subr.c Normal file
View file

@ -0,0 +1,284 @@
/*
* Bootstrap code for the INTEL
* $Id$
*
*/
#ifndef lint
static char rcsid[] = "$Id$";
#endif
#include <cpu/p5/io.h>
#include <cpu/p5/macros.h>
#include <printk.h>
#include <pci.h>
#include <subr.h>
#ifdef SERIAL_CONSOLE
#include <serial_subr.h>
#endif
// kludgy but this is only used here ...
static char *vidmem; /* The video buffer, should be replaced by symbol in ldscript.ld */
static int line_number;
#define LINES 25 /* Number of lines and */
#define COLS 80 /* columns on display */
#define VIDBUFFER 0x20000;
#ifdef VIDEO_SCROLLING
static void scroll()
{
int i;
memcpy(vidmem, vidmem + COLS * 2, (LINES - 1) * COLS * 2);
for (i = (LINES - 1) * COLS * 2; i < LINES * COLS * 2; i += 2)
vidmem[i] = ' ';
}
#endif
// initialize the display
void displayinit(void)
{
line_number = 0;
vidmem = (char *) VIDBUFFER;
memset(vidmem, 0, 64 * 1024);
#ifdef SERIAL_CONSOLE
#endif
}
void display(char msg[])
{
int i = 0;
#ifdef SERIAL_CONSOLE
ttys0_tx_string(msg);
#endif
#ifdef VIDEO_BIOS_WORKS
while (msg[i] != 0) {
vidmem[(line_number + 1) * COLS * 2 + i * 2] = msg[i];
vidmem[(line_number + 1) * COLS * 2 + i * 2 + 1] = 0x07;
i++;
}
(line_number >= (LINES - 1)) ? scroll() : line_number++;
#else /* VIDEO_BIOS_WORKS */
while (msg[i] != 0)
vidmem[(line_number++)] = msg[i++];
/* vidmem[(line_number++)]= 0; */
#endif /* VIDEO_BIOS_WORKS */
}
void printnibl(unsigned long nibl)
{
static char c[2];
nibl &= 0xf;
c[0] = nibl;
c[1] = 0;
if ((nibl >= 0) && (nibl <= 9))
c[0] += '0';
else
c[0] += ('A' - 10);
display(c);
}
void printchar(unsigned char x)
{
int i;
for (i = 4; i >= 0; i -= 4)
printnibl(x >> i);
display(" ");
}
void printint(unsigned long x)
{
int i;
display(" 0x");
for (i = 28; i >= 0; i -= 4)
printnibl(x >> i);
display(" ");
}
void error(char errmsg[])
{
display(errmsg);
intel_post(0xee);
while (1); /* Halt */
}
/*
* Write POST information
*/
void intel_post(char value)
{
outb(value, 0x80);
}
/*
* Write the special configuration registers on the INTEL
*/
void intel_conf_writeb(unsigned long port, unsigned char value)
{
unsigned char whichbyte = port & 3;
port &= (~3);
outl(port, PCI_CONF_REG_INDEX);
outb(value, PCI_CONF_REG_DATA + whichbyte);
}
/*
* Read the special configuration registers on the INTEL
*/
unsigned char intel_conf_readb(unsigned long port)
{
unsigned char whichbyte = port & 3;
port &= (~3);
outl(port, PCI_CONF_REG_INDEX);
return inb(PCI_CONF_REG_DATA + whichbyte);
}
void intel_cache_on(unsigned long base, unsigned long totalram)
{
intel_post(0x60);
/* we need an #ifdef i586 here at some point ... */
__asm__ __volatile__("mov %cr0, %eax\n\t"
"and $0x9fffffff,%eax\n\t"
"mov %eax, %cr0\n\t");
/* turns out cache isn't really on until you set MTRR registers on
* 686 and later.
* NOTHING FANCY. Linux does a much better job anyway.
* so absolute minimum needed to get it going.
*/
/* OK, linux it turns out does nothing. We have to do it ... */
#ifdef i686
// totalram here is in linux sizing, i.e. units of KB.
// set_mtrr is responsible for getting it into the right units!
intel_set_mtrr(base, totalram);
#endif
intel_post(0x62);
}
void intel_interrupts_on()
{
/* this is so interrupts work. This is very limited scope --
* linux will do better later, we hope ...
*/
/* this is the first way we learned to do it. It fails on real SMP
* stuff. So we have to do things differently ...
* see the Intel mp1.4 spec, page A-3
*/
#ifdef SMP
unsigned long reg, *regp;
#define SVR 0xfee000f0
#define LVT1 0xfee00350
#define LVT2 0xfee00360
#define APIC_ENABLED 0x100
regp = (unsigned long *) SVR;
reg = *regp;
reg &= (~0xf0);
reg |= APIC_ENABLED;
*regp = reg;
regp = (unsigned long *) LVT1;
reg = *regp;
reg &= 0xfffe00ff;
reg |= 0x5700;
*regp = reg;
regp = (unsigned long *) LVT2;
reg = *regp;
reg &= 0xfffe00ff;
reg |= 0x5400;
*regp = reg;
#else
unsigned long low, high;
rdmsr(0x1b, low, high);
low &= ~0x800;
wrmsr(0x1b, low, high);
#endif
}
#ifdef NEWPCI
/* These functions should be chip-set independent -tds */
void intel_zero_irq_settings(void)
{
struct pci_dev *pcidev;
// unsigned char irq;
unsigned char line;
pcidev = pci_devices;
while (pcidev) {
pci_read_config_byte(pcidev, 0x3d, &line);
if (line) {
pci_write_config_byte(pcidev, 0x3c, 0);
}
pcidev = pcidev->next;
}
}
void intel_check_irq_routing_table(void)
{
#if (defined(L440BX) || defined (SIS630))
const u8 *addr;
const struct irq_routing_table *rt;
int i;
u8 sum;
rt = &intel_irq_routing_table;
addr = (u8 *)rt;
sum = 0;
for (i=0; i<rt->size; i++)
sum += addr[i];
printk(KERN_DEBUG "%s:%6d:%s() - "
"irq_routing_table located at: 0x%08x\n",
__FILE__, __LINE__, __FUNCTION__, addr);
sum = (unsigned char)(rt->checksum-sum);
if (sum != rt->checksum) {
printk(KERN_WARNING "%s:%6d:%s() - "
"checksum is: 0x%02x but should be: 0x%02x\n",
__FILE__, __LINE__, __FUNCTION__, rt->checksum, sum);
}
if (rt->signature != PIRQ_SIGNATURE || rt->version != PIRQ_VERSION ||
rt->size % 16 || rt->size < sizeof(struct irq_routing_table)) {
printk(KERN_WARNING "%s:%6d:%s() - "
"Interrupt Routing Table not valid\n",
__FILE__, __LINE__, __FUNCTION__);
return;
}
sum = 0;
for (i=0; i<rt->size; i++)
sum += addr[i];
if (sum) {
printk(KERN_WARNING "%s:%6d:%s() - "
"checksum error in irq routing table\n",
__FILE__, __LINE__, __FUNCTION__);
}
#endif /* #if defined(L440BX) */
}
#define RTABLE_DEST 0xf0000
void intel_copy_irq_routing_table(void)
{
#ifdef SIS630
memcpy((char *) RTABLE_DEST, &intel_irq_routing_table, intel_irq_routing_table.size);
#endif
}
#endif /* NEWPCI */

View file

@ -0,0 +1,6 @@
void
mainboard_fixup()
{
void southbridge_fixup(void);
southbridge_fixup();
}

View file

@ -0,0 +1,4 @@
unsigned long sizeram()
{
return 0;
}

View file

@ -0,0 +1,138 @@
/*
* Bootstrap code for the INTEL
* $Id$
*
*/
#ifndef lint
static char rcsid[] =
"$Id$";
#endif
#include <printk.h>
#include <intel_conf.h>
#include <intel_subr.h>
#include <lbpci.h>
#include <sis630.h>
/* these functions query the hardware to figure out how much ram is in
* the machine. They then place that information in the parameter block.
* This is kind of schizophrenic, but we do it this way because the
* functions that actually set the registers are kind of hairy, and
* we're not sure they can carry the full burden of also passing on
* the size information to the rest of the bootstrap. Besides, querying
* hardware for ram sizes is trivial.
*/
/* table for calculate the DRAM size, the unit is Mega Bytes */
const static ramsizes[16] =
{
8, 32, 32, 64, 16, 64, 64, 128,
32, 128, 128, 256, 16, 256, 256, 512
};
#define SIS630_BANKENABLE 0x63
#define SIS630_BANK0 0x60
#define SIS630_BANK1 0x61
#define SIS630_BANK2 0x62
#define SIS630_DIMM_LOCATION_FOR_SMA 0x65
unsigned long sizeram()
{
struct pci_dev *pcidev;
unsigned int dimm_slot, dimm_reg, sides;
unsigned long total_size;
u8 dram_status, dimm_status;
u8 sma_enable, sma_size, sma_size_bits, sma_location;
if ((pcidev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630, NULL)) == NULL)
return 0;
pci_read_config_byte(pcidev, SIS630_BANKENABLE, &dram_status);
dimm_status = dram_status & 0x7;
sma_enable = dram_status & 0x80;
pci_read_config_byte(pcidev, SIS630_DIMM_LOCATION_FOR_SMA, &sma_location);
sma_location &= 0x03;
/* compute Shared Menory Area (SMA) size in Mega Bytes */
sma_size_bits = (dram_status >> 4) & 0x7;
if (sma_size_bits > 5)
// this is invalid!
sma_size = 0;
else {
sma_size = (2 << sma_size_bits);
}
for (dimm_slot = 0, total_size = 0, dimm_reg = SIS630_BANK0;
dimm_reg <= SIS630_BANK2; dimm_slot++, dimm_reg++) {
u8 regval;
if ((dimm_status & (1 << dimm_slot)) == 0)
/* this DIMM slot does not have SDRAM installed */
continue;
pci_read_config_byte(pcidev, dimm_reg, &regval);
/* is this DIMM single or double sided ?? */
if (regval & 0x20)
sides = 2;
else
sides = 1;
/* low-order 4 bits are a ram size */
total_size += (ramsizes[regval & 0xf] * sides);
}
/* the total memory visible to the system is physical memory installed minus the
amount used by VGA (sma_size) */
total_size -= sma_size;
/* return the memory size in KB */
total_size *= 1024;
return total_size;
}
#ifdef HAVE_FRAMEBUFFER
void intel_framebuffer_on()
{
unsigned long devfn = PCI_DEVFN(0, 0);
unsigned int bus = 0;
u8 dramstatus;
u32 command;
#if 0
/* No, you can not do this here, but WHY ??? */
/* TODO:
1. clean up the memory footprint to make this work.
2. make the share size configurable.
3. use the information found from DRAM sizing to select whic DIMM is to be shared */
pcibios_read_config_byte(0, devfn, SIS630_BANKENABLE, &dramstatus);
dramstatus |= 0x90;
pcibios_write_config_byte(0, devfn, SIS630_BANKENABLE, dramstatus);
#endif
/* enable legacy VGA register (0x3?4, 0x3?5), not actually needed */
devfn = PCI_DEVFN(2, 0);
pcibios_read_config_dword(0, devfn, 0x3e, &command);
command |= 0x08;
pcibios_write_config_dword(0, devfn, 0x3e, command);
}
#endif /* HAVE_FRAMEBUFFER */
// mainboard fixup.
void mainboard_fixup()
{
}
#define RTABLE_DEST 0xf0000
void copy_irq_routing_table(void)
{
#ifdef SIS630
memcpy((char *) RTABLE_DEST, &intel_irq_routing_table, intel_irq_routing_table.size);
#endif
}

View file

@ -0,0 +1,352 @@
/*
This software and ancillary information (herein called SOFTWARE )
called LinuxBIOS is made available under the terms described
here. The SOFTWARE has been approved for release with associated
LA-CC Number 00-34 . Unless otherwise indicated, this SOFTWARE has
been authored by an employee or employees of the University of
California, operator of the Los Alamos National Laboratory under
Contract No. W-7405-ENG-36 with the U.S. Department of Energy. The
U.S. Government has rights to use, reproduce, and distribute this
SOFTWARE. The public may copy, distribute, prepare derivative works
and publicly display this SOFTWARE without charge, provided that this
Notice and any statement of authorship are reproduced on all copies.
Neither the Government nor the University makes any warranty, express
or implied, or assumes any liability or responsibility for the use of
this SOFTWARE. If SOFTWARE is modified to produce derivative works,
such modified SOFTWARE should be clearly marked, so as not to confuse
it with the version available from LANL.
*/
/* Copyright 2000, Ron Minnich, Advanced Computing Lab, LANL
* rminnich@lanl.gov
*/
/* this set of steps is REQUIRED before you do anything to DRAM */
/* Reg name Power-on dflt*/
CS_WRITE(SIS_PCMC_REG04,$0x07)
CS_WRITE(SIS_PCMC_REG05,$0x00)
CS_WRITE(SIS_PCMC_REG06,$0x00)
CS_WRITE(SIS_PCMC_REG07,$0x02)
CS_WRITE(SIS_PCMC_REG0C,$0x00)
CS_WRITE(SIS_PCMC_REG0D,$0x20)
CS_WRITE(SIS_PCMC_REG0E,$0x00)
CS_WRITE(SIS_PCMC_REG0F,$0x00)
CS_WRITE(SIS_PCMC_REG50,$0x09C)
CS_WRITE(SIS_PCMC_REG51,$0x000)
CS_WRITE(SIS_PCMC_REG52,$0x0C5)
CS_WRITE(SIS_PCMC_REG53,$0x000)
CS_WRITE(SIS_PCMC_REG54,$0x000) /** 00h (66/100), 08h (133)*/
CS_WRITE(SIS_PCMC_REG55,$0x029) /** 29h (100), 1Dh (133)*/
CS_WRITE(SIS_PCMC_REG56,$0x080) /** 00h (66), 80h (100/133) */
/*CS_WRITE(SIS_PCMC_REG57,$0x000) */ /* 000h (100||VCM), 001h (133)*/
/* temporary change ... set it to 1, since the bst1b does that too */
#ifndef USE_DOC_MIL
CS_WRITE(SIS_PCMC_REG57,$0x001) /** 000h (100||VCM), 001h (133)*/
#endif
CS_WRITE(SIS_PCMC_REG58,$0x000)
CS_WRITE(SIS_PCMC_REG59,$0x035)
CS_WRITE(SIS_PCMC_REG5A,$0x051)
CS_WRITE(SIS_PCMC_REG5B,$0x000)
#ifndef USE_DOC_MIL
CS_WRITE(SIS_PCMC_REG63,$0x000)
#endif
/* This is needed for SiSfb. Shared memory is in dimm 0. */
CS_WRITE(SIS_PCMC_REG65,$0x000)
CS_WRITE(SIS_PCMC_REG6A,$0x0C0)
CS_WRITE(SIS_PCMC_REG6B,$0x001) /** 000h (66/133), 001h (100)*/
CS_WRITE(SIS_PCMC_REG6C,$0x020) /** 02Eh (66), 020h (100), 02Ch (133)*/
CS_WRITE(SIS_PCMC_REG70,$0x000) /* Shadow register*/
CS_WRITE(SIS_PCMC_REG71,$0x080) /* Shadow register*/
CS_WRITE(SIS_PCMC_REG72,$0x000) /* Shadow register*/
CS_WRITE(SIS_PCMC_REG73,$0x000) /* Shadow register*/
#ifdef NOTUSED
CS_WRITE(SIS_PCMC_REG74,$0x000) /* Shadow register*/
CS_WRITE(SIS_PCMC_REG75,$0x010) /* Shadow register*/
#endif
CS_WRITE(SIS_PCMC_REG80,$0x021)
CS_WRITE(SIS_PCMC_REG81,$0x0FF)
CS_WRITE(SIS_PCMC_REG82,$0x07F)
CS_WRITE(SIS_PCMC_REG83,$0x01E)
CS_WRITE(SIS_PCMC_REG84,$0x060)
CS_WRITE(SIS_PCMC_REG85,$0x000)
CS_WRITE(SIS_PCMC_REG86,$0x003)
CS_WRITE(SIS_PCMC_REG87,$0x040)
CS_WRITE(SIS_PCMC_REG88,$0x000)
CS_WRITE(SIS_PCMC_REG89,$0x008)
#ifndef USE_DOC_MIL
CS_WRITE(SIS_PCMC_REG8C,$0x066)
CS_WRITE(SIS_PCMC_REG8D,$0x066)
CS_WRITE(SIS_PCMC_REG8E,$0x003) /** default=03h for 100/133, recommend=00h*/
CS_WRITE(SIS_PCMC_REG8F,$0x055)
#endif
CS_WRITE(SIS_PCMC_REG90,$0x000)
CS_WRITE(SIS_PCMC_REG91,$0x000)
CS_WRITE(SIS_PCMC_REG92,$0x000)
CS_WRITE(SIS_PCMC_REG93,$0x000)
CS_WRITE(SIS_PCMC_REG94,$0x040)
CS_WRITE(SIS_PCMC_REG97,$0x001)
CS_WRITE(SIS_PCMC_REG98,$0x000)
CS_WRITE(SIS_PCMC_REG9C,$0x002)
CS_WRITE(SIS_PCMC_REGA0,$0x000)
CS_WRITE(SIS_PCMC_REGA1,$0x000)
CS_WRITE(SIS_PCMC_REGA2,$0x003)
CS_WRITE(SIS_PCMC_REGA3,$0x001)
CS_WRITE(SIS_PCMC_REGA5,$0x000)
CS_WRITE(SIS_PCMC_REGA6,$0x000)
CS_WRITE(SIS_PCMC_REGA7,$0x000)
CS_WRITE(SIS_PCMC_REGA8,$0x000)
CS_WRITE(SIS_PCMC_REGA9,$0x000)
CS_WRITE(SIS_PCMC_REGAA,$0x000)
CS_WRITE(SIS_PCMC_REGAB,$0x000)
CS_WRITE(SIS_PCMC_REGAC,$0x000)
CS_WRITE(SIS_PCMC_REGC8,$0x004)
CS_WRITE(SIS_PCMC_REGC9,$0x000)
CS_WRITE(SIS_PCMC_REGCA,$0x000)
CS_WRITE(SIS_PCMC_REGCB,$0x000)
#ifdef SIS630S
CS_WRITE(SIS_PCMC_REG50, $0x7e)
CS_WRITE(SIS_PCMC_REG51, $0x13)
CS_WRITE(SIS_PCMC_REG53, $0x0b)
CS_WRITE(SIS_PCMC_REG55, $0x05)
CS_WRITE(SIS_PCMC_REG59, $0x05)
CS_WRITE(SIS_PCMC_REG6A, $0xc6)
CS_WRITE(SIS_PCMC_REG6B, $0x00)
CS_WRITE(SIS_PCMC_REG6C, $0x2f)
CS_WRITE(SIS_PCMC_REG71, $0x00)
CS_WRITE(SIS_PCMC_REG80, $0x23)
CS_WRITE(SIS_PCMC_REG83, $0x1f)
CS_WRITE(SIS_PCMC_REG84, $0xf0)
CS_WRITE(SIS_PCMC_REG86, $0x01)
CS_WRITE(SIS_PCMC_REG9C, $0x80)
#endif /* SIS630S */
#ifndef USE_DOC_MIL
/* this sequence gets the SiS 630 ram up and running, we hope. */
/* for now, let's stick to bank 0, and jam the size to 64M, 2 side (128M) */
/* the sizing is not hard, but we need an opinion from SiS on whether
* they would prefer to write it. They can do this better than we can.
*/
/* post 0x01 to 0x80 port for debugging */
intel_chip_post_macro(0x01)
movb $0xBF, %al /* Bit 7 controls NMI*/
outb %al, $0x70 /* Disable NMI interrupts */
movw $0x0, %si
movw $0x0, %di
OtherBank:
/* registers we use: eax, cl, and dx */
/* parameters: at some point, cl will be the bank # */
/* returns: none */
/* note: the macros trash cl, eax and dx. Nothing else gets
* hurt. So to subroutine-ify them you can call with things in
* ebx and ch. So you could have the bank in ch and return in ebx
* For now, this is in-line code until we think we know what we're
* doing.
*/
/* for now, we don't try to autosize
* We know the size -- 64M X 2
*/
/* turn on dimm 0 */
movw %si, %cx
movw $0x1, %ax
shlw %cl, %ax
movw %ax, %bx
CS_WRITE(SIS_PCMC_REG63, %bl)
movw %cx, %si
/* make it the max size configuration */
movw %si, %bx
addw SIS_PCMC_REG60, %si
CS_WRITE(%si, DRAM_MAXSIZE)
movw %bx, %si
/* disable refresh */
REGBIC(SIS_PCMC_REG52, REFRESH_ENABLE)
/* mode register set */
REGBIS(SIS_PCMC_REG57, MRS)
/* precharge */
REGBIS(SIS_PCMC_REG57, PRECHARGE)
/* refresh command */
/* the question is, will these cause trouble back-to-back */
/* not really, because this is a macro, so we have lots of insns
* between sets
* macros sometimes win
* 16 refresh commands
*/
REGBIS(SIS_PCMC_REG57, REFRESH)
REGBIS(SIS_PCMC_REG57, REFRESH)
REGBIS(SIS_PCMC_REG57, REFRESH)
REGBIS(SIS_PCMC_REG57, REFRESH)
REGBIS(SIS_PCMC_REG57, REFRESH)
REGBIS(SIS_PCMC_REG57, REFRESH)
REGBIS(SIS_PCMC_REG57, REFRESH)
REGBIS(SIS_PCMC_REG57, REFRESH)
REGBIS(SIS_PCMC_REG57, REFRESH)
REGBIS(SIS_PCMC_REG57, REFRESH)
REGBIS(SIS_PCMC_REG57, REFRESH)
REGBIS(SIS_PCMC_REG57, REFRESH)
REGBIS(SIS_PCMC_REG57, REFRESH)
REGBIS(SIS_PCMC_REG57, REFRESH)
REGBIS(SIS_PCMC_REG57, REFRESH)
REGBIS(SIS_PCMC_REG57, REFRESH)
/* now turn refresh back on */
REGBIS(SIS_PCMC_REG52, REFRESH_ENABLE)
/* now write some data to the sdram. This is required by the
* pc100 spec. The specific patterns vary by mainboard ...
* the jmp's are cheap delays, back-to-back writes at this point
* may be a problem.
*/
movl MPATTERN0, %eax
movl %eax, 0
movl SDPATTERN1, %eax
jmp 1f
1: movl %eax, 0x8
jmp 1f
1: movl %eax, 0x8
jmp 1f
1: movl %eax, 0x8
jmp 1f
1: movl %eax, 0x8
jmp 1f
1: movl %eax, 0x8
jmp 1f
1: movl %eax, 0x8
jmp 1f
1: movl %eax, 0x8
jmp 1f
1: movl %eax, 0x8
jmp 1f
1:
movl MPATTERN0, %eax
cmpl 0, %eax
jmp 1f
1: jne noram
movl MPATTERN1, %eax
movl %eax, 0x40000000-0x10
movl SDPATTERN1, %eax
movl %eax, 0x40000000-0x8
movl MPATTERN1, %eax
cmpl %eax, 0x40000000-0x10
jne 1f
/* save drame type of this slot
* in bit 15-31 of %ecx */
movb $0x20, %cl
shll $0x10, %ecx
jmp doubleside
1:
mov $0x00, %cl
shll $0x10,%ecx
doubleside:
movw %di, %bx
movw $0x1, %di
movw %si, %cx
shlw %cl, %di
orw %bx, %di
/* FIXME: why do we have this two ?? */
movl SDPATTERN1, %eax
cmpl 8, %eax
CALLSP(sizeram630)
shrl $0x10, %ecx
movb %al, %ch
orb %cl, %ch
movw %si, %bx
addw SIS_PCMC_REG60, %si
CS_WRITE(%si, %ch)
movw %bx, %si
incw %si
/* this appears to be trouble, so we'll skip it for now. RGM */
#if 1
cmpw $0x03, %si
je done
jmp OtherBank
#else
jmp done
#endif
#define CMPBRANCH(address, target) cmp %eax, address; jne target
#define CMPEQRETURN(address, value) cmp %eax, address; jne 1f; mov value, %eax; RETSP; 1:
#define CMPNERETURN(address, value) cmp %eax, address; je 1f; mov value, %eax; RETSP; 1:
#define RETURN(value) mov value, %eax; RETSP
sizeram630:
movl MPATTERN0, %eax
movl %eax, 0
CMPBRANCH(0x1000, SMA2)
CMPBRANCH(0x800000, SMA_1_1x_0910)
CMPEQRETURN(0x4000000, SMA_1_11_08)
RETURN(SMA_1_13_08)
SMA_1_1x_0910:
CMPBRANCH(0x1000000, SMA_1_xx_10)
CMPEQRETURN(0x4000000, SMA_1_11_09)
RETURN(SMA_1_13_09)
SMA_1_xx_10:
CMPNERETURN(0x8000000, SMA_1_13_11)
CMPEQRETURN(0x4000000, SMA_1_11_10)
RETURN(SMA_1_13_10)
SMA2: CMPBRANCH(0x800000, SMA_2_xx_091011)
CMPNERETURN(0x10000000, SMA_2_13_08)
CMPEQRETURN(0x4000000, SMA_2_11_08)
RETURN(SMA_2_12_08)
SMA_2_xx_091011:
CMPBRANCH(0x1000000, SMA_2_xx_1011)
CMPEQRETURN(0x10000000, SMA_2_12_09)
RETURN(SMA_2_13_09)
SMA_2_xx_1011:
CMPBRANCH(0x8000000, SMA_2_xx_11)
CMPEQRETURN(0x10000000, SMA_2_12_10)
RETURN(SMA_2_13_10)
SMA_2_xx_11:
CMPEQRETURN(0x10000000, SMA_2_12_11)
movl MPATTERN1, %eax
movl %eax, 0x20000000
CMPEQRETURN(0x20000000, SMA_2_13_11)
noram:
incw %si
cmpw $0x03,%si
je done
jmp OtherBank
done:
movl $0x80000060, %eax
movw $0x0cf8, %dx
outl %eax, %dx
movw $0x0cff, %dx
movw %di, %ax
outb %al, %dx
#ifdef SIS630
#ifdef SIS_FIXUP_FOR_FB
// make shared memory between the agp and the processor
movl $0x80000060, %eax
movw $0x0cf8, %dx
outl %eax, %dx
movw $0x0cff, %dx
inb %dx, %al
orb $0x90, %al
outb %al, %dx
#endif /* SIS_FIXUP_FOR_FB */
#endif /* SIS630 */
#endif /* USE_DOC_MIL */

View file

@ -0,0 +1,81 @@
/*
* Bootstrap code for the INTEL
* $Id$
*
*/
#ifndef lint
static char rcsid[] =
"$Id$";
#endif
#include <printk.h>
#include <intel_conf.h>
#include <intel_subr.h>
#include <lbpci.h>
#include <sis630.h>
void keyboard_on()
{
u8 regval;
struct pci_dev *pcidev;
/* turn on sis630 keyboard/mouse controller */
pcidev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, (void *)NULL);
if (pcidev != NULL) {
/* Register 0x47, Keyboard Controller */
pci_read_config_byte(pcidev, 0x47, &regval);
/* enable both integrated keyboard and PS/2 mouse controller */
regval |= 0x0c;
pci_write_config_byte(pcidev, 0x47, regval);
}
pc_keyboard_init();
}
void nvram_on()
{
struct pci_dev *pcidev;
/* turn on sis630 nvram. */
pcidev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, (void *)NULL);
if (pcidev != NULL) {
/* Enable FFF80000 to FFFFFFFF decode */
pci_write_config_byte(pcidev, 0x40, 0x33);
/* Flash can be flashed */
pci_write_config_byte(pcidev, 0x45, 0x40);
}
/* turn off nvram shadow in 0xc0000 ~ 0xfffff */
pcidev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630, (void *)NULL);
if (pcidev != NULL) {
/* read cycle goes to System Memory */
pci_write_config_word(pcidev, 0x70, 0x1fff);
/* write cycle goest to System Memory */
pci_write_config_word(pcidev, 0x72, 0x1fff);
}
}
/* turn on the floppy. On some chipsets you have to do this. */
#ifdef MUST_ENABLE_FLOPPY
void enable_floppy()
{
/* unlock it XXX make this a subr at some point */
outb(0x87, 0x2e);
outb(0x01, 0x2e);
outb(0x55, 0x2e);
outb(0x55, 0x2e);
/* now set the LDN to floppy LDN */
outb(0x7, 0x2e); /* pick reg. 7 */
outb(0x0, 0x2f); /* LDN 0 to reg. 7 */
/* now select register 0x30, and set bit 1 in that register */
outb(0x30, 0x2e);
outb(0x1, 0x2f);
/* all done. */
outb(1, 0x2e);
}
#endif /* MUST_ENABLE_FLOPPY */

50
src/pc80/keyboard.c Normal file
View file

@ -0,0 +1,50 @@
#include <cpu/p5/io.h>
#include <subr.h>
/* much better keyboard init courtesy ollie@sis.com.tw
TODO: Typematic Setting, the keyboard is too slow for me */
void pc_keyboard_init()
{
volatile unsigned char regval;
/* send cmd = 0xAA, self test 8042 */
outb(0xaa, 0x64);
/* empty inut bufferm or any other command/data will be lost */
while ((inb(0x64) & 0x02))
intel_post(0);
/* empty output buffer or any other command/data will be lost */
while ((inb(0x64) & 0x01) == 0)
intel_post(1);
/* read self-test result, 0x55 should be returned form 0x60 */
if ((regval = inb(0x60) != 0x55))
return;
/* enable keyboard interface */
outb(0x60, 0x64);
while ((inb(0x64) & 0x02))
intel_post(2);
/* send cmd: enable IRQ 1 */
outb(0x61, 0x60);
while ((inb(0x64) & 0x02))
intel_post(3);
/* reset kerboard and self test (keyboard side) */
outb(0xff, 0x60);
/* empty inut bufferm or any other command/data will be lost */
while ((inb(0x64) & 0x02))
intel_post(4);
/* empty output buffer or any other command/data will be lost */
while ((inb(0x64) & 0x01) == 0)
intel_post(5);
if ((regval = inb(0x60) != 0xfa))
return;
while ((inb(0x64) & 0x01) == 0)
intel_post(6);
if ((regval = inb(0x60) != 0xaa))
return;
}