Commit 35231647 authored by Richard Henderson's avatar Richard Henderson

Merge

parents 5ad0c942 2192cb52
......@@ -458,6 +458,11 @@ config ALPHA_SRM
If unsure, say N.
config EARLY_PRINTK
bool
depends on ALPHA_GENERIC || ALPHA_SRM
default y
config ALPHA_EISA
bool
depends on ALPHA_ALCOR || ALPHA_MIKASA || ALPHA_SABLE || ALPHA_NORITAKE || ALPHA_RAWHIDE
......
......@@ -33,8 +33,13 @@ obj-y += err_titan.o err_marvel.o
obj-y += es1888.o smc37c669.o smc37c93x.o ns87312.o gct.o
obj-y += srmcons.o
else
# Misc support
obj-$(CONFIG_ALPHA_SRM) += srmcons.o
# Core logic support
obj-$(CONFIG_ALPHA_APECS) += core_apecs.o
obj-$(CONFIG_ALPHA_CIA) += core_cia.o
......
......@@ -40,7 +40,6 @@
extern struct hwrpb_struct *hwrpb;
extern void dump_thread(struct pt_regs *, struct user *);
extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
extern spinlock_t rtc_lock;
/* these are C runtime functions with special calling conventions: */
......@@ -144,7 +143,9 @@ EXPORT_SYMBOL(pci_dac_dma_to_offset);
#endif
EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(dump_elf_thread);
EXPORT_SYMBOL(dump_elf_task);
EXPORT_SYMBOL(dump_elf_task_fp);
EXPORT_SYMBOL(hwrpb);
EXPORT_SYMBOL(start_thread);
EXPORT_SYMBOL(alpha_read_fp_reg);
......
......@@ -27,13 +27,11 @@
#include <asm/core_irongate.h>
#undef __EXTERN_INLINE
#include <linux/bootmem.h>
#include "proto.h"
#include "pci_impl.h"
#undef DEBUG_IRONGATE /* define to enable verbose Irongate debug */
#define IRONGATE_DEFAULT_AGP_APER_SIZE (256*1024*1024) /* 256MB */
/*
* BIOS32-style PCI interface:
*/
......@@ -46,6 +44,7 @@
# define DBG_CFG(args)
#endif
igcsr32 *IronECC;
/*
* Given a bus, device, and function number, compute resulting
......@@ -165,143 +164,6 @@ struct pci_ops irongate_pci_ops =
.write = irongate_write_config,
};
#ifdef DEBUG_IRONGATE
static void
irongate_register_dump(const char *function_name)
{
printk("%s: Irongate registers:\n"
"\tFunction 0:\n"
"\tdev_vendor\t0x%08x\n"
"\tstat_cmd\t0x%08x\n"
"\tclass\t\t0x%08x\n"
"\tlatency\t\t0x%08x\n"
"\tbar0\t\t0x%08x\n"
"\tbar1\t\t0x%08x\n"
"\tbar2\t\t0x%08x\n"
"\trsrvd0[0]\t0x%08x\n"
"\trsrvd0[1]\t0x%08x\n"
"\trsrvd0[2]\t0x%08x\n"
"\trsrvd0[3]\t0x%08x\n"
"\trsrvd0[4]\t0x%08x\n"
"\trsrvd0[5]\t0x%08x\n"
"\tcapptr\t\t0x%08x\n"
"\trsrvd1[0]\t0x%08x\n"
"\trsrvd1[1]\t0x%08x\n"
"\tbacsr10\t\t0x%08x\n"
"\tbacsr32\t\t0x%08x\n"
"\tbacsr54\t\t0x%08x\n"
"\trsrvd2[0]\t0x%08x\n"
"\tdrammap\t\t0x%08x\n"
"\tdramtm\t\t0x%08x\n"
"\tdramms\t\t0x%08x\n"
"\trsrvd3[0]\t0x%08x\n"
"\tbiu0\t\t0x%08x\n"
"\tbiusip\t\t0x%08x\n"
"\trsrvd4[0]\t0x%08x\n"
"\trsrvd4[1]\t0x%08x\n"
"\tmro\t\t0x%08x\n"
"\trsrvd5[0]\t0x%08x\n"
"\trsrvd5[1]\t0x%08x\n"
"\trsrvd5[2]\t0x%08x\n"
"\twhami\t\t0x%08x\n"
"\tpciarb\t\t0x%08x\n"
"\tpcicfg\t\t0x%08x\n"
"\trsrvd6[0]\t0x%08x\n"
"\trsrvd6[1]\t0x%08x\n"
"\trsrvd6[2]\t0x%08x\n"
"\trsrvd6[3]\t0x%08x\n"
"\trsrvd6[4]\t0x%08x\n"
"\tagpcap\t\t0x%08x\n"
"\tagpstat\t\t0x%08x\n"
"\tagpcmd\t\t0x%08x\n"
"\tagpva\t\t0x%08x\n"
"\tagpmode\t\t0x%08x\n"
"\n\tFunction 1:\n"
"\tdev_vendor:\t0x%08x\n"
"\tcmd_status:\t0x%08x\n"
"\trevid_etc :\t0x%08x\n"
"\thtype_etc :\t0x%08x\n"
"\trsrvd0[0] :\t0x%08x\n"
"\trsrvd0[1] :\t0x%08x\n"
"\tbus_nmbers:\t0x%08x\n"
"\tio_baselim:\t0x%08x\n"
"\tmem_bselim:\t0x%08x\n"
"\tpf_baselib:\t0x%08x\n"
"\trsrvd1[0] :\t0x%08x\n"
"\trsrvd1[1] :\t0x%08x\n"
"\tio_baselim:\t0x%08x\n"
"\trsrvd2[0] :\t0x%08x\n"
"\trsrvd2[1] :\t0x%08x\n"
"\tinterrupt :\t0x%08x\n",
function_name,
IRONGATE0->dev_vendor,
IRONGATE0->stat_cmd,
IRONGATE0->class,
IRONGATE0->latency,
IRONGATE0->bar0,
IRONGATE0->bar1,
IRONGATE0->bar2,
IRONGATE0->rsrvd0[0],
IRONGATE0->rsrvd0[1],
IRONGATE0->rsrvd0[2],
IRONGATE0->rsrvd0[3],
IRONGATE0->rsrvd0[4],
IRONGATE0->rsrvd0[5],
IRONGATE0->capptr,
IRONGATE0->rsrvd1[0],
IRONGATE0->rsrvd1[1],
IRONGATE0->bacsr10,
IRONGATE0->bacsr32,
IRONGATE0->bacsr54,
IRONGATE0->rsrvd2[0],
IRONGATE0->drammap,
IRONGATE0->dramtm,
IRONGATE0->dramms,
IRONGATE0->rsrvd3[0],
IRONGATE0->biu0,
IRONGATE0->biusip,
IRONGATE0->rsrvd4[0],
IRONGATE0->rsrvd4[1],
IRONGATE0->mro,
IRONGATE0->rsrvd5[0],
IRONGATE0->rsrvd5[1],
IRONGATE0->rsrvd5[2],
IRONGATE0->whami,
IRONGATE0->pciarb,
IRONGATE0->pcicfg,
IRONGATE0->rsrvd6[0],
IRONGATE0->rsrvd6[1],
IRONGATE0->rsrvd6[2],
IRONGATE0->rsrvd6[3],
IRONGATE0->rsrvd6[4],
IRONGATE0->agpcap,
IRONGATE0->agpstat,
IRONGATE0->agpcmd,
IRONGATE0->agpva,
IRONGATE0->agpmode,
IRONGATE1->dev_vendor,
IRONGATE1->stat_cmd,
IRONGATE1->class,
IRONGATE1->htype,
IRONGATE1->rsrvd0[0],
IRONGATE1->rsrvd0[1],
IRONGATE1->busnos,
IRONGATE1->io_baselim_regs,
IRONGATE1->mem_baselim,
IRONGATE1->pfmem_baselim,
IRONGATE1->rsrvd1[0],
IRONGATE1->rsrvd1[1],
IRONGATE1->io_baselim,
IRONGATE1->rsrvd2[0],
IRONGATE1->rsrvd2[1],
IRONGATE1->interrupt );
}
#else
#define irongate_register_dump(x)
#endif
int
irongate_pci_clr_err(void)
{
......@@ -315,11 +177,11 @@ irongate_pci_clr_err(void)
mb();
IRONGATE_jd = IRONGATE0->stat_cmd; /* re-read to force write */
IRONGATE_jd = IRONGATE0->dramms;
printk("Iron dramms %x\n", IRONGATE_jd);
IRONGATE0->dramms = IRONGATE_jd; /* write again clears error bits */
IRONGATE_jd = *IronECC;
printk("Iron ECC %x\n", IRONGATE_jd);
*IronECC = IRONGATE_jd; /* write again clears error bits */
mb();
IRONGATE_jd = IRONGATE0->dramms; /* re-read to force write */
IRONGATE_jd = *IronECC; /* re-read to force write */
/* Clear ALI NMI */
nmi_ctl = inb(0x61);
......@@ -328,28 +190,88 @@ irongate_pci_clr_err(void)
nmi_ctl &= ~0x0c;
outb(nmi_ctl, 0x61);
IRONGATE_jd = IRONGATE0->dramms;
IRONGATE_jd = *IronECC;
if (IRONGATE_jd & 0x300) goto again;
return 0;
}
#define IRONGATE_3GB 0xc0000000UL
/* On Albacore (aka UP1500) with 4Gb of RAM we have to reserve some
memory for PCI. At this point we just reserve memory above 3Gb. Most
of this memory will be freed after PCI setup is done. */
static void __init
albacore_init_arch(void)
{
unsigned long memtop = max_low_pfn << PAGE_SHIFT;
unsigned long pci_mem = (memtop + 0x1000000UL) & ~0xffffffUL;
struct percpu_struct *cpu;
int pal_rev, pal_var;
cpu = (struct percpu_struct*)((char*)hwrpb + hwrpb->processor_offset);
pal_rev = cpu->pal_revision & 0xffff;
pal_var = (cpu->pal_revision >> 16) & 0xff;
/* Consoles earlier than A5.6-18 (OSF PALcode v1.62-2) set up
the CPU incorrectly (leave speculative stores enabled),
which causes memory corruption under certain conditions.
Issue a warning for such consoles. */
if (alpha_using_srm &&
(pal_rev < 0x13e || (pal_rev == 0x13e && pal_var < 2)))
printk(KERN_WARNING "WARNING! Upgrade to SRM A5.6-19 "
"or later\n");
if (pci_mem > IRONGATE_3GB)
pci_mem = IRONGATE_3GB;
IRONGATE0->pci_mem = pci_mem;
alpha_mv.min_mem_address = pci_mem;
if (memtop > pci_mem) {
#ifdef CONFIG_BLK_DEV_INITRD
extern unsigned long initrd_start, initrd_end;
extern void *move_initrd(unsigned long);
/* Move the initrd out of the way. */
if (initrd_end && __pa(initrd_end) > pci_mem) {
unsigned long size;
size = initrd_end - initrd_start;
free_bootmem(__pa(initrd_start), PAGE_ALIGN(size));
if (!move_initrd(pci_mem))
printk("irongate_init_arch: initrd too big "
"(%ldK)\ndisabling initrd\n",
size / 1024);
}
#endif
reserve_bootmem(pci_mem, memtop - pci_mem);
printk("irongate_init_arch: temporarily reserving "
"region %08lx-%08lx for PCI\n", pci_mem, memtop - 1);
}
}
static void __init
irongate_setup_agp(void)
{
/* Disable the GART window. AGPGART doesn't work due to yet
unresolved memory coherency issues... */
IRONGATE0->agpva = IRONGATE0->agpva & ~0xf;
alpha_agpgart_size = 0;
}
void __init
irongate_init_arch(void)
{
struct pci_controller *hose;
int amd761 = (IRONGATE0->dev_vendor >> 16) > 0x7006; /* Albacore? */
IronECC = amd761 ? &IRONGATE0->bacsr54_eccms761 : &IRONGATE0->dramms;
IRONGATE0->stat_cmd = IRONGATE0->stat_cmd & ~0x100;
irongate_pci_clr_err();
irongate_register_dump(__FUNCTION__);
/*
* HACK: set AGP aperture size to 256MB.
* This should really be changed during PCI probe, when the
* size of the aperture the AGP card wants is known.
*/
printk("irongate_init_arch: AGPVA was 0x%x\n", IRONGATE0->agpva);
IRONGATE0->agpva = (IRONGATE0->agpva & ~0x0000000f) | 0x00000007;
if (amd761)
albacore_init_arch();
irongate_setup_agp();
/*
* Create our single hose.
......@@ -380,89 +302,9 @@ irongate_init_arch(void)
* IO map and AGP support
*/
#include <linux/vmalloc.h>
#include <asm/pgalloc.h>
static inline void
irongate_remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
unsigned long phys_addr, unsigned long flags)
{
unsigned long end;
unsigned long pfn;
address &= ~PMD_MASK;
end = address + size;
if (end > PMD_SIZE)
end = PMD_SIZE;
if (address >= end)
BUG();
pfn = phys_addr >> PAGE_SHIFT;
do {
if (!pte_none(*pte)) {
printk("irongate_remap_area_pte: page already exists\n");
BUG();
}
set_pte(pte, pfn_pte(pfn,
__pgprot(_PAGE_VALID | _PAGE_ASM |
_PAGE_KRE | _PAGE_KWE | flags)));
address += PAGE_SIZE;
pfn++;
pte++;
} while (address && (address < end));
}
static inline int
irongate_remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
unsigned long phys_addr, unsigned long flags)
{
unsigned long end;
address &= ~PGDIR_MASK;
end = address + size;
if (end > PGDIR_SIZE)
end = PGDIR_SIZE;
phys_addr -= address;
if (address >= end)
BUG();
do {
pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address);
if (!pte)
return -ENOMEM;
irongate_remap_area_pte(pte, address, end - address,
address + phys_addr, flags);
address = (address + PMD_SIZE) & PMD_MASK;
pmd++;
} while (address && (address < end));
return 0;
}
static int
irongate_remap_area_pages(unsigned long address, unsigned long phys_addr,
unsigned long size, unsigned long flags)
{
pgd_t * dir;
unsigned long end = address + size;
phys_addr -= address;
dir = pgd_offset(&init_mm, address);
flush_cache_all();
if (address >= end)
BUG();
do {
pmd_t *pmd;
pmd = pmd_alloc(&init_mm, dir, address);
if (!pmd)
return -ENOMEM;
if (irongate_remap_area_pmd(pmd, address, end - address,
phys_addr + address, flags))
return -ENOMEM;
address = (address + PGDIR_SIZE) & PGDIR_MASK;
dir++;
} while (address && (address < end));
return 0;
}
#include <linux/agp_backend.h>
#include <linux/agpgart.h>
#include <asm/pgalloc.h>
#define GET_PAGE_DIR_OFF(addr) (addr >> 22)
#define GET_PAGE_DIR_IDX(addr) (GET_PAGE_DIR_OFF(addr))
......@@ -477,15 +319,13 @@ irongate_ioremap(unsigned long addr, unsigned long size)
unsigned long vaddr;
unsigned long baddr, last;
u32 *mmio_regs, *gatt_pages, *cur_gatt, pte;
unsigned long gart_bus_addr, gart_aper_size;
unsigned long gart_bus_addr;
gart_bus_addr = (unsigned long)IRONGATE0->bar0 &
PCI_BASE_ADDRESS_MEM_MASK;
if (!gart_bus_addr) /* FIXME - there must be a better way!!! */
if (!alpha_agpgart_size)
return addr + IRONGATE_MEM;
gart_aper_size = IRONGATE_DEFAULT_AGP_APER_SIZE; /* FIXME */
gart_bus_addr = (unsigned long)IRONGATE0->bar0 &
PCI_BASE_ADDRESS_MEM_MASK;
/*
* Check for within the AGP aperture...
......@@ -495,7 +335,7 @@ irongate_ioremap(unsigned long addr, unsigned long size)
* Check the AGP area
*/
if (addr >= gart_bus_addr && addr + size - 1 <
gart_bus_addr + gart_aper_size)
gart_bus_addr + alpha_agpgart_size)
break;
/*
......@@ -549,7 +389,7 @@ irongate_ioremap(unsigned long addr, unsigned long size)
cur_gatt = phys_to_virt(GET_GATT(baddr) & ~1);
pte = cur_gatt[GET_GATT_OFF(baddr)] & ~1;
if (irongate_remap_area_pages(VMALLOC_VMADDR(vaddr),
if (__alpha_remap_area_pages(VMALLOC_VMADDR(vaddr),
pte, PAGE_SIZE, 0)) {
printk("AGP ioremap: FAILED to map...\n");
vfree(area->addr);
......
......@@ -732,21 +732,6 @@ marvel_iounmap(unsigned long addr)
EXPORT_SYMBOL(marvel_ioremap);
EXPORT_SYMBOL(marvel_iounmap);
#endif
/*
* SRMCons support
*
* Marvel doesn't have a real serial console -- it's either graphics or
* server management based. If we're running on the server management based
* console, allow the srmcons callback driver to be a console device.
*/
int
marvel_srmcons_allowed(void)
{
u64 *pu64 = (u64 *)((u64)hwrpb + hwrpb->ctbt_offset);
return (pu64[7] == 2);
}
/*
......@@ -874,8 +859,6 @@ marvel_node_mem_size(int nid)
#include <linux/slab.h>
#include <linux/delay.h>
#define MARVEL_AGP_APER_SIZE (64 * 1024 * 1024)
struct marvel_agp_aperture {
struct pci_iommu_arena *arena;
long pg_start;
......@@ -887,11 +870,14 @@ marvel_agp_setup(alpha_agp_info *agp)
{
struct marvel_agp_aperture *aper;
if (!alpha_agpgart_size)
return -ENOMEM;
aper = kmalloc(sizeof(*aper), GFP_KERNEL);
if (aper == NULL) return -ENOMEM;
aper->arena = agp->hose->sg_pci;
aper->pg_count = MARVEL_AGP_APER_SIZE / PAGE_SIZE;
aper->pg_count = alpha_agpgart_size / PAGE_SIZE;
aper->pg_start = iommu_reserve(aper->arena, aper->pg_count,
aper->pg_count - 1);
......
......@@ -580,8 +580,6 @@ EXPORT_SYMBOL(titan_iounmap);
#include <linux/slab.h>
#include <linux/delay.h>
#define TITAN_AGP_APER_SIZE (64 * 1024 * 1024)
struct titan_agp_aperture {
struct pci_iommu_arena *arena;
long pg_start;
......@@ -593,12 +591,15 @@ titan_agp_setup(alpha_agp_info *agp)
{
struct titan_agp_aperture *aper;
if (!alpha_agpgart_size)
return -ENOMEM;
aper = kmalloc(sizeof(struct titan_agp_aperture), GFP_KERNEL);
if (aper == NULL)
return -ENOMEM;
aper->arena = agp->hose->sg_pci;
aper->pg_count = TITAN_AGP_APER_SIZE / PAGE_SIZE;
aper->pg_count = alpha_agpgart_size / PAGE_SIZE;
aper->pg_start = iommu_reserve(aper->arena, aper->pg_count,
aper->pg_count - 1);
if (aper->pg_start < 0) {
......
......@@ -534,7 +534,7 @@ show_interrupts(struct seq_file *p, void *v)
#else
for (j = 0; j < NR_CPUS; j++)
if (cpu_online(j))
seq_printf(p, "%10u ", kstat_cpu(i).irqs[j]);
seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
#endif
seq_printf(p, " %14s", irq_desc[i].handler->typename);
seq_printf(p, " %c%s",
......
......@@ -71,6 +71,8 @@ struct pci_iommu_arena;
#define IRONGATE_DEFAULT_MEM_BASE ((256*8-16)*1024*1024)
#define DEFAULT_AGP_APER_SIZE (64*1024*1024)
/*
* A small note about bridges and interrupts. The DECchip 21050 (and
* later) adheres to the PCI-PCI bridge specification. This says that
......@@ -153,6 +155,8 @@ extern struct pci_controller *pci_isa_hose;
/* Indicate that we trust the console to configure things properly. */
extern int pci_probe_only;
extern unsigned long alpha_agpgart_size;
extern void common_init_pci(void);
extern u8 common_swizzle(struct pci_dev *, u8 *);
extern struct pci_controller *alloc_pci_controller(void);
......
......@@ -313,7 +313,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
}
/*
* fill in the user structure for a core dump..
* Fill in the user structure for an ECOFF core dump.
*/
void
dump_thread(struct pt_regs * pt, struct user * dump)
......@@ -373,12 +373,81 @@ dump_thread(struct pt_regs * pt, struct user * dump)
memcpy((char *)dump->regs + EF_SIZE, sw->fp, 32 * 8);
}
int
dump_fpu(struct pt_regs * regs, elf_fpregset_t *r)
/*
* Fill in the user structure for a ELF core dump.
*/
void
dump_elf_thread(elf_greg_t *dest, struct pt_regs *pt, struct thread_info *ti)
{
/* switch stack follows right below pt_regs: */
struct switch_stack * sw = ((struct switch_stack *) regs) - 1;
memcpy(r, sw->fp, 32 * 8);
struct switch_stack * sw = ((struct switch_stack *) pt) - 1;
dest[ 0] = pt->r0;
dest[ 1] = pt->r1;
dest[ 2] = pt->r2;
dest[ 3] = pt->r3;
dest[ 4] = pt->r4;
dest[ 5] = pt->r5;
dest[ 6] = pt->r6;
dest[ 7] = pt->r7;
dest[ 8] = pt->r8;
dest[ 9] = sw->r9;
dest[10] = sw->r10;
dest[11] = sw->r11;
dest[12] = sw->r12;
dest[13] = sw->r13;
dest[14] = sw->r14;
dest[15] = sw->r15;
dest[16] = pt->r16;
dest[17] = pt->r17;
dest[18] = pt->r18;
dest[19] = pt->r19;
dest[20] = pt->r20;
dest[21] = pt->r21;
dest[22] = pt->r22;
dest[23] = pt->r23;
dest[24] = pt->r24;
dest[25] = pt->r25;
dest[26] = pt->r26;
dest[27] = pt->r27;
dest[28] = pt->r28;
dest[29] = pt->gp;
dest[30] = rdusp();
dest[31] = pt->pc;
/* Once upon a time this was the PS value. Which is stupid
since that is always 8 for usermode. Usurped for the more
useful value of the thread's UNIQUE field. */
dest[32] = ti->pcb.unique;
}
int
dump_elf_task(elf_greg_t *dest, struct task_struct *task)
{
struct thread_info *ti;
struct pt_regs *pt;
ti = task->thread_info;
pt = (struct pt_regs *)((unsigned long)ti + 2*PAGE_SIZE) - 1;
dump_elf_thread(dest, pt, ti);
return 1;
}
int
dump_elf_task_fp(elf_fpreg_t *dest, struct task_struct *task)
{
struct thread_info *ti;
struct pt_regs *pt;
struct switch_stack *sw;
ti = task->thread_info;
pt = (struct pt_regs *)((unsigned long)ti + 2*PAGE_SIZE) - 1;
sw = (struct switch_stack *)pt - 1;
memcpy(dest, sw->fp, 32 * 8);
return 1;
}
......
......@@ -53,7 +53,6 @@ extern int marvel_pa_to_nid(unsigned long);
extern int marvel_cpuid_to_nid(int);
extern unsigned long marvel_node_mem_start(int);
extern unsigned long marvel_node_mem_size(int);
extern int marvel_srmcons_allowed(void);
extern struct _alpha_agp_info *marvel_agp_info(void);
struct io7 *marvel_find_io7(int pe);
struct io7 *marvel_next_io7(struct io7 *prev);
......@@ -109,9 +108,15 @@ extern unsigned long wildfire_node_mem_size(int);
/* setup.c */
extern unsigned long srm_hae;
extern int boot_cpuid;
extern int srmcons_output;
/* srmcons.c */
#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM)
extern void register_srm_console(void);
extern void unregister_srm_console(void);
#else
#define register_srm_console()
#define unregister_srm_console()
#endif
/* smp.c */
extern void setup_smp(void);
......
......@@ -102,7 +102,9 @@ get_reg_addr(struct task_struct * task, unsigned long regno)
if (regno == 30) {
addr = &task->thread_info->pcb.usp;
} else if (regno == 31 || regno > 64) {
} else if (regno == 65) {
addr = &task->thread_info->pcb.unique;
} else if (regno == 31 || regno > 65) {
zero = 0;
addr = &zero;
} else {
......
......@@ -77,18 +77,25 @@ int boot_cpuid;
* "srmcons" specified in the boot command arguments allows us to
* see kernel messages during the period of time before the true
* console device is "registered" during console_init(). As of this
* version (2.4.10), time_init() is the last Alpha-specific code
* called before console_init(), so we put "unregister" code
* there to prevent schizophrenic console behavior later... ;-}
* console device is "registered" during console_init().
* As of this version (2.5.59), console_init() will call
* disable_early_printk() as the last action before initializing
* the console drivers. That's the last possible time srmcons can be
* unregistered without interfering with console behavior.
*
* By default, OFF; set it with a bootcommand arg of "srmcons".
* By default, OFF; set it with a bootcommand arg of "srmcons" or
* "console=srm". The meaning of these two args is:
* "srmcons" - early callback prints
* "console=srm" - full callback based console, including early prints
*/
int srmcons_output = 0;
/* Enforce a memory size limit; useful for testing. By default, none. */
unsigned long mem_size_limit = 0;
/* Set AGP GART window size (0 means disabled). */
unsigned long alpha_agpgart_size = DEFAULT_AGP_APER_SIZE;
#ifdef CONFIG_ALPHA_GENERIC
struct alpha_machine_vector alpha_mv;
int alpha_using_srm;
......@@ -461,57 +468,6 @@ page_is_ram(unsigned long pfn)
#undef PFN_PHYS
#undef PFN_MAX
#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM)
/*
* Manage the SRM callbacks as a "console".
*/
static struct console srmcons;
void __init register_srm_console(void)
{
register_console(&srmcons);
}
void __init unregister_srm_console(void)
{
unregister_console(&srmcons);
}
static void srm_console_write(struct console *co, const char *s,
unsigned count)
{
srm_printk(s);
}
static kdev_t srm_console_device(struct console *c)
{
/* Huh? */
return mk_kdev(TTY_MAJOR, 64 + c->index);
}
static int __init srm_console_setup(struct console *co, char *options)
{
return 1;
}
static struct console srmcons = {
.name = "srm0",
.write = srm_console_write,
.device = srm_console_device,
.setup = srm_console_setup,
.flags = CON_PRINTBUFFER | CON_ENABLED, /* fake it out */
.index = -1,
};
#else
void __init register_srm_console(void)
{
}
void __init unregister_srm_console(void)
{
}
#endif
void __init
setup_arch(char **cmdline_p)
{
......@@ -574,7 +530,16 @@ setup_arch(char **cmdline_p)
continue;
}
if (strncmp(p, "srmcons", 7) == 0) {
srmcons_output = 1;
srmcons_output |= 1;
continue;
}
if (strncmp(p, "console=srm", 11) == 0) {
srmcons_output |= 2;
continue;
}
if (strncmp(p, "gartsize=", 9) == 0) {
alpha_agpgart_size =
get_mem_size_limit(p+9) << PAGE_SHIFT;
continue;
}
}
......@@ -585,6 +550,13 @@ setup_arch(char **cmdline_p)
/* If we want SRM console printk echoing early, do it now. */
if (alpha_using_srm && srmcons_output) {
register_srm_console();
/*
* If "console=srm" was specified, clear the srmcons_output
* flag now so that time.c won't unregister_srm_console
*/
if (srmcons_output & 2)
srmcons_output = 0;
}
#ifdef CONFIG_MAGIC_SYSRQ
......@@ -688,6 +660,15 @@ setup_arch(char **cmdline_p)
paging_init();
}
void __init
disable_early_printk(void)
{
if (alpha_using_srm && srmcons_output) {
unregister_srm_console();
srmcons_output = 0;
}
}
static char sys_unknown[] = "Unknown";
static char systype_names[][16] = {
"0",
......
......@@ -544,9 +544,6 @@ smp_prepare_cpus(unsigned int max_cpus)
smp_tune_scheduling(boot_cpuid);
smp_setup_percpu_timer(boot_cpuid);
/* We have already have the boot CPU online.. */
set_bit(boot_cpuid, &cpu_online_map);
/* Nothing to do on a UP box, or when told not to. */
if (smp_num_probed == 1 || max_cpus == 0) {
cpu_present_mask = 1UL << boot_cpuid;
......@@ -574,7 +571,11 @@ smp_prepare_cpus(unsigned int max_cpus)
void __devinit
smp_prepare_boot_cpu(void)
{
/*
* Mark the boot cpu (current cpu) as both present and online
*/
set_bit(smp_processor_id(), &cpu_present_mask);
set_bit(smp_processor_id(), &cpu_online_map);
}
int __devinit
......
/*
* linux/arch/alpha/kernel/srmcons.c
*
* Callback based driver for SRM Console console device.
* (TTY driver and console driver)
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/timer.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
#include <asm/console.h>
#include <asm/uaccess.h>
static spinlock_t srmcons_callback_lock = SPIN_LOCK_UNLOCKED;
static int srm_is_registered_console = 0;
/*
* The TTY driver
*/
#define MAX_SRM_CONSOLE_DEVICES 1 /* only support 1 console device */
static int srmcons_refcount;
static struct tty_struct *srmcons_table[MAX_SRM_CONSOLE_DEVICES];
static struct termios *srmcons_termios[MAX_SRM_CONSOLE_DEVICES];
static struct termios *srmcons_termios_locked[MAX_SRM_CONSOLE_DEVICES];
struct srmcons_private {
struct tty_struct *tty;
struct timer_list timer;
spinlock_t lock;
};
typedef union _srmcons_result {
struct {
unsigned long c :61;
unsigned long status :3;
} bits;
long as_long;
} srmcons_result;
/* called with callback_lock held */
static int
srmcons_do_receive_chars(struct tty_struct *tty)
{
srmcons_result result;
int count = 0, loops = 0;
do {
result.as_long = callback_getc(0);
if (result.bits.status < 2) {
tty_insert_flip_char(tty, (char)result.bits.c, 0);
count++;
}
} while((result.bits.status & 1) && (++loops < 10));
if (count)
tty_schedule_flip(tty);
return count;
}
static void
srmcons_receive_chars(unsigned long data)
{
struct srmcons_private *srmconsp = (struct srmcons_private *)data;
unsigned long flags;
int incr = 10;
local_irq_save(flags);
if (spin_trylock(&srmcons_callback_lock)) {
if (!srmcons_do_receive_chars(srmconsp->tty))
incr = 100;
spin_unlock(&srmcons_callback_lock);
}
spin_lock(&srmconsp->lock);
if (srmconsp->tty) {
srmconsp->timer.expires = jiffies + incr;
add_timer(&srmconsp->timer);
}
spin_unlock(&srmconsp->lock);
local_irq_restore(flags);
}
/* called with callback_lock held */
static int
srmcons_do_write(struct tty_struct *tty, const unsigned char *buf, int count)
{
unsigned char *str_cr = "\r";
long c, remaining = count;
srmcons_result result;
unsigned char *cur;
int need_cr;
for (cur = (unsigned char *)buf; remaining > 0; ) {
need_cr = 0;
/*
* Break it up into reasonable size chunks to allow a chance
* for input to get in
*/
for (c = 0; c < min_t(long, 128L, remaining) && !need_cr; c++)
if (cur[c] == '\n')
need_cr = 1;
while (c > 0) {
result.as_long = callback_puts(0, cur, c);
c -= result.bits.c;
remaining -= result.bits.c;
cur += result.bits.c;
/*
* Check for pending input iff a tty was provided
*/
if (tty)
srmcons_do_receive_chars(tty);
}
while (need_cr) {
result.as_long = callback_puts(0, str_cr, 1);
if (result.bits.c > 0)
need_cr = 0;
}
}
return count;
}
static int
srmcons_write(struct tty_struct *tty, int from_user,
const unsigned char *buf, int count)
{
unsigned long flags;
if (from_user) {
unsigned char tmp[512];
int ret = 0;
size_t c;
while ((c = count) > 0) {
if (c > sizeof(tmp))
c = sizeof(tmp);
c -= copy_from_user(tmp, buf, c);
if (!c) {
printk("%s: EFAULT (count %d)\n",
__FUNCTION__, count);
return -EFAULT;
}
spin_lock_irqsave(&srmcons_callback_lock, flags);
srmcons_do_write(tty, tmp, c);
spin_unlock_irqrestore(&srmcons_callback_lock, flags);
buf += c;
count -= c;
ret += c;
}
return ret;
}
spin_lock_irqsave(&srmcons_callback_lock, flags);
srmcons_do_write(tty, buf, count);
spin_unlock_irqrestore(&srmcons_callback_lock, flags);
return count;
}
static int
srmcons_write_room(struct tty_struct *tty)
{
return 512;
}
static int
srmcons_chars_in_buffer(struct tty_struct *tty)
{
return 0;
}
static int
srmcons_get_private_struct(struct srmcons_private **ps)
{
static struct srmcons_private *srmconsp = NULL;
static spinlock_t srmconsp_lock = SPIN_LOCK_UNLOCKED;
unsigned long flags;
int retval = 0;
spin_lock_irqsave(&srmconsp_lock, flags);
do {
if (srmconsp != NULL) {
*ps = srmconsp;
break;
}
srmconsp = kmalloc(sizeof(*srmconsp), GFP_KERNEL);
if (srmconsp == NULL) {
retval = -ENOMEM;
break;
}
srmconsp->tty = NULL;
srmconsp->lock = SPIN_LOCK_UNLOCKED;
init_timer(&srmconsp->timer);
*ps = srmconsp;
} while(0);
spin_unlock_irqrestore(&srmconsp_lock, flags);
return retval;
}
static int
srmcons_open(struct tty_struct *tty, struct file *filp)
{
struct srmcons_private *srmconsp;
unsigned long flags;
int retval;
retval = srmcons_get_private_struct(&srmconsp);
if (retval)
return retval;
spin_lock_irqsave(&srmconsp->lock, flags);
if (!srmconsp->tty) {
tty->driver_data = srmconsp;
srmconsp->tty = tty;
srmconsp->timer.function = srmcons_receive_chars;
srmconsp->timer.data = (unsigned long)srmconsp;
srmconsp->timer.expires = jiffies + 10;
add_timer(&srmconsp->timer);
}
spin_unlock_irqrestore(&srmconsp->lock, flags);
return 0;
}
static void
srmcons_close(struct tty_struct *tty, struct file *filp)
{
struct srmcons_private *srmconsp = tty->driver_data;
unsigned long flags;
spin_lock_irqsave(&srmconsp->lock, flags);
if (tty->count == 1) {
srmconsp->tty = NULL;
del_timer(&srmconsp->timer);
}
spin_unlock_irqrestore(&srmconsp->lock, flags);
}
static struct tty_driver srmcons_driver = {
.driver_name = "srm",
.name = "srm",
.magic = TTY_DRIVER_MAGIC,
.major = 0, /* dynamic */
.minor_start = 0,
.num = MAX_SRM_CONSOLE_DEVICES,
.type = TTY_DRIVER_TYPE_SYSTEM,
.subtype = SYSTEM_TYPE_SYSCONS,
.table = srmcons_table,
.termios = srmcons_termios,
.termios_locked = srmcons_termios_locked,
.refcount = &srmcons_refcount,
.open = srmcons_open,
.close = srmcons_close,
.write = srmcons_write,
.write_room = srmcons_write_room,
.chars_in_buffer= srmcons_chars_in_buffer,
};
static int __init
srmcons_init(void)
{
if (srm_is_registered_console) {
srmcons_driver.init_termios = tty_std_termios;
return tty_register_driver(&srmcons_driver);
}
return -ENODEV;
}
module_init(srmcons_init);
/*
* The console driver
*/
static void
srm_console_write(struct console *co, const char *s, unsigned count)
{
unsigned long flags;
spin_lock_irqsave(&srmcons_callback_lock, flags);
srmcons_do_write(NULL, s, count);
spin_unlock_irqrestore(&srmcons_callback_lock, flags);
}
static kdev_t
srm_console_device(struct console *co)
{
return mk_kdev(srmcons_driver.major,
srmcons_driver.minor_start + co->index);
}
static int __init
srm_console_setup(struct console *co, char *options)
{
return 0;
}
static struct console srmcons = {
.name = "srm",
.write = srm_console_write,
.device = srm_console_device,
.setup = srm_console_setup,
.flags = CON_PRINTBUFFER,
.index = -1,
};
void __init
register_srm_console(void)
{
if (!srm_is_registered_console) {
callback_open_console();
register_console(&srmcons);
srm_is_registered_console = 1;
}
}
void __init
unregister_srm_console(void)
{
if (srm_is_registered_console) {
callback_close_console();
unregister_console(&srmcons);
srm_is_registered_console = 0;
}
}
......@@ -31,6 +31,7 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/reboot.h>
#include <linux/bootmem.h>
#include <asm/ptrace.h>
#include <asm/system.h>
......@@ -174,6 +175,70 @@ nautilus_machine_check(unsigned long vector, unsigned long la_ptr,
mb();
}
extern void free_reserved_mem(void *, void *);
void __init
nautilus_init_pci(void)
{
struct pci_controller *hose = hose_head;
struct pci_bus *bus;
struct pci_dev *irongate;
unsigned long saved_io_start, saved_io_end;
unsigned long saved_mem_start, saved_mem_end;
unsigned long bus_align, bus_size, pci_mem;
unsigned long memtop = max_low_pfn << PAGE_SHIFT;
/* Scan our single hose. */
bus = pci_scan_bus(0, alpha_mv.pci_ops, hose);
hose->bus = bus;
hose->last_busno = bus->subordinate;
/* We're going to size the root bus, so we must
- have a non-NULL PCI device associated with the bus
- preserve hose resources. */
irongate = pci_find_slot(0, 0);
bus->self = irongate;
saved_io_start = bus->resource[0]->start;
saved_io_end = bus->resource[0]->end;
saved_mem_start = bus->resource[1]->start;
saved_mem_end = bus->resource[1]->end;
pci_bus_size_bridges(bus);
/* Don't care about IO. */
bus->resource[0]->start = saved_io_start;
bus->resource[0]->end = saved_io_end;
bus_align = bus->resource[1]->start;
bus_size = bus->resource[1]->end + 1 - bus_align;
/* Align to 16Mb. */
if (bus_align < 0x1000000UL)
bus_align = 0x1000000UL;
/* Restore hose MEM resource. */
bus->resource[1]->start = saved_mem_start;
bus->resource[1]->end = saved_mem_end;
pci_mem = (0x100000000UL - bus_size) & -bus_align;
if (pci_mem < memtop && pci_mem > alpha_mv.min_mem_address) {
free_reserved_mem(__va(alpha_mv.min_mem_address),
__va(pci_mem));
printk("nautilus_init_arch: %ldk freed\n",
(pci_mem - alpha_mv.min_mem_address) >> 10);
}
alpha_mv.min_mem_address = pci_mem;
if ((IRONGATE0->dev_vendor >> 16) > 0x7006) /* Albacore? */
IRONGATE0->pci_mem = pci_mem;
pci_bus_assign_resources(bus);
/* To break the loop in common_swizzle() */
bus->self = NULL;
pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
}
/*
* The System Vectors
......@@ -196,7 +261,7 @@ struct alpha_machine_vector nautilus_mv __initmv = {
.init_arch = irongate_init_arch,
.init_irq = nautilus_init_irq,
.init_rtc = common_init_rtc,
.init_pci = common_init_pci,
.init_pci = nautilus_init_pci,
.kill_arch = nautilus_kill_arch,
.pci_map_irq = nautilus_map_irq,
.pci_swizzle = common_swizzle,
......
......@@ -383,21 +383,6 @@ time_init(void)
/* Startup the timer source. */
alpha_mv.init_rtc();
/*
* If we had wanted SRM console printk echoing early, undo it now.
*
* "srmcons" specified in the boot command arguments allows us to
* see kernel messages during the period of time before the true
* console device is "registered" during console_init(). As of this
* version (2.4.10), time_init() is the last Alpha-specific code
* called before console_init(), so we put this "unregister" code
* here to prevent schizophrenic console behavior later... ;-}
*/
if (alpha_using_srm && srmcons_output) {
unregister_srm_console();
srmcons_output = 0;
}
}
/*
......
......@@ -50,13 +50,14 @@ typedef struct {
igcsr32 bacsr10; /* 0x40 - base address chip selects */
igcsr32 bacsr32; /* 0x44 - base address chip selects */
igcsr32 bacsr54; /* 0x48 - base address chip selects */
igcsr32 bacsr54_eccms761; /* 0x48 - 751: base addr. chip selects
761: ECC, mode/status */
igcsr32 rsrvd2[1]; /* 0x4C-0x4F reserved */
igcsr32 drammap; /* 0x50 - address mapping control */
igcsr32 dramtm; /* 0x54 - timing, driver strength */
igcsr32 dramms; /* 0x58 - ECC, mode/status */
igcsr32 dramms; /* 0x58 - DRAM mode/status */
igcsr32 rsrvd3[1]; /* 0x5C-0x5F reserved */
......@@ -73,7 +74,10 @@ typedef struct {
igcsr32 pciarb; /* 0x84 - PCI arbitration control */
igcsr32 pcicfg; /* 0x88 - PCI config status */
igcsr32 rsrvd6[5]; /* 0x8C-0x9F reserved */
igcsr32 rsrvd6[4]; /* 0x8C-0x9B reserved */
igcsr32 pci_mem; /* 0x9C - PCI top of memory,
761 only */
/* AGP (bus 1) control registers */
igcsr32 agpcap; /* 0xA0 - AGP Capability Identifier */
......@@ -102,6 +106,7 @@ typedef struct {
} Irongate1;
extern igcsr32 *IronECC;
/*
* Memory spaces:
......
......@@ -52,53 +52,25 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
#define ELF_PLAT_INIT(_r) _r->r0 = 0
/* Use the same format as the OSF/1 procfs interface. The register
layout is sane. However, since dump_thread() creates the funky
layout that ECOFF coredumps want, we need to undo that layout here.
Eventually, it would be nice if the ECOFF core-dump had to do the
translation, then ELF_CORE_COPY_REGS() would become trivial and
faster. */
#define ELF_CORE_COPY_REGS(_dest,_regs) \
{ \
extern void dump_thread(struct pt_regs *, struct user *); \
struct user _dump; \
\
dump_thread(_regs, &_dump); \
_dest[ 0] = _dump.regs[EF_V0]; \
_dest[ 1] = _dump.regs[EF_T0]; \
_dest[ 2] = _dump.regs[EF_T1]; \
_dest[ 3] = _dump.regs[EF_T2]; \
_dest[ 4] = _dump.regs[EF_T3]; \
_dest[ 5] = _dump.regs[EF_T4]; \
_dest[ 6] = _dump.regs[EF_T5]; \
_dest[ 7] = _dump.regs[EF_T6]; \
_dest[ 8] = _dump.regs[EF_T7]; \
_dest[ 9] = _dump.regs[EF_S0]; \
_dest[10] = _dump.regs[EF_S1]; \
_dest[11] = _dump.regs[EF_S2]; \
_dest[12] = _dump.regs[EF_S3]; \
_dest[13] = _dump.regs[EF_S4]; \
_dest[14] = _dump.regs[EF_S5]; \
_dest[15] = _dump.regs[EF_S6]; \
_dest[16] = _dump.regs[EF_A0]; \
_dest[17] = _dump.regs[EF_A1]; \
_dest[18] = _dump.regs[EF_A2]; \
_dest[19] = _dump.regs[EF_A3]; \
_dest[20] = _dump.regs[EF_A4]; \
_dest[21] = _dump.regs[EF_A5]; \
_dest[22] = _dump.regs[EF_T8]; \
_dest[23] = _dump.regs[EF_T9]; \
_dest[24] = _dump.regs[EF_T10]; \
_dest[25] = _dump.regs[EF_T11]; \
_dest[26] = _dump.regs[EF_RA]; \
_dest[27] = _dump.regs[EF_T12]; \
_dest[28] = _dump.regs[EF_AT]; \
_dest[29] = _dump.regs[EF_GP]; \
_dest[30] = _dump.regs[EF_SP]; \
_dest[31] = _dump.regs[EF_PC]; /* store PC here */ \
_dest[32] = _dump.regs[EF_PS]; \
}
/* The registers are layed out in pt_regs for PAL and syscall
convenience. Re-order them for the linear elf_gregset_t. */
extern void dump_elf_thread(elf_greg_t *dest, struct pt_regs *pt,
struct thread_info *ti);
#define ELF_CORE_COPY_REGS(DEST, REGS) \
dump_elf_thread(DEST, REGS, current_thread_info());
/* Similar, but for a thread other than current. */
extern int dump_elf_task(elf_greg_t *dest, struct task_struct *task);
#define ELF_CORE_COPY_TASK_REGS(TASK, DEST) \
dump_elf_task(*(DEST), TASK)
/* Similar, but for the FP registers. */
extern int dump_elf_task_fp(elf_fpreg_t *dest, struct task_struct *task);
#define ELF_CORE_COPY_FPREGS(TASK, DEST) \
dump_elf_task_fp(*(DEST), TASK)
/* This yields a mask that user programs can use to figure out what
instruction set this CPU supports. This is trivial on Alpha,
......
......@@ -43,6 +43,9 @@ static inline int node_to_cpumask(int node)
# define node_to_memblk(node) (node)
# define memblk_to_node(memblk) (memblk)
/* Cross-node load balancing interval. */
# define NODE_BALANCE_RATE 10
#else /* CONFIG_NUMA */
# include <asm-generic/topology.h>
#endif /* !CONFIG_NUMA */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment