Start of merge from work on the AMD760MP platform.
This is the safe part just additions to files, and comment changes
This commit is contained in:
parent
ad44ad6bc8
commit
228148aa23
63 changed files with 6591 additions and 3 deletions
30
src/arch/i386/include/arch/asm.h
Normal file
30
src/arch/i386/include/arch/asm.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef ASM_H
|
||||
#define ASM_H
|
||||
|
||||
#define ASSEMBLER
|
||||
|
||||
/*
|
||||
* Bootstrap code for the STPC Consumer
|
||||
* Copyright (c) 1999 by Net Insight AB. All Rights Reserved.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#define I386_ALIGN_TEXT 0
|
||||
#define I386_ALIGN_DATA 0
|
||||
|
||||
/*
|
||||
* XXX
|
||||
*/
|
||||
#ifdef __ELF__
|
||||
#define EXT(x) x
|
||||
#else
|
||||
#define EXT(x) _ ## x
|
||||
#endif
|
||||
|
||||
#define STATIC(x) .align I386_ALIGN_TEXT; EXT(x):
|
||||
#define GLOBAL(x) .globl EXT(x); STATIC(x)
|
||||
#define ENTRY(x) .text; GLOBAL(x)
|
||||
|
||||
#endif /* ASM_H */
|
||||
7
src/arch/i386/include/arch/i386_subr.h
Normal file
7
src/arch/i386/include/arch/i386_subr.h
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef I386_SUBR_H
|
||||
#define I386_SUBR_H
|
||||
|
||||
void cache_on(unsigned long totalram);
|
||||
void interrupts_on(void);
|
||||
|
||||
#endif /* I386_SUBR_H */
|
||||
369
src/arch/i386/include/arch/intel.h
Normal file
369
src/arch/i386/include/arch/intel.h
Normal file
|
|
@ -0,0 +1,369 @@
|
|||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ROM_INTEL_H
|
||||
#define ROM_INTEL_H
|
||||
|
||||
/*
|
||||
* Bootstrap code for the Intel
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Config registers.
|
||||
*/
|
||||
/* yeah, yeah, I know these are macros, which is bad. Don't forget:
|
||||
* we have almost no assembly, so I am not worrying just yet about this.
|
||||
* we'll fix it someday if we care. My guess is we won't.
|
||||
*/
|
||||
|
||||
/* well we want functions. But first we want to see it work at all. */
|
||||
#undef FUNCTIONS
|
||||
#ifndef FUNCTIONS
|
||||
|
||||
|
||||
#define RET_LABEL(label) \
|
||||
jmp label##_done
|
||||
|
||||
#define CALL_LABEL(label) \
|
||||
jmp label ;\
|
||||
label##_done:
|
||||
|
||||
#define CALLSP(func) \
|
||||
lea 0f, %esp ; \
|
||||
jmp func ; \
|
||||
0:
|
||||
|
||||
#define RETSP \
|
||||
jmp *%esp
|
||||
|
||||
|
||||
#define DELAY(x) mov x, %ecx ;\
|
||||
1: loop 1b ;\
|
||||
|
||||
|
||||
/*
|
||||
* Macro: PCI_WRITE_CONFIG_BYTE
|
||||
* Arguments: %eax address to write to (includes bus, device, function, &offset)
|
||||
* %dl byte to write
|
||||
*
|
||||
* Results: none
|
||||
*
|
||||
* Trashed: %eax, %edx
|
||||
* Effects: writes a single byte to pci config space
|
||||
*
|
||||
* Notes: This routine is optimized for minimal register usage.
|
||||
* And the tricks it does cannot scale beyond writing a single byte.
|
||||
*
|
||||
* What it does is almost simple.
|
||||
* It preserves %eax (baring special bits) until it is written
|
||||
* out to the appropriate port. And hides the data byte
|
||||
* in the high half of edx.
|
||||
*
|
||||
* In %edx[3] it stores the byte to write.
|
||||
* In %edx[2] it stores the lower three bits of the address.
|
||||
*/
|
||||
|
||||
|
||||
#define PCI_WRITE_CONFIG_BYTE \
|
||||
shll $8, %edx ; \
|
||||
movb %al, %dl ; \
|
||||
andb $0x3, %dl ; \
|
||||
shll $16, %edx ; \
|
||||
\
|
||||
orl $0x80000000, %eax ; \
|
||||
andl $0xfffffffc, %eax ; \
|
||||
movw $0xcf8, %dx ; \
|
||||
outl %eax, %dx ; \
|
||||
\
|
||||
shrl $16, %edx ; \
|
||||
movb %dh, %al ; \
|
||||
movb $0, %dh ; \
|
||||
addl $0xcfc, %edx ; \
|
||||
outb %al, %dx
|
||||
|
||||
|
||||
/*
|
||||
* Macro: PCI_WRITE_CONFIG_WORD
|
||||
* Arguments: %eax address to write to (includes bus, device, function, &offset)
|
||||
* %ecx word to write
|
||||
*
|
||||
* Results: none
|
||||
*
|
||||
* Trashed: %eax, %edx
|
||||
* Preserved: %ecx
|
||||
* Effects: writes a single byte to pci config space
|
||||
*
|
||||
* Notes: This routine is optimized for minimal register usage.
|
||||
*
|
||||
* What it does is almost simple.
|
||||
* It preserves %eax (baring special bits) until it is written
|
||||
* out to the appropriate port. And hides the least significant
|
||||
* bits of the address in the high half of edx.
|
||||
*
|
||||
* In %edx[2] it stores the lower three bits of the address.
|
||||
*/
|
||||
|
||||
|
||||
#define PCI_WRITE_CONFIG_WORD \
|
||||
movb %al, %dl ; \
|
||||
andl $0x3, %edx ; \
|
||||
shll $16, %edx ; \
|
||||
\
|
||||
orl $0x80000000, %eax ; \
|
||||
andl $0xfffffffc, %eax ; \
|
||||
movw $0xcf8, %dx ; \
|
||||
outl %eax, %dx ; \
|
||||
\
|
||||
shrl $16, %edx ; \
|
||||
movl %ecx, %eax ; \
|
||||
addl $0xcfc, %edx ; \
|
||||
outw %ax, %dx
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Macro: PCI_WRITE_CONFIG_DWORD
|
||||
* Arguments: %eax address to write to (includes bus, device, function, &offset)
|
||||
* %ecx dword to write
|
||||
*
|
||||
* Results: none
|
||||
*
|
||||
* Trashed: %eax, %edx
|
||||
* Preserved: %ecx
|
||||
* Effects: writes a single byte to pci config space
|
||||
*
|
||||
* Notes: This routine is optimized for minimal register usage.
|
||||
*
|
||||
* What it does is almost simple.
|
||||
* It preserves %eax (baring special bits) until it is written
|
||||
* out to the appropriate port. And hides the least significant
|
||||
* bits of the address in the high half of edx.
|
||||
*
|
||||
* In %edx[2] it stores the lower three bits of the address.
|
||||
*/
|
||||
|
||||
|
||||
#define PCI_WRITE_CONFIG_DWORD \
|
||||
movb %al, %dl ; \
|
||||
andl $0x3, %edx ; \
|
||||
shll $16, %edx ; \
|
||||
\
|
||||
orl $0x80000000, %eax ; \
|
||||
andl $0xfffffffc, %eax ; \
|
||||
movw $0xcf8, %dx ; \
|
||||
outl %eax, %dx ; \
|
||||
\
|
||||
shrl $16, %edx ; \
|
||||
movl %ecx, %eax ; \
|
||||
addl $0xcfc, %edx ; \
|
||||
outl %eax, %dx
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Macro: PCI_READ_CONFIG_BYTE
|
||||
* Arguments: %eax address to read from (includes bus, device, function, &offset)
|
||||
*
|
||||
* Results: %al Byte read
|
||||
*
|
||||
* Trashed: %eax, %edx
|
||||
* Effects: reads a single byte from pci config space
|
||||
*
|
||||
* Notes: This routine is optimized for minimal register usage.
|
||||
*
|
||||
* What it does is almost simple.
|
||||
* It preserves %eax (baring special bits) until it is written
|
||||
* out to the appropriate port. And hides the least significant
|
||||
* bits of the address in the high half of edx.
|
||||
*
|
||||
* In %edx[2] it stores the lower three bits of the address.
|
||||
*/
|
||||
|
||||
|
||||
#define PCI_READ_CONFIG_BYTE \
|
||||
movb %al, %dl ; \
|
||||
andl $0x3, %edx ; \
|
||||
shll $16, %edx ; \
|
||||
\
|
||||
orl $0x80000000, %eax ; \
|
||||
andl $0xfffffffc, %eax ; \
|
||||
movw $0xcf8, %dx ; \
|
||||
outl %eax, %dx ; \
|
||||
\
|
||||
shrl $16, %edx ; \
|
||||
addl $0xcfc, %edx ; \
|
||||
inb %dx, %al
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Macro: PCI_READ_CONFIG_WORD
|
||||
* Arguments: %eax address to read from (includes bus, device, function, &offset)
|
||||
*
|
||||
* Results: %ax word read
|
||||
*
|
||||
* Trashed: %eax, %edx
|
||||
* Effects: reads a 2 bytes from pci config space
|
||||
*
|
||||
* Notes: This routine is optimized for minimal register usage.
|
||||
*
|
||||
* What it does is almost simple.
|
||||
* It preserves %eax (baring special bits) until it is written
|
||||
* out to the appropriate port. And hides the least significant
|
||||
* bits of the address in the high half of edx.
|
||||
*
|
||||
* In %edx[2] it stores the lower three bits of the address.
|
||||
*/
|
||||
|
||||
|
||||
#define PCI_READ_CONFIG_WORD \
|
||||
movb %al, %dl ; \
|
||||
andl $0x3, %edx ; \
|
||||
shll $16, %edx ; \
|
||||
\
|
||||
orl $0x80000000, %eax ; \
|
||||
andl $0xfffffffc, %eax ; \
|
||||
movw $0xcf8, %dx ; \
|
||||
outl %eax, %dx ; \
|
||||
\
|
||||
shrl $16, %edx ; \
|
||||
addl $0xcfc, %edx ; \
|
||||
inw %dx, %ax
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Macro: PCI_READ_CONFIG_DWORD
|
||||
* Arguments: %eax address to read from (includes bus, device, function, &offset)
|
||||
*
|
||||
* Results: %eax
|
||||
*
|
||||
* Trashed: %edx
|
||||
* Effects: reads 4 bytes from pci config space
|
||||
*
|
||||
* Notes: This routine is optimized for minimal register usage.
|
||||
*
|
||||
* What it does is almost simple.
|
||||
* It preserves %eax (baring special bits) until it is written
|
||||
* out to the appropriate port. And hides the least significant
|
||||
* bits of the address in the high half of edx.
|
||||
*
|
||||
* In %edx[2] it stores the lower three bits of the address.
|
||||
*/
|
||||
|
||||
|
||||
#define PCI_READ_CONFIG_DWORD \
|
||||
movb %al, %dl ; \
|
||||
andl $0x3, %edx ; \
|
||||
shll $16, %edx ; \
|
||||
\
|
||||
orl $0x80000000, %eax ; \
|
||||
andl $0xfffffffc, %eax ; \
|
||||
movw $0xcf8, %dx ; \
|
||||
outl %eax, %dx ; \
|
||||
\
|
||||
shrl $16, %edx ; \
|
||||
addl $0xcfc, %edx ; \
|
||||
inl %dx, %eax
|
||||
|
||||
|
||||
|
||||
|
||||
#define CS_READ(which) \
|
||||
mov $0x80000000,%eax ; \
|
||||
mov which,%ax ; \
|
||||
and $0xfc,%al /* clear bits 1-0 */ ; \
|
||||
mov $0xcf8,%dx /* port 0xcf8 ?*/ ; \
|
||||
outl %eax,%dx /* open up CS config */ ; \
|
||||
add $0x4,%dl /* 0xcfc data port 0 */ ; \
|
||||
mov which,%al ; \
|
||||
and $0x3,%al /* only bits 1-0 */ ; \
|
||||
add %al,%dl ; \
|
||||
inb %dx,%al /* read */ ; \
|
||||
|
||||
|
||||
#define CS_WRITE(which, data) \
|
||||
mov $0x80000000,%eax /* 32bit word with bit 31 set */ ; \
|
||||
mov which,%ax /* put the reg# in the low part */ ; \
|
||||
and $0xfc,%al /* dword align the reg# */ ; \
|
||||
mov $0xcf8,%dx /* enable port */ ; \
|
||||
outl %eax,%dx ; \
|
||||
add $0x4,%dl /* 1st data port */ ; \
|
||||
mov which,%ax /* register# */ ; \
|
||||
and $0x3,%ax ; \
|
||||
add %al,%dl ; \
|
||||
mov data, %al ; \
|
||||
outb %al,%dx /* write to reg */
|
||||
|
||||
#define REGBIS(which, bis) \
|
||||
CS_READ(which) ;\
|
||||
movb bis, %cl ;\
|
||||
orb %al, %cl ;\
|
||||
CS_WRITE(which, %cl)
|
||||
|
||||
#define REGBIC(which, bic) \
|
||||
CS_READ(which) ;\
|
||||
movb bic, %cl ;\
|
||||
notb %cl ;\
|
||||
andb %al, %cl ;\
|
||||
CS_WRITE(which, %cl)
|
||||
|
||||
|
||||
/* macro to BIC and BIS a reg. calls read a reg,
|
||||
* does a BIC and then a BIS on it.
|
||||
* to clear no bits, make BIC 0.
|
||||
* to set no bits, make BIS 0
|
||||
*/
|
||||
#define REGBICBIS(which, bic, bis) \
|
||||
CS_READ(which) ;\
|
||||
movb bic, %cl ;\
|
||||
notb %cl ;\
|
||||
andb %cl, %al ;\
|
||||
movb bis, %cl ;\
|
||||
orb %al, %cl ;\
|
||||
CS_WRITE(which, %cl)
|
||||
|
||||
#else
|
||||
NO FUNCTIONS YET!
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* originally this macro was from STPC BIOS */
|
||||
#define intel_chip_post_macro(value) \
|
||||
movb $value, %al ; \
|
||||
outb %al, $0x80
|
||||
|
||||
#define INTEL_PDATA_MAGIC 0xdeadbeef
|
||||
|
||||
/* SLOW_DOWN_IO is a delay we can use that is roughly cpu neutral,
|
||||
* and can be used before memory or timer chips come up.
|
||||
* Since this hits the isa bus it's roughly
|
||||
*/
|
||||
#define SLOW_DOWN_IO inb $0x80, %al
|
||||
|
||||
#endif /* ROM_INTEL_H */
|
||||
11
src/arch/i386/include/arch/ioapic.h
Normal file
11
src/arch/i386/include/arch/ioapic.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef ARCH_IOAPIC_H
|
||||
#define ARCH_IOAPIC_H
|
||||
|
||||
|
||||
#ifdef IOAPIC
|
||||
extern void setup_ioapic(void);
|
||||
#else
|
||||
#define setup_ioapic() do {} while(0)
|
||||
#endif
|
||||
|
||||
#endif /* ARCH_IOAPIC_H */
|
||||
21
src/arch/i386/include/arch/pirq_routing.h
Normal file
21
src/arch/i386/include/arch/pirq_routing.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef ARCH_PIRQ_ROUTING_H
|
||||
#define ARCH_PIRQ_ROUTING_H
|
||||
|
||||
#define PIRQ_SIGNATURE (('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24))
|
||||
#define PIRQ_VERSION 0x0100
|
||||
|
||||
extern const struct irq_routing_table intel_irq_routing_table;
|
||||
|
||||
#if !defined(DEBUG) && defined(HAVE_PIRQ_TABLE)
|
||||
void check_pirq_routing_table(void);
|
||||
#else
|
||||
#define check_pirq_routing_table() do {} while(0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_PIRQ_ROUTING_TABLE)
|
||||
void copy_pirq_routing_table(void);
|
||||
#else
|
||||
#define copy_pirq_routing_table() do {} while(0)
|
||||
#endif
|
||||
|
||||
#endif /* ARCH_PIRQ_ROUTING_H */
|
||||
69
src/arch/i386/include/arch/smp/atomic.h
Normal file
69
src/arch/i386/include/arch/smp/atomic.h
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
#ifndef ARCH_SMP_ATOMIC_H
|
||||
#define ARCH_SMP_ATOMIC_H
|
||||
|
||||
/*
|
||||
* Make sure gcc doesn't try to be clever and move things around
|
||||
* on us. We need to use _exactly_ the address the user gave us,
|
||||
* not some alias that contains the same information.
|
||||
*/
|
||||
typedef struct { volatile int counter; } atomic_t;
|
||||
|
||||
#define ATOMIC_INIT(i) { (i) }
|
||||
|
||||
/*
|
||||
* Atomic operations that C can't guarantee us. Useful for
|
||||
* resource counting etc..
|
||||
*/
|
||||
|
||||
/**
|
||||
* atomic_read - read atomic variable
|
||||
* @v: pointer of type atomic_t
|
||||
*
|
||||
* Atomically reads the value of @v. Note that the guaranteed
|
||||
* useful range of an atomic_t is only 24 bits.
|
||||
*/
|
||||
#define atomic_read(v) ((v)->counter)
|
||||
|
||||
/**
|
||||
* atomic_set - set atomic variable
|
||||
* @v: pointer of type atomic_t
|
||||
* @i: required value
|
||||
*
|
||||
* Atomically sets the value of @v to @i. Note that the guaranteed
|
||||
* useful range of an atomic_t is only 24 bits.
|
||||
*/
|
||||
#define atomic_set(v,i) (((v)->counter) = (i))
|
||||
|
||||
/**
|
||||
* atomic_inc - increment atomic variable
|
||||
* @v: pointer of type atomic_t
|
||||
*
|
||||
* Atomically increments @v by 1. Note that the guaranteed
|
||||
* useful range of an atomic_t is only 24 bits.
|
||||
*/
|
||||
static __inline__ void atomic_inc(atomic_t *v)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"lock ; incl %0"
|
||||
:"=m" (v->counter)
|
||||
:"m" (v->counter));
|
||||
}
|
||||
|
||||
/**
|
||||
* atomic_dec - decrement atomic variable
|
||||
* @v: pointer of type atomic_t
|
||||
*
|
||||
* Atomically decrements @v by 1. Note that the guaranteed
|
||||
* useful range of an atomic_t is only 24 bits.
|
||||
*/
|
||||
static __inline__ void atomic_dec(atomic_t *v)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"lock ; decl %0"
|
||||
:"=m" (v->counter)
|
||||
:"m" (v->counter));
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* ARCH_SMP_ATOMIC_H */
|
||||
275
src/arch/i386/include/arch/smp/mpspec.h
Normal file
275
src/arch/i386/include/arch/smp/mpspec.h
Normal file
|
|
@ -0,0 +1,275 @@
|
|||
#ifndef __ASM_MPSPEC_H
|
||||
#define __ASM_MPSPEC_H
|
||||
|
||||
#ifdef HAVE_MP_TABLE
|
||||
|
||||
/*
|
||||
* Structure definitions for SMP machines following the
|
||||
* Intel Multiprocessing Specification 1.1 and 1.4.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This tag identifies where the SMP configuration
|
||||
* information is.
|
||||
*/
|
||||
|
||||
#define SMP_MAGIC_IDENT (('_'<<24)|('P'<<16)|('M'<<8)|'_')
|
||||
|
||||
/*
|
||||
* a maximum of 16 APICs with the current APIC ID architecture.
|
||||
*/
|
||||
#define MAX_APICS 16
|
||||
|
||||
|
||||
#define SMP_FLOATING_TABLE_LEN sizeof(struct intel_mp_floating)
|
||||
|
||||
struct intel_mp_floating
|
||||
{
|
||||
char mpf_signature[4]; /* "_MP_" */
|
||||
unsigned long mpf_physptr; /* Configuration table address */
|
||||
unsigned char mpf_length; /* Our length (paragraphs) */
|
||||
unsigned char mpf_specification;/* Specification version */
|
||||
unsigned char mpf_checksum; /* Checksum (makes sum 0) */
|
||||
unsigned char mpf_feature1; /* Standard or configuration ? */
|
||||
unsigned char mpf_feature2; /* Bit7 set for IMCR|PIC */
|
||||
unsigned char mpf_feature3; /* Unused (0) */
|
||||
unsigned char mpf_feature4; /* Unused (0) */
|
||||
unsigned char mpf_feature5; /* Unused (0) */
|
||||
};
|
||||
|
||||
struct mp_config_table
|
||||
{
|
||||
char mpc_signature[4];
|
||||
#define MPC_SIGNATURE "PCMP"
|
||||
unsigned short mpc_length; /* Size of table */
|
||||
char mpc_spec; /* 0x01 */
|
||||
char mpc_checksum;
|
||||
char mpc_oem[8];
|
||||
char mpc_productid[12];
|
||||
unsigned long mpc_oemptr; /* 0 if not present */
|
||||
unsigned short mpc_oemsize; /* 0 if not present */
|
||||
unsigned short mpc_entry_count;
|
||||
unsigned long mpc_lapic; /* APIC address */
|
||||
unsigned short mpe_length; /* Extended Table size */
|
||||
unsigned char mpe_checksum; /* Extended Table checksum */
|
||||
unsigned char reserved;
|
||||
};
|
||||
|
||||
/* Followed by entries */
|
||||
|
||||
#define MP_PROCESSOR 0
|
||||
#define MP_BUS 1
|
||||
#define MP_IOAPIC 2
|
||||
#define MP_INTSRC 3
|
||||
#define MP_LINTSRC 4
|
||||
|
||||
struct mpc_config_processor
|
||||
{
|
||||
unsigned char mpc_type;
|
||||
unsigned char mpc_apicid; /* Local APIC number */
|
||||
unsigned char mpc_apicver; /* Its versions */
|
||||
unsigned char mpc_cpuflag;
|
||||
#define CPU_ENABLED 1 /* Processor is available */
|
||||
#define CPU_BOOTPROCESSOR 2 /* Processor is the BP */
|
||||
unsigned long mpc_cpufeature;
|
||||
#define CPU_STEPPING_MASK 0x0F
|
||||
#define CPU_MODEL_MASK 0xF0
|
||||
#define CPU_FAMILY_MASK 0xF00
|
||||
unsigned long mpc_featureflag; /* CPUID feature value */
|
||||
unsigned long mpc_reserved[2];
|
||||
};
|
||||
|
||||
struct mpc_config_bus
|
||||
{
|
||||
unsigned char mpc_type;
|
||||
unsigned char mpc_busid;
|
||||
unsigned char mpc_bustype[6] __attribute((packed));
|
||||
};
|
||||
|
||||
#define BUSTYPE_EISA "EISA"
|
||||
#define BUSTYPE_ISA "ISA"
|
||||
#define BUSTYPE_INTERN "INTERN" /* Internal BUS */
|
||||
#define BUSTYPE_MCA "MCA"
|
||||
#define BUSTYPE_VL "VL" /* Local bus */
|
||||
#define BUSTYPE_PCI "PCI"
|
||||
#define BUSTYPE_PCMCIA "PCMCIA"
|
||||
|
||||
struct mpc_config_ioapic
|
||||
{
|
||||
unsigned char mpc_type;
|
||||
unsigned char mpc_apicid;
|
||||
unsigned char mpc_apicver;
|
||||
unsigned char mpc_flags;
|
||||
#define MPC_APIC_USABLE 0x01
|
||||
unsigned long mpc_apicaddr;
|
||||
};
|
||||
|
||||
struct mpc_config_intsrc
|
||||
{
|
||||
unsigned char mpc_type;
|
||||
unsigned char mpc_irqtype;
|
||||
unsigned short mpc_irqflag;
|
||||
unsigned char mpc_srcbus;
|
||||
unsigned char mpc_srcbusirq;
|
||||
unsigned char mpc_dstapic;
|
||||
unsigned char mpc_dstirq;
|
||||
};
|
||||
|
||||
enum mp_irq_source_types {
|
||||
mp_INT = 0,
|
||||
mp_NMI = 1,
|
||||
mp_SMI = 2,
|
||||
mp_ExtINT = 3
|
||||
};
|
||||
|
||||
#define MP_IRQ_POLARITY_DEFAULT 0x0
|
||||
#define MP_IRQ_POLARITY_HIGH 0x1
|
||||
#define MP_IRQ_POLARITY_LOW 0x3
|
||||
#define MP_IRQ_POLARITY_MASK 0x3
|
||||
#define MP_IRQ_TRIGGER_DEFAULT 0x0
|
||||
#define MP_IRQ_TRIGGER_EDGE 0x4
|
||||
#define MP_IRQ_TRIGGER_LEVEL 0xc
|
||||
#define MP_IRQ_TRIGGER_MASK 0xc
|
||||
|
||||
|
||||
struct mpc_config_lintsrc
|
||||
{
|
||||
unsigned char mpc_type;
|
||||
unsigned char mpc_irqtype;
|
||||
unsigned short mpc_irqflag;
|
||||
unsigned char mpc_srcbusid;
|
||||
unsigned char mpc_srcbusirq;
|
||||
unsigned char mpc_destapic;
|
||||
#define MP_APIC_ALL 0xFF
|
||||
unsigned char mpc_destapiclint;
|
||||
};
|
||||
|
||||
/*
|
||||
* Default configurations
|
||||
*
|
||||
* 1 2 CPU ISA 82489DX
|
||||
* 2 2 CPU EISA 82489DX neither IRQ 0 timer nor IRQ 13 DMA chaining
|
||||
* 3 2 CPU EISA 82489DX
|
||||
* 4 2 CPU MCA 82489DX
|
||||
* 5 2 CPU ISA+PCI
|
||||
* 6 2 CPU EISA+PCI
|
||||
* 7 2 CPU MCA+PCI
|
||||
*/
|
||||
|
||||
#define MAX_IRQ_SOURCES 128
|
||||
#define MAX_MP_BUSSES 32
|
||||
enum mp_bustype {
|
||||
MP_BUS_ISA,
|
||||
MP_BUS_EISA,
|
||||
MP_BUS_PCI,
|
||||
MP_BUS_MCA
|
||||
};
|
||||
|
||||
/* Followed by entries */
|
||||
|
||||
#define MPE_SYSTEM_ADDRESS_SPACE 0x80
|
||||
#define MPE_BUS_HIERARCHY 0x81
|
||||
#define MPE_COMPATIBILITY_ADDRESS_SPACE 0x82
|
||||
|
||||
struct mp_exten_config {
|
||||
unsigned char mpe_type;
|
||||
unsigned char mpe_length;
|
||||
};
|
||||
|
||||
typedef struct mp_exten_config *mpe_t;
|
||||
|
||||
struct mp_exten_system_address_space {
|
||||
unsigned char mpe_type;
|
||||
unsigned char mpe_length;
|
||||
unsigned char mpe_busid;
|
||||
unsigned char mpe_address_type;
|
||||
#define ADDRESS_TYPE_IO 0
|
||||
#define ADDRESS_TYPE_MEM 1
|
||||
#define ADDRESS_TYPE_PREFETCH 2
|
||||
unsigned int mpe_address_base_low;
|
||||
unsigned int mpe_address_base_high;
|
||||
unsigned int mpe_address_length_low;
|
||||
unsigned int mpe_address_length_high;
|
||||
};
|
||||
|
||||
struct mp_exten_bus_hierarchy {
|
||||
unsigned char mpe_type;
|
||||
unsigned char mpe_length;
|
||||
unsigned char mpe_busid;
|
||||
unsigned char mpe_bus_info;
|
||||
#define BUS_SUBTRACTIVE_DECODE 1
|
||||
unsigned char mpe_parent_busid;
|
||||
unsigned char reserved[3];
|
||||
};
|
||||
|
||||
struct mp_exten_compatibility_address_space {
|
||||
unsigned char mpe_type;
|
||||
unsigned char mpe_length;
|
||||
unsigned char mpe_busid;
|
||||
unsigned char mpe_address_modifier;
|
||||
#define ADDRESS_RANGE_SUBTRACT 1
|
||||
#define ADDRESS_RANGE_ADD 0
|
||||
unsigned int mpe_range_list;
|
||||
#define RANGE_LIST_IO_ISA 0
|
||||
/* X100 - X3FF
|
||||
* X500 - X7FF
|
||||
* X900 - XBFF
|
||||
* XD00 - XFFF
|
||||
*/
|
||||
#define RANGE_LIST_IO_VGA 1
|
||||
/* X3B0 - X3BB
|
||||
* X3C0 - X3DF
|
||||
* X7B0 - X7BB
|
||||
* X7C0 - X7DF
|
||||
* XBB0 - XBBB
|
||||
* XBC0 - XBDF
|
||||
* XFB0 - XFBB
|
||||
* XFC0 - XCDF
|
||||
*/
|
||||
};
|
||||
|
||||
/* Default local apic addr */
|
||||
#define LAPIC_ADDR 0xFEE00000
|
||||
|
||||
void *smp_next_mpc_entry(struct mp_config_table *mc);
|
||||
void *smp_next_mpe_entry(struct mp_config_table *mc);
|
||||
|
||||
void smp_write_processor(struct mp_config_table *mc,
|
||||
unsigned char apicid, unsigned char apicver,
|
||||
unsigned char cpuflag, unsigned int cpufeature,
|
||||
unsigned int featureflag);
|
||||
void smp_write_processors(struct mp_config_table *mc);
|
||||
void smp_write_bus(struct mp_config_table *mc,
|
||||
unsigned char id, unsigned char *bustype);
|
||||
void smp_write_ioapic(struct mp_config_table *mc,
|
||||
unsigned char id, unsigned char ver,
|
||||
unsigned long apicaddr);
|
||||
void smp_write_intsrc(struct mp_config_table *mc,
|
||||
unsigned char irqtype, unsigned short irqflag,
|
||||
unsigned char srcbus, unsigned char srcbusirq,
|
||||
unsigned char dstapic, unsigned char dstirq);
|
||||
void smp_write_lintsrc(struct mp_config_table *mc,
|
||||
unsigned char irqtype, unsigned short irqflag,
|
||||
unsigned char srcbusid, unsigned char srcbusirq,
|
||||
unsigned char destapic, unsigned char destapiclint);
|
||||
void smp_write_address_space(struct mp_config_table *mc,
|
||||
unsigned char busid, unsigned char address_type,
|
||||
unsigned int address_base_low, unsigned int address_base_high,
|
||||
unsigned int address_length_low, unsigned int address_length_high);
|
||||
void smp_write_bus_hierarchy(struct mp_config_table *mc,
|
||||
unsigned char busid, unsigned char bus_info,
|
||||
unsigned char parent_busid);
|
||||
void smp_write_compatibility_address_space(struct mp_config_table *mc,
|
||||
unsigned char busid, unsigned char address_modifier,
|
||||
unsigned int range_list);
|
||||
unsigned char smp_compute_checksum(void *v, int len);
|
||||
void smp_write_floating_table(void *v);
|
||||
void write_smp_table(void *v);
|
||||
|
||||
|
||||
#else /* HAVE_MP_TABLE */
|
||||
#define write_smp_table(v) do {} while(0)
|
||||
#endif /* HAVE_MP_TABLE */
|
||||
|
||||
#endif
|
||||
|
||||
57
src/arch/i386/include/arch/smp/spinlock.h
Normal file
57
src/arch/i386/include/arch/smp/spinlock.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#ifndef ARCH_SMP_SPINLOCK_H
|
||||
#define ARCH_SMP_SPINLOCK_H
|
||||
|
||||
/*
|
||||
* Your basic SMP spinlocks, allowing only a single CPU anywhere
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
volatile unsigned int lock;
|
||||
} spinlock_t;
|
||||
|
||||
|
||||
#define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 }
|
||||
|
||||
/*
|
||||
* Simple spin lock operations. There are two variants, one clears IRQ's
|
||||
* on the local processor, one does not.
|
||||
*
|
||||
* We make no fairness assumptions. They have a cost.
|
||||
*/
|
||||
#define barrier() __asm__ __volatile__("": : :"memory")
|
||||
#define spin_is_locked(x) (*(volatile char *)(&(x)->lock) <= 0)
|
||||
#define spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x))
|
||||
|
||||
#define spin_lock_string \
|
||||
"\n1:\t" \
|
||||
"lock ; decb %0\n\t" \
|
||||
"js 2f\n" \
|
||||
".section .text.lock,\"ax\"\n" \
|
||||
"2:\t" \
|
||||
"cmpb $0,%0\n\t" \
|
||||
"rep;nop\n\t" \
|
||||
"jle 2b\n\t" \
|
||||
"jmp 1b\n" \
|
||||
".previous"
|
||||
|
||||
/*
|
||||
* This works. Despite all the confusion.
|
||||
*/
|
||||
#define spin_unlock_string \
|
||||
"movb $1,%0"
|
||||
|
||||
static inline void spin_lock(spinlock_t *lock)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
spin_lock_string
|
||||
:"=m" (lock->lock) : : "memory");
|
||||
}
|
||||
|
||||
static inline void spin_unlock(spinlock_t *lock)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
spin_unlock_string
|
||||
:"=m" (lock->lock) : : "memory");
|
||||
}
|
||||
|
||||
#endif /* ARCH_SMP_SPINLOCK_H */
|
||||
55
src/arch/i386/lib/cpu_reset.inc
Normal file
55
src/arch/i386/lib/cpu_reset.inc
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
jmp cpu_reset_out
|
||||
|
||||
#ifdef DEBUG
|
||||
cpu_reset_str: .string "cpu_reset\r\n";
|
||||
cpu_size_set_str: .string "cpu memory size set\r\n";
|
||||
#endif
|
||||
|
||||
|
||||
__cpu_reset:
|
||||
#ifdef DEBUG
|
||||
TTYS0_TX_STRING($cpu_reset_str);
|
||||
#endif /* DEBUG */
|
||||
|
||||
CALLSP(set_memory_size)
|
||||
|
||||
#ifdef DEBUG
|
||||
TTYS0_TX_STRING($cpu_size_set_str);
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifdef SMP
|
||||
/* Test to see if we are the boot strap processor.
|
||||
* If so the boot must be complete.
|
||||
*/
|
||||
movl $0x1b, %ecx
|
||||
rdmsr
|
||||
testl $0x100, %eax
|
||||
jnz __reboot
|
||||
|
||||
/* Fixed mtrrs are enabled by the C code so if they
|
||||
* aren't enabled yet we must be a secondary
|
||||
* processor initializing in an SMP system.
|
||||
*/
|
||||
mov $MTRRdefType_MSR, %ecx
|
||||
rdmsr
|
||||
testl $0x400, %eax
|
||||
jnz __reboot
|
||||
|
||||
/* set the stack pointer */
|
||||
movl $_estack, %esp
|
||||
movl $APIC_DEFAULT_BASE, %edi
|
||||
movl APIC_ID(%edi), %eax
|
||||
shrl $24, %eax
|
||||
movl $STACK_SIZE, %ebx
|
||||
mull %ebx
|
||||
subl %eax, %esp
|
||||
|
||||
call EXT(secondary_cpu_init)
|
||||
/* Fall through in case we somehow return */
|
||||
#endif /* SMP */
|
||||
|
||||
__reboot:
|
||||
movl $0xffffffff, %ebp
|
||||
jmp __main
|
||||
|
||||
cpu_reset_out:
|
||||
65
src/arch/i386/lib/pirq_routing.c
Normal file
65
src/arch/i386/lib/pirq_routing.c
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
#ifdef HAVE_PIRQ_TABLE
|
||||
#include <printk.h>
|
||||
#include <pci.h>
|
||||
#include <arch/pirq_routing.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
void check_pirq_routing_table(void)
|
||||
{
|
||||
const u8 *addr;
|
||||
const struct irq_routing_table *rt;
|
||||
int i;
|
||||
u8 sum;
|
||||
|
||||
printk_info("Checking IRQ routing tables...");
|
||||
|
||||
rt = &intel_irq_routing_table;
|
||||
addr = (u8 *)rt;
|
||||
|
||||
sum = 0;
|
||||
for (i = 0; i < rt->size; i++)
|
||||
sum += addr[i];
|
||||
|
||||
printk_debug("%s:%6d:%s() - irq_routing_table located at: 0x%p\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, addr);
|
||||
|
||||
sum = (unsigned char)(rt->checksum-sum);
|
||||
|
||||
if (sum != rt->checksum) {
|
||||
printk_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_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_warning("%s:%6d:%s() - "
|
||||
"checksum error in irq routing table\n",
|
||||
__FILE__, __LINE__, __FUNCTION__);
|
||||
}
|
||||
|
||||
printk_info("done.\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#define RTABLE_DEST 0xf0000
|
||||
|
||||
void copy_pirq_routing_table(void)
|
||||
{
|
||||
printk_info("Copying IRQ routing tables...");
|
||||
memcpy((char *) RTABLE_DEST, &intel_irq_routing_table, intel_irq_routing_table.size);
|
||||
printk_info("done.\n");
|
||||
}
|
||||
#endif /* HAVE_PIRQ_TABLE */
|
||||
|
||||
3
src/arch/i386/smp/Config
Normal file
3
src/arch/i386/smp/Config
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
object mpspec.o
|
||||
object ioapic.o
|
||||
object start_stop.o
|
||||
137
src/arch/i386/smp/ioapic.c
Normal file
137
src/arch/i386/smp/ioapic.c
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
#if defined(IOAPIC)
|
||||
#include <arch/ioapic.h>
|
||||
#include <printk.h>
|
||||
|
||||
/* TODO: this must move to chip/intel */
|
||||
/* we have to do more than we thought. I assumed Linux would do all the
|
||||
* interesting parts, and I was wrong.
|
||||
*/
|
||||
struct ioapicreg {
|
||||
unsigned int reg;
|
||||
unsigned int value_low, value_high;
|
||||
};
|
||||
struct ioapicreg ioapicregvalues[] = {
|
||||
#define ALL (0xff << 24)
|
||||
#define NONE (0)
|
||||
#define DISABLED (1 << 16)
|
||||
#define ENABLED (0 << 16)
|
||||
#define TRIGGER_EDGE (0 << 15)
|
||||
#define TRIGGER_LEVEL (1 << 15)
|
||||
#define POLARITY_HIGH (0 << 13)
|
||||
#define POLARITY_LOW (1 << 13)
|
||||
#define PHYSICAL_DEST (0 << 11)
|
||||
#define LOGICAL_DEST (1 << 11)
|
||||
#define ExtINT (7 << 8)
|
||||
#define NMI (4 << 8)
|
||||
#define SMI (2 << 8)
|
||||
#define INT (1 << 8)
|
||||
#if 0 /* L440GX */
|
||||
{0x00, DISABLED, NONE},
|
||||
{0x01, ENABLED|TRIGGER_EDGE|POLARITY_HIGH|LOGICAL_DEST|INT|0x59, ALL},
|
||||
{0x02, ENABLED|TRIGGER_EDGE|POLARITY_HIGH|LOGICAL_DEST|INT|0x51, ALL},
|
||||
{0x03, ENABLED|TRIGGER_EDGE|POLARITY_HIGH|LOGICAL_DEST|INT|0x61, NONE},
|
||||
{0x04, ENABLED|TRIGGER_EDGE|POLARITY_HIGH|LOGICAL_DEST|INT|0x69, ALL},
|
||||
{0x05, ENABLED|TRIGGER_EDGE|POLARITY_HIGH|LOGICAL_DEST|INT|0x71, NONE},
|
||||
{0x06, ENABLED|TRIGGER_EDGE|POLARITY_HIGH|LOGICAL_DEST|INT|0x79, NONE},
|
||||
{0x07, ENABLED|TRIGGER_EDGE|POLARITY_HIGH|LOGICAL_DEST|INT|0x81, NONE},
|
||||
{0x08, ENABLED|TRIGGER_EDGE|POLARITY_HIGH|LOGICAL_DEST|INT|0x89, ALL},
|
||||
{0x09, DISABLED, NONE},
|
||||
{0x0a, DISABLED, NONE},
|
||||
{0x0b, DISABLED, NONE},
|
||||
{0x0c, ENABLED|TRIGGER_EDGE|POLARITY_HIGH|LOGICAL_DEST|INT|0x91, ALL},
|
||||
{0x0d, DISABLED, NONE},
|
||||
{0x0e, ENABLED|TRIGGER_EDGE|POLARITY_HIGH|LOGICAL_DEST|INT|0x99, ALL},
|
||||
{0x0f, ENABLED|TRIGGER_EDGE|POLARITY_HIGH|LOGICAL_DEST|INT|0xa1, ALL},
|
||||
{0x10, DISABLED, NONE},
|
||||
{0x11, DISABLED, NONE},
|
||||
{0x12, DISABLED, NONE},
|
||||
{0x13, ENABLED|TRIGGER_LEVEL|POLARITY_LOW|LOGICAL_DEST|INT|0xa9, ALL},
|
||||
{0x14, DISABLED, NONE},
|
||||
{0x15, ENABLED|TRIGGER_LEVEL|POLARITY_LOW|LOGICAL_DEST|INT|0xb1, ALL},
|
||||
{0x16, DISABLED, NONE},
|
||||
{0x17, DISABLED, NONE}
|
||||
#endif
|
||||
#if 0 /* tyan guinness */
|
||||
/* mask, trigger, polarity, destination, delivery, vector */
|
||||
{0x00, ENABLED|TRIGGER_EDGE|POLARITY_HIGH|LOGICAL_DEST|ExtINT|0x0, ALL},
|
||||
{0x01, ENABLED|TRIGGER_EDGE|POLARITY_HIGH|LOGICAL_DEST|INT|0x1, ALL},
|
||||
{0x02, ENABLED|TRIGGER_EDGE|POLARITY_HIGH|LOGICAL_DEST|INT|0x0, ALL},
|
||||
{0x03, ENABLED|TRIGGER_EDGE|POLARITY_HIGH|LOGICAL_DEST|INT|0x3, ALL},
|
||||
{0x04, ENABLED|TRIGGER_EDGE|POLARITY_HIGH|LOGICAL_DEST|INT|0x4, ALL},
|
||||
{0x05, ENABLED|TRIGGER_EDGE|POLARITY_HIGH|LOGICAL_DEST|INT|0x5, ALL},
|
||||
{0x06, ENABLED|TRIGGER_EDGE|POLARITY_HIGH|LOGICAL_DEST|INT|0x6, ALL},
|
||||
{0x07, ENABLED|TRIGGER_EDGE|POLARITY_HIGH|LOGICAL_DEST|INT|0x7, ALL},
|
||||
{0x08, ENABLED|TRIGGER_EDGE|POLARITY_HIGH|LOGICAL_DEST|INT|0x8, ALL},
|
||||
{0x09, ENABLED|TRIGGER_EDGE|POLARITY_HIGH|LOGICAL_DEST|INT|0x9, ALL},
|
||||
{0x0a, ENABLED|TRIGGER_EDGE|POLARITY_HIGH|LOGICAL_DEST|INT|0xa, ALL},
|
||||
{0x0b, ENABLED|TRIGGER_EDGE|POLARITY_HIGH|LOGICAL_DEST|INT|0xb, ALL},
|
||||
{0x0c, ENABLED|TRIGGER_EDGE|POLARITY_HIGH|LOGICAL_DEST|INT|0xc, ALL},
|
||||
{0x0d, ENABLED|TRIGGER_EDGE|POLARITY_HIGH|LOGICAL_DEST|INT|0xd, ALL},
|
||||
{0x0e, ENABLED|TRIGGER_EDGE|POLARITY_HIGH|LOGICAL_DEST|INT|0xe, ALL},
|
||||
{0x0f, ENABLED|TRIGGER_EDGE|POLARITY_HIGH|LOGICAL_DEST|INT|0xf, ALL},
|
||||
{0x10, ENABLED|TRIGGER_LEVEL|POLARITY_LOW|LOGICAL_DEST|INT|0x10, ALL},
|
||||
{0x11, ENABLED|TRIGGER_LEVEL|POLARITY_LOW|LOGICAL_DEST|INT|0x11, ALL},
|
||||
{0x12, ENABLED|TRIGGER_LEVEL|POLARITY_LOW|LOGICAL_DEST|INT|0x12, ALL},
|
||||
{0x13, ENABLED|TRIGGER_LEVEL|POLARITY_LOW|LOGICAL_DEST|INT|0x13, ALL},
|
||||
{0x14, DISABLED, NONE},
|
||||
{0x14, DISABLED, NONE},
|
||||
{0x15, DISABLED, NONE},
|
||||
{0x16, DISABLED, NONE},
|
||||
{0x17, DISABLED, NONE},
|
||||
#endif
|
||||
#if 1
|
||||
/* mask, trigger, polarity, destination, delivery, vector */
|
||||
{0x00, DISABLED, NONE},
|
||||
{0x01, DISABLED, NONE},
|
||||
{0x02, DISABLED, NONE},
|
||||
{0x03, DISABLED, NONE},
|
||||
{0x04, DISABLED, NONE},
|
||||
{0x05, DISABLED, NONE},
|
||||
{0x06, DISABLED, NONE},
|
||||
{0x07, DISABLED, NONE},
|
||||
{0x08, DISABLED, NONE},
|
||||
{0x09, DISABLED, NONE},
|
||||
{0x0a, DISABLED, NONE},
|
||||
{0x0b, DISABLED, NONE},
|
||||
{0x0c, DISABLED, NONE},
|
||||
{0x0d, DISABLED, NONE},
|
||||
{0x0e, DISABLED, NONE},
|
||||
{0x0f, DISABLED, NONE},
|
||||
{0x10, DISABLED, NONE},
|
||||
{0x11, DISABLED, NONE},
|
||||
{0x12, DISABLED, NONE},
|
||||
{0x13, DISABLED, NONE},
|
||||
{0x14, DISABLED, NONE},
|
||||
{0x14, DISABLED, NONE},
|
||||
{0x15, DISABLED, NONE},
|
||||
{0x16, DISABLED, NONE},
|
||||
{0x17, DISABLED, NONE},
|
||||
#endif
|
||||
};
|
||||
|
||||
void setup_ioapic(void)
|
||||
{
|
||||
int i;
|
||||
unsigned long value_low, value_high;
|
||||
unsigned long nvram = 0xfec00000;
|
||||
volatile unsigned long *l;
|
||||
struct ioapicreg *a = ioapicregvalues;
|
||||
|
||||
l = (unsigned long *) nvram;
|
||||
for (i = 0; i < sizeof(ioapicregvalues) / sizeof(ioapicregvalues[0]);
|
||||
i++, a++) {
|
||||
l[0] = (a->reg * 2) + 0x10;
|
||||
l[4] = a->value_low;
|
||||
value_low = l[4];
|
||||
l[0] = (a->reg *2) + 0x11;
|
||||
l[4] = a->value_high;
|
||||
value_high = l[4];
|
||||
if ((i==0) && (value_low == 0xffffffff)) {
|
||||
printk_warning("IO APIC not responding.\n");
|
||||
return;
|
||||
}
|
||||
printk_spew("for IRQ, reg 0x%08x value 0x%08x 0x%08x\n",
|
||||
a->reg, a->value_low, a->value_high);
|
||||
}
|
||||
}
|
||||
#endif /* IOAPIC */
|
||||
243
src/arch/i386/smp/mpspec.c
Normal file
243
src/arch/i386/smp/mpspec.c
Normal file
|
|
@ -0,0 +1,243 @@
|
|||
#ifdef HAVE_MP_TABLE
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
#include <smp/start_stop.h>
|
||||
#include <arch/smp/mpspec.h>
|
||||
#include <string.h>
|
||||
#include <cpu/p5/cpuid.h>
|
||||
#include <cpu/p6/apic.h>
|
||||
#include <printk.h>
|
||||
|
||||
unsigned char smp_compute_checksum(void *v, int len)
|
||||
{
|
||||
unsigned char *bytes;
|
||||
unsigned char checksum;
|
||||
int i;
|
||||
bytes = v;
|
||||
checksum = 0;
|
||||
for(i = 0; i < len; i++) {
|
||||
checksum -= bytes[i];
|
||||
}
|
||||
return checksum;
|
||||
}
|
||||
|
||||
void smp_write_floating_table(void *v)
|
||||
{
|
||||
struct intel_mp_floating *mf;
|
||||
|
||||
mf = v;
|
||||
mf->mpf_signature[0] = '_';
|
||||
mf->mpf_signature[1] = 'M';
|
||||
mf->mpf_signature[2] = 'P';
|
||||
mf->mpf_signature[3] = '_';
|
||||
mf->mpf_physptr = (unsigned long)(((char *)v) + SMP_FLOATING_TABLE_LEN);
|
||||
mf->mpf_length = 1;
|
||||
mf->mpf_specification = 4;
|
||||
mf->mpf_checksum = 0;
|
||||
mf->mpf_feature1 = 0;
|
||||
mf->mpf_feature2 = 0;
|
||||
mf->mpf_feature3 = 0;
|
||||
mf->mpf_feature4 = 0;
|
||||
mf->mpf_feature5 = 0;
|
||||
mf->mpf_checksum = smp_compute_checksum(mf, mf->mpf_length*16);
|
||||
}
|
||||
|
||||
void *smp_next_mpc_entry(struct mp_config_table *mc)
|
||||
{
|
||||
void *v;
|
||||
v = (void *)(((char *)mc) + mc->mpc_length);
|
||||
return v;
|
||||
}
|
||||
static void smp_add_mpc_entry(struct mp_config_table *mc, unsigned length)
|
||||
{
|
||||
mc->mpc_length += length;
|
||||
mc->mpc_entry_count++;
|
||||
}
|
||||
|
||||
void *smp_next_mpe_entry(struct mp_config_table *mc)
|
||||
{
|
||||
void *v;
|
||||
v = (void *)(((char *)mc) + mc->mpc_length + mc->mpe_length);
|
||||
return v;
|
||||
}
|
||||
static void smp_add_mpe_entry(struct mp_config_table *mc, mpe_t mpe)
|
||||
{
|
||||
mc->mpe_length += mpe->mpe_length;
|
||||
}
|
||||
|
||||
void smp_write_processor(struct mp_config_table *mc,
|
||||
unsigned char apicid, unsigned char apicver,
|
||||
unsigned char cpuflag, unsigned int cpufeature,
|
||||
unsigned int featureflag)
|
||||
{
|
||||
struct mpc_config_processor *mpc;
|
||||
mpc = smp_next_mpc_entry(mc);
|
||||
memset(mpc, '\0', sizeof(*mpc));
|
||||
mpc->mpc_type = MP_PROCESSOR;
|
||||
mpc->mpc_apicid = apicid;
|
||||
mpc->mpc_apicver = apicver;
|
||||
mpc->mpc_cpuflag = cpuflag;
|
||||
mpc->mpc_cpufeature = cpufeature;
|
||||
mpc->mpc_featureflag = featureflag;
|
||||
smp_add_mpc_entry(mc, sizeof(*mpc));
|
||||
}
|
||||
|
||||
/* If we assume a symmetric processor configuration we can
|
||||
* get all of the information we need to write the processor
|
||||
* entry from the bootstrap processor.
|
||||
* Plus I don't think linux really even cares.
|
||||
* Having the proper apicid's in the table so the non-bootstrap
|
||||
* processors can be woken up should be enough.
|
||||
*/
|
||||
void smp_write_processors(struct mp_config_table *mc)
|
||||
{
|
||||
int i;
|
||||
int processor_id;
|
||||
unsigned apic_version;
|
||||
unsigned cpu_features;
|
||||
unsigned cpu_feature_flags;
|
||||
int eax, ebx, ecx, edx;
|
||||
processor_id = this_processors_id();
|
||||
apic_version = apic_read(APIC_LVR) & 0xff;
|
||||
cpuid(1, &eax, &ebx, &ecx, &edx);
|
||||
cpu_features = eax;
|
||||
cpu_feature_flags = edx;
|
||||
for(i = 0; i < MAX_CPUS; i++) {
|
||||
smp_write_processor(mc, i, apic_version,
|
||||
((processor_id == i)? CPU_BOOTPROCESSOR:0) | CPU_ENABLED,
|
||||
cpu_features, cpu_feature_flags
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void smp_write_bus(struct mp_config_table *mc,
|
||||
unsigned char id, unsigned char *bustype)
|
||||
{
|
||||
struct mpc_config_bus *mpc;
|
||||
mpc = smp_next_mpc_entry(mc);
|
||||
memset(mpc, '\0', sizeof(*mpc));
|
||||
mpc->mpc_type = MP_BUS;
|
||||
mpc->mpc_busid = id;
|
||||
memcpy(mpc->mpc_bustype, bustype, sizeof(mpc->mpc_bustype));
|
||||
smp_add_mpc_entry(mc, sizeof(*mpc));
|
||||
}
|
||||
|
||||
void smp_write_ioapic(struct mp_config_table *mc,
|
||||
unsigned char id, unsigned char ver,
|
||||
unsigned long apicaddr)
|
||||
{
|
||||
struct mpc_config_ioapic *mpc;
|
||||
mpc = smp_next_mpc_entry(mc);
|
||||
memset(mpc, '\0', sizeof(*mpc));
|
||||
mpc->mpc_type = MP_IOAPIC;
|
||||
mpc->mpc_apicid = id;
|
||||
mpc->mpc_apicver = ver;
|
||||
mpc->mpc_flags = MPC_APIC_USABLE;
|
||||
mpc->mpc_apicaddr = apicaddr;
|
||||
smp_add_mpc_entry(mc, sizeof(*mpc));
|
||||
}
|
||||
|
||||
void smp_write_intsrc(struct mp_config_table *mc,
|
||||
unsigned char irqtype, unsigned short irqflag,
|
||||
unsigned char srcbus, unsigned char srcbusirq,
|
||||
unsigned char dstapic, unsigned char dstirq)
|
||||
{
|
||||
struct mpc_config_intsrc *mpc;
|
||||
mpc = smp_next_mpc_entry(mc);
|
||||
memset(mpc, '\0', sizeof(*mpc));
|
||||
mpc->mpc_type = MP_INTSRC;
|
||||
mpc->mpc_irqtype = irqtype;
|
||||
mpc->mpc_irqflag = irqflag;
|
||||
mpc->mpc_srcbus = srcbus;
|
||||
mpc->mpc_srcbusirq = srcbusirq;
|
||||
mpc->mpc_dstapic = dstapic;
|
||||
mpc->mpc_dstirq = dstirq;
|
||||
smp_add_mpc_entry(mc, sizeof(*mpc));
|
||||
}
|
||||
|
||||
|
||||
void smp_write_lintsrc(struct mp_config_table *mc,
|
||||
unsigned char irqtype, unsigned short irqflag,
|
||||
unsigned char srcbusid, unsigned char srcbusirq,
|
||||
unsigned char destapic, unsigned char destapiclint)
|
||||
{
|
||||
struct mpc_config_lintsrc *mpc;
|
||||
mpc = smp_next_mpc_entry(mc);
|
||||
memset(mpc, '\0', sizeof(*mpc));
|
||||
mpc->mpc_type = MP_LINTSRC;
|
||||
mpc->mpc_irqtype = irqtype;
|
||||
mpc->mpc_irqflag = irqflag;
|
||||
mpc->mpc_srcbusid = srcbusid;
|
||||
mpc->mpc_srcbusirq = srcbusirq;
|
||||
mpc->mpc_destapic = destapic;
|
||||
mpc->mpc_destapiclint = destapiclint;
|
||||
smp_add_mpc_entry(mc, sizeof(*mpc));
|
||||
}
|
||||
|
||||
void smp_write_address_space(struct mp_config_table *mc,
|
||||
unsigned char busid, unsigned char address_type,
|
||||
unsigned int address_base_low, unsigned int address_base_high,
|
||||
unsigned int address_length_low, unsigned int address_length_high)
|
||||
{
|
||||
struct mp_exten_system_address_space *mpe;
|
||||
mpe = smp_next_mpe_entry(mc);
|
||||
memset(mpe, '\0', sizeof(*mpe));
|
||||
mpe->mpe_type = MPE_SYSTEM_ADDRESS_SPACE;
|
||||
mpe->mpe_length = sizeof(*mpe);
|
||||
mpe->mpe_busid = busid;
|
||||
mpe->mpe_address_type = address_type;
|
||||
mpe->mpe_address_base_low = address_base_low;
|
||||
mpe->mpe_address_base_high = address_base_high;
|
||||
mpe->mpe_address_length_low = address_length_low;
|
||||
mpe->mpe_address_length_high = address_length_high;
|
||||
smp_add_mpe_entry(mc, (mpe_t)mpe);
|
||||
}
|
||||
|
||||
|
||||
void smp_write_bus_hierarchy(struct mp_config_table *mc,
|
||||
unsigned char busid, unsigned char bus_info,
|
||||
unsigned char parent_busid)
|
||||
{
|
||||
struct mp_exten_bus_hierarchy *mpe;
|
||||
mpe = smp_next_mpe_entry(mc);
|
||||
memset(mpe, '\0', sizeof(*mpe));
|
||||
mpe->mpe_type = MPE_BUS_HIERARCHY;
|
||||
mpe->mpe_length = sizeof(*mpe);
|
||||
mpe->mpe_busid = busid;
|
||||
mpe->mpe_bus_info = bus_info;
|
||||
mpe->mpe_parent_busid = parent_busid;
|
||||
smp_add_mpe_entry(mc, (mpe_t)mpe);
|
||||
}
|
||||
|
||||
void smp_write_compatibility_address_space(struct mp_config_table *mc,
|
||||
unsigned char busid, unsigned char address_modifier,
|
||||
unsigned int range_list)
|
||||
{
|
||||
struct mp_exten_compatibility_address_space *mpe;
|
||||
mpe = smp_next_mpe_entry(mc);
|
||||
memset(mpe, '\0', sizeof(*mpe));
|
||||
mpe->mpe_type = MPE_COMPATIBILITY_ADDRESS_SPACE;
|
||||
mpe->mpe_length = sizeof(*mpe);
|
||||
mpe->mpe_busid = busid;
|
||||
mpe->mpe_address_modifier = address_modifier;
|
||||
mpe->mpe_range_list = range_list;
|
||||
smp_add_mpe_entry(mc, (mpe_t)mpe);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* memcpy standard block */
|
||||
const static char smpblock[] =
|
||||
{0x5F, 0x4D, 0x50, 0x5F, 0x00, 0x00, 0x00,
|
||||
0x00, 0x01, 0x04, 0x9B, 0x05, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
void write_smp_table(void *v)
|
||||
{
|
||||
memcpy(v, smpblock, sizeof(smpblock));
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
#endif /* HAVE_MP_TABLE */
|
||||
194
src/arch/i386/smp/start_stop.c
Normal file
194
src/arch/i386/smp/start_stop.c
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
#include <smp/start_stop.h>
|
||||
#include <cpu/p6/apic.h>
|
||||
#include <delay.h>
|
||||
|
||||
static inline void hlt(void)
|
||||
{
|
||||
asm("hlt");
|
||||
return;
|
||||
}
|
||||
|
||||
int this_processors_id(void)
|
||||
{
|
||||
return apic_read(APIC_ID) >> 24;
|
||||
}
|
||||
|
||||
void stop_cpu(int apicid)
|
||||
{
|
||||
int timeout;
|
||||
unsigned long send_status;
|
||||
|
||||
/* send an APIC INIT to myself */
|
||||
apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
|
||||
apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT);
|
||||
|
||||
/* wait for the ipi send to finish */
|
||||
printk_spew("Waiting for send to finish...\n");
|
||||
timeout = 0;
|
||||
do {
|
||||
printk_spew("+");
|
||||
udelay(100);
|
||||
send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
|
||||
} while (send_status && (timeout++ < 1000));
|
||||
if (timeout >= 1000) {
|
||||
printk_spew("timed out\n");
|
||||
}
|
||||
mdelay(10);
|
||||
|
||||
printk_spew("Deasserting INIT.\n");
|
||||
/* Deassert the APIC INIT */
|
||||
apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
|
||||
apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
|
||||
|
||||
printk_spew("Waiting for send to finish...\n");
|
||||
timeout = 0;
|
||||
do {
|
||||
printk_spew("+");
|
||||
udelay(100);
|
||||
send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
|
||||
} while (send_status && (timeout++ < 1000));
|
||||
if (timeout >= 1000) {
|
||||
printk_debug("timed out\n");
|
||||
}
|
||||
|
||||
while(1) {
|
||||
hlt();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void start_cpu(int apicid)
|
||||
{
|
||||
int timeout;
|
||||
unsigned long send_status, accept_status, start_eip;
|
||||
int j, num_starts, maxlvt;
|
||||
/*
|
||||
* Starting actual IPI sequence...
|
||||
*/
|
||||
|
||||
printk_spew("Asserting INIT.\n");
|
||||
|
||||
/*
|
||||
* Turn INIT on target chip
|
||||
*/
|
||||
apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
|
||||
|
||||
/*
|
||||
* Send IPI
|
||||
*/
|
||||
apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
|
||||
| APIC_DM_INIT);
|
||||
|
||||
printk_spew("Waiting for send to finish...\n");
|
||||
timeout = 0;
|
||||
do {
|
||||
printk_spew("+");
|
||||
udelay(100);
|
||||
send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
|
||||
} while (send_status && (timeout++ < 1000));
|
||||
if (timeout >= 1000) {
|
||||
printk_spew("timed out\n");
|
||||
}
|
||||
|
||||
mdelay(10);
|
||||
|
||||
printk_spew("Deasserting INIT.\n");
|
||||
|
||||
/* Target chip */
|
||||
apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
|
||||
|
||||
/* Send IPI */
|
||||
apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
|
||||
|
||||
printk_spew("Waiting for send to finish...\n");
|
||||
timeout = 0;
|
||||
do {
|
||||
printk_spew("+");
|
||||
udelay(100);
|
||||
send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
|
||||
} while (send_status && (timeout++ < 1000));
|
||||
if (timeout >= 1000) {
|
||||
printk_spew("timed out\n");
|
||||
}
|
||||
|
||||
/* FIXME start_eip should be more flexible! */
|
||||
start_eip = 0xf0000;
|
||||
printk_spew("start eip=0x%08lx\n", start_eip);
|
||||
|
||||
num_starts = 2;
|
||||
|
||||
/*
|
||||
* Run STARTUP IPI loop.
|
||||
*/
|
||||
printk_spew("#startup loops: %d.\n", num_starts);
|
||||
|
||||
maxlvt = 4;
|
||||
|
||||
for (j = 1; j <= num_starts; j++) {
|
||||
printk_spew("Sending STARTUP #%d.\n",j);
|
||||
apic_read_around(APIC_SPIV);
|
||||
apic_write(APIC_ESR, 0);
|
||||
apic_read(APIC_ESR);
|
||||
printk_spew("After apic_write.\n");
|
||||
|
||||
/*
|
||||
* STARTUP IPI
|
||||
*/
|
||||
|
||||
/* Target chip */
|
||||
apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
|
||||
|
||||
/* Boot on the stack */
|
||||
/* Kick the second */
|
||||
apic_write_around(APIC_ICR, APIC_DM_STARTUP
|
||||
| (start_eip >> 12));
|
||||
|
||||
/*
|
||||
* Give the other CPU some time to accept the IPI.
|
||||
*/
|
||||
udelay(300);
|
||||
|
||||
printk_spew("Startup point 1.\n");
|
||||
|
||||
printk_spew("Waiting for send to finish...\n");
|
||||
timeout = 0;
|
||||
do {
|
||||
printk_spew("+");
|
||||
udelay(100);
|
||||
send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
|
||||
} while (send_status && (timeout++ < 1000));
|
||||
|
||||
/*
|
||||
* Give the other CPU some time to accept the IPI.
|
||||
*/
|
||||
udelay(200);
|
||||
/*
|
||||
* Due to the Pentium erratum 3AP.
|
||||
*/
|
||||
if (maxlvt > 3) {
|
||||
apic_read_around(APIC_SPIV);
|
||||
apic_write(APIC_ESR, 0);
|
||||
}
|
||||
accept_status = (apic_read(APIC_ESR) & 0xEF);
|
||||
if (send_status || accept_status)
|
||||
break;
|
||||
}
|
||||
printk_spew("After Startup.\n");
|
||||
if (send_status)
|
||||
printk_warning("APIC never delivered???\n");
|
||||
if (accept_status)
|
||||
printk_warning("APIC delivery error (%lx).\n", accept_status);
|
||||
}
|
||||
|
||||
void startup_other_cpus(void)
|
||||
{
|
||||
int apicid = this_processors_id();
|
||||
int i;
|
||||
/* Assume the cpus are densly packed by apicid */
|
||||
for(i = 0; i < MAX_CPUS; i++) {
|
||||
if (i == apicid ) {
|
||||
continue;
|
||||
}
|
||||
start_cpu(i);
|
||||
}
|
||||
}
|
||||
91
src/cpu/k7/earlymtrr.inc
Normal file
91
src/cpu/k7/earlymtrr.inc
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
#include <cpu/k7/mtrr.h>
|
||||
|
||||
/* The fixed and variable MTRRs are powered-up with random values, clear them to
|
||||
* MTRR_TYPE_UNCACHABLE for safty reason
|
||||
*/
|
||||
|
||||
|
||||
earlymtrr_start:
|
||||
xorl %eax, %eax # clear %eax and %edx
|
||||
xorl %edx, %edx #
|
||||
movl $fixed_mtrr_msr, %esi
|
||||
|
||||
clear_fixed_var_mtrr:
|
||||
lodsl (%esi), %eax
|
||||
testl %eax, %eax
|
||||
jz clear_fixed_var_mtrr_out
|
||||
|
||||
movl %eax, %ecx
|
||||
xorl %eax, %eax
|
||||
wrmsr
|
||||
|
||||
jmp clear_fixed_var_mtrr
|
||||
clear_fixed_var_mtrr_out:
|
||||
|
||||
|
||||
set_var_mtrr:
|
||||
/* enable caching for 0 - 128MB using variable mtrr */
|
||||
movl $0x200, %ecx
|
||||
rdmsr
|
||||
andl $0xfffffff0, %edx
|
||||
orl $0x00000000, %edx
|
||||
andl $0x00000f00, %eax
|
||||
orl $0x00000006, %eax
|
||||
wrmsr
|
||||
|
||||
movl $0x201, %ecx
|
||||
rdmsr
|
||||
andl $0xfffffff0, %edx
|
||||
orl $0x0000000f, %edx
|
||||
andl $0x000007ff, %eax
|
||||
orl $0xf0000800, %eax
|
||||
wrmsr
|
||||
|
||||
#if defined(XIP_ROM_SIZE) && defined(XIP_ROM_BASE)
|
||||
/* enable write protect caching so we can do execute in place
|
||||
* on the flash rom.
|
||||
*/
|
||||
movl $0x202, %ecx
|
||||
xorl %edx, %edx
|
||||
movl $(XIP_ROM_BASE | 0x005), %eax
|
||||
wrmsr
|
||||
|
||||
movl $0x203, %ecx
|
||||
movl $0x0000000f, %edx
|
||||
movl $(~(XIP_ROM_SIZE - 1) | 0x800), %eax
|
||||
wrmsr
|
||||
#endif /* XIP_ROM_SIZE && XIP_ROM_BASE */
|
||||
|
||||
enable_mtrr:
|
||||
/* Set the default memory type and enable fixed and variable MTRRs */
|
||||
movl $0x2ff, %ecx
|
||||
xorl %edx, %edx
|
||||
/* Enable Variable MTRRs */
|
||||
movl $0x00000800, %eax
|
||||
wrmsr
|
||||
|
||||
/* Enable the MTRRs in SYSCFG */
|
||||
#if USE_AMD_NDA_CODE
|
||||
#endif /* USE_AMD_NDA_CODE */
|
||||
|
||||
/* enable cache */
|
||||
movl %cr0, %eax
|
||||
andl $0x9fffffff,%eax
|
||||
movl %eax, %cr0
|
||||
|
||||
jmp earlymtrr_end
|
||||
|
||||
fixed_mtrr_msr:
|
||||
.long 0x250, 0x258, 0x259
|
||||
.long 0x268, 0x269, 0x26A
|
||||
.long 0x26B, 0x26C, 0x26D
|
||||
.long 0x26E, 0x26F
|
||||
var_mtrr_msr:
|
||||
.long 0x200, 0x201, 0x202, 0x203
|
||||
.long 0x204, 0x205, 0x206, 0x207
|
||||
.long 0x208, 0x209, 0x20A, 0x20B
|
||||
.long 0x20C, 0x20D, 0x20E, 0x20F
|
||||
#if USE_AMD_NDA_CODE
|
||||
#endif /* USE_AMD_NDA_CODE */
|
||||
.long 0x000 /* NULL, end of table */
|
||||
earlymtrr_end:
|
||||
17
src/include/cpu/cpufixup.h
Normal file
17
src/include/cpu/cpufixup.h
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef CPU_CPUFIXUP_H
|
||||
#define CPU_CPUFIXUP_H
|
||||
|
||||
#include <cpu/k7/cpufixup.h>
|
||||
#include <cpu/p6/cpufixup.h>
|
||||
|
||||
#ifdef CPU_FIXUP
|
||||
# if defined(k7)
|
||||
# define cpufixup(totalram) k7_cpufixup(totalram)
|
||||
# elif defined(i686)
|
||||
# define cpufixup(totalram) p6_cpufixup(totalram)
|
||||
# endif
|
||||
#else
|
||||
# define cpu_fixup(totalram) do {} while(0)
|
||||
#endif
|
||||
|
||||
#endif /* CPU_CPUFIXUP_H */
|
||||
6
src/include/cpu/k7/cpufixup.h
Normal file
6
src/include/cpu/k7/cpufixup.h
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef CPU_K7_CPUFIXUP_H
|
||||
#define CPU_K7_CPUFIXUP_H
|
||||
|
||||
void k7_cpufixup(unsigned long totalram);
|
||||
|
||||
#endif /* CPU_K7_CPUFIXUP_H */
|
||||
9
src/include/cpu/k7/mtrr.h
Normal file
9
src/include/cpu/k7/mtrr.h
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef CPU_K7_MTRR_H
|
||||
#define CPU_K7_MTRR_H
|
||||
|
||||
#include <cpu/p6/mtrr.h>
|
||||
|
||||
# if USE_AMD_NDA_CODE
|
||||
# endif /* USE_AMD_NDA_CODE */
|
||||
|
||||
#endif /* CPU_K7_MTRR_H */
|
||||
14
src/include/cpu/l2_cache.h
Normal file
14
src/include/cpu/l2_cache.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef CPU_L2_CACHE_H
|
||||
#define CPU_L2_CACHE_H
|
||||
|
||||
#include <cpu/p6/l2_cache.h>
|
||||
|
||||
#ifdef CONFIGURE_L2_CACHE
|
||||
# if defined(i686)
|
||||
# define configure_l2_cache() p6_configure_l2_cache()
|
||||
# endif
|
||||
#else
|
||||
# define configure_l2_cache() do {} while(0)
|
||||
#endif
|
||||
|
||||
#endif /* CPU_L2_CACHE_H */
|
||||
176
src/include/cpu/p6/apic.h
Normal file
176
src/include/cpu/p6/apic.h
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
#ifndef APIC_H
|
||||
#define APIC_H
|
||||
|
||||
#define APIC_BASE_MSR 0x1B
|
||||
#define APIC_BASE_MSR_BOOTSTRAP_PROCESSOR (1 << 8)
|
||||
#define APIC_BASE_MSR_ENABLE (1 << 11)
|
||||
#define APIC_BASE_MSR_ADDR_MASK 0xFFFFF000
|
||||
|
||||
#define APIC_DEFAULT_BASE 0xfee00000
|
||||
|
||||
#define APIC_ID 0x020
|
||||
#define APIC_LVR 0x030
|
||||
#define APIC_ARBID 0x090
|
||||
#define APIC_RRR 0x0C0
|
||||
#define APIC_SVR 0x0f0
|
||||
#define APIC_SPIV 0x0f0
|
||||
#define APIC_SPIV_ENABLE 0x100
|
||||
#define APIC_ESR 0x280
|
||||
#define APIC_ESR_SEND_CS 0x00001
|
||||
#define APIC_ESR_RECV_CS 0x00002
|
||||
#define APIC_ESR_SEND_ACC 0x00004
|
||||
#define APIC_ESR_RECV_ACC 0x00008
|
||||
#define APIC_ESR_SENDILL 0x00020
|
||||
#define APIC_ESR_RECVILL 0x00040
|
||||
#define APIC_ESR_ILLREGA 0x00080
|
||||
#define APIC_ICR 0x300
|
||||
#define APIC_DEST_SELF 0x40000
|
||||
#define APIC_DEST_ALLINC 0x80000
|
||||
#define APIC_DEST_ALLBUT 0xC0000
|
||||
#define APIC_ICR_RR_MASK 0x30000
|
||||
#define APIC_ICR_RR_INVALID 0x00000
|
||||
#define APIC_ICR_RR_INPROG 0x10000
|
||||
#define APIC_ICR_RR_VALID 0x20000
|
||||
#define APIC_INT_LEVELTRIG 0x08000
|
||||
#define APIC_INT_ASSERT 0x04000
|
||||
#define APIC_ICR_BUSY 0x01000
|
||||
#define APIC_DEST_LOGICAL 0x00800
|
||||
#define APIC_DM_FIXED 0x00000
|
||||
#define APIC_DM_LOWEST 0x00100
|
||||
#define APIC_DM_SMI 0x00200
|
||||
#define APIC_DM_REMRD 0x00300
|
||||
#define APIC_DM_NMI 0x00400
|
||||
#define APIC_DM_INIT 0x00500
|
||||
#define APIC_DM_STARTUP 0x00600
|
||||
#define APIC_DM_EXTINT 0x00700
|
||||
#define APIC_VECTOR_MASK 0x000FF
|
||||
#define APIC_ICR2 0x310
|
||||
#define GET_APIC_DEST_FIELD(x) (((x)>>24)&0xFF)
|
||||
#define SET_APIC_DEST_FIELD(x) ((x)<<24)
|
||||
#define APIC_LVTT 0x320
|
||||
#define APIC_LVTPC 0x340
|
||||
#define APIC_LVT0 0x350
|
||||
#define APIC_LVT_TIMER_BASE_MASK (0x3<<18)
|
||||
#define GET_APIC_TIMER_BASE(x) (((x)>>18)&0x3)
|
||||
#define SET_APIC_TIMER_BASE(x) (((x)<<18))
|
||||
#define APIC_TIMER_BASE_CLKIN 0x0
|
||||
#define APIC_TIMER_BASE_TMBASE 0x1
|
||||
#define APIC_TIMER_BASE_DIV 0x2
|
||||
#define APIC_LVT_TIMER_PERIODIC (1<<17)
|
||||
#define APIC_LVT_MASKED (1<<16)
|
||||
#define APIC_LVT_LEVEL_TRIGGER (1<<15)
|
||||
#define APIC_LVT_REMOTE_IRR (1<<14)
|
||||
#define APIC_INPUT_POLARITY (1<<13)
|
||||
#define APIC_SEND_PENDING (1<<12)
|
||||
#define APIC_LVT_RESERVED_1 (1<<11)
|
||||
#define APIC_DELIVERY_MODE_MASK (7<<8)
|
||||
#define APIC_DELIVERY_MODE_FIXED (0<<8)
|
||||
#define APIC_DELIVERY_MODE_NMI (4<<8)
|
||||
#define APIC_DELIVERY_MODE_EXTINT (7<<8)
|
||||
#define GET_APIC_DELIVERY_MODE(x) (((x)>>8)&0x7)
|
||||
#define SET_APIC_DELIVERY_MODE(x,y) (((x)&~0x700)|((y)<<8))
|
||||
#define APIC_MODE_FIXED 0x0
|
||||
#define APIC_MODE_NMI 0x4
|
||||
#define APIC_MODE_EXINT 0x7
|
||||
#define APIC_LVT1 0x360
|
||||
#define APIC_LVTERR 0x370
|
||||
|
||||
|
||||
#if !defined(ASSEMBLY)
|
||||
|
||||
#include <printk.h>
|
||||
|
||||
|
||||
#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
|
||||
|
||||
struct __xchg_dummy { unsigned long a[100]; };
|
||||
#define __xg(x) ((struct __xchg_dummy *)(x))
|
||||
|
||||
/*
|
||||
* Note: no "lock" prefix even on SMP: xchg always implies lock anyway
|
||||
* Note 2: xchg has side effect, so that attribute volatile is necessary,
|
||||
* but generally the primitive is invalid, *ptr is output argument. --ANK
|
||||
*/
|
||||
static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
|
||||
{
|
||||
switch (size) {
|
||||
case 1:
|
||||
__asm__ __volatile__("xchgb %b0,%1"
|
||||
:"=q" (x)
|
||||
:"m" (*__xg(ptr)), "0" (x)
|
||||
:"memory");
|
||||
break;
|
||||
case 2:
|
||||
__asm__ __volatile__("xchgw %w0,%1"
|
||||
:"=r" (x)
|
||||
:"m" (*__xg(ptr)), "0" (x)
|
||||
:"memory");
|
||||
break;
|
||||
case 4:
|
||||
__asm__ __volatile__("xchgl %0,%1"
|
||||
:"=r" (x)
|
||||
:"m" (*__xg(ptr)), "0" (x)
|
||||
:"memory");
|
||||
break;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
static inline unsigned long apic_read(unsigned long reg)
|
||||
{
|
||||
return *((volatile unsigned long *)(APIC_DEFAULT_BASE+reg));
|
||||
}
|
||||
|
||||
extern inline void apic_write_atomic(unsigned long reg, unsigned long v)
|
||||
{
|
||||
xchg((volatile unsigned long *)(APIC_DEFAULT_BASE+reg), v);
|
||||
}
|
||||
|
||||
static inline void apic_write(unsigned long reg, unsigned long v)
|
||||
{
|
||||
*((volatile unsigned long *)(APIC_DEFAULT_BASE+reg)) = v;
|
||||
}
|
||||
|
||||
static inline void apic_wait_icr_idle(void)
|
||||
{
|
||||
do { } while ( apic_read( APIC_ICR ) & APIC_ICR_BUSY );
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_GOOD_APIC
|
||||
# define FORCE_READ_AROUND_WRITE 0
|
||||
# define apic_read_around(x)
|
||||
# define apic_write_around(x,y) apic_write((x),(y))
|
||||
#else
|
||||
# define FORCE_READ_AROUND_WRITE 1
|
||||
# define apic_read_around(x) apic_read(x)
|
||||
# define apic_write_around(x,y) apic_write_atomic((x),(y))
|
||||
#endif
|
||||
|
||||
static inline unsigned long apic_remote_read(int apicid, int reg)
|
||||
{
|
||||
int timeout;
|
||||
unsigned long status, result;
|
||||
apic_wait_icr_idle();
|
||||
apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
|
||||
apic_write_around(APIC_ICR, APIC_DM_REMRD | (reg >> 4));
|
||||
timeout = 0;
|
||||
do {
|
||||
#if 0
|
||||
udelay(100);
|
||||
#endif
|
||||
status = apic_read(APIC_ICR) & APIC_ICR_RR_MASK;
|
||||
} while (status == APIC_ICR_RR_INPROG && timeout++ < 1000);
|
||||
|
||||
result = -1;
|
||||
if (status == APIC_ICR_RR_VALID) {
|
||||
result = apic_read(APIC_RRR);
|
||||
}
|
||||
else {
|
||||
printk_err("remote apic read failed\n");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif /* ASSEMBLY */
|
||||
|
||||
#endif /* APIC_H */
|
||||
10
src/include/cpu/p6/cpufixup.h
Normal file
10
src/include/cpu/p6/cpufixup.h
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef CPU_P6_CPUFIXUP_H
|
||||
#define CPU_P6_CPUFIXUP_H
|
||||
|
||||
#ifdef UPDATE_MICROCODE
|
||||
#define CPU_FIXUP
|
||||
#endif
|
||||
|
||||
void p6_cpufixup(unsigned long totalram);
|
||||
|
||||
#endif /* CPU_P6_CPUFIXUP_H */
|
||||
7
src/include/delay.h
Normal file
7
src/include/delay.h
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef DELAY_H
|
||||
#define DELAY_H
|
||||
|
||||
void udelay(int usecs);
|
||||
void mdelay(int msecs);
|
||||
|
||||
#endif /* DELAY_H */
|
||||
10
src/include/part/floppy.h
Normal file
10
src/include/part/floppy.h
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef PART_FLOPPY_H
|
||||
#define PART_FLOPPY_H
|
||||
|
||||
#ifdef MUST_ENABLE_FLOPPY
|
||||
void enable_floppy(void);
|
||||
#else
|
||||
# define enable_floppy() do {} while(0)
|
||||
#endif
|
||||
|
||||
#endif /* PART_FLOPPY_H */
|
||||
10
src/include/part/framebuffer.h
Normal file
10
src/include/part/framebuffer.h
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef PART_FRAMEBUFFER_H
|
||||
#define PART_FRAMEBUFFER_H
|
||||
|
||||
#ifdef HAVE_FRAMEBUFFER
|
||||
void framebuffer_on(void)
|
||||
#else
|
||||
# define framebuffer_on() do {} while(0)
|
||||
#endif /* HAVE_FRAMEBUFFER */
|
||||
|
||||
#endif /* PART_FRAMEBUFFER_H */
|
||||
11
src/include/part/hard_reset.h
Normal file
11
src/include/part/hard_reset.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef PART_HARD_RESET_H
|
||||
#define PART_HARD_RESET_H
|
||||
|
||||
#ifdef HAVE_HARD_RESET
|
||||
void hard_reset(void);
|
||||
#else
|
||||
#define hard_reset() do {} while(0)
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
10
src/include/part/keyboard.h
Normal file
10
src/include/part/keyboard.h
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef PART_KEYBOARD_H
|
||||
#define KEYBOARD_H
|
||||
|
||||
#ifndef NO_KEYBOARD
|
||||
void keyboard_on(void);
|
||||
#else
|
||||
# define keyboard_on() do {} while(0)
|
||||
#endif
|
||||
|
||||
#endif /* PART_KEYBOARD_H */
|
||||
12
src/include/part/mainboard.h
Normal file
12
src/include/part/mainboard.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef PART_MAINBOARD_H
|
||||
#define PART_MAINBOARD_H
|
||||
|
||||
void mainboard_fixup(void);
|
||||
|
||||
#ifdef FINAL_MAINBOARD_FIXUP
|
||||
void final_mainboard_fixup(void);
|
||||
#else
|
||||
# define final_mainboard_fixup() do {} while(0)
|
||||
#endif /* FINAL_MAINBOARD_FIXUP */
|
||||
|
||||
#endif /* PART_MAINBOARD_H */
|
||||
7
src/include/part/nvram.h
Normal file
7
src/include/part/nvram.h
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef PART_NVRAM_H
|
||||
#define PART_NVRAM_H
|
||||
|
||||
/* Turn on full access to the flash chip */
|
||||
void nvram_on(void);
|
||||
|
||||
#endif /* PART_NVRAM_H */
|
||||
6
src/include/part/sizeram.h
Normal file
6
src/include/part/sizeram.h
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef PART_SIZERAM_H
|
||||
#define PART_SIZERAM_H
|
||||
|
||||
unsigned long sizeram(void);
|
||||
|
||||
#endif /* PART_SIZERAM_H */
|
||||
11
src/include/pc80/i8259.h
Normal file
11
src/include/pc80/i8259.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef PC80_I8259
|
||||
#define PC80_I8259
|
||||
|
||||
|
||||
#ifdef I8259
|
||||
void setup_i8259(void);
|
||||
#else
|
||||
#define setup_i8259() do {} while(0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -1 +1,6 @@
|
|||
#ifndef PC80_KEYBOARD_H
|
||||
#define PC80_KEYBOARD_H
|
||||
|
||||
void pc_keyboard_init(void);
|
||||
|
||||
#endif /* PC80_KEYBOARD_H */
|
||||
|
|
|
|||
53
src/include/smp/atomic.h
Normal file
53
src/include/smp/atomic.h
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
#ifndef SMP_ATOMIC_H
|
||||
#define SMP_ATOMIC_H
|
||||
|
||||
#ifdef SMP
|
||||
#include <arch/smp/atomic.h>
|
||||
#else
|
||||
|
||||
typedef struct { int counter } atomic_t;
|
||||
#define ATOMIC_INIT(i) { (i) }
|
||||
|
||||
/**
|
||||
* atomic_read - read atomic variable
|
||||
* @v: pointer of type atomic_t
|
||||
*
|
||||
* Atomically reads the value of @v. Note that the guaranteed
|
||||
* useful range of an atomic_t is only 24 bits.
|
||||
*/
|
||||
#define atomic_read(v) ((v)->counter)
|
||||
|
||||
/**
|
||||
* atomic_set - set atomic variable
|
||||
* @v: pointer of type atomic_t
|
||||
* @i: required value
|
||||
*
|
||||
* Atomically sets the value of @v to @i. Note that the guaranteed
|
||||
* useful range of an atomic_t is only 24 bits.
|
||||
*/
|
||||
#define atomic_set(v,i) (((v)->counter) = (i))
|
||||
|
||||
|
||||
/**
|
||||
* atomic_inc - increment atomic variable
|
||||
* @v: pointer of type atomic_t
|
||||
*
|
||||
* Atomically increments @v by 1. Note that the guaranteed
|
||||
* useful range of an atomic_t is only 24 bits.
|
||||
*/
|
||||
#define atomic_inc(v) (((v)->counter)++)
|
||||
|
||||
|
||||
/**
|
||||
* atomic_dec - decrement atomic variable
|
||||
* @v: pointer of type atomic_t
|
||||
*
|
||||
* Atomically decrements @v by 1. Note that the guaranteed
|
||||
* useful range of an atomic_t is only 24 bits.
|
||||
*/
|
||||
#define atomic_inc(v) (((v)->counter)--)
|
||||
|
||||
|
||||
#endif /* SMP */
|
||||
|
||||
#endif /* SMP_ATOMIC_H */
|
||||
24
src/include/smp/spinlock.h
Normal file
24
src/include/smp/spinlock.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef SMP_SPINLOCK_H
|
||||
#define SMP_SPINLOCK_H
|
||||
|
||||
#ifdef SMP
|
||||
#include <arch/smp/spinlock.h>
|
||||
#else /* !SMP */
|
||||
|
||||
/* Most GCC versions have a nasty bug with empty initializers */
|
||||
#if (__GNUC__ > 2)
|
||||
typedef struct { } spinlock_t;
|
||||
#define SPIN_LOCK_UNLOCKED (spinlock_t) { }
|
||||
#else
|
||||
typedef struct { int gcc_is_buggy; } spinlock_t;
|
||||
#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
|
||||
#endif
|
||||
|
||||
#define barrier() do {} while(0)
|
||||
#define spin_is_locked(lock) 0
|
||||
#define spin_unlock_wait(lock) do {} while(0)
|
||||
#define spin_lock(lock) do {} while(0)
|
||||
#define spin_unlock(lock) do {} while(0)
|
||||
#endif
|
||||
|
||||
#endif /* SMP_SPINLOCK_H */
|
||||
15
src/include/smp/start_stop.h
Normal file
15
src/include/smp/start_stop.h
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef SMP_START_STOP_H
|
||||
#define SMP_START_STOP_H
|
||||
|
||||
#ifdef SMP
|
||||
#include <smp/atomic.h>
|
||||
int this_processors_id(void);
|
||||
void stop_cpu(int processor_id);
|
||||
void start_cpu(int processor_id);
|
||||
void startup_other_cpus(void);
|
||||
#else
|
||||
#define this_processors_id() 0
|
||||
#define startup_other_cpus() do {} while(0)
|
||||
#endif
|
||||
|
||||
#endif /* SMP_START_STOP_H */
|
||||
63
src/lib/delay.c
Normal file
63
src/lib/delay.c
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
#include <delay.h>
|
||||
#include <arch/io.h>
|
||||
|
||||
/* Ports for the 8254 timer chip */
|
||||
#define TIMER2_PORT 0x42
|
||||
#define TIMER_MODE_PORT 0x43
|
||||
|
||||
/* Meaning of the mode bits */
|
||||
#define TIMER0_SEL 0x00
|
||||
#define TIMER1_SEL 0x40
|
||||
#define TIMER2_SEL 0x80
|
||||
#define READBACK_SEL 0xC0
|
||||
|
||||
#define LATCH_COUNT 0x00
|
||||
#define LOBYTE_ACCESS 0x10
|
||||
#define HIBYTE_ACCESS 0x20
|
||||
#define WORD_ACCESS 0x30
|
||||
|
||||
#define MODE0 0x00
|
||||
#define MODE1 0x02
|
||||
#define MODE2 0x04
|
||||
#define MODE3 0x06
|
||||
#define MODE4 0x08
|
||||
#define MODE5 0x0A
|
||||
|
||||
#define BINARY_COUNT 0x00
|
||||
#define BCD_COUNT 0x01
|
||||
|
||||
/* Timers tick over at this rate */
|
||||
#define TICKS_PER_MS 1193
|
||||
|
||||
/* Parallel Peripheral Controller Port B */
|
||||
#define PPC_PORTB 0x61
|
||||
|
||||
/* Meaning of the port bits */
|
||||
#define PPCB_T2OUT 0x20 /* Bit 5 */
|
||||
#define PPCB_SPKR 0x02 /* Bit 1 */
|
||||
#define PPCB_T2GATE 0x01 /* Bit 0 */
|
||||
|
||||
|
||||
static void load_timer2(unsigned int ticks)
|
||||
{
|
||||
/* Set up the timer gate, turn off the speaker */
|
||||
outb((inb(PPC_PORTB) & ~PPCB_SPKR) | PPCB_T2GATE, PPC_PORTB);
|
||||
outb(TIMER2_SEL|WORD_ACCESS|MODE0|BINARY_COUNT, TIMER_MODE_PORT);
|
||||
outb(ticks & 0xFF, TIMER2_PORT);
|
||||
outb(ticks >> 8, TIMER2_PORT);
|
||||
}
|
||||
|
||||
|
||||
void udelay(int usecs)
|
||||
{
|
||||
load_timer2((usecs*TICKS_PER_MS)/1000);
|
||||
while ((inb(PPC_PORTB) & PPCB_T2OUT) == 0)
|
||||
;
|
||||
}
|
||||
void mdelay(int msecs)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < msecs; i++) {
|
||||
udelay(1000);
|
||||
}
|
||||
}
|
||||
137
src/mainboard/intel/l440gx/mptable.c
Normal file
137
src/mainboard/intel/l440gx/mptable.c
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
#include <cpu/p6/mpspec.h>
|
||||
#include <string.h>
|
||||
|
||||
void smp_write_config_table(void *v)
|
||||
{
|
||||
int ioapicid = 0; // JAMES_HACK
|
||||
static const char sig[4] = "PCMP";
|
||||
static const char oem[8] = "LNXI ";
|
||||
static const char productid[12] = "L440GX ";
|
||||
struct mp_config_table *mc;
|
||||
|
||||
mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN);
|
||||
memset(mc, 0, sizeof(*mc));
|
||||
|
||||
memcpy(mc->mpc_signature, sig, sizeof(sig));
|
||||
mc->mpc_length = sizeof(*mc); /* initially just the header */
|
||||
mc->mpc_spec = 0x04;
|
||||
mc->mpc_checksum = 0; /* not yet computed */
|
||||
memcpy(mc->mpc_oem, oem, sizeof(oem));
|
||||
memcpy(mc->mpc_productid, productid, sizeof(productid));
|
||||
mc->mpc_oemptr = 0;
|
||||
mc->mpc_oemsize = 0;
|
||||
mc->mpc_entry_count = 0; /* No entries yet... */
|
||||
mc->mpc_lapic = LAPIC_ADDR;
|
||||
mc->mpe_length = 0;
|
||||
mc->mpe_checksum = 0;
|
||||
mc->reserved = 0;
|
||||
|
||||
#ifndef JAMES_HACK
|
||||
smp_write_processor(mc, 0x01, 0x11,
|
||||
CPU_ENABLED | CPU_BOOTPROCESSOR, 0x00000683, 0x0387fbff);
|
||||
#else
|
||||
printk("James: Setting up 2 proc. SMP table");
|
||||
|
||||
smp_write_processor(mc, 0x1, 0x11,
|
||||
CPU_ENABLED | CPU_BOOTPROCESSOR, 0x00000683, 0x0387fbff);
|
||||
smp_write_processor(mc, 0x0, 0x11,
|
||||
CPU_ENABLED, 0x00000683, 0x0387fbff);
|
||||
ioapicid = 2;
|
||||
#endif
|
||||
|
||||
smp_write_bus(mc, 0, "PCI ");
|
||||
smp_write_bus(mc, 1, "PCI ");
|
||||
smp_write_bus(mc, 2, "PCI ");
|
||||
smp_write_bus(mc, 3, "ISA ");
|
||||
|
||||
smp_write_ioapic(mc, ioapicid, 0x11, 0xfec00000);
|
||||
|
||||
/* ISA backward compatibility interrupts */
|
||||
smp_write_intsrc(mc, mp_ExtINT, 0x05, 0x03, 0x00, ioapicid, 0x00);
|
||||
smp_write_intsrc(mc, mp_INT, 0x05, 0x03, 0x01, ioapicid, 0x01);
|
||||
smp_write_intsrc(mc, mp_INT, 0x05, 0x03, 0x00, ioapicid, 0x02);
|
||||
smp_write_intsrc(mc, mp_INT, 0x05, 0x03, 0x03, ioapicid, 0x03);
|
||||
smp_write_intsrc(mc, mp_INT, 0x05, 0x03, 0x04, ioapicid, 0x03);
|
||||
smp_write_intsrc(mc, mp_INT, 0x05, 0x03, 0x04, ioapicid, 0x04);
|
||||
smp_write_intsrc(mc, mp_INT, 0x05, 0x03, 0x06, ioapicid, 0x06);
|
||||
smp_write_intsrc(mc, mp_INT, 0x05, 0x03, 0x07, ioapicid, 0x07);
|
||||
smp_write_intsrc(mc, mp_INT, 0x05, 0x03, 0x08, ioapicid, 0x08);
|
||||
smp_write_intsrc(mc, mp_INT, 0x05, 0x03, 0x0c, ioapicid, 0x0c);
|
||||
smp_write_intsrc(mc, mp_INT, 0x05, 0x03, 0x0d, ioapicid, 0x0d);
|
||||
smp_write_intsrc(mc, mp_INT, 0x05, 0x03, 0x0e, ioapicid, 0x0e);
|
||||
smp_write_intsrc(mc, mp_INT, 0x05, 0x03, 0x0f, ioapicid, 0x0f);
|
||||
|
||||
/* On bus 0 device 1 is the 440GX AGP/PCI bridge to bus 1 */
|
||||
/* On bus 1 device f is a DEC PCI bridge to bus 2 */
|
||||
/* Onboard pci devices */
|
||||
smp_write_intsrc(mc, mp_INT, 0x0f, 0x00, 0x30, ioapicid, 0x13); /* onboard SCSI */
|
||||
smp_write_intsrc(mc, mp_INT, 0x0f, 0x00, 0x38, ioapicid, 0x15); /* onboard NIC */
|
||||
smp_write_intsrc(mc, mp_INT, 0x0f, 0x00, 0x4b, ioapicid, 0x15); /* onboard PIIX4 */
|
||||
|
||||
/* PCI card slots */
|
||||
smp_write_intsrc(mc, mp_INT, 0x0f, 0x02, 0x1c, ioapicid, 0x17); /* slot 6 A */
|
||||
smp_write_intsrc(mc, mp_INT, 0x0f, 0x02, 0x1d, ioapicid, 0x14); /* slot 6 B */
|
||||
smp_write_intsrc(mc, mp_INT, 0x0f, 0x02, 0x1e, ioapicid, 0x15); /* slot 6 C */
|
||||
smp_write_intsrc(mc, mp_INT, 0x0f, 0x02, 0x1f, ioapicid, 0x16); /* slot 6 D */
|
||||
|
||||
smp_write_intsrc(mc, mp_INT, 0x0f, 0x02, 0x10, ioapicid, 0x14); /* slot 5 A */
|
||||
smp_write_intsrc(mc, mp_INT, 0x0f, 0x02, 0x11, ioapicid, 0x15); /* slot 5 B */
|
||||
smp_write_intsrc(mc, mp_INT, 0x0f, 0x02, 0x12, ioapicid, 0x16); /* slot 5 C */
|
||||
smp_write_intsrc(mc, mp_INT, 0x0f, 0x02, 0x13, ioapicid, 0x17); /* slot 5 D */
|
||||
/* 64bit slot */
|
||||
smp_write_intsrc(mc, mp_INT, 0x0f, 0x00, 0x24, ioapicid, 0x13); /* slot 4 A */
|
||||
smp_write_intsrc(mc, mp_INT, 0x0f, 0x00, 0x25, ioapicid, 0x15); /* slot 4 B */
|
||||
smp_write_intsrc(mc, mp_INT, 0x0f, 0x00, 0x26, ioapicid, 0x16); /* slot 4 C */
|
||||
smp_write_intsrc(mc, mp_INT, 0x0f, 0x00, 0x27, ioapicid, 0x17); /* slot 4 D */
|
||||
|
||||
smp_write_intsrc(mc, mp_INT, 0x0f, 0x00, 0x2c, ioapicid, 0x12); /* slot 3 A */
|
||||
smp_write_intsrc(mc, mp_INT, 0x0f, 0x00, 0x2d, ioapicid, 0x17); /* slot 3 B */
|
||||
smp_write_intsrc(mc, mp_INT, 0x0f, 0x00, 0x2e, ioapicid, 0x15); /* slot 3 C */
|
||||
smp_write_intsrc(mc, mp_INT, 0x0f, 0x00, 0x2f, ioapicid, 0x16); /* slot 3 D */
|
||||
|
||||
smp_write_intsrc(mc, mp_INT, 0x0f, 0x00, 0x34, ioapicid, 0x11); /* slot 2 A */
|
||||
smp_write_intsrc(mc, mp_INT, 0x0f, 0x00, 0x35, ioapicid, 0x16); /* slot 2 B */
|
||||
smp_write_intsrc(mc, mp_INT, 0x0f, 0x00, 0x36, ioapicid, 0x17); /* slot 2 C */
|
||||
smp_write_intsrc(mc, mp_INT, 0x0f, 0x00, 0x37, ioapicid, 0x15); /* slot 2 D */
|
||||
|
||||
/* If this slot hadn't been removed I'd know it's PCI address,
|
||||
* I'm guessing it's slot 0x0f (i.e. 0x3c >> 2) but I haven't
|
||||
* confirmed that.
|
||||
*/
|
||||
/* Slot one is the slot farthest from the processor */
|
||||
smp_write_intsrc(mc, mp_INT, 0x0f, 0x00, 0x3c, ioapicid, 0x10); /* slot 1 A */
|
||||
smp_write_intsrc(mc, mp_INT, 0x0f, 0x00, 0x3d, ioapicid, 0x15); /* slot 1 B */
|
||||
smp_write_intsrc(mc, mp_INT, 0x0f, 0x00, 0x3e, ioapicid, 0x16); /* slot 1 C */
|
||||
smp_write_intsrc(mc, mp_INT, 0x0f, 0x00, 0x3f, ioapicid, 0x17); /* slot 1 D */
|
||||
|
||||
/* Standard local interrupt assignments */
|
||||
smp_write_lintsrc(mc, mp_ExtINT, 0x05, 0x03, 0x00, MP_APIC_ALL, 0x00);
|
||||
smp_write_lintsrc(mc, mp_NMI, 0x05, 0x00, 0x00, MP_APIC_ALL, 0x01);
|
||||
|
||||
/* The following information in the extension section linux doesn't currnetly need
|
||||
* and has just been copied from the bios for now.
|
||||
*/
|
||||
smp_write_address_space(mc, 0x00, ADDRESS_TYPE_IO, 0x00000000, 0, 0x00010000, 0);
|
||||
smp_write_address_space(mc, 0x00, ADDRESS_TYPE_MEM, 0x08000000, 0, 0xee000000, 0);
|
||||
smp_write_address_space(mc, 0x00, ADDRESS_TYPE_PREFETCH, 0xf6000000, 0, 0x06000000, 0);
|
||||
smp_write_address_space(mc, 0x00, ADDRESS_TYPE_MEM, 0xfc000000, 0, 0x02e00000, 0);
|
||||
smp_write_address_space(mc, 0x00, ADDRESS_TYPE_MEM, 0xfef00000, 0, 0x01100000, 0);
|
||||
smp_write_address_space(mc, 0x00, ADDRESS_TYPE_MEM, 0x000a0000, 0, 0x00200000, 0);
|
||||
smp_write_address_space(mc, 0x00, ADDRESS_TYPE_MEM, 0x000d4000, 0, 0x00014000, 0);
|
||||
|
||||
smp_write_bus_hierarchy(mc, 0x03, BUS_SUBTRACTIVE_DECODE, 0x00);
|
||||
|
||||
smp_write_compatibility_address_space(mc, 0x00, ADDRESS_RANGE_ADD, RANGE_LIST_IO_ISA);
|
||||
smp_write_compatibility_address_space(mc, 0x00, ADDRESS_RANGE_ADD, RANGE_LIST_IO_VGA);
|
||||
|
||||
mc->mpe_checksum = smp_compute_checksum(smp_next_mpc_entry(mc), mc->mpe_length);
|
||||
mc->mpc_checksum = smp_compute_checksum(mc, mc->mpc_length);
|
||||
}
|
||||
|
||||
void write_smp_table(void *v)
|
||||
{
|
||||
smp_write_floating_table(v);
|
||||
smp_write_config_table(v);
|
||||
}
|
||||
|
||||
|
||||
55
src/mainboard/tyan/guiness/Config
Normal file
55
src/mainboard/tyan/guiness/Config
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
arch i386
|
||||
mainboardinit northbridge/amd/amd76x/reset_test.inc
|
||||
mainboardinit cpu/k7/earlymtrr.inc
|
||||
mainboardinit northbridge/amd/amd76x/mpinit.inc
|
||||
#mainboardinit southbridge/amd/amd766/disable_watchdog.inc
|
||||
mainboardinit southbridge/amd/amd766/lpc_com1.inc
|
||||
mainboardinit superio/winbond/w83627hf/setup_serial.inc
|
||||
mainboardinit pc80/serial.inc
|
||||
#mainboardinit ram/ramtest.inc
|
||||
#mainboardinit mainboard/tyan/guiness/do_ramtest.inc
|
||||
mainboardinit southbridge/amd/amd766/smbus.inc
|
||||
#mainboardinit sdram/generic_dump_spd.inc
|
||||
|
||||
mainboardinit mainboard/tyan/guiness/mainboard_raminit.inc
|
||||
northbridge amd/amd76x
|
||||
#mainboardinit mainboard/tyan/guiness/do_ramtest.inc
|
||||
#mainboardinit cpu/k7/earlymtrr.inc
|
||||
southbridge amd/amd766
|
||||
|
||||
|
||||
nsuperio winbond/w83627hf com1={1} com2={0} floppy=1 lpt=1
|
||||
|
||||
option RAMTEST=1
|
||||
option NO_KEYBOARD
|
||||
option ENABLE_FIXED_AND_VARIABLE_MTRRS
|
||||
#option FINAL_MAINBOARD_FIXUP
|
||||
|
||||
|
||||
object mainboard.o
|
||||
object mptable.o
|
||||
#object irq_tables.o
|
||||
#keyboard pc80
|
||||
dir ../../../pc80
|
||||
|
||||
option AMD766_DEV=0x3800
|
||||
# FIXME are the SMBUS DIMM locations documented anywhere?
|
||||
option SMBUS_MEM_DEVICE_START=(0xa << 3)
|
||||
option SMBUS_MEM_DEVICE_END=(SMBUS_MEM_DEVICE_START +3)
|
||||
option SMBUS_MEM_DEVICE_INC=1
|
||||
option SIO_BASE=0x2e
|
||||
option SMP=1
|
||||
option IOAPIC=1
|
||||
option USE_AMD_NDA_CODE=1
|
||||
option FINAL_MAINBOARD_FIXUP=1
|
||||
option HAVE_HARD_RESET=1
|
||||
option HAVE_MP_TABLE=1
|
||||
option STACK_SIZE=0x10000
|
||||
option MAX_CPUS=2
|
||||
option XIP_ROM_SIZE=0x8000
|
||||
option XIP_ROM_BASE=0xffff8000
|
||||
nooption MEMORY_HOLE
|
||||
|
||||
cpu p5
|
||||
cpu p6
|
||||
cpu k7
|
||||
28
src/mainboard/tyan/guiness/do_ramtest.inc
Normal file
28
src/mainboard/tyan/guiness/do_ramtest.inc
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#if 0
|
||||
movl $0x000f0000, %eax
|
||||
movl $0x000f1000, %ebx
|
||||
CALLSP(ramtest)
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
movl $0x00100000, %eax
|
||||
movl $0x00180000, %ebx
|
||||
CALLSP(ramtest)
|
||||
|
||||
xorl %eax, %eax
|
||||
movl $0x00080000, %ebx
|
||||
CALLSP(ramtest)
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
|
||||
xorl %eax, %eax
|
||||
movl $0x00001000, %ebx
|
||||
CALLSP(ramtest)
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
movl $0xffe00000, %eax
|
||||
movl $0xfff00000, %ebx
|
||||
CALLSP(ramtest)
|
||||
#endif
|
||||
546
src/mainboard/tyan/guiness/mainboard.c
Normal file
546
src/mainboard/tyan/guiness/mainboard.c
Normal file
|
|
@ -0,0 +1,546 @@
|
|||
#include <pci_ids.h>
|
||||
#include <pci.h>
|
||||
#include <arch/io.h>
|
||||
#include <printk.h>
|
||||
#include <delay.h>
|
||||
#include <part/mainboard.h>
|
||||
#include <part/hard_reset.h>
|
||||
|
||||
static void lpc_routing_fixup(void)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410,0);
|
||||
if (dev != NULL) {
|
||||
#if 0
|
||||
/* Send ACPI, keyboard controller,
|
||||
* FDC2, FDC1, ECP
|
||||
* to the LPC bus
|
||||
*/
|
||||
pci_write_config_byte(dev, 0x51, (1<<7)|(1<<6)|(1<<5)|(1<<4)|(1<<3)|(1));
|
||||
#else
|
||||
/* Send keyboard controller,
|
||||
* FDC1, ECP
|
||||
* to the LPC bus
|
||||
* Send APCI ports 0x62 & 0x66 to the ISA bus
|
||||
*/
|
||||
pci_write_config_byte(dev, 0x51, (0<<7)|(1<<6)|(0<<5)|(1<<4)|(0<<3)|(1));
|
||||
#endif
|
||||
/* Route io for both serial ports to the LPC bus */
|
||||
pci_write_config_byte(dev, 0x52, (1<<7)|(1<<4)|(1<<3)|(0<<0));
|
||||
/* Don't route any audio ports to the LPC bus */
|
||||
pci_write_config_byte(dev, 0x53, (0<<6)|(0<<4)|(0<<3)|(0<<2)|(0<<0));
|
||||
/* Route superio configuration accesses to the LPC bus */
|
||||
pci_write_config_byte(dev, 0x54, (0<<5)|(1<<4)|(0<<2)|(0<<0));
|
||||
/* Don't use LPC decode register 4 */
|
||||
pci_write_config_byte(dev, 0x55, (0<<4)|(0<<0));
|
||||
/* Don't use LPC decode register 5 */
|
||||
pci_write_config_byte(dev, 0x56, (0<<4)|(0<<0));
|
||||
/* Route 512 byte io address range 0x0c00 - 0xc200 the LPC bus */
|
||||
pci_write_config_dword(dev, 0x58, 0x00000c01);
|
||||
/* Route 1MB memory address range 0 - 0 to the LPC bus */
|
||||
pci_write_config_dword(dev, 0x5c, 0x00000000);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void enable_ioapic(void)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410,0);
|
||||
if (dev != NULL) {
|
||||
/* Enable the ioapic */
|
||||
pci_write_config_byte(dev, 0x4b, (0 << 3)|(0 <<2)|(0 << 1)|(1<< 0));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void serial_irq_fixup(void)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, 0);
|
||||
if (dev != NULL) {
|
||||
/* Setup serial irq's for the LPC bus. */
|
||||
pci_write_config_byte(dev, 0x4a, (1<<6)|(0<<2)|(0<<0));
|
||||
}
|
||||
}
|
||||
|
||||
static void mouse_sends_irq12(void)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, 0);
|
||||
if (dev != NULL) {
|
||||
unsigned short word;
|
||||
/* Setup so irq12 is sent by the ps2 mouse port. */
|
||||
pci_read_config_word(dev, 0x46, &word);
|
||||
pci_write_config_word(dev, 0x46, word | (1<<9));
|
||||
}
|
||||
}
|
||||
|
||||
static void disable_watchdog(void)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, 0);
|
||||
if (dev != NULL) {
|
||||
unsigned char byte;
|
||||
/* Disable the watchdog timer */
|
||||
pci_read_config_byte(dev, 0x41, &byte);
|
||||
pci_write_config_byte(dev, 0x41, byte | (1<<6)|(1<<2));
|
||||
}
|
||||
}
|
||||
|
||||
static void enable_reset_port_0xcf9(void)
|
||||
{
|
||||
/* FIXME this code is correct but the bit isn't getting set on my test machine. */
|
||||
struct pci_dev *dev;
|
||||
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, 0);
|
||||
if (dev != NULL) {
|
||||
unsigned char byte;
|
||||
/* Enable reset port 0xcf9 */
|
||||
pci_read_config_byte(dev, 0x41, &byte);
|
||||
pci_write_config_byte(dev, 0x41, byte | (1<<5));
|
||||
}
|
||||
}
|
||||
|
||||
static void enable_port92_reset(void)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, 0);
|
||||
if (dev != NULL) {
|
||||
unsigned char byte;
|
||||
/* Enable reset using port 0x92 */
|
||||
pci_read_config_byte(dev, 0x41, &byte);
|
||||
pci_write_config_byte(dev, 0x41, byte | (1<<5));
|
||||
}
|
||||
}
|
||||
|
||||
static void print_whami(void)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
u32 whami;
|
||||
/* Find out which processor I'm running on, and if it was the boot
|
||||
* procesor so I can verify everything was setup correctly
|
||||
*/
|
||||
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C,0);
|
||||
if (dev != NULL) {
|
||||
pci_read_config_dword(dev, 0x80, &whami);
|
||||
printk_spew("whami = 0x%08lx\n", whami);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define IDE_ERR_ICRC 0x80 /* ATA Ultra DMA bad CRC */
|
||||
#define IDE_ERR_BBK 0x80 /* ATA bad block */
|
||||
#define IDE_ERR_UNC 0x40 /* ATA uncorrected error */
|
||||
#define IDE_ERR_MC 0x20 /* ATA media change */
|
||||
#define IDE_ERR_IDNF 0x10 /* ATA id not found */
|
||||
#define IDE_ERR_MCR 0x08 /* ATA media change request */
|
||||
#define IDE_ERR_ABRT 0x04 /* ATA command aborted */
|
||||
#define IDE_ERR_NTK0 0x02 /* ATA track 0 not found */
|
||||
#define IDE_ERR_NDAM 0x01 /* ATA address mark not found */
|
||||
|
||||
#define IDE_STATUS_BSY 0x80 /* busy */
|
||||
#define IDE_STATUS_RDY 0x40 /* ready */
|
||||
#define IDE_STATUS_DF 0x20 /* device fault */
|
||||
#define IDE_STATUS_WFT 0x20 /* write fault (old name) */
|
||||
#define IDE_STATUS_SKC 0x10 /* seek complete */
|
||||
#define IDE_STATUS_DRQ 0x08 /* data request */
|
||||
#define IDE_STATUS_CORR 0x04 /* corrected */
|
||||
#define IDE_STATUS_IDX 0x02 /* index */
|
||||
#define IDE_STATUS_ERR 0x01 /* error (ATA) */
|
||||
#define IDE_STATUS_CHK 0x01 /* check (ATAPI) */
|
||||
|
||||
#define IDE_CTRL_HD15 0x08 /* bit should always be set to one */
|
||||
#define IDE_CTRL_SRST 0x04 /* soft reset */
|
||||
#define IDE_CTRL_NIEN 0x02 /* disable interrupts */
|
||||
|
||||
/* Most mandtory and optional ATA commands (from ATA-3), */
|
||||
|
||||
#define IDE_CMD_CFA_ERASE_SECTORS 0xC0
|
||||
#define IDE_CMD_CFA_REQUEST_EXT_ERR_CODE 0x03
|
||||
#define IDE_CMD_CFA_TRANSLATE_SECTOR 0x87
|
||||
#define IDE_CMD_CFA_WRITE_MULTIPLE_WO_ERASE 0xCD
|
||||
#define IDE_CMD_CFA_WRITE_SECTORS_WO_ERASE 0x38
|
||||
#define IDE_CMD_CHECK_POWER_MODE1 0xE5
|
||||
#define IDE_CMD_CHECK_POWER_MODE2 0x98
|
||||
#define IDE_CMD_DEVICE_RESET 0x08
|
||||
#define IDE_CMD_EXECUTE_DEVICE_DIAGNOSTIC 0x90
|
||||
#define IDE_CMD_FLUSH_CACHE 0xE7
|
||||
#define IDE_CMD_FORMAT_TRACK 0x50
|
||||
#define IDE_CMD_IDENTIFY_DEVICE 0xEC
|
||||
#define IDE_CMD_IDENTIFY_DEVICE_PACKET 0xA1
|
||||
#define IDE_CMD_IDENTIFY_PACKET_DEVICE 0xA1
|
||||
#define IDE_CMD_IDLE1 0xE3
|
||||
#define IDE_CMD_IDLE2 0x97
|
||||
#define IDE_CMD_IDLE_IMMEDIATE1 0xE1
|
||||
#define IDE_CMD_IDLE_IMMEDIATE2 0x95
|
||||
#define IDE_CMD_INITIALIZE_DRIVE_PARAMETERS 0x91
|
||||
#define IDE_CMD_INITIALIZE_DEVICE_PARAMETERS 0x91
|
||||
#define IDE_CMD_NOP 0x00
|
||||
#define IDE_CMD_PACKET 0xA0
|
||||
#define IDE_CMD_READ_BUFFER 0xE4
|
||||
#define IDE_CMD_READ_DMA 0xC8
|
||||
#define IDE_CMD_READ_DMA_QUEUED 0xC7
|
||||
#define IDE_CMD_READ_MULTIPLE 0xC4
|
||||
#define IDE_CMD_READ_SECTORS 0x20
|
||||
#define IDE_CMD_READ_VERIFY_SECTORS 0x40
|
||||
#define IDE_CMD_RECALIBRATE 0x10
|
||||
#define IDE_CMD_SEEK 0x70
|
||||
#define IDE_CMD_SET_FEATURES 0xEF
|
||||
#define IDE_CMD_SET_MULTIPLE_MODE 0xC6
|
||||
#define IDE_CMD_SLEEP1 0xE6
|
||||
#define IDE_CMD_SLEEP2 0x99
|
||||
#define IDE_CMD_STANDBY1 0xE2
|
||||
#define IDE_CMD_STANDBY2 0x96
|
||||
#define IDE_CMD_STANDBY_IMMEDIATE1 0xE0
|
||||
#define IDE_CMD_STANDBY_IMMEDIATE2 0x94
|
||||
#define IDE_CMD_WRITE_BUFFER 0xE8
|
||||
#define IDE_CMD_WRITE_DMA 0xCA
|
||||
#define IDE_CMD_WRITE_DMA_QUEUED 0xCC
|
||||
#define IDE_CMD_WRITE_MULTIPLE 0xC5
|
||||
#define IDE_CMD_WRITE_SECTORS 0x30
|
||||
#define IDE_CMD_WRITE_VERIFY 0x3C
|
||||
|
||||
static void reset_ide_controller(unsigned ide_ctl, unsigned ide_data)
|
||||
{
|
||||
unsigned char status, error;
|
||||
printk_spew("resetting ide controller at 0x%04x\n", ide_ctl);
|
||||
outb(IDE_CTRL_HD15 | IDE_CTRL_SRST | IDE_CTRL_NIEN, ide_ctl);
|
||||
printk_spew("1\n");
|
||||
udelay(25);
|
||||
printk_spew("2\n");
|
||||
outb(IDE_CTRL_HD15 | IDE_CTRL_NIEN, ide_ctl);
|
||||
printk_spew("3\n");
|
||||
do {
|
||||
mdelay(2);
|
||||
printk_spew("4\n");
|
||||
error = inb_p(ide_data+1);
|
||||
status = inb_p(ide_data+7);
|
||||
printk_spew("error = 0x%02x status = 0x%02x\n", error, status);
|
||||
} while(status & IDE_STATUS_BSY);
|
||||
printk_spew("reset ide controller at 0x%04x\n", ide_ctl);
|
||||
|
||||
}
|
||||
|
||||
static void setup_ide_devices(void)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7411, 0);
|
||||
if (dev != NULL) {
|
||||
/* Enable ide devices so the linux ide driver will work */
|
||||
u16 word;
|
||||
pci_read_config_word(dev, 0x40, &word);
|
||||
/* enable:
|
||||
* both devices
|
||||
* both devices posted write buffers
|
||||
*/
|
||||
pci_write_config_word(dev, 0x40, word |(1<<14)|(1<<12)|(1<<1)|(1<<0));
|
||||
|
||||
#if 1
|
||||
/* Setup the appropriate ide timing */
|
||||
pci_write_config_dword(dev, 0x48, 0x5e5e5e5e);
|
||||
pci_write_config_byte(dev, 0x4c, 0xaa);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
/* Enable native ide native mode, at the legacy addresses */
|
||||
/* This would be cool if I could receive an interrupt from
|
||||
* the ide controller.
|
||||
*/
|
||||
{
|
||||
u32 class_revision;
|
||||
|
||||
pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_revision);
|
||||
pci_write_config_dword(dev, PCI_CLASS_REVISION,
|
||||
class_revision | ( 1 << 8) | (1 << 10));
|
||||
pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
|
||||
0x1f0 | PCI_BASE_ADDRESS_SPACE_IO);
|
||||
pci_write_config_dword(dev, PCI_BASE_ADDRESS_1,
|
||||
0x3f6 | PCI_BASE_ADDRESS_SPACE_IO);
|
||||
pci_write_config_dword(dev, PCI_BASE_ADDRESS_2,
|
||||
0x170 | PCI_BASE_ADDRESS_SPACE_IO);
|
||||
pci_write_config_dword(dev, PCI_BASE_ADDRESS_3,
|
||||
0x376 | PCI_BASE_ADDRESS_SPACE_IO);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, 0);
|
||||
if (dev != NULL) {
|
||||
unsigned char byte;
|
||||
/* optimize ide dma acknowledge */
|
||||
pci_read_config_byte(dev, 0x4a, &byte);
|
||||
pci_write_config_byte(dev, 0x4a, byte & ~(1<<7));
|
||||
}
|
||||
}
|
||||
|
||||
static void enable_ide_devices(void)
|
||||
{
|
||||
u32 ide0_data = 0, ide0_ctl = 0, ide1_data = 0, ide1_ctl = 0, dma_base = 0;
|
||||
struct pci_dev *dev;
|
||||
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7411, 0);
|
||||
if (dev != NULL) {
|
||||
ide0_data = 0x1f0;
|
||||
ide0_ctl = 0x3f6;
|
||||
ide1_data = 0x170;
|
||||
ide1_ctl = 0x376;
|
||||
pci_read_config_dword(dev, PCI_BASE_ADDRESS_4, &dma_base);
|
||||
if (dma_base & PCI_BASE_ADDRESS_SPACE_IO) {
|
||||
dma_base &= ~PCI_BASE_ADDRESS_SPACE_IO;
|
||||
} else {
|
||||
dma_base = 0;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
/* IDE resets take forever, plus my reset code looks broken... */
|
||||
if (ide0_data && ide0_ctl) {
|
||||
reset_ide_controller(ide0_ctl,ide0_data + 7);
|
||||
}
|
||||
if (ide0_data && ide1_ctl) {
|
||||
reset_ide_controller(ide1_ctl, ide1_data + 7);
|
||||
}
|
||||
#endif
|
||||
if (dma_base) {
|
||||
printk_debug("ide dma_base = 0x%08lx\n", dma_base);
|
||||
#if 1
|
||||
/* Disable DMA */
|
||||
outb_p(inb_p(dma_base + 2) & ~((1<<5)|(1<<6)), dma_base +2);
|
||||
outb_p(inb_p(dma_base+8 + 2) & ~((1<<5)|(1<<6)), dma_base+8 +2);
|
||||
#endif
|
||||
#if 0
|
||||
/* Enable DMA */
|
||||
outb_p(inb_p(dma_base + 2) | ((1<<5)|(1<<6)), dma_base +2);
|
||||
outb_p(inb_p(dma_base+8 + 2) | ((1<<5)|(1<<6)), dma_base+8 +2);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void fixup_adaptec_7899P(struct pci_dev *pdev)
|
||||
{
|
||||
/* Enable writes to the device id */
|
||||
pci_write_config_byte(pdev, 0xff, 1);
|
||||
/* Set the device id */
|
||||
pci_write_config_word(pdev, PCI_DEVICE_ID, PCI_DEVICE_ID_ADAPTEC2_7899P);
|
||||
/* Set the subsytem vendor id */
|
||||
pci_write_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, PCI_VENDOR_ID_TYAN);
|
||||
/* Set the subsytem id */
|
||||
pci_write_config_word(pdev, PCI_SUBSYSTEM_ID, 0x2462);
|
||||
/* Disable writes to the device id */
|
||||
pci_write_config_byte(pdev, 0xff, 0);
|
||||
}
|
||||
|
||||
static void onboard_scsi_fixup(void)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
|
||||
/* Set the scsi device id's */
|
||||
dev = pci_find_slot(0, PCI_DEVFN(0xd, 0));
|
||||
if (dev != NULL) {
|
||||
fixup_adaptec_7899P(dev);
|
||||
}
|
||||
/* Set the scsi device id's */
|
||||
dev = pci_find_slot(0, PCI_DEVFN(0xd, 1));
|
||||
if (dev != NULL) {
|
||||
fixup_adaptec_7899P(dev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void cpu_reset_sends_init(void)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, 0);
|
||||
if (dev != NULL) {
|
||||
unsigned char byte;
|
||||
pci_read_config_byte(dev, 0x47, &byte);
|
||||
pci_write_config_byte(dev, 0x47, byte | (1<<7));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void decode_stop_grant_fixup(void)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, 0);
|
||||
if (dev != NULL) {
|
||||
unsigned char byte;
|
||||
pci_read_config_byte(dev, 0x41, &byte);
|
||||
pci_write_config_byte(dev, 0x41, byte | (1<<1));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void pm_controller_classcode_fixup(void)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, 0);
|
||||
if (dev != NULL) {
|
||||
pci_write_config_dword(dev, 0x60, 0x06800000);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void set_power_on_after_power_fail(int enable)
|
||||
{
|
||||
/* FIXME: This may be part of the picture but it isn't
|
||||
* the whole story :(
|
||||
*/
|
||||
struct pci_dev *dev;
|
||||
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, 0);
|
||||
if (dev != NULL) {
|
||||
unsigned char byte;
|
||||
pci_read_config_byte(dev, 0x43, &byte);
|
||||
if (enable) {
|
||||
byte &= ~(1<<6);
|
||||
}
|
||||
else {
|
||||
byte |= (1<<6);
|
||||
}
|
||||
pci_write_config_byte(dev, 0x43, byte);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void posted_memory_write_enable(void)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, 0);
|
||||
if (dev != NULL) {
|
||||
unsigned char byte;
|
||||
pci_read_config_byte(dev, 0x46, &byte);
|
||||
pci_write_config_byte(dev, 0x46, byte | (1<<0));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void setup_pci_irq_to_isa_routing(void)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, 0);
|
||||
if (dev != NULL) {
|
||||
/*
|
||||
* PIRQA -> 5
|
||||
* PIRQB -> 10
|
||||
* PIRQC -> 11
|
||||
* PIRQD -> 3
|
||||
*/
|
||||
pci_write_config_word(dev, 0x56, 0x3ba5);
|
||||
}
|
||||
}
|
||||
|
||||
static void setup_pci_arbiter(void)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, 0);
|
||||
if (dev) {
|
||||
/* Enable:
|
||||
* PCI parking
|
||||
* memory prefetching
|
||||
* EV6 mode
|
||||
* Enable power management registers
|
||||
* The southbridge lock
|
||||
* Read data error disable
|
||||
* PCI retries
|
||||
* AGP retries
|
||||
* AGP chaining
|
||||
* PCI chaining
|
||||
*/
|
||||
pci_write_config_dword(dev, 0x84,
|
||||
(0<<24)
|
||||
|(1<<23)
|
||||
|(1<<17)|(1<<16)
|
||||
|(0<<15)|(1<<14)|(1<<13)|(1<<12)
|
||||
|(0<<11)|(0<<10)|(0<<9)|(0<<8)
|
||||
|(1<<7)|(0<<6)|(0<<5)|(1<<4)
|
||||
|(0<<3)|(1<<2)|(1<<1)|(1<<0));
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_setup(void)
|
||||
{
|
||||
/* FIXME this is untested incomplete implementation. */
|
||||
struct pci_dev *dev;
|
||||
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7414, 0);
|
||||
if (dev) {
|
||||
u32 cmd;
|
||||
pci_read_config_dword(dev, PCI_COMMAND, &cmd);
|
||||
pci_write_config_dword(dev, PCI_COMMAND,
|
||||
cmd | PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
|
||||
PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE);
|
||||
}
|
||||
}
|
||||
|
||||
static void hide_devices(void)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, 0);
|
||||
if (dev) {
|
||||
u8 byte;
|
||||
pci_read_config_byte(dev, 0x48, &byte);
|
||||
#if 0
|
||||
/* Hide both the ide controller and the usb controller */
|
||||
pci_write_config_byte(dev, 0x48, byte | (0<<3)|(1<<2)|(1<<1));
|
||||
#endif
|
||||
#if 0
|
||||
/* Hide the usb controller */
|
||||
pci_write_config_byte(dev, 0x48, byte | (0<<3)|(1<<2)|(0<<1));
|
||||
#endif
|
||||
#if 1
|
||||
/* Hide no devices */
|
||||
pci_write_config_byte(dev, 0x48, byte | (0<<3)|(0<<2)|(0<<1));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void mainboard_fixup(void)
|
||||
{
|
||||
disable_watchdog();
|
||||
lpc_routing_fixup();
|
||||
enable_ioapic();
|
||||
serial_irq_fixup();
|
||||
enable_reset_port_0xcf9();
|
||||
enable_port92_reset();
|
||||
#if 0
|
||||
print_whami();
|
||||
#endif
|
||||
setup_ide_devices();
|
||||
onboard_scsi_fixup();
|
||||
cpu_reset_sends_init();
|
||||
rtc_init();
|
||||
decode_stop_grant_fixup();
|
||||
posted_memory_write_enable();
|
||||
pm_controller_classcode_fixup();
|
||||
#if 1
|
||||
mouse_sends_irq12();
|
||||
#endif
|
||||
setup_pci_irq_to_isa_routing();
|
||||
setup_pci_arbiter();
|
||||
isa_dma_init();
|
||||
#if 0
|
||||
usb_setup();
|
||||
#endif
|
||||
#if 0
|
||||
hide_devices();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void final_mainboard_fixup(void)
|
||||
{
|
||||
#if 1
|
||||
enable_ide_devices();
|
||||
#endif
|
||||
}
|
||||
|
||||
void hard_reset(void)
|
||||
{
|
||||
pci_set_method();
|
||||
/* Allow the watchdog timer to reboot us, and enable 0xcf9 */
|
||||
pcibios_write_config_byte(0, (AMD766_DEV >> 8) | 3, 0x41, (1<<5)|(1<<1));
|
||||
/* Try rebooting though port 0xcf9 */
|
||||
outb((0<<3)|(1<<2)|(1<<1), 0xcf9);
|
||||
return;
|
||||
}
|
||||
140
src/mainboard/tyan/guiness/mainboard_raminit.inc
Normal file
140
src/mainboard/tyan/guiness/mainboard_raminit.inc
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
jmp mainboard_raminit_out
|
||||
#define DEFAULT_RAM_TRACE_SETTINGS 0
|
||||
#define USE_ECC_SDRAM 1
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Routine: spd_to_dimm_side0
|
||||
* Arguments: %bl SMBUS_MEM_DEVICE
|
||||
*
|
||||
* Results: %edx DIMM register index
|
||||
*
|
||||
* Used: %ebx, %edx, %esp
|
||||
* Trashed: %eflags
|
||||
* Preserved: %eax, %ebx, %ecx, %esi, %edi, %ebp
|
||||
*
|
||||
* Effects: Dimms are not necessarily in the same order on the smbus
|
||||
* as they are in chipset register indexes. This function
|
||||
* maps the SMBUS device id to the logical index in
|
||||
* the chipset, that is used to refer to a particular dimm.
|
||||
*/
|
||||
spd_to_dimm_side0:
|
||||
movl %ebx, %edx
|
||||
andl $0xff, %edx
|
||||
subl $(SMBUS_MEM_DEVICE_START), %edx
|
||||
/* 0 -> 0 */
|
||||
cmpl $0, %edx
|
||||
jne 1f
|
||||
movl $0, %edx
|
||||
RETSP
|
||||
/* 1 -> 6 */
|
||||
1: cmpl $1, %edx
|
||||
jne 1f
|
||||
movl $6, %edx
|
||||
RETSP
|
||||
/* 2 -> 4 */
|
||||
1: cmpl $2, %edx
|
||||
jne 1f
|
||||
movl $4, %edx
|
||||
RETSP
|
||||
/* 3 -> 2 */
|
||||
1: movl $2, %edx
|
||||
RETSP
|
||||
|
||||
|
||||
/*
|
||||
* Routine: spd_to_dimm_side1
|
||||
* Arguments: %bl SMBUS_MEM_DEVICE
|
||||
*
|
||||
* Results: %edx DIMM register index
|
||||
*
|
||||
* Used: %ebx, %edx, %esp
|
||||
* Trashed: %eflags
|
||||
* Preserved: %eax, %ebx, %ecx, %esi, %edi, %ebp
|
||||
*
|
||||
* Effects: Dimms are not necessarily in the same order on the smbus
|
||||
* as they are in chipset register indexes. This function
|
||||
* maps the SMBUS device id to the logical index in
|
||||
* the chipset, that is used to refer to a particular dimm.
|
||||
*/
|
||||
spd_to_dimm_side1:
|
||||
movl %ebx, %edx
|
||||
andl $0xff, %edx
|
||||
subl $(SMBUS_MEM_DEVICE_START), %edx
|
||||
/* 0 -> 1 */
|
||||
cmpl $0, %edx
|
||||
jne 1f
|
||||
movl $1, %edx
|
||||
RETSP
|
||||
/* 1 -> 7 */
|
||||
1: cmpl $1, %edx
|
||||
jne 1f
|
||||
movl $7, %edx
|
||||
RETSP
|
||||
/* 2 -> 5 */
|
||||
1: cmpl $2, %edx
|
||||
jne 1f
|
||||
movl $5, %edx
|
||||
RETSP
|
||||
/* 3 -> 3 */
|
||||
1: movl $3, %edx
|
||||
RETSP
|
||||
|
||||
|
||||
/* Set the calibration delay. These values may need to change per mainboard
|
||||
* so we put them here.
|
||||
*/
|
||||
|
||||
sdram_software_calibration_delay:
|
||||
#if DEFAULT_RAM_TRACE_SETTINGS
|
||||
.byte 0x69, 0x00, 0x00, 0x6b
|
||||
#else
|
||||
.byte 0x69, 0x00, 0x00, 0x54
|
||||
#endif
|
||||
|
||||
mainboard_constant_register_values:
|
||||
#if DEFAULT_RAM_TRACE_SETTINGS
|
||||
#else
|
||||
.long 0x18c, 0x090e2d0e
|
||||
.long 0x190, 0x3f0f2d0e
|
||||
.long 0x194, 0x2d0e2d0e
|
||||
.long 0x198, 0x2d0e2d0e
|
||||
#endif
|
||||
#if USE_ECC_SDRAM
|
||||
.long 0x48, (3 << 14)|(2 << 10)|(0 << 8)|(0 << 4)|(0 << 0)
|
||||
#else
|
||||
.long 0x48, 0
|
||||
#endif
|
||||
mainboard_constant_register_values_end:
|
||||
|
||||
|
||||
/*
|
||||
* Routine: mainboard_verify_dram_timing
|
||||
* Arguments: %edi the computed timing for the current dimm.
|
||||
* Trashed: %eflags
|
||||
* Results: cf clear
|
||||
* %edi has a timing supported by this motherboard
|
||||
* On Error:
|
||||
* cf set
|
||||
* %edi holds a timing not supported by this motherboard
|
||||
*
|
||||
* Effects: Verifies we can use the current dimm settings
|
||||
* on the tyan guinness motherboard.
|
||||
* Currently the only potential problem is putting
|
||||
* in unregistered SDRAM.
|
||||
*/
|
||||
mainboard_verify_dram_timing:
|
||||
testl $(1<<27), %edi
|
||||
jnz mainboard_verify_dram_timing_ok
|
||||
mainboard_verify_dram_timing_error:
|
||||
stc
|
||||
jmp mainboard_verify_dram_timing_out
|
||||
mainboard_verify_dram_timing_ok:
|
||||
clc
|
||||
mainboard_verify_dram_timing_out:
|
||||
RET_LABEL(mainboard_verify_dram_timing)
|
||||
|
||||
#undef DEFAULT_RAM_TRACE_SETTINGS
|
||||
mainboard_raminit_out:
|
||||
|
||||
158
src/mainboard/tyan/guiness/mptable.c
Normal file
158
src/mainboard/tyan/guiness/mptable.c
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
#include <arch/smp/mpspec.h>
|
||||
#include <string.h>
|
||||
#include <printk.h>
|
||||
#include <cpu/p6/apic.h>
|
||||
|
||||
#define USE_ALL_CPUS 1
|
||||
void smp_write_config_table(void *v)
|
||||
{
|
||||
static const char sig[4] = "PCMP";
|
||||
static const char oem[8] = "TYAN ";
|
||||
static const char productid[12] = "GUINESS ";
|
||||
struct mp_config_table *mc;
|
||||
|
||||
mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN);
|
||||
memset(mc, 0, sizeof(*mc));
|
||||
|
||||
memcpy(mc->mpc_signature, sig, sizeof(sig));
|
||||
mc->mpc_length = sizeof(*mc); /* initially just the header */
|
||||
mc->mpc_spec = 0x04;
|
||||
mc->mpc_checksum = 0; /* not yet computed */
|
||||
memcpy(mc->mpc_oem, oem, sizeof(oem));
|
||||
memcpy(mc->mpc_productid, productid, sizeof(productid));
|
||||
mc->mpc_oemptr = 0;
|
||||
mc->mpc_oemsize = 0;
|
||||
mc->mpc_entry_count = 0; /* No entries yet... */
|
||||
mc->mpc_lapic = LAPIC_ADDR;
|
||||
mc->mpe_length = 0;
|
||||
mc->mpe_checksum = 0;
|
||||
mc->reserved = 0;
|
||||
|
||||
|
||||
smp_write_processors(mc);
|
||||
smp_write_bus(mc, 0, "PCI ");
|
||||
smp_write_bus(mc, 1, "PCI ");
|
||||
smp_write_bus(mc, 2, "ISA ");
|
||||
|
||||
smp_write_ioapic(mc, 2, 0x11, 0xfec00000);
|
||||
|
||||
/* ISA backward compatibility interrupts */
|
||||
smp_write_intsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
|
||||
0x02, 0x00, 0x02, 0x00);
|
||||
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
|
||||
0x02, 0x01, 0x02, 0x01);
|
||||
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
|
||||
0x02, 0x00, 0x02, 0x02);
|
||||
/* PCI 0x03 <-> 0x13 ? */
|
||||
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
|
||||
0x02, 0x03, 0x02, 0x03);
|
||||
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
|
||||
0x02, 0x04, 0x02, 0x04);
|
||||
/* PCI 0x05 <-> 0x12 ? */
|
||||
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
|
||||
0x02, 0x05, 0x02, 0x05);
|
||||
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
|
||||
0x02, 0x06, 0x02, 0x06);
|
||||
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
|
||||
0x02, 0x07, 0x02, 0x07);
|
||||
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
|
||||
0x02, 0x08, 0x02, 0x08);
|
||||
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
|
||||
0x02, 0x09, 0x02, 0x09);
|
||||
/* PCI 0x0a <-> 0x11 ? */
|
||||
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
|
||||
0x02, 0x0a, 0x02, 0x0a);
|
||||
/* PCI 0x0b <-> 0x10 ? */
|
||||
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
|
||||
0x02, 0x0b, 0x02, 0x0b);
|
||||
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
|
||||
0x02, 0x0c, 0x02, 0x0c);
|
||||
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
|
||||
0x02, 0x0d, 0x02, 0x0d);
|
||||
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
|
||||
0x02, 0x0e, 0x02, 0x0e);
|
||||
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
|
||||
0x02, 0x0f, 0x02, 0x0f);
|
||||
|
||||
|
||||
/* Onboard SCSI 0 */
|
||||
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
|
||||
0x00, (0xd<<2)|0, 0x02, 0x10);
|
||||
/* Onboard SCSI 1 */
|
||||
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
|
||||
0x00, (0xd<<2)|1, 0x02, 0x11);
|
||||
/* Onboard eth0 */
|
||||
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
|
||||
0x00, (0x0f<<2)|0, 0x02, 0x12);
|
||||
/* Onboard eth1 */
|
||||
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
|
||||
0x00, (0x10<<2)|0, 0x02, 0x13);
|
||||
|
||||
#if 0
|
||||
/* Onboard IDE0 */
|
||||
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
|
||||
0x00, (0x7<<2)|1, 0x02, 0x10);
|
||||
#endif
|
||||
|
||||
/* PCI slot 0 */
|
||||
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
|
||||
0x00, (0x08<<2)|0, 0x02, 0x10);
|
||||
/* PCI slot 1 */
|
||||
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
|
||||
0x00, (0x09<<2)|0, 0x02, 0x11);
|
||||
/* PCI Slot 2 */
|
||||
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_HIGH,
|
||||
0x00, (0x0a<<2)|0, 0x02, 0x12);
|
||||
/* PCI Slot 3 */
|
||||
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_HIGH,
|
||||
0x00, (0x0b<<2)|0, 0x02, 0x13);
|
||||
/* PCI Slot 4 */
|
||||
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_HIGH,
|
||||
0x00, (0x0c<<2)|0, 0x02, 0x10);
|
||||
|
||||
|
||||
/* Standard local interrupt assignments */
|
||||
smp_write_lintsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
|
||||
0x02, 0x00, MP_APIC_ALL, 0x00);
|
||||
smp_write_lintsrc(mc, mp_NMI, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
|
||||
0x01, 0x00, MP_APIC_ALL, 0x01);
|
||||
|
||||
|
||||
/* The following information in the extension section linux doesn't currnetly need
|
||||
* and has just been copied from the bios for now.
|
||||
*/
|
||||
smp_write_address_space(mc, 0x00, ADDRESS_TYPE_IO, 0x00000000, 0x00000000, 0x00010000, 0x00000000);
|
||||
smp_write_address_space(mc, 0x00, ADDRESS_TYPE_MEM, 0x10000000, 0x00000000, 0xe4100000, 0x00000000);
|
||||
smp_write_address_space(mc, 0x00, ADDRESS_TYPE_PREFETCH, 0xf4100000, 0x00000000, 0x07f00000, 0x00000000);
|
||||
smp_write_address_space(mc, 0x00, ADDRESS_TYPE_MEM, 0xfc000000, 0x00000000, 0x02e00000, 0x00000000);
|
||||
smp_write_address_space(mc, 0x00, ADDRESS_TYPE_MEM, 0xfee01000, 0x00000000, 0x011ff000, 0x00000000);
|
||||
smp_write_address_space(mc, 0x00, ADDRESS_TYPE_MEM, 0x000a0000, 0x00000000, 0x00024000, 0x00000000);
|
||||
smp_write_address_space(mc, 0x00, ADDRESS_TYPE_MEM, 0x000c8000, 0x00000000, 0x00002000, 0x00000000);
|
||||
smp_write_address_space(mc, 0x00, ADDRESS_TYPE_MEM, 0x000cc000, 0x00000000, 0x00002000, 0x00000000);
|
||||
smp_write_address_space(mc, 0x00, ADDRESS_TYPE_MEM, 0x000d0000, 0x00000000, 0x00001000, 0x00000000);
|
||||
smp_write_address_space(mc, 0x00, ADDRESS_TYPE_MEM, 0x000d2000, 0x00000000, 0x00001000, 0x00000000);
|
||||
smp_write_address_space(mc, 0x00, ADDRESS_TYPE_MEM, 0x000d4000, 0x00000000, 0x00001000, 0x00000000);
|
||||
smp_write_address_space(mc, 0x00, ADDRESS_TYPE_MEM, 0x000d6000, 0x00000000, 0x00001000, 0x00000000);
|
||||
smp_write_address_space(mc, 0x00, ADDRESS_TYPE_MEM, 0x000d8000, 0x00000000, 0x00002000, 0x00000000);
|
||||
smp_write_address_space(mc, 0x00, ADDRESS_TYPE_MEM, 0x000e0000, 0x00000000, 0x00012000, 0x00000000);
|
||||
smp_write_address_space(mc, 0x00, ADDRESS_TYPE_MEM, 0x000f4000, 0x00000000, 0x00002000, 0x00000000);
|
||||
smp_write_address_space(mc, 0x00, ADDRESS_TYPE_MEM, 0x000f8000, 0x00000000, 0x00004000, 0x00000000);
|
||||
smp_write_bus_hierarchy(mc, 0x02, BUS_SUBTRACTIVE_DECODE, 0x00);
|
||||
smp_write_compatibility_address_space(mc, 0x00, ADDRESS_RANGE_ADD, RANGE_LIST_IO_ISA);
|
||||
smp_write_compatibility_address_space(mc, 0x00, ADDRESS_RANGE_ADD, RANGE_LIST_IO_VGA);
|
||||
|
||||
|
||||
mc->mpe_checksum = smp_compute_checksum(smp_next_mpc_entry(mc), mc->mpe_length);
|
||||
mc->mpc_checksum = smp_compute_checksum(mc, mc->mpc_length);
|
||||
printk_debug("Wrote the mp table end at: %p - %p\n",
|
||||
mc, smp_next_mpe_entry(mc));
|
||||
}
|
||||
|
||||
void write_smp_table(void *v)
|
||||
{
|
||||
printk_debug("Writing the mp table\n");
|
||||
smp_write_floating_table(v);
|
||||
smp_write_config_table(v);
|
||||
}
|
||||
|
||||
|
||||
7
src/northbridge/amd/amd76x/Config
Normal file
7
src/northbridge/amd/amd76x/Config
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
mainboardinit northbridge/amd/amd76x/set_memory_size.inc
|
||||
mainboardinit northbridge/amd/amd76x/raminit.inc
|
||||
mainboardinit sdram/generic_sdram.inc
|
||||
mainboardinit sdram/generic_zero_ecc_sdram.inc
|
||||
mainboardinit arch/i386/lib/cpu_reset.inc
|
||||
|
||||
object northbridge.o
|
||||
256
src/northbridge/amd/amd76x/mpinit.inc
Normal file
256
src/northbridge/amd/amd76x/mpinit.inc
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
/* Very early on the K7 needs to setup it's multiprocessor state */
|
||||
|
||||
/* Extended BIU Control
|
||||
* 0x44
|
||||
* [23:20] P1 Speculative Read Data Movement Enable
|
||||
* 0000 == Function Disabled
|
||||
* 0001 == One Clock
|
||||
* 0010 == Two Clocks
|
||||
* ....
|
||||
* 1111 == Fifteen Clocks
|
||||
*
|
||||
* [19:16] P0 Speculate Read Data Movement Enable
|
||||
* 0000 == Function Disabled
|
||||
* 0001 == One Clock
|
||||
* 0010 == Two Clocks
|
||||
* ....
|
||||
* 1111 == Fifteen Clocks
|
||||
*
|
||||
* [13:11] P1 Write Data Delay (Status Register)
|
||||
* [10: 8] P0 Write Data Delay (Status Register)
|
||||
* [ 7: 7] 1 == Defer Write Data Movement
|
||||
* [ 4: 4] P1 2 Bit Times Per Frame Enable
|
||||
* Use 0 for alpha 1 for athlon
|
||||
* [ 3: 3] P0 2 Bit Times Per Frame Enable
|
||||
* Use 0 for alpha 1 for athlon
|
||||
*
|
||||
*/
|
||||
|
||||
/* BIU[01] Status/Control
|
||||
* 0x60, 0x68
|
||||
* [31:31] Probe_Enable
|
||||
* 1 == Probes are sent to this processor
|
||||
* 0 == Probes are not sent to this processor
|
||||
* [27:25] Xca_Probe_Count
|
||||
* Must be non-zero
|
||||
* Recommended value 0x2
|
||||
* [24:22] Xca_Read_Count
|
||||
* Must be non-zero
|
||||
* Recommended value 0x6
|
||||
* [21:19] Xca_Write_Count
|
||||
* Must be non-zero
|
||||
* Recommended value 0x6
|
||||
* [18:18] Halt_Disconnect_Enable
|
||||
* 0 == No AMD Athlon system bus disconnect following HALT
|
||||
* 1 == AMD Athlon system bus discconnect following HALT
|
||||
* [17:17] Stop_Grant_Disconnect_Enable
|
||||
* 0 == No AMD Athlon system bus disconnect following Stop/Grant
|
||||
* 1 == AMD Athlon system bus disconnect following Stop/Grant
|
||||
* special cycle
|
||||
* [16:14] Probe_Limit
|
||||
* 000 = 1 probe
|
||||
* 001 = 2 probes
|
||||
* ...
|
||||
* 111 = 8 probes
|
||||
* [13:10] Ack_Limit (Read only)
|
||||
* 0000 = 1 unacknowledged command
|
||||
* 0001 = 2 unacknowledged commands
|
||||
* ...
|
||||
* 1111 = 16 unacknowledged commands
|
||||
* [09:09] Bypass_Enable
|
||||
* 0 == No don't bypass certain memory pipe stages
|
||||
* 1 == bypass some memory stages for optimal performace
|
||||
* - Requires single CPU system
|
||||
* - Requires clock multipler >= 4
|
||||
* [08:07] SysDC_Out_Enable
|
||||
* Initialized by pinstrapping during reset
|
||||
* 00 == Reserved
|
||||
* 01 == 1 clock
|
||||
* 10 == 2 clocks
|
||||
* 11 == 3 clocks
|
||||
* [06:03] SysDC_In_Enable
|
||||
* Initialized during pinstrapping
|
||||
* 0000 == 1 clock
|
||||
* 0001 == 2 clocks
|
||||
* 1111 == 16 clocks
|
||||
* [02:02] WR2_Read
|
||||
* Initialized during pinstrapping
|
||||
* [01:00] WR2_Write
|
||||
* Initialized during pinstrapping
|
||||
*/
|
||||
|
||||
#include <cpu/k7/mtrr.h>
|
||||
#include <cpu/p6/apic.h>
|
||||
|
||||
#define BIU_CONTROL_MASK 0x00003dff
|
||||
#define BIU_CONTROL ((1 << 31)|(0x2 << 25)|(0x6 << 22)|(0x6 << 19)|(0 << 18)\
|
||||
|(1 << 17)|(7<<14)|(0<<9))
|
||||
#define EBIU_MASK 0xffffe4ff
|
||||
#define EBIU_VALUE ((0<<20)|(0<<16)|(1<<4)|(1<<3))
|
||||
|
||||
#define PCI_CONFIG_ADDR 0xFE000000
|
||||
#define PCI_IO_ADDR 0xFC000000
|
||||
#define PCI_IACK_ADDR 0xF8000000
|
||||
#define PCI_SPEC_ADDR 0xF8000000
|
||||
|
||||
/* Read the northbridge whami register
|
||||
*/
|
||||
movl $0x80000080, %eax
|
||||
movw $0xcf8, %dx
|
||||
outl %eax, %dx
|
||||
movw $0xcfc, %dx
|
||||
inl %dx, %eax
|
||||
|
||||
/* Isolate the processor id */
|
||||
movl %eax, %ebx
|
||||
movl %eax, %esi
|
||||
andl $0xf, %esi
|
||||
|
||||
#if defined(USE_AMD_NDA_CODE)
|
||||
#endif
|
||||
|
||||
|
||||
/* Figure out how many unacknowledged acks
|
||||
* the AMD762 northbridge can support
|
||||
*/
|
||||
shll $3, %esi
|
||||
movl $0x80000060, %eax
|
||||
orl %esi, %eax
|
||||
shrl $3, %esi
|
||||
movw $0xcf8, %dx
|
||||
outl %eax, %dx
|
||||
movw $0xcfc, %dx
|
||||
inl %dx, %eax
|
||||
|
||||
shrl $10, %eax
|
||||
andl $0xf, %eax
|
||||
addl $1, %eax
|
||||
|
||||
/* Move the count into a safe place. */
|
||||
movl %eax, %ebp
|
||||
|
||||
/* Tell the processor how many unacknoledged probes the AMD762 can
|
||||
* support
|
||||
*/
|
||||
#if defined(USE_AMD_NDA_CODE)
|
||||
#endif /* USE_AMD_NDA_CODE */
|
||||
|
||||
/* Enable the local apic, and map it where we expect it. */
|
||||
movl $APIC_BASE_MSR, %ecx
|
||||
rdmsr
|
||||
orl $APIC_BASE_MSR_ENABLE, %eax
|
||||
andl $(~APIC_BASE_MSR_ADDR_MASK), %eax
|
||||
orl $APIC_DEFAULT_BASE, %eax
|
||||
xorl %edx, %edx
|
||||
wrmsr
|
||||
/* Save off the apic address */
|
||||
movl %eax, %edi
|
||||
andl $APIC_BASE_MSR_ADDR_MASK, %edi
|
||||
|
||||
/* Set the local apicid */
|
||||
xorl %eax, %eax
|
||||
shll $24, %esi
|
||||
movl %esi, APIC_ID(%edi)
|
||||
shrl $24, %esi
|
||||
|
||||
/* Set the enabled bit for the local apic
|
||||
* and clear the spurious vector.
|
||||
*/
|
||||
movl APIC_SPIV(%edi), %eax
|
||||
andl $0xfffffe0f, %eax
|
||||
orl $APIC_SPIV_ENABLE, %eax
|
||||
movl %eax, APIC_SPIV(%edi)
|
||||
|
||||
/* See if I'm the first processor to initialize. */
|
||||
cmpb %bl, %bh
|
||||
je bootstrap_cpu
|
||||
|
||||
/* I'm not the bootstrap processor */
|
||||
/* clear the BSP bit */
|
||||
movl $APIC_BASE_MSR, %ecx
|
||||
rdmsr
|
||||
andl $(~APIC_BASE_MSR_BOOTSTRAP_PROCESSOR), %eax
|
||||
wrmsr
|
||||
|
||||
/* Send an APIC INIT to myself */
|
||||
movl %esi, %eax
|
||||
shll $24, %eax
|
||||
movl %eax, APIC_ICR2(%edi)
|
||||
|
||||
movl $((0<<18)|(1<<15)|(1<<14)|(0<<11)|(5 << 8)|(0<<0)), %eax
|
||||
movl %eax, APIC_ICR(%edi)
|
||||
|
||||
/* Wait for the ipi send to finish */
|
||||
1: movl APIC_ICR(%edi), %eax
|
||||
testl $APIC_ICR_BUSY, %eax
|
||||
jnz 1b
|
||||
|
||||
/* Deassert the APIC INIT */
|
||||
movl %esi, %eax
|
||||
shll $24, %eax
|
||||
movl %eax, APIC_ICR2(%edi)
|
||||
|
||||
movl $((0<<18)|(1<<15)|(0<<14)|(0<<11)|(5 << 8)|(0<<0)), %eax
|
||||
movl %eax, APIC_ICR(%edi)
|
||||
|
||||
/* Wait for the ipi send to finish */
|
||||
1: movl APIC_ICR(%edi), %eax
|
||||
testl $APIC_ICR_BUSY, %eax
|
||||
jnz 1b
|
||||
|
||||
wait_for_startup_ipi:
|
||||
hlt
|
||||
jmp wait_for_startup_ipi
|
||||
|
||||
|
||||
bootstrap_cpu:
|
||||
/* Set the bootstrap processor flag */
|
||||
movl $APIC_BASE_MSR, %ecx
|
||||
rdmsr
|
||||
orl $APIC_BASE_MSR_BOOTSTRAP_PROCESSOR, %eax
|
||||
wrmsr
|
||||
|
||||
|
||||
init_cpu_bus_all:
|
||||
/* Setup Common AMD Athlon system bus */
|
||||
movl $0x80000044, %eax
|
||||
mov $0xcf8, %dx
|
||||
outl %eax, %dx
|
||||
mov $0xcfc, %dx
|
||||
inl %dx, %eax
|
||||
andl $EBIU_MASK, %eax
|
||||
orl $EBIU_VALUE, %eax
|
||||
outl %eax, %dx
|
||||
|
||||
init_cpu_bus_0:
|
||||
testl $(1<<16), %ebx
|
||||
jz init_cpu_bus_0_done
|
||||
/* Setup the AMD Athlon system bus */
|
||||
movl $0x80000060, %eax
|
||||
movw $0xcf8, %dx
|
||||
outl %eax, %dx
|
||||
movw $0xcfc, %dx
|
||||
inl %dx, %eax
|
||||
andl $BIU_CONTROL_MASK, %eax
|
||||
orl $BIU_CONTROL, %eax
|
||||
outl %eax, %dx
|
||||
init_cpu_bus_0_done:
|
||||
|
||||
init_cpu_bus_1:
|
||||
testl $(2<<16), %ebx
|
||||
jz init_cpu_bus_1_done
|
||||
/* Setup the AMD Athlon system bus */
|
||||
movl $0x80000068, %eax
|
||||
movw $0xcf8, %dx
|
||||
outl %eax, %dx
|
||||
movw $0xcfc, %dx
|
||||
inl %dx, %eax
|
||||
andl $BIU_CONTROL_MASK, %eax
|
||||
orl $BIU_CONTROL, %eax
|
||||
outl %eax, %dx
|
||||
init_cpu_bus_1_done:
|
||||
|
||||
|
||||
/* FIXME enable superbypass memory accesses if only cpu0 is present,
|
||||
* and we have a cpu multiplier > 4.
|
||||
*/
|
||||
14
src/northbridge/amd/amd76x/northbridge.c
Normal file
14
src/northbridge/amd/amd76x/northbridge.c
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#include <pci.h>
|
||||
#include <cpu/p5/io.h>
|
||||
#include <part/sizeram.h>
|
||||
|
||||
unsigned long sizeram(void)
|
||||
{
|
||||
unsigned long size;
|
||||
/* Use the PCI top memory register */
|
||||
pcibios_read_config_dword(0, 0, 0x9c, &size);
|
||||
/* Convert size in bytes to size in K */
|
||||
size = size >> 10;
|
||||
return size;
|
||||
}
|
||||
|
||||
2114
src/northbridge/amd/amd76x/raminit.inc
Normal file
2114
src/northbridge/amd/amd76x/raminit.inc
Normal file
File diff suppressed because it is too large
Load diff
8
src/northbridge/amd/amd76x/reset_test.inc
Normal file
8
src/northbridge/amd/amd76x/reset_test.inc
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
/* If I have already booted once skip a bunch of initialization */
|
||||
/* To see if I have already booted I check to see if memory
|
||||
* has been enabled.
|
||||
*/
|
||||
movl $0x58, %eax
|
||||
PCI_READ_CONFIG_DWORD
|
||||
testl $(1<<25), %eax
|
||||
jnz __cpu_reset
|
||||
14
src/northbridge/amd/amd76x/set_memory_size.inc
Normal file
14
src/northbridge/amd/amd76x/set_memory_size.inc
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
jmp set_memory_size_out
|
||||
|
||||
#include <cpu/k7/mtrr.h>
|
||||
set_memory_size:
|
||||
/* Read the top of memory */
|
||||
movl $0x9c, %eax
|
||||
PCI_READ_CONFIG_DWORD
|
||||
|
||||
#if USE_AMD_NDA_CODE
|
||||
#endif /* USE_AMD_NDA_CODE */
|
||||
|
||||
set_memory_size_end:
|
||||
RETSP
|
||||
set_memory_size_out:
|
||||
44
src/pc80/i8259.c
Normal file
44
src/pc80/i8259.c
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
#ifdef I8259
|
||||
|
||||
#include <pc80/i8259.h>
|
||||
#include <arch/io.h>
|
||||
/* code taken from:
|
||||
!
|
||||
! setup.S Copyright (C) 1991, 1992 Linus Torvalds
|
||||
!
|
||||
! setup.s is responsible for getting the system data from the BIOS,
|
||||
! and putting them into the appropriate places in system memory.
|
||||
! both setup.s and system has been loaded by the bootblock.
|
||||
*/
|
||||
/* we're getting screwed again and again by this problem of the 8259.
|
||||
* so we're going to leave this lying around for inclusion into
|
||||
* crt0.S on an as-needed basis.
|
||||
! well, that went ok, I hope. Now we have to reprogram the interrupts :-(
|
||||
! we put them right after the intel-reserved hardware interrupts, at
|
||||
! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
|
||||
! messed this up with the original PC, and they haven't been able to
|
||||
! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
|
||||
! which is used for the internal hardware interrupts as well. We just
|
||||
! have to reprogram the 8259's, and it isn't fun.
|
||||
*/
|
||||
|
||||
void setup_i8259(void)
|
||||
{
|
||||
outb(0x11, 0x20); /*! initialization sequence to 8259A-1*/
|
||||
outb(0x11, 0xA0); /*! and to 8259A-2*/
|
||||
outb(0x20, 0x21); /*! start of hardware int's (0x20)*/
|
||||
outb(0x28, 0xA1); /*! start of hardware int's 2 (0x28)*/
|
||||
outb(0x04, 0x21); /*! 8259-1 is master*/
|
||||
outb(0x02, 0xA1); /*! 8259-2 is slave*/
|
||||
outb(0x01, 0x21); /*! 8086 mode for both*/
|
||||
outb(0x01, 0xA1);
|
||||
outb(0xFF, 0xA1); /*! mask off all interrupts for now*/
|
||||
outb(0xFB, 0x21); /*! mask all irq's but irq2 which is cascaded*/
|
||||
}
|
||||
|
||||
/*
|
||||
* I like the way Linus says it:
|
||||
! Well, that certainly wasn't fun :-(. Hopefully it works, and we don't
|
||||
! need no steenking BIOS anyway (except for the initial loading :-).
|
||||
*/
|
||||
#endif /* I8259 */
|
||||
43
src/pc80/isa-dma.c
Normal file
43
src/pc80/isa-dma.c
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#include <arch/io.h>
|
||||
|
||||
/* DMA controller registers */
|
||||
#define DMA1_CMD_REG 0x08 /* command register (w) */
|
||||
#define DMA1_STAT_REG 0x08 /* status register (r) */
|
||||
#define DMA1_REQ_REG 0x09 /* request register (w) */
|
||||
#define DMA1_MASK_REG 0x0A /* single-channel mask (w) */
|
||||
#define DMA1_MODE_REG 0x0B /* mode register (w) */
|
||||
#define DMA1_CLEAR_FF_REG 0x0C /* clear pointer flip-flop (w) */
|
||||
#define DMA1_TEMP_REG 0x0D /* Temporary Register (r) */
|
||||
#define DMA1_RESET_REG 0x0D /* Master Clear (w) */
|
||||
#define DMA1_CLR_MASK_REG 0x0E /* Clear Mask */
|
||||
#define DMA1_MASK_ALL_REG 0x0F /* all-channels mask (w) */
|
||||
|
||||
#define DMA2_CMD_REG 0xD0 /* command register (w) */
|
||||
#define DMA2_STAT_REG 0xD0 /* status register (r) */
|
||||
#define DMA2_REQ_REG 0xD2 /* request register (w) */
|
||||
#define DMA2_MASK_REG 0xD4 /* single-channel mask (w) */
|
||||
#define DMA2_MODE_REG 0xD6 /* mode register (w) */
|
||||
#define DMA2_CLEAR_FF_REG 0xD8 /* clear pointer flip-flop (w) */
|
||||
#define DMA2_TEMP_REG 0xDA /* Temporary Register (r) */
|
||||
#define DMA2_RESET_REG 0xDA /* Master Clear (w) */
|
||||
#define DMA2_CLR_MASK_REG 0xDC /* Clear Mask */
|
||||
#define DMA2_MASK_ALL_REG 0xDE /* all-channels mask (w) */
|
||||
|
||||
#define DMA_MODE_READ 0x44 /* I/O to memory, no autoinit, increment, single mode */
|
||||
#define DMA_MODE_WRITE 0x48 /* memory to I/O, no autoinit, increment, single mode */
|
||||
#define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */
|
||||
|
||||
#define DMA_AUTOINIT 0x10
|
||||
|
||||
|
||||
void isa_dma_init(void)
|
||||
{
|
||||
/* slave at 0x00 - 0x0f */
|
||||
/* master at 0xc0 - 0xdf */
|
||||
/* 0x80 - 0x8f DMA page registers */
|
||||
/* DMA: 0x00, 0x02, 0x4, 0x06 base address for DMA channel */
|
||||
outb(0, DMA1_RESET_REG);
|
||||
outb(0, DMA2_RESET_REG);
|
||||
outb(DMA_MODE_CASCADE, DMA2_MODE_REG);
|
||||
outb(0, DMA2_MASK_REG);
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
static char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
#include <cpu/p5/io.h>
|
||||
#include <arch/io.h>
|
||||
#include <subr.h>
|
||||
/* much better keyboard init courtesy ollie@sis.com.tw
|
||||
TODO: Typematic Setting, the keyboard is too slow for me */
|
||||
|
|
@ -13,7 +13,7 @@ void pc_keyboard_init()
|
|||
/* send cmd = 0xAA, self test 8042 */
|
||||
outb(0xaa, 0x64);
|
||||
|
||||
/* empty inut bufferm or any other command/data will be lost */
|
||||
/* empty input buffer or any other command/data will be lost */
|
||||
while ((inb(0x64) & 0x02))
|
||||
post_code(0);
|
||||
/* empty output buffer or any other command/data will be lost */
|
||||
|
|
@ -52,3 +52,4 @@ void pc_keyboard_init()
|
|||
if ((regval = inb(0x60) != 0xaa))
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
161
src/pc80/mc146818rtc.c
Normal file
161
src/pc80/mc146818rtc.c
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
#include <arch/io.h>
|
||||
#include <printk.h>
|
||||
|
||||
#define RTC_PORT(x) (0x70 + (x))
|
||||
|
||||
#define CMOS_READ(addr) ({ \
|
||||
outb_p((addr),RTC_PORT(0)); \
|
||||
inb_p(RTC_PORT(1)); \
|
||||
})
|
||||
|
||||
#define CMOS_WRITE(val, addr) ({ \
|
||||
outb_p((addr),RTC_PORT(0)); \
|
||||
outb_p((val),RTC_PORT(1)); \
|
||||
})
|
||||
|
||||
/* control registers - Moto names
|
||||
*/
|
||||
#define RTC_REG_A 10
|
||||
#define RTC_REG_B 11
|
||||
#define RTC_REG_C 12
|
||||
#define RTC_REG_D 13
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* register details
|
||||
**********************************************************************/
|
||||
#define RTC_FREQ_SELECT RTC_REG_A
|
||||
|
||||
/* update-in-progress - set to "1" 244 microsecs before RTC goes off the bus,
|
||||
* reset after update (may take 1.984ms @ 32768Hz RefClock) is complete,
|
||||
* totalling to a max high interval of 2.228 ms.
|
||||
*/
|
||||
# define RTC_UIP 0x80
|
||||
# define RTC_DIV_CTL 0x70
|
||||
/* divider control: refclock values 4.194 / 1.049 MHz / 32.768 kHz */
|
||||
# define RTC_REF_CLCK_4MHZ 0x00
|
||||
# define RTC_REF_CLCK_1MHZ 0x10
|
||||
# define RTC_REF_CLCK_32KHZ 0x20
|
||||
/* 2 values for divider stage reset, others for "testing purposes only" */
|
||||
# define RTC_DIV_RESET1 0x60
|
||||
# define RTC_DIV_RESET2 0x70
|
||||
/* Periodic intr. / Square wave rate select. 0=none, 1=32.8kHz,... 15=2Hz */
|
||||
# define RTC_RATE_SELECT 0x0F
|
||||
# define RTC_RATE_NONE 0x00
|
||||
# define RTC_RATE_32786HZ 0x01
|
||||
# define RTC_RATE_16384HZ 0x02
|
||||
# define RTC_RATE_8192HZ 0x03
|
||||
# define RTC_RATE_4096HZ 0x04
|
||||
# define RTC_RATE_2048HZ 0x05
|
||||
# define RTC_RATE_1024HZ 0x06
|
||||
# define RTC_RATE_512HZ 0x07
|
||||
# define RTC_RATE_256HZ 0x08
|
||||
# define RTC_RATE_128HZ 0x09
|
||||
# define RTC_RATE_64HZ 0x0a
|
||||
# define RTC_RATE_32HZ 0x0b
|
||||
# define RTC_RATE_16HZ 0x0c
|
||||
# define RTC_RATE_8HZ 0x0d
|
||||
# define RTC_RATE_4HZ 0x0e
|
||||
# define RTC_RATE_2HZ 0x0f
|
||||
|
||||
/**********************************************************************/
|
||||
#define RTC_CONTROL RTC_REG_B
|
||||
# define RTC_SET 0x80 /* disable updates for clock setting */
|
||||
# define RTC_PIE 0x40 /* periodic interrupt enable */
|
||||
# define RTC_AIE 0x20 /* alarm interrupt enable */
|
||||
# define RTC_UIE 0x10 /* update-finished interrupt enable */
|
||||
# define RTC_SQWE 0x08 /* enable square-wave output */
|
||||
# define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */
|
||||
# define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */
|
||||
# define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */
|
||||
|
||||
/**********************************************************************/
|
||||
#define RTC_INTR_FLAGS RTC_REG_C
|
||||
/* caution - cleared by read */
|
||||
# define RTC_IRQF 0x80 /* any of the following 3 is active */
|
||||
# define RTC_PF 0x40
|
||||
# define RTC_AF 0x20
|
||||
# define RTC_UF 0x10
|
||||
|
||||
/**********************************************************************/
|
||||
#define RTC_VALID RTC_REG_D
|
||||
# define RTC_VRT 0x80 /* valid RAM and time */
|
||||
/**********************************************************************/
|
||||
|
||||
|
||||
/* On PCs, the checksum is built only over bytes 16..45 */
|
||||
#define PC_CKS_RANGE_START 16
|
||||
#define PC_CKS_RANGE_END 45
|
||||
#define PC_CKS_LOC 46
|
||||
|
||||
static int rtc_checksum_valid(void)
|
||||
{
|
||||
int i;
|
||||
unsigned sum, old_sum;
|
||||
sum = 0;
|
||||
for(i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; i++) {
|
||||
sum += CMOS_READ(i);
|
||||
}
|
||||
sum &= 0xffff;
|
||||
old_sum = (CMOS_READ(PC_CKS_LOC) << 8) | CMOS_READ(PC_CKS_LOC+1);
|
||||
return sum == old_sum;
|
||||
}
|
||||
|
||||
static void rtc_set_checksum(void)
|
||||
{
|
||||
int i;
|
||||
unsigned sum;
|
||||
sum = 0;
|
||||
for(i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; i++) {
|
||||
sum += CMOS_READ(i);
|
||||
}
|
||||
sum &= 0xffff;
|
||||
CMOS_WRITE(((sum >> 8) & 0xff), PC_CKS_LOC);
|
||||
CMOS_WRITE(((sum >> 0) & 0xff), PC_CKS_LOC+1);
|
||||
}
|
||||
|
||||
#define RTC_CONTROL_DEFAULT (RTC_24H)
|
||||
#define RTC_FREQ_SELECT_DEFAULT (RTC_REF_CLCK_32KHZ | RTC_RATE_1024HZ)
|
||||
|
||||
#if 0 /* alpha setup */
|
||||
#undef RTC_CONTROL_DEFAULT
|
||||
#undef RTC_FREQ_SELECT_DEFAULT
|
||||
#define RTC_CONTROL_DEFAULT (RTC_SQWE | RTC_24H)
|
||||
#define RTC_FREQ_SELECT_DEFAULT (RTC_REF_CLCK_32KHZ | RTC_RATE_1024HZ)
|
||||
#endif
|
||||
void rtc_init(void)
|
||||
{
|
||||
unsigned char x;
|
||||
int cmos_valid;
|
||||
/* See if there has been a CMOS power problem. */
|
||||
x = CMOS_READ(RTC_VALID);
|
||||
cmos_valid = !(x & RTC_VRT);
|
||||
|
||||
/* See if there is a CMOS checksum error */
|
||||
cmos_valid = rtc_checksum_valid();
|
||||
|
||||
if (!cmos_valid) {
|
||||
int i;
|
||||
printk_warning("RTC power problem, zeroing cmos\n");
|
||||
for(i = 0x0; i < 128; i++) {
|
||||
CMOS_WRITE(0, i);
|
||||
}
|
||||
|
||||
/* Now setup a default date of Sat 1 January 2000 */
|
||||
CMOS_WRITE(0, 0x00); /* seconds */
|
||||
CMOS_WRITE(0, 0x02); /* minutes */
|
||||
CMOS_WRITE(1, 0x04); /* hours */
|
||||
CMOS_WRITE(7, 0x06); /* day of week */
|
||||
CMOS_WRITE(1, 0x07); /* day of month */
|
||||
CMOS_WRITE(1, 0x08); /* month */
|
||||
CMOS_WRITE(0, 0x09); /* year */
|
||||
}
|
||||
/* Setup the real time clock */
|
||||
CMOS_WRITE(RTC_CONTROL_DEFAULT, RTC_CONTROL);
|
||||
/* Setup the frequency it operates at */
|
||||
CMOS_WRITE(RTC_FREQ_SELECT_DEFAULT, RTC_FREQ_SELECT);
|
||||
/* Make certain we have a valid checksum */
|
||||
rtc_set_checksum();
|
||||
/* Clear any pending interrupts */
|
||||
(void) CMOS_READ(RTC_INTR_FLAGS);
|
||||
}
|
||||
38
src/sdram/generic_dump_spd.inc
Normal file
38
src/sdram/generic_dump_spd.inc
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
dump_spd_registers:
|
||||
movl $((0 << 8) | SMBUS_MEM_DEVICE_START), %ebx
|
||||
dump_spd_reg_dimm:
|
||||
TTYS0_TX_CHAR($'\r')
|
||||
TTYS0_TX_CHAR($'\n')
|
||||
TTYS0_TX_CHAR($'d')
|
||||
TTYS0_TX_CHAR($'i')
|
||||
TTYS0_TX_CHAR($'m')
|
||||
TTYS0_TX_CHAR($'m')
|
||||
TTYS0_TX_CHAR($' ')
|
||||
movb %bl, %al
|
||||
CALLSP(ttys0_tx_hex8)
|
||||
TTYS0_TX_CHAR($'\r')
|
||||
TTYS0_TX_CHAR($'\n')
|
||||
dump_spd_reg_byte:
|
||||
CALLSP(smbus_read_byte)
|
||||
jz dump_spd_reg_next_dimm
|
||||
|
||||
CALLSP(ttys0_tx_hex8)
|
||||
TTYS0_TX_CHAR($' ')
|
||||
incb %bh
|
||||
testb $0x0F, %bh
|
||||
jnz dump_spd_reg_next_byte
|
||||
TTYS0_TX_CHAR($'\r')
|
||||
TTYS0_TX_CHAR($'\n')
|
||||
|
||||
dump_spd_reg_next_byte:
|
||||
cmpb $0, %bh
|
||||
jne dump_spd_reg_byte
|
||||
|
||||
dump_spd_reg_next_dimm:
|
||||
TTYS0_TX_CHAR($'\r')
|
||||
TTYS0_TX_CHAR($'\n')
|
||||
xorb %bh, %bh
|
||||
add $SMBUS_MEM_DEVICE_INC, %bl
|
||||
cmpb $(SMBUS_MEM_DEVICE_END + SMBUS_MEM_DEVICE_INC), %bl
|
||||
jne dump_spd_reg_dimm
|
||||
dump_spd_registers_out:
|
||||
73
src/sdram/generic_sdram_enable.inc
Normal file
73
src/sdram/generic_sdram_enable.inc
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
jmp generic_sdram_enable_out
|
||||
|
||||
ram_enable_1: .string "Ram Enable 1\r\n"
|
||||
ram_enable_2: .string "Ram Enable 2\r\n"
|
||||
ram_enable_3: .string "Ram Enable 3\r\n"
|
||||
ram_enable_4: .string "Ram Enable 4\r\n"
|
||||
ram_enable_5: .string "Ram Enable 5\r\n"
|
||||
|
||||
/* Estimate that SLOW_DOWN_IO takes about 50&76us*/
|
||||
/* delay for 200us */
|
||||
|
||||
#define DO_DELAY \
|
||||
movl $4, %edi ; \
|
||||
1: SLOW_DOWN_IO ; \
|
||||
decl %edi ; \
|
||||
jnz 1b
|
||||
|
||||
|
||||
enable_sdram:
|
||||
/* now the fun begins.
|
||||
turn on the dram and wait a while (this from the intel book)
|
||||
turn power on and set the nop bit too
|
||||
*/
|
||||
TTYS0_TX_STRING($ram_enable_1)
|
||||
/* SDRAMC */
|
||||
SET_RAM_COMMAND(RAM_COMMAND_NOP)
|
||||
|
||||
DO_DELAY
|
||||
|
||||
ASSERT_RAM_COMMAND() /* nop command */
|
||||
|
||||
/* Precharge all */
|
||||
SET_RAM_COMMAND(RAM_COMMAND_PRECHARGE)
|
||||
ASSERT_RAM_COMMAND()
|
||||
|
||||
/* wait until the all banks idle state... */
|
||||
|
||||
TTYS0_TX_STRING($ram_enable_2)
|
||||
|
||||
/* Now we need 8 AUTO REFRESH / CBR cycles to be performed */
|
||||
|
||||
SET_RAM_COMMAND(RAM_COMMAND_CBR)
|
||||
ASSERT_RAM_COMMAND()
|
||||
ASSERT_RAM_COMMAND()
|
||||
ASSERT_RAM_COMMAND()
|
||||
ASSERT_RAM_COMMAND()
|
||||
ASSERT_RAM_COMMAND()
|
||||
ASSERT_RAM_COMMAND()
|
||||
ASSERT_RAM_COMMAND()
|
||||
ASSERT_RAM_COMMAND()
|
||||
|
||||
TTYS0_TX_STRING($ram_enable_3)
|
||||
|
||||
/* mode register set */
|
||||
SET_RAM_MODE_REGISTER
|
||||
|
||||
/* MAx[14:0] lines,
|
||||
* MAx[2:0 ] 010 == burst mode of 4
|
||||
* MAx[3:3 ] 1 == interleave wrap type
|
||||
* MAx[4:4 ] == CAS# latency bit
|
||||
* MAx[6:5 ] == 01
|
||||
* MAx[12:7] == 0
|
||||
*/
|
||||
|
||||
TTYS0_TX_STRING($ram_enable_4)
|
||||
|
||||
/* normal operation */
|
||||
SET_RAM_COMMAND(RAM_COMMAND_NONE)
|
||||
|
||||
TTYS0_TX_STRING($ram_enable_5)
|
||||
RET_LABEL(enable_sdram)
|
||||
|
||||
generic_sdram_enable_out:
|
||||
102
src/sdram/generic_zero_ecc_sdram.inc
Normal file
102
src/sdram/generic_zero_ecc_sdram.inc
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
jmp ecc_ram_initialize
|
||||
|
||||
ecc_ram_1: .string "ecc_ram_1\r\n"
|
||||
ecc_ram_2: .string "ecc_ram_2\r\n"
|
||||
ecc_ram_3: .string "ecc_ram_3\r\n"
|
||||
ecc_ram_4: .string "ecc_ram_4\r\n"
|
||||
|
||||
ecc_ram_initialize:
|
||||
TTYS0_TX_STRING($ecc_ram_1)
|
||||
CALL_LABEL(get_ecc_ram_size_bytes_ebx)
|
||||
|
||||
/* If we don't have an ECC SDRAM size skip the zeroing */
|
||||
testl %ebx, %ebx
|
||||
jz zero_ecc_ram_out
|
||||
movl %ebx, %ebp
|
||||
|
||||
/* Compute the next greater power of two memory size, to use in the mtrrs */
|
||||
bsrl %ebp, %ecx
|
||||
movl $1, %esi
|
||||
shll %cl, %esi
|
||||
/* See if I need to round up */
|
||||
subl $1, %esi
|
||||
testl %esi, %ebp
|
||||
jz 1f
|
||||
incl %ecx
|
||||
1: movl $1, %esi
|
||||
shll %cl, %esi
|
||||
|
||||
/* Set caching on all of memory into write-combining mode.
|
||||
* So we can zero it quickly.
|
||||
*/
|
||||
/* Disable the cache while we set up a new MTRR over memory */
|
||||
movl %cr0, %eax
|
||||
orl $0x40000000, %eax
|
||||
movl %eax, %cr0
|
||||
|
||||
movl $0x200, %ecx /* mtrr[0] physical base register */
|
||||
movl $0x00000000, %edx
|
||||
movl $0x00000001, %eax
|
||||
wrmsr
|
||||
|
||||
movl $0x201, %ecx /* mtrr[0] physical mask register */
|
||||
movl $0x0000000f, %edx
|
||||
xorl %eax, %eax
|
||||
subl %esi, %eax
|
||||
andl $0xfffff000, %eax
|
||||
orl $0x800, %eax
|
||||
wrmsr
|
||||
|
||||
/* Reenable the cache now that the mtrr is set up */
|
||||
movl %cr0, %eax
|
||||
andl $0x9fffffff, %eax
|
||||
movl %eax, %cr0
|
||||
|
||||
/* Now zero the memory */
|
||||
TTYS0_TX_STRING($ecc_ram_2)
|
||||
cld
|
||||
|
||||
#if !defined(HAVE_PC80_MEMORY_HOLE)
|
||||
/* The 640KB - 1MB memory should not be enabled at this point. */
|
||||
xorl %eax, %eax
|
||||
xorl %edi, %edi
|
||||
movl %ebp, %ecx
|
||||
shrl $2, %ecx
|
||||
rep stosl
|
||||
|
||||
#else /* HAVE_PC80_MEMORY_HOLE */
|
||||
|
||||
xorl %eax, %eax /* zero */
|
||||
xorl %edi, %edi /* destination */
|
||||
movl $0x28000,%ecx
|
||||
rep stosl
|
||||
|
||||
xorl %eax, %eax
|
||||
movl $0x100000, %edi
|
||||
movl %ebp, %ecx
|
||||
subl %edi, %ecx
|
||||
shrl $2, %ecx
|
||||
rep stosl
|
||||
#endif /* HAVE_PC80_MEMORY_HOLE */
|
||||
|
||||
TTYS0_TX_STRING($ecc_ram_3)
|
||||
|
||||
/* Change caching on memory from write-combining to write-back. */
|
||||
/* Disable the cache while we set up a new MTRR over memory */
|
||||
movl %cr0, %eax
|
||||
orl $0x40000000, %eax
|
||||
movl %eax, %cr0
|
||||
|
||||
movl $0x200, %ecx
|
||||
movl $0x00000000, %edx
|
||||
movl $0x00000006, %eax
|
||||
wrmsr
|
||||
|
||||
/* Reenable the cache now that the mtrr is set up */
|
||||
movl %cr0, %eax
|
||||
andl $0x9fffffff, %eax
|
||||
movl %eax, %cr0
|
||||
|
||||
zero_ecc_ram_out:
|
||||
TTYS0_TX_STRING($ecc_ram_4)
|
||||
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/* Useful macros PCIBUS, and SMBUS functions for getting DRAM going. */
|
||||
/* courtesy Eric Beiderman of linuxnetworx.com */
|
||||
/* courtesy Eric Biederman of linuxnetworx.com */
|
||||
|
||||
#define CS_WRITE_BYTE(addr, byte) \
|
||||
movl $addr, %eax ; \
|
||||
|
|
|
|||
3
src/southbridge/amd/amd766/Config
Normal file
3
src/southbridge/amd/amd766/Config
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
object southbridge.o
|
||||
object nvram.o
|
||||
|
||||
10
src/southbridge/amd/amd766/disable_watchdog.inc
Normal file
10
src/southbridge/amd/amd766/disable_watchdog.inc
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#define PM_DEV_FN (AMD766_DEV + 0x300)
|
||||
/* Disable the watchdog timer */
|
||||
movl $(0x80000000 | PM_DEV_FN | 0x40), %eax
|
||||
movw $0xcf8, %dx
|
||||
outl %eax, %dx
|
||||
movw $0xcfd, %dx
|
||||
inb %dx, %al
|
||||
orb $0x44, %al
|
||||
outb %al, %dx
|
||||
|
||||
16
src/southbridge/amd/amd766/lpc_com1.inc
Normal file
16
src/southbridge/amd/amd766/lpc_com1.inc
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/* enable LPC superio on the AMD 766 south bridge */
|
||||
movl $(0x80000000 | AMD766_DEV | 0x54), %eax
|
||||
movw $0xcf8, %dx
|
||||
outl %eax, %dx
|
||||
movw $0xcfc, %dx
|
||||
inb %dx, %al
|
||||
orb $0x30, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* enable LPC serial port 0x3f8 */
|
||||
movl $(0x80000000 | AMD766_DEV | 0x50), %eax
|
||||
movw $0xcf8, %dx
|
||||
outl %eax, %dx
|
||||
movw $0xcfe, %dx
|
||||
movb $0x8, %al
|
||||
outb %al, %dx
|
||||
18
src/southbridge/amd/amd766/nvram.c
Normal file
18
src/southbridge/amd/amd766/nvram.c
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#include <pci_ids.h>
|
||||
#include <pci.h>
|
||||
#include <cpu/p5/io.h>
|
||||
#include <part/nvram.h>
|
||||
|
||||
void nvram_on(void)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, 0);
|
||||
if (dev != NULL) {
|
||||
u8 segen;
|
||||
u32 regval;
|
||||
pci_read_config_byte(dev, 0x43, &segen);
|
||||
/* Enable 4MB rom access at 0xFFC00000 - 0xFFFFFFFF */
|
||||
segen |= 0x80;
|
||||
pci_write_config_byte(dev, 0x43, segen);
|
||||
}
|
||||
}
|
||||
182
src/southbridge/amd/amd766/smbus.inc
Normal file
182
src/southbridge/amd/amd766/smbus.inc
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
jmp smbus_code_end
|
||||
|
||||
#define PM_DEV_FN (AMD766_DEV + 0x300)
|
||||
|
||||
|
||||
#define PM_BASE 0xDD00
|
||||
#define SMBUS_IO_BASE (PM_BASE + 0xE0)
|
||||
#define SMB_GSTAT (SMBUS_IO_BASE + 0x0)
|
||||
#define SMB_GCTL (SMBUS_IO_BASE + 0x2)
|
||||
#define SMB_HOST_ADDR (SMBUS_IO_BASE + 0x4)
|
||||
#define SMB_HOST_DAT (SMBUS_IO_BASE + 0x6)
|
||||
#define SMB_HOST_CMD (SMBUS_IO_BASE + 0x8)
|
||||
#define SMB_BLKDAT (SMBUS_IO_BASE + 0x9)
|
||||
#define SMB_SLAVE_DAT (SMBUS_IO_BASE + 0xa)
|
||||
#define SMB_SLAVE_DEV (SMBUS_IO_BASE + 0xc)
|
||||
#define SMB_SLAVE_ADDR (SMBUS_IO_BASE + 0xe)
|
||||
#define SMB_SNOOP_ADDR (SMBUS_IO_BASE + 0xf)
|
||||
|
||||
#define SMB_GSTAT_ABORT (1 << 0)
|
||||
#define SMB_GSTAT_COLLISION (1 << 1)
|
||||
#define SMB_GSTAT_PROTO_ERROR (1 << 2)
|
||||
#define SMB_GSTAT_HOST_BUSY (1 << 3)
|
||||
#define SMB_GSTAT_COMPLETE (1 << 4)
|
||||
#define SMB_GSTAT_TIMEOUT (1 << 5)
|
||||
#define SMB_GSTAT_SNOOP_MATCH (1 << 8)
|
||||
#define SMB_GSTAT_SLAVE_MATCH (1 << 9)
|
||||
#define SMB_GSTAT_ALERT (1 << 10)
|
||||
#define SMB_GSTAT_BUSY (1 << 11)
|
||||
|
||||
/* The low bit of the address specifies read or write */
|
||||
#define SMB_GCTL_QUICK_COMMAND 0
|
||||
#define SMB_GCTL_SEND_RECV_BYTE 1
|
||||
#define SMB_GCTL_WRITE_READ_BYTE 2
|
||||
#define SMB_GCTL_WRITE_READ_WORD 3
|
||||
#define SMB_GCTL_PROCESS_CALL 4
|
||||
#define SMB_GCTL_WRITE_READ_BLOCK 5
|
||||
|
||||
#define SMB_GCTL_HOST_START (1 << 3)
|
||||
#define SMB_GCTL_HOST_INTERRUPT (1 << 4)
|
||||
#define SMB_GCTL_ABORT (1 << 5)
|
||||
#define SMB_GCTL_SNOOP (1 << 8)
|
||||
#define SMB_GCTL_SLAVE_INTERRUPT (1 << 9)
|
||||
#define SMB_GCTL_ALERT_INTERRUPT (1 << 10)
|
||||
|
||||
|
||||
enable_smbus:
|
||||
/* Enable PM IO C3A41 */
|
||||
movl $(0x80000000 | PM_DEV_FN | 0x40), %eax
|
||||
movw $0xcf8, %dx
|
||||
outl %eax, %dx
|
||||
movw $0xcfd, %dx
|
||||
inb %dx, %al
|
||||
orb $0x80, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* Set the PM registers to 0xDD00 */
|
||||
movl $(0x80000000 | PM_DEV_FN | 0x58), %eax
|
||||
mov $0xcf8, %dx
|
||||
outl %eax, %dx
|
||||
movw $0xcfc, %dx
|
||||
movl $(PM_BASE | 0x01), %eax
|
||||
outl %eax, %dx
|
||||
|
||||
RET_LABEL(enable_smbus)
|
||||
|
||||
/*
|
||||
* Routine: setup_smbus
|
||||
* Arguments: none
|
||||
* Results: none
|
||||
* Trashed: eax, edx
|
||||
* Effects: The smbus is enabled
|
||||
*/
|
||||
setup_smbus:
|
||||
movl $(SMB_GSTAT_ABORT | SMB_GSTAT_COLLISION | \
|
||||
SMB_GSTAT_PROTO_ERROR | SMB_GSTAT_COMPLETE | \
|
||||
SMB_GSTAT_TIMEOUT | SMB_GSTAT_SNOOP_MATCH | \
|
||||
SMB_GSTAT_SLAVE_MATCH | SMB_GSTAT_ALERT),%eax
|
||||
movw $SMB_GSTAT, %dx
|
||||
outb %al, %dx
|
||||
RET_LABEL(setup_smbus)
|
||||
|
||||
/*
|
||||
* Routine: smbus_wait_until_ready
|
||||
* Arguments: none
|
||||
* Results: none
|
||||
* Trashed: eax, edx
|
||||
* Effects: Upon return the smbus is ready to accept commands
|
||||
*/
|
||||
smbus_wait_until_ready:
|
||||
movl $SMB_GSTAT, %edx
|
||||
1: inb %dx, %al
|
||||
testb $SMB_GSTAT_HOST_BUSY, %al
|
||||
jnz 1b
|
||||
RET_LABEL(smbus_wait_until_ready)
|
||||
|
||||
|
||||
/*
|
||||
* Routine: smbus_wait_until_done
|
||||
* Arguments: none
|
||||
* Results: none
|
||||
* Trashed: eax, edx
|
||||
* Effects: Upon return the smbus has completed it's most recent transation
|
||||
*/
|
||||
smbus_wait_until_done:
|
||||
movl $SMB_GSTAT, %edx
|
||||
1: inb %dx, %al
|
||||
testb $(SMB_GSTAT_HOST_BUSY), %al
|
||||
jnz 1b
|
||||
2: testb $(~(SMB_GSTAT_HOST_BUSY)), %al
|
||||
jnz 3f
|
||||
inb %dx, %al
|
||||
testb $(~(SMB_GSTAT_HOST_BUSY)), %al
|
||||
jz 2b
|
||||
3: RET_LABEL(smbus_wait_until_done)
|
||||
|
||||
|
||||
/*
|
||||
* Routine: smbus_read_byte
|
||||
* Arguments: %esp return address
|
||||
* %bl device on the smbus to read from
|
||||
* %bh address on the smbus to read
|
||||
*
|
||||
* Results: zf clear
|
||||
* byte read %eax
|
||||
* On Error:
|
||||
* zf set
|
||||
* %eax trashed
|
||||
*
|
||||
* Trashed: %edx, %eax
|
||||
* Effects: reads a byte off of the smbus
|
||||
*/
|
||||
|
||||
smbus_read_byte:
|
||||
/* poll until the smbus is ready for commands */
|
||||
CALL_LABEL(smbus_wait_until_ready)
|
||||
|
||||
/* clear any lingering errors, so that the transaction will run */
|
||||
movw $SMB_GSTAT, %dx
|
||||
inw %dx, %ax
|
||||
outw %ax, %dx
|
||||
|
||||
/* set the device I'm talking to, and set the low bit for a read */
|
||||
movw $SMB_HOST_ADDR, %dx
|
||||
xorl %eax, %eax
|
||||
movb %bl /* device */, %al
|
||||
shlb $1, %al
|
||||
orb $1, %al
|
||||
outw %ax, %dx
|
||||
|
||||
/* set the command address... */
|
||||
movw $SMB_HOST_CMD, %dx
|
||||
movb %bh /* address */, %al
|
||||
outb %al, %dx
|
||||
|
||||
/* clear the data byte */
|
||||
movw $SMB_HOST_DAT, %dx
|
||||
xorl %eax, %eax
|
||||
outw %ax, %dx
|
||||
|
||||
/* start a byte read, with interrupts disabled */
|
||||
movw $SMB_GCTL, %dx
|
||||
movl $(SMB_GCTL_HOST_START | SMB_GCTL_WRITE_READ_BYTE), %eax
|
||||
outw %ax, %dx
|
||||
|
||||
/* poll for transaction completion */
|
||||
CALL_LABEL(smbus_wait_until_done)
|
||||
|
||||
/* read the results and see if we succeded */
|
||||
movl $SMB_GSTAT, %edx
|
||||
inb %dx, %al
|
||||
testb $(SMB_GSTAT_COMPLETE), %al
|
||||
jz 1f
|
||||
movw $SMB_HOST_DAT, %dx
|
||||
inb %dx, %al
|
||||
1:
|
||||
RETSP
|
||||
|
||||
|
||||
|
||||
smbus_code_end:
|
||||
CALL_LABEL(enable_smbus)
|
||||
CALL_LABEL(setup_smbus)
|
||||
7
src/southbridge/amd/amd766/southbridge.c
Normal file
7
src/southbridge/amd/amd766/southbridge.c
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
void southbridge_fixup(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
51
src/superio/winbond/w83627hf/setup_serial.inc
Normal file
51
src/superio/winbond/w83627hf/setup_serial.inc
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Enable the peripheral devices on the windbond w83627hf
|
||||
*/
|
||||
|
||||
|
||||
/* The base address is 0x2e,0x4e depending on config bytes */
|
||||
|
||||
#define SIO_INDEX SIO_BASE
|
||||
#define SIO_DATA SIO_BASE+1
|
||||
|
||||
#define SIO_COM1_DEVICE 2
|
||||
|
||||
#define SIO_ENTER_PNP_MODE() \
|
||||
movw $SIO_BASE, %dx ; \
|
||||
movb $0x87, %al ; \
|
||||
outb %al, %dx ; \
|
||||
outb %al, %dx
|
||||
|
||||
|
||||
#define SIO_EXIT_PNP_MODE() \
|
||||
movw $SIO_BASE, %dx ; \
|
||||
movb $0xaa, %al ; \
|
||||
outb %al, %dx
|
||||
|
||||
#define SIO_WRITE_CONFIG(value, reg) \
|
||||
movw $SIO_BASE, %dx ; \
|
||||
movb $reg, %al ; \
|
||||
outb %al, %dx ; \
|
||||
incw %dx ; \
|
||||
movb $value, %al ; \
|
||||
outb %al, %dx
|
||||
|
||||
#define SIO_READ_CONFIG(value, reg) \
|
||||
movw $SIO_BASE, %dx ; \
|
||||
movb $reg, %al ; \
|
||||
outb %al, %dx ; \
|
||||
incw %dx ; \
|
||||
inb %al, %dx
|
||||
|
||||
#define SIO_SET_LOGICAL_DEVICE(device) \
|
||||
SIO_WRITE_CONFIG(device, 0x07)
|
||||
|
||||
|
||||
/* enable serial 1 */
|
||||
SIO_ENTER_PNP_MODE()
|
||||
SIO_SET_LOGICAL_DEVICE(SIO_COM1_DEVICE)
|
||||
SIO_WRITE_CONFIG(1, 0x30)
|
||||
SIO_WRITE_CONFIG(0x3, 0x60)
|
||||
SIO_WRITE_CONFIG(0xf8, 0x61)
|
||||
SIO_EXIT_PNP_MODE()
|
||||
|
||||
259
src/superio/winbond/w83627hf/superio.c
Normal file
259
src/superio/winbond/w83627hf/superio.c
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
#include <pci.h>
|
||||
#include <cpu/p5/io.h>
|
||||
#include <serial_subr.h>
|
||||
#include <printk.h>
|
||||
|
||||
#define FLOPPY_DEVICE 0
|
||||
#define PARALLEL_DEVICE 1
|
||||
#define COM1_DEVICE 2
|
||||
#define COM2_DEVICE 3
|
||||
#define KBC_DEVICE 5
|
||||
#define CIR_DEVICE 6
|
||||
#define GAME_PORT_DEVICE 7
|
||||
#define GPIO_PORT2_DEVICE 8
|
||||
#define GPIO_PORT3_DEVICE 9
|
||||
#define ACPI_DEVICE 0xa
|
||||
#define HW_MONITOR_DEVICE 0xb
|
||||
|
||||
|
||||
#define FLOPPY_DEFAULT_IOBASE 0x3f0
|
||||
#define FLOPPY_DEFAULT_IRQ 6
|
||||
#define FLOPPY_DEFAULT_DRQ 2
|
||||
#define PARALLEL_DEFAULT_IOBASE 0x378
|
||||
#define PARALLEL_DEFAULT_IRQ 7
|
||||
#define PARALLEL_DEFAULT_DRQ 4 /* No dma */
|
||||
#define COM1_DEFAULT_IOBASE 0x3f8
|
||||
#define COM1_DEFAULT_IRQ 4
|
||||
#define COM1_DEFAULT_BAUD 115200
|
||||
#define COM2_DEFAULT_IOBASE 0x2f8
|
||||
#define COM2_DEFAULT_IRQ 3
|
||||
#define COM2_DEFAULT_BAUD 115200
|
||||
#define KBC_DEFAULT_IOBASE0 0x60
|
||||
#define KBC_DEFAULT_IOBASE1 0x64
|
||||
#define KBC_DEFAULT_IRQ0 0x1
|
||||
#define KBC_DEFAULT_IRQ1 0xc
|
||||
|
||||
|
||||
static void enter_pnp(struct superio *sio)
|
||||
{
|
||||
outb(0x87, sio->port);
|
||||
outb(0x87, sio->port);
|
||||
}
|
||||
|
||||
static void exit_pnp(struct superio *sio)
|
||||
{
|
||||
outb(0xaa, sio->port);
|
||||
}
|
||||
|
||||
static void write_config(struct superio *sio,
|
||||
unsigned char value, unsigned char reg)
|
||||
{
|
||||
outb(reg, sio->port);
|
||||
outb(value, sio->port +1);
|
||||
}
|
||||
|
||||
static unsigned char read_config(struct superio *sio, unsigned char reg)
|
||||
{
|
||||
outb(reg, sio->port);
|
||||
return inb(sio->port +1);
|
||||
}
|
||||
static void set_logical_device(struct superio *sio, int device)
|
||||
{
|
||||
write_config(sio, device, 0x07);
|
||||
}
|
||||
|
||||
static void set_enable(struct superio *sio, int enable)
|
||||
{
|
||||
write_config(sio, enable?0x1:0x0, 0x30);
|
||||
#if 0
|
||||
if (enable) {
|
||||
printk_debug("enabled superio device: %d\n",
|
||||
read_config(sio, 0x07));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void set_iobase0(struct superio *sio, unsigned iobase)
|
||||
{
|
||||
write_config(sio, (iobase >> 8) & 0xff, 0x60);
|
||||
write_config(sio, iobase & 0xff, 0x61);
|
||||
}
|
||||
|
||||
static void set_iobase1(struct superio *sio, unsigned iobase)
|
||||
{
|
||||
write_config(sio, (iobase >> 8) & 0xff, 0x62);
|
||||
write_config(sio, iobase & 0xff, 0x63);
|
||||
}
|
||||
|
||||
static void set_irq0(struct superio *sio, unsigned irq)
|
||||
{
|
||||
write_config(sio, irq, 0x70);
|
||||
}
|
||||
|
||||
static void set_irq1(struct superio *sio, unsigned irq)
|
||||
{
|
||||
write_config(sio, irq, 0x72);
|
||||
}
|
||||
|
||||
static void set_drq(struct superio *sio, unsigned drq)
|
||||
{
|
||||
write_config(sio, drq & 0xff, 0x74);
|
||||
}
|
||||
|
||||
static void enable_com(struct superio *sio,
|
||||
struct com_ports *com, int device)
|
||||
{
|
||||
int divisor = 115200/com->baud;
|
||||
printk_debug("Enabling com device: %02x\n", device);
|
||||
printk_debug(" iobase = 0x%04x irq=%d\n", com->base, com->irq);
|
||||
/* Select the device */
|
||||
set_logical_device(sio, device);
|
||||
/* Disable it while it is initialized */
|
||||
set_enable(sio, 0);
|
||||
if (com->enable) {
|
||||
set_iobase0(sio, com->base);
|
||||
set_irq0(sio, com->irq);
|
||||
/* We are initialized so enable the device */
|
||||
set_enable(sio, 1);
|
||||
/* Now initialize the com port */
|
||||
uart_init(com->base, divisor);
|
||||
}
|
||||
}
|
||||
|
||||
static void enable_floppy(struct superio *sio)
|
||||
{
|
||||
/* Remember the default resources */
|
||||
unsigned iobase = FLOPPY_DEFAULT_IOBASE;
|
||||
unsigned irq = FLOPPY_DEFAULT_IRQ;
|
||||
unsigned drq = FLOPPY_DEFAULT_DRQ;
|
||||
/* Select the device */
|
||||
set_logical_device(sio, FLOPPY_DEVICE);
|
||||
/* Disable it while initializing */
|
||||
set_enable(sio, 0);
|
||||
if (sio->lpt) {
|
||||
set_iobase0(sio, iobase);
|
||||
set_irq0(sio, irq);
|
||||
set_drq(sio, drq);
|
||||
set_enable(sio, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void enable_parallel(struct superio *sio)
|
||||
{
|
||||
/* Remember the default resources */
|
||||
unsigned iobase = PARALLEL_DEFAULT_IOBASE;
|
||||
unsigned irq = PARALLEL_DEFAULT_IRQ;
|
||||
unsigned drq = PARALLEL_DEFAULT_DRQ;
|
||||
/* Select the device */
|
||||
set_logical_device(sio, PARALLEL_DEVICE);
|
||||
/* Disable it while initializing */
|
||||
set_enable(sio, 0);
|
||||
if (sio->lpt) {
|
||||
set_iobase0(sio, iobase);
|
||||
set_irq0(sio, irq);
|
||||
set_drq(sio, drq);
|
||||
set_enable(sio, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void enable_keyboard(struct superio *sio)
|
||||
{
|
||||
/* Remember the default resources */
|
||||
unsigned iobase0 = KBC_DEFAULT_IOBASE0;
|
||||
unsigned iobase1 = KBC_DEFAULT_IOBASE1;
|
||||
unsigned irq0 = KBC_DEFAULT_IRQ0;
|
||||
unsigned irq1 = KBC_DEFAULT_IRQ1;
|
||||
/* Select the device */
|
||||
set_logical_device(sio, KBC_DEVICE);
|
||||
/* Disable it while initializing */
|
||||
set_enable(sio, 0);
|
||||
if (sio->lpt) {
|
||||
set_iobase0(sio, iobase0);
|
||||
set_iobase1(sio, iobase1);
|
||||
set_irq0(sio, irq0);
|
||||
set_irq1(sio, irq1);
|
||||
set_enable(sio, 1);
|
||||
/* Initialize the keyboard */
|
||||
pc_keyboard_init();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static void setup_acpi_registers(struct superio *sio)
|
||||
{
|
||||
set_logical_device(sio, ACPI_DEVICE);
|
||||
/* Enable power on after power fail */
|
||||
write_config(sio, (1 << 7)|(0 <<5), 0xe4);
|
||||
set_enable(sio, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void enable_devices(struct superio *sio)
|
||||
{
|
||||
if (sio->port == 0) {
|
||||
sio->port = sio->super->defaultport;
|
||||
}
|
||||
if (sio->com1.base == 0) sio->com1.base = COM1_DEFAULT_IOBASE;
|
||||
if (sio->com1.irq == 0) sio->com1.irq = COM1_DEFAULT_IRQ;
|
||||
if (sio->com1.baud == 0) sio->com1.baud = COM1_DEFAULT_BAUD;
|
||||
if (sio->com2.base == 0) sio->com2.base = COM2_DEFAULT_IOBASE;
|
||||
if (sio->com2.irq == 0) sio->com2.irq = COM2_DEFAULT_IRQ;
|
||||
if (sio->com2.baud == 0) sio->com2.baud = COM2_DEFAULT_BAUD;
|
||||
|
||||
enter_pnp(sio);
|
||||
|
||||
/* enable floppy */
|
||||
enable_floppy(sio);
|
||||
|
||||
/* enable parallel */
|
||||
enable_parallel(sio);
|
||||
|
||||
/* enable com1 */
|
||||
enable_com(sio, &sio->com1, COM1_DEVICE);
|
||||
|
||||
/* enable com2 */
|
||||
enable_com(sio, &sio->com2, COM2_DEVICE);
|
||||
|
||||
/* enable keyboard */
|
||||
enable_keyboard(sio);
|
||||
|
||||
/* disable cir */
|
||||
set_logical_device(sio, CIR_DEVICE);
|
||||
set_enable(sio, 0);
|
||||
|
||||
/* disable game */
|
||||
set_logical_device(sio, GAME_PORT_DEVICE);
|
||||
set_enable(sio, 0);
|
||||
|
||||
/* disable gpio_port2 */
|
||||
set_logical_device(sio, GPIO_PORT2_DEVICE);
|
||||
set_enable(sio, 0);
|
||||
|
||||
/* disable gpio_port3 */
|
||||
set_logical_device(sio, GPIO_PORT3_DEVICE);
|
||||
set_enable(sio, 0);
|
||||
|
||||
/* disable acpi */
|
||||
set_logical_device(sio, ACPI_DEVICE);
|
||||
set_enable(sio, 0);
|
||||
|
||||
/* disable hw monitor */
|
||||
set_logical_device(sio, HW_MONITOR_DEVICE);
|
||||
set_enable(sio, 0);
|
||||
|
||||
#if 0
|
||||
/* setup acpi registers so I am certain to get
|
||||
* power on after power fail.
|
||||
*/
|
||||
setup_acpi_registers(sio);
|
||||
#endif
|
||||
|
||||
write_config(sio, 1, 0x30);
|
||||
exit_pnp(sio);
|
||||
}
|
||||
|
||||
/* The base address is either 0x2e or 0x4e */
|
||||
struct superio_control superio_winbond_w83627hf_control = {
|
||||
(void *)0, enable_devices, (void *)0, 0x2e, "w83627hf"
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue