Commit ca370702 authored by Richard Henderson's avatar Richard Henderson

Merge kanga.twiddle.net:/home/rth/linux/linus-2.5

into kanga.twiddle.net:/home/rth/linux/axp-2.5
parents 63ffe4d6 db142755
...@@ -65,6 +65,7 @@ choice ...@@ -65,6 +65,7 @@ choice
LX164 AlphaPC164-LX LX164 AlphaPC164-LX
Miata Personal Workstation 433a, 433au, 500a, Miata Personal Workstation 433a, 433au, 500a,
500au, 600a, or 600au 500au, 600a, or 600au
Marvel AlphaServer ES47 / ES80 / GS1280
Mikasa AS 1000 Mikasa AS 1000
Noname AXPpci33, UDB (Multia) Noname AXPpci33, UDB (Multia)
Noritake AS 1000A, AS 600A, AS 800 Noritake AS 1000A, AS 600A, AS 800
...@@ -75,7 +76,7 @@ choice ...@@ -75,7 +76,7 @@ choice
Sable AS 2000, AS 2100 Sable AS 2000, AS 2100
Shark DS 20L Shark DS 20L
Takara Takara Takara Takara
Titan Privateer Titan AlphaServer ES45 / DS25
Wildfire AlphaServer GS 40/80/160/320 Wildfire AlphaServer GS 40/80/160/320
If you don't know what to do, choose "generic". If you don't know what to do, choose "generic".
...@@ -172,6 +173,11 @@ config ALPHA_LX164 ...@@ -172,6 +173,11 @@ config ALPHA_LX164
A technical overview of this board is available at A technical overview of this board is available at
<http://www.unix-ag.org/Linux-Alpha/Architectures/LX164.html>. <http://www.unix-ag.org/Linux-Alpha/Architectures/LX164.html>.
config ALPHA_MARVEL
bool "Marvel"
help
AlphaServer ES47 / ES80 / GS1280 based on EV7.
config ALPHA_MIATA config ALPHA_MIATA
bool "Miata" bool "Miata"
help help
...@@ -238,6 +244,8 @@ config ALPHA_TAKARA ...@@ -238,6 +244,8 @@ config ALPHA_TAKARA
config ALPHA_TITAN config ALPHA_TITAN
bool "Titan" bool "Titan"
help
AlphaServer ES45/DS25 SMP based on EV68 and Titan chipset.
config ALPHA_WILDFIRE config ALPHA_WILDFIRE
bool "Wildfire" bool "Wildfire"
...@@ -301,6 +309,11 @@ config PCI ...@@ -301,6 +309,11 @@ config PCI
information about which PCI hardware does work under Linux and which information about which PCI hardware does work under Linux and which
doesn't. doesn't.
config ALPHA_CORE_AGP
bool
depends on ALPHA_GENERIC || ALPHA_TITAN || ALPHA_MARVEL
default y
config ALPHA_NONAME config ALPHA_NONAME
bool bool
depends on ALPHA_BOOK1 || ALPHA_NONAME_CH depends on ALPHA_BOOK1 || ALPHA_NONAME_CH
...@@ -387,7 +400,7 @@ config ALPHA_PYXIS ...@@ -387,7 +400,7 @@ config ALPHA_PYXIS
config ALPHA_EV6 config ALPHA_EV6
bool bool
depends on ALPHA_NAUTILUS || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_SHARK || ALPHA_DP264 || ALPHA_EIGER depends on ALPHA_NAUTILUS || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_SHARK || ALPHA_DP264 || ALPHA_EIGER || ALPHA_MARVEL
default y default y
config ALPHA_TSUNAMI config ALPHA_TSUNAMI
...@@ -397,11 +410,16 @@ config ALPHA_TSUNAMI ...@@ -397,11 +410,16 @@ config ALPHA_TSUNAMI
config ALPHA_EV67 config ALPHA_EV67
bool "EV67 (or later) CPU (speed > 600MHz)?" if ALPHA_DP264 || ALPHA_EIGER bool "EV67 (or later) CPU (speed > 600MHz)?" if ALPHA_DP264 || ALPHA_EIGER
default y if ALPHA_NAUTILUS || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_SHARK default y if ALPHA_NAUTILUS || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_SHARK || ALPHA_MARVEL
help help
Is this a machine based on the EV67 core? If in doubt, select N here Is this a machine based on the EV67 core? If in doubt, select N here
and the machine will be treated as an EV6. and the machine will be treated as an EV6.
config ALPHA_EV7
bool
depends on ALPHA_MARVEL
default y
config ALPHA_MCPCIA config ALPHA_MCPCIA
bool bool
depends on ALPHA_RAWHIDE depends on ALPHA_RAWHIDE
...@@ -419,7 +437,7 @@ config ALPHA_IRONGATE ...@@ -419,7 +437,7 @@ config ALPHA_IRONGATE
config ALPHA_SRM config ALPHA_SRM
bool "Use SRM as bootloader" if ALPHA_CABRIOLET || ALPHA_AVANTI_CH || ALPHA_EB64P || ALPHA_PC164 || ALPHA_TAKARA || ALPHA_EB164 || ALPHA_ALCOR || ALPHA_MIATA || ALPHA_LX164 || ALPHA_SX164 || ALPHA_NAUTILUS || ALPHA_NONAME bool "Use SRM as bootloader" if ALPHA_CABRIOLET || ALPHA_AVANTI_CH || ALPHA_EB64P || ALPHA_PC164 || ALPHA_TAKARA || ALPHA_EB164 || ALPHA_ALCOR || ALPHA_MIATA || ALPHA_LX164 || ALPHA_SX164 || ALPHA_NAUTILUS || ALPHA_NONAME
default y if ALPHA_JENSEN || ALPHA_MIKASA || ALPHA_SABLE || ALPHA_NORITAKE || ALPHA_DP264 || ALPHA_RAWHIDE || ALPHA_EIGER || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_SHARK default y if ALPHA_JENSEN || ALPHA_MIKASA || ALPHA_SABLE || ALPHA_NORITAKE || ALPHA_DP264 || ALPHA_RAWHIDE || ALPHA_EIGER || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_SHARK || ALPHA_MARVEL
---help--- ---help---
There are two different types of booting firmware on Alphas: SRM, There are two different types of booting firmware on Alphas: SRM,
which is command line driven, and ARC, which uses menus and arrow which is command line driven, and ARC, which uses menus and arrow
...@@ -461,7 +479,7 @@ config ALPHA_BROKEN_IRQ_MASK ...@@ -461,7 +479,7 @@ config ALPHA_BROKEN_IRQ_MASK
config SMP config SMP
bool "Symmetric multi-processing support" bool "Symmetric multi-processing support"
depends on ALPHA_SABLE || ALPHA_RAWHIDE || ALPHA_DP264 || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_GENERIC || ALPHA_SHARK depends on ALPHA_SABLE || ALPHA_RAWHIDE || ALPHA_DP264 || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_GENERIC || ALPHA_SHARK || ALPHA_MARVEL
---help--- ---help---
This enables support for systems with more than one CPU. If you have This enables support for systems with more than one CPU. If you have
a system with only one CPU, like most personal computers, say N. If a system with only one CPU, like most personal computers, say N. If
......
...@@ -6,7 +6,7 @@ EXTRA_TARGETS := head.o ...@@ -6,7 +6,7 @@ EXTRA_TARGETS := head.o
EXTRA_AFLAGS := $(CFLAGS) EXTRA_AFLAGS := $(CFLAGS)
export-objs := alpha_ksyms.o export-objs := alpha_ksyms.o core_marvel.o core_titan.o
obj-y := entry.o traps.o process.o init_task.o osf_sys.o irq.o \ obj-y := entry.o traps.o process.o init_task.o osf_sys.o irq.o \
irq_alpha.o signal.o setup.o ptrace.o time.o semaphore.o \ irq_alpha.o signal.o setup.o ptrace.o time.o semaphore.o \
...@@ -21,18 +21,19 @@ obj-$(CONFIG_MODULES) += module.o ...@@ -21,18 +21,19 @@ obj-$(CONFIG_MODULES) += module.o
ifdef CONFIG_ALPHA_GENERIC ifdef CONFIG_ALPHA_GENERIC
obj-y += core_apecs.o core_cia.o core_irongate.o core_lca.o \ obj-y += core_apecs.o core_cia.o core_irongate.o core_lca.o \
core_mcpcia.o core_polaris.o core_t2.o core_tsunami.o \ core_marvel.o core_mcpcia.o core_polaris.o core_t2.o \
core_titan.o core_wildfire.o core_tsunami.o core_titan.o core_wildfire.o
obj-y += sys_alcor.o sys_cabriolet.o sys_dp264.o sys_eb64p.o sys_eiger.o \ obj-y += sys_alcor.o sys_cabriolet.o sys_dp264.o sys_eb64p.o sys_eiger.o \
sys_jensen.o sys_miata.o sys_mikasa.o sys_nautilus.o sys_titan.o \ sys_jensen.o sys_marvel.o sys_miata.o sys_mikasa.o sys_nautilus.o \
sys_noritake.o sys_rawhide.o sys_ruffian.o sys_rx164.o \ sys_titan.o sys_noritake.o sys_rawhide.o sys_ruffian.o sys_rx164.o \
sys_sable.o sys_sio.o sys_sx164.o sys_takara.o \ sys_sable.o sys_sio.o sys_sx164.o sys_takara.o sys_wildfire.o
sys_wildfire.o
obj-y += irq_pyxis.o irq_i8259.o irq_srm.o obj-y += irq_pyxis.o irq_i8259.o irq_srm.o
obj-y += es1888.o smc37c669.o smc37c93x.o ns87312.o obj-y += err_titan.o err_marvel.o
obj-y += es1888.o smc37c669.o smc37c93x.o ns87312.o gct.o
else else
...@@ -41,6 +42,7 @@ obj-$(CONFIG_ALPHA_APECS) += core_apecs.o ...@@ -41,6 +42,7 @@ obj-$(CONFIG_ALPHA_APECS) += core_apecs.o
obj-$(CONFIG_ALPHA_CIA) += core_cia.o obj-$(CONFIG_ALPHA_CIA) += core_cia.o
obj-$(CONFIG_ALPHA_IRONGATE) += core_irongate.o obj-$(CONFIG_ALPHA_IRONGATE) += core_irongate.o
obj-$(CONFIG_ALPHA_LCA) += core_lca.o obj-$(CONFIG_ALPHA_LCA) += core_lca.o
obj-$(CONFIG_ALPHA_MARVEL) += core_marvel.o gct.o
obj-$(CONFIG_ALPHA_MCPCIA) += core_mcpcia.o obj-$(CONFIG_ALPHA_MCPCIA) += core_mcpcia.o
obj-$(CONFIG_ALPHA_POLARIS) += core_polaris.o obj-$(CONFIG_ALPHA_POLARIS) += core_polaris.o
obj-$(CONFIG_ALPHA_T2) += core_t2.o obj-$(CONFIG_ALPHA_T2) += core_t2.o
...@@ -62,11 +64,13 @@ obj-$(CONFIG_ALPHA_PC164) += sys_cabriolet.o irq_i8259.o irq_srm.o \ ...@@ -62,11 +64,13 @@ obj-$(CONFIG_ALPHA_PC164) += sys_cabriolet.o irq_i8259.o irq_srm.o \
smc37c93x.o smc37c93x.o
obj-$(CONFIG_ALPHA_DP264) += sys_dp264.o irq_i8259.o es1888.o smc37c669.o obj-$(CONFIG_ALPHA_DP264) += sys_dp264.o irq_i8259.o es1888.o smc37c669.o
obj-$(CONFIG_ALPHA_SHARK) += sys_dp264.o irq_i8259.o es1888.o smc37c669.o obj-$(CONFIG_ALPHA_SHARK) += sys_dp264.o irq_i8259.o es1888.o smc37c669.o
obj-$(CONFIG_ALPHA_TITAN) += sys_titan.o irq_i8259.o smc37c669.o obj-$(CONFIG_ALPHA_TITAN) += sys_titan.o irq_i8259.o smc37c669.o \
err_titan.o
obj-$(CONFIG_ALPHA_EB64P) += sys_eb64p.o irq_i8259.o obj-$(CONFIG_ALPHA_EB64P) += sys_eb64p.o irq_i8259.o
obj-$(CONFIG_ALPHA_EB66) += sys_eb64p.o irq_i8259.o obj-$(CONFIG_ALPHA_EB66) += sys_eb64p.o irq_i8259.o
obj-$(CONFIG_ALPHA_EIGER) += sys_eiger.o irq_i8259.o obj-$(CONFIG_ALPHA_EIGER) += sys_eiger.o irq_i8259.o
obj-$(CONFIG_ALPHA_JENSEN) += sys_jensen.o pci-noop.o irq_i8259.o obj-$(CONFIG_ALPHA_JENSEN) += sys_jensen.o pci-noop.o irq_i8259.o
obj-$(CONFIG_ALPHA_MARVEL) += sys_marvel.o err_marvel.o
obj-$(CONFIG_ALPHA_MIATA) += sys_miata.o irq_pyxis.o irq_i8259.o \ obj-$(CONFIG_ALPHA_MIATA) += sys_miata.o irq_pyxis.o irq_i8259.o \
es1888.o smc37c669.o es1888.o smc37c669.o
obj-$(CONFIG_ALPHA_MIKASA) += sys_mikasa.o irq_i8259.o irq_srm.o obj-$(CONFIG_ALPHA_MIKASA) += sys_mikasa.o irq_i8259.o irq_srm.o
......
/*
* linux/arch/alpha/kernel/core_marvel.c
*
* Code common to all Marvel based systems.
*/
#include <linux/config.h>
#define __EXTERN_INLINE inline
#include <asm/io.h>
#include <asm/core_marvel.h>
#undef __EXTERN_INLINE
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/vmalloc.h>
#include <linux/mc146818rtc.h>
#include <linux/rtc.h>
#include <linux/module.h>
#include <asm/ptrace.h>
#include <asm/system.h>
#include <asm/smp.h>
#include <asm/hwrpb.h>
#include <asm/gct.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
#include <asm/rtc.h>
#include <linux/bootmem.h>
#include "proto.h"
#include "pci_impl.h"
/*
* Debug helpers
*/
#define DEBUG_CONFIG 0
#if DEBUG_CONFIG
# define DBG_CFG(args) printk args
#else
# define DBG_CFG(args)
#endif
/*
* Private data
*/
static struct io7 *io7_head = NULL;
/*
* Helper functions
*/
static unsigned long __attribute__ ((unused))
read_ev7_csr(int pe, unsigned long offset)
{
ev7_csr *ev7csr = EV7_CSR_KERN(pe, offset);
unsigned long q;
mb();
q = ev7csr->csr;
mb();
return q;
}
static void __attribute__ ((unused))
write_ev7_csr(int pe, unsigned long offset, unsigned long q)
{
ev7_csr *ev7csr = EV7_CSR_KERN(pe, offset);
mb();
ev7csr->csr = q;
mb();
}
static char * __init
mk_resource_name(int pe, int port, char *str)
{
char tmp[80];
char *name;
sprintf(tmp, "PCI %s PE %d PORT %d", str, pe, port);
name = alloc_bootmem(strlen(tmp) + 1);
strcpy(name, tmp);
return name;
}
inline struct io7 *
marvel_next_io7(struct io7 *prev)
{
return (prev ? prev->next : io7_head);
}
struct io7 *
marvel_find_io7(int pe)
{
struct io7 *io7;
for (io7 = io7_head; io7 && io7->pe != pe; io7 = io7->next)
continue;
return io7;
}
static struct io7 * __init
alloc_io7(unsigned int pe)
{
struct io7 *io7;
struct io7 *insp;
int h;
if (marvel_find_io7(pe)) {
printk(KERN_WARNING "IO7 at PE %d already allocated!\n", pe);
return NULL;
}
io7 = alloc_bootmem(sizeof(*io7));
io7->pe = pe;
io7->irq_lock = SPIN_LOCK_UNLOCKED;
for (h = 0; h < 4; h++) {
io7->ports[h].io7 = io7;
io7->ports[h].port = h;
io7->ports[h].enabled = 0; /* default to disabled */
}
/*
* Insert in pe sorted order.
*/
if (NULL == io7_head) /* empty list */
io7_head = io7;
else if (io7_head->pe > io7->pe) { /* insert at head */
io7->next = io7_head;
io7_head = io7;
} else { /* insert at position */
for (insp = io7_head; insp; insp = insp->next) {
if (insp->pe == io7->pe) {
printk(KERN_ERR "Too many IO7s at PE %d\n",
io7->pe);
return NULL;
}
if (NULL == insp->next ||
insp->next->pe > io7->pe) { /* insert here */
io7->next = insp->next;
insp->next = io7;
break;
}
}
if (NULL == insp) { /* couldn't insert ?!? */
printk(KERN_WARNING "Failed to insert IO7 at PE %d "
" - adding at head of list\n", io7->pe);
io7->next = io7_head;
io7_head = io7;
}
}
return io7;
}
void
io7_clear_errors(struct io7 *io7)
{
io7_port7_csrs *p7csrs;
io7_ioport_csrs *csrs;
int port;
/*
* First the IO ports.
*/
for (port = 0; port < 4; port++) {
csrs = IO7_CSRS_KERN(io7->pe, port);
csrs->POx_ERR_SUM.csr = -1UL;
csrs->POx_TLB_ERR.csr = -1UL;
csrs->POx_SPL_COMPLT.csr = -1UL;
csrs->POx_TRANS_SUM.csr = -1UL;
}
/*
* Then the common ones.
*/
p7csrs = IO7_PORT7_CSRS_KERN(io7->pe);
p7csrs->PO7_ERROR_SUM.csr = -1UL;
p7csrs->PO7_UNCRR_SYM.csr = -1UL;
p7csrs->PO7_CRRCT_SYM.csr = -1UL;
}
/*
* IO7 PCI, PCI/X, AGP configuration.
*/
static void __init
io7_init_hose(struct io7 *io7, int port)
{
static int hose_index = 0;
struct pci_controller *hose = alloc_pci_controller();
struct io7_port *io7_port = &io7->ports[port];
io7_ioport_csrs *csrs = IO7_CSRS_KERN(io7->pe, port);
int i;
hose->index = hose_index++; /* arbitrary */
/*
* We don't have an isa or legacy hose, but glibc expects to be
* able to use the bus == 0 / dev == 0 form of the iobase syscall
* to determine information about the i/o system. Since XFree86
* relies on glibc's determination to tell whether or not to use
* sparse access, we need to point the pci_isa_hose at a real hose
* so at least that determination is correct.
*/
if (hose->index == 0)
pci_isa_hose = hose;
io7_port->csrs = csrs;
io7_port->hose = hose;
hose->sysdata = io7_port;
hose->io_space = alloc_resource();
hose->mem_space = alloc_resource();
/*
* Base addresses for userland consumption. Since these are going
* to be mapped, they are pure physical addresses.
*/
hose->sparse_mem_base = hose->sparse_io_base = 0;
hose->dense_mem_base = IO7_MEM_PHYS(io7->pe, port);
hose->dense_io_base = IO7_IO_PHYS(io7->pe, port);
/*
* Base addresses and resource ranges for kernel consumption.
*/
hose->config_space_base = (unsigned long)IO7_CONF_KERN(io7->pe, port);
hose->io_space->start = (unsigned long)IO7_IO_KERN(io7->pe, port);
hose->io_space->end = hose->io_space->start + IO7_IO_SPACE - 1;
hose->io_space->name = mk_resource_name(io7->pe, port, "IO");
hose->io_space->flags = IORESOURCE_IO;
hose->mem_space->start = (unsigned long)IO7_MEM_KERN(io7->pe, port);
hose->mem_space->end = hose->mem_space->start + IO7_MEM_SPACE - 1;
hose->mem_space->name = mk_resource_name(io7->pe, port, "MEM");
hose->mem_space->flags = IORESOURCE_MEM;
if (request_resource(&ioport_resource, hose->io_space) < 0)
printk(KERN_ERR "Failed to request IO on hose %d\n",
hose->index);
if (request_resource(&iomem_resource, hose->mem_space) < 0)
printk(KERN_ERR "Failed to request MEM on hose %d\n",
hose->index);
/*
* Save the existing DMA window settings for later restoration.
*/
for (i = 0; i < 4; i++) {
io7_port->saved_wbase[i] = csrs->POx_WBASE[i].csr;
io7_port->saved_wmask[i] = csrs->POx_WMASK[i].csr;
io7_port->saved_tbase[i] = csrs->POx_TBASE[i].csr;
}
/*
* Set up the PCI to main memory translation windows.
*
* Window 0 is scatter-gather 8MB at 8MB
* Window 1 is direct access 1GB at 2GB
* Window 2 is scatter-gather (up-to) 1GB at 3GB
* Window 3 is disabled
*/
/*
* TBIA before modifying windows.
*/
marvel_pci_tbi(hose, 0, -1);
/*
* Set up window 0 for scatter-gather 8MB at 8MB.
*/
hose->sg_isa = iommu_arena_new_node(marvel_cpuid_to_nid(io7->pe),
hose, 0x00800000, 0x00800000, 0);
hose->sg_isa->align_entry = 8; /* cache line boundary */
csrs->POx_WBASE[0].csr =
hose->sg_isa->dma_base | wbase_m_ena | wbase_m_sg;
csrs->POx_WMASK[0].csr = (hose->sg_isa->size - 1) & wbase_m_addr;
csrs->POx_TBASE[0].csr = virt_to_phys(hose->sg_isa->ptes);
/*
* Set up window 1 for direct-mapped 1GB at 2GB.
*/
csrs->POx_WBASE[1].csr = __direct_map_base | wbase_m_ena;
csrs->POx_WMASK[1].csr = (__direct_map_size - 1) & wbase_m_addr;
csrs->POx_TBASE[1].csr = 0;
/*
* Set up window 2 for scatter-gather (up-to) 1GB at 3GB.
*/
hose->sg_pci = iommu_arena_new_node(marvel_cpuid_to_nid(io7->pe),
hose, 0xc0000000, 0x40000000, 0);
hose->sg_pci->align_entry = 8; /* cache line boundary */
csrs->POx_WBASE[2].csr =
hose->sg_pci->dma_base | wbase_m_ena | wbase_m_sg;
csrs->POx_WMASK[2].csr = (hose->sg_pci->size - 1) & wbase_m_addr;
csrs->POx_TBASE[2].csr = virt_to_phys(hose->sg_pci->ptes);
/*
* Disable window 3.
*/
csrs->POx_WBASE[3].csr = 0;
/*
* Make sure that the AGP Monster Window is disabled.
*/
csrs->POx_CTRL.csr &= ~(1UL << 61);
#if 1
printk("FIXME: disabling master aborts\n");
csrs->POx_MSK_HEI.csr &= ~(3UL << 14);
#endif
/*
* TBIA after modifying windows.
*/
marvel_pci_tbi(hose, 0, -1);
}
static void __init
marvel_init_io7(struct io7 *io7)
{
int i;
printk("Initializing IO7 at PID %d\n", io7->pe);
/*
* Get the Port 7 CSR pointer.
*/
io7->csrs = IO7_PORT7_CSRS_KERN(io7->pe);
/*
* Init this IO7's hoses.
*/
for (i = 0; i < IO7_NUM_PORTS; i++) {
io7_ioport_csrs *csrs = IO7_CSRS_KERN(io7->pe, i);
if (csrs->POx_CACHE_CTL.csr == 8) {
io7->ports[i].enabled = 1;
io7_init_hose(io7, i);
}
}
}
void
marvel_io7_present(gct6_node *node)
{
int pe;
if (node->type != GCT_TYPE_HOSE ||
node->subtype != GCT_SUBTYPE_IO_PORT_MODULE)
return;
pe = (node->id >> 8) & 0xff;
printk("Found an IO7 at PID %d\n", pe);
alloc_io7(pe);
}
static void __init
marvel_init_vga_hose(void)
{
#ifdef CONFIG_VGA_HOSE
u64 *pu64 = (u64 *)((u64)hwrpb + hwrpb->ctbt_offset);
if (pu64[7] == 3) { /* TERM_TYPE == graphics */
struct pci_controller *hose = NULL;
int h = (pu64[30] >> 24) & 0xff; /* TERM_OUT_LOC, hose # */
struct io7 *io7;
int pid, port;
/* FIXME - encoding is going to have to change for Marvel
* since hose will be able to overflow a byte...
* need to fix this decode when the console
* changes its encoding
*/
printk("console graphics is on hose %d (console)\n", h);
/*
* The console's hose numbering is:
*
* hose<n:2>: PID
* hose<1:0>: PORT
*
* We need to find the hose at that pid and port
*/
pid = h >> 2;
port = h & 3;
if ((io7 = marvel_find_io7(pid)))
hose = io7->ports[port].hose;
if (hose) {
printk("Console graphics on hose %d\n", hose->index);
pci_vga_hose = hose;
}
}
#endif /* CONFIG_VGA_HOSE */
}
gct6_search_struct gct_wanted_node_list[] = {
{ GCT_TYPE_HOSE, GCT_SUBTYPE_IO_PORT_MODULE, marvel_io7_present },
{ 0, 0, NULL }
};
/*
* In case the GCT is not complete, let the user specify PIDs with IO7s
* at boot time. Syntax is 'io7=a,b,c,...,n' where a-n are the PIDs (decimal)
* where IO7s are connected
*/
static int __init
marvel_specify_io7(char *str)
{
unsigned long pid;
struct io7 *io7;
char *pchar;
do {
pid = simple_strtoul(str, &pchar, 0);
if (pchar != str) {
printk("User-specified IO7 at PID %lu\n", pid);
io7 = alloc_io7(pid);
if (io7) marvel_init_io7(io7);
}
if (pchar == str) pchar++;
str = pchar;
} while(*str);
return 0;
}
__setup("io7=", marvel_specify_io7);
void __init
marvel_init_arch(void)
{
struct io7 *io7;
/* With multiple PCI busses, we play with I/O as physical addrs. */
ioport_resource.end = ~0UL;
iomem_resource.end = ~0UL;
/* PCI DMA Direct Mapping is 1GB at 2GB. */
__direct_map_base = 0x80000000;
__direct_map_size = 0x40000000;
/* Parse the config tree. */
gct6_find_nodes(GCT_NODE_PTR(0), gct_wanted_node_list);
/* Init the io7s. */
for (io7 = NULL; NULL != (io7 = marvel_next_io7(io7)); )
marvel_init_io7(io7);
/* Check for graphic console location (if any). */
marvel_init_vga_hose();
}
void
marvel_kill_arch(int mode)
{
}
/*
* PCI Configuration Space access functions
*
* Configuration space addresses have the following format:
*
* |2 2 2 2|1 1 1 1|1 1 1 1|1 1
* |3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|R|R|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* n:24 reserved for hose base
* 23:16 bus number (8 bits = 128 possible buses)
* 15:11 Device number (5 bits)
* 10:8 function number
* 7:2 register number
*
* Notes:
* IO7 determines whether to use a type 0 or type 1 config cycle
* based on the bus number. Therefore the bus number must be set
* to 0 for the root bus on any hose.
*
* The function number selects which function of a multi-function device
* (e.g., SCSI and Ethernet).
*
*/
static inline unsigned long
build_conf_addr(struct pci_controller *hose, u8 bus,
unsigned int devfn, int where)
{
return (hose->config_space_base | (bus << 16) | (devfn << 8) | where);
}
static unsigned long
mk_conf_addr(struct pci_bus *pbus, unsigned int devfn, int where)
{
struct pci_controller *hose = pbus->sysdata;
struct io7_port *io7_port;
unsigned long addr = 0;
u8 bus = pbus->number;
if (!hose)
return addr;
/* Check for enabled. */
io7_port = hose->sysdata;
if (!io7_port->enabled)
return addr;
if (hose->first_busno == bus) {
/* Don't support idsel > 20 on primary bus. */
if (devfn >= PCI_DEVFN(21, 0))
return addr;
bus = 0;
}
addr = build_conf_addr(hose, bus, devfn, where);
DBG_CFG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
return addr;
}
static int
marvel_read_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 *value)
{
unsigned long addr;
if (0 == (addr = mk_conf_addr(bus, devfn, where)))
return PCIBIOS_DEVICE_NOT_FOUND;
switch(size) {
case 1:
*value = __kernel_ldbu(*(vucp)addr);
break;
case 2:
*value = __kernel_ldwu(*(vusp)addr);
break;
case 4:
*value = *(vuip)addr;
break;
default:
return PCIBIOS_FUNC_NOT_SUPPORTED;
}
return PCIBIOS_SUCCESSFUL;
}
static int
marvel_write_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 value)
{
unsigned long addr;
if (0 == (addr = mk_conf_addr(bus, devfn, where)))
return PCIBIOS_DEVICE_NOT_FOUND;
switch (size) {
case 1:
__kernel_stb(value, *(vucp)addr);
mb();
__kernel_ldbu(*(vucp)addr);
break;
case 2:
__kernel_stw(value, *(vusp)addr);
mb();
__kernel_ldwu(*(vusp)addr);
break;
case 4:
*(vuip)addr = value;
mb();
*(vuip)addr;
break;
default:
return PCIBIOS_FUNC_NOT_SUPPORTED;
}
return PCIBIOS_SUCCESSFUL;
}
struct pci_ops marvel_pci_ops =
{
.read = marvel_read_config,
.write = marvel_write_config,
};
/*
* Other PCI helper functions.
*/
void
marvel_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
{
io7_ioport_csrs *csrs = ((struct io7_port *)hose->sysdata)->csrs;
wmb();
csrs->POx_SG_TBIA.csr = 0;
mb();
csrs->POx_SG_TBIA.csr;
}
/*
* IO map support.
*/
unsigned long
marvel_ioremap(unsigned long addr, unsigned long size)
{
struct pci_controller *hose;
unsigned long baddr, last;
struct vm_struct *area;
unsigned long vaddr;
unsigned long *ptes;
unsigned long pfn;
/*
* Adjust the addr.
*/
#ifdef CONFIG_VGA_HOSE
if (pci_vga_hose && __marvel_is_mem_vga(addr)) {
addr += pci_vga_hose->mem_space->start;
}
#endif
if (!marvel_is_ioaddr(addr)) return 0UL;
/*
* Find the hose.
*/
for (hose = hose_head; hose; hose = hose->next) {
if ((addr >> 32) == (hose->mem_space->start >> 32))
break;
}
if (!hose)
return 0UL;
/*
* We have the hose - calculate the bus limits.
*/
baddr = addr - hose->mem_space->start;
last = baddr + size - 1;
/*
* Is it direct-mapped?
*/
if ((baddr >= __direct_map_base) &&
((baddr + size - 1) < __direct_map_base + __direct_map_size))
return IDENT_ADDR | (baddr - __direct_map_base);
/*
* Check the scatter-gather arena.
*/
if (hose->sg_pci &&
baddr >= (unsigned long)hose->sg_pci->dma_base &&
last < (unsigned long)hose->sg_pci->dma_base + hose->sg_pci->size){
/*
* Adjust the limits (mappings must be page aligned)
*/
baddr -= hose->sg_pci->dma_base;
last -= hose->sg_pci->dma_base;
baddr &= PAGE_MASK;
size = PAGE_ALIGN(last) - baddr;
/*
* Map it.
*/
area = get_vm_area(size, VM_IOREMAP);
if (!area) return (unsigned long)NULL;
ptes = hose->sg_pci->ptes;
for (vaddr = (unsigned long)area->addr;
baddr <= last;
baddr += PAGE_SIZE, vaddr += PAGE_SIZE) {
pfn = ptes[baddr >> PAGE_SHIFT];
if (!(pfn & 1)) {
printk("ioremap failed... pte not valid...\n");
vfree(area->addr);
return 0UL;
}
pfn >>= 1; /* make it a true pfn */
if (__alpha_remap_area_pages(VMALLOC_VMADDR(vaddr),
pfn << PAGE_SHIFT,
PAGE_SIZE, 0)) {
printk("FAILED to map...\n");
vfree(area->addr);
return 0UL;
}
}
flush_tlb_all();
vaddr = (unsigned long)area->addr + (addr & ~PAGE_MASK);
return vaddr;
}
/*
* Not found - assume legacy ioremap.
*/
return addr;
}
void
marvel_iounmap(unsigned long addr)
{
if (((long)addr >> 41) == -2)
return; /* kseg map, nothing to do */
if (addr)
return vfree((void *)(PAGE_MASK & addr));
}
#ifndef CONFIG_ALPHA_GENERIC
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);
}
/*
* RTC Support
*/
struct marvel_rtc_access_info {
unsigned long function;
unsigned long index;
unsigned long data;
};
static void
__marvel_access_rtc(void *info)
{
struct marvel_rtc_access_info *rtc_access = info;
register unsigned long __r0 __asm__("$0");
register unsigned long __r16 __asm__("$16") = rtc_access->function;
register unsigned long __r17 __asm__("$17") = rtc_access->index;
register unsigned long __r18 __asm__("$18") = rtc_access->data;
__asm__ __volatile__(
"call_pal %4 # cserve rtc"
: "=r"(__r16), "=r"(__r17), "=r"(__r18), "=r"(__r0)
: "i"(PAL_cserve), "0"(__r16), "1"(__r17), "2"(__r18)
: "$1", "$22", "$23", "$24", "$25");
rtc_access->data = __r0;
}
u8
__marvel_rtc_io(int write, u8 b, unsigned long addr)
{
struct marvel_rtc_access_info rtc_access = {0, };
static u8 index = 0;
u8 ret = 0;
switch(addr) {
case 0x70: /* RTC_PORT(0) */
if (write) index = b;
ret = index;
break;
case 0x71: /* RTC_PORT(1) */
rtc_access.index = index;
rtc_access.data = BCD_TO_BIN(b);
rtc_access.function = 0x49; /* GET_TOY */
if (write) rtc_access.function = 0x48; /* PUT_TOY */
#if CONFIG_SMP
if (smp_processor_id() != boot_cpuid)
smp_call_function_on_cpu(__marvel_access_rtc,
&rtc_access,
1, /* retry */
1, /* wait */
1UL << boot_cpuid);
else
__marvel_access_rtc(&rtc_access);
#else
__marvel_access_rtc(&rtc_access);
#endif
ret = BIN_TO_BCD(rtc_access.data);
break;
default:
printk(KERN_WARNING "Illegal RTC port %lx\n", addr);
break;
}
return ret;
}
/*
* NUMA Support
*/
/**********
* FIXME - for now each cpu is a node by itself
* -- no real support for striped mode
**********
*/
int
marvel_pa_to_nid(unsigned long pa)
{
int cpuid;
if ((pa >> 43) & 1) /* I/O */
cpuid = (~(pa >> 35) & 0xff);
else /* mem */
cpuid = ((pa >> 34) & 0x3) | ((pa >> (37 - 2)) & (0x1f << 2));
return marvel_cpuid_to_nid(cpuid);
}
int
marvel_cpuid_to_nid(int cpuid)
{
return cpuid;
}
unsigned long
marvel_node_mem_start(int nid)
{
unsigned long pa;
pa = (nid & 0x3) | ((nid & (0x1f << 2)) << 1);
pa <<= 34;
return pa;
}
unsigned long
marvel_node_mem_size(int nid)
{
return 16UL * 1024 * 1024 * 1024; /* 16GB */
}
/*
* AGP GART Support.
*/
#include <linux/agp_backend.h>
#include <asm/agp_backend.h>
#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;
long pg_count;
};
static int
marvel_agp_setup(alpha_agp_info *agp)
{
struct marvel_agp_aperture *aper;
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_start = iommu_reserve(aper->arena, aper->pg_count,
aper->pg_count - 1);
if (aper->pg_start < 0) {
printk(KERN_ERR "Failed to reserve AGP memory\n");
kfree(aper);
return -ENOMEM;
}
agp->aperture.bus_base =
aper->arena->dma_base + aper->pg_start * PAGE_SIZE;
agp->aperture.size = aper->pg_count * PAGE_SIZE;
agp->aperture.sysdata = aper;
return 0;
}
static void
marvel_agp_cleanup(alpha_agp_info *agp)
{
struct marvel_agp_aperture *aper = agp->aperture.sysdata;
int status;
status = iommu_release(aper->arena, aper->pg_start, aper->pg_count);
if (status == -EBUSY) {
printk(KERN_WARNING
"Attempted to release bound AGP memory - unbinding\n");
iommu_unbind(aper->arena, aper->pg_start, aper->pg_count);
status = iommu_release(aper->arena, aper->pg_start,
aper->pg_count);
}
if (status < 0)
printk(KERN_ERR "Failed to release AGP memory\n");
kfree(aper);
kfree(agp);
}
static int
marvel_agp_configure(alpha_agp_info *agp)
{
io7_ioport_csrs *csrs = ((struct io7_port *)agp->hose->sysdata)->csrs;
struct io7 *io7 = ((struct io7_port *)agp->hose->sysdata)->io7;
unsigned int new_rate = 0;
unsigned long agp_pll;
/*
* Check the requested mode against the PLL setting.
* The agpgart_be code has not programmed the card yet,
* so we can still tweak mode here.
*/
agp_pll = io7->csrs->POx_RST[IO7_AGP_PORT].csr;
switch(IO7_PLL_RNGB(agp_pll)) {
case 0x4: /* 2x only */
/*
* The PLL is only programmed for 2x, so adjust the
* rate to 2x, if necessary.
*/
if (agp->mode.bits.rate != 2)
new_rate = 2;
break;
case 0x6: /* 1x / 4x */
/*
* The PLL is programmed for 1x or 4x. Don't go faster
* than requested, so if the requested rate is 2x, use 1x.
*/
if (agp->mode.bits.rate == 2)
new_rate = 1;
break;
default: /* ??????? */
/*
* Don't know what this PLL setting is, take the requested
* rate, but warn the user.
*/
printk("%s: unknown PLL setting RNGB=%lx (PLL6_CTL=%016lx)\n",
__FUNCTION__, IO7_PLL_RNGB(agp_pll), agp_pll);
break;
}
/*
* Set the new rate, if necessary.
*/
if (new_rate) {
printk("Requested AGP Rate %dX not compatible "
"with PLL setting - using %dX\n",
agp->mode.bits.rate,
new_rate);
agp->mode.bits.rate = new_rate;
}
printk("Enabling AGP on hose %d: %dX%s RQ %d\n",
agp->hose->index, agp->mode.bits.rate,
agp->mode.bits.sba ? " - SBA" : "", agp->mode.bits.rq);
csrs->AGP_CMD.csr = agp->mode.lw;
return 0;
}
static int
marvel_agp_bind_memory(alpha_agp_info *agp, off_t pg_start, agp_memory *mem)
{
struct marvel_agp_aperture *aper = agp->aperture.sysdata;
return iommu_bind(aper->arena, aper->pg_start + pg_start,
mem->page_count, mem->memory);
}
static int
marvel_agp_unbind_memory(alpha_agp_info *agp, off_t pg_start, agp_memory *mem)
{
struct marvel_agp_aperture *aper = agp->aperture.sysdata;
return iommu_unbind(aper->arena, aper->pg_start + pg_start,
mem->page_count);
}
static unsigned long
marvel_agp_translate(alpha_agp_info *agp, dma_addr_t addr)
{
struct marvel_agp_aperture *aper = agp->aperture.sysdata;
unsigned long baddr = addr - aper->arena->dma_base;
unsigned long pte;
if (addr < agp->aperture.bus_base ||
addr >= agp->aperture.bus_base + agp->aperture.size) {
printk("%s: addr out of range\n", __FUNCTION__);
return -EINVAL;
}
pte = aper->arena->ptes[baddr >> PAGE_SHIFT];
if (!(pte & 1)) {
printk("%s: pte not valid\n", __FUNCTION__);
return -EINVAL;
}
return (pte >> 1) << PAGE_SHIFT;
}
struct alpha_agp_ops marvel_agp_ops =
{
.setup = marvel_agp_setup,
.cleanup = marvel_agp_cleanup,
.configure = marvel_agp_configure,
.bind = marvel_agp_bind_memory,
.unbind = marvel_agp_unbind_memory,
.translate = marvel_agp_translate
};
alpha_agp_info *
marvel_agp_info(void)
{
struct pci_controller *hose;
io7_ioport_csrs *csrs;
alpha_agp_info *agp;
struct io7 *io7;
/*
* Find the first IO7 with an AGP card.
*
* FIXME -- there should be a better way (we want to be able to
* specify and what if the agp card is not video???)
*/
hose = NULL;
for (io7 = NULL; (io7 = marvel_next_io7(io7)) != NULL; ) {
struct pci_controller *h;
vuip addr;
if (!io7->ports[IO7_AGP_PORT].enabled)
continue;
h = io7->ports[IO7_AGP_PORT].hose;
addr = (vuip)build_conf_addr(h, 0, PCI_DEVFN(5, 0), 0);
if (*addr != 0xffffffffu) {
hose = h;
break;
}
}
printk("MARVEL - using hose %d as AGP\n", hose->index);
if (!hose || !hose->sg_pci)
return NULL;
/*
* Get the csrs from the hose.
*/
csrs = ((struct io7_port *)hose->sysdata)->csrs;
/*
* Allocate the info structure.
*/
agp = kmalloc(sizeof(*agp), GFP_KERNEL);
/*
* Fill it in.
*/
agp->type = 0 /* FIXME: ALPHA_CORE_AGP */;
agp->hose = hose;
agp->private = NULL;
agp->ops = &marvel_agp_ops;
/*
* Aperture - not configured until ops.setup().
*/
agp->aperture.bus_base = 0;
agp->aperture.size = 0;
agp->aperture.sysdata = NULL;
/*
* Capabilities.
*
* NOTE: IO7 reports through AGP_STAT that it can support a read queue
* depth of 17 (rq = 0x10). It actually only supports a depth of
* 16 (rq = 0xf).
*/
agp->capability.lw = csrs->AGP_STAT.csr;
agp->capability.bits.rq = 0xf;
/*
* Mode.
*/
agp->mode.lw = csrs->AGP_CMD.csr;
return agp;
}
...@@ -5,15 +5,20 @@ ...@@ -5,15 +5,20 @@
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/vmalloc.h>
#include <asm/hwrpb.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
#define __EXTERN_INLINE inline #define __EXTERN_INLINE inline
#include <asm/io.h> #include <asm/io.h>
...@@ -25,8 +30,6 @@ ...@@ -25,8 +30,6 @@
#include "proto.h" #include "proto.h"
#include "pci_impl.h" #include "pci_impl.h"
unsigned TITAN_agp = 0;
/* Save Titan configuration data as the console had it set up. */ /* Save Titan configuration data as the console had it set up. */
struct struct
...@@ -49,6 +52,31 @@ struct ...@@ -49,6 +52,31 @@ struct
# define DBG_CFG(args) # define DBG_CFG(args)
#endif #endif
/*
* Routines to access TIG registers.
*/
static inline volatile unsigned long *
mk_tig_addr(int offset)
{
return (volatile unsigned long *)(TITAN_TIG_SPACE + (offset << 6));
}
static inline u8
titan_read_tig(int offset, u8 value)
{
volatile unsigned long *tig_addr = mk_tig_addr(offset);
return (u8)(*tig_addr & 0xff);
}
static inline void
titan_write_tig(int offset, u8 value)
{
volatile unsigned long *tig_addr = mk_tig_addr(offset);
*tig_addr = (unsigned long)value;
}
/* /*
* Given a bus, device, and function number, compute resulting * Given a bus, device, and function number, compute resulting
* configuration space address * configuration space address
...@@ -179,13 +207,16 @@ titan_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end) ...@@ -179,13 +207,16 @@ titan_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
volatile unsigned long *csr; volatile unsigned long *csr;
unsigned long value; unsigned long value;
/* Get the right hose */ /* Get the right hose. */
port = &pachip->g_port; port = &pachip->g_port;
if (hose->index & 2) if (hose->index & 2)
port = &pachip->a_port; port = &pachip->a_port;
/* We can invalidate up to 8 tlb entries in a go. The flush /* We can invalidate up to 8 tlb entries in a go. The flush
matches against <31:16> in the pci address. */ matches against <31:16> in the pci address.
Note that gtlbi* and atlbi* are in the same place in the g_port
and a_port, respectively, so the g_port offset can be used
even if hose is an a_port */
csr = &port->port_specific.g.gtlbia.csr; csr = &port->port_specific.g.gtlbia.csr;
if (((start ^ end) & 0xffff0000) == 0) if (((start ^ end) & 0xffff0000) == 0)
csr = &port->port_specific.g.gtlbiv.csr; csr = &port->port_specific.g.gtlbiv.csr;
...@@ -200,9 +231,7 @@ titan_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end) ...@@ -200,9 +231,7 @@ titan_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
*csr; *csr;
} }
#define FN __FUNCTION__ static int
static int __init
titan_query_agp(titan_pachip_port *port) titan_query_agp(titan_pachip_port *port)
{ {
union TPAchipPCTL pctl; union TPAchipPCTL pctl;
...@@ -213,36 +242,6 @@ titan_query_agp(titan_pachip_port *port) ...@@ -213,36 +242,6 @@ titan_query_agp(titan_pachip_port *port)
return pctl.pctl_r_bits.apctl_v_agp_present; return pctl.pctl_r_bits.apctl_v_agp_present;
} }
static void __init
titan_init_agp(titan_pachip_port *port, struct pci_controller *hose)
{
union TPAchipPCTL pctl;
if (!titan_query_agp(port))
return;
printk("AGP present on hose %d\n", hose->index);
/* get APCTL */
pctl.pctl_q_whole = port->pctl.csr;
pctl.pctl_r_bits.apctl_v_agp_en = 1; /* enable AGP */
pctl.pctl_r_bits.apctl_v_agp_lp_rd = 0;
pctl.pctl_r_bits.apctl_v_agp_hp_rd = 0;
port->pctl.csr = pctl.pctl_q_whole;
TITAN_agp |= 1 << hose->index;
#ifdef CONFIG_VGA_HOSE
/* is a graphics card on the AGP? (always device 5) */
if (hose != NULL &&
__kernel_ldwu(*(vusp)(hose->config_space_base + 0x280a)) ==
PCI_CLASS_DISPLAY_VGA)
set_vga_hose(hose);
#endif
}
static void __init static void __init
titan_init_one_pachip_port(titan_pachip_port *port, int index) titan_init_one_pachip_port(titan_pachip_port *port, int index)
...@@ -255,10 +254,13 @@ titan_init_one_pachip_port(titan_pachip_port *port, int index) ...@@ -255,10 +254,13 @@ titan_init_one_pachip_port(titan_pachip_port *port, int index)
hose->io_space = alloc_resource(); hose->io_space = alloc_resource();
hose->mem_space = alloc_resource(); hose->mem_space = alloc_resource();
/* This is for userland consumption. For some reason, the 40-bit /*
PIO bias that we use in the kernel through KSEG didn't work for * This is for userland consumption. The 40-bit PIO bias that we
the page table based user mappings. So make sure we get the * use in the kernel through KSEG doesn't work in the page table
43-bit PIO bias. */ * based user mappings. (43-bit KSEG sign extends the physical
* address from bit 40 to hit the I/O bit - mapped addresses don't).
* So make sure we get the 43-bit PIO bias.
*/
hose->sparse_mem_base = 0; hose->sparse_mem_base = 0;
hose->sparse_io_base = 0; hose->sparse_io_base = 0;
hose->dense_mem_base hose->dense_mem_base
...@@ -284,9 +286,6 @@ titan_init_one_pachip_port(titan_pachip_port *port, int index) ...@@ -284,9 +286,6 @@ titan_init_one_pachip_port(titan_pachip_port *port, int index)
if (request_resource(&iomem_resource, hose->mem_space) < 0) if (request_resource(&iomem_resource, hose->mem_space) < 0)
printk(KERN_ERR "Failed to request MEM on hose %d\n", index); printk(KERN_ERR "Failed to request MEM on hose %d\n", index);
/* It's safe to call this for both G-Ports and A-Ports */
titan_init_agp(port, hose);
/* /*
* Save the existing PCI window translations. SRM will * Save the existing PCI window translations. SRM will
* need them when we go to reboot. * need them when we go to reboot.
...@@ -310,39 +309,41 @@ titan_init_one_pachip_port(titan_pachip_port *port, int index) ...@@ -310,39 +309,41 @@ titan_init_one_pachip_port(titan_pachip_port *port, int index)
/* /*
* Set up the PCI to main memory translation windows. * Set up the PCI to main memory translation windows.
* *
* Note: Window 3 on Titan is Scatter-Gather ONLY * Note: Window 3 on Titan is Scatter-Gather ONLY.
* *
* Window 0 is scatter-gather 8MB at 8MB (for isa) * Window 0 is scatter-gather 8MB at 8MB (for isa)
* Window 1 is scatter-gather (up to) 1GB at 1GB * Window 1 is direct access 1GB at 2GB
* Window 2 is direct access 2GB at 2GB * Window 2 is scatter-gather 1GB at 3GB
*/ */
hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0); hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0);
hose->sg_isa->align_entry = 8; /* 64KB for ISA */ hose->sg_isa->align_entry = 8; /* 64KB for ISA */
hose->sg_pci = iommu_arena_new(hose, 0x40000000, hose->sg_pci = iommu_arena_new(hose, 0xc0000000, 0x40000000, 0);
size_for_memory(0x40000000), 0);
hose->sg_pci->align_entry = 4; /* Titan caches 4 PTEs at a time */ hose->sg_pci->align_entry = 4; /* Titan caches 4 PTEs at a time */
__direct_map_base = 0x80000000;
__direct_map_size = 0x80000000;
port->wsba[0].csr = hose->sg_isa->dma_base | 3; port->wsba[0].csr = hose->sg_isa->dma_base | 3;
port->wsm[0].csr = (hose->sg_isa->size - 1) & 0xfff00000; port->wsm[0].csr = (hose->sg_isa->size - 1) & 0xfff00000;
port->tba[0].csr = virt_to_phys(hose->sg_isa->ptes); port->tba[0].csr = virt_to_phys(hose->sg_isa->ptes);
port->wsba[1].csr = hose->sg_pci->dma_base | 3; port->wsba[1].csr = __direct_map_base | 1;
port->wsm[1].csr = (hose->sg_pci->size - 1) & 0xfff00000; port->wsm[1].csr = (__direct_map_size - 1) & 0xfff00000;
port->tba[1].csr = virt_to_phys(hose->sg_pci->ptes); port->tba[1].csr = 0;
port->wsba[2].csr = 0x80000000 | 1; port->wsba[2].csr = hose->sg_pci->dma_base | 3;
port->wsm[2].csr = (0x80000000 - 1) & 0xfff00000; port->wsm[2].csr = (hose->sg_pci->size - 1) & 0xfff00000;
port->tba[2].csr = 0; port->tba[2].csr = virt_to_phys(hose->sg_pci->ptes);
port->wsba[3].csr = 0; port->wsba[3].csr = 0;
/* Enable the Monster Window to make DAC pci64 possible. */ /* Enable the Monster Window to make DAC pci64 possible. */
port->pctl.csr |= pctl_m_mwin; port->pctl.csr |= pctl_m_mwin;
/*
* If it's an AGP port, initialize agplastwr.
*/
if (titan_query_agp(port))
port->port_specific.a.agplastwr.csr = __direct_map_base;
titan_pci_tbi(hose, 0, -1); titan_pci_tbi(hose, 0, -1);
} }
...@@ -360,25 +361,51 @@ titan_init_pachips(titan_pachip *pachip0, titan_pachip *pachip1) ...@@ -360,25 +361,51 @@ titan_init_pachips(titan_pachip *pachip0, titan_pachip *pachip1)
titan_init_one_pachip_port(&pachip1->a_port, 3);/* hose 3 */ titan_init_one_pachip_port(&pachip1->a_port, 3);/* hose 3 */
} }
static void __init
titan_init_vga_hose(void)
{
#ifdef CONFIG_VGA_HOSE
u64 *pu64 = (u64 *)((u64)hwrpb + hwrpb->ctbt_offset);
if (pu64[7] == 3) { /* TERM_TYPE == graphics */
struct pci_controller *hose;
int h = (pu64[30] >> 24) & 0xff; /* console hose # */
/*
* Our hose numbering matches the console's, so just find
* the right one...
*/
for (hose = hose_head; hose; hose = hose->next) {
if (hose->index == h) break;
}
if (hose) {
printk("Console graphics on hose %d\n", hose->index);
pci_vga_hose = hose;
}
}
#endif /* CONFIG_VGA_HOSE */
}
void __init void __init
titan_init_arch(void) titan_init_arch(void)
{ {
#if 0 #if 0
printk("%s: titan_init_arch()\n", FN); printk("%s: titan_init_arch()\n", __FUNCTION__);
printk("%s: CChip registers:\n", FN); printk("%s: CChip registers:\n", __FUNCTION__);
printk("%s: CSR_CSC 0x%lx\n", FN, TITAN_cchip->csc.csr); printk("%s: CSR_CSC 0x%lx\n", __FUNCTION__, TITAN_cchip->csc.csr);
printk("%s: CSR_MTR 0x%lx\n", FN, TITAN_cchip->mtr.csr); printk("%s: CSR_MTR 0x%lx\n", __FUNCTION__, TITAN_cchip->mtr.csr);
printk("%s: CSR_MISC 0x%lx\n", FN, TITAN_cchip->misc.csr); printk("%s: CSR_MISC 0x%lx\n", __FUNCTION__, TITAN_cchip->misc.csr);
printk("%s: CSR_DIM0 0x%lx\n", FN, TITAN_cchip->dim0.csr); printk("%s: CSR_DIM0 0x%lx\n", __FUNCTION__, TITAN_cchip->dim0.csr);
printk("%s: CSR_DIM1 0x%lx\n", FN, TITAN_cchip->dim1.csr); printk("%s: CSR_DIM1 0x%lx\n", __FUNCTION__, TITAN_cchip->dim1.csr);
printk("%s: CSR_DIR0 0x%lx\n", FN, TITAN_cchip->dir0.csr); printk("%s: CSR_DIR0 0x%lx\n", __FUNCTION__, TITAN_cchip->dir0.csr);
printk("%s: CSR_DIR1 0x%lx\n", FN, TITAN_cchip->dir1.csr); printk("%s: CSR_DIR1 0x%lx\n", __FUNCTION__, TITAN_cchip->dir1.csr);
printk("%s: CSR_DRIR 0x%lx\n", FN, TITAN_cchip->drir.csr); printk("%s: CSR_DRIR 0x%lx\n", __FUNCTION__, TITAN_cchip->drir.csr);
printk("%s: DChip registers:\n", FN); printk("%s: DChip registers:\n", __FUNCTION__);
printk("%s: CSR_DSC 0x%lx\n", FN, TITAN_dchip->dsc.csr); printk("%s: CSR_DSC 0x%lx\n", __FUNCTION__, TITAN_dchip->dsc.csr);
printk("%s: CSR_STR 0x%lx\n", FN, TITAN_dchip->str.csr); printk("%s: CSR_STR 0x%lx\n", __FUNCTION__, TITAN_dchip->str.csr);
printk("%s: CSR_DREV 0x%lx\n", FN, TITAN_dchip->drev.csr); printk("%s: CSR_DREV 0x%lx\n", __FUNCTION__, TITAN_dchip->drev.csr);
#endif #endif
boot_cpuid = __hard_smp_processor_id(); boot_cpuid = __hard_smp_processor_id();
...@@ -387,8 +414,15 @@ titan_init_arch(void) ...@@ -387,8 +414,15 @@ titan_init_arch(void)
ioport_resource.end = ~0UL; ioport_resource.end = ~0UL;
iomem_resource.end = ~0UL; iomem_resource.end = ~0UL;
/* Init the PA chip(s) */ /* PCI DMA Direct Mapping is 1GB at 2GB. */
__direct_map_base = 0x80000000;
__direct_map_size = 0x40000000;
/* Init the PA chip(s). */
titan_init_pachips(TITAN_pachip0, TITAN_pachip1); titan_init_pachips(TITAN_pachip0, TITAN_pachip1);
/* Check for graphic console location (if any). */
titan_init_vga_hose();
} }
static void static void
...@@ -417,8 +451,8 @@ titan_kill_pachips(titan_pachip *pachip0, titan_pachip *pachip1) ...@@ -417,8 +451,8 @@ titan_kill_pachips(titan_pachip *pachip0, titan_pachip *pachip1)
int pchip1_present = TITAN_cchip->csc.csr & 1L<<14; int pchip1_present = TITAN_cchip->csc.csr & 1L<<14;
if (pchip1_present) { if (pchip1_present) {
titan_kill_one_pachip_port(&pachip0->g_port, 1); titan_kill_one_pachip_port(&pachip1->g_port, 1);
titan_kill_one_pachip_port(&pachip0->a_port, 3); titan_kill_one_pachip_port(&pachip1->a_port, 3);
} }
titan_kill_one_pachip_port(&pachip0->g_port, 0); titan_kill_one_pachip_port(&pachip0->g_port, 0);
titan_kill_one_pachip_port(&pachip0->a_port, 2); titan_kill_one_pachip_port(&pachip0->a_port, 2);
...@@ -430,38 +464,336 @@ titan_kill_arch(int mode) ...@@ -430,38 +464,336 @@ titan_kill_arch(int mode)
titan_kill_pachips(TITAN_pachip0, TITAN_pachip1); titan_kill_pachips(TITAN_pachip0, TITAN_pachip1);
} }
static inline void
titan_pci_clr_err_1(titan_pachip *pachip) /*
* IO map support.
*/
unsigned long
titan_ioremap(unsigned long addr, unsigned long size)
{ {
unsigned int jd; int h = (addr & TITAN_HOSE_MASK) >> TITAN_HOSE_SHIFT;
unsigned long baddr = addr & ~TITAN_HOSE_MASK;
unsigned long last = baddr + size - 1;
struct pci_controller *hose;
struct vm_struct *area;
unsigned long vaddr;
unsigned long *ptes;
unsigned long pfn;
/*
* Adjust the addr.
*/
#ifdef CONFIG_VGA_HOSE
if (pci_vga_hose && __titan_is_mem_vga(addr)) {
h = pci_vga_hose->index;
addr += pci_vga_hose->mem_space->start;
}
#endif
/*
* Find the hose.
*/
for (hose = hose_head; hose; hose = hose->next)
if (hose->index == h) break;
if (!hose) return (unsigned long)NULL;
/*
* Is it direct-mapped?
*/
if ((baddr >= __direct_map_base) &&
((baddr + size - 1) < __direct_map_base + __direct_map_size))
return addr - __direct_map_base + TITAN_MEM_BIAS;
/*
* Check the scatter-gather arena.
*/
if (hose->sg_pci &&
baddr >= (unsigned long)hose->sg_pci->dma_base &&
last < (unsigned long)hose->sg_pci->dma_base + hose->sg_pci->size){
/*
* Adjust the limits (mappings must be page aligned)
*/
baddr -= hose->sg_pci->dma_base;
last -= hose->sg_pci->dma_base;
baddr &= PAGE_MASK;
size = PAGE_ALIGN(last) - baddr;
/*
* Map it
*/
area = get_vm_area(size, VM_IOREMAP);
if (!area) return (unsigned long)NULL;
ptes = hose->sg_pci->ptes;
for (vaddr = (unsigned long)area->addr;
baddr <= last;
baddr += PAGE_SIZE, vaddr += PAGE_SIZE) {
pfn = ptes[baddr >> PAGE_SHIFT];
if (!(pfn & 1)) {
printk("ioremap failed... pte not valid...\n");
vfree(area->addr);
return (unsigned long)NULL;
}
pfn >>= 1; /* make it a true pfn */
if (__alpha_remap_area_pages(VMALLOC_VMADDR(vaddr),
pfn << PAGE_SHIFT,
PAGE_SIZE, 0)) {
printk("FAILED to map...\n");
vfree(area->addr);
return (unsigned long)NULL;
}
}
flush_tlb_all();
vaddr = (unsigned long)area->addr + (addr & ~PAGE_MASK);
return vaddr;
}
/*
* Not found - assume legacy ioremap.
*/
return addr + TITAN_MEM_BIAS;
jd = pachip->g_port.port_specific.g.gperror.csr;
pachip->g_port.port_specific.g.gperror.csr = jd;
mb();
pachip->g_port.port_specific.g.gperror.csr;
} }
static inline void void
titan_pci_clr_err(void) titan_iounmap(unsigned long addr)
{ {
titan_pci_clr_err_1(TITAN_pachip0); if (((long)addr >> 41) == -2)
return; /* kseg map, nothing to do */
if (addr)
vfree((void *)(PAGE_MASK & addr));
}
#ifndef CONFIG_ALPHA_GENERIC
EXPORT_SYMBOL(titan_ioremap);
EXPORT_SYMBOL(titan_iounmap);
#endif
/*
* AGP GART Support.
*/
#include <linux/agp_backend.h>
#include <asm/agp_backend.h>
#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;
long pg_count;
};
if (TITAN_cchip->csc.csr & 1L<<14) static int
titan_pci_clr_err_1(TITAN_pachip1); titan_agp_setup(alpha_agp_info *agp)
{
struct titan_agp_aperture *aper;
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_start = iommu_reserve(aper->arena, aper->pg_count,
aper->pg_count - 1);
if (aper->pg_start < 0) {
printk(KERN_ERR "Failed to reserve AGP memory\n");
kfree(aper);
return -ENOMEM;
}
agp->aperture.bus_base =
aper->arena->dma_base + aper->pg_start * PAGE_SIZE;
agp->aperture.size = aper->pg_count * PAGE_SIZE;
agp->aperture.sysdata = aper;
return 0;
} }
void static void
titan_machine_check(unsigned long vector, unsigned long la_ptr, titan_agp_cleanup(alpha_agp_info *agp)
struct pt_regs * regs)
{ {
/* clear error before any reporting. */ struct titan_agp_aperture *aper = agp->aperture.sysdata;
mb(); int status;
draina();
titan_pci_clr_err(); status = iommu_release(aper->arena, aper->pg_start, aper->pg_count);
wrmces(0x7); if (status == -EBUSY) {
mb(); printk(KERN_WARNING
"Attempted to release bound AGP memory - unbinding\n");
iommu_unbind(aper->arena, aper->pg_start, aper->pg_count);
status = iommu_release(aper->arena, aper->pg_start,
aper->pg_count);
}
if (status < 0)
printk(KERN_ERR "Failed to release AGP memory\n");
kfree(aper);
kfree(agp);
}
static int
titan_agp_configure(alpha_agp_info *agp)
{
union TPAchipPCTL pctl;
titan_pachip_port *port = agp->private;
pctl.pctl_q_whole = port->pctl.csr;
/* Side-Band Addressing? */
pctl.pctl_r_bits.apctl_v_agp_sba_en = agp->mode.bits.sba;
/* AGP Rate? */
pctl.pctl_r_bits.apctl_v_agp_rate = 0; /* 1x */
if (agp->mode.bits.rate & 2)
pctl.pctl_r_bits.apctl_v_agp_rate = 1; /* 2x */
#if 0
if (agp->mode.bits.rate & 4)
pctl.pctl_r_bits.apctl_v_agp_rate = 2; /* 4x */
#endif
/* RQ Depth? */
pctl.pctl_r_bits.apctl_v_agp_hp_rd = 2;
pctl.pctl_r_bits.apctl_v_agp_lp_rd = 7;
/*
* AGP Enable.
*/
pctl.pctl_r_bits.apctl_v_agp_en = agp->mode.bits.enable;
/* Tell the user. */
printk("Enabling AGP: %dX%s\n",
1 << pctl.pctl_r_bits.apctl_v_agp_rate,
pctl.pctl_r_bits.apctl_v_agp_sba_en ? " - SBA" : "");
/* Write it. */
port->pctl.csr = pctl.pctl_q_whole;
/* And wait at least 5000 66MHz cycles (per Titan spec). */
udelay(100);
return 0;
}
static int
titan_agp_bind_memory(alpha_agp_info *agp, off_t pg_start, agp_memory *mem)
{
struct titan_agp_aperture *aper = agp->aperture.sysdata;
return iommu_bind(aper->arena, aper->pg_start + pg_start,
mem->page_count, mem->memory);
}
static int
titan_agp_unbind_memory(alpha_agp_info *agp, off_t pg_start, agp_memory *mem)
{
struct titan_agp_aperture *aper = agp->aperture.sysdata;
return iommu_unbind(aper->arena, aper->pg_start + pg_start,
mem->page_count);
}
static unsigned long
titan_agp_translate(alpha_agp_info *agp, dma_addr_t addr)
{
struct titan_agp_aperture *aper = agp->aperture.sysdata;
unsigned long baddr = addr - aper->arena->dma_base;
unsigned long pte;
if (addr < agp->aperture.bus_base ||
addr >= agp->aperture.bus_base + agp->aperture.size) {
printk("%s: addr out of range\n", __FUNCTION__);
return -EINVAL;
}
pte = aper->arena->ptes[baddr >> PAGE_SHIFT];
if (!(pte & 1)) {
printk("%s: pte not valid\n", __FUNCTION__);
return -EINVAL;
}
process_mcheck_info(vector, la_ptr, regs, "TITAN", return (pte >> 1) << PAGE_SHIFT;
mcheck_expected(smp_processor_id()));
} }
struct alpha_agp_ops titan_agp_ops =
{
setup: titan_agp_setup,
cleanup: titan_agp_cleanup,
configure: titan_agp_configure,
bind: titan_agp_bind_memory,
unbind: titan_agp_unbind_memory,
translate: titan_agp_translate
};
alpha_agp_info *
titan_agp_info(void)
{
alpha_agp_info *agp;
struct pci_controller *hose;
titan_pachip_port *port;
int hosenum = -1;
union TPAchipPCTL pctl;
/*
* Find the AGP port.
*/
port = &TITAN_pachip0->a_port;
if (titan_query_agp(port))
hosenum = 2;
if (hosenum < 0 &&
titan_query_agp(port = &TITAN_pachip1->a_port))
hosenum = 3;
/*
* Find the hose the port is on.
*/
for (hose = hose_head; hose; hose = hose->next)
if (hose->index == hosenum)
break;
if (!hose || !hose->sg_pci)
return NULL;
/*
* Allocate the info structure.
*/
agp = kmalloc(sizeof(*agp), GFP_KERNEL);
/*
* Fill it in.
*/
agp->type = 0 /* FIXME: ALPHA_CORE_AGP */;
agp->hose = hose;
agp->private = port;
agp->ops = &titan_agp_ops;
/*
* Aperture - not configured until ops.setup().
*
* FIXME - should we go ahead and allocate it here?
*/
agp->aperture.bus_base = 0;
agp->aperture.size = 0;
agp->aperture.sysdata = NULL;
/*
* Capabilities.
*/
agp->capability.lw = 0;
agp->capability.bits.rate = 3; /* 2x, 1x */
agp->capability.bits.sba = 1;
agp->capability.bits.rq = 7; /* 8 - 1 */
/*
* Mode.
*/
pctl.pctl_q_whole = port->pctl.csr;
agp->mode.lw = 0;
agp->mode.bits.rate = 1 << pctl.pctl_r_bits.apctl_v_agp_rate;
agp->mode.bits.sba = pctl.pctl_r_bits.apctl_v_agp_sba_en;
agp->mode.bits.rq = 7; /* RQ Depth? */
agp->mode.bits.enable = pctl.pctl_r_bits.apctl_v_agp_en;
return agp;
}
...@@ -357,7 +357,6 @@ void __init ...@@ -357,7 +357,6 @@ void __init
tsunami_init_arch(void) tsunami_init_arch(void)
{ {
#ifdef NXM_MACHINE_CHECKS_ON_TSUNAMI #ifdef NXM_MACHINE_CHECKS_ON_TSUNAMI
extern asmlinkage void entInt(void);
unsigned long tmp; unsigned long tmp;
/* Ho hum.. init_arch is called before init_IRQ, but we need to be /* Ho hum.. init_arch is called before init_IRQ, but we need to be
......
...@@ -146,3 +146,17 @@ extern void cdl_check_console_data_log(void); ...@@ -146,3 +146,17 @@ extern void cdl_check_console_data_log(void);
extern int cdl_register_subpacket_annotation(struct el_subpacket_annotation *); extern int cdl_register_subpacket_annotation(struct el_subpacket_annotation *);
extern int cdl_register_subpacket_handler(struct el_subpacket_handler *); extern int cdl_register_subpacket_handler(struct el_subpacket_handler *);
/*
* err_marvel.c
*/
extern void marvel_machine_check(u64, u64, struct pt_regs *);
extern void marvel_register_error_handlers(void);
/*
* err_titan.c
*/
extern int titan_process_logout_frame(struct el_common *, int);
extern void titan_machine_check(u64, u64, struct pt_regs *);
extern void titan_register_error_handlers(void);
extern int privateer_process_logout_frame(struct el_common *, int);
extern void privateer_machine_check(u64, u64, struct pt_regs *);
/*
* linux/arch/alpha/kernel/err_marvel.c
*
* Copyright (C) 2001 Jeff Wiedemeier (Compaq Computer Corporation)
*
*/
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/sched.h>
#include <asm/io.h>
#include <asm/console.h>
#include <asm/core_marvel.h>
#include <asm/hwrpb.h>
#include <asm/smp.h>
#include "err_impl.h"
#include "proto.h"
void
marvel_machine_check(u64 vector, u64 la_ptr, struct pt_regs *regs)
{
struct el_subpacket *el_ptr = (struct el_subpacket *)la_ptr;
/*
* Sync the processor
*/
mb();
draina();
el_process_subpacket(el_ptr);
switch(vector) {
case SCB_Q_SYSEVENT:
printk(KERN_CRIT "MARVEL SYSEVENT %ld\n", vector);
break;
case SCB_Q_SYSMCHK:
case SCB_Q_SYSERR:
printk(KERN_CRIT "MARVEL SYSMCHK/ERR %ld\n", vector);
break;
default:
/* Don't know it - pass it up. */
return ev7_machine_check(vector, la_ptr, regs);
}
/* Release the logout frame. */
wrmces(0x7);
mb();
}
void
marvel_register_error_handlers(void)
{
ev7_register_error_handlers();
}
/*
* linux/arch/alpha/kernel/err_titan.c
*
* Copyright (C) 2000 Jeff Wiedemeier (Compaq Computer Corporation)
*
* Error handling code supporting TITAN systems
*/
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/sched.h>
#include <asm/io.h>
#include <asm/core_titan.h>
#include <asm/hwrpb.h>
#include <asm/smp.h>
#include "err_impl.h"
#include "proto.h"
static int
titan_parse_c_misc(u64 c_misc, int print)
{
char *src;
int nxs = 0;
int status = MCHK_DISPOSITION_REPORT;
#define TITAN__CCHIP_MISC__NXM (1UL << 28)
#define TITAN__CCHIP_MISC__NXS__S (29)
#define TITAN__CCHIP_MISC__NXS__M (0x7)
if (!(c_misc & TITAN__CCHIP_MISC__NXM))
return MCHK_DISPOSITION_UNKNOWN_ERROR;
#ifdef CONFIG_VERBOSE_MCHECK
if (!print)
return status;
nxs = EXTRACT(c_misc, TITAN__CCHIP_MISC__NXS);
switch(nxs) {
case 0: /* CPU 0 */
case 1: /* CPU 1 */
case 2: /* CPU 2 */
case 3: /* CPU 3 */
src = "CPU";
/* num is already the CPU number */
break;
case 4: /* Pchip 0 */
case 5: /* Pchip 1 */
src = "Pchip";
nxs -= 4;
break;
default:/* reserved */
src = "Unknown, NXS =";
/* leave num untouched */
break;
}
printk("%s Non-existent memory access from: %s %d\n",
err_print_prefix, src, nxs);
#endif /* CONFIG_VERBOSE_MCHECK */
return status;
}
static int
titan_parse_p_serror(int which, u64 serror, int print)
{
int status = MCHK_DISPOSITION_REPORT;
#ifdef CONFIG_VERBOSE_MCHECK
char *serror_src[] = {"GPCI", "APCI", "AGP HP", "AGP LP"};
char *serror_cmd[] = {"DMA Read", "DMA RMW", "SGTE Read", "Reserved"};
#endif /* CONFIG_VERBOSE_MCHECK */
#define TITAN__PCHIP_SERROR__LOST_UECC (1UL << 0)
#define TITAN__PCHIP_SERROR__UECC (1UL << 1)
#define TITAN__PCHIP_SERROR__CRE (1UL << 2)
#define TITAN__PCHIP_SERROR__NXIO (1UL << 3)
#define TITAN__PCHIP_SERROR__LOST_CRE (1UL << 4)
#define TITAN__PCHIP_SERROR__ECCMASK (TITAN__PCHIP_SERROR__UECC | \
TITAN__PCHIP_SERROR__CRE)
#define TITAN__PCHIP_SERROR__ERRMASK (TITAN__PCHIP_SERROR__LOST_UECC | \
TITAN__PCHIP_SERROR__UECC | \
TITAN__PCHIP_SERROR__CRE | \
TITAN__PCHIP_SERROR__NXIO | \
TITAN__PCHIP_SERROR__LOST_CRE)
#define TITAN__PCHIP_SERROR__SRC__S (52)
#define TITAN__PCHIP_SERROR__SRC__M (0x3)
#define TITAN__PCHIP_SERROR__CMD__S (54)
#define TITAN__PCHIP_SERROR__CMD__M (0x3)
#define TITAN__PCHIP_SERROR__SYN__S (56)
#define TITAN__PCHIP_SERROR__SYN__M (0xff)
#define TITAN__PCHIP_SERROR__ADDR__S (15)
#define TITAN__PCHIP_SERROR__ADDR__M (0xffffffffUL)
if (!(serror & TITAN__PCHIP_SERROR__ERRMASK))
return MCHK_DISPOSITION_UNKNOWN_ERROR;
#ifdef CONFIG_VERBOSE_MCHECK
if (!print)
return status;
printk("%s PChip %d SERROR: %016lx\n",
err_print_prefix, which, serror);
if (serror & TITAN__PCHIP_SERROR__ECCMASK) {
printk("%s %sorrectable ECC Error:\n"
" Source: %-6s Command: %-8s Syndrome: 0x%08x\n"
" Address: 0x%lx\n",
err_print_prefix,
(serror & TITAN__PCHIP_SERROR__UECC) ? "Unc" : "C",
serror_src[EXTRACT(serror, TITAN__PCHIP_SERROR__SRC)],
serror_cmd[EXTRACT(serror, TITAN__PCHIP_SERROR__CMD)],
(unsigned)EXTRACT(serror, TITAN__PCHIP_SERROR__SYN),
EXTRACT(serror, TITAN__PCHIP_SERROR__ADDR));
}
if (serror & TITAN__PCHIP_SERROR__NXIO)
printk("%s Non Existent I/O Error\n", err_print_prefix);
if (serror & TITAN__PCHIP_SERROR__LOST_UECC)
printk("%s Lost Uncorrectable ECC Error\n",
err_print_prefix);
if (serror & TITAN__PCHIP_SERROR__LOST_CRE)
printk("%s Lost Correctable ECC Error\n", err_print_prefix);
#endif /* CONFIG_VERBOSE_MCHECK */
return status;
}
static int
titan_parse_p_perror(int which, int port, u64 perror, int print)
{
int cmd;
unsigned long addr;
int status = MCHK_DISPOSITION_REPORT;
#ifdef CONFIG_VERBOSE_MCHECK
char *perror_cmd[] = { "Interrupt Acknowledge", "Special Cycle",
"I/O Read", "I/O Write",
"Reserved", "Reserved",
"Memory Read", "Memory Write",
"Reserved", "Reserved",
"Configuration Read", "Configuration Write",
"Memory Read Multiple", "Dual Address Cycle",
"Memory Read Line","Memory Write and Invalidate"
};
#endif /* CONFIG_VERBOSE_MCHECK */
#define TITAN__PCHIP_PERROR__LOST (1UL << 0)
#define TITAN__PCHIP_PERROR__SERR (1UL << 1)
#define TITAN__PCHIP_PERROR__PERR (1UL << 2)
#define TITAN__PCHIP_PERROR__DCRTO (1UL << 3)
#define TITAN__PCHIP_PERROR__SGE (1UL << 4)
#define TITAN__PCHIP_PERROR__APE (1UL << 5)
#define TITAN__PCHIP_PERROR__TA (1UL << 6)
#define TITAN__PCHIP_PERROR__DPE (1UL << 7)
#define TITAN__PCHIP_PERROR__NDS (1UL << 8)
#define TITAN__PCHIP_PERROR__IPTPR (1UL << 9)
#define TITAN__PCHIP_PERROR__IPTPW (1UL << 10)
#define TITAN__PCHIP_PERROR__ERRMASK (TITAN__PCHIP_PERROR__LOST | \
TITAN__PCHIP_PERROR__SERR | \
TITAN__PCHIP_PERROR__PERR | \
TITAN__PCHIP_PERROR__DCRTO | \
TITAN__PCHIP_PERROR__SGE | \
TITAN__PCHIP_PERROR__APE | \
TITAN__PCHIP_PERROR__TA | \
TITAN__PCHIP_PERROR__DPE | \
TITAN__PCHIP_PERROR__NDS | \
TITAN__PCHIP_PERROR__IPTPR | \
TITAN__PCHIP_PERROR__IPTPW)
#define TITAN__PCHIP_PERROR__DAC (1UL << 47)
#define TITAN__PCHIP_PERROR__MWIN (1UL << 48)
#define TITAN__PCHIP_PERROR__CMD__S (52)
#define TITAN__PCHIP_PERROR__CMD__M (0x0f)
#define TITAN__PCHIP_PERROR__ADDR__S (14)
#define TITAN__PCHIP_PERROR__ADDR__M (0x1ffffffff)
if (!(perror & TITAN__PCHIP_PERROR__ERRMASK))
return MCHK_DISPOSITION_UNKNOWN_ERROR;
cmd = EXTRACT(perror, TITAN__PCHIP_PERROR__CMD);
addr = EXTRACT(perror, TITAN__PCHIP_PERROR__ADDR) << 2;
/*
* Initializing the BIOS on a video card on a bus without
* a south bridge (subtractive decode agent) can result in
* master aborts as the BIOS probes the capabilities of the
* card. XFree86 does such initialization. If the error
* is a master abort (No DevSel as PCI Master) and the command
* is an I/O read or write below the address where we start
* assigning PCI I/O spaces (SRM uses 0x1000), then mark the
* error as dismissable so starting XFree86 doesn't result
* in a series of uncorrectable errors being reported. Also
* dismiss master aborts to VGA frame buffer space
* (0xA0000 - 0xC0000) and legacy BIOS space (0xC0000 - 0x100000)
* for the same reason.
*
* Also mark the error dismissible if it looks like the right
* error but only the Lost bit is set. Since the BIOS initialization
* can cause multiple master aborts and the error interrupt can
* be handled on a different CPU than the BIOS code is run on,
* it is possible for a second master abort to occur between the
* time the PALcode reads PERROR and the time it writes PERROR
* to acknowledge the error. If this timing happens, a second
* error will be signalled after the first, and if no additional
* errors occur, will look like a Lost error with no additional
* errors on the same transaction as the previous error.
*/
if (((perror & TITAN__PCHIP_PERROR__NDS) ||
((perror & TITAN__PCHIP_PERROR__ERRMASK) ==
TITAN__PCHIP_PERROR__LOST)) &&
((((cmd & 0xE) == 2) && (addr < 0x1000)) ||
(((cmd & 0xE) == 6) && (addr >= 0xA0000) && (addr < 0x100000)))) {
status = MCHK_DISPOSITION_DISMISS;
}
#ifdef CONFIG_VERBOSE_MCHECK
if (!print)
return status;
printk("%s PChip %d %cPERROR: %016lx\n",
err_print_prefix, which,
port ? 'A' : 'G', perror);
if (perror & TITAN__PCHIP_PERROR__IPTPW)
printk("%s Invalid Peer-to-Peer Write\n", err_print_prefix);
if (perror & TITAN__PCHIP_PERROR__IPTPR)
printk("%s Invalid Peer-to-Peer Read\n", err_print_prefix);
if (perror & TITAN__PCHIP_PERROR__NDS)
printk("%s No DEVSEL as PCI Master [Master Abort]\n",
err_print_prefix);
if (perror & TITAN__PCHIP_PERROR__DPE)
printk("%s Data Parity Error\n", err_print_prefix);
if (perror & TITAN__PCHIP_PERROR__TA)
printk("%s Target Abort\n", err_print_prefix);
if (perror & TITAN__PCHIP_PERROR__APE)
printk("%s Address Parity Error\n", err_print_prefix);
if (perror & TITAN__PCHIP_PERROR__SGE)
printk("%s Scatter-Gather Error, Invalid PTE\n",
err_print_prefix);
if (perror & TITAN__PCHIP_PERROR__DCRTO)
printk("%s Delayed-Completion Retry Timeout\n",
err_print_prefix);
if (perror & TITAN__PCHIP_PERROR__PERR)
printk("%s PERR Asserted\n", err_print_prefix);
if (perror & TITAN__PCHIP_PERROR__SERR)
printk("%s SERR Asserted\n", err_print_prefix);
if (perror & TITAN__PCHIP_PERROR__LOST)
printk("%s Lost Error\n", err_print_prefix);
printk("%s Command: 0x%x - %s\n"
" Address: 0x%lx\n",
err_print_prefix,
cmd, perror_cmd[cmd],
addr);
if (perror & TITAN__PCHIP_PERROR__DAC)
printk("%s Dual Address Cycle\n", err_print_prefix);
if (perror & TITAN__PCHIP_PERROR__MWIN)
printk("%s Hit in Monster Window\n", err_print_prefix);
#endif /* CONFIG_VERBOSE_MCHECK */
return status;
}
static int
titan_parse_p_agperror(int which, u64 agperror, int print)
{
int cmd, len;
unsigned long addr;
int status = MCHK_DISPOSITION_REPORT;
#ifdef CONFIG_VERBOSE_MCHECK
char *agperror_cmd[] = { "Read (low-priority)", "Read (high-priority)",
"Write (low-priority)",
"Write (high-priority)",
"Reserved", "Reserved",
"Flush", "Fence"
};
#endif /* CONFIG_VERBOSE_MCHECK */
#define TITAN__PCHIP_AGPERROR__LOST (1UL << 0)
#define TITAN__PCHIP_AGPERROR__LPQFULL (1UL << 1)
#define TITAN__PCHIP_AGPERROR__HPQFULL (1UL << 2)
#define TITAN__PCHIP_AGPERROR__RESCMD (1UL << 3)
#define TITAN__PCHIP_AGPERROR__IPTE (1UL << 4)
#define TITAN__PCHIP_AGPERROR__PTP (1UL << 5)
#define TITAN__PCHIP_AGPERROR__NOWINDOW (1UL << 6)
#define TITAN__PCHIP_AGPERROR__ERRMASK (TITAN__PCHIP_AGPERROR__LOST | \
TITAN__PCHIP_AGPERROR__LPQFULL | \
TITAN__PCHIP_AGPERROR__HPQFULL | \
TITAN__PCHIP_AGPERROR__RESCMD | \
TITAN__PCHIP_AGPERROR__IPTE | \
TITAN__PCHIP_AGPERROR__PTP | \
TITAN__PCHIP_AGPERROR__NOWINDOW)
#define TITAN__PCHIP_AGPERROR__DAC (1UL << 48)
#define TITAN__PCHIP_AGPERROR__MWIN (1UL << 49)
#define TITAN__PCHIP_AGPERROR__FENCE (1UL << 59)
#define TITAN__PCHIP_AGPERROR__CMD__S (50)
#define TITAN__PCHIP_AGPERROR__CMD__M (0x07)
#define TITAN__PCHIP_AGPERROR__ADDR__S (15)
#define TITAN__PCHIP_AGPERROR__ADDR__M (0xffffffffUL)
#define TITAN__PCHIP_AGPERROR__LEN__S (53)
#define TITAN__PCHIP_AGPERROR__LEN__M (0x3f)
if (!(agperror & TITAN__PCHIP_AGPERROR__ERRMASK))
return MCHK_DISPOSITION_UNKNOWN_ERROR;
#ifdef CONFIG_VERBOSE_MCHECK
if (!print)
return status;
cmd = EXTRACT(agperror, TITAN__PCHIP_AGPERROR__CMD);
addr = EXTRACT(agperror, TITAN__PCHIP_AGPERROR__ADDR) << 3;
len = EXTRACT(agperror, TITAN__PCHIP_AGPERROR__LEN);
printk("%s PChip %d AGPERROR: %016lx\n", err_print_prefix,
which, agperror);
if (agperror & TITAN__PCHIP_AGPERROR__NOWINDOW)
printk("%s No Window\n", err_print_prefix);
if (agperror & TITAN__PCHIP_AGPERROR__PTP)
printk("%s Peer-to-Peer set\n", err_print_prefix);
if (agperror & TITAN__PCHIP_AGPERROR__IPTE)
printk("%s Invalid PTE\n", err_print_prefix);
if (agperror & TITAN__PCHIP_AGPERROR__RESCMD)
printk("%s Reserved Command\n", err_print_prefix);
if (agperror & TITAN__PCHIP_AGPERROR__HPQFULL)
printk("%s HP Transaction Received while Queue Full\n",
err_print_prefix);
if (agperror & TITAN__PCHIP_AGPERROR__LPQFULL)
printk("%s LP Transaction Received while Queue Full\n",
err_print_prefix);
if (agperror & TITAN__PCHIP_AGPERROR__LOST)
printk("%s Lost Error\n", err_print_prefix);
printk("%s Command: 0x%x - %s, %d Quadwords%s\n"
" Address: 0x%lx\n",
err_print_prefix, cmd, agperror_cmd[cmd], len,
(agperror & TITAN__PCHIP_AGPERROR__FENCE) ? ", FENCE" : "",
addr);
if (agperror & TITAN__PCHIP_AGPERROR__DAC)
printk("%s Dual Address Cycle\n", err_print_prefix);
if (agperror & TITAN__PCHIP_AGPERROR__MWIN)
printk("%s Hit in Monster Window\n", err_print_prefix);
#endif /* CONFIG_VERBOSE_MCHECK */
return status;
}
static int
titan_parse_p_chip(int which, u64 serror, u64 gperror,
u64 aperror, u64 agperror, int print)
{
int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
status |= titan_parse_p_serror(which, serror, print);
status |= titan_parse_p_perror(which, 0, gperror, print);
status |= titan_parse_p_perror(which, 1, aperror, print);
status |= titan_parse_p_agperror(which, agperror, print);
return status;
}
int
titan_process_logout_frame(struct el_common *mchk_header, int print)
{
struct el_TITAN_sysdata_mcheck *tmchk =
(struct el_TITAN_sysdata_mcheck *)
((unsigned long)mchk_header + mchk_header->sys_offset);
int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
status |= titan_parse_c_misc(tmchk->c_misc, print);
status |= titan_parse_p_chip(0, tmchk->p0_serror, tmchk->p0_gperror,
tmchk->p0_aperror, tmchk->p0_agperror,
print);
status |= titan_parse_p_chip(1, tmchk->p1_serror, tmchk->p1_gperror,
tmchk->p1_aperror, tmchk->p1_agperror,
print);
return status;
}
void
titan_machine_check(u64 vector, u64 la_ptr, struct pt_regs *regs)
{
struct el_common *mchk_header = (struct el_common *)la_ptr;
struct el_TITAN_sysdata_mcheck *tmchk =
(struct el_TITAN_sysdata_mcheck *)
((unsigned long)mchk_header + mchk_header->sys_offset);
u64 irqmask;
/*
* Mask of Titan interrupt sources which are reported as machine checks
*
* 63 - CChip Error
* 62 - PChip 0 H_Error
* 61 - PChip 1 H_Error
* 60 - PChip 0 C_Error
* 59 - PChip 1 C_Error
*/
#define TITAN_MCHECK_INTERRUPT_MASK 0xF800000000000000UL
/*
* Sync the processor
*/
mb();
draina();
/*
* Only handle system errors here
*/
if ((vector != SCB_Q_SYSMCHK) && (vector != SCB_Q_SYSERR))
return ev6_machine_check(vector, la_ptr, regs);
/*
* It's a system error, handle it here
*
* The PALcode has already cleared the error, so just parse it
*/
/*
* Parse the logout frame without printing first. If the only error(s)
* found are classified as "dismissable", then just dismiss them and
* don't print any message
*/
if (titan_process_logout_frame(mchk_header, 0) !=
MCHK_DISPOSITION_DISMISS) {
char *saved_err_prefix = err_print_prefix;
err_print_prefix = KERN_CRIT;
/*
* Either a nondismissable error was detected or no
* recognized error was detected in the logout frame
* -- report the error in either case
*/
printk("%s"
"*System %s Error (Vector 0x%x) reported on CPU %d:\n",
err_print_prefix,
(vector == SCB_Q_SYSERR)?"Correctable":"Uncorrectable",
(unsigned int)vector, (int)smp_processor_id());
#ifdef CONFIG_VERBOSE_MCHECK
titan_process_logout_frame(mchk_header, 1);
dik_show_regs(regs, NULL);
#endif /* CONFIG_VERBOSE_MCHECK */
err_print_prefix = saved_err_prefix;
/*
* Convert any pending interrupts which report as system
* machine checks to interrupts
*/
irqmask = tmchk->c_dirx & TITAN_MCHECK_INTERRUPT_MASK;
titan_dispatch_irqs(irqmask, regs);
}
/*
* Release the logout frame
*/
wrmces(0x7);
mb();
}
/*
* Subpacket Annotations
*/
static char *el_titan_pchip0_extended_annotation[] = {
"Subpacket Header", "P0_SCTL", "P0_SERREN",
"P0_APCTL", "P0_APERREN", "P0_AGPERREN",
"P0_ASPRST", "P0_AWSBA0", "P0_AWSBA1",
"P0_AWSBA2", "P0_AWSBA3", "P0_AWSM0",
"P0_AWSM1", "P0_AWSM2", "P0_AWSM3",
"P0_ATBA0", "P0_ATBA1", "P0_ATBA2",
"P0_ATBA3", "P0_GPCTL", "P0_GPERREN",
"P0_GSPRST", "P0_GWSBA0", "P0_GWSBA1",
"P0_GWSBA2", "P0_GWSBA3", "P0_GWSM0",
"P0_GWSM1", "P0_GWSM2", "P0_GWSM3",
"P0_GTBA0", "P0_GTBA1", "P0_GTBA2",
"P0_GTBA3", NULL
};
static char *el_titan_pchip1_extended_annotation[] = {
"Subpacket Header", "P1_SCTL", "P1_SERREN",
"P1_APCTL", "P1_APERREN", "P1_AGPERREN",
"P1_ASPRST", "P1_AWSBA0", "P1_AWSBA1",
"P1_AWSBA2", "P1_AWSBA3", "P1_AWSM0",
"P1_AWSM1", "P1_AWSM2", "P1_AWSM3",
"P1_ATBA0", "P1_ATBA1", "P1_ATBA2",
"P1_ATBA3", "P1_GPCTL", "P1_GPERREN",
"P1_GSPRST", "P1_GWSBA0", "P1_GWSBA1",
"P1_GWSBA2", "P1_GWSBA3", "P1_GWSM0",
"P1_GWSM1", "P1_GWSM2", "P1_GWSM3",
"P1_GTBA0", "P1_GTBA1", "P1_GTBA2",
"P1_GTBA3", NULL
};
static char *el_titan_memory_extended_annotation[] = {
"Subpacket Header", "AAR0", "AAR1",
"AAR2", "AAR3", "P0_SCTL",
"P0_GPCTL", "P0_APCTL", "P1_SCTL",
"P1_GPCTL", "P1_SCTL", NULL
};
static struct el_subpacket_annotation el_titan_annotations[] = {
SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
EL_TYPE__REGATTA__TITAN_PCHIP0_EXTENDED,
1,
"Titan PChip 0 Extended Frame",
el_titan_pchip0_extended_annotation),
SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
EL_TYPE__REGATTA__TITAN_PCHIP1_EXTENDED,
1,
"Titan PChip 1 Extended Frame",
el_titan_pchip1_extended_annotation),
SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
EL_TYPE__REGATTA__TITAN_MEMORY_EXTENDED,
1,
"Titan Memory Extended Frame",
el_titan_memory_extended_annotation),
SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
EL_TYPE__TERMINATION__TERMINATION,
1,
"Termination Subpacket",
NULL)
};
static struct el_subpacket *
el_process_regatta_subpacket(struct el_subpacket *header)
{
int status;
if (header->class != EL_CLASS__REGATTA_FAMILY) {
printk("%s ** Unexpected header CLASS %d TYPE %d, aborting\n",
err_print_prefix,
header->class, header->type);
return NULL;
}
switch(header->type) {
case EL_TYPE__REGATTA__PROCESSOR_ERROR_FRAME:
case EL_TYPE__REGATTA__SYSTEM_ERROR_FRAME:
case EL_TYPE__REGATTA__ENVIRONMENTAL_FRAME:
case EL_TYPE__REGATTA__PROCESSOR_DBL_ERROR_HALT:
case EL_TYPE__REGATTA__SYSTEM_DBL_ERROR_HALT:
printk("%s ** Occurred on CPU %d:\n",
err_print_prefix,
(int)header->by_type.regatta_frame.cpuid);
status = privateer_process_logout_frame((struct el_common *)
header->by_type.regatta_frame.data_start, 1);
break;
default:
printk("%s ** REGATTA TYPE %d SUBPACKET\n",
err_print_prefix, header->type);
el_annotate_subpacket(header);
break;
}
return (struct el_subpacket *)((unsigned long)header + header->length);
}
static struct el_subpacket_handler titan_subpacket_handler =
SUBPACKET_HANDLER_INIT(EL_CLASS__REGATTA_FAMILY,
el_process_regatta_subpacket);
void
titan_register_error_handlers(void)
{
size_t i;
for (i = 0; i < ARRAY_SIZE (el_titan_annotations); i++)
cdl_register_subpacket_annotation(&el_titan_annotations[i]);
cdl_register_subpacket_handler(&titan_subpacket_handler);
}
/*
* Privateer
*/
static int
privateer_process_680_frame(struct el_common *mchk_header, int print)
{
struct el_PRIVATEER_envdata_mcheck *emchk =
(struct el_PRIVATEER_envdata_mcheck *)
((unsigned long)mchk_header + mchk_header->sys_offset);
int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
/* TODO - catagorize errors, for now, no error */
#ifdef CONFIG_VERBOSE_MCHECK
if (!print)
return status;
/* TODO - decode instead of just dumping... */
printk("%s Summary Flags: %016lx\n"
" CChip DIRx: %016lx\n"
" System Management IR: %016lx\n"
" CPU IR: %016lx\n"
" Power Supply IR: %016lx\n"
" LM78 Fault Status: %016lx\n"
" System Doors: %016lx\n"
" Temperature Warning: %016lx\n"
" Fan Control: %016lx\n"
" Fatal Power Down Code: %016lx\n",
err_print_prefix,
emchk->summary,
emchk->c_dirx,
emchk->smir,
emchk->cpuir,
emchk->psir,
emchk->fault,
emchk->sys_doors,
emchk->temp_warn,
emchk->fan_ctrl,
emchk->code);
#endif /* CONFIG_VERBOSE_MCHECK */
return status;
}
int
privateer_process_logout_frame(struct el_common *mchk_header, int print)
{
struct el_common_EV6_mcheck *ev6mchk =
(struct el_common_EV6_mcheck *)mchk_header;
int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
/*
* Machine check codes
*/
#define PRIVATEER_MCHK__CORR_ECC 0x86 /* 630 */
#define PRIVATEER_MCHK__DC_TAG_PERR 0x9E /* 630 */
#define PRIVATEER_MCHK__PAL_BUGCHECK 0x8E /* 670 */
#define PRIVATEER_MCHK__OS_BUGCHECK 0x90 /* 670 */
#define PRIVATEER_MCHK__PROC_HRD_ERR 0x98 /* 670 */
#define PRIVATEER_MCHK__ISTREAM_CMOV_PRX 0xA0 /* 670 */
#define PRIVATEER_MCHK__ISTREAM_CMOV_FLT 0xA2 /* 670 */
#define PRIVATEER_MCHK__SYS_HRD_ERR 0x202 /* 660 */
#define PRIVATEER_MCHK__SYS_CORR_ERR 0x204 /* 620 */
#define PRIVATEER_MCHK__SYS_ENVIRON 0x206 /* 680 */
switch(ev6mchk->MCHK_Code) {
/*
* Vector 630 - Processor, Correctable
*/
case PRIVATEER_MCHK__CORR_ECC:
case PRIVATEER_MCHK__DC_TAG_PERR:
/*
* Fall through to vector 670 for processing...
*/
/*
* Vector 670 - Processor, Uncorrectable
*/
case PRIVATEER_MCHK__PAL_BUGCHECK:
case PRIVATEER_MCHK__OS_BUGCHECK:
case PRIVATEER_MCHK__PROC_HRD_ERR:
case PRIVATEER_MCHK__ISTREAM_CMOV_PRX:
case PRIVATEER_MCHK__ISTREAM_CMOV_FLT:
status |= ev6_process_logout_frame(mchk_header, print);
break;
/*
* Vector 620 - System, Correctable
*/
case PRIVATEER_MCHK__SYS_CORR_ERR:
/*
* Fall through to vector 660 for processing...
*/
/*
* Vector 660 - System, Uncorrectable
*/
case PRIVATEER_MCHK__SYS_HRD_ERR:
status |= titan_process_logout_frame(mchk_header, print);
break;
/*
* Vector 680 - System, Environmental
*/
case PRIVATEER_MCHK__SYS_ENVIRON: /* System, Environmental */
status |= privateer_process_680_frame(mchk_header, print);
break;
/*
* Unknown
*/
default:
status |= MCHK_DISPOSITION_REPORT;
if (print) {
printk("%s** Unknown Error, frame follows\n",
err_print_prefix);
mchk_dump_logout_frame(mchk_header);
}
}
return status;
}
void
privateer_machine_check(u64 vector, u64 la_ptr, struct pt_regs *regs)
{
struct el_common *mchk_header = (struct el_common *)la_ptr;
struct el_TITAN_sysdata_mcheck *tmchk =
(struct el_TITAN_sysdata_mcheck *)
(la_ptr + mchk_header->sys_offset);
u64 irqmask;
char *saved_err_prefix = err_print_prefix;
#define PRIVATEER_680_INTERRUPT_MASK (0xE00UL)
#define PRIVATEER_HOTPLUG_INTERRUPT_MASK (0xE00UL)
/*
* Sync the processor.
*/
mb();
draina();
/*
* Only handle system events here.
*/
if (vector != SCB_Q_SYSEVENT)
return titan_machine_check(vector, la_ptr, regs);
/*
* Report the event - System Events should be reported even if no
* error is indicated since the event could indicate the return
* to normal status.
*/
err_print_prefix = KERN_CRIT;
printk("%s*System Event (Vector 0x%x) reported on CPU %d:\n",
err_print_prefix,
(unsigned int)vector, (int)smp_processor_id());
privateer_process_680_frame(mchk_header, 1);
err_print_prefix = saved_err_prefix;
/*
* Convert any pending interrupts which report as 680 machine
* checks to interrupts.
*/
irqmask = tmchk->c_dirx & PRIVATEER_680_INTERRUPT_MASK;
/*
* Dispatch the interrupt(s).
*/
titan_dispatch_irqs(irqmask, regs);
/*
* Release the logout frame.
*/
wrmces(0x7);
mb();
}
/*
* linux/arch/alpha/kernel/gct.c
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/hwrpb.h>
#include <asm/gct.h>
int
gct6_find_nodes(gct6_node *node, gct6_search_struct *search)
{
gct6_search_struct *wanted;
int status = 0;
/* First check the magic number. */
if (node->magic != GCT_NODE_MAGIC) {
printk(KERN_ERR "GCT Node MAGIC incorrect - GCT invalid\n");
return -EINVAL;
}
/* Check against the search struct. */
for (wanted = search;
wanted && (wanted->type | wanted->subtype);
wanted++) {
if (node->type != wanted->type)
continue;
if (node->subtype != wanted->subtype)
continue;
/* Found it -- call out. */
if (wanted->callout)
wanted->callout(node);
}
/* Now walk the tree, siblings first. */
if (node->next)
status |= gct6_find_nodes(GCT_NODE_PTR(node->next), search);
/* Then the children. */
if (node->child)
status |= gct6_find_nodes(GCT_NODE_PTR(node->child), search);
return status;
}
...@@ -362,6 +362,7 @@ register_irq_proc (unsigned int irq) ...@@ -362,6 +362,7 @@ register_irq_proc (unsigned int irq)
irq_dir[irq] = proc_mkdir(name, root_irq_dir); irq_dir[irq] = proc_mkdir(name, root_irq_dir);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
if (irq_desc[irq].handler->set_affinity) {
/* create /proc/irq/1234/smp_affinity */ /* create /proc/irq/1234/smp_affinity */
entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]); entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
...@@ -371,6 +372,7 @@ register_irq_proc (unsigned int irq) ...@@ -371,6 +372,7 @@ register_irq_proc (unsigned int irq)
entry->write_proc = irq_affinity_write_proc; entry->write_proc = irq_affinity_write_proc;
smp_affinity_entry[irq] = entry; smp_affinity_entry[irq] = entry;
}
#endif #endif
} }
...@@ -398,13 +400,17 @@ init_irq_proc (void) ...@@ -398,13 +400,17 @@ init_irq_proc (void)
#endif #endif
/* /*
* Create entries for all existing IRQs. * Create entries for all existing IRQs. If the number of IRQs
* is greater the 1/4 the total dynamic inode space for /proc,
* don't pollute the inode space
*/ */
for (i = 0; i < NR_IRQS; i++) { if (ACTUAL_NR_IRQS < (PROC_NDYNAMIC / 4)) {
for (i = 0; i < ACTUAL_NR_IRQS; i++) {
if (irq_desc[i].handler == &no_irq_type) if (irq_desc[i].handler == &no_irq_type)
continue; continue;
register_irq_proc(i); register_irq_proc(i);
} }
}
} }
int int
...@@ -518,7 +524,7 @@ show_interrupts(struct seq_file *p, void *v) ...@@ -518,7 +524,7 @@ show_interrupts(struct seq_file *p, void *v)
seq_putc(p, '\n'); seq_putc(p, '\n');
#endif #endif
for (i = 0; i < NR_IRQS; i++) { for (i = 0; i < ACTUAL_NR_IRQS; i++) {
action = irq_desc[i].action; action = irq_desc[i].action;
if (!action) if (!action)
continue; continue;
......
...@@ -9,10 +9,12 @@ ...@@ -9,10 +9,12 @@
#include <linux/config.h> #include <linux/config.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
/* Whee. IRONGATE, POLARIS, TSUNAMI, TITAN, and WILDFIRE don't have an HAE. /* Whee. These systems don't have an HAE:
IRONGATE, MARVEL, POLARIS, TSUNAMI, TITAN, WILDFIRE
Fix things up for the GENERIC kernel by defining the HAE address Fix things up for the GENERIC kernel by defining the HAE address
to be that of the cache. Now we can read and write it as we like. ;-) */ to be that of the cache. Now we can read and write it as we like. ;-) */
#define IRONGATE_HAE_ADDRESS (&alpha_mv.hae_cache) #define IRONGATE_HAE_ADDRESS (&alpha_mv.hae_cache)
#define MARVEL_HAE_ADDRESS (&alpha_mv.hae_cache)
#define POLARIS_HAE_ADDRESS (&alpha_mv.hae_cache) #define POLARIS_HAE_ADDRESS (&alpha_mv.hae_cache)
#define TSUNAMI_HAE_ADDRESS (&alpha_mv.hae_cache) #define TSUNAMI_HAE_ADDRESS (&alpha_mv.hae_cache)
#define TITAN_HAE_ADDRESS (&alpha_mv.hae_cache) #define TITAN_HAE_ADDRESS (&alpha_mv.hae_cache)
...@@ -32,7 +34,6 @@ ...@@ -32,7 +34,6 @@
#define T2_IACK_SC 1 #define T2_IACK_SC 1
#define WILDFIRE_IACK_SC 1 /* FIXME */ #define WILDFIRE_IACK_SC 1 /* FIXME */
/* /*
* Some helpful macros for filling in the blanks. * Some helpful macros for filling in the blanks.
*/ */
...@@ -63,6 +64,13 @@ ...@@ -63,6 +64,13 @@
mv_flush_tlb_current: ev5_flush_tlb_current, \ mv_flush_tlb_current: ev5_flush_tlb_current, \
mv_flush_tlb_current_page: ev5_flush_tlb_current_page mv_flush_tlb_current_page: ev5_flush_tlb_current_page
#define DO_EV7_MMU \
max_asn: EV6_MAX_ASN, \
mv_switch_mm: ev5_switch_mm, \
mv_activate_mm: ev5_activate_mm, \
mv_flush_tlb_current: ev5_flush_tlb_current, \
mv_flush_tlb_current_page: ev5_flush_tlb_current_page
#define IO_LITE(UP,low) \ #define IO_LITE(UP,low) \
hae_register: (unsigned long *) CAT(UP,_HAE_ADDRESS), \ hae_register: (unsigned long *) CAT(UP,_HAE_ADDRESS), \
iack_sc: CAT(UP,_IACK_SC), \ iack_sc: CAT(UP,_IACK_SC), \
...@@ -91,6 +99,7 @@ ...@@ -91,6 +99,7 @@
#define DO_CIA_IO IO(CIA,cia) #define DO_CIA_IO IO(CIA,cia)
#define DO_IRONGATE_IO IO(IRONGATE,irongate) #define DO_IRONGATE_IO IO(IRONGATE,irongate)
#define DO_LCA_IO IO(LCA,lca) #define DO_LCA_IO IO(LCA,lca)
#define DO_MARVEL_IO IO(MARVEL,marvel)
#define DO_MCPCIA_IO IO(MCPCIA,mcpcia) #define DO_MCPCIA_IO IO(MCPCIA,mcpcia)
#define DO_POLARIS_IO IO(POLARIS,polaris) #define DO_POLARIS_IO IO(POLARIS,polaris)
#define DO_T2_IO IO(T2,t2) #define DO_T2_IO IO(T2,t2)
...@@ -109,6 +118,7 @@ ...@@ -109,6 +118,7 @@
#define DO_CIA_BUS BUS(cia) #define DO_CIA_BUS BUS(cia)
#define DO_IRONGATE_BUS BUS(irongate) #define DO_IRONGATE_BUS BUS(irongate)
#define DO_LCA_BUS BUS(lca) #define DO_LCA_BUS BUS(lca)
#define DO_MARVEL_BUS BUS(marvel)
#define DO_MCPCIA_BUS BUS(mcpcia) #define DO_MCPCIA_BUS BUS(mcpcia)
#define DO_POLARIS_BUS BUS(polaris) #define DO_POLARIS_BUS BUS(polaris)
#define DO_T2_BUS BUS(t2) #define DO_T2_BUS BUS(t2)
...@@ -116,7 +126,6 @@ ...@@ -116,7 +126,6 @@
#define DO_TITAN_BUS BUS(titan) #define DO_TITAN_BUS BUS(titan)
#define DO_WILDFIRE_BUS BUS(wildfire) #define DO_WILDFIRE_BUS BUS(wildfire)
/* /*
* In a GENERIC kernel, we have lots of these vectors floating about, * In a GENERIC kernel, we have lots of these vectors floating about,
* all but one of which we want to go away. In a non-GENERIC kernel, * all but one of which we want to go away. In a non-GENERIC kernel,
......
...@@ -825,7 +825,7 @@ extern struct timezone sys_tz; ...@@ -825,7 +825,7 @@ extern struct timezone sys_tz;
extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz); extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
extern int do_getitimer(int which, struct itimerval *value); extern int do_getitimer(int which, struct itimerval *value);
extern int do_setitimer(int which, struct itimerval *, struct itimerval *); extern int do_setitimer(int which, struct itimerval *, struct itimerval *);
asmlinkage int sys_utimes(char *, struct timeval *); extern asmlinkage int sys_utimes(char *, struct timeval *);
extern int do_adjtimex(struct timex *); extern int do_adjtimex(struct timex *);
struct timeval32 struct timeval32
......
...@@ -42,6 +42,8 @@ const char *const pci_mem_names[] = { ...@@ -42,6 +42,8 @@ const char *const pci_mem_names[] = {
const char pci_hae0_name[] = "HAE0"; const char pci_hae0_name[] = "HAE0";
/* Indicate whether we respect the PCI setup left by console. */
int __initdata pci_probe_only;
/* /*
* The PCI controller list. * The PCI controller list.
...@@ -270,6 +272,10 @@ pcibios_fixup_bus(struct pci_bus *bus) ...@@ -270,6 +272,10 @@ pcibios_fixup_bus(struct pci_bus *bus)
end = hose->mem_space->start + pci_mem_end; end = hose->mem_space->start + pci_mem_end;
if (hose->mem_space->end > end) if (hose->mem_space->end > end)
hose->mem_space->end = end; hose->mem_space->end = end;
} else if (pci_probe_only &&
(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
pci_read_bridge_bases(bus);
pcibios_fixup_device_resources(dev, bus);
} }
for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) { for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
...@@ -407,6 +413,30 @@ pcibios_set_master(struct pci_dev *dev) ...@@ -407,6 +413,30 @@ pcibios_set_master(struct pci_dev *dev)
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
} }
static void __init
pcibios_claim_console_setup(void)
{
struct list_head *lb;
for(lb = pci_root_buses.next; lb != &pci_root_buses; lb = lb->next) {
struct pci_bus *b = pci_bus_b(lb);
struct list_head *ld;
for (ld = b->devices.next; ld != &b->devices; ld = ld->next) {
struct pci_dev *dev = pci_dev_b(ld);
int i;
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
struct resource *r = &dev->resource[i];
if (r->parent || !r->start || !r->flags)
continue;
pci_claim_resource(dev, i);
}
}
}
}
void __init void __init
common_init_pci(void) common_init_pci(void)
{ {
...@@ -424,6 +454,11 @@ common_init_pci(void) ...@@ -424,6 +454,11 @@ common_init_pci(void)
next_busno += 1; next_busno += 1;
} }
if (pci_probe_only)
pcibios_claim_console_setup();
else /* FIXME: `else' will be removed when
pci_assign_unassigned_resources() is able to work
correctly with [partially] allocated PCI tree. */
pci_assign_unassigned_resources(); pci_assign_unassigned_resources();
pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq); pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
} }
......
...@@ -150,6 +150,9 @@ struct pci_iommu_arena ...@@ -150,6 +150,9 @@ struct pci_iommu_arena
extern struct pci_controller *hose_head, **hose_tail; extern struct pci_controller *hose_head, **hose_tail;
extern struct pci_controller *pci_isa_hose; extern struct pci_controller *pci_isa_hose;
/* Indicate that we trust the console to configure things properly. */
extern int pci_probe_only;
extern void common_init_pci(void); extern void common_init_pci(void);
extern u8 common_swizzle(struct pci_dev *, u8 *); extern u8 common_swizzle(struct pci_dev *, u8 *);
extern struct pci_controller *alloc_pci_controller(void); extern struct pci_controller *alloc_pci_controller(void);
......
#include <linux/config.h> #include <linux/config.h>
/* Prototypes of functions used across modules here in this directory. */ /* Prototypes of functions used across modules here in this directory. */
#define vucp volatile unsigned char * #define vucp volatile unsigned char *
...@@ -41,6 +43,22 @@ extern void lca_init_arch(void); ...@@ -41,6 +43,22 @@ extern void lca_init_arch(void);
extern void lca_machine_check(u64, u64, struct pt_regs *); extern void lca_machine_check(u64, u64, struct pt_regs *);
extern void lca_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); extern void lca_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
/* core_marvel.c */
extern struct pci_ops marvel_pci_ops;
extern void marvel_init_arch(void);
extern void marvel_kill_arch(int);
extern void marvel_machine_check(u64, u64, struct pt_regs *);
extern void marvel_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
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);
void io7_clear_errors(struct io7 *io7);
/* core_mcpcia.c */ /* core_mcpcia.c */
extern struct pci_ops mcpcia_pci_ops; extern struct pci_ops mcpcia_pci_ops;
extern void mcpcia_init_arch(void); extern void mcpcia_init_arch(void);
...@@ -68,6 +86,7 @@ extern void titan_init_arch(void); ...@@ -68,6 +86,7 @@ extern void titan_init_arch(void);
extern void titan_kill_arch(int); extern void titan_kill_arch(int);
extern void titan_machine_check(u64, u64, struct pt_regs *); extern void titan_machine_check(u64, u64, struct pt_regs *);
extern void titan_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); extern void titan_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
extern struct _alpha_agp_info *titan_agp_info(void);
/* core_tsunami.c */ /* core_tsunami.c */
extern struct pci_ops tsunami_pci_ops; extern struct pci_ops tsunami_pci_ops;
...@@ -149,10 +168,17 @@ extern int ptrace_cancel_bpt (struct task_struct *child); ...@@ -149,10 +168,17 @@ extern int ptrace_cancel_bpt (struct task_struct *child);
extern void dik_show_regs(struct pt_regs *regs, unsigned long *r9_15); extern void dik_show_regs(struct pt_regs *regs, unsigned long *r9_15);
extern void die_if_kernel(char *, struct pt_regs *, long, unsigned long *); extern void die_if_kernel(char *, struct pt_regs *, long, unsigned long *);
/* sys_titan.c */
extern void titan_dispatch_irqs(u64, struct pt_regs *);
/* ../mm/init.c */ /* ../mm/init.c */
extern void switch_to_system_map(void); extern void switch_to_system_map(void);
extern void srm_paging_stop(void); extern void srm_paging_stop(void);
/* ../mm/remap.c */
extern int __alpha_remap_area_pages(unsigned long, unsigned long,
unsigned long, unsigned long);
/* irq.c */ /* irq.c */
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
......
...@@ -155,6 +155,7 @@ WEAK(eb66p_mv); ...@@ -155,6 +155,7 @@ WEAK(eb66p_mv);
WEAK(eiger_mv); WEAK(eiger_mv);
WEAK(jensen_mv); WEAK(jensen_mv);
WEAK(lx164_mv); WEAK(lx164_mv);
WEAK(marvel_ev7_mv);
WEAK(miata_mv); WEAK(miata_mv);
WEAK(mikasa_mv); WEAK(mikasa_mv);
WEAK(mikasa_primo_mv); WEAK(mikasa_primo_mv);
...@@ -174,6 +175,7 @@ WEAK(sable_gamma_mv); ...@@ -174,6 +175,7 @@ WEAK(sable_gamma_mv);
WEAK(shark_mv); WEAK(shark_mv);
WEAK(sx164_mv); WEAK(sx164_mv);
WEAK(takara_mv); WEAK(takara_mv);
WEAK(titan_mv);
WEAK(webbrick_mv); WEAK(webbrick_mv);
WEAK(wildfire_mv); WEAK(wildfire_mv);
WEAK(xl_mv); WEAK(xl_mv);
...@@ -288,7 +290,7 @@ setup_memory(void *kernel_end) ...@@ -288,7 +290,7 @@ setup_memory(void *kernel_end)
(hwrpb->mddt_offset + (unsigned long) hwrpb); (hwrpb->mddt_offset + (unsigned long) hwrpb);
for_each_mem_cluster(memdesc, cluster, i) { for_each_mem_cluster(memdesc, cluster, i) {
printk("memcluster %d, usage %01lx, start %8lu, end %8lu\n", printk("memcluster %lu, usage %01lx, start %8lu, end %8lu\n",
i, cluster->usage, cluster->start_pfn, i, cluster->usage, cluster->start_pfn,
cluster->start_pfn + cluster->numpages); cluster->start_pfn + cluster->numpages);
...@@ -695,7 +697,7 @@ static char systype_names[][16] = { ...@@ -695,7 +697,7 @@ static char systype_names[][16] = {
"Mikasa", "EB64", "EB66", "EB64+", "AlphaBook1", "Mikasa", "EB64", "EB66", "EB64+", "AlphaBook1",
"Rawhide", "K2", "Lynx", "XL", "EB164", "Noritake", "Rawhide", "K2", "Lynx", "XL", "EB164", "Noritake",
"Cortex", "29", "Miata", "XXM", "Takara", "Yukon", "Cortex", "29", "Miata", "XXM", "Takara", "Yukon",
"Tsunami", "Wildfire", "CUSCO", "Eiger", "Titan" "Tsunami", "Wildfire", "CUSCO", "Eiger", "Titan", "Marvel"
}; };
static char unofficial_names[][8] = {"100", "Ruffian"}; static char unofficial_names[][8] = {"100", "Ruffian"};
...@@ -714,15 +716,20 @@ static int eb64p_indices[] = {0,0,1,2}; ...@@ -714,15 +716,20 @@ static int eb64p_indices[] = {0,0,1,2};
static char eb66_names[][8] = {"EB66", "EB66+"}; static char eb66_names[][8] = {"EB66", "EB66+"};
static int eb66_indices[] = {0,0,1}; static int eb66_indices[] = {0,0,1};
static char marvel_names[][16] = {
"Marvel/EV7"
};
static int marvel_indices[] = { 0 };
static char rawhide_names[][16] = { static char rawhide_names[][16] = {
"Dodge", "Wrangler", "Durango", "Tincup", "DaVinci" "Dodge", "Wrangler", "Durango", "Tincup", "DaVinci"
}; };
static int rawhide_indices[] = {0,0,0,1,1,2,2,3,3,4,4}; static int rawhide_indices[] = {0,0,0,1,1,2,2,3,3,4,4};
static char titan_names[][16] = { static char titan_names[][16] = {
"0", "Privateer" "DEFAULT", "Privateer", "Falcon", "Granite"
}; };
static int titan_indices[] = {0,1}; static int titan_indices[] = {0,1,2,2,3};
static char tsunami_names[][16] = { static char tsunami_names[][16] = {
"0", "DP264", "Warhol", "Windjammer", "Monet", "Clipper", "0", "DP264", "Warhol", "Windjammer", "Monet", "Clipper",
...@@ -775,6 +782,7 @@ get_sysvec(unsigned long type, unsigned long variation, unsigned long cpu) ...@@ -775,6 +782,7 @@ get_sysvec(unsigned long type, unsigned long variation, unsigned long cpu)
NULL, /* CUSCO */ NULL, /* CUSCO */
&eiger_mv, /* Eiger */ &eiger_mv, /* Eiger */
NULL, /* Titan */ NULL, /* Titan */
NULL, /* Marvel */
}; };
static struct alpha_machine_vector *unofficial_vecs[] __initdata = static struct alpha_machine_vector *unofficial_vecs[] __initdata =
...@@ -812,10 +820,17 @@ get_sysvec(unsigned long type, unsigned long variation, unsigned long cpu) ...@@ -812,10 +820,17 @@ get_sysvec(unsigned long type, unsigned long variation, unsigned long cpu)
&eb66p_mv &eb66p_mv
}; };
static struct alpha_machine_vector *marvel_vecs[] __initdata =
{
&marvel_ev7_mv,
};
static struct alpha_machine_vector *titan_vecs[] __initdata = static struct alpha_machine_vector *titan_vecs[] __initdata =
{ {
NULL, &titan_mv, /* default */
&privateer_mv, /* privateer */ &privateer_mv, /* privateer */
&titan_mv, /* falcon */
&privateer_mv, /* granite */
}; };
static struct alpha_machine_vector *tsunami_vecs[] __initdata = static struct alpha_machine_vector *tsunami_vecs[] __initdata =
...@@ -880,7 +895,12 @@ get_sysvec(unsigned long type, unsigned long variation, unsigned long cpu) ...@@ -880,7 +895,12 @@ get_sysvec(unsigned long type, unsigned long variation, unsigned long cpu)
if (member < N(eb66_indices)) if (member < N(eb66_indices))
vec = eb66_vecs[eb66_indices[member]]; vec = eb66_vecs[eb66_indices[member]];
break; break;
case ST_DEC_MARVEL:
if (member < N(marvel_indices))
vec = marvel_vecs[marvel_indices[member]];
break;
case ST_DEC_TITAN: case ST_DEC_TITAN:
vec = titan_vecs[0]; /* default */
if (member < N(titan_indices)) if (member < N(titan_indices))
vec = titan_vecs[titan_indices[member]]; vec = titan_vecs[titan_indices[member]];
break; break;
...@@ -1019,11 +1039,16 @@ get_sysnames(unsigned long type, unsigned long variation, unsigned long cpu, ...@@ -1019,11 +1039,16 @@ get_sysnames(unsigned long type, unsigned long variation, unsigned long cpu,
if (member < N(eb66_indices)) if (member < N(eb66_indices))
*variation_name = eb66_names[eb66_indices[member]]; *variation_name = eb66_names[eb66_indices[member]];
break; break;
case ST_DEC_MARVEL:
if (member < N(marvel_indices))
*variation_name = marvel_names[marvel_indices[member]];
break;
case ST_DEC_RAWHIDE: case ST_DEC_RAWHIDE:
if (member < N(rawhide_indices)) if (member < N(rawhide_indices))
*variation_name = rawhide_names[rawhide_indices[member]]; *variation_name = rawhide_names[rawhide_indices[member]];
break; break;
case ST_DEC_TITAN: case ST_DEC_TITAN:
*variation_name = titan_names[0]; /* default */
if (member < N(titan_indices)) if (member < N(titan_indices))
*variation_name = titan_names[titan_indices[member]]; *variation_name = titan_names[titan_indices[member]];
break; break;
......
...@@ -83,7 +83,6 @@ cycles_t cacheflush_time; ...@@ -83,7 +83,6 @@ cycles_t cacheflush_time;
unsigned long cache_decay_ticks; unsigned long cache_decay_ticks;
extern void calibrate_delay(void); extern void calibrate_delay(void);
extern asmlinkage void entInt(void);
...@@ -151,6 +150,9 @@ smp_callin(void) ...@@ -151,6 +150,9 @@ smp_callin(void)
/* Get our local ticker going. */ /* Get our local ticker going. */
smp_setup_percpu_timer(cpuid); smp_setup_percpu_timer(cpuid);
/* Call platform-specific callin, if specified */
if (alpha_mv.smp_callin) alpha_mv.smp_callin();
/* All kernel threads share the same mm context. */ /* All kernel threads share the same mm context. */
atomic_inc(&init_mm.mm_count); atomic_inc(&init_mm.mm_count);
current->active_mm = &init_mm; current->active_mm = &init_mm;
......
/*
* linux/arch/alpha/kernel/sys_marvel.c
*
* Marvel / IO7 support
*/
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <asm/ptrace.h>
#include <asm/system.h>
#include <asm/dma.h>
#include <asm/irq.h>
#include <asm/bitops.h>
#include <asm/mmu_context.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/core_marvel.h>
#include <asm/hwrpb.h>
#include <asm/tlbflush.h>
#include "proto.h"
#include "err_impl.h"
#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"
/*
* Interrupt handling.
*/
#define IRQ_VEC_PE_SHIFT (10)
#define IRQ_VEC_IRQ_MASK ((1 << IRQ_VEC_PE_SHIFT) - 1)
static void
io7_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
unsigned int pid;
unsigned int irq;
/*
* Vector is 0x800 + (interrupt)
*
* where (interrupt) is:
*
* ...16|15 14|13 4|3 0
* -----+-----+--------+---
* PE | 0 | irq | 0
*
* where (irq) is
*
* 0x0800 - 0x0ff0 - 0x0800 + (LSI id << 4)
* 0x1000 - 0x2ff0 - 0x1000 + (MSI_DAT<8:0> << 4)
*/
pid = vector >> 16;
irq = ((vector & 0xffff) - 0x800) >> 4;
irq += 16; /* offset for legacy */
irq &= IRQ_VEC_IRQ_MASK; /* not too many bits */
irq |= pid << IRQ_VEC_PE_SHIFT; /* merge the pid */
handle_irq(irq, regs);
}
static volatile unsigned long *
io7_get_irq_ctl(unsigned int irq, struct io7 **pio7)
{
volatile unsigned long *ctl;
unsigned int pid;
struct io7 *io7;
pid = irq >> IRQ_VEC_PE_SHIFT;
if (!(io7 = marvel_find_io7(pid))) {
printk(KERN_ERR
"%s for nonexistent io7 -- vec %x, pid %d\n",
__FUNCTION__, irq, pid);
return NULL;
}
irq &= IRQ_VEC_IRQ_MASK; /* isolate the vector */
irq -= 16; /* subtract legacy bias */
if (irq >= 0x180) {
printk(KERN_ERR
"%s for invalid irq -- pid %d adjusted irq %x\n",
__FUNCTION__, pid, irq);
return NULL;
}
ctl = &io7->csrs->PO7_LSI_CTL[irq & 0xff].csr; /* assume LSI */
if (irq >= 0x80) /* MSI */
ctl = &io7->csrs->PO7_MSI_CTL[((irq - 0x80) >> 5) & 0x0f].csr;
if (pio7) *pio7 = io7;
return ctl;
}
static void
io7_enable_irq(unsigned int irq)
{
volatile unsigned long *ctl;
struct io7 *io7;
ctl = io7_get_irq_ctl(irq, &io7);
if (!ctl || !io7) {
printk(KERN_ERR "%s: get_ctl failed for irq %x\n",
__FUNCTION__, irq);
return;
}
spin_lock(&io7->irq_lock);
*ctl |= 1UL << 24;
mb();
*ctl;
spin_unlock(&io7->irq_lock);
}
static void
io7_disable_irq(unsigned int irq)
{
volatile unsigned long *ctl;
struct io7 *io7;
ctl = io7_get_irq_ctl(irq, &io7);
if (!ctl || !io7) {
printk(KERN_ERR "%s: get_ctl failed for irq %x\n",
__FUNCTION__, irq);
return;
}
spin_lock(&io7->irq_lock);
*ctl &= ~(1UL << 24);
mb();
*ctl;
spin_unlock(&io7->irq_lock);
}
static unsigned int
io7_startup_irq(unsigned int irq)
{
io7_enable_irq(irq);
return 0; /* never anything pending */
}
static void
io7_end_irq(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
io7_enable_irq(irq);
}
static void
marvel_irq_noop(unsigned int irq)
{
return;
}
static unsigned int
marvel_irq_noop_return(unsigned int irq)
{
return 0;
}
static struct hw_interrupt_type marvel_legacy_irq_type = {
.typename = "LEGACY",
.startup = marvel_irq_noop_return,
.shutdown = marvel_irq_noop,
.enable = marvel_irq_noop,
.disable = marvel_irq_noop,
.ack = marvel_irq_noop,
.end = marvel_irq_noop,
};
static struct hw_interrupt_type io7_lsi_irq_type = {
.typename = "LSI",
.startup = io7_startup_irq,
.shutdown = io7_disable_irq,
.enable = io7_enable_irq,
.disable = io7_disable_irq,
.ack = io7_disable_irq,
.end = io7_end_irq,
};
static struct hw_interrupt_type io7_msi_irq_type = {
.typename = "MSI",
.startup = io7_startup_irq,
.shutdown = io7_disable_irq,
.enable = io7_enable_irq,
.disable = io7_disable_irq,
.ack = marvel_irq_noop,
.end = io7_end_irq,
};
static void
io7_redirect_irq(struct io7 *io7,
volatile unsigned long *csr,
unsigned int where)
{
unsigned long val;
val = *csr;
val &= ~(0x1ffUL << 24); /* clear the target pid */
val |= ((unsigned long)where << 24); /* set the new target pid */
*csr = val;
mb();
*csr;
}
static void
io7_redirect_one_lsi(struct io7 *io7, unsigned int which, unsigned int where)
{
unsigned long val;
/*
* LSI_CTL has target PID @ 14
*/
val = io7->csrs->PO7_LSI_CTL[which].csr;
val &= ~(0x1ffUL << 14); /* clear the target pid */
val |= ((unsigned long)where << 14); /* set teh new target pid */
io7->csrs->PO7_LSI_CTL[which].csr = val;
mb();
io7->csrs->PO7_LSI_CTL[which].csr;
}
static void
io7_redirect_one_msi(struct io7 *io7, unsigned int which, unsigned int where)
{
unsigned long val;
/*
* MSI_CTL has target PID @ 14
*/
val = io7->csrs->PO7_MSI_CTL[which].csr;
val &= ~(0x1ffUL << 14); /* clear the target pid */
val |= ((unsigned long)where << 14); /* set teh new target pid */
io7->csrs->PO7_MSI_CTL[which].csr = val;
mb();
io7->csrs->PO7_MSI_CTL[which].csr;
}
static void __init
init_one_io7_lsi(struct io7 *io7, unsigned int which, unsigned int where)
{
/*
* LSI_CTL has target PID @ 14
*/
io7->csrs->PO7_LSI_CTL[which].csr = ((unsigned long)where << 14);
mb();
io7->csrs->PO7_LSI_CTL[which].csr;
}
static void __init
init_one_io7_msi(struct io7 *io7, unsigned int which, unsigned int where)
{
/*
* MSI_CTL has target PID @ 14
*/
io7->csrs->PO7_MSI_CTL[which].csr = ((unsigned long)where << 14);
mb();
io7->csrs->PO7_MSI_CTL[which].csr;
}
static void __init
init_io7_irqs(struct io7 *io7,
struct hw_interrupt_type *lsi_ops,
struct hw_interrupt_type *msi_ops)
{
long base = (io7->pe << IRQ_VEC_PE_SHIFT) + 16;
long i;
printk("Initializing interrupts for IO7 at PE %u - base %lx\n",
io7->pe, base);
/*
* Where should interrupts from this IO7 go?
*
* They really should be sent to the local CPU to avoid having to
* traverse the mesh, but if it's not an SMP kernel, they have to
* go to the boot CPU. Send them all to the boot CPU for now,
* as each secondary starts, it can redirect it's local device
* interrupts.
*/
printk(" Interrupts reported to CPU at PE %u\n", boot_cpuid);
spin_lock(&io7->irq_lock);
/* set up the error irqs */
io7_redirect_irq(io7, &io7->csrs->HLT_CTL.csr, boot_cpuid);
io7_redirect_irq(io7, &io7->csrs->HPI_CTL.csr, boot_cpuid);
io7_redirect_irq(io7, &io7->csrs->CRD_CTL.csr, boot_cpuid);
io7_redirect_irq(io7, &io7->csrs->STV_CTL.csr, boot_cpuid);
io7_redirect_irq(io7, &io7->csrs->HEI_CTL.csr, boot_cpuid);
/* Set up the lsi irqs. */
for (i = 0; i < 128; ++i) {
irq_desc[base + i].status = IRQ_DISABLED | IRQ_LEVEL;
irq_desc[base + i].handler = lsi_ops;
}
/* Disable the implemented irqs in hardware. */
for (i = 0; i < 0x60; ++i)
init_one_io7_lsi(io7, i, boot_cpuid);
init_one_io7_lsi(io7, 0x74, boot_cpuid);
init_one_io7_lsi(io7, 0x75, boot_cpuid);
/* Set up the msi irqs. */
for (i = 128; i < (128 + 512); ++i) {
irq_desc[base + i].status = IRQ_DISABLED | IRQ_LEVEL;
irq_desc[base + i].handler = msi_ops;
}
for (i = 0; i < 16; ++i)
init_one_io7_msi(io7, i, boot_cpuid);
spin_unlock(&io7->irq_lock);
}
static void __init
marvel_init_irq(void)
{
int i;
struct io7 *io7 = NULL;
/* Reserve the legacy irqs. */
for (i = 0; i < 16; ++i) {
irq_desc[i].status = IRQ_DISABLED;
irq_desc[i].handler = &marvel_legacy_irq_type;
}
/* Init the io7 irqs. */
for (io7 = NULL; (io7 = marvel_next_io7(io7)) != NULL; )
init_io7_irqs(io7, &io7_lsi_irq_type, &io7_msi_irq_type);
}
static int
marvel_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
struct pci_controller *hose = dev->sysdata;
struct io7_port *io7_port = hose->sysdata;
struct io7 *io7 = io7_port->io7;
int msi_loc, msi_data_off;
u16 msg_ctl;
u16 msg_dat;
u8 intline;
int irq;
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &intline);
irq = intline;
msi_loc = pci_find_capability(dev, PCI_CAP_ID_MSI);
msg_ctl = 0;
if (msi_loc)
pci_read_config_word(dev, msi_loc + PCI_MSI_FLAGS, &msg_ctl);
if (msg_ctl & PCI_MSI_FLAGS_ENABLE) {
msi_data_off = PCI_MSI_DATA_32;
if (msg_ctl & PCI_MSI_FLAGS_64BIT)
msi_data_off = PCI_MSI_DATA_64;
pci_read_config_word(dev, msi_loc + msi_data_off, &msg_dat);
irq = msg_dat & 0x1ff; /* we use msg_data<8:0> */
irq += 0x80; /* offset for lsi */
#if 1
printk("PCI:%d:%d:%d (hose %d) [%s] is using MSI\n",
dev->bus->number,
PCI_SLOT(dev->devfn),
PCI_FUNC(dev->devfn),
hose->index,
dev->dev.name);
printk(" %d message(s) from 0x%04x\n",
1 << ((msg_ctl & PCI_MSI_FLAGS_QSIZE) >> 4),
msg_dat);
printk(" reporting on %d IRQ(s) from %d (0x%x)\n",
1 << ((msg_ctl & PCI_MSI_FLAGS_QSIZE) >> 4),
(irq + 16) | (io7->pe << IRQ_VEC_PE_SHIFT),
(irq + 16) | (io7->pe << IRQ_VEC_PE_SHIFT));
#endif
#if 0
pci_write_config_word(dev, msi_loc + PCI_MSI_FLAGS,
msg_ctl & ~PCI_MSI_FLAGS_ENABLE);
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &intline);
irq = intline;
printk(" forcing LSI interrupt on irq %d [0x%x]\n", irq, irq);
#endif
}
irq += 16; /* offset for legacy */
irq |= io7->pe << IRQ_VEC_PE_SHIFT; /* merge the pid */
return irq;
}
static void __init
marvel_init_pci(void)
{
struct io7 *io7;
marvel_register_error_handlers();
pci_probe_only = 1;
common_init_pci();
#ifdef CONFIG_VGA_HOSE
locate_and_init_vga(NULL);
#endif
/* Clear any io7 errors. */
for (io7 = NULL; (io7 = marvel_next_io7(io7)) != NULL; )
io7_clear_errors(io7);
}
static void
marvel_init_rtc(void)
{
init_rtc_irq();
}
static void
marvel_smp_callin(void)
{
int cpuid = hard_smp_processor_id();
struct io7 *io7 = marvel_find_io7(cpuid);
unsigned int i;
if (!io7)
return;
/*
* There is a local IO7 - redirect all of it's interrupts here.
*/
printk("Redirecting IO7 interrupts to local CPU at PE %u\n", cpuid);
/* Redirect the error IRQS here. */
io7_redirect_irq(io7, &io7->csrs->HLT_CTL.csr, cpuid);
io7_redirect_irq(io7, &io7->csrs->HPI_CTL.csr, cpuid);
io7_redirect_irq(io7, &io7->csrs->CRD_CTL.csr, cpuid);
io7_redirect_irq(io7, &io7->csrs->STV_CTL.csr, cpuid);
io7_redirect_irq(io7, &io7->csrs->HEI_CTL.csr, cpuid);
/* Redirect the implemented LSIs here. */
for (i = 0; i < 0x60; ++i)
io7_redirect_one_lsi(io7, i, cpuid);
io7_redirect_one_lsi(io7, 0x74, cpuid);
io7_redirect_one_lsi(io7, 0x75, cpuid);
/* Redirect the MSIs here. */
for (i = 0; i < 16; ++i)
io7_redirect_one_msi(io7, i, cpuid);
}
/*
* System Vectors
*/
struct alpha_machine_vector marvel_ev7_mv __initmv = {
.vector_name = "MARVEL/EV7",
DO_EV7_MMU,
DO_DEFAULT_RTC,
DO_MARVEL_IO,
DO_MARVEL_BUS,
.machine_check = marvel_machine_check,
.max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
.min_io_address = DEFAULT_IO_BASE,
.min_mem_address = DEFAULT_MEM_BASE,
.pci_dac_offset = IO7_DAC_OFFSET,
.nr_irqs = MARVEL_NR_IRQS,
.device_interrupt = io7_device_interrupt,
.agp_info = marvel_agp_info,
.smp_callin = marvel_smp_callin,
.init_arch = marvel_init_arch,
.init_irq = marvel_init_irq,
.init_rtc = marvel_init_rtc,
.init_pci = marvel_init_pci,
.kill_arch = marvel_kill_arch,
.pci_map_irq = marvel_map_irq,
.pci_swizzle = common_swizzle,
.pa_to_nid = marvel_pa_to_nid,
.cpuid_to_nid = marvel_cpuid_to_nid,
.node_mem_start = marvel_node_mem_start,
.node_mem_size = marvel_node_mem_size,
};
ALIAS_MV(marvel_ev7)
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
* *
* Code supporting TITAN systems (EV6+TITAN), currently: * Code supporting TITAN systems (EV6+TITAN), currently:
* Privateer * Privateer
* Falcon
* Granite
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -34,12 +36,26 @@ ...@@ -34,12 +36,26 @@
#include "irq_impl.h" #include "irq_impl.h"
#include "pci_impl.h" #include "pci_impl.h"
#include "machvec_impl.h" #include "machvec_impl.h"
#include "err_impl.h"
/* Note mask bit is true for ENABLED irqs. */
static unsigned long cached_irq_mask; /*
/* Titan boards handle at most four CPUs. */ * Titan generic
static unsigned long cpu_irq_affinity[4] = { ~0UL, ~0UL, ~0UL, ~0UL }; */
/*
* Titan supports up to 4 CPUs
*/
static unsigned long titan_cpu_irq_affinity[4] = { ~0UL, ~0UL, ~0UL, ~0UL };
/*
* Mask is set (1) if enabled
*/
static unsigned long titan_cached_irq_mask;
/*
* Need SMP-safe access to interrupt CSRs
*/
spinlock_t titan_irq_lock = SPIN_LOCK_UNLOCKED; spinlock_t titan_irq_lock = SPIN_LOCK_UNLOCKED;
static void static void
...@@ -55,10 +71,10 @@ titan_update_irq_hw(unsigned long mask) ...@@ -55,10 +71,10 @@ titan_update_irq_hw(unsigned long mask)
unsigned long mask0, mask1, mask2, mask3, dummy; unsigned long mask0, mask1, mask2, mask3, dummy;
mask &= ~isa_enable; mask &= ~isa_enable;
mask0 = mask & cpu_irq_affinity[0]; mask0 = mask & titan_cpu_irq_affinity[0];
mask1 = mask & cpu_irq_affinity[1]; mask1 = mask & titan_cpu_irq_affinity[1];
mask2 = mask & cpu_irq_affinity[2]; mask2 = mask & titan_cpu_irq_affinity[2];
mask3 = mask & cpu_irq_affinity[3]; mask3 = mask & titan_cpu_irq_affinity[3];
if (bcpu == 0) mask0 |= isa_enable; if (bcpu == 0) mask0 |= isa_enable;
else if (bcpu == 1) mask1 |= isa_enable; else if (bcpu == 1) mask1 |= isa_enable;
...@@ -97,79 +113,68 @@ titan_update_irq_hw(unsigned long mask) ...@@ -97,79 +113,68 @@ titan_update_irq_hw(unsigned long mask)
} }
static inline void static inline void
privateer_enable_irq(unsigned int irq) titan_enable_irq(unsigned int irq)
{ {
spin_lock(&titan_irq_lock); spin_lock(&titan_irq_lock);
cached_irq_mask |= 1UL << (irq - 16); titan_cached_irq_mask |= 1UL << (irq - 16);
titan_update_irq_hw(cached_irq_mask); titan_update_irq_hw(titan_cached_irq_mask);
spin_unlock(&titan_irq_lock); spin_unlock(&titan_irq_lock);
} }
static inline void static inline void
privateer_disable_irq(unsigned int irq) titan_disable_irq(unsigned int irq)
{ {
spin_lock(&titan_irq_lock); spin_lock(&titan_irq_lock);
cached_irq_mask &= ~(1UL << (irq - 16)); titan_cached_irq_mask &= ~(1UL << (irq - 16));
titan_update_irq_hw(cached_irq_mask); titan_update_irq_hw(titan_cached_irq_mask);
spin_unlock(&titan_irq_lock); spin_unlock(&titan_irq_lock);
} }
static unsigned int static unsigned int
privateer_startup_irq(unsigned int irq) titan_startup_irq(unsigned int irq)
{ {
privateer_enable_irq(irq); titan_enable_irq(irq);
return 0; /* never anything pending */ return 0; /* never anything pending */
} }
static void static void
privateer_end_irq(unsigned int irq) titan_end_irq(unsigned int irq)
{ {
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
privateer_enable_irq(irq); titan_enable_irq(irq);
} }
static void static void
cpu_set_irq_affinity(unsigned int irq, unsigned long affinity) titan_cpu_set_irq_affinity(unsigned int irq, unsigned long affinity)
{ {
int cpu; int cpu;
for (cpu = 0; cpu < 4; cpu++) { for (cpu = 0; cpu < 4; cpu++) {
if (affinity & (1UL << cpu)) if (affinity & (1UL << cpu))
cpu_irq_affinity[cpu] |= 1UL << irq; titan_cpu_irq_affinity[cpu] |= 1UL << irq;
else else
cpu_irq_affinity[cpu] &= ~(1UL << irq); titan_cpu_irq_affinity[cpu] &= ~(1UL << irq);
} }
} }
static void static void
privateer_set_affinity(unsigned int irq, unsigned long affinity) titan_set_irq_affinity(unsigned int irq, unsigned long affinity)
{ {
spin_lock(&titan_irq_lock); spin_lock(&titan_irq_lock);
cpu_set_irq_affinity(irq - 16, affinity); titan_cpu_set_irq_affinity(irq - 16, affinity);
titan_update_irq_hw(cached_irq_mask); titan_update_irq_hw(titan_cached_irq_mask);
spin_unlock(&titan_irq_lock); spin_unlock(&titan_irq_lock);
} }
static struct hw_interrupt_type privateer_irq_type = {
.typename = "PRIVATEER",
.startup = privateer_startup_irq,
.shutdown = privateer_disable_irq,
.enable = privateer_enable_irq,
.disable = privateer_disable_irq,
.ack = privateer_disable_irq,
.end = privateer_end_irq,
.set_affinity = privateer_set_affinity,
};
static void static void
privateer_device_interrupt(unsigned long vector, struct pt_regs * regs) titan_device_interrupt(unsigned long vector, struct pt_regs * regs)
{ {
printk("privateer_device_interrupt: NOT IMPLEMENTED YET!! \n"); printk("titan_device_interrupt: NOT IMPLEMENTED YET!! \n");
} }
static void static void
privateer_srm_device_interrupt(unsigned long vector, struct pt_regs * regs) titan_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
{ {
int irq; int irq;
...@@ -182,186 +187,209 @@ static void __init ...@@ -182,186 +187,209 @@ static void __init
init_titan_irqs(struct hw_interrupt_type * ops, int imin, int imax) init_titan_irqs(struct hw_interrupt_type * ops, int imin, int imax)
{ {
long i; long i;
for(i = imin; i <= imax; ++i) { for (i = imin; i <= imax; ++i) {
irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL; irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
irq_desc[i].handler = ops; irq_desc[i].handler = ops;
} }
} }
static struct hw_interrupt_type titan_irq_type = {
.typename = "TITAN",
.startup = titan_startup_irq,
.shutdown = titan_disable_irq,
.enable = titan_enable_irq,
.disable = titan_disable_irq,
.ack = titan_disable_irq,
.end = titan_end_irq,
.set_affinity = titan_set_irq_affinity,
};
static void
titan_intr_nop(int irq, void *dev_id, struct pt_regs *regs)
{
/*
* This is a NOP interrupt handler for the purposes of
* event counting -- just return.
*/
}
static void __init
titan_init_irq(void)
{
if (alpha_using_srm && !alpha_mv.device_interrupt)
alpha_mv.device_interrupt = titan_srm_device_interrupt;
if (!alpha_mv.device_interrupt)
alpha_mv.device_interrupt = titan_device_interrupt;
titan_update_irq_hw(0);
init_titan_irqs(&titan_irq_type, 16, 63 + 16);
}
static void __init static void __init
privateer_init_irq(void) titan_legacy_init_irq(void)
{ {
/* init the legacy dma controller */
outb(0, DMA1_RESET_REG); outb(0, DMA1_RESET_REG);
outb(0, DMA2_RESET_REG); outb(0, DMA2_RESET_REG);
outb(DMA_MODE_CASCADE, DMA2_MODE_REG); outb(DMA_MODE_CASCADE, DMA2_MODE_REG);
outb(0, DMA2_MASK_REG); outb(0, DMA2_MASK_REG);
if (alpha_using_srm) /* init the legacy irq controller */
alpha_mv.device_interrupt = privateer_srm_device_interrupt; init_i8259a_irqs();
titan_update_irq_hw(0UL); /* init the titan irqs */
titan_init_irq();
}
init_i8259a_irqs(); void
init_titan_irqs(&privateer_irq_type, 16, 63 + 16); titan_dispatch_irqs(u64 mask, struct pt_regs *regs)
{
unsigned long vector;
/*
* Mask down to those interrupts which are enable on this processor
*/
mask &= titan_cpu_irq_affinity[smp_processor_id()];
/*
* Dispatch all requested interrupts
*/
while (mask) {
/* convert to SRM vector... priority is <63> -> <0> */
__asm__("ctlz %1, %0" : "=r"(vector) : "r"(mask));
vector = 63 - vector;
mask &= ~(1UL << vector); /* clear it out */
vector = 0x900 + (vector << 4); /* convert to SRM vector */
/* dispatch it */
alpha_mv.device_interrupt(vector, regs);
}
} }
/* /*
* Privateer PCI Fixup configuration. * Titan Family
*
* PCHIP 0 BUS 0 (Hose 0)
*
* IDSEL Dev What
* ----- --- ----
* 18 7 Embedded Southbridge
* 19 8 Slot 0
* 20 9 Slot 1
* 21 10 Slot 2
* 22 11 Slot 3
* 23 12 Embedded HotPlug controller
* 27 16 Embedded Southbridge IDE
* 29 18 Embedded Southbridge PMU
* 31 20 Embedded Southbridge USB
*
* PCHIP 1 BUS 0 (Hose 1)
*
* IDSEL Dev What
* ----- --- ----
* 12 1 Slot 0
* 13 2 Slot 1
* 17 6 Embedded hotPlug controller
*
* PCHIP 0 BUS 1 (Hose 2)
*
* IDSEL What
* ----- ----
* NONE AGP
*
* PCHIP 1 BUS 1 (Hose 3)
*
* IDSEL Dev What
* ----- --- ----
* 12 1 Slot 0
* 13 2 Slot 1
* 17 6 Embedded hotPlug controller
*
* Summary @ TITAN_CSR_DIM0:
* Bit Meaning
* 0-7 Unused
* 8 PCHIP 0 BUS 1 YUKON (if present)
* 9 PCHIP 1 BUS 1 YUKON
* 10 PCHIP 1 BUS 0 YUKON
* 11 PCHIP 0 BUS 0 YUKON
* 12 PCHIP 0 BUS 0 SLOT 2 INT A
* 13 PCHIP 0 BUS 0 SLOT 2 INT B
* 14 PCHIP 0 BUS 0 SLOT 2 INT C
* 15 PCHIP 0 BUS 0 SLOT 2 INT D
* 16 PCHIP 0 BUS 0 SLOT 3 INT A
* 17 PCHIP 0 BUS 0 SLOT 3 INT B
* 18 PCHIP 0 BUS 0 SLOT 3 INT C
* 19 PCHIP 0 BUS 0 SLOT 3 INT D
* 20 PCHIP 0 BUS 0 SLOT 0 INT A
* 21 PCHIP 0 BUS 0 SLOT 0 INT B
* 22 PCHIP 0 BUS 0 SLOT 0 INT C
* 23 PCHIP 0 BUS 0 SLOT 0 INT D
* 24 PCHIP 0 BUS 0 SLOT 1 INT A
* 25 PCHIP 0 BUS 0 SLOT 1 INT B
* 26 PCHIP 0 BUS 0 SLOT 1 INT C
* 27 PCHIP 0 BUS 0 SLOT 1 INT D
* 28 PCHIP 1 BUS 0 SLOT 0 INT A
* 29 PCHIP 1 BUS 0 SLOT 0 INT B
* 30 PCHIP 1 BUS 0 SLOT 0 INT C
* 31 PCHIP 1 BUS 0 SLOT 0 INT D
* 32 PCHIP 1 BUS 0 SLOT 1 INT A
* 33 PCHIP 1 BUS 0 SLOT 1 INT B
* 34 PCHIP 1 BUS 0 SLOT 1 INT C
* 35 PCHIP 1 BUS 0 SLOT 1 INT D
* 36 PCHIP 1 BUS 1 SLOT 0 INT A
* 37 PCHIP 1 BUS 1 SLOT 0 INT B
* 38 PCHIP 1 BUS 1 SLOT 0 INT C
* 39 PCHIP 1 BUS 1 SLOT 0 INT D
* 40 PCHIP 1 BUS 1 SLOT 1 INT A
* 41 PCHIP 1 BUS 1 SLOT 1 INT B
* 42 PCHIP 1 BUS 1 SLOT 1 INT C
* 43 PCHIP 1 BUS 1 SLOT 1 INT D
* 44 AGP INT A
* 45 AGP INT B
* 46-47 Unused
* 49 Reserved for Sleep mode
* 50 Temperature Warning (optional)
* 51 Power Warning (optional)
* 52 Reserved
* 53 South Bridge NMI
* 54 South Bridge SMI INT
* 55 South Bridge ISA Interrupt
* 56-58 Unused
* 59 PCHIP1_C_ERROR
* 60 PCHIP0_C_ERROR
* 61 PCHIP1_H_ERROR
* 62 PCHIP0_H_ERROR
* 63 Reserved
*
*/ */
static int __init static void __init
privateer_map_irq(struct pci_dev *dev, u8 slot, u8 pin) titan_late_init(void)
{ {
u8 irq; /*
* Enable the system error interrupts. These interrupts are
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); * all reported to the kernel as machine checks, so the handler
* is a nop so it can be called to count the individual events.
*/
request_irq(63+16, titan_intr_nop, SA_INTERRUPT,
"CChip Error", NULL);
request_irq(62+16, titan_intr_nop, SA_INTERRUPT,
"PChip 0 H_Error", NULL);
request_irq(61+16, titan_intr_nop, SA_INTERRUPT,
"PChip 1 H_Error", NULL);
request_irq(60+16, titan_intr_nop, SA_INTERRUPT,
"PChip 0 C_Error", NULL);
request_irq(59+16, titan_intr_nop, SA_INTERRUPT,
"PChip 1 C_Error", NULL);
/*
* Register our error handlers.
*/
titan_register_error_handlers();
/* is it routed through ISA? */ /*
if ((irq & 0xF0) == 0xE0) * Check if the console left us any error logs.
return (int)irq; */
cdl_check_console_data_log();
return (int)irq + 16; /* HACK -- this better only be called once */
} }
#ifdef CONFIG_VGA_HOSE static int __devinit
static struct pci_controller * __init titan_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
privateer_vga_hose_select(struct pci_controller *h1, struct pci_controller *h2)
{ {
struct pci_controller *hose = h1; u8 intline;
int agp1, agp2; int irq;
/* which hose(s) are agp? */ /* Get the current intline. */
agp1 = (0 != (TITAN_agp & (1 << h1->index))); pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &intline);
agp2 = (0 != (TITAN_agp & (1 << h2->index))); irq = intline;
hose = h1; /* default to h1 */ /* Is it explicitly routed through ISA? */
if (agp1 ^ agp2) { if ((irq & 0xF0) == 0xE0)
if (agp2) hose = h2; /* take agp if only one */ return irq;
} else if (h2->index < h1->index)
hose = h2; /* first hose if 2xpci or 2xagp */
return hose; /* Offset by 16 to make room for ISA interrupts 0 - 15. */
return irq + 16;
} }
#endif
static void __init static void __init
privateer_init_pci(void) titan_init_pci(void)
{ {
/*
* This isn't really the right place, but there's some init
* that needs to be done after everything is basically up.
*/
titan_late_init();
pci_probe_only = 1;
common_init_pci(); common_init_pci();
SMC669_Init(0); SMC669_Init(0);
#ifdef CONFIG_VGA_HOSE #ifdef CONFIG_VGA_HOSE
locate_and_init_vga(privateer_vga_hose_select); locate_and_init_vga(NULL);
#endif #endif
} }
void
privateer_machine_check(unsigned long vector, unsigned long la_ptr, /*
struct pt_regs * regs) * Privateer
*/
static void __init
privateer_init_pci(void)
{ {
/* only handle system events here */ /*
if (vector != SCB_Q_SYSEVENT) * Hook a couple of extra err interrupts that the
return titan_machine_check(vector, la_ptr, regs); * common titan code won't.
*/
request_irq(53+16, titan_intr_nop, SA_INTERRUPT,
"NMI", NULL);
request_irq(50+16, titan_intr_nop, SA_INTERRUPT,
"Temperature Warning", NULL);
/* it's a system event, handle it here */ /*
printk("PRIVATEER 680 Machine Check on CPU %d\n", smp_processor_id()); * Finish with the common version.
*/
return titan_init_pci();
} }
/* /*
* The System Vectors * The System Vectors.
*/ */
struct alpha_machine_vector titan_mv __initmv = {
.vector_name = "TITAN",
DO_EV6_MMU,
DO_DEFAULT_RTC,
DO_TITAN_IO,
DO_TITAN_BUS,
.machine_check = titan_machine_check,
.max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
.min_io_address = DEFAULT_IO_BASE,
.min_mem_address = DEFAULT_MEM_BASE,
.pci_dac_offset = TITAN_DAC_OFFSET,
.nr_irqs = 80, /* 64 + 16 */
/* device_interrupt will be filled in by titan_init_irq */
.agp_info = titan_agp_info,
.init_arch = titan_init_arch,
.init_irq = titan_legacy_init_irq,
.init_rtc = common_init_rtc,
.init_pci = titan_init_pci,
.kill_arch = titan_kill_arch,
.pci_map_irq = titan_map_irq,
.pci_swizzle = common_swizzle,
};
ALIAS_MV(titan)
struct alpha_machine_vector privateer_mv __initmv = { struct alpha_machine_vector privateer_mv __initmv = {
.vector_name = "PRIVATEER", .vector_name = "PRIVATEER",
...@@ -376,14 +404,18 @@ struct alpha_machine_vector privateer_mv __initmv = { ...@@ -376,14 +404,18 @@ struct alpha_machine_vector privateer_mv __initmv = {
.pci_dac_offset = TITAN_DAC_OFFSET, .pci_dac_offset = TITAN_DAC_OFFSET,
.nr_irqs = 80, /* 64 + 16 */ .nr_irqs = 80, /* 64 + 16 */
.device_interrupt = privateer_device_interrupt, /* device_interrupt will be filled in by titan_init_irq */
.agp_info = titan_agp_info,
.init_arch = titan_init_arch, .init_arch = titan_init_arch,
.init_irq = privateer_init_irq, .init_irq = titan_legacy_init_irq,
.init_rtc = common_init_rtc, .init_rtc = common_init_rtc,
.init_pci = privateer_init_pci, .init_pci = privateer_init_pci,
.kill_arch = titan_kill_arch, .kill_arch = titan_kill_arch,
.pci_map_irq = privateer_map_irq, .pci_map_irq = titan_map_irq,
.pci_swizzle = common_swizzle, .pci_swizzle = common_swizzle,
}; };
ALIAS_MV(privateer) /* No alpha_mv alias for privateer since we compile it
in unconditionally with titan; setup_arch knows how to cope. */
...@@ -118,7 +118,7 @@ dik_show_trace(unsigned long *sp) ...@@ -118,7 +118,7 @@ dik_show_trace(unsigned long *sp)
long i = 0; long i = 0;
printk("Trace:"); printk("Trace:");
while (0x1ff8 & (unsigned long) sp) { while (0x1ff8 & (unsigned long) sp) {
extern unsigned long _stext, _etext; extern char _stext[], _etext[];
unsigned long tmp = *sp; unsigned long tmp = *sp;
sp++; sp++;
if (tmp < (unsigned long) &_stext) if (tmp < (unsigned long) &_stext)
......
...@@ -2,6 +2,6 @@ ...@@ -2,6 +2,6 @@
# Makefile for the linux alpha-specific parts of the memory manager. # Makefile for the linux alpha-specific parts of the memory manager.
# #
obj-y := init.o fault.o extable.o obj-y := init.o fault.o extable.o remap.o
obj-$(CONFIG_DISCONTIGMEM) += numa.o obj-$(CONFIG_DISCONTIGMEM) += numa.o
#include <linux/vmalloc.h>
#include <asm/pgalloc.h>
#include <asm/cacheflush.h>
/* called with the page_table_lock held */
static inline void
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("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));
}
/* called with the page_table_lock held */
static inline int
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;
remap_area_pte(pte, address, end - address,
address + phys_addr, flags);
address = (address + PMD_SIZE) & PMD_MASK;
pmd++;
} while (address && (address < end));
return 0;
}
int
__alpha_remap_area_pages(unsigned long address, unsigned long phys_addr,
unsigned long size, unsigned long flags)
{
pgd_t * dir;
int error = 0;
unsigned long end = address + size;
phys_addr -= address;
dir = pgd_offset(&init_mm, address);
flush_cache_all();
if (address >= end)
BUG();
spin_lock(&init_mm.page_table_lock);
do {
pmd_t *pmd;
pmd = pmd_alloc(&init_mm, dir, address);
error = -ENOMEM;
if (!pmd)
break;
if (remap_area_pmd(pmd, address, end - address,
phys_addr + address, flags))
break;
error = 0;
address = (address + PGDIR_SIZE) & PGDIR_MASK;
dir++;
} while (address && (address < end));
spin_unlock(&init_mm.page_table_lock);
return error;
}
#ifndef AGP_H #ifndef AGP_H
#define AGP_H 1 #define AGP_H 1
#include <asm/io.h>
/* dummy for now */ /* dummy for now */
#define map_page_into_agp(page) #define map_page_into_agp(page)
......
#ifndef _ALPHA_AGP_BACKEND_H
#define _ALPHA_AGP_BACKEND_H 1
typedef union _alpha_agp_mode {
struct {
u32 rate : 3;
u32 reserved0 : 1;
u32 fw : 1;
u32 fourgb : 1;
u32 reserved1 : 2;
u32 enable : 1;
u32 sba : 1;
u32 reserved2 : 14;
u32 rq : 8;
} bits;
u32 lw;
} alpha_agp_mode;
typedef struct _alpha_agp_info {
enum chipset_type type;
struct pci_controller *hose;
struct {
dma_addr_t bus_base;
unsigned long size;
void *sysdata;
} aperture;
alpha_agp_mode capability;
alpha_agp_mode mode;
void *private;
struct alpha_agp_ops *ops;
} alpha_agp_info;
struct alpha_agp_ops {
int (*setup)(alpha_agp_info *);
void (*cleanup)(alpha_agp_info *);
int (*configure)(alpha_agp_info *);
int (*bind)(alpha_agp_info *, off_t, agp_memory *);
int (*unbind)(alpha_agp_info *, off_t, agp_memory *);
unsigned long (*translate)(alpha_agp_info *, dma_addr_t);
};
#endif /* _ALPHA_AGP_BACKEND_H */
/*
* Marvel systems use the IO7 I/O chip provides PCI/PCIX/AGP access
*
* This file is based on:
*
* Marvel / EV7 System Programmer's Manual
* Revision 1.00
* 14 May 2001
*/
#ifndef __ALPHA_MARVEL__H__
#define __ALPHA_MARVEL__H__
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/spinlock.h>
#include <asm/compiler.h>
#define MARVEL_MAX_PIDS 128
#define MARVEL_MAX_LSIS_PER_PID 256
#define MARVEL_NR_IRQS (MARVEL_MAX_PIDS * MARVEL_MAX_LSIS_PER_PID)
/*
* EV7 RBOX Registers
*/
typedef struct {
volatile unsigned long csr __attribute__((aligned(16)));
} ev7_csr;
typedef struct {
ev7_csr RBOX_CFG; /* 0x0000 */
ev7_csr RBOX_NSVC;
ev7_csr RBOX_EWVC;
ev7_csr RBOX_WHAMI;
ev7_csr RBOX_TCTL; /* 0x0040 */
ev7_csr RBOX_INT;
ev7_csr RBOX_IMASK;
ev7_csr RBOX_IREQ;
ev7_csr RBOX_INTQ; /* 0x0080 */
ev7_csr RBOX_INTA;
ev7_csr RBOX_IT;
ev7_csr RBOX_SCRATCH1;
ev7_csr RBOX_SCRATCH2; /* 0x00c0 */
ev7_csr RBOX_L_ERR;
} ev7_csrs;
/*
* EV7 CSR addressing macros
*/
#define EV7_MASK40(addr) ((addr) & ((1UL << 41) - 1))
#define EV7_KERN_ADDR(addr) ((void *)(IDENT_ADDR | EV7_MASK40(addr)))
#define EV7_PE_MASK 0x1ffUL /* 9 bits ( 256 + mem/io ) */
#define EV7_IPE(pe) ((~((long)(pe)) & EV7_PE_MASK) << 35)
#define EV7_CSR_PHYS(pe, off) (EV7_IPE(pe) | (0x7FFCUL << 20) | (off))
#define EV7_CSRS_PHYS(pe) (EV7_CSR_PHYS(pe, 0UL))
#define EV7_CSR_KERN(pe, off) (EV7_KERN_ADDR(EV7_CSR_PHYS(pe, off)))
#define EV7_CSRS_KERN(pe) (EV7_KERN_ADDR(EV7_CSRS_PHYS(pe)))
#define EV7_CSR_OFFSET(name) ((unsigned long)&((ev7_csrs *)NULL)->name.csr)
/*
* IO7 registers
*/
typedef struct {
volatile unsigned long csr __attribute__((aligned(64)));
} io7_csr;
typedef struct {
/* I/O Port Control Registers */
io7_csr POx_CTRL; /* 0x0000 */
io7_csr POx_CACHE_CTL;
io7_csr POx_TIMER;
io7_csr POx_IO_ADR_EXT;
io7_csr POx_MEM_ADR_EXT; /* 0x0100 */
io7_csr POx_XCAL_CTRL;
io7_csr rsvd1[2]; /* ?? spec doesn't show 0x180 */
io7_csr POx_DM_SOURCE; /* ox0200 */
io7_csr POx_DM_DEST;
io7_csr POx_DM_SIZE;
io7_csr POx_DM_STATE;
io7_csr rsvd2[4]; /* 0x0300 */
/* AGP Control Registers -- port 3 only */
io7_csr AGP_CAP_ID; /* 0x0400 */
io7_csr AGP_STAT;
io7_csr AGP_CMD;
io7_csr rsvd3;
/* I/O Port Monitor Registers */
io7_csr POx_MONCTL; /* 0x0500 */
io7_csr POx_CTRA;
io7_csr POx_CTRB;
io7_csr POx_CTR56;
io7_csr POx_SCRATCH; /* 0x0600 */
io7_csr POx_XTRA_A;
io7_csr POx_XTRA_TS;
io7_csr POx_XTRA_Z;
io7_csr rsvd4; /* 0x0700 */
io7_csr POx_THRESHA;
io7_csr POx_THRESHB;
io7_csr rsvd5[33];
/* System Address Space Window Control Registers */
io7_csr POx_WBASE[4]; /* 0x1000 */
io7_csr POx_WMASK[4];
io7_csr POx_TBASE[4];
io7_csr POx_SG_TBIA;
io7_csr POx_MSI_WBASE;
io7_csr rsvd6[50];
/* I/O Port Error Registers */
io7_csr POx_ERR_SUM;
io7_csr POx_FIRST_ERR;
io7_csr POx_MSK_HEI;
io7_csr POx_TLB_ERR;
io7_csr POx_SPL_COMPLT;
io7_csr POx_TRANS_SUM;
io7_csr POx_FRC_PCI_ERR;
io7_csr POx_MULT_ERR;
io7_csr rsvd7[8];
/* I/O Port End of Interrupt Registers */
io7_csr EOI_DAT;
io7_csr rsvd8[7];
io7_csr POx_IACK_SPECIAL;
io7_csr rsvd9[103];
} io7_ioport_csrs;
typedef struct {
io7_csr IO_ASIC_REV; /* 0x30.0000 */
io7_csr IO_SYS_REV;
io7_csr SER_CHAIN3;
io7_csr PO7_RST1;
io7_csr PO7_RST2; /* 0x30.0100 */
io7_csr POx_RST[4];
io7_csr IO7_DWNH;
io7_csr IO7_MAF;
io7_csr IO7_MAF_TO;
io7_csr IO7_ACC_CLUMP; /* 0x30.0300 */
io7_csr IO7_PMASK;
io7_csr IO7_IOMASK;
io7_csr IO7_UPH;
io7_csr IO7_UPH_TO; /* 0x30.0400 */
io7_csr RBX_IREQ_OFF;
io7_csr RBX_INTA_OFF;
io7_csr INT_RTY;
io7_csr PO7_MONCTL; /* 0x30.0500 */
io7_csr PO7_CTRA;
io7_csr PO7_CTRB;
io7_csr PO7_CTR56;
io7_csr PO7_SCRATCH; /* 0x30.0600 */
io7_csr PO7_XTRA_A;
io7_csr PO7_XTRA_TS;
io7_csr PO7_XTRA_Z;
io7_csr PO7_PMASK; /* 0x30.0700 */
io7_csr PO7_THRESHA;
io7_csr PO7_THRESHB;
io7_csr rsvd1[97];
io7_csr PO7_ERROR_SUM; /* 0x30.2000 */
io7_csr PO7_BHOLE_MASK;
io7_csr PO7_HEI_MSK;
io7_csr PO7_CRD_MSK;
io7_csr PO7_UNCRR_SYM; /* 0x30.2100 */
io7_csr PO7_CRRCT_SYM;
io7_csr PO7_ERR_PKT[2];
io7_csr PO7_UGBGE_SYM; /* 0x30.2200 */
io7_csr rsbv2[887];
io7_csr PO7_LSI_CTL[128]; /* 0x31.0000 */
io7_csr rsvd3[123];
io7_csr HLT_CTL; /* 0x31.3ec0 */
io7_csr HPI_CTL; /* 0x31.3f00 */
io7_csr CRD_CTL;
io7_csr STV_CTL;
io7_csr HEI_CTL;
io7_csr PO7_MSI_CTL[16]; /* 0x31.4000 */
io7_csr rsvd4[240];
/*
* Interrupt Diagnostic / Test
*/
struct {
io7_csr INT_PND;
io7_csr INT_CLR;
io7_csr INT_EOI;
io7_csr rsvd[29];
} INT_DIAG[4];
io7_csr rsvd5[125]; /* 0x31.a000 */
io7_csr MISC_PND; /* 0x31.b800 */
io7_csr rsvd6[31];
io7_csr MSI_PND[16]; /* 0x31.c000 */
io7_csr rsvd7[16];
io7_csr MSI_CLR[16]; /* 0x31.c800 */
} io7_port7_csrs;
/*
* IO7 DMA Window Base register (POx_WBASEx)
*/
#define wbase_m_ena 0x1
#define wbase_m_sg 0x2
#define wbase_m_dac 0x4
#define wbase_m_addr 0xFFF00000
union IO7_POx_WBASE {
struct {
unsigned ena : 1; /* <0> */
unsigned sg : 1; /* <1> */
unsigned dac : 1; /* <2> -- window 3 only */
unsigned rsvd1 : 17;
unsigned addr : 12; /* <31:20> */
unsigned rsvd2 : 32;
} bits;
unsigned as_long[2];
unsigned as_quad;
};
/*
* IO7 IID (Interrupt IDentifier) format
*
* For level-sensative interupts, int_num is encoded as:
*
* bus/port slot/device INTx
* <7:5> <4:2> <1:0>
*/
union IO7_IID {
struct {
unsigned int_num : 9; /* <8:0> */
unsigned tpu_mask : 4; /* <12:9> rsvd */
unsigned msi : 1; /* 13 */
unsigned ipe : 10; /* <23:14> */
unsigned long rsvd : 40;
} bits;
unsigned int as_long[2];
unsigned long as_quad;
};
/*
* IO7 addressing macros
*/
#define IO7_KERN_ADDR(addr) (EV7_KERN_ADDR(addr))
#define IO7_PORT_MASK 0x07UL /* 3 bits of port */
#define IO7_IPE(pe) (EV7_IPE(pe))
#define IO7_IPORT(port) ((~((long)(port)) & IO7_PORT_MASK) << 32)
#define IO7_HOSE(pe, port) (IO7_IPE(pe) | IO7_IPORT(port))
#define IO7_MEM_PHYS(pe, port) (IO7_HOSE(pe, port) | 0x00000000UL)
#define IO7_CONF_PHYS(pe, port) (IO7_HOSE(pe, port) | 0xFE000000UL)
#define IO7_IO_PHYS(pe, port) (IO7_HOSE(pe, port) | 0xFF000000UL)
#define IO7_CSR_PHYS(pe, port, off) \
(IO7_HOSE(pe, port) | 0xFF800000UL | (off))
#define IO7_CSRS_PHYS(pe, port) (IO7_CSR_PHYS(pe, port, 0UL))
#define IO7_PORT7_CSRS_PHYS(pe) (IO7_CSR_PHYS(pe, 7, 0x300000UL))
#define IO7_MEM_KERN(pe, port) (IO7_KERN_ADDR(IO7_MEM_PHYS(pe, port)))
#define IO7_CONF_KERN(pe, port) (IO7_KERN_ADDR(IO7_CONF_PHYS(pe, port)))
#define IO7_IO_KERN(pe, port) (IO7_KERN_ADDR(IO7_IO_PHYS(pe, port)))
#define IO7_CSR_KERN(pe, port, off) (IO7_KERN_ADDR(IO7_CSR_PHYS(pe,port,off)))
#define IO7_CSRS_KERN(pe, port) (IO7_KERN_ADDR(IO7_CSRS_PHYS(pe, port)))
#define IO7_PORT7_CSRS_KERN(pe) (IO7_KERN_ADDR(IO7_PORT7_CSRS_PHYS(pe)))
#define IO7_PLL_RNGA(pll) (((pll) >> 3) & 0x7)
#define IO7_PLL_RNGB(pll) (((pll) >> 6) & 0x7)
#define IO7_MEM_SPACE (2UL * 1024 * 1024 * 1024) /* 2GB MEM */
#define IO7_IO_SPACE (8UL * 1024 * 1024) /* 8MB I/O */
/*
* Offset between ram physical addresses and pci64 DAC addresses
*/
#define IO7_DAC_OFFSET (1UL << 49)
/*
* This is needed to satisify the IO() macro used in initializing the machvec
*/
#define MARVEL_IACK_SC \
((unsigned long) \
(&(((io7_ioport_csrs *)IO7_CSRS_KERN(0, 0))->POx_IACK_SPECIAL)))
#ifdef __KERNEL__
/*
* IO7 structs
*/
#define IO7_NUM_PORTS 4
#define IO7_AGP_PORT 3
struct io7_port {
struct io7 *io7;
struct pci_controller *hose;
int enabled;
unsigned int port;
io7_ioport_csrs *csrs;
unsigned long saved_wbase[4];
unsigned long saved_wmask[4];
unsigned long saved_tbase[4];
};
struct io7 {
struct io7 *next;
unsigned int pe;
io7_port7_csrs *csrs;
struct io7_port ports[IO7_NUM_PORTS];
spinlock_t irq_lock;
};
#ifndef __EXTERN_INLINE
# define __EXTERN_INLINE extern inline
# define __IO_EXTERN_INLINE
#endif
/*
* I/O functions. All access through linear space.
*/
#define vucp volatile unsigned char *
#define vusp volatile unsigned short *
#define vuip volatile unsigned int *
#define vulp volatile unsigned long *
#ifdef CONFIG_VGA_HOSE
extern struct pci_controller *pci_vga_hose;
# define __marvel_is_port_vga(a) \
(((a) >= 0x3b0) && ((a) < 0x3e0) && ((a) != 0x3b3) && ((a) != 0x3d3))
# define __marvel_is_mem_vga(a) (((a) >= 0xa0000) && ((a) <= 0xc0000))
# define FIXUP_IOADDR_VGA(a) do { \
if (pci_vga_hose && __marvel_is_port_vga(a)) \
a += pci_vga_hose->io_space->start; \
} while(0)
#else
# define FIXUP_IOADDR_VGA(a)
#endif
#define __marvel_is_port_kbd(a) (((a) == 0x60) || ((a) == 0x64))
#define __marvel_is_port_rtc(a) (((a) == 0x70) || ((a) == 0x71))
#define FIXUP_IOADDR_LEGACY(a)
#define FIXUP_IOADDR(a) do { \
FIXUP_IOADDR_VGA(a); \
FIXUP_IOADDR_LEGACY(a); \
} while(0)
#if 0
# define IOBUG(x) printk x
# define IOBUG_FILTER_IOADDR(a, x) \
if (!__marvel_is_port_kbd(a) && !__marvel_is_port_rtc(a)) IOBUG(x)
#else
# define IOBUG(x)
# define IOBUG_FILTER_IOADDR(a, x)
#endif
extern u8 __marvel_rtc_io(int write, u8 b, unsigned long addr);
#define __marvel_rtc_inb(a) __marvel_rtc_io(0, 0, (a))
#define __marvel_rtc_outb(b, a) __marvel_rtc_io(1, (b), (a))
__EXTERN_INLINE int marvel_is_ioaddr(unsigned long addr)
{
return (addr & (1UL << 40)) != 0; /*FIXME - hardwire*/
}
__EXTERN_INLINE u8 marvel_inb(unsigned long addr)
{
FIXUP_IOADDR(addr);
if (!marvel_is_ioaddr(addr)) {
if (__marvel_is_port_kbd(addr))
return (u8)0;
if (__marvel_is_port_rtc(addr))
return __marvel_rtc_inb(addr);
IOBUG_FILTER_IOADDR(addr,
("Bad IO addr %lx - reading -1\n", addr));
return (u8)-1;
}
return __kernel_ldbu(*(vucp)addr);
}
__EXTERN_INLINE void marvel_outb(u8 b, unsigned long addr)
{
FIXUP_IOADDR(addr);
if (!marvel_is_ioaddr(addr)) {
if (__marvel_is_port_rtc(addr))
return (void)__marvel_rtc_outb(b, addr);
IOBUG_FILTER_IOADDR(addr,
("Bad IO addr %lx - reading -1\n", addr));
return;
}
__kernel_stb(b, *(vucp)addr);
mb();
}
__EXTERN_INLINE u16 marvel_inw(unsigned long addr)
{
FIXUP_IOADDR(addr);
if (!marvel_is_ioaddr(addr)) {
IOBUG_FILTER_IOADDR(addr,
("Bad IO addr %lx - reading -1\n", addr));
return (u16)-1;
}
return __kernel_ldwu(*(vusp)addr);
}
__EXTERN_INLINE void marvel_outw(u16 w, unsigned long addr)
{
FIXUP_IOADDR(addr);
if (!marvel_is_ioaddr(addr)) {
IOBUG_FILTER_IOADDR(addr,
("Bad IO addr %lx - reading -1\n", addr));
return;
}
__kernel_stw(w, *(vusp)addr);
mb();
}
__EXTERN_INLINE u32 marvel_inl(unsigned long addr)
{
FIXUP_IOADDR(addr);
if (!marvel_is_ioaddr(addr)) {
IOBUG_FILTER_IOADDR(addr,
("Bad IO addr %lx - reading -1\n", addr));
return (u32)-1;
}
return *(vuip)addr;
}
__EXTERN_INLINE void marvel_outl(u32 l, unsigned long addr)
{
FIXUP_IOADDR(addr);
if (!marvel_is_ioaddr(addr)) {
IOBUG_FILTER_IOADDR(addr,
("Bad IO addr %lx - reading -1\n", addr));
return;
}
*(vuip)addr = l;
mb();
}
/*
* Memory functions. All accesses through linear space.
*/
extern unsigned long marvel_ioremap(unsigned long addr, unsigned long size);
extern void marvel_iounmap(unsigned long addr);
__EXTERN_INLINE u8 marvel_readb(unsigned long addr)
{
if (!marvel_is_ioaddr(addr)) {
IOBUG(("Bad MEM addr %lx - reading -1\n", addr));
return (u8)-1;
}
return __kernel_ldbu(*(vucp)addr);
}
__EXTERN_INLINE u16 marvel_readw(unsigned long addr)
{
if (!marvel_is_ioaddr(addr)) {
IOBUG(("Bad MEM addr %lx - reading -1\n", addr));
return (u16)-1;
}
return __kernel_ldwu(*(vusp)addr);
}
__EXTERN_INLINE u32 marvel_readl(unsigned long addr)
{
if (!marvel_is_ioaddr(addr)) {
IOBUG(("Bad MEM addr %lx - reading -1\n", addr));
return (u32)-1;
}
return *(vuip)addr;
}
__EXTERN_INLINE u64 marvel_readq(unsigned long addr)
{
if (!marvel_is_ioaddr(addr)) {
IOBUG(("Bad MEM addr %lx - reading -1\n", addr));
return (u64)-1;
}
return *(vulp)addr;
}
__EXTERN_INLINE void marvel_writeb(u8 b, unsigned long addr)
{
if (!marvel_is_ioaddr(addr)) {
IOBUG(("Bad MEM addr %lx - dropping store\n", addr));
return;
}
__kernel_stb(b, *(vucp)addr);
}
__EXTERN_INLINE void marvel_writew(u16 w, unsigned long addr)
{
if (!marvel_is_ioaddr(addr)) {
IOBUG(("Bad MEM addr %lx - dropping store\n", addr));
return;
}
__kernel_stw(w, *(vusp)addr);
}
__EXTERN_INLINE void marvel_writel(u32 l, unsigned long addr)
{
if (!marvel_is_ioaddr(addr)) {
IOBUG(("Bad MEM addr %lx - dropping store\n", addr));
return;
}
*(vuip)addr = l;
}
__EXTERN_INLINE void marvel_writeq(u64 q, unsigned long addr)
{
if (!marvel_is_ioaddr(addr)) {
IOBUG(("Bad MEM addr %lx - dropping store\n", addr));
return;
}
*(vulp)addr = q;
}
#undef FIXUP_IOADDR
#undef FIXUP_IOADDR_LEGACY
#undef FIXUP_IOADDR_VGA
#undef vucp
#undef vusp
#undef vuip
#undef vulp
#ifdef __WANT_IO_DEF
#define __inb(p) marvel_inb((unsigned long)(p))
#define __inw(p) marvel_inw((unsigned long)(p))
#define __inl(p) marvel_inl((unsigned long)(p))
#define __outb(x,p) marvel_outb((x),(unsigned long)(p))
#define __outw(x,p) marvel_outw((x),(unsigned long)(p))
#define __outl(x,p) marvel_outl((x),(unsigned long)(p))
#define __readb(a) marvel_readb((unsigned long)(a))
#define __readw(a) marvel_readw((unsigned long)(a))
#define __readl(a) marvel_readl((unsigned long)(a))
#define __readq(a) marvel_readq((unsigned long)(a))
#define __writeb(x,a) marvel_writeb((x),(unsigned long)(a))
#define __writew(x,a) marvel_writew((x),(unsigned long)(a))
#define __writel(x,a) marvel_writel((x),(unsigned long)(a))
#define __writeq(x,a) marvel_writeq((x),(unsigned long)(a))
#define __ioremap(a,s) marvel_ioremap((unsigned long)(a),(s))
#define __iounmap(a) marvel_iounmap((unsigned long)(a))
#define __is_ioaddr(a) marvel_is_ioaddr((unsigned long)(a))
/* Disable direct inlining of these calls with the debug checks present. */
#if 0
#define __raw_readb(a) __readb(a)
#define __raw_readw(a) __readw(a)
#define __raw_readl(a) __readl(a)
#define __raw_readq(a) __readq(a)
#define __raw_writeb(v,a) __writeb(v,a)
#define __raw_writew(v,a) __writew(v,a)
#define __raw_writel(v,a) __writel(v,a)
#define __raw_writeq(v,a) __writeq(v,a)
#endif
#endif /* __WANT_IO_DEF */
#ifdef __IO_EXTERN_INLINE
# undef __EXTERN_INLINE
# undef __IO_EXTERN_INLINE
#endif
#endif /* __KERNEL__ */
#endif /* __ALPHA_MARVEL__H__ */
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define __ALPHA_TITAN__H__ #define __ALPHA_TITAN__H__
#include <linux/types.h> #include <linux/types.h>
#include <linux/pci.h>
#include <asm/compiler.h> #include <asm/compiler.h>
/* /*
...@@ -293,13 +294,15 @@ union TPAchipAGPERR { ...@@ -293,13 +294,15 @@ union TPAchipAGPERR {
* 2 - pachip 0 / A Port * 2 - pachip 0 / A Port
* 3 - pachip 1 / A Port * 3 - pachip 1 / A Port
*/ */
#define TITAN_HOSE(h) (((unsigned long)(h)) << 33) #define TITAN_HOSE_SHIFT (33)
#define TITAN_HOSE(h) (((unsigned long)(h)) << TITAN_HOSE_SHIFT)
#define TITAN_BASE (IDENT_ADDR + TI_BIAS) #define TITAN_BASE (IDENT_ADDR + TI_BIAS)
#define TITAN_MEM(h) (TITAN_BASE+TITAN_HOSE(h)+0x000000000UL) #define TITAN_MEM(h) (TITAN_BASE+TITAN_HOSE(h)+0x000000000UL)
#define _TITAN_IACK_SC(h) (TITAN_BASE+TITAN_HOSE(h)+0x1F8000000UL) #define _TITAN_IACK_SC(h) (TITAN_BASE+TITAN_HOSE(h)+0x1F8000000UL)
#define TITAN_IO(h) (TITAN_BASE+TITAN_HOSE(h)+0x1FC000000UL) #define TITAN_IO(h) (TITAN_BASE+TITAN_HOSE(h)+0x1FC000000UL)
#define TITAN_CONF(h) (TITAN_BASE+TITAN_HOSE(h)+0x1FE000000UL) #define TITAN_CONF(h) (TITAN_BASE+TITAN_HOSE(h)+0x1FE000000UL)
#define TITAN_HOSE_MASK TITAN_HOSE(3)
#define TITAN_IACK_SC _TITAN_IACK_SC(0) /* hack! */ #define TITAN_IACK_SC _TITAN_IACK_SC(0) /* hack! */
/* /*
...@@ -427,17 +430,8 @@ __EXTERN_INLINE void titan_outl(u32 b, unsigned long addr) ...@@ -427,17 +430,8 @@ __EXTERN_INLINE void titan_outl(u32 b, unsigned long addr)
* Memory functions. all accesses are done through linear space. * Memory functions. all accesses are done through linear space.
*/ */
__EXTERN_INLINE unsigned long titan_ioremap(unsigned long addr, extern unsigned long titan_ioremap(unsigned long addr, unsigned long size);
unsigned long size extern void titan_iounmap(unsigned long addr);
__attribute__((unused)))
{
return addr + TITAN_MEM_BIAS;
}
__EXTERN_INLINE void titan_iounmap(unsigned long addr)
{
return;
}
__EXTERN_INLINE int titan_is_ioaddr(unsigned long addr) __EXTERN_INLINE int titan_is_ioaddr(unsigned long addr)
{ {
......
#ifndef __ALPHA_GCT_H
#define __ALPHA_GCT_H
typedef u64 gct_id;
typedef u64 gct6_handle;
typedef struct __gct6_node {
u8 type;
u8 subtype;
u16 size;
u32 hd_extension;
gct6_handle owner;
gct6_handle active_user;
gct_id id;
u64 flags;
u16 rev;
u16 change_counter;
u16 max_child;
u16 reserved1;
gct6_handle saved_owner;
gct6_handle affinity;
gct6_handle parent;
gct6_handle next;
gct6_handle prev;
gct6_handle child;
u64 fw_flags;
u64 os_usage;
u64 fru_id;
u32 checksum;
u32 magic; /* 'GLXY' */
} gct6_node;
typedef struct {
u8 type;
u8 subtype;
void (*callout)(gct6_node *);
} gct6_search_struct;
#define GCT_NODE_MAGIC 0x59584c47 /* 'GLXY' */
/*
* node types
*/
#define GCT_TYPE_HOSE 0x0E
/*
* node subtypes
*/
#define GCT_SUBTYPE_IO_PORT_MODULE 0x2C
#define GCT_NODE_PTR(off) ((gct6_node *)((char *)hwrpb + \
hwrpb->frut_offset + \
(gct6_handle)(off))) \
int gct6_find_nodes(gct6_node *, gct6_search_struct *);
#endif /* __ALPHA_GCT_H */
...@@ -64,6 +64,7 @@ ...@@ -64,6 +64,7 @@
#define ST_DEC_CUSCO 36 /* CUSCO systype */ #define ST_DEC_CUSCO 36 /* CUSCO systype */
#define ST_DEC_EIGER 37 /* Eiger systype */ #define ST_DEC_EIGER 37 /* Eiger systype */
#define ST_DEC_TITAN 38 /* Titan systype */ #define ST_DEC_TITAN 38 /* Titan systype */
#define ST_DEC_MARVEL 39 /* Marvel systype */
/* UNOFFICIAL!!! */ /* UNOFFICIAL!!! */
#define ST_UNOFFICIAL_BIAS 100 #define ST_UNOFFICIAL_BIAS 100
......
...@@ -190,6 +190,8 @@ extern void _sethae (unsigned long addr); /* cached version */ ...@@ -190,6 +190,8 @@ extern void _sethae (unsigned long addr); /* cached version */
# include <asm/jensen.h> # include <asm/jensen.h>
#elif defined(CONFIG_ALPHA_LCA) #elif defined(CONFIG_ALPHA_LCA)
# include <asm/core_lca.h> # include <asm/core_lca.h>
#elif defined(CONFIG_ALPHA_MARVEL)
# include <asm/core_marvel.h>
#elif defined(CONFIG_ALPHA_MCPCIA) #elif defined(CONFIG_ALPHA_MCPCIA)
# include <asm/core_mcpcia.h> # include <asm/core_mcpcia.h>
#elif defined(CONFIG_ALPHA_POLARIS) #elif defined(CONFIG_ALPHA_POLARIS)
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
many places throughout the kernel to size static arrays. That's ok, many places throughout the kernel to size static arrays. That's ok,
we'll use alpha_mv.nr_irqs when we want the real thing. */ we'll use alpha_mv.nr_irqs when we want the real thing. */
# define NR_IRQS 2048 /* enuff for WILDFIRE with 8 QBBs */ # define NR_IRQS (32768 + 16) /* enough for MARVEL with 128 PIDs */
#elif defined(CONFIG_ALPHA_CABRIOLET) || \ #elif defined(CONFIG_ALPHA_CABRIOLET) || \
defined(CONFIG_ALPHA_EB66P) || \ defined(CONFIG_ALPHA_EB66P) || \
...@@ -56,6 +56,9 @@ ...@@ -56,6 +56,9 @@
#elif defined(CONFIG_ALPHA_WILDFIRE) #elif defined(CONFIG_ALPHA_WILDFIRE)
# define NR_IRQS 2048 /* enuff for 8 QBBs */ # define NR_IRQS 2048 /* enuff for 8 QBBs */
#elif defined(CONFIG_ALPHA_MARVEL)
# define NR_IRQS (32768 + 16) /* enough for MARVEL with 128 PIDs */
#else /* everyone else */ #else /* everyone else */
# define NR_IRQS 16 # define NR_IRQS 16
#endif #endif
......
...@@ -22,6 +22,7 @@ struct linux_hose_info; ...@@ -22,6 +22,7 @@ struct linux_hose_info;
struct pci_dev; struct pci_dev;
struct pci_ops; struct pci_ops;
struct pci_controller; struct pci_controller;
struct _alpha_agp_info;
struct alpha_machine_vector struct alpha_machine_vector
{ {
...@@ -80,6 +81,7 @@ struct alpha_machine_vector ...@@ -80,6 +81,7 @@ struct alpha_machine_vector
void (*device_interrupt)(unsigned long vector, struct pt_regs *regs); void (*device_interrupt)(unsigned long vector, struct pt_regs *regs);
void (*machine_check)(u64 vector, u64 la, struct pt_regs *regs); void (*machine_check)(u64 vector, u64 la, struct pt_regs *regs);
void (*smp_callin)(void);
void (*init_arch)(void); void (*init_arch)(void);
void (*init_irq)(void); void (*init_irq)(void);
void (*init_rtc)(void); void (*init_rtc)(void);
...@@ -90,6 +92,8 @@ struct alpha_machine_vector ...@@ -90,6 +92,8 @@ struct alpha_machine_vector
int (*pci_map_irq)(struct pci_dev *, u8, u8); int (*pci_map_irq)(struct pci_dev *, u8, u8);
struct pci_ops *pci_ops; struct pci_ops *pci_ops;
struct _alpha_agp_info *(*agp_info)(void);
const char *vector_name; const char *vector_name;
/* NUMA information */ /* NUMA information */
......
...@@ -42,6 +42,8 @@ struct pci_controller { ...@@ -42,6 +42,8 @@ struct pci_controller {
struct pci_iommu_arena *sg_pci; struct pci_iommu_arena *sg_pci;
struct pci_iommu_arena *sg_isa; struct pci_iommu_arena *sg_isa;
void *sysdata;
}; };
/* Override the logic in pci_scan_bus for skipping already-configured /* Override the logic in pci_scan_bus for skipping already-configured
......
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