diff options
Diffstat (limited to 'arch/alpha/kernel')
45 files changed, 2411 insertions, 4389 deletions
diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile index 4032c8c0e..282147e72 100644 --- a/arch/alpha/kernel/Makefile +++ b/arch/alpha/kernel/Makefile @@ -16,7 +16,7 @@ all: kernel.o head.o O_TARGET := kernel.o O_OBJS := entry.o traps.o process.o osf_sys.o irq.o signal.o setup.o \ - bios32.o ptrace.o time.o fpreg.o + ptrace.o time.o fpreg.o semaphore.o OX_OBJS := alpha_ksyms.o @@ -28,9 +28,13 @@ O_OBJS += core_apecs.o core_cia.o core_lca.o core_mcpcia.o core_pyxis.o \ sys_jensen.o sys_miata.o sys_mikasa.o sys_noritake.o \ sys_rawhide.o sys_ruffian.o sys_sable.o sys_sio.o \ sys_sx164.o sys_takara.o sys_rx164.o \ - es1888.o smc37c669.o smc37c93x.o + es1888.o smc37c669.o smc37c93x.o ns87312.o pci.o else +ifdef CONFIG_PCI +O_OBJS += pci.o +endif + # Core logic support ifdef CONFIG_ALPHA_APECS O_OBJS += core_apecs.o @@ -62,10 +66,10 @@ ifneq ($(CONFIG_ALPHA_ALCOR)$(CONFIG_ALPHA_XLT),) O_OBJS += sys_alcor.o endif ifneq ($(CONFIG_ALPHA_CABRIOLET)$(CONFIG_ALPHA_EB164)$(CONFIG_ALPHA_EB66P)$(CONFIG_ALPHA_LX164)$(CONFIG_ALPHA_PC164),) -O_OBJS += sys_cabriolet.o +O_OBJS += sys_cabriolet.o ns87312.o endif ifdef CONFIG_ALPHA_DP264 -O_OBJS += sys_dp264.o +O_OBJS += sys_dp264.o es1888.o smc37c669.o endif ifneq ($(CONFIG_ALPHA_EB64P)$(CONFIG_ALPHA_EB66),) O_OBJS += sys_eb64p.o @@ -74,7 +78,7 @@ ifdef CONFIG_ALPHA_JENSEN O_OBJS += sys_jensen.o endif ifdef CONFIG_ALPHA_MIATA -O_OBJS += sys_miata.o +O_OBJS += sys_miata.o es1888.o smc37c669.o endif ifdef CONFIG_ALPHA_MIKASA O_OBJS += sys_mikasa.o @@ -95,22 +99,16 @@ ifdef CONFIG_ALPHA_SABLE O_OBJS += sys_sable.o endif ifneq ($(CONFIG_ALPHA_BOOK1)$(CONFIG_ALPHA_AVANTI)$(CONFIG_ALPHA_NONAME)$(CONFIG_ALPHA_P2K)$(CONFIG_ALPHA_XL),) -O_OBJS += sys_sio.o +O_OBJS += sys_sio.o ns87312.o endif ifdef CONFIG_ALPHA_SX164 -O_OBJS += sys_sx164.o +O_OBJS += sys_sx164.o smc37c669.o endif ifdef CONFIG_ALPHA_TAKARA -O_OBJS += sys_takara.o +O_OBJS += sys_takara.o ns87312.o endif # Device support -ifdef CONFIG_ALPHA_MIATA -O_OBJS += es1888.o -endif -ifneq ($(CONFIG_ALPHA_SX164)$(CONFIG_ALPHA_MIATA)$(CONFIG_ALPHA_DP264),) -O_OBJS += smc37c669.o -endif ifneq ($(CONFIG_ALPHA_PC164)$(CONFIG_ALPHA_LX164),) O_OBJS += smc37c93x.o endif diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c index cba493d09..d8e1082d8 100644 --- a/arch/alpha/kernel/alpha_ksyms.c +++ b/arch/alpha/kernel/alpha_ksyms.c @@ -36,6 +36,7 @@ extern struct hwrpb_struct *hwrpb; extern void dump_thread(struct pt_regs *, struct user *); extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); +extern void ___delay(void); /* these are C runtime functions with special calling conventions: */ extern void __divl (void); @@ -48,8 +49,6 @@ extern void __divqu (void); extern void __remqu (void); EXPORT_SYMBOL(alpha_mv); -EXPORT_SYMBOL(local_bh_count); -EXPORT_SYMBOL(local_irq_count); EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(disable_irq_nosync); @@ -107,7 +106,7 @@ EXPORT_SYMBOL(alpha_read_fp_reg); EXPORT_SYMBOL(alpha_write_fp_reg); /* In-kernel system calls. */ -EXPORT_SYMBOL(__kernel_thread); +EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(sys_open); EXPORT_SYMBOL(sys_dup); EXPORT_SYMBOL(sys_exit); @@ -149,6 +148,11 @@ EXPORT_SYMBOL_NOVERS(__down_failed); EXPORT_SYMBOL_NOVERS(__down_failed_interruptible); EXPORT_SYMBOL_NOVERS(__up_wakeup); +/* + * This is called specially from __delay. + */ +EXPORT_SYMBOL_NOVERS(___delay); + /* * SMP-specific symbols. */ @@ -178,6 +182,9 @@ EXPORT_SYMBOL(debug_spin_trylock); EXPORT_SYMBOL(write_lock); EXPORT_SYMBOL(read_lock); #endif +#else /* __SMP__ */ +EXPORT_SYMBOL(__local_bh_count); +EXPORT_SYMBOL(__local_irq_count); #endif /* __SMP__ */ /* diff --git a/arch/alpha/kernel/bios32.c b/arch/alpha/kernel/bios32.c deleted file mode 100644 index 1c7823397..000000000 --- a/arch/alpha/kernel/bios32.c +++ /dev/null @@ -1,1355 +0,0 @@ -/* - * bios32.c - PCI BIOS functions for Alpha systems not using BIOS - * emulation code. - * - * Written by Dave Rusling (david.rusling@reo.mts.dec.com) - * - * Adapted to 64-bit kernel and then rewritten by David Mosberger - * (davidm@cs.arizona.edu) - * - * For more information, please consult - * - * PCI BIOS Specification Revision - * PCI Local Bus Specification - * PCI System Design Guide - * - * PCI Special Interest Group - * M/S HF3-15A - * 5200 N.E. Elam Young Parkway - * Hillsboro, Oregon 97124-6497 - * +1 (503) 696-2000 - * +1 (800) 433-5177 - * - * Manuals are $25 each or $50 for all three, plus $7 shipping - * within the United States, $35 abroad. - */ - -#include <linux/config.h> -#include <linux/kernel.h> -#include <linux/tasks.h> -#include <linux/smp.h> -#include <linux/smp_lock.h> -#include <linux/init.h> -#include <linux/errno.h> -#include <linux/pci.h> -#include <asm/pci.h> -#include <asm/dma.h> - -#include "proto.h" -#include "bios32.h" - -#define DEBUG_DEVS 0 -#define DEBUG_HOSE 0 - -#if DEBUG_DEVS -# define DBG_DEVS(args) printk args -#else -# define DBG_DEVS(args) -#endif - -#if DEBUG_HOSE -# define DBG_HOSE(args) printk args -#else -# define DBG_HOSE(args) -#endif - -#ifndef CONFIG_PCI - -asmlinkage int sys_pciconfig_read() { return -ENOSYS; } -asmlinkage int sys_pciconfig_write() { return -ENOSYS; } -void reset_for_srm(void) { } - -#else /* CONFIG_PCI */ - -#include <linux/malloc.h> -#include <linux/mm.h> - -#include <asm/io.h> -#include <asm/uaccess.h> -#include <asm/segment.h> -#include <asm/system.h> - -/* - * PCI public interfaces. - */ - -#define MAJOR_REV 0 -#define MINOR_REV 4 /* minor revision 4, add multi-PCI handling */ - -struct linux_hose_info *bus2hose[256]; -struct linux_hose_info *hose_head, **hose_tail = &hose_head; -int hose_count; -int pci_probe_enabled; - -static void layout_hoses(void); - -int -pcibios_present(void) -{ - return alpha_mv.hose_read_config_byte != NULL; -} - -void __init -pcibios_init(void) -{ - if (!pcibios_present()) - return; - - printk("Alpha PCI BIOS32 revision %d.%02d\n", MAJOR_REV, MINOR_REV); - if (alpha_use_srm_setup) - printk(" NOT modifying existing (SRM) PCI configuration\n"); -} - -char * __init -pcibios_setup(char *str) -{ - return str; -} - -void __init -pcibios_fixup(void) -{ - alpha_mv.pci_fixup(); -} - -void __init -pcibios_fixup_bus(struct pci_bus *bus) -{ -} - -int -pcibios_read_config_byte (u8 bus, u8 dev, u8 where, u8 *value) -{ - int r = PCIBIOS_FUNC_NOT_SUPPORTED; - *value = 0xff; - if (alpha_mv.hose_read_config_byte) { - r = (alpha_mv.hose_read_config_byte - (bus, dev, where, value, bus2hose[bus])); - } - return r; -} - -int -pcibios_read_config_word (u8 bus, u8 dev, u8 where, u16 *value) -{ - int r = PCIBIOS_FUNC_NOT_SUPPORTED; - *value = 0xffff; - if (alpha_mv.hose_read_config_word) { - r = PCIBIOS_BAD_REGISTER_NUMBER; - if (!(where & 1)) - r = (alpha_mv.hose_read_config_word - (bus, dev, where, value, bus2hose[bus])); - } - return r; -} - -int -pcibios_read_config_dword (u8 bus, u8 dev, u8 where, u32 *value) -{ - int r = PCIBIOS_FUNC_NOT_SUPPORTED; - *value = 0xffffffff; - if (alpha_mv.hose_read_config_dword) { - r = PCIBIOS_BAD_REGISTER_NUMBER; - if (!(where & 3)) - r = (alpha_mv.hose_read_config_dword - (bus, dev, where, value, bus2hose[bus])); - } - return r; -} - -int -pcibios_write_config_byte (u8 bus, u8 dev, u8 where, u8 value) -{ - int r = PCIBIOS_FUNC_NOT_SUPPORTED; - if (alpha_mv.hose_write_config_byte) { - r = (alpha_mv.hose_write_config_byte - (bus, dev, where, value, bus2hose[bus])); - } - return r; -} - -int -pcibios_write_config_word (u8 bus, u8 dev, u8 where, u16 value) -{ - int r = PCIBIOS_FUNC_NOT_SUPPORTED; - if (alpha_mv.hose_write_config_word) { - r = PCIBIOS_BAD_REGISTER_NUMBER; - if (!(where & 1)) - r = (alpha_mv.hose_write_config_word - (bus, dev, where, value, bus2hose[bus])); - } - return r; -} - -int -pcibios_write_config_dword (u8 bus, u8 dev, u8 where, u32 value) -{ - int r = PCIBIOS_FUNC_NOT_SUPPORTED; - if (alpha_mv.hose_write_config_dword) { - r = PCIBIOS_BAD_REGISTER_NUMBER; - if (!(where & 3)) - r = (alpha_mv.hose_write_config_dword - (bus, dev, where, value, bus2hose[bus])); - } - return r; -} - -asmlinkage int -sys_pciconfig_read(unsigned long bus, unsigned long dfn, - unsigned long off, unsigned long len, - unsigned char *buf) -{ - unsigned char ubyte; - unsigned short ushort; - unsigned int uint; - long err = 0; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (!pcibios_present()) - return -ENOSYS; - - switch (len) { - case 1: - err = pcibios_read_config_byte(bus, dfn, off, &ubyte); - put_user(ubyte, buf); - break; - case 2: - err = pcibios_read_config_word(bus, dfn, off, &ushort); - put_user(ushort, (unsigned short *)buf); - break; - case 4: - err = pcibios_read_config_dword(bus, dfn, off, &uint); - put_user(uint, (unsigned int *)buf); - break; - default: - err = -EINVAL; - break; - } - return err; -} - -asmlinkage int -sys_pciconfig_write(unsigned long bus, unsigned long dfn, - unsigned long off, unsigned long len, - unsigned char *buf) -{ - unsigned char ubyte; - unsigned short ushort; - unsigned int uint; - long err = 0; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (!pcibios_present()) - return -ENOSYS; - - switch (len) { - case 1: - err = get_user(ubyte, buf); - if (err) - break; - err = pcibios_write_config_byte(bus, dfn, off, ubyte); - if (err != PCIBIOS_SUCCESSFUL) { - err = -EFAULT; - } - break; - case 2: - err = get_user(ushort, (unsigned short *)buf); - if (err) - break; - err = pcibios_write_config_word(bus, dfn, off, ushort); - if (err != PCIBIOS_SUCCESSFUL) { - err = -EFAULT; - } - break; - case 4: - err = get_user(uint, (unsigned int *)buf); - if (err) - break; - err = pcibios_write_config_dword(bus, dfn, off, uint); - if (err != PCIBIOS_SUCCESSFUL) { - err = -EFAULT; - } - break; - default: - err = -EINVAL; - break; - } - return err; -} - - -/* - * Gory details start here... - */ - -/* - * Align VAL to ALIGN, which must be a power of two. - */ -#define ALIGN(val,align) (((val) + ((align) - 1)) & ~((align) - 1)) - - -/* - * The following structure records initial configuration of devices - * so that we can reset them on shutdown and so enable clean reboots - * on SRM. It is more trouble than it iw worth to conditionalize this. - */ - -struct srm_irq_reset { - struct srm_irq_reset *next; - struct pci_dev *dev; - u8 irq; -} *srm_irq_resets; - -struct srm_io_reset { - struct srm_io_reset *next; - struct pci_dev *dev; - u32 io; - u8 reg; -} *srm_io_resets; - -/* Apply the collected reset modifications. */ - -void -reset_for_srm(void) -{ - struct srm_irq_reset *qreset; - struct srm_io_reset *ireset; - - /* Reset any IRQs that we changed. */ - for (qreset = srm_irq_resets; qreset ; qreset = qreset->next) { - pcibios_write_config_byte(qreset->dev->bus->number, - qreset->dev->devfn, - PCI_INTERRUPT_LINE, - qreset->irq); -#if 1 - printk("reset_for_srm: bus %d slot 0x%x " - "SRM IRQ 0x%x changed back from 0x%x\n", - qreset->dev->bus->number, - PCI_SLOT(qreset->dev->devfn), - qreset->irq, qreset->dev->irq); -#endif - } - - /* Reset any IO addresses that we changed. */ - for (ireset = srm_io_resets; ireset ; ireset = ireset->next) { - pcibios_write_config_dword(ireset->dev->bus->number, - ireset->dev->devfn, - ireset->reg, ireset->io); -#if 1 - printk("reset_for_srm: bus %d slot 0x%x " - "SRM MEM/IO restored to 0x%x\n", - ireset->dev->bus->number, - PCI_SLOT(ireset->dev->devfn), - ireset->io); -#endif - } -} - -static void -new_irq_reset(struct pci_dev *dev, u8 irq) -{ - struct srm_irq_reset *n; - n = kmalloc(sizeof(*n), GFP_KERNEL); - - n->next = srm_irq_resets; - n->dev = dev; - n->irq = irq; - srm_irq_resets = n; -} - -static void -new_io_reset(struct pci_dev *dev, u8 reg, u32 io) -{ - struct srm_io_reset *n; - n = kmalloc(sizeof(*n), GFP_KERNEL); - - n->next = srm_io_resets; - n->dev = dev; - n->reg = reg; - n->io = io; - srm_io_resets = n; -} - - -/* - * Disable PCI device DEV so that it does not respond to I/O or memory - * accesses. - */ -static void __init -disable_dev(struct pci_dev *dev) -{ - struct pci_bus *bus; - unsigned short cmd; - - /* - * HACK: the PCI-to-EISA bridge does not seem to identify - * itself as a bridge... :-( - */ - if (dev->vendor == PCI_VENDOR_ID_INTEL && - dev->device == PCI_DEVICE_ID_INTEL_82375) { - dev->class = PCI_CLASS_BRIDGE_EISA; - DBG_DEVS(("disable_dev: ignoring PCEB...\n")); - return; - } - - if (dev->vendor == PCI_VENDOR_ID_INTEL && - dev->device == PCI_DEVICE_ID_INTEL_82378) { - dev->class = PCI_CLASS_BRIDGE_ISA; - DBG_DEVS(("disable_dev: ignoring SIO...\n")); - return; - } - - /* - * We don't have code that will init the CYPRESS bridge correctly - * so we do the next best thing, and depend on the previous - * console code to do the right thing, and ignore it here... :-\ - */ - if (dev->vendor == PCI_VENDOR_ID_CONTAQ && - dev->device == PCI_DEVICE_ID_CONTAQ_82C693) { - DBG_DEVS(("disable_dev: ignoring CYPRESS bridge...\n")); - return; - } - -#if DEBUG_DEVS && 0 - /* Worse HACK: Don't disable the video card, so I can see where - it is *really* falling over. */ - if (dev->class >> 16 == PCI_BASE_CLASS_DISPLAY) { - DBG_DEVS(("disable_dev: ignoring video card %04x:%04x\n", - dev->vendor, dev->device)); - return; - } -#endif - - DBG_DEVS(("disable_dev: disabling %04x:%04x\n", - dev->vendor, dev->device)); - - bus = dev->bus; - pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd); - - /* hack, turn it off first... */ - cmd &= (~PCI_COMMAND_IO & ~PCI_COMMAND_MEMORY & ~PCI_COMMAND_MASTER); - pcibios_write_config_word(bus->number, dev->devfn, PCI_COMMAND, cmd); -} - - -/* - * Layout memory and I/O for a device: - */ -#define MAX(val1, val2) ((val1) > (val2) ? (val1) : (val2)) - -static unsigned int io_base; -static unsigned int mem_base; - -static void __init -layout_dev(struct pci_dev *dev) -{ - struct pci_bus *bus; - unsigned short cmd; - unsigned int base, mask, size, off, idx; - unsigned int orig_base; - unsigned int alignto; - unsigned long handle; - - /* - * HACK: the PCI-to-EISA bridge does not seem to identify - * itself as a bridge... :-( - */ - if (dev->vendor == PCI_VENDOR_ID_INTEL && - dev->device == PCI_DEVICE_ID_INTEL_82375) { - dev->class = PCI_CLASS_BRIDGE_EISA; - DBG_DEVS(("layout_dev: ignoring PCEB...\n")); - return; - } - - if (dev->vendor == PCI_VENDOR_ID_INTEL && - dev->device == PCI_DEVICE_ID_INTEL_82378) { - dev->class = PCI_CLASS_BRIDGE_ISA; - DBG_DEVS(("layout_dev: ignoring SIO...\n")); - return; - } - - /* - * We don't have code that will init the CYPRESS bridge correctly - * so we do the next best thing, and depend on the previous - * console code to do the right thing, and ignore it here... :-\ - */ - if (dev->vendor == PCI_VENDOR_ID_CONTAQ && - dev->device == PCI_DEVICE_ID_CONTAQ_82C693) { - DBG_DEVS(("layout_dev: ignoring CYPRESS bridge...\n")); - return; - } - - bus = dev->bus; - pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd); - - for (idx = 0; idx <= 5; idx++) { - off = PCI_BASE_ADDRESS_0 + 4*idx; - /* - * Figure out how much space and of what type this - * device wants. - */ - pcibios_read_config_dword(bus->number, dev->devfn, off, - &orig_base); - pcibios_write_config_dword(bus->number, dev->devfn, off, - 0xffffffff); - pcibios_read_config_dword(bus->number, dev->devfn, off, &base); - if (!base) { - /* this base-address register is unused */ - dev->base_address[idx] = 0; - continue; - } - - DBG_DEVS(("layout_dev: slot %d fn %d off 0x%x base 0x%x\n", - PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), - off, base)); - - /* - * We've read the base address register back after - * writing all ones and so now we must decode it. - */ - if (base & PCI_BASE_ADDRESS_SPACE_IO) { - /* - * I/O space base address register. - */ - cmd |= PCI_COMMAND_IO; - - base &= PCI_BASE_ADDRESS_IO_MASK; - mask = (~base << 1) | 0x1; - size = (mask & base) & 0xffffffff; - /* - * Aligning to 0x800 rather than the minimum base of - * 0x400 is an attempt to avoid having devices in - * any 0x?C?? range, which is where the de4x5 driver - * probes for EISA cards. - * - * Adaptecs, especially, resent such intrusions. - */ - alignto = MAX(0x800, size); - base = ALIGN(io_base, alignto); - io_base = base + size; - - pcibios_write_config_dword(bus->number, dev->devfn, - off, base | 0x1); - new_io_reset(dev, off, orig_base); - - handle = PCI_HANDLE(bus->number) | base | 1; - dev->base_address[idx] = handle; - - DBG_DEVS(("layout_dev: dev 0x%x IO @ 0x%lx (0x%x)\n", - dev->device, handle, size)); - } else { - unsigned int type; - /* - * Memory space base address register. - */ - cmd |= PCI_COMMAND_MEMORY; - type = base & PCI_BASE_ADDRESS_MEM_TYPE_MASK; - base &= PCI_BASE_ADDRESS_MEM_MASK; - mask = (~base << 1) | 0x1; - size = (mask & base) & 0xffffffff; - switch (type) { - case PCI_BASE_ADDRESS_MEM_TYPE_32: - case PCI_BASE_ADDRESS_MEM_TYPE_64: - break; - - case PCI_BASE_ADDRESS_MEM_TYPE_1M: - /* - * Allocating memory below 1MB is *very* - * tricky, as there may be all kinds of - * ISA devices lurking that we don't know - * about. For now, we just cross fingers - * and hope nobody tries to do this on an - * Alpha (or that the console has set it - * up properly). - */ - printk("bios32 WARNING: slot %d, function %d" - " requests memory below 1MB---don't" - " know how to do that.\n", - PCI_SLOT(dev->devfn), - PCI_FUNC(dev->devfn)); - continue; - } - /* - * The following holds at least for the Low Cost - * Alpha implementation of the PCI interface: - * - * In sparse memory address space, the first - * octant (16MB) of every 128MB segment is - * aliased to the very first 16 MB of the - * address space (i.e., it aliases the ISA - * memory address space). Thus, we try to - * avoid allocating PCI devices in that range. - * Can be allocated in 2nd-7th octant only. - * Devices that need more than 112MB of - * address space must be accessed through - * dense memory space only! - */ - /* align to multiple of size of minimum base */ - alignto = MAX(0x1000, size); - base = ALIGN(mem_base, alignto); - if (size > 7 * 16*MB) { - printk("bios32 WARNING: slot %d, function %d" - " requests 0x%x bytes of contiguous" - " address space---don't use sparse" - " memory accesses on this device!!\n", - PCI_SLOT(dev->devfn), - PCI_FUNC(dev->devfn), size); - } else { - if (((base / (16*MB)) & 0x7) == 0) { - base &= ~(128*MB - 1); - base += 16*MB; - base = ALIGN(base, alignto); - } - if (base/(128*MB) != (base + size)/(128*MB)) { - base &= ~(128*MB - 1); - base += (128 + 16)*MB; - base = ALIGN(base, alignto); - } - } - mem_base = base + size; - - pcibios_write_config_dword(bus->number, dev->devfn, - off, base); - new_io_reset(dev, off, orig_base); - - handle = PCI_HANDLE(bus->number) | base; - dev->base_address[idx] = handle; - - /* - * Currently for 64-bit cards, we simply do the usual - * for setup of the first register (low) of the pair, - * and then clear out the second (high) register, as - * we are not yet able to do 64-bit addresses, and - * setting the high register to 0 allows 32-bit SAC - * addresses to be used. - */ - if (type == PCI_BASE_ADDRESS_MEM_TYPE_64) { - unsigned int orig_base2; - pcibios_read_config_dword(bus->number, - dev->devfn, - off+4, &orig_base2); - if (0 != orig_base2) { - pcibios_write_config_dword(bus->number, - dev->devfn, - off+4, 0); - new_io_reset (dev, off+4, orig_base2); - } - /* Bypass hi reg in the loop. */ - dev->base_address[++idx] = 0; - - printk("bios32 WARNING: " - "handling 64-bit device in " - "slot %d, function %d: \n", - PCI_SLOT(dev->devfn), - PCI_FUNC(dev->devfn)); - } - - DBG_DEVS(("layout_dev: dev 0x%x MEM @ 0x%lx (0x%x)\n", - dev->device, handle, size)); - } - } - - /* Enable device: */ - if (dev->class >> 8 == PCI_CLASS_NOT_DEFINED || - dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA || - dev->class >> 8 == PCI_CLASS_STORAGE_IDE || - dev->class >> 16 == PCI_BASE_CLASS_DISPLAY) - { - /* - * All of these (may) have I/O scattered all around - * and may not use i/o-base address registers at all. - * So we just have to always enable I/O to these - * devices. - */ - cmd |= PCI_COMMAND_IO; - } - - pcibios_write_config_word(bus->number, dev->devfn, PCI_COMMAND, - cmd | PCI_COMMAND_MASTER); - - DBG_DEVS(("layout_dev: bus %d slot %d VID 0x%x DID 0x%x" - " class 0x%x cmd 0 x%x\n", - bus->number, PCI_SLOT(dev->devfn), dev->vendor, - dev->device, dev->class, cmd|PCI_COMMAND_MASTER)); -} - -static int __init -layout_bus(struct pci_bus *bus) -{ - unsigned int l, tio, bio, tmem, bmem; - struct pci_bus *child; - struct pci_dev *dev; - int found_vga = 0; - - DBG_DEVS(("layout_bus: starting bus %d\n", bus->number)); - - if (!bus->devices && !bus->children) - return 0; - - /* - * Align the current bases on appropriate boundaries (4K for - * IO and 1MB for memory). - */ - bio = io_base = ALIGN(io_base, 4*KB); - bmem = mem_base = ALIGN(mem_base, 1*MB); - - /* - * There are times when the PCI devices have already been - * setup (e.g., by MILO or SRM). In these cases there is a - * window during which two devices may have an overlapping - * address range. To avoid this causing trouble, we first - * turn off the I/O and memory address decoders for all PCI - * devices. They'll be re-enabled only once all address - * decoders are programmed consistently. - */ - DBG_DEVS(("layout_bus: disable_dev for bus %d\n", bus->number)); - - for (dev = bus->devices; dev; dev = dev->sibling) { - if ((dev->class >> 16 != PCI_BASE_CLASS_BRIDGE) || - (dev->class >> 8 == PCI_CLASS_BRIDGE_PCMCIA)) { - disable_dev(dev); - } - } - - /* - * Allocate space to each device: - */ - DBG_DEVS(("layout_bus: starting bus %d devices\n", bus->number)); - - for (dev = bus->devices; dev; dev = dev->sibling) { - if ((dev->class >> 16 != PCI_BASE_CLASS_BRIDGE) || - (dev->class >> 8 == PCI_CLASS_BRIDGE_PCMCIA)) { - layout_dev(dev); - } - if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) - found_vga = 1; - } - /* - * Recursively allocate space for all of the sub-buses: - */ - DBG_DEVS(("layout_bus: starting bus %d children\n", bus->number)); - - for (child = bus->children; child; child = child->next) { - found_vga += layout_bus(child); - } - /* - * Align the current bases on 4K and 1MB boundaries: - */ - tio = io_base = ALIGN(io_base, 4*KB); - tmem = mem_base = ALIGN(mem_base, 1*MB); - - if (bus->self) { - struct pci_dev *bridge = bus->self; - - DBG_DEVS(("layout_bus: config bus %d bridge\n", bus->number)); - - /* - * Set up the top and bottom of the PCI I/O segment - * for this bus. - */ - pcibios_read_config_dword(bridge->bus->number, bridge->devfn, - PCI_IO_BASE, &l); - l &= 0xffff0000; - l |= ((bio >> 8) & 0x00f0) | ((tio - 1) & 0xf000); - pcibios_write_config_dword(bridge->bus->number, bridge->devfn, - PCI_IO_BASE, l); - - /* - * Clear out the upper 16 bits of IO base/limit. - * Clear out the upper 32 bits of PREF base/limit. - */ - pcibios_write_config_dword(bridge->bus->number, bridge->devfn, - PCI_IO_BASE_UPPER16, 0); - pcibios_write_config_dword(bridge->bus->number, bridge->devfn, - PCI_PREF_BASE_UPPER32, 0); - pcibios_write_config_dword(bridge->bus->number, bridge->devfn, - PCI_PREF_LIMIT_UPPER32, 0); - - /* - * Set up the top and bottom of the PCI Memory segment - * for this bus. - */ - l = ((bmem & 0xfff00000) >> 16) | ((tmem - 1) & 0xfff00000); - pcibios_write_config_dword(bridge->bus->number, bridge->devfn, - PCI_MEMORY_BASE, l); - - /* - * Turn off downstream PF memory address range, unless - * there is a VGA behind this bridge, in which case, we - * enable the PREFETCH range to include BIOS ROM at C0000. - * - * NOTE: this is a bit of a hack, done with PREFETCH for - * simplicity, rather than having to add it into the above - * non-PREFETCH range, which could then be bigger than we want. - * We might assume that we could relocate the BIOS ROM, but - * that would depend on having it found by those who need it - * (the DEC BIOS emulator would find it, but I do not know - * about the Xservers). So, we do it this way for now... ;-} - */ - l = (found_vga) ? 0 : 0x0000ffff; - pcibios_write_config_dword(bridge->bus->number, bridge->devfn, - PCI_PREF_MEMORY_BASE, l); - - /* - * Tell bridge that there is an ISA bus in the system, - * and (possibly) a VGA as well. - */ - l = (found_vga) ? 0x0c : 0x04; - pcibios_write_config_byte(bridge->bus->number, bridge->devfn, - PCI_BRIDGE_CONTROL, l); - - /* - * Clear status bits, - * turn on I/O enable (for downstream I/O), - * turn on memory enable (for downstream memory), - * turn on master enable (for upstream memory and I/O). - */ - pcibios_write_config_dword(bridge->bus->number, bridge->devfn, - PCI_COMMAND, 0xffff0007); - } - DBG_DEVS(("layout_bus: bus %d finished\n", bus->number)); - return found_vga; -} - -void __init -layout_all_busses(unsigned long default_io_base, - unsigned long default_mem_base) -{ - struct pci_bus *cur; - - layout_hoses(); - - /* - * Scan the tree, allocating PCI memory and I/O space. - */ - /* - * Sigh; check_region() will need changing to accept a PCI_HANDLE, - * if we allocate I/O space addresses on a per-bus basis. - * For now, make the I/O bases unique across all busses, so - * that check_region() will not get confused... ;-} - */ - io_base = default_io_base; - for (cur = &pci_root; cur; cur = cur->next) { - mem_base = default_mem_base; - DBG_DEVS(("layout_all_busses: calling layout_bus()\n")); - layout_bus(cur); - } - DBG_DEVS(("layout_all_busses: done.\n")); -} - - -/* - * The SRM console *disables* the IDE interface, this code ensures it's - * enabled. - * - * This code bangs on a control register of the 87312 Super I/O chip - * that implements parallel port/serial ports/IDE/FDI. Depending on - * the motherboard, the Super I/O chip can be configured through a - * pair of registers that are located either at I/O ports 0x26e/0x26f - * or 0x398/0x399. Unfortunately, autodetecting which base address is - * in use works only once (right after a reset). The Super I/O chip - * has the additional quirk that configuration register data must be - * written twice (I believe this is a safety feature to prevent - * accidental modification---fun, isn't it?). - */ - -void __init -enable_ide(long ide_base) -{ - int data; - unsigned long flags; - - __save_and_cli(flags); - outb(0, ide_base); /* set the index register for reg #0 */ - data = inb(ide_base+1); /* read the current contents */ - outb(0, ide_base); /* set the index register for reg #0 */ - outb(data | 0x40, ide_base+1); /* turn on IDE */ - outb(data | 0x40, ide_base+1); /* turn on IDE, really! */ - __restore_flags(flags); -} - -/* Look for mis-configured devices' I/O space addresses behind bridges. */ -static void -check_behind_io(struct pci_dev *dev) -{ - struct pci_bus *bus = dev->bus; - unsigned int reg, orig_base, new_base, found_one = 0; - - for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) { - /* Read the current setting, check for I/O space and >= 64K */ - pcibios_read_config_dword(bus->number, dev->devfn, - reg, &orig_base); - - if (!orig_base || !(orig_base & PCI_BASE_ADDRESS_SPACE_IO)) - continue; /* unused or non-IO */ - - if (orig_base < 64*1024) { -#if 1 -printk("check_behind_io: ALREADY OK! bus %d slot %d base 0x%x\n", - bus->number, PCI_SLOT(dev->devfn), orig_base); -#endif - if (orig_base & ~1) - continue; /* OK! */ - orig_base = 0x12001; /* HACK! FIXME!! */ - } - - /* HACK ALERT! for now, just subtract 32K from the - original address, which should give us addresses - in the range 0x8000 and up */ - new_base = orig_base - 0x8000; -#if 1 -printk("check_behind_io: ALERT! bus %d slot %d old 0x%x new 0x%x\n", - bus->number, PCI_SLOT(dev->devfn), orig_base, new_base); -#endif - pcibios_write_config_dword(bus->number, dev->devfn, - reg, new_base); - - new_io_reset(dev, reg, orig_base); - found_one++; - } - - /* If any were modified, gotta hack the bridge IO limits too. */ - if (found_one) { - if (bus->self) { - struct pci_dev *bridge = bus->self; - unsigned int l; - /* - * Set up the top and bottom of the PCI I/O segment - * for this bus. - */ - pcibios_read_config_dword(bridge->bus->number, - bridge->devfn, 0x1c, &l); -#if 1 -printk("check_behind_io: ALERT! bus %d slot %d oldLIM 0x%x\n", - bus->number, PCI_SLOT(bridge->devfn), l); -#endif - l = (l & 0xffff0000U) | 0xf080U; /* give it ALL */ - pcibios_write_config_dword(bridge->bus->number, - bridge->devfn, 0x1c, l); - pcibios_write_config_dword(bridge->bus->number, - bridge->devfn, - 0x3c, 0x00040000); - pcibios_write_config_dword(bridge->bus->number, - bridge->devfn, - 0x4, 0xffff0007); - } else - printk("check_behind_io: WARNING! bus->self NULL\n"); - } -} - - -/* - * Most boards share most of the fixup code, which is isolated here. - */ - -void __init -common_pci_fixup(int (*map_irq)(struct pci_dev *dev, int slot, int pin), - int (*swizzle)(struct pci_dev *dev, int *pin)) -{ - struct pci_dev *dev; - u8 pin, slot, irq_orig; - int irq; - - /* - * Go through all devices, fixing up irqs as we see fit. - */ - for (dev = pci_devices; dev; dev = dev->next) { - if ((dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) && - (dev->class >> 8 != PCI_CLASS_BRIDGE_PCMCIA)) - continue; - - /* - * We don't have code that will init the CYPRESS bridge - * correctly so we do the next best thing, and depend on - * the previous console code to do the right thing, and - * ignore it here... :-\ - */ - if (dev->vendor == PCI_VENDOR_ID_CONTAQ && - dev->device == PCI_DEVICE_ID_CONTAQ_82C693) { - DBG_DEVS(("common_pci_fixup: ignoring CYPRESS bridge...\n")); - continue; - } - - /* - * This device is not on the primary bus, we need - * to figure out which interrupt pin it will come - * in on. We know which slot it will come in on - * 'cos that slot is where the bridge is. Each - * time the interrupt line passes through a PCI-PCI - * bridge we must apply the swizzle function (see - * the inline static routine above). - */ - dev->irq = 0; - - pcibios_read_config_byte(dev->bus->number, dev->devfn, - PCI_INTERRUPT_PIN, &pin); - /* Cope with 0 and illegal. */ - if (pin == 0 || pin > 4) - pin = 1; - - if (!DEV_IS_ON_PRIMARY(dev)) { - /* Follow the chain of bridges, swizzling as we go. */ - - int spill = pin; - slot = (*swizzle)(dev, &spill); - pin = spill; - - /* Must make sure that SRM didn't screw up - and allocate an address > 64K for I/O - space behind a PCI-PCI bridge. */ - if (alpha_use_srm_setup) - check_behind_io(dev); - } else { - /* Just a device on a primary bus. */ - slot = PCI_SLOT(dev->devfn); - } - - irq = (*map_irq)(dev, slot, pin); - - DBG_DEVS(("common_pci_fixup: bus %d slot %d " - "pin %d irq %d\n", - dev->bus->number, slot, pin, irq)); - - if (irq != -1) - dev->irq = irq; - - if (alpha_using_srm) { - /* Read the original SRM-set IRQ and tell. */ - pcibios_read_config_byte(dev->bus->number, - dev->devfn, - PCI_INTERRUPT_LINE, - &irq_orig); - - if (irq_orig != dev->irq) { - DBG_DEVS(("common_pci_fixup: bus %d " - "slot 0x%x SRM IRQ 0x%x " - "changed to 0x%x\n", - dev->bus->number, - PCI_SLOT(dev->devfn), - irq_orig, dev->irq)); - - new_irq_reset(dev, irq_orig); - } - } - - /* Always tell the device, so the driver knows what is - the real IRQ to use; the device does not use it. */ - pcibios_write_config_byte(dev->bus->number, dev->devfn, - PCI_INTERRUPT_LINE, dev->irq); - - DBG_DEVS(("common_pci_fixup: bus %d slot 0x%x" - " VID 0x%x DID 0x%x\n" - " int_slot 0x%x pin 0x%x" - " pirq 0x%x\n", - dev->bus->number, PCI_SLOT(dev->devfn), - dev->vendor, dev->device, - slot, pin, dev->irq)); - - /* - * If it's a VGA, enable its BIOS ROM at C0000. - */ - if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) { - /* But if its a Cirrus 543x/544x DISABLE it, - since enabling ROM disables the memory... */ - if ((dev->vendor == PCI_VENDOR_ID_CIRRUS) && - (dev->device >= 0x00a0) && - (dev->device <= 0x00ac)) { - pcibios_write_config_dword( - dev->bus->number, - dev->devfn, - PCI_ROM_ADDRESS, - 0x00000000); - } else { - pcibios_write_config_dword( - dev->bus->number, - dev->devfn, - PCI_ROM_ADDRESS, - 0x000c0000 | PCI_ROM_ADDRESS_ENABLE); - } - } - /* - * If it's a SCSI, disable its BIOS ROM. - */ - if ((dev->class >> 8) == PCI_CLASS_STORAGE_SCSI) { - pcibios_write_config_dword(dev->bus->number, - dev->devfn, - PCI_ROM_ADDRESS, - 0x0000000); - } - } -} - -/* Most Alphas have straight-forward swizzling needs. */ - -int __init -common_swizzle(struct pci_dev *dev, int *pinp) -{ - int pin = *pinp; - do { - pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)); - /* Move up the chain of bridges. */ - dev = dev->bus->self; - } while (dev->bus->self); - *pinp = pin; - - /* The slot is the slot of the last bridge. */ - return PCI_SLOT(dev->devfn); -} - -/* - * On multiple bus machines, in order to cope with a somewhat deficient - * API, we must map the 8-bit bus identifier so that it is unique across - * multiple interfaces (hoses). At the same time we do this, chain the - * other hoses off of pci_root so that they will be found during normal - * PCI probing and layout. - */ - -#define PRIMARY(b) ((b)&0xff) -#define SECONDARY(b) (((b)>>8)&0xff) -#define SUBORDINATE(b) (((b)>>16)&0xff) - -static int __init -hose_scan_bridges(struct linux_hose_info *hose, unsigned char bus) -{ - unsigned int devfn, l, class; - unsigned char hdr_type = 0; - unsigned int found = 0; - - for (devfn = 0; devfn < 0xff; ++devfn) { - if (PCI_FUNC(devfn) == 0) { - alpha_mv.hose_read_config_byte(bus, devfn, - PCI_HEADER_TYPE, - &hdr_type, hose); - } else if (!(hdr_type & 0x80)) { - /* not a multi-function device */ - continue; - } - - /* Check if there is anything here. */ - alpha_mv.hose_read_config_dword(bus, devfn, PCI_VENDOR_ID, - &l, hose); - if (l == 0xffffffff || l == 0x00000000) { - hdr_type = 0; - continue; - } - - /* See if this is a bridge device. */ - alpha_mv.hose_read_config_dword(bus, devfn, PCI_CLASS_REVISION, - &class, hose); - - if ((class >> 16) == PCI_CLASS_BRIDGE_PCI) { - unsigned int busses; - - found++; - - alpha_mv.hose_read_config_dword(bus, devfn, - PCI_PRIMARY_BUS, - &busses, hose); - - DBG_HOSE(("hose_scan_bridges: hose %d bus %d " - "slot %d busses 0x%x\n", - hose->pci_hose_index, bus, PCI_SLOT(devfn), - busses)); - - /* - * Do something with first_busno and last_busno - */ - if (hose->pci_first_busno > PRIMARY(busses)) { - hose->pci_first_busno = PRIMARY(busses); - DBG_HOSE(("hose_scan_bridges: hose %d bus %d " - "slot %d change first to %d\n", - hose->pci_hose_index, bus, - PCI_SLOT(devfn), PRIMARY(busses))); - } - if (hose->pci_last_busno < SUBORDINATE(busses)) { - hose->pci_last_busno = SUBORDINATE(busses); - DBG_HOSE(("hose_scan_bridges: hose %d bus %d " - "slot %d change last to %d\n", - hose->pci_hose_index, bus, - PCI_SLOT(devfn), - SUBORDINATE(busses))); - } - /* - * Now scan everything underneath the bridge. - */ - hose_scan_bridges(hose, SECONDARY(busses)); - } - } - return found; -} - -static void __init -hose_reconfigure_bridges(struct linux_hose_info *hose, unsigned char bus) -{ - unsigned int devfn, l, class; - unsigned char hdr_type = 0; - - for (devfn = 0; devfn < 0xff; ++devfn) { - if (PCI_FUNC(devfn) == 0) { - alpha_mv.hose_read_config_byte(bus, devfn, - PCI_HEADER_TYPE, - &hdr_type, hose); - } else if (!(hdr_type & 0x80)) { - /* not a multi-function device */ - continue; - } - - /* Check if there is anything here. */ - alpha_mv.hose_read_config_dword(bus, devfn, PCI_VENDOR_ID, - &l, hose); - if (l == 0xffffffff || l == 0x00000000) { - hdr_type = 0; - continue; - } - - /* See if this is a bridge device. */ - alpha_mv.hose_read_config_dword(bus, devfn, PCI_CLASS_REVISION, - &class, hose); - - if ((class >> 16) == PCI_CLASS_BRIDGE_PCI) { - unsigned int busses; - - alpha_mv.hose_read_config_dword(bus, devfn, - PCI_PRIMARY_BUS, - &busses, hose); - - /* - * First reconfigure everything underneath the bridge. - */ - hose_reconfigure_bridges(hose, (busses >> 8) & 0xff); - - /* - * Unconfigure this bridges bus numbers, - * pci_scan_bus() will fix this up properly. - */ - busses &= 0xff000000; - alpha_mv.hose_write_config_dword(bus, devfn, - PCI_PRIMARY_BUS, - busses, hose); - } - } -} - -static void __init -hose_fixup_busno(struct linux_hose_info *hose, unsigned char bus) -{ - int nbus; - - /* - * First, scan for all bridge devices underneath this hose, - * to determine the first and last busnos. - */ - DBG_HOSE(("hose_fixup_busno: before hose_scan_bridges()\n")); - - if (!hose_scan_bridges(hose, 0)) { - /* none found, exit */ - hose->pci_first_busno = bus; - hose->pci_last_busno = bus; - } else { - /* - * Reconfigure all bridge devices underneath this hose. - */ - DBG_HOSE(("hose_fixup_busno: before hose_reconfigure_bridges\n")); - hose_reconfigure_bridges(hose, hose->pci_first_busno); - } - - /* - * Now reconfigure the hose to it's new bus number and set up - * our bus2hose mapping for this hose. - */ - nbus = hose->pci_last_busno - hose->pci_first_busno; - - hose->pci_first_busno = bus; - - DBG_HOSE(("hose_fixup_busno: hose %d startbus %d nbus %d\n", - hose->pci_hose_index, bus, nbus)); - - do { - bus2hose[bus++] = hose; - } while (nbus-- > 0); - DBG_HOSE(("hose_fixup_busno: returning...\n")); -} - -static void __init -layout_one_hose(struct linux_hose_info *hose) -{ - static struct pci_bus *pchain = NULL; - struct pci_bus *pbus = &hose->pci_bus; - static unsigned char busno = 0; - - DBG_HOSE(("layout_one_hose: entry\n")); - - /* - * Hoses include child PCI bridges in bus-range property, - * but we don't scan each of those ourselves, Linux generic PCI - * probing code will find child bridges and link them into this - * hose's root PCI device hierarchy. - */ - - pbus->number = pbus->secondary = busno; - pbus->sysdata = hose; - - DBG_HOSE(("layout_one_hose: before hose_fixup_busno()\n")); - - hose_fixup_busno(hose, busno); - - DBG_HOSE(("layout_one_hose: before pci_scan_bus()\n")); - - pbus->subordinate = pci_scan_bus(pbus); /* the original! */ - - /* - * Set the maximum subordinate bus of this hose. - */ - hose->pci_last_busno = pbus->subordinate; -#if 0 - alpha_mv.hose_write_config_byte(busno, 0, 0x41, hose->pci_last_busno, - hose); -#endif - busno = pbus->subordinate + 1; - - /* - * Fixup the chain of primary PCI busses. - */ - if (pchain) { - pchain->next = &hose->pci_bus; - pchain = pchain->next; - } else { - pchain = &pci_root; - memcpy(pchain, &hose->pci_bus, sizeof(pci_root)); - } - DBG_HOSE(("layout_one_hose: returning...\n")); -} - -static void __init -layout_hoses(void) -{ - struct linux_hose_info * hose; - int i; - - /* On multiple bus machines, we play games with pci_root in order - that all of the busses are probed as part of the normal PCI - setup. The existance of the busses was determined in init_arch. */ - - if (hose_head) { - /* Multi-bus machines did not yet wish to allow bus - accesses. We now do our own thing after the normal - pci_scan_bus is over. This mechanism is relatively - broken but will be fixed later. */ - pci_probe_enabled = 1; - - for (hose = hose_head; hose; hose = hose->next) - layout_one_hose(hose); - } else { - /* For the benefit of single-bus machines, emulate a - multi-bus machine to the (limited) extent necessary. - Init all bus2hose entries to point to a dummy. */ - hose = kmalloc(sizeof(*hose), GFP_KERNEL); - memset(hose, 0, sizeof(*hose)); - for (i = 0; i < 256; ++i) - bus2hose[i] = hose; - } -} - -#endif /* CONFIG_PCI */ diff --git a/arch/alpha/kernel/core_apecs.c b/arch/alpha/kernel/core_apecs.c index fa23a4cf6..46378b762 100644 --- a/arch/alpha/kernel/core_apecs.c +++ b/arch/alpha/kernel/core_apecs.c @@ -1,22 +1,24 @@ /* * linux/arch/alpha/kernel/core_apecs.c * - * Code common to all APECS core logic chips. - * * Rewritten for Apecs from the lca.c from: * * Written by David Mosberger (davidm@cs.arizona.edu) with some code * taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit * bios code. + * + * Code common to all APECS core logic chips. */ + #include <linux/kernel.h> -#include <linux/config.h> #include <linux/types.h> #include <linux/pci.h> #include <linux/init.h> #include <asm/system.h> #include <asm/ptrace.h> +#include <asm/smp.h> +#include <asm/pci.h> #define __EXTERN_INLINE inline #include <asm/io.h> @@ -24,6 +26,7 @@ #undef __EXTERN_INLINE #include "proto.h" +#include "pci_impl.h" /* * NOTE: Herein lie back-to-back mb instructions. They are magic. @@ -35,19 +38,16 @@ * BIOS32-style PCI interface: */ -#ifdef DEBUG -# define DBG(args) printk args +#define DEBUG_CONFIG 0 + +#if DEBUG_CONFIG +# define DBGC(args) printk args #else -# define DBG(args) +# define DBGC(args) #endif #define vuip volatile unsigned int * -volatile unsigned int apecs_mcheck_expected = 0; -volatile unsigned int apecs_mcheck_taken = 0; -static unsigned int apecs_jd, apecs_jd1, apecs_jd2; - - /* * Given a bus, device, and function number, compute resulting * configuration space address and setup the APECS_HAXR2 register @@ -91,14 +91,16 @@ static unsigned int apecs_jd, apecs_jd1, apecs_jd2; */ static int -mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr, +mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr, unsigned char *type1) { unsigned long addr; + u8 bus = dev->bus->number; + u8 device_fn = dev->devfn; - DBG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x," - " pci_addr=0x%p, type1=0x%p)\n", - bus, device_fn, where, pci_addr, type1)); + DBGC(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x," + " pci_addr=0x%p, type1=0x%p)\n", + bus, device_fn, where, pci_addr, type1)); if (bus == 0) { int device = device_fn >> 3; @@ -106,8 +108,8 @@ mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr, /* type 0 configuration cycle: */ if (device > 20) { - DBG(("mk_conf_addr: device (%d) > 20, returning -1\n", - device)); + DBGC(("mk_conf_addr: device (%d) > 20, returning -1\n", + device)); return -1; } @@ -119,7 +121,7 @@ mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr, addr = (bus << 16) | (device_fn << 8) | (where); } *pci_addr = addr; - DBG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr)); + DBGC(("mk_conf_addr: returning pci_addr 0x%lx\n", addr)); return 0; } @@ -132,25 +134,25 @@ conf_read(unsigned long addr, unsigned char type1) __save_and_cli(flags); /* avoid getting hit by machine check */ - DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1)); + DBGC(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1)); /* Reset status register to avoid losing errors. */ stat0 = *(vuip)APECS_IOC_DCSR; *(vuip)APECS_IOC_DCSR = stat0; mb(); - DBG(("conf_read: APECS DCSR was 0x%x\n", stat0)); + DBGC(("conf_read: APECS DCSR was 0x%x\n", stat0)); /* If Type1 access, must set HAE #2. */ if (type1) { haxr2 = *(vuip)APECS_IOC_HAXR2; mb(); *(vuip)APECS_IOC_HAXR2 = haxr2 | 1; - DBG(("conf_read: TYPE1 access\n")); + DBGC(("conf_read: TYPE1 access\n")); } draina(); - apecs_mcheck_expected = 1; - apecs_mcheck_taken = 0; + mcheck_expected(0) = 1; + mcheck_taken(0) = 0; mb(); /* Access configuration space. */ @@ -159,12 +161,12 @@ conf_read(unsigned long addr, unsigned char type1) asm volatile("ldl %0,%1; mb; mb" : "=r"(value) : "m"(*(vuip)addr) : "$9", "$10", "$11", "$12", "$13", "$14", "memory"); - if (apecs_mcheck_taken) { - apecs_mcheck_taken = 0; + if (mcheck_taken(0)) { + mcheck_taken(0) = 0; value = 0xffffffffU; mb(); } - apecs_mcheck_expected = 0; + mcheck_expected(0) = 0; mb(); #if 1 @@ -178,7 +180,7 @@ conf_read(unsigned long addr, unsigned char type1) /* Now look for any errors. */ stat0 = *(vuip)APECS_IOC_DCSR; - DBG(("conf_read: APECS DCSR after read 0x%x\n", stat0)); + DBGC(("conf_read: APECS DCSR after read 0x%x\n", stat0)); /* Is any error bit set? */ if (stat0 & 0xffe0U) { @@ -214,7 +216,6 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1) __save_and_cli(flags); /* avoid getting hit by machine check */ - /* Reset status register to avoid losing errors. */ stat0 = *(vuip)APECS_IOC_DCSR; *(vuip)APECS_IOC_DCSR = stat0; @@ -228,14 +229,14 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1) } draina(); - apecs_mcheck_expected = 1; + mcheck_expected(0) = 1; mb(); /* Access configuration space. */ *(vuip)addr = value; mb(); mb(); /* magic */ - apecs_mcheck_expected = 0; + mcheck_expected(0) = 0; mb(); #if 1 @@ -272,162 +273,106 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1) __restore_flags(flags); } -int -apecs_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value, - struct linux_hose_info *hose) +static int +apecs_read_config_byte(struct pci_dev *dev, int where, u8 *value) { - unsigned long addr = APECS_CONF; - unsigned long pci_addr; + unsigned long addr, pci_addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + if (mk_conf_addr(dev, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - addr |= (pci_addr << 5) + 0x00; - + addr = (pci_addr << 5) + 0x00 + APECS_CONF; *value = conf_read(addr, type1) >> ((where & 3) * 8); - return PCIBIOS_SUCCESSFUL; } -int -apecs_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value, - struct linux_hose_info *hose) +static int +apecs_read_config_word(struct pci_dev *dev, int where, u16 *value) { - unsigned long addr = APECS_CONF; - unsigned long pci_addr; + unsigned long addr, pci_addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + if (mk_conf_addr(dev, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - addr |= (pci_addr << 5) + 0x08; - + addr = (pci_addr << 5) + 0x08 + APECS_CONF; *value = conf_read(addr, type1) >> ((where & 3) * 8); return PCIBIOS_SUCCESSFUL; } -int -apecs_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value, - struct linux_hose_info *hose) +static int +apecs_read_config_dword(struct pci_dev *dev, int where, u32 *value) { - unsigned long addr = APECS_CONF; - unsigned long pci_addr; + unsigned long addr, pci_addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + if (mk_conf_addr(dev, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - addr |= (pci_addr << 5) + 0x18; + addr = (pci_addr << 5) + 0x18 + APECS_CONF; *value = conf_read(addr, type1); return PCIBIOS_SUCCESSFUL; } -int -apecs_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value, - struct linux_hose_info *hose) +static int +apecs_write_config(struct pci_dev *dev, int where, u32 value, long mask) { - unsigned long addr = APECS_CONF; - unsigned long pci_addr; + unsigned long addr, pci_addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + if (mk_conf_addr(dev, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - addr |= (pci_addr << 5) + 0x00; + addr = (pci_addr << 5) + mask + APECS_CONF; conf_write(addr, value << ((where & 3) * 8), type1); return PCIBIOS_SUCCESSFUL; } -int -apecs_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value, - struct linux_hose_info *hose) +static int +apecs_write_config_byte(struct pci_dev *dev, int where, u8 value) { - unsigned long addr = APECS_CONF; - unsigned long pci_addr; - unsigned char type1; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) - return PCIBIOS_DEVICE_NOT_FOUND; - - addr |= (pci_addr << 5) + 0x08; - conf_write(addr, value << ((where & 3) * 8), type1); - return PCIBIOS_SUCCESSFUL; + return apecs_write_config(dev, where, value, 0x00); } -int -apecs_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value, - struct linux_hose_info *hose) +static int +apecs_write_config_word(struct pci_dev *dev, int where, u16 value) { - unsigned long addr = APECS_CONF; - unsigned long pci_addr; - unsigned char type1; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) - return PCIBIOS_DEVICE_NOT_FOUND; + return apecs_write_config(dev, where, value, 0x08); +} - addr |= (pci_addr << 5) + 0x18; - conf_write(addr, value << ((where & 3) * 8), type1); - return PCIBIOS_SUCCESSFUL; +static int +apecs_write_config_dword(struct pci_dev *dev, int where, u32 value) +{ + return apecs_write_config(dev, where, value, 0x18); } +struct pci_ops apecs_pci_ops = +{ + read_byte: apecs_read_config_byte, + read_word: apecs_read_config_word, + read_dword: apecs_read_config_dword, + write_byte: apecs_write_config_byte, + write_word: apecs_write_config_word, + write_dword: apecs_write_config_dword +}; + void __init apecs_init_arch(unsigned long *mem_start, unsigned long *mem_end) { - switch (alpha_use_srm_setup) - { - default: -#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP) - /* Check window 1 for enabled and mapped to 0. */ - if ((*(vuip)APECS_IOC_PB1R & (1U<<19)) - && (*(vuip)APECS_IOC_TB1R == 0)) { - APECS_DMA_WIN_BASE = *(vuip)APECS_IOC_PB1R & 0xfff00000U; - APECS_DMA_WIN_SIZE = *(vuip)APECS_IOC_PM1R & 0xfff00000U; - APECS_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("apecs_init: using Window 1 settings\n"); - printk("apecs_init: PB1R 0x%x PM1R 0x%x TB1R 0x%x\n", - *(vuip)APECS_IOC_PB1R, - *(vuip)APECS_IOC_PM1R, - *(vuip)APECS_IOC_TB1R); -#endif - break; - } + struct pci_controler *hose; - /* Check window 2 for enabled and mapped to 0. */ - if ((*(vuip)APECS_IOC_PB2R & (1U<<19)) - && (*(vuip)APECS_IOC_TB2R == 0)) { - APECS_DMA_WIN_BASE = *(vuip)APECS_IOC_PB2R & 0xfff00000U; - APECS_DMA_WIN_SIZE = *(vuip)APECS_IOC_PM2R & 0xfff00000U; - APECS_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("apecs_init: using Window 2 settings\n"); - printk("apecs_init: PB2R 0x%x PM2R 0x%x TB2R 0x%x\n", - *(vuip)APECS_IOC_PB2R, - *(vuip)APECS_IOC_PM2R, - *(vuip)APECS_IOC_TB2R); -#endif - break; - } - - /* Otherwise, we must use our defaults. */ - APECS_DMA_WIN_BASE = APECS_DMA_WIN_BASE_DEFAULT; - APECS_DMA_WIN_SIZE = APECS_DMA_WIN_SIZE_DEFAULT; -#endif - case 0: - /* - * Set up the PCI->physical memory translation windows. - * For now, window 2 is disabled. In the future, we may - * want to use it to do scatter/gather DMA. Window 1 - * goes at 1 GB and is 1 GB large. - */ - *(vuip)APECS_IOC_PB2R = 0U; /* disable window 2 */ - - *(vuip)APECS_IOC_PB1R = 1U<<19 | (APECS_DMA_WIN_BASE_DEFAULT & 0xfff00000U); - *(vuip)APECS_IOC_PM1R = (APECS_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U; - *(vuip)APECS_IOC_TB1R = 0; - break; - } + /* + * Set up the PCI->physical memory translation windows. + * For now, window 2 is disabled. In the future, we may + * want to use it to do scatter/gather DMA. Window 1 + * goes at 1 GB and is 1 GB large. + */ + *(vuip)APECS_IOC_PB1R = 1UL << 19 | (APECS_DMA_WIN_BASE & 0xfff00000U); + *(vuip)APECS_IOC_PM1R = (APECS_DMA_WIN_SIZE - 1) & 0xfff00000U; + *(vuip)APECS_IOC_TB1R = 0; + + *(vuip)APECS_IOC_PB2R = 0U; /* disable window 2 */ /* * Finally, clear the HAXR2 register, which gets used @@ -435,23 +380,35 @@ apecs_init_arch(unsigned long *mem_start, unsigned long *mem_end) * we want to use it, and we do not want to depend on * what ARC or SRM might have left behind... */ - *(vuip)APECS_IOC_HAXR2 = 0; mb(); + *(vuip)APECS_IOC_HAXR2 = 0; + mb(); + + /* + * Create our single hose. + */ + + hose = alloc_pci_controler(mem_start); + hose->io_space = &ioport_resource; + hose->mem_space = &iomem_resource; + hose->config_space = APECS_CONF; + hose->index = 0; } -int +void apecs_pci_clr_err(void) { - apecs_jd = *(vuip)APECS_IOC_DCSR; - if (apecs_jd & 0xffe0L) { - apecs_jd1 = *(vuip)APECS_IOC_SEAR; - *(vuip)APECS_IOC_DCSR = apecs_jd | 0xffe1L; - apecs_jd = *(vuip)APECS_IOC_DCSR; + unsigned int jd; + + jd = *(vuip)APECS_IOC_DCSR; + if (jd & 0xffe0L) { + *(vuip)APECS_IOC_SEAR; + *(vuip)APECS_IOC_DCSR = jd | 0xffe1L; mb(); + *(vuip)APECS_IOC_DCSR; } *(vuip)APECS_IOC_TBIA = (unsigned int)APECS_IOC_TBIA; - apecs_jd2 = *(vuip)APECS_IOC_TBIA; mb(); - return 0; + *(vuip)APECS_IOC_TBIA; } void @@ -461,8 +418,6 @@ apecs_machine_check(unsigned long vector, unsigned long la_ptr, struct el_common *mchk_header; struct el_apecs_procdata *mchk_procdata; struct el_apecs_sysdata_mcheck *mchk_sysdata; - unsigned long *ptr; - int i; mchk_header = (struct el_common *)la_ptr; @@ -473,66 +428,16 @@ apecs_machine_check(unsigned long vector, unsigned long la_ptr, mchk_sysdata = (struct el_apecs_sysdata_mcheck *) (la_ptr + mchk_header->sys_offset); -#ifdef DEBUG - printk("apecs_machine_check: vector=0x%lx la_ptr=0x%lx\n", - vector, la_ptr); - printk(" pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", - regs->pc, mchk_header->size, mchk_header->proc_offset, - mchk_header->sys_offset); - printk("apecs_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n", - apecs_mcheck_expected, mchk_sysdata->epic_dcsr, - mchk_sysdata->epic_pear); - ptr = (unsigned long *)la_ptr; - for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { - printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]); - } -#endif - /* - * Check if machine check is due to a badaddr() and if so, - * ignore the machine check. - */ + /* Clear the error before any reporting. */ + mb(); + mb(); /* magic */ + draina(); + apecs_pci_clr_err(); + wrmces(0x7); /* reset machine check pending flag */ + mb(); - if (apecs_mcheck_expected - && (mchk_sysdata->epic_dcsr & 0x0c00UL)) { - apecs_mcheck_expected = 0; - apecs_mcheck_taken = 1; - mb(); - mb(); /* magic */ - apecs_pci_clr_err(); - wrmces(0x7); - mb(); - draina(); - DBG(("apecs_machine_check: EXPECTED\n")); - } - else if (vector == 0x620 || vector == 0x630) { - /* Disable correctable from now on. */ - wrmces(0x1f); - mb(); - draina(); - printk("apecs_machine_check: HW correctable (0x%lx)\n", - vector); - } - else { - printk(KERN_CRIT "APECS machine check:\n"); - printk(KERN_CRIT " vector=0x%lx la_ptr=0x%lx\n", - vector, la_ptr); - printk(KERN_CRIT - " pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", - regs->pc, mchk_header->size, mchk_header->proc_offset, - mchk_header->sys_offset); - printk(KERN_CRIT " expected %d DCSR 0x%lx PEAR 0x%lx\n", - apecs_mcheck_expected, mchk_sysdata->epic_dcsr, - mchk_sysdata->epic_pear); - - ptr = (unsigned long *)la_ptr; - for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { - printk(KERN_CRIT " +%lx %lx %lx\n", - i*sizeof(long), ptr[i], ptr[i+1]); - } -#if 0 - /* doesn't work with MILO */ - show_regs(regs); -#endif - } + process_mcheck_info(vector, la_ptr, regs, "APECS", + (mcheck_expected(0) + && (mchk_sysdata->epic_dcsr & 0x0c00UL))); } diff --git a/arch/alpha/kernel/core_cia.c b/arch/alpha/kernel/core_cia.c index eef315826..5821db09d 100644 --- a/arch/alpha/kernel/core_cia.c +++ b/arch/alpha/kernel/core_cia.c @@ -1,14 +1,17 @@ /* * linux/arch/alpha/kernel/core_cia.c * - * Code common to all CIA core logic chips. - * * Written by David A Rusling (david.rusling@reo.mts.dec.com). * December 1995. * + * Copyright (C) 1995 David A Rusling + * Copyright (C) 1997, 1998 Jay Estabrook + * Copyright (C) 1998, 1999 Richard Henderson + * + * Code common to all CIA core logic chips. */ + #include <linux/kernel.h> -#include <linux/config.h> #include <linux/types.h> #include <linux/pci.h> #include <linux/sched.h> @@ -16,6 +19,7 @@ #include <asm/system.h> #include <asm/ptrace.h> +#include <asm/pci.h> #define __EXTERN_INLINE inline #include <asm/io.h> @@ -23,6 +27,8 @@ #undef __EXTERN_INLINE #include "proto.h" +#include "pci_impl.h" + /* * NOTE: Herein lie back-to-back mb instructions. They are magic. @@ -31,30 +37,12 @@ */ /* - * Machine check reasons. Defined according to PALcode sources - * (osf.h and platform.h). - */ -#define MCHK_K_TPERR 0x0080 -#define MCHK_K_TCPERR 0x0082 -#define MCHK_K_HERR 0x0084 -#define MCHK_K_ECC_C 0x0086 -#define MCHK_K_ECC_NC 0x0088 -#define MCHK_K_OS_BUGCHECK 0x008A -#define MCHK_K_PAL_BUGCHECK 0x0090 - -/* * BIOS32-style PCI interface: */ -#define DEBUG_MCHECK 0 #define DEBUG_CONFIG 0 -/* #define DEBUG_DUMP_REGS */ +#define DEBUG_DUMP_REGS 0 -#if DEBUG_MCHECK -# define DBGM(args) printk args -#else -# define DBGM(args) -#endif #if DEBUG_CONFIG # define DBGC(args) printk args #else @@ -63,11 +51,6 @@ #define vuip volatile unsigned int * -static volatile unsigned int CIA_mcheck_expected = 0; -static volatile unsigned int CIA_mcheck_taken = 0; -static unsigned int CIA_jd; - - /* * Given a bus, device, and function number, compute resulting * configuration space address and setup the CIA_HAXR2 register @@ -111,10 +94,12 @@ static unsigned int CIA_jd; */ static int -mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr, +mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr, unsigned char *type1) { unsigned long addr; + u8 bus = dev->bus->number; + u8 device_fn = dev->devfn; DBGC(("mk_conf_addr(bus=%d, device_fn=0x%x, where=0x%x, " "pci_addr=0x%p, type1=0x%p)\n", @@ -173,46 +158,22 @@ conf_read(unsigned long addr, unsigned char type1) mb(); draina(); - CIA_mcheck_expected = 1; - CIA_mcheck_taken = 0; + mcheck_expected(0) = 1; + mcheck_taken(0) = 0; mb(); /* Access configuration space. */ value = *(vuip)addr; mb(); mb(); /* magic */ - if (CIA_mcheck_taken) { - CIA_mcheck_taken = 0; + if (mcheck_taken(0)) { + mcheck_taken(0) = 0; value = 0xffffffffU; mb(); } - CIA_mcheck_expected = 0; + mcheck_expected(0) = 0; mb(); -#if 0 - /* This code might be necessary if machine checks aren't taken, - but I can't get it to work on CIA-2, so its disabled. */ - draina(); - - /* Now look for any errors. */ - stat0 = *(vuip)CIA_IOC_CIA_ERR; - DBGC(("conf_read: CIA ERR after read 0x%x\n", stat0)); - - /* Is any error bit set? */ - if (stat0 & 0x8FEF0FFFU) { - /* If not MAS_ABT, print status. */ - if (!(stat0 & 0x0080)) { - printk("CIA.c:conf_read: got stat0=%x\n", stat0); - } - - /* reset error status: */ - *(vuip)CIA_IOC_CIA_ERR = stat0; - mb(); - wrmces(0x7); /* reset machine check */ - value = 0xffffffff; - } -#endif - /* If Type1 access, must reset IOC CFG so normal IO space ops work. */ if (type1) { *(vuip)CIA_IOC_CFG = cia_cfg & ~1; @@ -249,7 +210,7 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1) } draina(); - CIA_mcheck_expected = 1; + mcheck_expected(0) = 1; mb(); /* Access configuration space. */ @@ -257,33 +218,9 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1) mb(); mb(); /* magic */ - CIA_mcheck_expected = 0; + mcheck_expected(0) = 0; mb(); -#if 0 - /* This code might be necessary if machine checks aren't taken, - but I can't get it to work on CIA-2, so its disabled. */ - draina(); - - /* Now look for any errors */ - stat0 = *(vuip)CIA_IOC_CIA_ERR; - DBGC(("conf_write: CIA ERR after write 0x%x\n", stat0)); - - /* Is any error bit set? */ - if (stat0 & 0x8FEF0FFFU) { - /* If not MAS_ABT, print status */ - if (!(stat0 & 0x0080)) { - printk("CIA.c:conf_read: got stat0=%x\n", stat0); - } - - /* Reset error status. */ - *(vuip)CIA_IOC_CIA_ERR = stat0; - mb(); - wrmces(0x7); /* reset machine check */ - value = 0xffffffff; - } -#endif - /* If Type1 access, must reset IOC CFG so normal IO space ops work. */ if (type1) { *(vuip)CIA_IOC_CFG = cia_cfg & ~1; @@ -294,260 +231,179 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1) __restore_flags(flags); } -int -cia_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value, - struct linux_hose_info *hose) +static int +cia_read_config_byte(struct pci_dev *dev, int where, u8 *value) { - unsigned long addr = CIA_CONF; - unsigned long pci_addr; + unsigned long addr, pci_addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + if (mk_conf_addr(dev, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - addr |= (pci_addr << 5) + 0x00; + addr = (pci_addr << 5) + 0x00 + CIA_CONF; *value = conf_read(addr, type1) >> ((where & 3) * 8); return PCIBIOS_SUCCESSFUL; } -int -cia_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value, - struct linux_hose_info *hose) +static int +cia_read_config_word(struct pci_dev *dev, int where, u16 *value) { - unsigned long addr = CIA_CONF; - unsigned long pci_addr; + unsigned long addr, pci_addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + if (mk_conf_addr(dev, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - addr |= (pci_addr << 5) + 0x08; + addr = (pci_addr << 5) + 0x08 + CIA_CONF; *value = conf_read(addr, type1) >> ((where & 3) * 8); return PCIBIOS_SUCCESSFUL; } -int -cia_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value, - struct linux_hose_info *hose) +static int +cia_read_config_dword(struct pci_dev *dev, int where, u32 *value) { - unsigned long addr = CIA_CONF; - unsigned long pci_addr; + unsigned long addr, pci_addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + if (mk_conf_addr(dev, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - addr |= (pci_addr << 5) + 0x18; + addr = (pci_addr << 5) + 0x18 + CIA_CONF; *value = conf_read(addr, type1); return PCIBIOS_SUCCESSFUL; } -int -cia_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value, - struct linux_hose_info *hose) +static int +cia_write_config(struct pci_dev *dev, int where, u32 value, long mask) { - unsigned long addr = CIA_CONF; - unsigned long pci_addr; + unsigned long addr, pci_addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + if (mk_conf_addr(dev, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - addr |= (pci_addr << 5) + 0x00; + addr = (pci_addr << 5) + mask + CIA_CONF; conf_write(addr, value << ((where & 3) * 8), type1); return PCIBIOS_SUCCESSFUL; } -int -cia_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value, - struct linux_hose_info *hose) +static int +cia_write_config_byte(struct pci_dev *dev, int where, u8 value) { - unsigned long addr = CIA_CONF; - unsigned long pci_addr; - unsigned char type1; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) - return PCIBIOS_DEVICE_NOT_FOUND; - - addr |= (pci_addr << 5) + 0x08; - conf_write(addr, value << ((where & 3) * 8), type1); - return PCIBIOS_SUCCESSFUL; + return cia_write_config(dev, where, value, 0x00); } -int -cia_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value, - struct linux_hose_info *hose) +static int +cia_write_config_word(struct pci_dev *dev, int where, u16 value) { - unsigned long addr = CIA_CONF; - unsigned long pci_addr; - unsigned char type1; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) - return PCIBIOS_DEVICE_NOT_FOUND; + return cia_write_config(dev, where, value, 0x08); +} - addr |= (pci_addr << 5) + 0x18; - conf_write(addr, value << ((where & 3) * 8), type1); - return PCIBIOS_SUCCESSFUL; +static int +cia_write_config_dword(struct pci_dev *dev, int where, u32 value) +{ + return cia_write_config(dev, where, value, 0x18); } +struct pci_ops cia_pci_ops = +{ + read_byte: cia_read_config_byte, + read_word: cia_read_config_word, + read_dword: cia_read_config_dword, + write_byte: cia_write_config_byte, + write_word: cia_write_config_word, + write_dword: cia_write_config_dword +}; + void __init cia_init_arch(unsigned long *mem_start, unsigned long *mem_end) { - unsigned int cia_tmp; - -#ifdef DEBUG_DUMP_REGS - { - unsigned int temp; - temp = *(vuip)CIA_IOC_CIA_REV; mb(); - printk("cia_init: CIA_REV was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_PCI_LAT; mb(); - printk("cia_init: CIA_PCI_LAT was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_CIA_CTRL; mb(); - printk("cia_init: CIA_CTRL was 0x%x\n", temp); - temp = *(vuip)0xfffffc8740000140UL; mb(); - printk("cia_init: CIA_CTRL1 was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_HAE_MEM; mb(); - printk("cia_init: CIA_HAE_MEM was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_HAE_IO; mb(); - printk("cia_init: CIA_HAE_IO was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_CFG; mb(); - printk("cia_init: CIA_CFG was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_CACK_EN; mb(); - printk("cia_init: CIA_CACK_EN was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_CFG; mb(); - printk("cia_init: CIA_CFG was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_CIA_DIAG; mb(); - printk("cia_init: CIA_DIAG was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_DIAG_CHECK; mb(); - printk("cia_init: CIA_DIAG_CHECK was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_PERF_MONITOR; mb(); - printk("cia_init: CIA_PERF_MONITOR was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_PERF_CONTROL; mb(); - printk("cia_init: CIA_PERF_CONTROL was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_CIA_ERR; mb(); - printk("cia_init: CIA_ERR was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_CIA_STAT; mb(); - printk("cia_init: CIA_STAT was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_MCR; mb(); - printk("cia_init: CIA_MCR was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_CIA_CTRL; mb(); - printk("cia_init: CIA_CTRL was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_ERR_MASK; mb(); - printk("cia_init: CIA_ERR_MASK was 0x%x\n", temp); - temp = *((vuip)CIA_IOC_PCI_W0_BASE); mb(); - printk("cia_init: W0_BASE was 0x%x\n", temp); - temp = *((vuip)CIA_IOC_PCI_W1_BASE); mb(); - printk("cia_init: W1_BASE was 0x%x\n", temp); - temp = *((vuip)CIA_IOC_PCI_W2_BASE); mb(); - printk("cia_init: W2_BASE was 0x%x\n", temp); - temp = *((vuip)CIA_IOC_PCI_W3_BASE); mb(); - printk("cia_init: W3_BASE was 0x%x\n", temp); - } + struct pci_controler *hose; + struct resource *hae_mem; + unsigned int temp; + +#if DEBUG_DUMP_REGS + temp = *(vuip)CIA_IOC_CIA_REV; mb(); + printk("cia_init: CIA_REV was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_PCI_LAT; mb(); + printk("cia_init: CIA_PCI_LAT was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_CIA_CTRL; mb(); + printk("cia_init: CIA_CTRL was 0x%x\n", temp); + temp = *(vuip)0xfffffc8740000140UL; mb(); + printk("cia_init: CIA_CTRL1 was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_HAE_MEM; mb(); + printk("cia_init: CIA_HAE_MEM was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_HAE_IO; mb(); + printk("cia_init: CIA_HAE_IO was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_CFG; mb(); + printk("cia_init: CIA_CFG was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_CACK_EN; mb(); + printk("cia_init: CIA_CACK_EN was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_CFG; mb(); + printk("cia_init: CIA_CFG was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_CIA_DIAG; mb(); + printk("cia_init: CIA_DIAG was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_DIAG_CHECK; mb(); + printk("cia_init: CIA_DIAG_CHECK was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_PERF_MONITOR; mb(); + printk("cia_init: CIA_PERF_MONITOR was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_PERF_CONTROL; mb(); + printk("cia_init: CIA_PERF_CONTROL was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_CIA_ERR; mb(); + printk("cia_init: CIA_ERR was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_CIA_STAT; mb(); + printk("cia_init: CIA_STAT was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_MCR; mb(); + printk("cia_init: CIA_MCR was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_CIA_CTRL; mb(); + printk("cia_init: CIA_CTRL was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_ERR_MASK; mb(); + printk("cia_init: CIA_ERR_MASK was 0x%x\n", temp); + temp = *((vuip)CIA_IOC_PCI_W0_BASE); mb(); + printk("cia_init: W0_BASE was 0x%x\n", temp); + temp = *((vuip)CIA_IOC_PCI_W1_BASE); mb(); + printk("cia_init: W1_BASE was 0x%x\n", temp); + temp = *((vuip)CIA_IOC_PCI_W2_BASE); mb(); + printk("cia_init: W2_BASE was 0x%x\n", temp); + temp = *((vuip)CIA_IOC_PCI_W3_BASE); mb(); + printk("cia_init: W3_BASE was 0x%x\n", temp); #endif /* DEBUG_DUMP_REGS */ /* * Set up error reporting. */ - cia_tmp = *(vuip)CIA_IOC_CIA_ERR; - cia_tmp |= 0x180; /* master, target abort */ - *(vuip)CIA_IOC_CIA_ERR = cia_tmp; + temp = *(vuip)CIA_IOC_CIA_ERR; + temp |= 0x180; /* master, target abort */ + *(vuip)CIA_IOC_CIA_ERR = temp; mb(); - cia_tmp = *(vuip)CIA_IOC_CIA_CTRL; - cia_tmp |= 0x400; /* turn on FILL_ERR to get mchecks */ - *(vuip)CIA_IOC_CIA_CTRL = cia_tmp; + temp = *(vuip)CIA_IOC_CIA_CTRL; + temp |= 0x400; /* turn on FILL_ERR to get mchecks */ + *(vuip)CIA_IOC_CIA_CTRL = temp; mb(); - switch (alpha_use_srm_setup) - { - default: -#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP) - /* Check window 0 for enabled and mapped to 0 */ - if (((*(vuip)CIA_IOC_PCI_W0_BASE & 3) == 1) - && (*(vuip)CIA_IOC_PCI_T0_BASE == 0)) { - CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W0_BASE & 0xfff00000U; - CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W0_MASK & 0xfff00000U; - CIA_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("cia_init: using Window 0 settings\n"); - printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vuip)CIA_IOC_PCI_W0_BASE, - *(vuip)CIA_IOC_PCI_W0_MASK, - *(vuip)CIA_IOC_PCI_T0_BASE); -#endif - break; - } - - /* Check window 1 for enabled and mapped to 0. */ - if (((*(vuip)CIA_IOC_PCI_W1_BASE & 3) == 1) - && (*(vuip)CIA_IOC_PCI_T1_BASE == 0)) { - CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W1_BASE & 0xfff00000U; - CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W1_MASK & 0xfff00000U; - CIA_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("cia_init: using Window 1 settings\n"); - printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vuip)CIA_IOC_PCI_W1_BASE, - *(vuip)CIA_IOC_PCI_W1_MASK, - *(vuip)CIA_IOC_PCI_T1_BASE); -#endif - break; - } - - /* Check window 2 for enabled and mapped to 0. */ - if (((*(vuip)CIA_IOC_PCI_W2_BASE & 3) == 1) - && (*(vuip)CIA_IOC_PCI_T2_BASE == 0)) { - CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W2_BASE & 0xfff00000U; - CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W2_MASK & 0xfff00000U; - CIA_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("cia_init: using Window 2 settings\n"); - printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vuip)CIA_IOC_PCI_W2_BASE, - *(vuip)CIA_IOC_PCI_W2_MASK, - *(vuip)CIA_IOC_PCI_T2_BASE); -#endif - break; - } - - /* Check window 3 for enabled and mapped to 0. */ - if (((*(vuip)CIA_IOC_PCI_W3_BASE & 3) == 1) - && (*(vuip)CIA_IOC_PCI_T3_BASE == 0)) { - CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W3_BASE & 0xfff00000U; - CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W3_MASK & 0xfff00000U; - CIA_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("cia_init: using Window 3 settings\n"); - printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vuip)CIA_IOC_PCI_W3_BASE, - *(vuip)CIA_IOC_PCI_W3_MASK, - *(vuip)CIA_IOC_PCI_T3_BASE); -#endif - break; - } + /* + * Set up the PCI->physical memory translation windows. + * For now, windows 2 and 3 are disabled. In the future, + * we may want to use them to do scatter/gather DMA. + * + * Window 0 goes at 1 GB and is 1 GB large. + * Window 1 goes at 2 GB and is 1 GB large. + */ - /* Otherwise, we must use our defaults. */ - CIA_DMA_WIN_BASE = CIA_DMA_WIN_BASE_DEFAULT; - CIA_DMA_WIN_SIZE = CIA_DMA_WIN_SIZE_DEFAULT; -#endif - case 0: - /* - * Set up the PCI->physical memory translation windows. - * For now, windows 1,2 and 3 are disabled. In the future, - * we may want to use them to do scatter/gather DMA. - * - * Window 0 goes at 1 GB and is 1 GB large. - */ - - *(vuip)CIA_IOC_PCI_W0_BASE = 1U | (CIA_DMA_WIN_BASE_DEFAULT & 0xfff00000U); - *(vuip)CIA_IOC_PCI_W0_MASK = (CIA_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U; - *(vuip)CIA_IOC_PCI_T0_BASE = 0; - - *(vuip)CIA_IOC_PCI_W1_BASE = 0x0; - *(vuip)CIA_IOC_PCI_W2_BASE = 0x0; - *(vuip)CIA_IOC_PCI_W3_BASE = 0x0; - break; - } + *(vuip)CIA_IOC_PCI_W0_BASE = CIA_DMA_WIN0_BASE_DEFAULT | 1U; + *(vuip)CIA_IOC_PCI_W0_MASK = (CIA_DMA_WIN0_SIZE_DEFAULT - 1) & + 0xfff00000U; + *(vuip)CIA_IOC_PCI_T0_BASE = CIA_DMA_WIN0_TRAN_DEFAULT >> 2; + + *(vuip)CIA_IOC_PCI_W1_BASE = CIA_DMA_WIN1_BASE_DEFAULT | 1U; + *(vuip)CIA_IOC_PCI_W1_MASK = (CIA_DMA_WIN1_SIZE_DEFAULT - 1) & + 0xfff00000U; + *(vuip)CIA_IOC_PCI_T1_BASE = CIA_DMA_WIN1_TRAN_DEFAULT >> 2; + + *(vuip)CIA_IOC_PCI_W2_BASE = 0x0; + *(vuip)CIA_IOC_PCI_W3_BASE = 0x0; + mb(); /* * Next, clear the CIA_CFG register, which gets used @@ -557,164 +413,55 @@ cia_init_arch(unsigned long *mem_start, unsigned long *mem_end) */ *((vuip)CIA_IOC_CFG) = 0; mb(); + /* + * Zero the HAEs. + */ + *((vuip)CIA_IOC_HAE_MEM) = 0; mb(); + *((vuip)CIA_IOC_HAE_MEM); /* read it back. */ + *((vuip)CIA_IOC_HAE_IO) = 0; mb(); + *((vuip)CIA_IOC_HAE_IO); /* read it back. */ /* - * Sigh... For the SRM setup, unless we know apriori what the HAE - * contents will be, we need to setup the arbitrary region bases - * so we can test against the range of addresses and tailor the - * region chosen for the SPARSE memory access. - * - * See include/asm-alpha/cia.h for the SPARSE mem read/write. + * Create our single hose. */ - if (alpha_use_srm_setup) { - unsigned int cia_hae_mem = *((vuip)CIA_IOC_HAE_MEM); - - alpha_mv.sm_base_r1 = (cia_hae_mem ) & 0xe0000000UL; - alpha_mv.sm_base_r2 = (cia_hae_mem << 16) & 0xf8000000UL; - alpha_mv.sm_base_r3 = (cia_hae_mem << 24) & 0xfc000000UL; - - /* - * Set the HAE cache, so that setup_arch() code - * will use the SRM setting always. Our readb/writeb - * code in cia.h expects never to have to change - * the contents of the HAE. - */ - alpha_mv.hae_cache = cia_hae_mem; - - alpha_mv.mv_readb = cia_srm_readb; - alpha_mv.mv_readw = cia_srm_readw; - alpha_mv.mv_writeb = cia_srm_writeb; - alpha_mv.mv_writew = cia_srm_writew; - } else { - *((vuip)CIA_IOC_HAE_MEM) = 0; mb(); - *((vuip)CIA_IOC_HAE_MEM); /* read it back. */ - *((vuip)CIA_IOC_HAE_IO) = 0; mb(); - *((vuip)CIA_IOC_HAE_IO); /* read it back. */ - } + + hose = alloc_pci_controler(mem_start); + hae_mem = alloc_resource(mem_start); + + hose->io_space = &ioport_resource; + hose->mem_space = hae_mem; + hose->config_space = CIA_CONF; + hose->index = 0; + + hae_mem->start = 0; + hae_mem->end = CIA_MEM_R1_MASK; + hae_mem->name = pci_hae0_name; + + request_resource(&iomem_resource, hae_mem); } -static int +static inline void cia_pci_clr_err(void) { - CIA_jd = *(vuip)CIA_IOC_CIA_ERR; - DBGM(("CIA_pci_clr_err: CIA ERR after read 0x%x\n", CIA_jd)); - *(vuip)CIA_IOC_CIA_ERR = CIA_jd; + unsigned int jd; + + jd = *(vuip)CIA_IOC_CIA_ERR; + *(vuip)CIA_IOC_CIA_ERR = jd; mb(); - return 0; + *(vuip)CIA_IOC_CIA_ERR; /* re-read to force write. */ } void cia_machine_check(unsigned long vector, unsigned long la_ptr, struct pt_regs * regs) { - struct el_common *mchk_header; - struct el_CIA_procdata *mchk_procdata; - struct el_CIA_sysdata_mcheck *mchk_sysdata; - unsigned long * ptr; - const char * reason; - char buf[128]; - long i; - - mchk_header = (struct el_common *)la_ptr; - - mchk_procdata = (struct el_CIA_procdata *) - (la_ptr + mchk_header->proc_offset); - - mchk_sysdata = (struct el_CIA_sysdata_mcheck *) - (la_ptr + mchk_header->sys_offset); - - DBGM(("cia_machine_check: vector=0x%lx la_ptr=0x%lx\n", - vector, la_ptr)); - DBGM((" pc=0x%lx size=0x%x procoffset=0x%x " - "sysoffset 0x%x\n", regs->pc, mchk_header->size, - mchk_header->proc_offset, mchk_header->sys_offset)); - DBGM(("cia_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n", - CIA_mcheck_expected, mchk_sysdata->epic_dcsr, - mchk_sysdata->epic_pear)); - -#if DEBUG_MCHECK - { - unsigned long *ptr; - int i; - - ptr = (unsigned long *)la_ptr; - for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { - printk(" +%lx %lx %lx\n", i*sizeof(long), - ptr[i], ptr[i+1]); - } - } -#endif - - /* - * Check if machine check is due to a badaddr() and if so, - * ignore the machine check. - */ - mb(); - mb(); /* magic */ - if (CIA_mcheck_expected) { - DBGM(("CIA machine check expected\n")); - CIA_mcheck_expected = 0; - CIA_mcheck_taken = 1; - mb(); - mb(); /* magic */ - draina(); - cia_pci_clr_err(); - wrmces(0x7); - mb(); - return; - } - - switch ((unsigned int) mchk_header->code) { - case MCHK_K_TPERR: reason = "tag parity error"; break; - case MCHK_K_TCPERR: reason = "tag control parity error"; break; - case MCHK_K_HERR: reason = "generic hard error"; break; - case MCHK_K_ECC_C: reason = "correctable ECC error"; break; - case MCHK_K_ECC_NC: reason = "uncorrectable ECC error"; break; - case MCHK_K_OS_BUGCHECK: reason = "OS-specific PAL bugcheck"; break; - case MCHK_K_PAL_BUGCHECK: reason = "callsys in kernel mode"; break; - case 0x96: reason = "i-cache read retryable error"; break; - case 0x98: reason = "processor detected hard error"; break; - - /* System specific (these are for Alcor, at least): */ - case 0x203: reason = "system detected uncorrectable ECC error"; break; - case 0x205: reason = "parity error detected by CIA"; break; - case 0x207: reason = "non-existent memory error"; break; - case 0x209: reason = "PCI SERR detected"; break; - case 0x20b: reason = "PCI data parity error detected"; break; - case 0x20d: reason = "PCI address parity error detected"; break; - case 0x20f: reason = "PCI master abort error"; break; - case 0x211: reason = "PCI target abort error"; break; - case 0x213: reason = "scatter/gather PTE invalid error"; break; - case 0x215: reason = "flash ROM write error"; break; - case 0x217: reason = "IOA timeout detected"; break; - case 0x219: reason = "IOCHK#, EISA add-in board parity or other catastrophic error"; break; - case 0x21b: reason = "EISA fail-safe timer timeout"; break; - case 0x21d: reason = "EISA bus time-out"; break; - case 0x21f: reason = "EISA software generated NMI"; break; - case 0x221: reason = "unexpected ev5 IRQ[3] interrupt"; break; - default: - sprintf(buf, "reason for machine-check unknown (0x%x)", - (unsigned int) mchk_header->code); - reason = buf; - break; - } + /* Clear the error before any reporting. */ mb(); mb(); /* magic */ draina(); cia_pci_clr_err(); - wrmces(rdmces()); /* reset machine check pending flag */ + wrmces(rdmces()); /* reset machine check pending flag. */ mb(); - printk(KERN_CRIT "CIA machine check: %s%s\n", - reason, mchk_header->retry ? " (retryable)" : ""); - printk(KERN_CRIT " vector=0x%lx la_ptr=0x%lx pc=0x%lx\n", - vector, la_ptr, regs->pc); - - /* Dump the logout area to give all info. */ - - ptr = (unsigned long *)la_ptr; - for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { - printk(KERN_CRIT " +%8lx %016lx %016lx\n", - i*sizeof(long), ptr[i], ptr[i+1]); - } + process_mcheck_info(vector, la_ptr, regs, "CIA", mcheck_expected(0)); } diff --git a/arch/alpha/kernel/core_lca.c b/arch/alpha/kernel/core_lca.c index 8a529f27a..13172b708 100644 --- a/arch/alpha/kernel/core_lca.c +++ b/arch/alpha/kernel/core_lca.c @@ -1,14 +1,14 @@ /* * linux/arch/alpha/kernel/core_lca.c * - * Code common to all LCA core logic chips. - * * Written by David Mosberger (davidm@cs.arizona.edu) with some code * taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit * bios code. + * + * Code common to all LCA core logic chips. */ + #include <linux/kernel.h> -#include <linux/config.h> #include <linux/types.h> #include <linux/pci.h> #include <linux/init.h> @@ -17,6 +17,7 @@ #include <asm/ptrace.h> #include <asm/system.h> #include <asm/smp.h> +#include <asm/pci.h> #define __EXTERN_INLINE inline #include <asm/io.h> @@ -24,6 +25,8 @@ #undef __EXTERN_INLINE #include "proto.h" +#include "pci_impl.h" + /* * BIOS32-style PCI interface: @@ -97,9 +100,11 @@ */ static int -mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr) +mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr) { unsigned long addr; + u8 bus = dev->bus->number; + u8 device_fn = dev->devfn; if (bus == 0) { int device = device_fn >> 3; @@ -194,154 +199,103 @@ conf_write(unsigned long addr, unsigned int value) __restore_flags(flags); } -int -lca_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value, - struct linux_hose_info *hose) +static int +lca_read_config_byte(struct pci_dev *dev, int where, u8 *value) { - unsigned long addr = LCA_CONF; - unsigned long pci_addr; + unsigned long addr, pci_addr; - if (mk_conf_addr(bus, device_fn, where, &pci_addr)) + if (mk_conf_addr(dev, where, &pci_addr)) return PCIBIOS_DEVICE_NOT_FOUND; - addr |= (pci_addr << 5) + 0x00; + addr = (pci_addr << 5) + 0x00 + LCA_CONF; *value = conf_read(addr) >> ((where & 3) * 8); return PCIBIOS_SUCCESSFUL; } -int -lca_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value, - struct linux_hose_info *hose) +static int +lca_read_config_word(struct pci_dev *dev, int where, u16 *value) { - unsigned long addr = LCA_CONF; - unsigned long pci_addr; + unsigned long addr, pci_addr; - if (mk_conf_addr(bus, device_fn, where, &pci_addr)) + if (mk_conf_addr(dev, where, &pci_addr)) return PCIBIOS_DEVICE_NOT_FOUND; - addr |= (pci_addr << 5) + 0x08; + addr = (pci_addr << 5) + 0x08 + LCA_CONF; *value = conf_read(addr) >> ((where & 3) * 8); return PCIBIOS_SUCCESSFUL; } -int -lca_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value, - struct linux_hose_info *hose) +static int +lca_read_config_dword(struct pci_dev *dev, int where, u32 *value) { - unsigned long addr = LCA_CONF; - unsigned long pci_addr; + unsigned long addr, pci_addr; - if (mk_conf_addr(bus, device_fn, where, &pci_addr)) + if (mk_conf_addr(dev, where, &pci_addr)) return PCIBIOS_DEVICE_NOT_FOUND; - addr |= (pci_addr << 5) + 0x18; + addr = (pci_addr << 5) + 0x18 + LCA_CONF; *value = conf_read(addr); return PCIBIOS_SUCCESSFUL; } -int -lca_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value, - struct linux_hose_info *hose) +static int +lca_write_config(struct pci_dev *dev, int where, u32 value, long mask) { - unsigned long addr = LCA_CONF; - unsigned long pci_addr; + unsigned long addr, pci_addr; - if (mk_conf_addr(bus, device_fn, where, &pci_addr)) + if (mk_conf_addr(dev, where, &pci_addr)) return PCIBIOS_DEVICE_NOT_FOUND; - addr |= (pci_addr << 5) + 0x00; + addr = (pci_addr << 5) + mask + LCA_CONF; conf_write(addr, value << ((where & 3) * 8)); return PCIBIOS_SUCCESSFUL; } -int -lca_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value, - struct linux_hose_info *hose) +static int +lca_write_config_byte(struct pci_dev *dev, int where, u8 value) { - unsigned long addr = LCA_CONF; - unsigned long pci_addr; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr)) - return PCIBIOS_DEVICE_NOT_FOUND; - - addr |= (pci_addr << 5) + 0x08; - conf_write(addr, value << ((where & 3) * 8)); - return PCIBIOS_SUCCESSFUL; + return lca_write_config(dev, where, value, 0x00); } -int -lca_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value, - struct linux_hose_info *hose) +static int +lca_write_config_word(struct pci_dev *dev, int where, u16 value) { - unsigned long addr = LCA_CONF; - unsigned long pci_addr; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr)) - return PCIBIOS_DEVICE_NOT_FOUND; + return lca_write_config(dev, where, value, 0x08); +} - addr |= (pci_addr << 5) + 0x18; - conf_write(addr, value << ((where & 3) * 8)); - return PCIBIOS_SUCCESSFUL; +static int +lca_write_config_dword(struct pci_dev *dev, int where, u32 value) +{ + return lca_write_config(dev, where, value, 0x18); } +struct pci_ops lca_pci_ops = +{ + read_byte: lca_read_config_byte, + read_word: lca_read_config_word, + read_dword: lca_read_config_dword, + write_byte: lca_write_config_byte, + write_word: lca_write_config_word, + write_dword: lca_write_config_dword +}; + void __init lca_init_arch(unsigned long *mem_start, unsigned long *mem_end) { - switch (alpha_use_srm_setup) - { - default: -#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP) - /* Check window 0 for enabled and mapped to 0. */ - if ((*(vulp)LCA_IOC_W_BASE0 & (1UL<<33)) - && (*(vulp)LCA_IOC_T_BASE0 == 0)) { - LCA_DMA_WIN_BASE = *(vulp)LCA_IOC_W_BASE0 & 0xffffffffUL; - LCA_DMA_WIN_SIZE = *(vulp)LCA_IOC_W_MASK0 & 0xffffffffUL; - LCA_DMA_WIN_SIZE += 1; -#if 0 - printk("lca_init: using Window 0 settings\n"); - printk("lca_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n", - *(vulp)LCA_IOC_W_BASE0, - *(vulp)LCA_IOC_W_MASK0, - *(vulp)LCA_IOC_T_BASE0); -#endif - break; - } + struct pci_controler *hose; - /* Check window 2 for enabled and mapped to 0. */ - if ((*(vulp)LCA_IOC_W_BASE1 & (1UL<<33)) - && (*(vulp)LCA_IOC_T_BASE1 == 0)) { - LCA_DMA_WIN_BASE = *(vulp)LCA_IOC_W_BASE1 & 0xffffffffUL; - LCA_DMA_WIN_SIZE = *(vulp)LCA_IOC_W_MASK1 & 0xffffffffUL; - LCA_DMA_WIN_SIZE += 1; -#if 1 - printk("lca_init: using Window 1 settings\n"); - printk("lca_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n", - *(vulp)LCA_IOC_W_BASE1, - *(vulp)LCA_IOC_W_MASK1, - *(vulp)LCA_IOC_T_BASE1); -#endif - break; - } + /* + * Set up the PCI->physical memory translation windows. + * For now, window 1 is disabled. In the future, we may + * want to use it to do scatter/gather DMA. + * + * Window 0 goes at 1 GB and is 1 GB large. + */ + *(vulp)LCA_IOC_W_BASE0 = 1UL << 33 | LCA_DMA_WIN_BASE; + *(vulp)LCA_IOC_W_MASK0 = LCA_DMA_WIN_SIZE - 1; + *(vulp)LCA_IOC_T_BASE0 = 0; - /* Otherwise, we must use our defaults. */ - LCA_DMA_WIN_BASE = LCA_DMA_WIN_BASE_DEFAULT; - LCA_DMA_WIN_SIZE = LCA_DMA_WIN_SIZE_DEFAULT; -#endif - case 0: - /* - * Set up the PCI->physical memory translation windows. - * For now, window 1 is disabled. In the future, we may - * want to use it to do scatter/gather DMA. - * - * Window 0 goes at 1 GB and is 1 GB large. - */ - *(vulp)LCA_IOC_W_BASE1 = 0UL<<33; - - *(vulp)LCA_IOC_W_BASE0 = 1UL<<33 | LCA_DMA_WIN_BASE_DEFAULT; - *(vulp)LCA_IOC_W_MASK0 = LCA_DMA_WIN_SIZE_DEFAULT - 1; - *(vulp)LCA_IOC_T_BASE0 = 0; - break; - } + *(vulp)LCA_IOC_W_BASE1 = 0UL; /* * Disable PCI parity for now. The NCR53c810 chip has @@ -349,6 +303,16 @@ lca_init_arch(unsigned long *mem_start, unsigned long *mem_end) * data parity errors. */ *(vulp)LCA_IOC_PAR_DIS = 1UL<<5; + + /* + * Create our single hose. + */ + + hose = alloc_pci_controler(mem_start); + hose->io_space = &ioport_resource; + hose->mem_space = &iomem_resource; + hose->config_space = LCA_CONF; + hose->index = 0; } /* @@ -376,7 +340,7 @@ lca_init_arch(unsigned long *mem_start, unsigned long *mem_end) #define IOC_P_NBR ((__u32) ~((1<<13) - 1)) static void -mem_error (unsigned long esr, unsigned long ear) +mem_error(unsigned long esr, unsigned long ear) { printk(" %s %s error to %s occurred at address %x\n", ((esr & ESR_CEE) ? "Correctable" : @@ -399,7 +363,7 @@ mem_error (unsigned long esr, unsigned long ear) } static void -ioc_error (__u32 stat0, __u32 stat1) +ioc_error(__u32 stat0, __u32 stat1) { static const char * const pci_cmd[] = { "Interrupt Acknowledge", "Special", "I/O Read", "I/O Write", @@ -430,18 +394,18 @@ ioc_error (__u32 stat0, __u32 stat1) } void -lca_machine_check (unsigned long vector, unsigned long la, - struct pt_regs *regs) +lca_machine_check(unsigned long vector, unsigned long la_ptr, + struct pt_regs *regs) { - unsigned long * ptr; const char * reason; union el_lca el; - char buf[128]; - long i; - printk(KERN_CRIT "lca: machine check (la=0x%lx,pc=0x%lx)\n", - la, regs->pc); - el.c = (struct el_common *) la; + el.c = (struct el_common *) la_ptr; + + wrmces(rdmces()); /* reset machine check pending flag */ + + printk(KERN_CRIT "LCA machine check: vector=%#lx pc=%#lx code=%#x\n", + vector, regs->pc, (unsigned int) el.c->code); /* * The first quadword after the common header always seems to @@ -450,13 +414,13 @@ lca_machine_check (unsigned long vector, unsigned long la, * logout frame, the upper 32 bits is the machine check * revision level, which we ignore for now. */ - switch (el.c->code & 0xffffffff) { + switch ((unsigned int) el.c->code) { case MCHK_K_TPERR: reason = "tag parity error"; break; case MCHK_K_TCPERR: reason = "tag control parity error"; break; case MCHK_K_HERR: reason = "access to non-existent memory"; break; case MCHK_K_ECC_C: reason = "correctable ECC error"; break; case MCHK_K_ECC_NC: reason = "non-correctable ECC error"; break; - case MCHK_K_CACKSOFT: reason = "MCHK_K_CACKSOFT"; break; /* what's this? */ + case MCHK_K_CACKSOFT: reason = "MCHK_K_CACKSOFT"; break; case MCHK_K_BUGCHECK: reason = "illegal exception in PAL mode"; break; case MCHK_K_OS_BUGCHECK: reason = "callsys in kernel mode"; break; case MCHK_K_DCPERR: reason = "d-cache parity error"; break; @@ -465,19 +429,13 @@ lca_machine_check (unsigned long vector, unsigned long la, case MCHK_K_SIO_IOCHK: reason = "SIO IOCHK occurred on ISA bus"; break; case MCHK_K_DCSR: reason = "MCHK_K_DCSR"; break; case MCHK_K_UNKNOWN: - default: - sprintf(buf, "reason for machine-check unknown (0x%lx)", - el.c->code & 0xffffffff); - reason = buf; - break; + default: reason = "unknown"; break; } - wrmces(rdmces()); /* reset machine check pending flag */ - switch (el.c->size) { case sizeof(struct el_lca_mcheck_short): printk(KERN_CRIT - " Reason: %s (short frame%s, dc_stat=%lx):\n", + " Reason: %s (short frame%s, dc_stat=%#lx):\n", reason, el.c->retry ? ", retryable" : "", el.s->dc_stat); if (el.s->esr & ESR_EAV) { @@ -492,9 +450,9 @@ lca_machine_check (unsigned long vector, unsigned long la, printk(KERN_CRIT " Reason: %s (long frame%s):\n", reason, el.c->retry ? ", retryable" : ""); printk(KERN_CRIT - " reason: %lx exc_addr: %lx dc_stat: %lx\n", + " reason: %#lx exc_addr: %#lx dc_stat: %#lx\n", el.l->pt[0], el.l->exc_addr, el.l->dc_stat); - printk(KERN_CRIT " car: %lx\n", el.l->car); + printk(KERN_CRIT " car: %#lx\n", el.l->car); if (el.l->esr & ESR_EAV) { mem_error(el.l->esr, el.l->ear); } @@ -508,12 +466,16 @@ lca_machine_check (unsigned long vector, unsigned long la, } /* Dump the logout area to give all info. */ - - ptr = (unsigned long *) la; - for (i = 0; i < el.c->size / sizeof(long); i += 2) { - printk(KERN_CRIT " +%8lx %016lx %016lx\n", - i*sizeof(long), ptr[i], ptr[i+1]); +#if DEBUG_MCHECK > 1 + { + unsigned long * ptr = (unsigned long *) la_ptr; + long i; + for (i = 0; i < el.c->size / sizeof(long); i += 2) { + printk(KERN_CRIT " +%8lx %016lx %016lx\n", + i*sizeof(long), ptr[i], ptr[i+1]); + } } +#endif } /* diff --git a/arch/alpha/kernel/core_mcpcia.c b/arch/alpha/kernel/core_mcpcia.c index 6e24dca07..ac86d5255 100644 --- a/arch/alpha/kernel/core_mcpcia.c +++ b/arch/alpha/kernel/core_mcpcia.c @@ -1,12 +1,11 @@ /* * linux/arch/alpha/kernel/core_mcpcia.c * - * Code common to all MCbus-PCI Adaptor core logic chipsets - * * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com). * + * Code common to all MCbus-PCI Adaptor core logic chipsets */ -#include <linux/config.h> + #include <linux/kernel.h> #include <linux/types.h> #include <linux/pci.h> @@ -25,7 +24,7 @@ #undef __EXTERN_INLINE #include "proto.h" -#include "bios32.h" +#include "pci_impl.h" /* * NOTE: Herein lie back-to-back mb instructions. They are magic. @@ -37,28 +36,20 @@ * BIOS32-style PCI interface: */ -#undef DEBUG_CFG +#define DEBUG_CFG 0 -#ifdef DEBUG_CFG +#if DEBUG_CFG # define DBG_CFG(args) printk args #else # define DBG_CFG(args) #endif +#define MCPCIA_MAX_HOSES 2 -#define DEBUG_MCHECK - -#ifdef DEBUG_MCHECK -# define DBG_MCK(args) printk args -#else -# define DBG_MCK(args) -#endif +/* Dodge has PCI0 and PCI1 at MID 4 and 5 respectively. Durango adds + PCI2 and PCI3 at MID 6 and 7 respectively. */ -static volatile unsigned int MCPCIA_mcheck_expected[NR_CPUS]; -static volatile unsigned int MCPCIA_mcheck_taken[NR_CPUS]; -static unsigned int MCPCIA_jd[NR_CPUS]; - -#define MCPCIA_MAX_HOSES 2 +#define hose2mid(h) ((h) + 4) /* @@ -105,10 +96,10 @@ static unsigned int MCPCIA_jd[NR_CPUS]; static unsigned int conf_read(unsigned long addr, unsigned char type1, - struct linux_hose_info *hose) + struct pci_controler *hose) { unsigned long flags; - unsigned long hoseno = hose->pci_hose_index; + unsigned long mid = hose2mid(hose->index); unsigned int stat0, value, temp, cpu; cpu = smp_processor_id(); @@ -116,18 +107,20 @@ conf_read(unsigned long addr, unsigned char type1, __save_and_cli(flags); DBG_CFG(("conf_read(addr=0x%lx, type1=%d, hose=%d)\n", - addr, type1, hoseno)); + addr, type1, mid)); /* Reset status register to avoid losing errors. */ - stat0 = *(vuip)MCPCIA_CAP_ERR(hoseno); - *(vuip)MCPCIA_CAP_ERR(hoseno) = stat0; mb(); - temp = *(vuip)MCPCIA_CAP_ERR(hoseno); - DBG_CFG(("conf_read: MCPCIA CAP_ERR(%d) was 0x%x\n", hoseno, stat0)); + stat0 = *(vuip)MCPCIA_CAP_ERR(mid); + *(vuip)MCPCIA_CAP_ERR(mid) = stat0; + mb(); + temp = *(vuip)MCPCIA_CAP_ERR(mid); + DBG_CFG(("conf_read: MCPCIA_CAP_ERR(%d) was 0x%x\n", mid, stat0)); mb(); draina(); - MCPCIA_mcheck_expected[cpu] = 1; - MCPCIA_mcheck_taken[cpu] = 0; + mcheck_expected(cpu) = 1; + mcheck_taken(cpu) = 0; + mcheck_extra(cpu) = mid; mb(); /* Access configuration space. */ @@ -135,12 +128,12 @@ conf_read(unsigned long addr, unsigned char type1, mb(); mb(); /* magic */ - if (MCPCIA_mcheck_taken[cpu]) { - MCPCIA_mcheck_taken[cpu] = 0; + if (mcheck_taken(cpu)) { + mcheck_taken(cpu) = 0; value = 0xffffffffU; mb(); } - MCPCIA_mcheck_expected[cpu] = 0; + mcheck_expected(cpu) = 0; mb(); DBG_CFG(("conf_read(): finished\n")); @@ -151,10 +144,10 @@ conf_read(unsigned long addr, unsigned char type1, static void conf_write(unsigned long addr, unsigned int value, unsigned char type1, - struct linux_hose_info *hose) + struct pci_controler *hose) { unsigned long flags; - unsigned long hoseno = hose->pci_hose_index; + unsigned long mid = hose2mid(hose->index); unsigned int stat0, temp, cpu; cpu = smp_processor_id(); @@ -162,21 +155,22 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1, __save_and_cli(flags); /* avoid getting hit by machine check */ /* Reset status register to avoid losing errors. */ - stat0 = *(vuip)MCPCIA_CAP_ERR(hoseno); - *(vuip)MCPCIA_CAP_ERR(hoseno) = stat0; mb(); - temp = *(vuip)MCPCIA_CAP_ERR(hoseno); - DBG_CFG(("conf_write: MCPCIA CAP_ERR(%d) was 0x%x\n", hoseno, stat0)); + stat0 = *(vuip)MCPCIA_CAP_ERR(mid); + *(vuip)MCPCIA_CAP_ERR(mid) = stat0; mb(); + temp = *(vuip)MCPCIA_CAP_ERR(mid); + DBG_CFG(("conf_write: MCPCIA CAP_ERR(%d) was 0x%x\n", mid, stat0)); draina(); - MCPCIA_mcheck_expected[cpu] = 1; + mcheck_expected(cpu) = 1; + mcheck_extra(cpu) = mid; mb(); /* Access configuration space. */ *((vuip)addr) = value; mb(); mb(); /* magic */ - temp = *(vuip)MCPCIA_CAP_ERR(hoseno); /* read to force the write */ - MCPCIA_mcheck_expected[cpu] = 0; + temp = *(vuip)MCPCIA_CAP_ERR(mid); /* read to force the write */ + mcheck_expected(cpu) = 0; mb(); DBG_CFG(("conf_write(): finished\n")); @@ -184,71 +178,71 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1, } static int -mk_conf_addr(struct linux_hose_info *hose, - u8 bus, u8 device_fn, u8 where, +mk_conf_addr(struct pci_dev *dev, int where, struct pci_controler *hose, unsigned long *pci_addr, unsigned char *type1) { + u8 bus = dev->bus->number; + u8 devfn = dev->devfn; unsigned long addr; - if (!pci_probe_enabled) - return -1; - - DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x," + DBG_CFG(("mk_conf_addr(bus=%d,devfn=0x%x,hose=%d,where=0x%x," " pci_addr=0x%p, type1=0x%p)\n", - bus, device_fn, where, pci_addr, type1)); + bus, devfn, hose->index, where, pci_addr, type1)); /* Type 1 configuration cycle for *ALL* busses. */ *type1 = 1; - if (hose->pci_first_busno == bus) + if (dev->bus->number == hose->first_busno) bus = 0; - addr = (bus << 16) | (device_fn << 8) | (where); + addr = (bus << 16) | (devfn << 8) | (where); addr <<= 5; /* swizzle for SPARSE */ - addr |= hose->pci_config_space; + addr |= hose->config_space; *pci_addr = addr; DBG_CFG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr)); return 0; } -int -mcpcia_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value, - struct linux_hose_info *hose) +static int +mcpcia_read_config_byte(struct pci_dev *dev, int where, u8 *value) { - unsigned long addr; + struct pci_controler *hose = dev->sysdata ? : probing_hose; + unsigned long addr, w; unsigned char type1; - if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1)) + if (mk_conf_addr(dev, where, hose, &addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; addr |= 0x00; - *value = conf_read(addr, type1, hose) >> ((where & 3) * 8); + w = conf_read(addr, type1, hose); + *value = __kernel_extbl(w, where & 3); return PCIBIOS_SUCCESSFUL; } -int -mcpcia_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value, - struct linux_hose_info *hose) +static int +mcpcia_read_config_word(struct pci_dev *dev, int where, u16 *value) { - unsigned long addr; + struct pci_controler *hose = dev->sysdata ? : probing_hose; + unsigned long addr, w; unsigned char type1; - if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1)) + if (mk_conf_addr(dev, where, hose, &addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; addr |= 0x08; - *value = conf_read(addr, type1, hose) >> ((where & 3) * 8); + w = conf_read(addr, type1, hose); + *value = __kernel_extwl(w, where & 3); return PCIBIOS_SUCCESSFUL; } -int -mcpcia_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value, - struct linux_hose_info *hose) +static int +mcpcia_read_config_dword(struct pci_dev *dev, int where, u32 *value) { + struct pci_controler *hose = dev->sysdata ? : probing_hose; unsigned long addr; unsigned char type1; - if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1)) + if (mk_conf_addr(dev, where, hose, &addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; addr |= 0x18; @@ -256,317 +250,213 @@ mcpcia_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value, return PCIBIOS_SUCCESSFUL; } -int -mcpcia_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value, - struct linux_hose_info *hose) +static int +mcpcia_write_config(struct pci_dev *dev, int where, u32 value, long mask) { + struct pci_controler *hose = dev->sysdata ? : probing_hose; unsigned long addr; unsigned char type1; - if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1)) + if (mk_conf_addr(dev, where, hose, &addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - addr |= 0x00; - conf_write(addr, value << ((where & 3) * 8), type1, hose); + addr |= mask; + value = __kernel_insql(value, where & 3); + conf_write(addr, value, type1, hose); return PCIBIOS_SUCCESSFUL; } -int -mcpcia_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value, - struct linux_hose_info *hose) +static int +mcpcia_write_config_byte(struct pci_dev *dev, int where, u8 value) { - unsigned long addr; - unsigned char type1; - - if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1)) - return PCIBIOS_DEVICE_NOT_FOUND; - - addr |= 0x08; - conf_write(addr, value << ((where & 3) * 8), type1, hose); - return PCIBIOS_SUCCESSFUL; + return mcpcia_write_config(dev, where, value, 0x00); } -int -mcpcia_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value, - struct linux_hose_info *hose) +static int +mcpcia_write_config_word(struct pci_dev *dev, int where, u16 value) { - unsigned long addr; - unsigned char type1; - - if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1)) - return PCIBIOS_DEVICE_NOT_FOUND; + return mcpcia_write_config(dev, where, value, 0x08); +} - addr |= 0x18; - conf_write(addr, value << ((where & 3) * 8), type1, hose); - return PCIBIOS_SUCCESSFUL; +static int +mcpcia_write_config_dword(struct pci_dev *dev, int where, u32 value) +{ + return mcpcia_write_config(dev, where, value, 0x18); } -void __init -mcpcia_init_arch(unsigned long *mem_start, unsigned long *mem_end) +struct pci_ops mcpcia_pci_ops = { - extern asmlinkage void entInt(void); - struct linux_hose_info *hose; - unsigned int mcpcia_err; + read_byte: mcpcia_read_config_byte, + read_word: mcpcia_read_config_word, + read_dword: mcpcia_read_config_dword, + write_byte: mcpcia_write_config_byte, + write_word: mcpcia_write_config_word, + write_dword: mcpcia_write_config_dword +}; + +static int __init +mcpcia_probe_hose(int h) +{ + int cpu = smp_processor_id(); + int mid = hose2mid(h); unsigned int pci_rev; - int h, cpu; - /* Ho hum.. init_arch is called before init_IRQ, but we need to be - able to handle machine checks. So install the handler now. */ - wrent(entInt, 0); - - /* Align memory to cache line; we'll be allocating from it. */ - *mem_start = (*mem_start | 31) + 1; - - cpu = smp_processor_id(); + /* Gotta be REAL careful. If hose is absent, we get an mcheck. */ - /* First, find how many hoses we have. */ - for (h = 0; h < MCPCIA_MAX_HOSES; h++) { + mb(); + mb(); + draina(); + mcheck_expected(cpu) = 1; + mcheck_taken(cpu) = 0; + mcheck_extra(cpu) = mid; + mb(); - /* Gotta be REAL careful. If hose is absent, we get a - machine check. */ + /* Access the bus revision word. */ + pci_rev = *(vuip)MCPCIA_REV(mid); + mb(); + mb(); /* magic */ + if (mcheck_taken(cpu)) { + mcheck_taken(cpu) = 0; + pci_rev = 0xffffffff; mb(); - mb(); - draina(); - MCPCIA_mcheck_expected[cpu] = 1; - MCPCIA_mcheck_taken[cpu] = 0; - mb(); + } + mcheck_expected(cpu) = 0; + mb(); + + return (pci_rev >> 16) == PCI_CLASS_BRIDGE_HOST; +} - /* Access the bus revision word. */ - pci_rev = *(vuip)MCPCIA_REV(h); +static void __init +mcpcia_new_hose(unsigned long *mem_start, int h) +{ + struct pci_controler *hose; + struct resource *io, *mem, *hae_mem; + int mid = hose2mid(h); + + hose = alloc_pci_controler(mem_start); + io = alloc_resource(mem_start); + mem = alloc_resource(mem_start); + hae_mem = alloc_resource(mem_start); + + hose->io_space = io; + hose->mem_space = hae_mem; + hose->config_space = MCPCIA_CONF(mid); + hose->index = h; + + io->start = MCPCIA_IO(mid) - MCPCIA_IO_BIAS; + io->end = io->start + 0xffff; + io->name = pci_io_names[h]; + + mem->start = MCPCIA_DENSE(mid) - MCPCIA_MEM_BIAS; + mem->end = mem->start + 0xffffffff; + mem->name = pci_mem_names[h]; + + hae_mem->start = mem->start; + hae_mem->end = mem->start + MCPCIA_MEM_MASK; + hae_mem->name = pci_hae0_name; + + request_resource(&ioport_resource, io); + request_resource(&iomem_resource, mem); + request_resource(mem, hae_mem); +} - mb(); - mb(); /* magic */ - if (MCPCIA_mcheck_taken[cpu]) { - MCPCIA_mcheck_taken[cpu] = 0; - pci_rev = 0xffffffff; - mb(); - } - MCPCIA_mcheck_expected[cpu] = 0; - mb(); +static void __init +mcpcia_startup_hose(struct pci_controler *hose) +{ + int mid = hose2mid(hose->index); + unsigned int tmp; + /* + * Set up error reporting. Make sure CPU_PE is OFF in the mask. + */ #if 0 - printk("mcpcia_init_arch: got 0x%x for PCI_REV for hose %d\n", - pci_rev, h); + tmp = *(vuip)MCPCIA_ERR_MASK(mid); + tmp &= ~4; + *(vuip)MCPCIA_ERR_MASK(mid) = tmp; + mb(); + tmp = *(vuip)MCPCIA_ERR_MASK(mid); #endif - if ((pci_rev >> 16) == PCI_CLASS_BRIDGE_HOST) { - hose_count++; - hose = (struct linux_hose_info *)*mem_start; - *mem_start = (unsigned long)(hose + 1); + tmp = *(vuip)MCPCIA_CAP_ERR(mid); + tmp |= 0x0006; /* master/target abort */ + *(vuip)MCPCIA_CAP_ERR(mid) = tmp; + mb(); + tmp = *(vuip)MCPCIA_CAP_ERR(mid); - memset(hose, 0, sizeof(*hose)); + /* + * Set up the PCI->physical memory translation windows. + * For now, windows 1,2 and 3 are disabled. In the + * future, we may want to use them to do scatter/ + * gather DMA. + * + * Window 0 goes at 2 GB and is 2 GB large. + */ - *hose_tail = hose; - hose_tail = &hose->next; + *(vuip)MCPCIA_W0_BASE(mid) = 1U | (MCPCIA_DMA_WIN_BASE & 0xfff00000U); + *(vuip)MCPCIA_W0_MASK(mid) = (MCPCIA_DMA_WIN_SIZE - 1) & 0xfff00000U; + *(vuip)MCPCIA_T0_BASE(mid) = 0; - hose->pci_io_space = MCPCIA_IO(h); - hose->pci_mem_space = MCPCIA_DENSE(h); - hose->pci_config_space = MCPCIA_CONF(h); - hose->pci_sparse_space = MCPCIA_SPARSE(h); - hose->pci_hose_index = h; - hose->pci_first_busno = 255; - hose->pci_last_busno = 0; - } - } + *(vuip)MCPCIA_W1_BASE(mid) = 0x0; + *(vuip)MCPCIA_W2_BASE(mid) = 0x0; + *(vuip)MCPCIA_W3_BASE(mid) = 0x0; -#if 1 - printk("mcpcia_init_arch: found %d hoses\n", hose_count); -#endif + *(vuip)MCPCIA_HBASE(mid) = 0x0; + mb(); - /* Now do init for each hose. */ - for (hose = hose_head; hose; hose = hose->next) { - h = hose->pci_hose_index; #if 0 - printk("mcpcia_init_arch: -------- hose %d --------\n",h); - printk("MCPCIA_REV 0x%x\n", *(vuip)MCPCIA_REV(h)); - printk("MCPCIA_WHOAMI 0x%x\n", *(vuip)MCPCIA_WHOAMI(h)); - printk("MCPCIA_HAE_MEM 0x%x\n", *(vuip)MCPCIA_HAE_MEM(h)); - printk("MCPCIA_HAE_IO 0x%x\n", *(vuip)MCPCIA_HAE_IO(h)); - printk("MCPCIA_HAE_DENSE 0x%x\n", *(vuip)MCPCIA_HAE_DENSE(h)); - printk("MCPCIA_INT_CTL 0x%x\n", *(vuip)MCPCIA_INT_CTL(h)); - printk("MCPCIA_INT_REQ 0x%x\n", *(vuip)MCPCIA_INT_REQ(h)); - printk("MCPCIA_INT_TARG 0x%x\n", *(vuip)MCPCIA_INT_TARG(h)); - printk("MCPCIA_INT_ADR 0x%x\n", *(vuip)MCPCIA_INT_ADR(h)); - printk("MCPCIA_INT_ADR_EXT 0x%x\n", *(vuip)MCPCIA_INT_ADR_EXT(h)); - printk("MCPCIA_INT_MASK0 0x%x\n", *(vuip)MCPCIA_INT_MASK0(h)); - printk("MCPCIA_INT_MASK1 0x%x\n", *(vuip)MCPCIA_INT_MASK1(h)); - printk("MCPCIA_HBASE 0x%x\n", *(vuip)MCPCIA_HBASE(h)); + tmp = *(vuip)MCPCIA_INT_CTL(mid); + printk("mcpcia_init_arch: INT_CTL was 0x%x\n", tmp); + *(vuip)MCPCIA_INT_CTL(mid) = 1U; + mb(); + tmp = *(vuip)MCPCIA_INT_CTL(mid); #endif - /* - * Set up error reporting. Make sure CPU_PE is OFF in the mask. - */ -#if 0 - mcpcia_err = *(vuip)MCPCIA_ERR_MASK(h); - mcpcia_err &= ~4; - *(vuip)MCPCIA_ERR_MASK(h) = mcpcia_err; - mb(); - mcpcia_err = *(vuip)MCPCIA_ERR_MASK; -#endif + *(vuip)MCPCIA_HAE_MEM(mid) = 0U; + mb(); + *(vuip)MCPCIA_HAE_MEM(mid); /* read it back. */ + *(vuip)MCPCIA_HAE_IO(mid) = 0; + mb(); + *(vuip)MCPCIA_HAE_IO(mid); /* read it back. */ +} - mcpcia_err = *(vuip)MCPCIA_CAP_ERR(h); - mcpcia_err |= 0x0006; /* master/target abort */ - *(vuip)MCPCIA_CAP_ERR(h) = mcpcia_err; - mb() ; - mcpcia_err = *(vuip)MCPCIA_CAP_ERR(h); - - switch (alpha_use_srm_setup) - { - default: -#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP) - /* Check window 0 for enabled and mapped to 0. */ - if (((*(vuip)MCPCIA_W0_BASE(h) & 3) == 1) - && (*(vuip)MCPCIA_T0_BASE(h) == 0) - && ((*(vuip)MCPCIA_W0_MASK(h) & 0xfff00000U) > 0x0ff00000U)) { - MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W0_BASE(h) & 0xfff00000U; - MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W0_MASK(h) & 0xfff00000U; - MCPCIA_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("mcpcia_init_arch: using Window 0 settings\n"); - printk("mcpcia_init_arch: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vuip)MCPCIA_W0_BASE(h), - *(vuip)MCPCIA_W0_MASK(h), - *(vuip)MCPCIA_T0_BASE(h)); -#endif - break; - } - - /* Check window 1 for enabled and mapped to 0. */ - if (((*(vuip)MCPCIA_W1_BASE(h) & 3) == 1) - && (*(vuip)MCPCIA_T1_BASE(h) == 0) - && ((*(vuip)MCPCIA_W1_MASK(h) & 0xfff00000U) > 0x0ff00000U)) { - MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W1_BASE(h) & 0xfff00000U; - MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W1_MASK(h) & 0xfff00000U; - MCPCIA_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("mcpcia_init_arch: using Window 1 settings\n"); - printk("mcpcia_init_arch: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vuip)MCPCIA_W1_BASE(h), - *(vuip)MCPCIA_W1_MASK(h), - *(vuip)MCPCIA_T1_BASE(h)); -#endif - break; - } - - /* Check window 2 for enabled and mapped to 0. */ - if (((*(vuip)MCPCIA_W2_BASE(h) & 3) == 1) - && (*(vuip)MCPCIA_T2_BASE(h) == 0) - && ((*(vuip)MCPCIA_W2_MASK(h) & 0xfff00000U) > 0x0ff00000U)) { - MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W2_BASE(h) & 0xfff00000U; - MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W2_MASK(h) & 0xfff00000U; - MCPCIA_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("mcpcia_init_arch: using Window 2 settings\n"); - printk("mcpcia_init_arch: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vuip)MCPCIA_W2_BASE(h), - *(vuip)MCPCIA_W2_MASK(h), - *(vuip)MCPCIA_T2_BASE(h)); -#endif - break; - } - - /* Check window 3 for enabled and mapped to 0. */ - if (((*(vuip)MCPCIA_W3_BASE(h) & 3) == 1) - && (*(vuip)MCPCIA_T3_BASE(h) == 0) - && ((*(vuip)MCPCIA_W3_MASK(h) & 0xfff00000U) > 0x0ff00000U)) { - MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W3_BASE(h) & 0xfff00000U; - MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W3_MASK(h) & 0xfff00000U; - MCPCIA_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("mcpcia_init_arch: using Window 3 settings\n"); - printk("mcpcia_init_arch: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vuip)MCPCIA_W3_BASE(h), - *(vuip)MCPCIA_W3_MASK(h), - *(vuip)MCPCIA_T3_BASE(h)); -#endif - break; - } +void __init +mcpcia_init_arch(unsigned long *mem_start, unsigned long *mem_end) +{ + extern asmlinkage void entInt(void); + struct pci_controler *hose; + int h, hose_count = 0; - /* Otherwise, we must use our defaults. */ - MCPCIA_DMA_WIN_BASE = MCPCIA_DMA_WIN_BASE_DEFAULT; - MCPCIA_DMA_WIN_SIZE = MCPCIA_DMA_WIN_SIZE_DEFAULT; -#endif - case 0: - /* - * Set up the PCI->physical memory translation windows. - * For now, windows 1,2 and 3 are disabled. In the - * future, we may want to use them to do scatter/ - * gather DMA. - * - * Window 0 goes at 2 GB and is 2 GB large. - */ - - *(vuip)MCPCIA_W0_BASE(h) = 1U | (MCPCIA_DMA_WIN_BASE_DEFAULT & 0xfff00000U); - *(vuip)MCPCIA_W0_MASK(h) = (MCPCIA_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U; - *(vuip)MCPCIA_T0_BASE(h) = 0; - - *(vuip)MCPCIA_W1_BASE(h) = 0x0 ; - *(vuip)MCPCIA_W2_BASE(h) = 0x0 ; - *(vuip)MCPCIA_W3_BASE(h) = 0x0 ; - - *(vuip)MCPCIA_HBASE(h) = 0x0 ; - mb(); - break; - } -#if 0 - { - unsigned int mcpcia_int_ctl = *((vuip)MCPCIA_INT_CTL(h)); - printk("mcpcia_init_arch: INT_CTL was 0x%x\n", mcpcia_int_ctl); - *(vuip)MCPCIA_INT_CTL(h) = 1U; mb(); - mcpcia_int_ctl = *(vuip)MCPCIA_INT_CTL(h); - } -#endif + /* Ho hum.. init_arch is called before init_IRQ, but we need to be + able to handle machine checks. So install the handler now. */ + wrent(entInt, 0); + + /* With multiple PCI busses, we play with I/O as physical addrs. */ + ioport_resource.end = ~0UL; + iomem_resource.end = ~0UL; - /* - * Sigh... For the SRM setup, unless we know apriori what the HAE - * contents will be, we need to setup the arbitrary region bases - * so we can test against the range of addresses and tailor the - * region chosen for the SPARSE memory access. - * - * See include/asm-alpha/mcpcia.h for the SPARSE mem read/write. - */ - if (alpha_use_srm_setup) { - unsigned int mcpcia_hae_mem = *(vuip)MCPCIA_HAE_MEM(h); - - alpha_mv.sm_base_r1 = (mcpcia_hae_mem ) & 0xe0000000UL; - alpha_mv.sm_base_r2 = (mcpcia_hae_mem << 16) & 0xf8000000UL; - alpha_mv.sm_base_r3 = (mcpcia_hae_mem << 24) & 0xfc000000UL; - - /* - * Set the HAE cache, so that setup_arch() code - * will use the SRM setting always. Our readb/writeb - * code in mcpcia.h expects never to have to change - * the contents of the HAE. - */ - alpha_mv.hae_cache = mcpcia_hae_mem; - - alpha_mv.mv_readb = mcpcia_srm_readb; - alpha_mv.mv_readw = mcpcia_srm_readw; - alpha_mv.mv_writeb = mcpcia_srm_writeb; - alpha_mv.mv_writew = mcpcia_srm_writew; - } else { - *(vuip)MCPCIA_HAE_MEM(h) = 0U; mb(); - *(vuip)MCPCIA_HAE_MEM(h); /* read it back. */ - *(vuip)MCPCIA_HAE_IO(h) = 0; mb(); - *(vuip)MCPCIA_HAE_IO(h); /* read it back. */ + /* First, find how many hoses we have. */ + for (h = 0; h < MCPCIA_MAX_HOSES; ++h) { + if (mcpcia_probe_hose(h)) { + mcpcia_new_hose(mem_start, h); + hose_count++; } } + + printk("mcpcia_init_arch: found %d hoses\n", hose_count); + + /* Now do init for each hose. */ + for (hose = hose_head; hose; hose = hose->next) + mcpcia_startup_hose(hose); } -static int -mcpcia_pci_clr_err(int h) +static void +mcpcia_pci_clr_err(int mid) { - unsigned int cpu = smp_processor_id(); - - MCPCIA_jd[cpu] = *(vuip)MCPCIA_CAP_ERR(h); -#if 0 - DBG_MCK(("MCPCIA_pci_clr_err: MCPCIA CAP_ERR(%d) after read 0x%x\n", - h, MCPCIA_jd[cpu])); -#endif - *(vuip)MCPCIA_CAP_ERR(h) = 0xffffffff; mb(); /* clear them all */ - MCPCIA_jd[cpu] = *(vuip)MCPCIA_CAP_ERR(h); - return 0; + *(vuip)MCPCIA_CAP_ERR(mid); + *(vuip)MCPCIA_CAP_ERR(mid) = 0xffffffff; /* Clear them all. */ + mb(); + *(vuip)MCPCIA_CAP_ERR(mid); /* Re-read for force write. */ } static void @@ -642,70 +532,35 @@ mcpcia_print_uncorrectable(struct el_MCPCIA_uncorrected_frame_mcheck *logout) } void -mcpcia_machine_check(unsigned long type, unsigned long la_ptr, +mcpcia_machine_check(unsigned long vector, unsigned long la_ptr, struct pt_regs * regs) { -#if 0 - printk("mcpcia machine check ignored\n") ; -#else struct el_common *mchk_header; struct el_MCPCIA_uncorrected_frame_mcheck *mchk_logout; unsigned int cpu = smp_processor_id(); - int h = 0; mchk_header = (struct el_common *)la_ptr; mchk_logout = (struct el_MCPCIA_uncorrected_frame_mcheck *)la_ptr; -#if 0 - DBG_MCK(("mcpcia_machine_check: type=0x%lx la_ptr=0x%lx\n", - type, la_ptr)); - DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", - regs->pc, mchk_header->size, mchk_header->proc_offset, - mchk_header->sys_offset)); -#endif - /* - * Check if machine check is due to a badaddr() and if so, - * ignore the machine check. - */ mb(); mb(); /* magic */ - if (MCPCIA_mcheck_expected[cpu]) { -#if 0 - DBG_MCK(("MCPCIA machine check expected\n")); -#endif - MCPCIA_mcheck_expected[cpu] = 0; - MCPCIA_mcheck_taken[cpu] = 1; - mb(); - mb(); /* magic */ - draina(); - mcpcia_pci_clr_err(h); - wrmces(0x7); - mb(); + draina(); + if (mcheck_expected(cpu)) { + mcpcia_pci_clr_err(mcheck_extra(cpu)); + } else { + /* FIXME: how do we figure out which hose the error was on? */ + struct pci_controler *hose; + for (hose = hose_head; hose; hose = hose->next) + mcpcia_pci_clr_err(hose2mid(hose->index)); } -#if 1 - else { - printk("MCPCIA machine check NOT expected on CPU %d\n", cpu); - DBG_MCK(("mcpcia_machine_check: type=0x%lx pc=0x%lx" - " code=0x%lx\n", - type, regs->pc, mchk_header->code)); - - MCPCIA_mcheck_expected[cpu] = 0; - MCPCIA_mcheck_taken[cpu] = 1; - mb(); - mb(); /* magic */ - draina(); - mcpcia_pci_clr_err(h); - wrmces(0x7); - mb(); -#ifdef DEBUG_MCHECK_DUMP - if (type == 0x620) - printk("MCPCIA machine check: system CORRECTABLE!\n"); - else if (type == 0x630) - printk("MCPCIA machine check: processor CORRECTABLE!\n"); - else -#endif /* DEBUG_MCHECK_DUMP */ + wrmces(0x7); + mb(); + + if (mcheck_expected(cpu)) { + process_mcheck_info(vector, la_ptr, regs, "MCPCIA", 1); + } else { + process_mcheck_info(vector, la_ptr, regs, "MCPCIA", 0); + if (vector != 0x620 && vector != 0x630) mcpcia_print_uncorrectable(mchk_logout); } -#endif -#endif } diff --git a/arch/alpha/kernel/core_polaris.c b/arch/alpha/kernel/core_polaris.c index b9945402f..39ae36f8e 100644 --- a/arch/alpha/kernel/core_polaris.c +++ b/arch/alpha/kernel/core_polaris.c @@ -2,8 +2,8 @@ * linux/arch/alpha/kernel/core_polaris.c * * POLARIS chip-specific code - * */ + #include <linux/kernel.h> #include <linux/types.h> #include <linux/pci.h> @@ -20,29 +20,20 @@ #undef __EXTERN_INLINE #include "proto.h" -#include "bios32.h" +#include "pci_impl.h" /* * BIOS32-style PCI interface: */ -#ifdef DEBUG_CONFIG +#define DEBUG_CONFIG 0 + +#if DEBUG_CONFIG # define DBG_CFG(args) printk args #else # define DBG_CFG(args) #endif -#define DEBUG_MCHECK -#ifdef DEBUG_MCHECK -# define DBG_MCK(args) printk args -/* #define DEBUG_MCHECK_DUMP */ -#else -# define DBG_MCK(args) -#endif - -static volatile unsigned int POLARIS_mcheck_expected = 0; -static volatile unsigned int POLARIS_mcheck_taken = 0; -static volatile unsigned short POLARIS_jd = 0; /* * Given a bus, device, and function number, compute resulting @@ -75,8 +66,11 @@ static volatile unsigned short POLARIS_jd = 0; */ static int -mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr, u8 *type1) +mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr, u8 *type1) { + u8 bus = dev->bus->number; + u8 device_fn = dev->devfn; + *type1 = (bus == 0) ? 0 : 1; *pci_addr = (bus << 16) | (device_fn << 8) | (where) | POLARIS_DENSE_CONFIG_BASE; @@ -88,59 +82,52 @@ mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr, u8 *type1) return 0; } -int -polaris_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value, - struct linux_hose_info *hose) +static int +polaris_read_config_byte(struct pci_dev *dev, int where, u8 *value) { unsigned long pci_addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + if (mk_conf_addr(dev, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; *value = __kernel_ldbu(*(vucp)pci_addr); return PCIBIOS_SUCCESSFUL; } - -int -polaris_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value, - struct linux_hose_info *hose) +static int +polaris_read_config_word(struct pci_dev *dev, int where, u16 *value) { unsigned long pci_addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + if (mk_conf_addr(dev, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; *value = __kernel_ldwu(*(vusp)pci_addr); return PCIBIOS_SUCCESSFUL; } - -int -polaris_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value, - struct linux_hose_info *hose) +static int +polaris_read_config_dword(struct pci_dev *dev, int where, u32 *value) { unsigned long pci_addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + if (mk_conf_addr(dev, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; *value = *(vuip)pci_addr; return PCIBIOS_SUCCESSFUL; } - -int -polaris_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value, - struct linux_hose_info *hose) +static int +polaris_write_config_byte(struct pci_dev *dev, int where, u8 value) { unsigned long pci_addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + if (mk_conf_addr(dev, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; __kernel_stb(value, *(vucp)pci_addr); @@ -149,15 +136,13 @@ polaris_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value, return PCIBIOS_SUCCESSFUL; } - -int -polaris_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value, - struct linux_hose_info *hose) +static int +polaris_write_config_word(struct pci_dev *dev, int where, u16 value) { unsigned long pci_addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + if (mk_conf_addr(dev, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; __kernel_stw(value, *(vusp)pci_addr); @@ -166,15 +151,13 @@ polaris_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value, return PCIBIOS_SUCCESSFUL; } - -int -polaris_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value, - struct linux_hose_info *hose) +static int +polaris_write_config_dword(struct pci_dev *dev, int where, u32 value) { unsigned long pci_addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + if (mk_conf_addr(dev, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; *(vuip)pci_addr = value; @@ -183,9 +166,21 @@ polaris_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value, return PCIBIOS_SUCCESSFUL; } +struct pci_ops polaris_pci_ops = +{ + read_byte: polaris_read_config_byte, + read_word: polaris_read_config_word, + read_dword: polaris_read_config_dword, + write_byte: polaris_write_config_byte, + write_word: polaris_write_config_word, + write_dword: polaris_write_config_dword +}; + void __init polaris_init_arch(unsigned long *mem_start, unsigned long *mem_end) { + struct pci_controler *hose; + /* May need to initialize error reporting (see PCICTL0/1), but * for now assume that the firmware has done the right thing * already. @@ -193,83 +188,40 @@ polaris_init_arch(unsigned long *mem_start, unsigned long *mem_end) #if 0 printk("polaris_init_arch(): trusting firmware for setup\n"); #endif + + /* + * Create our single hose. + */ + + hose = alloc_pci_controler(mem_start); + hose->io_space = &ioport_resource; + hose->mem_space = &iomem_resource; + hose->config_space = POLARIS_DENSE_CONFIG_BASE; + hose->index = 0; } -int polaris_pci_clr_err(void) +static inline void +polaris_pci_clr_err(void) { - POLARIS_jd = *((vusp)POLARIS_W_STATUS); - DBG_MCK(("POLARIS_pci_clr_err: POLARIS_W_STATUS after read 0x%x\n", - POLARIS_jd)); + *(vusp)POLARIS_W_STATUS; /* Write 1's to settable bits to clear errors */ - *((vusp)POLARIS_W_STATUS) = 0x7800; mb(); - POLARIS_jd = *((vusp)POLARIS_W_STATUS); - return 0; + *(vusp)POLARIS_W_STATUS = 0x7800; + mb(); + *(vusp)POLARIS_W_STATUS; } -void polaris_machine_check(unsigned long vector, unsigned long la_ptr, - struct pt_regs * regs) +void +polaris_machine_check(unsigned long vector, unsigned long la_ptr, + struct pt_regs * regs) { - struct el_common *mchk_header; - struct el_POLARIS_sysdata_mcheck *mchk_sysdata; - - mchk_header = (struct el_common *)la_ptr; - - mchk_sysdata = - (struct el_POLARIS_sysdata_mcheck *)(la_ptr+mchk_header->sys_offset); - -#if 0 - DBG_MCK(("polaris_machine_check: vector=0x%lx la_ptr=0x%lx\n", - vector, la_ptr)); - DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", - regs->pc, mchk_header->size, mchk_header->proc_offset, - mchk_header->sys_offset)); - DBG_MCK(("polaris_machine_check: expected %d status 0x%lx\n", - POLARIS_mcheck_expected, mchk_sysdata->psc_status)); -#endif -#ifdef DEBUG_MCHECK_DUMP - { - unsigned long *ptr; - int i; - - ptr = (unsigned long *)la_ptr; - for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { - printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]); - } - } -#endif /* DEBUG_MCHECK_DUMP */ - /* - * Check if machine check is due to a badaddr() and if so, - * ignore the machine check. - */ + /* Clear the error before any reporting. */ mb(); mb(); - if (POLARIS_mcheck_expected) { - DBG_MCK(("POLARIS machine check expected\n")); - POLARIS_mcheck_expected = 0; - POLARIS_mcheck_taken = 1; - mb(); - mb(); - draina(); - polaris_pci_clr_err(); - wrmces(0x7); - mb(); - } -#if 1 - else { - printk("POLARIS machine check NOT expected\n") ; - DBG_MCK(("polaris_machine_check: vector=0x%lx la_ptr=0x%lx\n", - vector, la_ptr)); - DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", - regs->pc, mchk_header->size, mchk_header->proc_offset, - mchk_header->sys_offset)); - POLARIS_mcheck_expected = 0; - POLARIS_mcheck_taken = 1; - mb(); - mb(); - draina(); - polaris_pci_clr_err(); - wrmces(0x7); - mb(); - } -#endif + draina(); + polaris_pci_clr_err(); + wrmces(0x7); + mb(); + + process_mcheck_info(vector, la_ptr, regs, "POLARIS", + mcheck_expected(0)); } diff --git a/arch/alpha/kernel/core_pyxis.c b/arch/alpha/kernel/core_pyxis.c index f0a5c3eb8..88a3e37c9 100644 --- a/arch/alpha/kernel/core_pyxis.c +++ b/arch/alpha/kernel/core_pyxis.c @@ -1,12 +1,11 @@ /* * linux/arch/alpha/kernel/core_pyxis.c * - * Code common to all PYXIS core logic chips. - * * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com). * + * Code common to all PYXIS core logic chips. */ -#include <linux/config.h> + #include <linux/kernel.h> #include <linux/types.h> #include <linux/pci.h> @@ -15,6 +14,7 @@ #include <asm/ptrace.h> #include <asm/system.h> +#include <asm/pci.h> #define __EXTERN_INLINE inline #include <asm/io.h> @@ -22,6 +22,8 @@ #undef __EXTERN_INLINE #include "proto.h" +#include "pci_impl.h" + /* NOTE: Herein are back-to-back mb instructions. They are magic. One plausible explanation is that the I/O controller does not properly @@ -32,7 +34,6 @@ */ #define DEBUG_CONFIG 0 -#define DEBUG_MCHECK 0 #if DEBUG_CONFIG # define DBG_CNF(args) printk args @@ -40,18 +41,6 @@ # define DBG_CNF(args) #endif -#if DEBUG_MCHECK -# define DBG_MCK(args) printk args -# define DEBUG_MCHECK_DUMP -#else -# define DBG_MCK(args) -#endif - - -static volatile unsigned int PYXIS_mcheck_expected = 0; -static volatile unsigned int PYXIS_mcheck_taken = 0; -static unsigned int PYXIS_jd; - /* * Given a bus, device, and function number, compute resulting @@ -96,9 +85,12 @@ static unsigned int PYXIS_jd; */ static int -mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr, +mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr, unsigned char *type1) { + u8 bus = dev->bus->number; + u8 device_fn = dev->devfn; + *type1 = (bus == 0) ? 0 : 1; *pci_addr = (bus << 16) | (device_fn << 8) | (where); @@ -132,8 +124,8 @@ conf_read(unsigned long addr, unsigned char type1) mb(); draina(); - PYXIS_mcheck_expected = 1; - PYXIS_mcheck_taken = 0; + mcheck_expected(0) = 1; + mcheck_taken(0) = 0; mb(); /* Access configuration space. */ @@ -141,12 +133,12 @@ conf_read(unsigned long addr, unsigned char type1) mb(); mb(); /* magic */ - if (PYXIS_mcheck_taken) { - PYXIS_mcheck_taken = 0; + if (mcheck_taken(0)) { + mcheck_taken(0) = 0; value = 0xffffffffU; mb(); } - PYXIS_mcheck_expected = 0; + mcheck_expected(0) = 0; mb(); /* If Type1 access, must reset IOC CFG so normal IO space ops work. */ @@ -186,15 +178,15 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1) mb(); draina(); - PYXIS_mcheck_expected = 1; - PYXIS_mcheck_taken = 0; + mcheck_expected(0) = 1; + mcheck_taken(0) = 0; mb(); /* Access configuration space. */ *(vuip)addr = value; mb(); temp = *(vuip)addr; /* read back to force the write */ - PYXIS_mcheck_expected = 0; + mcheck_expected(0) = 0; mb(); /* If Type1 access, must reset IOC CFG so normal IO space ops work. */ @@ -209,106 +201,95 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1) addr, value, type1)); } -int -pyxis_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value, - struct linux_hose_info *hose) +static int +pyxis_read_config_byte(struct pci_dev *dev, int where, u8 *value) { - unsigned long addr = PYXIS_CONF; - unsigned long pci_addr; + unsigned long addr, pci_addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + if (mk_conf_addr(dev, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - addr |= (pci_addr << 5) + 0x00; + addr = (pci_addr << 5) + 0x00 + PYXIS_CONF; *value = conf_read(addr, type1) >> ((where & 3) * 8); return PCIBIOS_SUCCESSFUL; } -int -pyxis_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value, - struct linux_hose_info *hose) +static int +pyxis_read_config_word(struct pci_dev *dev, int where, u16 *value) { - unsigned long addr = PYXIS_CONF; - unsigned long pci_addr; + unsigned long addr, pci_addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + if (mk_conf_addr(dev, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - addr |= (pci_addr << 5) + 0x08; + addr = (pci_addr << 5) + 0x08 + PYXIS_CONF; *value = conf_read(addr, type1) >> ((where & 3) * 8); return PCIBIOS_SUCCESSFUL; } -int -pyxis_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value, - struct linux_hose_info *hose) +static int +pyxis_read_config_dword(struct pci_dev *dev, int where, u32 *value) { - unsigned long addr = PYXIS_CONF; - unsigned long pci_addr; + unsigned long addr, pci_addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + if (mk_conf_addr(dev, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - addr |= (pci_addr << 5) + 0x18; + addr = (pci_addr << 5) + 0x18 + PYXIS_CONF; *value = conf_read(addr, type1); return PCIBIOS_SUCCESSFUL; } -int -pyxis_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value, - struct linux_hose_info *hose) +static int +pyxis_write_config(struct pci_dev *dev, int where, u32 value, long mask) { - unsigned long addr = PYXIS_CONF; - unsigned long pci_addr; + unsigned long addr, pci_addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + if (mk_conf_addr(dev, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - addr |= (pci_addr << 5) + 0x00; + addr = (pci_addr << 5) + mask + PYXIS_CONF; conf_write(addr, value << ((where & 3) * 8), type1); return PCIBIOS_SUCCESSFUL; } -int -pyxis_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value, - struct linux_hose_info *hose) +static int +pyxis_write_config_byte(struct pci_dev *dev, int where, u8 value) { - unsigned long addr = PYXIS_CONF; - unsigned long pci_addr; - unsigned char type1; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) - return PCIBIOS_DEVICE_NOT_FOUND; - - addr |= (pci_addr << 5) + 0x08; - conf_write(addr, value << ((where & 3) * 8), type1); - return PCIBIOS_SUCCESSFUL; + return pyxis_write_config(dev, where, value, 0x00); } -int -pyxis_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value, - struct linux_hose_info *hose) +static int +pyxis_write_config_word(struct pci_dev *dev, int where, u16 value) { - unsigned long addr = PYXIS_CONF; - unsigned long pci_addr; - unsigned char type1; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) - return PCIBIOS_DEVICE_NOT_FOUND; + return pyxis_write_config(dev, where, value, 0x08); +} - addr |= (pci_addr << 5) + 0x18; - conf_write(addr, value << ((where & 3) * 8), type1); - return PCIBIOS_SUCCESSFUL; +static int +pyxis_write_config_dword(struct pci_dev *dev, int where, u32 value) +{ + return pyxis_write_config(dev, where, value, 0x18); } +struct pci_ops pyxis_pci_ops = +{ + read_byte: pyxis_read_config_byte, + read_word: pyxis_read_config_word, + read_dword: pyxis_read_config_dword, + write_byte: pyxis_write_config_byte, + write_word: pyxis_write_config_word, + write_dword: pyxis_write_config_dword +}; + void __init -pyxis_enable_errors (void) +pyxis_init_arch(unsigned long *mem_start, unsigned long *mem_end) { - unsigned int pyxis_err; + struct pci_controler *hose; + unsigned int temp; #if 0 printk("pyxis_init: PYXIS_ERR_MASK 0x%x\n", *(vuip)PYXIS_ERR_MASK); @@ -324,126 +305,37 @@ pyxis_enable_errors (void) /* * Set up error reporting. Make sure CPU_PE is OFF in the mask. */ - pyxis_err = *(vuip)PYXIS_ERR_MASK; - pyxis_err &= ~4; - *(vuip)PYXIS_ERR_MASK = pyxis_err; mb(); - pyxis_err = *(vuip)PYXIS_ERR_MASK; /* re-read to force write */ - - pyxis_err = *(vuip)PYXIS_ERR ; - pyxis_err |= 0x180; /* master/target abort */ - *(vuip)PYXIS_ERR = pyxis_err; mb(); - pyxis_err = *(vuip)PYXIS_ERR; /* re-read to force write */ -} + temp = *(vuip)PYXIS_ERR_MASK; + temp &= ~4; + *(vuip)PYXIS_ERR_MASK = temp; mb(); + temp = *(vuip)PYXIS_ERR_MASK; /* re-read to force write */ -int __init -pyxis_srm_window_setup (void) -{ - switch (alpha_use_srm_setup) - { - default: -#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP) - /* Check window 0 for enabled and mapped to 0. */ - if (((*(vuip)PYXIS_W0_BASE & 3) == 1) - && (*(vuip)PYXIS_T0_BASE == 0) - && ((*(vuip)PYXIS_W0_MASK & 0xfff00000U) > 0x0ff00000U)) { - PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W0_BASE & 0xfff00000U; - PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W0_MASK & 0xfff00000U; - PYXIS_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("pyxis_init: using Window 0 settings\n"); - printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vuip)PYXIS_W0_BASE, - *(vuip)PYXIS_W0_MASK, - *(vuip)PYXIS_T0_BASE); -#endif - break; - } - - /* Check window 1 for enabled and mapped to 0. */ - if (((*(vuip)PYXIS_W1_BASE & 3) == 1) - && (*(vuip)PYXIS_T1_BASE == 0) - && ((*(vuip)PYXIS_W1_MASK & 0xfff00000U) > 0x0ff00000U)) { - PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W1_BASE & 0xfff00000U; - PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W1_MASK & 0xfff00000U; - PYXIS_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("pyxis_init: using Window 1 settings\n"); - printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vuip)PYXIS_W1_BASE, - *(vuip)PYXIS_W1_MASK, - *(vuip)PYXIS_T1_BASE); -#endif - break; - } + temp = *(vuip)PYXIS_ERR ; + temp |= 0x180; /* master/target abort */ + *(vuip)PYXIS_ERR = temp; mb(); + temp = *(vuip)PYXIS_ERR; /* re-read to force write */ - /* Check window 2 for enabled and mapped to 0. */ - if (((*(vuip)PYXIS_W2_BASE & 3) == 1) - && (*(vuip)PYXIS_T2_BASE == 0) - && ((*(vuip)PYXIS_W2_MASK & 0xfff00000U) > 0x0ff00000U)) { - PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W2_BASE & 0xfff00000U; - PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W2_MASK & 0xfff00000U; - PYXIS_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("pyxis_init: using Window 2 settings\n"); - printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vuip)PYXIS_W2_BASE, - *(vuip)PYXIS_W2_MASK, - *(vuip)PYXIS_T2_BASE); -#endif - break; - } - - /* Check window 3 for enabled and mapped to 0. */ - if (((*(vuip)PYXIS_W3_BASE & 3) == 1) - && (*(vuip)PYXIS_T3_BASE == 0) - && ((*(vuip)PYXIS_W3_MASK & 0xfff00000U) > 0x0ff00000U)) { - PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W3_BASE & 0xfff00000U; - PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W3_MASK & 0xfff00000U; - PYXIS_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("pyxis_init: using Window 3 settings\n"); - printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vuip)PYXIS_W3_BASE, - *(vuip)PYXIS_W3_MASK, - *(vuip)PYXIS_T3_BASE); -#endif - break; - } - - /* Otherwise, we must use our defaults. */ - PYXIS_DMA_WIN_BASE = PYXIS_DMA_WIN_BASE_DEFAULT; - PYXIS_DMA_WIN_SIZE = PYXIS_DMA_WIN_SIZE_DEFAULT; -#endif - case 0: - return 0; - } - return 1; -} - -void __init -pyxis_native_window_setup(void) -{ /* * Set up the PCI->physical memory translation windows. - * For now, windows 1,2 and 3 are disabled. In the future, we may + * For now, windows 2 and 3 are disabled. In the future, we may * want to use them to do scatter/gather DMA. * - * Window 0 goes at 1 GB and is 1 GB large. + * Window 0 goes at 2 GB and is 1 GB large. + * Window 1 goes at 3 GB and is 1 GB large. */ - *(vuip)PYXIS_W0_BASE = 1U | (PYXIS_DMA_WIN_BASE_DEFAULT & 0xfff00000U); - *(vuip)PYXIS_W0_MASK = (PYXIS_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U; - *(vuip)PYXIS_T0_BASE = 0; + *(vuip)PYXIS_W0_BASE = PYXIS_DMA_WIN0_BASE_DEFAULT | 1U; + *(vuip)PYXIS_W0_MASK = (PYXIS_DMA_WIN0_SIZE_DEFAULT - 1) & 0xfff00000U; + *(vuip)PYXIS_T0_BASE = PYXIS_DMA_WIN0_TRAN_DEFAULT >> 2; + + *(vuip)PYXIS_W1_BASE = PYXIS_DMA_WIN1_BASE_DEFAULT | 1U; + *(vuip)PYXIS_W1_MASK = (PYXIS_DMA_WIN1_SIZE_DEFAULT - 1) & 0xfff00000U; + *(vuip)PYXIS_T1_BASE = PYXIS_DMA_WIN1_TRAN_DEFAULT >> 2; - *(vuip)PYXIS_W1_BASE = 0x0 ; - *(vuip)PYXIS_W2_BASE = 0x0 ; - *(vuip)PYXIS_W3_BASE = 0x0 ; + *(vuip)PYXIS_W2_BASE = 0x0; + *(vuip)PYXIS_W3_BASE = 0x0; mb(); -} -void __init -pyxis_finish_init_arch(void) -{ /* * Next, clear the PYXIS_CFG register, which gets used * for PCI Config Space accesses. That is the way @@ -462,42 +354,11 @@ pyxis_finish_init_arch(void) } } - /* - * Sigh... For the SRM setup, unless we know apriori what the HAE - * contents will be, we need to setup the arbitrary region bases - * so we can test against the range of addresses and tailor the - * region chosen for the SPARSE memory access. - * - * See include/asm-alpha/pyxis.h for the SPARSE mem read/write. - */ - if (alpha_use_srm_setup) { - unsigned int pyxis_hae_mem = *(vuip)PYXIS_HAE_MEM; - - alpha_mv.sm_base_r1 = (pyxis_hae_mem ) & 0xe0000000UL; - alpha_mv.sm_base_r2 = (pyxis_hae_mem << 16) & 0xf8000000UL; - alpha_mv.sm_base_r3 = (pyxis_hae_mem << 24) & 0xfc000000UL; - - /* - * Set the HAE cache, so that setup_arch() code - * will use the SRM setting always. Our readb/writeb - * code in pyxis.h expects never to have to change - * the contents of the HAE. - */ - alpha_mv.hae_cache = pyxis_hae_mem; - -#ifndef CONFIG_ALPHA_GENERIC - /* In a generic kernel, we can always use BWIO. */ - alpha_mv.mv_readb = pyxis_srm_readb; - alpha_mv.mv_readw = pyxis_srm_readw; - alpha_mv.mv_writeb = pyxis_srm_writeb; - alpha_mv.mv_writew = pyxis_srm_writew; -#endif - } else { - *(vuip)PYXIS_HAE_MEM = 0U; mb(); - *(vuip)PYXIS_HAE_MEM; /* re-read to force write */ - *(vuip)PYXIS_HAE_IO = 0; mb(); - *(vuip)PYXIS_HAE_IO; /* re-read to force write */ - } + /* Zero the HAE. */ + *(vuip)PYXIS_HAE_MEM = 0U; mb(); + *(vuip)PYXIS_HAE_MEM; /* re-read to force write */ + *(vuip)PYXIS_HAE_IO = 0; mb(); + *(vuip)PYXIS_HAE_IO; /* re-read to force write */ /* * Finally, check that the PYXIS_CTRL1 has IOA_BEN set for @@ -514,94 +375,38 @@ pyxis_finish_init_arch(void) ctrl1 = *(vuip)PYXIS_CTRL1; /* re-read */ } } -} -void __init -pyxis_init_arch(unsigned long *mem_start, unsigned long *mem_end) -{ - pyxis_enable_errors(); - if (!pyxis_srm_window_setup()) - pyxis_native_window_setup(); - pyxis_finish_init_arch(); + /* + * Create our single hose. + */ + + hose = alloc_pci_controler(mem_start); + hose->io_space = &ioport_resource; + hose->mem_space = &iomem_resource; + hose->config_space = PYXIS_CONF; + hose->index = 0; } -static int +static inline void pyxis_pci_clr_err(void) { - PYXIS_jd = *(vuip)PYXIS_ERR; - DBG_MCK(("PYXIS_pci_clr_err: PYXIS ERR after read 0x%x\n", PYXIS_jd)); - *(vuip)PYXIS_ERR = 0x0180; mb(); - PYXIS_jd = *(vuip)PYXIS_ERR; /* re-read to force write */ - return 0; + *(vuip)PYXIS_ERR; + *(vuip)PYXIS_ERR = 0x0180; + mb(); + *(vuip)PYXIS_ERR; /* re-read to force write */ } void pyxis_machine_check(unsigned long vector, unsigned long la_ptr, struct pt_regs * regs) { - struct el_common *mchk_header; - struct el_PYXIS_sysdata_mcheck *mchk_sysdata; - - mchk_header = (struct el_common *)la_ptr; - - mchk_sysdata = (struct el_PYXIS_sysdata_mcheck *) - (la_ptr + mchk_header->sys_offset); - -#if 0 - DBG_MCK(("pyxis_machine_check: vector=0x%lx la_ptr=0x%lx\n", - vector, la_ptr)); - DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", - regs->pc, mchk_header->size, mchk_header->proc_offset, - mchk_header->sys_offset)); - DBG_MCK(("pyxis_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n", - PYXIS_mcheck_expected, mchk_sysdata->epic_dcsr, - mchk_sysdata->epic_pear)); -#endif - - /* - * Check if machine check is due to a badaddr() and if so, - * ignore the machine check. - */ + /* Clear the error before reporting anything. */ mb(); mb(); /* magic */ - if (PYXIS_mcheck_expected) { - DBG_MCK(("PYXIS machine check expected\n")); - PYXIS_mcheck_expected = 0; - PYXIS_mcheck_taken = 1; - mb(); - mb(); /* magic */ - draina(); - pyxis_pci_clr_err(); - wrmces(0x7); - mb(); - } - else { - printk("PYXIS machine check NOT expected\n") ; - DBG_MCK(("pyxis_machine_check: vector=0x%lx la_ptr=0x%lx\n", - vector, la_ptr)); - DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x" - " sysoffset 0x%x\n", - regs->pc, mchk_header->size, mchk_header->proc_offset, - mchk_header->sys_offset)); - PYXIS_mcheck_expected = 0; - PYXIS_mcheck_taken = 1; - mb(); - mb(); /* magic */ - draina(); - pyxis_pci_clr_err(); - wrmces(0x7); - mb(); - -#ifdef DEBUG_MCHECK_DUMP - { - unsigned long *ptr = (unsigned long *)la_ptr;; - long n = mchk_header->size / (2*sizeof(long)); + draina(); + pyxis_pci_clr_err(); + wrmces(0x7); + mb(); - do - printk(" +%lx %lx %lx\n", i*sizeof(long), - ptr[i], ptr[i+1]); - while (--i); - } -#endif - } + process_mcheck_info(vector, la_ptr, regs, "PYXIS", mcheck_expected(0)); } diff --git a/arch/alpha/kernel/core_t2.c b/arch/alpha/kernel/core_t2.c index c7ec2b6ee..43103f8eb 100644 --- a/arch/alpha/kernel/core_t2.c +++ b/arch/alpha/kernel/core_t2.c @@ -1,15 +1,14 @@ /* * linux/arch/alpha/kernel/core_t2.c * - * Code common to all T2 core logic chips. - * * Written by Jay A Estabrook (jestabro@amt.tay1.dec.com). * December 1996. * * based on CIA code by David A Rusling (david.rusling@reo.mts.dec.com) * + * Code common to all T2 core logic chips. */ -#include <linux/config.h> + #include <linux/kernel.h> #include <linux/types.h> #include <linux/pci.h> @@ -18,6 +17,7 @@ #include <asm/ptrace.h> #include <asm/system.h> +#include <asm/pci.h> #define __EXTERN_INLINE #include <asm/io.h> @@ -25,6 +25,8 @@ #undef __EXTERN_INLINE #include "proto.h" +#include "pci_impl.h" + /* * NOTE: Herein lie back-to-back mb instructions. They are magic. @@ -33,36 +35,17 @@ */ /* - * Machine check reasons. Defined according to PALcode sources - * (osf.h and platform.h). - */ -#define MCHK_K_TPERR 0x0080 -#define MCHK_K_TCPERR 0x0082 -#define MCHK_K_HERR 0x0084 -#define MCHK_K_ECC_C 0x0086 -#define MCHK_K_ECC_NC 0x0088 -#define MCHK_K_OS_BUGCHECK 0x008A -#define MCHK_K_PAL_BUGCHECK 0x0090 - -/* * BIOS32-style PCI interface: */ -#ifdef DEBUG_CONF +#define DEBUG_CONFIG 0 + +#if DEBUG_CONFIG # define DBG(args) printk args #else # define DBG(args) #endif -#ifdef DEBUG_MCHECK -# define DBGMC(args) printk args -#else -# define DBGMC(args) -#endif - -static volatile unsigned int T2_mcheck_expected[NR_CPUS]; -static volatile unsigned int T2_mcheck_taken[NR_CPUS]; - /* * Given a bus, device, and function number, compute resulting @@ -107,10 +90,12 @@ static volatile unsigned int T2_mcheck_taken[NR_CPUS]; */ static int -mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr, +mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr, unsigned char *type1) { unsigned long addr; + u8 bus = dev->bus->number; + u8 device_fn = dev->devfn; DBG(("mk_conf_addr(bus=%d, dfn=0x%x, where=0x%x," " addr=0x%lx, type1=0x%x)\n", @@ -173,8 +158,8 @@ conf_read(unsigned long addr, unsigned char type1) mb(); draina(); - T2_mcheck_expected[cpu] = 1; - T2_mcheck_taken[cpu] = 0; + mcheck_expected(cpu) = 1; + mcheck_taken(cpu) = 0; mb(); /* Access configuration space. */ @@ -182,12 +167,12 @@ conf_read(unsigned long addr, unsigned char type1) mb(); mb(); /* magic */ - if (T2_mcheck_taken[cpu]) { - T2_mcheck_taken[cpu] = 0; + if (mcheck_taken(cpu)) { + mcheck_taken(cpu) = 0; value = 0xffffffffU; mb(); } - T2_mcheck_expected[cpu] = 0; + mcheck_expected(cpu) = 0; mb(); /* If Type1 access, must reset T2 CFG so normal IO space ops work. */ @@ -233,7 +218,7 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1) mb(); draina(); - T2_mcheck_expected[cpu] = 1; + mcheck_expected(cpu) = 1; mb(); /* Access configuration space. */ @@ -241,7 +226,7 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1) mb(); mb(); /* magic */ - T2_mcheck_expected[cpu] = 0; + mcheck_expected(cpu) = 0; mb(); /* If Type1 access, must reset T2 CFG so normal IO space ops work. */ @@ -253,110 +238,99 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1) __restore_flags(flags); } -int -t2_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value, - struct linux_hose_info *hose) +static int +t2_read_config_byte(struct pci_dev *dev, int where, u8 *value) { - unsigned long addr = T2_CONF; - unsigned long pci_addr; + unsigned long addr, pci_addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + if (mk_conf_addr(dev, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - addr |= (pci_addr << 5) + 0x00; + addr = (pci_addr << 5) + 0x00 + T2_CONF; *value = conf_read(addr, type1) >> ((where & 3) * 8); return PCIBIOS_SUCCESSFUL; } -int -t2_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value, - struct linux_hose_info *hose) +static int +t2_read_config_word(struct pci_dev *dev, int where, u16 *value) { - unsigned long addr = T2_CONF; - unsigned long pci_addr; + unsigned long addr, pci_addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + if (mk_conf_addr(dev, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - addr |= (pci_addr << 5) + 0x08; + addr = (pci_addr << 5) + 0x08 + T2_CONF; *value = conf_read(addr, type1) >> ((where & 3) * 8); return PCIBIOS_SUCCESSFUL; } -int -t2_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value, - struct linux_hose_info *hose) +static int +t2_read_config_dword(struct pci_dev *dev, int where, u32 *value) { - unsigned long addr = T2_CONF; - unsigned long pci_addr; + unsigned long addr, pci_addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + if (mk_conf_addr(dev, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - addr |= (pci_addr << 5) + 0x18; + addr = (pci_addr << 5) + 0x18 + T2_CONF; *value = conf_read(addr, type1); return PCIBIOS_SUCCESSFUL; } -int -t2_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value, - struct linux_hose_info *hose) +static int +t2_write_config(struct pci_dev *dev, int where, u32 value, long mask) { - unsigned long addr = T2_CONF; - unsigned long pci_addr; + unsigned long addr, pci_addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + if (mk_conf_addr(dev, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - addr |= (pci_addr << 5) + 0x00; + addr = (pci_addr << 5) + mask + T2_CONF; conf_write(addr, value << ((where & 3) * 8), type1); return PCIBIOS_SUCCESSFUL; } -int -t2_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value, - struct linux_hose_info *hose) +static int +t2_write_config_byte(struct pci_dev *dev, int where, u8 value) { - unsigned long addr = T2_CONF; - unsigned long pci_addr; - unsigned char type1; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) - return PCIBIOS_DEVICE_NOT_FOUND; - - addr |= (pci_addr << 5) + 0x08; - conf_write(addr, value << ((where & 3) * 8), type1); - return PCIBIOS_SUCCESSFUL; + return t2_write_config(dev, where, value, 0x00); } -int -t2_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value, - struct linux_hose_info *hose) +static int +t2_write_config_word(struct pci_dev *dev, int where, u16 value) { - unsigned long addr = T2_CONF; - unsigned long pci_addr; - unsigned char type1; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) - return PCIBIOS_DEVICE_NOT_FOUND; + return t2_write_config(dev, where, value, 0x08); +} - addr |= (pci_addr << 5) + 0x18; - conf_write(addr, value << ((where & 3) * 8), type1); - return PCIBIOS_SUCCESSFUL; +static int +t2_write_config_dword(struct pci_dev *dev, int where, u32 value) +{ + return t2_write_config(dev, where, value, 0x18); } +struct pci_ops t2_pci_ops = +{ + read_byte: t2_read_config_byte, + read_word: t2_read_config_word, + read_dword: t2_read_config_dword, + write_byte: t2_write_config_byte, + write_word: t2_write_config_word, + write_dword: t2_write_config_dword +}; + void __init t2_init_arch(unsigned long *mem_start, unsigned long *mem_end) { + struct pci_controler *hose; unsigned int i; for (i = 0; i < NR_CPUS; i++) { - T2_mcheck_expected[i] = 0; - T2_mcheck_taken[i] = 0; + mcheck_expected(i) = 0; + mcheck_taken(i) = 0; } #if 0 @@ -383,125 +357,59 @@ t2_init_arch(unsigned long *mem_start, unsigned long *mem_end) *(vulp)T2_TBASE2); #endif - switch (alpha_use_srm_setup) - { - default: -#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP) - /* Check window 1 for enabled and mapped to 0. */ - if (((*(vulp)T2_WBASE1 & (3UL<<18)) == (2UL<<18)) - && (*(vulp)T2_TBASE1 == 0)) { - T2_DMA_WIN_BASE = *(vulp)T2_WBASE1 & 0xfff00000UL; - T2_DMA_WIN_SIZE = *(vulp)T2_WMASK1 & 0xfff00000UL; - T2_DMA_WIN_SIZE += 0x00100000UL; - /* DISABLE window 2!! ?? */ -#if 1 - printk("t2_init: using Window 1 settings\n"); - printk("t2_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n", - *(vulp)T2_WBASE1, - *(vulp)T2_WMASK1, - *(vulp)T2_TBASE1); -#endif - break; - } + /* + * Set up the PCI->physical memory translation windows. + * For now, window 2 is disabled. In the future, we may + * want to use it to do scatter/gather DMA. + * + * Window 1 goes at 1 GB and is 1 GB large. + */ - /* Check window 2 for enabled and mapped to 0. */ - if (((*(vulp)T2_WBASE2 & (3UL<<18)) == (2UL<<18)) - && (*(vulp)T2_TBASE2 == 0)) { - T2_DMA_WIN_BASE = *(vulp)T2_WBASE2 & 0xfff00000UL; - T2_DMA_WIN_SIZE = *(vulp)T2_WMASK2 & 0xfff00000UL; - T2_DMA_WIN_SIZE += 0x00100000UL; - /* DISABLE window 1!! ?? */ -#if 1 - printk("t2_init: using Window 2 settings\n"); - printk("t2_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n", - *(vulp)T2_WBASE2, - *(vulp)T2_WMASK2, - *(vulp)T2_TBASE2); -#endif - break; - } + /* WARNING!! must correspond to the DMA_WIN params!!! */ + *(vulp)T2_WBASE1 = 0x400807ffU; + *(vulp)T2_WMASK1 = 0x3ff00000U; + *(vulp)T2_TBASE1 = 0; + + *(vulp)T2_WBASE2 = 0x0; + *(vulp)T2_HBASE = 0x0; - /* Otherwise, we must use our defaults. */ - T2_DMA_WIN_BASE = T2_DMA_WIN_BASE_DEFAULT; - T2_DMA_WIN_SIZE = T2_DMA_WIN_SIZE_DEFAULT; + /* Zero HAE. */ + *(vulp)T2_HAE_1 = 0; mb(); + *(vulp)T2_HAE_2 = 0; mb(); + *(vulp)T2_HAE_3 = 0; mb(); +#if 0 + *(vulp)T2_HAE_4 = 0; mb(); /* do not touch this */ #endif - case 0: - /* - * Set up the PCI->physical memory translation windows. - * For now, window 2 is disabled. In the future, we may - * want to use it to do scatter/gather DMA. - * - * Window 1 goes at 1 GB and is 1 GB large. - */ - - /* WARNING!! must correspond to the DMA_WIN params!!! */ - *(vulp)T2_WBASE1 = 0x400807ffU; - *(vulp)T2_WMASK1 = 0x3ff00000U; - *(vulp)T2_TBASE1 = 0; - - *(vulp)T2_WBASE2 = 0x0; - *(vulp)T2_HBASE = 0x0; - break; - } /* - * Sigh... For the SRM setup, unless we know apriori what the HAE - * contents will be, we need to setup the arbitrary region bases - * so we can test against the range of addresses and tailor the - * region chosen for the SPARSE memory access. - * - * See include/asm-alpha/t2.h for the SPARSE mem read/write. + * Create our single hose. */ - if (alpha_use_srm_setup) { - unsigned long t2_hae_1 = *(vulp)T2_HAE_1; - - alpha_mv.sm_base_r1 = (t2_hae_1 << 27) & 0xf8000000UL; - - /* - * Set the HAE cache, so that setup_arch() code - * will use the SRM setting always. Our readb/writeb - * code in .h expects never to have to change - * the contents of the HAE. - */ - alpha_mv.hae_cache = t2_hae_1; - - alpha_mv.mv_readb = t2_srm_readb; - alpha_mv.mv_readw = t2_srm_readw; - alpha_mv.mv_writeb = t2_srm_writeb; - alpha_mv.mv_writew = t2_srm_writew; - } else { - *(vulp)T2_HAE_1 = 0; mb(); - *(vulp)T2_HAE_2 = 0; mb(); - *(vulp)T2_HAE_3 = 0; mb(); -#if 0 - *(vulp)T2_HAE_4 = 0; mb(); /* do not touch this */ -#endif - } + + hose = alloc_pci_controler(mem_start); + hose->io_space = &ioport_resource; + hose->mem_space = &iomem_resource; + hose->config_space = T2_CONF; + hose->index = 0; } #define SIC_SEIC (1UL << 33) /* System Event Clear */ -static int -t2_clear_errors(void) +static void +t2_clear_errors(int cpu) { - unsigned int cpu = smp_processor_id(); - static struct sable_cpu_csr *cpu_regs = NULL; - - switch (cpu) - { - case 0: cpu_regs = (struct sable_cpu_csr *)T2_CPU0_BASE; break; - case 1: cpu_regs = (struct sable_cpu_csr *)T2_CPU1_BASE; break; - case 2: cpu_regs = (struct sable_cpu_csr *)T2_CPU2_BASE; break; - case 3: cpu_regs = (struct sable_cpu_csr *)T2_CPU3_BASE; break; - } - - DBGMC(("???????? t2_clear_errors\n")); - + struct sable_cpu_csr *cpu_regs; + + cpu_regs = (struct sable_cpu_csr *)T2_CPU0_BASE; + if (cpu == 1) + cpu_regs = (struct sable_cpu_csr *)T2_CPU1_BASE; + if (cpu == 2) + cpu_regs = (struct sable_cpu_csr *)T2_CPU2_BASE; + if (cpu == 3) + cpu_regs = (struct sable_cpu_csr *)T2_CPU3_BASE; + cpu_regs->sic &= ~SIC_SEIC; - /* - * clear CPU errors - */ + /* Clear CPU errors. */ cpu_regs->bcce |= cpu_regs->bcce; cpu_regs->cbe |= cpu_regs->cbe; cpu_regs->bcue |= cpu_regs->bcue; @@ -512,116 +420,21 @@ t2_clear_errors(void) mb(); mb(); /* magic */ - return 0; } void t2_machine_check(unsigned long vector, unsigned long la_ptr, struct pt_regs * regs) { - struct el_t2_logout_header *mchk_header; - struct el_t2_procdata_mcheck *mchk_procdata; - struct el_t2_sysdata_mcheck *mchk_sysdata; - unsigned long * ptr; - const char * reason; - char buf[128]; - long i; - unsigned int cpu = smp_processor_id(); - - DBGMC(("t2_machine_check: vector=0x%lx la_ptr=0x%lx\n", - vector, la_ptr)); - - mchk_header = (struct el_t2_logout_header *)la_ptr; - - DBGMC(("t2_machine_check: susoffset=0x%lx procoffset=0x%lx\n", - mchk_header->elfl_sysoffset, mchk_header->elfl_procoffset)); - - mchk_sysdata = (struct el_t2_sysdata_mcheck *) - (la_ptr + mchk_header->elfl_sysoffset); - mchk_procdata = (struct el_t2_procdata_mcheck *) - (la_ptr + mchk_header->elfl_procoffset - sizeof(unsigned long)*32); - - DBGMC((" pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", - regs->pc, mchk_header->elfl_size, mchk_header->elfl_procoffset, - mchk_header->elfl_sysoffset)); - DBGMC(("t2_machine_check: expected %d\n", T2_mcheck_expected[cpu])); - -#ifdef DEBUG_DUMP - { - unsigned long *ptr; - int i; + int cpu = smp_processor_id(); - ptr = (unsigned long *)la_ptr; - for (i = 0; i < mchk_header->elfl_size/sizeof(long); i += 2) { - printk(" +%lx %lx %lx\n", i*sizeof(long), - ptr[i], ptr[i+1]); - } - } -#endif /* DEBUG_DUMP */ - - /* - * Check if machine check is due to a badaddr() and if so, - * ignore the machine check. - */ + /* Clear the error before any reporting. */ mb(); mb(); /* magic */ - if (T2_mcheck_expected[cpu]) { - DBGMC(("T2 machine check expected\n")); - T2_mcheck_taken[cpu] = 1; - t2_clear_errors(); - T2_mcheck_expected[cpu] = 0; - mb(); - mb(); /* magic */ - wrmces(rdmces()|1);/* ??? */ - draina(); - return; - } - - switch ((unsigned int) mchk_header->elfl_error_type) { - case MCHK_K_TPERR: reason = "tag parity error"; break; - case MCHK_K_TCPERR: reason = "tag control parity error"; break; - case MCHK_K_HERR: reason = "generic hard error"; break; - case MCHK_K_ECC_C: reason = "correctable ECC error"; break; - case MCHK_K_ECC_NC: reason = "uncorrectable ECC error"; break; - case MCHK_K_OS_BUGCHECK: reason = "OS-specific PAL bugcheck"; break; - case MCHK_K_PAL_BUGCHECK: reason = "callsys in kernel mode"; break; - case 0x96: reason = "i-cache read retryable error"; break; - case 0x98: reason = "processor detected hard error"; break; - - /* System specific (these are for Alcor, at least): */ - case 0x203: reason = "system detected uncorrectable ECC error"; break; - case 0x205: reason = "parity error detected by T2"; break; - case 0x207: reason = "non-existent memory error"; break; - case 0x209: reason = "PCI SERR detected"; break; - case 0x20b: reason = "PCI data parity error detected"; break; - case 0x20d: reason = "PCI address parity error detected"; break; - case 0x20f: reason = "PCI master abort error"; break; - case 0x211: reason = "PCI target abort error"; break; - case 0x213: reason = "scatter/gather PTE invalid error"; break; - case 0x215: reason = "flash ROM write error"; break; - case 0x217: reason = "IOA timeout detected"; break; - case 0x219: reason = "IOCHK#, EISA add-in board parity or other catastrophic error"; break; - case 0x21b: reason = "EISA fail-safe timer timeout"; break; - case 0x21d: reason = "EISA bus time-out"; break; - case 0x21f: reason = "EISA software generated NMI"; break; - case 0x221: reason = "unexpected ev5 IRQ[3] interrupt"; break; - default: - sprintf(buf, "reason for machine-check unknown (0x%x)", - (unsigned int) mchk_header->elfl_error_type); - reason = buf; - break; - } - wrmces(rdmces()|1); /* reset machine check pending flag */ + draina(); + t2_clear_errors(cpu); + wrmces(rdmces()|1); /* ??? */ mb(); - printk(KERN_CRIT " T2 machine check: %s%s\n", - reason, mchk_header->elfl_retry ? " (retryable)" : ""); - - /* Dump the logout area to give all info. */ - - ptr = (unsigned long *)la_ptr; - for (i = 0; i < mchk_header->elfl_size / sizeof(long); i += 2) { - printk(KERN_CRIT " +%8lx %016lx %016lx\n", - i*sizeof(long), ptr[i], ptr[i+1]); - } + process_mcheck_info(vector, la_ptr, regs, "T2", mcheck_expected(cpu)); } diff --git a/arch/alpha/kernel/core_tsunami.c b/arch/alpha/kernel/core_tsunami.c index efcce56d5..c0d7c867d 100644 --- a/arch/alpha/kernel/core_tsunami.c +++ b/arch/alpha/kernel/core_tsunami.c @@ -1,13 +1,11 @@ /* * linux/arch/alpha/kernel/core_tsunami.c * - * Code common to all TSUNAMI core logic chips. - * * Based on code written by David A. Rusling (david.rusling@reo.mts.dec.com). * + * Code common to all TSUNAMI core logic chips. */ -#include <linux/config.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/pci.h> @@ -17,6 +15,7 @@ #include <asm/ptrace.h> #include <asm/system.h> #include <asm/pci.h> +#include <asm/smp.h> #define __EXTERN_INLINE inline #include <asm/io.h> @@ -24,7 +23,9 @@ #undef __EXTERN_INLINE #include "proto.h" -#include "bios32.h" +#include "pci_impl.h" + +int TSUNAMI_bootcpu; /* * NOTE: Herein lie back-to-back mb instructions. They are magic. @@ -36,24 +37,15 @@ * BIOS32-style PCI interface: */ -#ifdef DEBUG_CONFIG +#define DEBUG_MCHECK 0 /* 0 = minimal, 1 = debug, 2 = debug+dump. */ +#define DEBUG_CONFIG 0 + +#if DEBUG_CONFIG # define DBG_CFG(args) printk args #else # define DBG_CFG(args) #endif -#define DEBUG_MCHECK -#ifdef DEBUG_MCHECK -# define DBG_MCK(args) printk args -#define DEBUG_MCHECK_DUMP -#else -# define DBG_MCK(args) -#endif - -static volatile unsigned int TSUNAMI_mcheck_expected[NR_CPUS]; -static volatile unsigned int TSUNAMI_mcheck_taken[NR_CPUS]; -static unsigned int TSUNAMI_jd[NR_CPUS]; -int TSUNAMI_bootcpu; /* * Given a bus, device, and function number, compute resulting @@ -90,115 +82,118 @@ int TSUNAMI_bootcpu; */ static int -mk_conf_addr(u8 bus, u8 device_fn, u8 where, struct linux_hose_info *hose, - unsigned long *pci_addr, unsigned char *type1) +mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr, + unsigned char *type1) { + struct pci_controler *hose = dev->sysdata ? : probing_hose; unsigned long addr; - - if (!pci_probe_enabled) - return -1; + u8 bus = dev->bus->number; + u8 device_fn = dev->devfn; DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, " "pci_addr=0x%p, type1=0x%p)\n", bus, device_fn, where, pci_addr, type1)); - *type1 = (bus != 0); - - if (hose->pci_first_busno == bus) + if (hose->first_busno == dev->bus->number) bus = 0; + *type1 = (bus != 0); addr = (bus << 16) | (device_fn << 8) | where; - addr |= hose->pci_config_space; + addr |= hose->config_space; *pci_addr = addr; DBG_CFG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr)); return 0; } -int -tsunami_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value, - struct linux_hose_info *hose) +static int +tsunami_read_config_byte(struct pci_dev *dev, int where, u8 *value) { unsigned long addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, hose, &addr, &type1)) + if (mk_conf_addr(dev, where, &addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; *value = __kernel_ldbu(*(vucp)addr); return PCIBIOS_SUCCESSFUL; } -int -tsunami_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value, - struct linux_hose_info *hose) +static int +tsunami_read_config_word(struct pci_dev *dev, int where, u16 *value) { unsigned long addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, hose, &addr, &type1)) + if (mk_conf_addr(dev, where, &addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; *value = __kernel_ldwu(*(vusp)addr); return PCIBIOS_SUCCESSFUL; } -int -tsunami_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value, - struct linux_hose_info *hose) +static int +tsunami_read_config_dword(struct pci_dev *dev, int where, u32 *value) { unsigned long addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, hose, &addr, &type1)) + if (mk_conf_addr(dev, where, &addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; *value = *(vuip)addr; return PCIBIOS_SUCCESSFUL; } -int -tsunami_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value, - struct linux_hose_info *hose) +static int +tsunami_write_config_byte(struct pci_dev *dev, int where, u8 value) { unsigned long addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, hose, &addr, &type1)) + if (mk_conf_addr(dev, where, &addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; __kernel_stb(value, *(vucp)addr); return PCIBIOS_SUCCESSFUL; } -int -tsunami_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value, - struct linux_hose_info *hose) +static int +tsunami_write_config_word(struct pci_dev *dev, int where, u16 value) { unsigned long addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, hose, &addr, &type1)) + if (mk_conf_addr(dev, where, &addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; __kernel_stw(value, *(vusp)addr); return PCIBIOS_SUCCESSFUL; } -int -tsunami_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value, - struct linux_hose_info *hose) +static int +tsunami_write_config_dword(struct pci_dev *dev, int where, u32 value) { unsigned long addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, hose, &addr, &type1)) + if (mk_conf_addr(dev, where, &addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; *(vuip)addr = value; return PCIBIOS_SUCCESSFUL; } +struct pci_ops tsunami_pci_ops = +{ + read_byte: tsunami_read_config_byte, + read_word: tsunami_read_config_word, + read_dword: tsunami_read_config_dword, + write_byte: tsunami_write_config_byte, + write_word: tsunami_write_config_word, + write_dword: tsunami_write_config_dword +}; + #ifdef NXM_MACHINE_CHECKS_ON_TSUNAMI static long tsunami_probe_read(volatile unsigned long *vaddr) @@ -207,13 +202,14 @@ tsunami_probe_read(volatile unsigned long *vaddr) int cpu = smp_processor_id(); int s = swpipl(6); /* Block everything but machine checks. */ - TSUNAMI_mcheck_taken[cpu] = 0; - TSUNAMI_mcheck_expected[cpu] = 1; + mcheck_taken(cpu) = 0; + mcheck_expected(cpu) = 1; + mb(); dont_care = *vaddr; draina(); - TSUNAMI_mcheck_expected[cpu] = 0; - probe_result = !TSUNAMI_mcheck_taken[cpu]; - TSUNAMI_mcheck_taken[cpu] = 0; + mcheck_expected(cpu) = 0; + probe_result = !mcheck_taken(cpu); + mcheck_taken(cpu) = 0; setipl(s); printk("dont_care == 0x%lx\n", dont_care); @@ -251,77 +247,51 @@ static void __init tsunami_init_one_pchip(tsunami_pchip *pchip, int index, unsigned long *mem_start) { - struct linux_hose_info *hose; - int i; + struct pci_controler *hose; if (tsunami_probe_read(&pchip->pctl.csr) == 0) return; - hose = (struct linux_hose_info *)*mem_start; - *mem_start = (unsigned long)(hose + 1); - memset(hose, 0, sizeof(*hose)); - - *hose_tail = hose; - hose_tail = &hose->next; - - hose->pci_io_space = TSUNAMI_IO(index); - hose->pci_mem_space = TSUNAMI_MEM(index); - hose->pci_config_space = TSUNAMI_CONF(index); - hose->pci_sparse_space = 0; - hose->pci_hose_index = index; - - switch (alpha_use_srm_setup) - { - default: -#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP) - for (i = 0; i < 4; ++i) { - if ((pchip->wsba[i].csr & 3) == 1 - && pchip->tba[i].csr == 0 - && (pchip->wsm[i].csr & 0xfff00000) > 0x0ff00000) { - TSUNAMI_DMA_WIN_BASE = pchip->wsba[i].csr & 0xfff00000; - TSUNAMI_DMA_WIN_SIZE = pchip->wsm[i].csr & 0xfff00000; - TSUNAMI_DMA_WIN_SIZE += 0x00100000; -#if 1 - printk("%s: using Window %d settings\n", FN, i); - printk("%s: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n", - FN, pchip->wsba[i].csr, pchip->wsm[i].csr, - pchip->tba[i].csr); -#endif - goto found; - } - } + hose = alloc_pci_controler(mem_start); + hose->io_space = alloc_resource(mem_start); + hose->mem_space = alloc_resource(mem_start); - /* Otherwise, we must use our defaults. */ - TSUNAMI_DMA_WIN_BASE = TSUNAMI_DMA_WIN_BASE_DEFAULT; - TSUNAMI_DMA_WIN_SIZE = TSUNAMI_DMA_WIN_SIZE_DEFAULT; -#endif - case 0: - /* - * Set up the PCI->physical memory translation windows. - * For now, windows 1,2 and 3 are disabled. In the future, - * we may want to use them to do scatter/gather DMA. - * - * Window 0 goes at 1 GB and is 1 GB large, mapping to 0. - */ - - pchip->wsba[0].csr = 1L | (TSUNAMI_DMA_WIN_BASE_DEFAULT & 0xfff00000U); - pchip->wsm[0].csr = (TSUNAMI_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000UL; - pchip->tba[0].csr = 0; + hose->config_space = TSUNAMI_CONF(index); + hose->index = index; -#if 0 - pchip->wsba[1].csr = 0; -#else - /* make the second window at 2Gb for 1Gb mapping to 1Gb */ - pchip->wsba[1].csr = 1L | ((0x80000000U) & 0xfff00000U); - pchip->wsm[1].csr = (0x40000000UL - 1) & 0xfff00000UL; - pchip->tba[1].csr = 0x40000000; -#endif + hose->io_space->start = TSUNAMI_IO(index) - TSUNAMI_IO_BIAS; + hose->io_space->end = hose->io_space->start + 0xffff; + hose->io_space->name = pci_io_names[index]; - pchip->wsba[2].csr = 0; - pchip->wsba[3].csr = 0; - mb(); - } -found:; + hose->mem_space->start = TSUNAMI_MEM(index) - TSUNAMI_MEM_BIAS; + hose->mem_space->end = hose->mem_space->start + 0xffffffff; + hose->mem_space->name = pci_mem_names[index]; + + request_resource(&ioport_resource, hose->io_space); + request_resource(&iomem_resource, hose->mem_space); + + /* + * Set up the PCI->physical memory translation windows. + * For now, windows 1,2 and 3 are disabled. In the future, + * we may want to use them to do scatter/gather DMA. + * + * Window 0 goes at 1 GB and is 1 GB large, mapping to 0. + * Window 1 goes at 2 GB and is 1 GB large, mapping to 1GB. + */ + + pchip->wsba[0].csr = TSUNAMI_DMA_WIN0_BASE_DEFAULT | 1UL; + pchip->wsm[0].csr = (TSUNAMI_DMA_WIN0_SIZE_DEFAULT - 1) & + 0xfff00000UL; + pchip->tba[0].csr = TSUNAMI_DMA_WIN0_TRAN_DEFAULT; + + pchip->wsba[1].csr = TSUNAMI_DMA_WIN1_BASE_DEFAULT | 1UL; + pchip->wsm[1].csr = (TSUNAMI_DMA_WIN1_SIZE_DEFAULT - 1) & + 0xfff00000UL; + pchip->tba[1].csr = TSUNAMI_DMA_WIN1_TRAN_DEFAULT; + + pchip->wsba[2].csr = 0; + pchip->wsba[3].csr = 0; + mb(); } void __init @@ -360,111 +330,53 @@ tsunami_init_arch(unsigned long *mem_start, unsigned long *mem_end) printk("%s: CSR_STR 0x%lx\n", FN, TSUNAMI_dchip->str.csr); printk("%s: CSR_DREV 0x%lx\n", FN, TSUNAMI_dchip->drev.csr); #endif + TSUNAMI_bootcpu = __hard_smp_processor_id(); - /* Align memory to cache line; we'll be allocating from it. */ - *mem_start = (*mem_start | 31) + 1; + /* With multiple PCI busses, we play with I/O as physical addrs. */ + ioport_resource.end = ~0UL; + iomem_resource.end = ~0UL; + + /* Find how many hoses we have, and initialize them. TSUNAMI + and TYPHOON can have 2, but might only have 1 (DS10). */ - /* Find how many hoses we have, and initialize them. */ tsunami_init_one_pchip(TSUNAMI_pchip0, 0, mem_start); - /* must change this for TYPHOON which may have 4 */ if (TSUNAMI_cchip->csc.csr & 1L<<14) - tsunami_init_one_pchip(TSUNAMI_pchip1, 1, mem_start); + tsunami_init_one_pchip(TSUNAMI_pchip1, 1, mem_start); } static inline void -tsunami_pci_clr_err_1(tsunami_pchip *pchip, int cpu) +tsunami_pci_clr_err_1(tsunami_pchip *pchip) { - TSUNAMI_jd[cpu] = pchip->perror.csr; - DBG_MCK(("TSUNAMI_pci_clr_err: PERROR after read 0x%x\n", - TSUNAMI_jd[cpu])); + unsigned int jd; + + jd = pchip->perror.csr; pchip->perror.csr = 0x040; mb(); - TSUNAMI_jd[cpu] = pchip->perror.csr; + jd = pchip->perror.csr; } -static int +static inline void tsunami_pci_clr_err(void) { - int cpu = smp_processor_id(); - tsunami_pci_clr_err_1(TSUNAMI_pchip0, cpu); - /* must change this for TYPHOON which may have 4 */ + tsunami_pci_clr_err_1(TSUNAMI_pchip0); + + /* TSUNAMI and TYPHOON can have 2, but might only have 1 (DS10) */ if (TSUNAMI_cchip->csc.csr & 1L<<14) - tsunami_pci_clr_err_1(TSUNAMI_pchip1, cpu); - return 0; + tsunami_pci_clr_err_1(TSUNAMI_pchip1); } void tsunami_machine_check(unsigned long vector, unsigned long la_ptr, struct pt_regs * regs) { -#if 0 - printk("TSUNAMI machine check ignored\n") ; -#else - struct el_common *mchk_header; - struct el_TSUNAMI_sysdata_mcheck *mchk_sysdata; - unsigned int cpu = smp_processor_id(); - - mb(); - mchk_header = (struct el_common *)la_ptr; - - mchk_sysdata = (struct el_TSUNAMI_sysdata_mcheck *) - (la_ptr + mchk_header->sys_offset); - -#if 0 - DBG_MCK(("tsunami_machine_check: vector=0x%lx la_ptr=0x%lx\n", - vector, la_ptr)); - DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", - regs->pc, mchk_header->size, mchk_header->proc_offset, - mchk_header->sys_offset)); - DBG_MCK(("tsunami_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n", - TSUNAMI_mcheck_expected[cpu], mchk_sysdata->epic_dcsr, - mchk_sysdata->epic_pear)); -#endif -#ifdef DEBUG_MCHECK_DUMP - { - unsigned long *ptr; - int i; - - ptr = (unsigned long *)la_ptr; - for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { - printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]); - } - } -#endif /* DEBUG_MCHECK_DUMP */ - /* - * Check if machine check is due to a badaddr() and if so, - * ignore the machine check. - */ + /* Clear error before any reporting. */ mb(); mb(); /* magic */ - if (TSUNAMI_mcheck_expected[cpu]) { - DBG_MCK(("TSUNAMI machine check expected\n")); - TSUNAMI_mcheck_expected[cpu] = 0; - TSUNAMI_mcheck_taken[cpu] = 1; - mb(); - mb(); /* magic */ - draina(); - tsunami_pci_clr_err(); - wrmces(0x7); - mb(); - } -#if 1 - else { - printk("TSUNAMI machine check NOT expected\n") ; - DBG_MCK(("tsunami_machine_check: vector=0x%lx la_ptr=0x%lx\n", - vector, la_ptr)); - DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", - regs->pc, mchk_header->size, mchk_header->proc_offset, - mchk_header->sys_offset)); - TSUNAMI_mcheck_expected[cpu] = 0; - TSUNAMI_mcheck_taken[cpu] = 1; - mb(); - mb(); /* magic */ - draina(); - tsunami_pci_clr_err(); - wrmces(0x7); - mb(); - } -#endif -#endif + draina(); + tsunami_pci_clr_err(); + wrmces(0x7); + mb(); + + process_mcheck_info(vector, la_ptr, regs, "TSUNAMI", + mcheck_expected(smp_processor_id())); } diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index b4e71bf56..1e34d5a33 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -8,7 +8,7 @@ #define SIGCHLD 20 -#define NR_SYSCALLS 371 +#define NR_SYSCALLS 373 /* * These offsets must match with alpha_mv in <asm/machvec.h>. @@ -38,6 +38,8 @@ */ #define PF_PTRACED 0x00000010 +#define CLONE_VM 0x00000100 + /* * This defines the normal kernel pt-regs layout. * @@ -225,21 +227,23 @@ kernel_clone: .end kernel_clone /* - * __kernel_thread(clone_flags, fn, arg) + * kernel_thread(fn, arg, clone_flags) */ .align 3 -.globl __kernel_thread -.ent __kernel_thread -__kernel_thread: +.globl kernel_thread +.ent kernel_thread +kernel_thread: ldgp $29,0($27) /* we can be called from a module */ .frame $30, 4*8, $26 subq $30,4*8,$30 stq $10,16($30) stq $9,8($30) + lda $0,CLONE_VM stq $26,0($30) .prologue 1 - mov $17,$9 /* save fn */ - mov $18,$10 /* save arg */ + mov $16,$9 /* save fn */ + mov $17,$10 /* save arg */ + or $18,$0,$16 /* shuffle flags to front; add CLONE_VM. */ bsr $26,kernel_clone bne $20,1f /* $20 is non-zero in child */ ldq $26,0($30) @@ -257,7 +261,7 @@ __kernel_thread: mov $0,$16 mov $31,$26 jsr $31,sys_exit -.end __kernel_thread +.end kernel_thread /* * __kernel_execve(path, argv, envp, regs) @@ -1092,7 +1096,7 @@ sys_call_table: .quad sys_munlockall .quad sys_sysinfo .quad sys_sysctl - .quad sys_idle /* 320 */ + .quad sys_ni_syscall /* 320 */ .quad sys_oldumount .quad sys_swapon .quad sys_times @@ -1143,3 +1147,5 @@ sys_call_table: .quad sys_capget .quad sys_capset .quad sys_sendfile /* 370 */ + .quad sys_setresgid + .quad sys_getresgid diff --git a/arch/alpha/kernel/es1888.c b/arch/alpha/kernel/es1888.c index 10115ac8d..d584c85fe 100644 --- a/arch/alpha/kernel/es1888.c +++ b/arch/alpha/kernel/es1888.c @@ -32,6 +32,7 @@ es1888_init(void) continue; inb(0x022a); /* pause */ outb(0xc6, 0x022c); /* enable extended mode */ + inb(0x022a); /* pause, also forces the write */ while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */ continue; outb(0xb1, 0x022c); /* setup for write to Interrupt CR */ @@ -44,4 +45,5 @@ es1888_init(void) while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */ continue; outb(0x18, 0x022c); /* set DMA channel 1 */ + inb(0x022c); /* force the write */ } diff --git a/arch/alpha/kernel/head.S b/arch/alpha/kernel/head.S index 3b004b7f6..e410e2684 100644 --- a/arch/alpha/kernel/head.S +++ b/arch/alpha/kernel/head.S @@ -95,3 +95,21 @@ halt: .prologue 0 call_pal PAL_halt .end halt + + # + # Having the delay loop out of line guarantees that we wont + # run into weird alignment conditions (on new processors) + # that vary the speed of the loop. + # + .align 5 + .globl ___delay + .ent ___delay +___delay: + .set noat + .frame $30,0,$28,0 + .prologue 0 +1: subq $0,1,$0 + bge $0,1b + ret $31,($28),0 + .set at + .end ___delay diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c index d53f7ffea..43da6affd 100644 --- a/arch/alpha/kernel/irq.c +++ b/arch/alpha/kernel/irq.c @@ -30,14 +30,17 @@ #include <asm/machvec.h> #include "proto.h" -#include "irq.h" +#include "irq_impl.h" #define vulp volatile unsigned long * #define vuip volatile unsigned int * -unsigned int local_irq_count[NR_CPUS]; -unsigned int local_bh_count[NR_CPUS]; -unsigned long hardirq_no[NR_CPUS]; +/* Only uniprocessor needs this IRQ/BH locking depth, on SMP it lives + in the per-cpu structure for cache reasons. */ +#ifndef __SMP__ +int __local_irq_count; +int __local_bh_count; +#endif #if NR_IRQS > 64 # error Unable to handle more than 64 irq levels. @@ -64,7 +67,7 @@ unsigned long alpha_irq_mask = ~0UL; */ void -generic_ack_irq(unsigned long irq) +common_ack_irq(unsigned long irq) { if (irq < 16) { /* Ack the interrupt making it the lowest priority */ @@ -384,6 +387,8 @@ static void *previous_irqholder = NULL; static void show(char * str, void *where); +#define SYNC_OTHER_CPUS(x) udelay((x)+1); + static inline void wait_on_irq(int cpu, void *where) { @@ -397,8 +402,8 @@ wait_on_irq(int cpu, void *where) * already executing in one.. */ if (!atomic_read(&global_irq_count)) { - if (local_bh_count[cpu] || - !atomic_read(&global_bh_count)) + if (local_bh_count(cpu) + || !atomic_read(&global_bh_count)) break; } @@ -412,19 +417,15 @@ wait_on_irq(int cpu, void *where) count = MAXCOUNT; } __sti(); -#if 0 - SYNC_OTHER_CORES(cpu); -#else - udelay(cpu+1); -#endif + SYNC_OTHER_CPUS(cpu); __cli(); if (atomic_read(&global_irq_count)) continue; - if (global_irq_lock.lock) + if (spin_is_locked(&global_irq_lock)) continue; - if (!local_bh_count[cpu] && - atomic_read(&global_bh_count)) + if (!local_bh_count(cpu) + && atomic_read(&global_bh_count)) continue; if (spin_trylock(&global_irq_lock)) break; @@ -469,14 +470,14 @@ get_irqlock(int cpu, void* where) void __global_cli(void) { - int cpu; + int cpu = smp_processor_id(); void *where = __builtin_return_address(0); /* * Maximize ipl. If ipl was previously 0 and if this thread * is not in an irq, then take global_irq_lock. */ - if ((swpipl(7) == 0) && !local_irq_count[cpu = smp_processor_id()]) + if (swpipl(7) == 0 && !local_irq_count(cpu)) get_irqlock(cpu, where); } @@ -485,9 +486,8 @@ __global_sti(void) { int cpu = smp_processor_id(); - if (!local_irq_count[cpu]) { + if (!local_irq_count(cpu)) release_irqlock(cpu); - } __sti(); } @@ -512,7 +512,7 @@ __global_save_flags(void) retval = 2 + local_enabled; /* Check for global flags if we're not in an interrupt. */ - if (!local_irq_count[cpu]) { + if (!local_irq_count(cpu)) { if (local_enabled) retval = 1; if (global_irq_holder == cpu) @@ -550,7 +550,7 @@ __global_restore_flags(unsigned long flags) #define STUCK \ if (!--stuck) { \ printk("irq_enter stuck (irq=%d, cpu=%d, global=%d)\n", \ - irq, cpu,global_irq_holder); \ + irq, cpu, global_irq_holder); \ stuck = INIT_STUCK; \ } @@ -566,11 +566,11 @@ irq_enter(int cpu, int irq) hardirq_enter(cpu, irq); barrier(); - while (global_irq_lock.lock) { + while (spin_is_locked(&global_irq_lock)) { if (cpu == global_irq_holder) { - int globl_locked = global_irq_lock.lock; + int globl_locked = spin_is_locked(&global_irq_lock); int globl_icount = atomic_read(&global_irq_count); - int local_count = local_irq_count[cpu]; + int local_count = local_irq_count(cpu); /* It is very important that we load the state variables before we do the first call to @@ -609,19 +609,16 @@ show(char * str, void *where) #endif int cpu = smp_processor_id(); - int global_count = atomic_read(&global_irq_count); - int local_count0 = local_irq_count[0]; - int local_count1 = local_irq_count[1]; - long hardirq_no0 = hardirq_no[0]; - long hardirq_no1 = hardirq_no[1]; - printk("\n%s, CPU %d: %p\n", str, cpu, where); - printk("irq: %d [%d(0x%016lx) %d(0x%016lx)]\n", global_count, - local_count0, hardirq_no0, local_count1, hardirq_no1); + printk("irq: %d [%d %d]\n", + atomic_read(&global_irq_count), + cpu_data[0].irq_count, + cpu_data[1].irq_count); printk("bh: %d [%d %d]\n", - atomic_read(&global_bh_count), local_bh_count[0], - local_bh_count[1]); + atomic_read(&global_bh_count), + cpu_data[0].bh_count, + cpu_data[1].bh_count); #if 0 stack = (unsigned long *) &str; for (i = 40; i ; i--) { @@ -644,6 +641,7 @@ wait_on_bh(void) count = ~0; } /* nothing .. wait for the other bh's to go away */ + barrier(); } while (atomic_read(&global_bh_count) != 0); } @@ -658,12 +656,8 @@ wait_on_bh(void) void synchronize_bh(void) { - if (atomic_read(&global_bh_count)) { - int cpu = smp_processor_id(); - if (!local_irq_count[cpu] && !local_bh_count[cpu]) { - wait_on_bh(); - } - } + if (atomic_read(&global_bh_count) && !in_interrupt()) + wait_on_bh(); } /* @@ -680,6 +674,8 @@ synchronize_bh(void) void synchronize_irq(void) { +#if 0 + /* Joe's version. */ int cpu = smp_processor_id(); int local_count; int global_count; @@ -688,7 +684,7 @@ synchronize_irq(void) mb(); do { - local_count = local_irq_count[cpu]; + local_count = local_irq_count(cpu); global_count = atomic_read(&global_irq_count); if (DEBUG_SYNCHRONIZE_IRQ && (--countdown == 0)) { printk("%d:%d/%d\n", cpu, local_count, global_count); @@ -696,12 +692,19 @@ synchronize_irq(void) break; } } while (global_count != local_count); +#else + /* Jay's version. */ + if (atomic_read(&global_irq_count)) { + cli(); + sti(); + } +#endif } #else /* !__SMP__ */ -#define irq_enter(cpu, irq) (++local_irq_count[cpu]) -#define irq_exit(cpu, irq) (--local_irq_count[cpu]) +#define irq_enter(cpu, irq) (++local_irq_count(cpu)) +#define irq_exit(cpu, irq) (--local_irq_count(cpu)) #endif /* __SMP__ */ @@ -868,31 +871,23 @@ do_entInt(unsigned long type, unsigned long vector, unsigned long la_ptr, unsigned long a3, unsigned long a4, unsigned long a5, struct pt_regs regs) { - unsigned long flags; - switch (type) { case 0: #ifdef __SMP__ - __save_and_cli(flags); handle_ipi(®s); - __restore_flags(flags); return; #else printk("Interprocessor interrupt? You must be kidding\n"); #endif break; case 1: - __save_and_cli(flags); handle_irq(RTC_IRQ, -1, ®s); - __restore_flags(flags); return; case 2: alpha_mv.machine_check(vector, la_ptr, ®s); return; case 3: - __save_and_cli(flags); alpha_mv.device_interrupt(vector, ®s); - __restore_flags(flags); return; case 4: perf_irq(vector, ®s); @@ -909,3 +904,101 @@ init_IRQ(void) wrent(entInt, 0); alpha_mv.init_irq(); } + + +/* + */ +#define MCHK_K_TPERR 0x0080 +#define MCHK_K_TCPERR 0x0082 +#define MCHK_K_HERR 0x0084 +#define MCHK_K_ECC_C 0x0086 +#define MCHK_K_ECC_NC 0x0088 +#define MCHK_K_OS_BUGCHECK 0x008A +#define MCHK_K_PAL_BUGCHECK 0x0090 + +#ifndef __SMP__ +struct mcheck_info __mcheck_info; +#endif + +void +process_mcheck_info(unsigned long vector, unsigned long la_ptr, + struct pt_regs *regs, const char *machine, + int expected) +{ + struct el_common *mchk_header; + const char *reason; + + /* + * See if the machine check is due to a badaddr() and if so, + * ignore it. + */ + +#if DEBUG_MCHECK > 0 + printk(KERN_CRIT "%s machine check %s\n", machine, + expected ? "expected." : "NOT expected!!!"); +#endif + + if (expected) { + int cpu = smp_processor_id(); + mcheck_expected(cpu) = 0; + mcheck_taken(cpu) = 1; + return; + } + + mchk_header = (struct el_common *)la_ptr; + + printk(KERN_CRIT "%s machine check: vector=0x%lx pc=0x%lx code=0x%lx\n", + machine, vector, regs->pc, mchk_header->code); + + switch ((unsigned int) mchk_header->code) { + /* Machine check reasons. Defined according to PALcode sources. */ + case 0x80: reason = "tag parity error"; break; + case 0x82: reason = "tag control parity error"; break; + case 0x84: reason = "generic hard error"; break; + case 0x86: reason = "correctable ECC error"; break; + case 0x88: reason = "uncorrectable ECC error"; break; + case 0x8A: reason = "OS-specific PAL bugcheck"; break; + case 0x90: reason = "callsys in kernel mode"; break; + case 0x96: reason = "i-cache read retryable error"; break; + case 0x98: reason = "processor detected hard error"; break; + + /* System specific (these are for Alcor, at least): */ + case 0x203: reason = "system detected uncorrectable ECC error"; break; + case 0x204: reason = "SIO SERR occurred on PCI bus"; break; + case 0x205: reason = "parity error detected by CIA"; break; + case 0x206: reason = "SIO IOCHK occurred on ISA bus"; break; + case 0x207: reason = "non-existent memory error"; break; + case 0x208: reason = "MCHK_K_DCSR"; break; + case 0x209: reason = "PCI SERR detected"; break; + case 0x20b: reason = "PCI data parity error detected"; break; + case 0x20d: reason = "PCI address parity error detected"; break; + case 0x20f: reason = "PCI master abort error"; break; + case 0x211: reason = "PCI target abort error"; break; + case 0x213: reason = "scatter/gather PTE invalid error"; break; + case 0x215: reason = "flash ROM write error"; break; + case 0x217: reason = "IOA timeout detected"; break; + case 0x219: reason = "IOCHK#, EISA add-in board parity or other catastrophic error"; break; + case 0x21b: reason = "EISA fail-safe timer timeout"; break; + case 0x21d: reason = "EISA bus time-out"; break; + case 0x21f: reason = "EISA software generated NMI"; break; + case 0x221: reason = "unexpected ev5 IRQ[3] interrupt"; break; + default: reason = "unknown"; break; + } + + printk(KERN_CRIT "machine check type: %s%s\n", + reason, mchk_header->retry ? " (retryable)" : ""); + + dik_show_regs(regs, NULL); + +#if DEBUG_MCHECK > 1 + { + /* Dump the logout area to give all info. */ + unsigned long *ptr = (unsigned long *)la_ptr; + long i; + for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { + printk(KERN_CRIT " +%8lx %016lx %016lx\n", + i*sizeof(long), ptr[i], ptr[i+1]); + } + } +#endif +} diff --git a/arch/alpha/kernel/irq.h b/arch/alpha/kernel/irq_impl.h index 6849e830b..bc8854212 100644 --- a/arch/alpha/kernel/irq.h +++ b/arch/alpha/kernel/irq_impl.h @@ -18,7 +18,7 @@ extern unsigned long alpha_irq_mask; -extern void generic_ack_irq(unsigned long irq); +extern void common_ack_irq(unsigned long irq); extern void isa_device_interrupt(unsigned long vector, struct pt_regs * regs); extern void srm_device_interrupt(unsigned long vector, struct pt_regs * regs); @@ -31,3 +31,19 @@ extern void handle_irq(int irq, int ack, struct pt_regs * regs); #define TIMER_IRQ RTC_IRQ /* timer is the rtc */ #endif +extern char _stext; +static inline void alpha_do_profile (unsigned long pc) +{ + if (prof_buffer && current->pid) { + pc -= (unsigned long) &_stext; + pc >>= prof_shift; + /* + * Don't ignore out-of-bounds PC values silently, + * put them into the last histogram slot, so if + * present, they will show up as a sharp peak. + */ + if (pc > prof_len - 1) + pc = prof_len - 1; + atomic_inc((atomic_t *)&prof_buffer[pc]); + } +} diff --git a/arch/alpha/kernel/machvec.h b/arch/alpha/kernel/machvec_impl.h index 1e11c046e..a0ff70dcc 100644 --- a/arch/alpha/kernel/machvec.h +++ b/arch/alpha/kernel/machvec_impl.h @@ -8,16 +8,19 @@ #include <linux/config.h> -/* Whee. TSUNAMI doesn't have an HAE. 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. ;-) */ +/* Whee. Both TSUNAMI and POLARIS don't have an HAE. 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. ;-) */ #define TSUNAMI_HAE_ADDRESS (&alpha_mv.hae_cache) - -/* Whee. POLARIS doesn't have an HAE. 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. ;-) */ #define POLARIS_HAE_ADDRESS (&alpha_mv.hae_cache) +#if CIA_ONE_HAE_WINDOW +#define CIA_HAE_ADDRESS (&alpha_mv.hae_cache) +#endif +#if MCPCIA_ONE_HAE_WINDOW +#define MCPCIA_HAE_ADDRESS (&alpha_mv.hae_cache) +#endif + /* Only a few systems don't define IACK_SC, handling all interrupts through the SRM console. But splitting out that one case from IO() below seems like such a pain. Define this to get things to compile. */ @@ -36,66 +39,63 @@ #define DO_EV4_MMU \ max_asn: EV4_MAX_ASN, \ - mv_get_mmu_context: ev4_get_mmu_context, \ + mv_switch_mm: ev4_switch_mm, \ + mv_activate_mm: ev4_activate_mm, \ mv_flush_tlb_current: ev4_flush_tlb_current, \ mv_flush_tlb_other: ev4_flush_tlb_other, \ mv_flush_tlb_current_page: ev4_flush_tlb_current_page #define DO_EV5_MMU \ max_asn: EV5_MAX_ASN, \ - mv_get_mmu_context: ev5_get_mmu_context, \ + mv_switch_mm: ev5_switch_mm, \ + mv_activate_mm: ev5_activate_mm, \ mv_flush_tlb_current: ev5_flush_tlb_current, \ mv_flush_tlb_other: ev5_flush_tlb_other, \ mv_flush_tlb_current_page: ev5_flush_tlb_current_page #define DO_EV6_MMU \ max_asn: EV6_MAX_ASN, \ - mv_get_mmu_context: ev5_get_mmu_context, \ + mv_switch_mm: ev5_switch_mm, \ + mv_activate_mm: ev5_activate_mm, \ mv_flush_tlb_current: ev5_flush_tlb_current, \ mv_flush_tlb_other: ev5_flush_tlb_other, \ mv_flush_tlb_current_page: ev5_flush_tlb_current_page -#define IO_LITE(UP,low1,low2) \ +#define IO_LITE(UP,low) \ hae_register: (unsigned long *) CAT(UP,_HAE_ADDRESS), \ iack_sc: CAT(UP,_IACK_SC), \ - mv_inb: CAT(low1,_inb), \ - mv_inw: CAT(low1,_inw), \ - mv_inl: CAT(low1,_inl), \ - mv_outb: CAT(low1,_outb), \ - mv_outw: CAT(low1,_outw), \ - mv_outl: CAT(low1,_outl), \ - mv_readb: CAT(low1,_readb), \ - mv_readw: CAT(low1,_readw), \ - mv_readl: CAT(low1,_readl), \ - mv_readq: CAT(low1,_readq), \ - mv_writeb: CAT(low1,_writeb), \ - mv_writew: CAT(low1,_writew), \ - mv_writel: CAT(low1,_writel), \ - mv_writeq: CAT(low1,_writeq), \ - mv_dense_mem: CAT(low2,_dense_mem) - -#define IO(UP,low1,low2) \ - IO_LITE(UP,low1,low2), \ - hose_read_config_byte: CAT(low2,_hose_read_config_byte), \ - hose_read_config_word: CAT(low2,_hose_read_config_word), \ - hose_read_config_dword: CAT(low2,_hose_read_config_dword), \ - hose_write_config_byte: CAT(low2,_hose_write_config_byte), \ - hose_write_config_word: CAT(low2,_hose_write_config_word), \ - hose_write_config_dword: CAT(low2,_hose_write_config_dword), \ - dma_win_base: CAT(UP,_DMA_WIN_BASE_DEFAULT), \ - dma_win_size: CAT(UP,_DMA_WIN_SIZE_DEFAULT) + mv_inb: CAT(low,_inb), \ + mv_inw: CAT(low,_inw), \ + mv_inl: CAT(low,_inl), \ + mv_outb: CAT(low,_outb), \ + mv_outw: CAT(low,_outw), \ + mv_outl: CAT(low,_outl), \ + mv_readb: CAT(low,_readb), \ + mv_readw: CAT(low,_readw), \ + mv_readl: CAT(low,_readl), \ + mv_readq: CAT(low,_readq), \ + mv_writeb: CAT(low,_writeb), \ + mv_writew: CAT(low,_writew), \ + mv_writel: CAT(low,_writel), \ + mv_writeq: CAT(low,_writeq), \ + mv_ioremap: CAT(low,_ioremap), \ + mv_is_ioaddr: CAT(low,_is_ioaddr) + +#define IO(UP,low) \ + IO_LITE(UP,low), \ + pci_ops: &CAT(low,_pci_ops) /* Any assembler that can generate a GENERIC kernel can generate BWX instructions. So always use them for PYXIS I/O. */ -#define DO_APECS_IO IO(APECS,apecs,apecs) -#define DO_CIA_IO IO(CIA,cia,cia) -#define DO_LCA_IO IO(LCA,lca,lca) -#define DO_MCPCIA_IO IO(MCPCIA,mcpcia,mcpcia) -#define DO_PYXIS_IO IO(PYXIS,pyxis_bw,pyxis) -#define DO_POLARIS_IO IO(POLARIS,polaris,polaris) -#define DO_T2_IO IO(T2,t2,t2) -#define DO_TSUNAMI_IO IO(TSUNAMI,tsunami,tsunami) +#define DO_APECS_IO IO(APECS,apecs) +#define DO_CIA_IO IO(CIA,cia) +#define DO_LCA_IO IO(LCA,lca) +#define DO_MCPCIA_IO IO(MCPCIA,mcpcia) +#define DO_PYXIS_IO IO(PYXIS,pyxis) +#define DO_POLARIS_IO IO(POLARIS,polaris) +#define DO_T2_IO IO(T2,t2) +#define DO_TSUNAMI_IO IO(TSUNAMI,tsunami) #define BUS(which) \ mv_virt_to_bus: CAT(which,_virt_to_bus), \ @@ -136,5 +136,11 @@ /* GCC actually has a syntax for defining aliases, but is under some delusion that you shouldn't be able to declare it extern somewhere else beforehand. Fine. We'll do it ourselves. */ -#define ALIAS_MV(system) asm(".global alpha_mv\nalpha_mv = " #system "_mv"); +#if 0 +#define ALIAS_MV(system) \ + struct alpha_machine_vector alpha_mv __attribute__((alias(#system "_mv"))); +#else +#define ALIAS_MV(system) \ + asm(".global alpha_mv\nalpha_mv = " #system "_mv"); #endif +#endif /* GENERIC */ diff --git a/arch/alpha/kernel/ns87312.c b/arch/alpha/kernel/ns87312.c new file mode 100644 index 000000000..8f690e43e --- /dev/null +++ b/arch/alpha/kernel/ns87312.c @@ -0,0 +1,38 @@ +/* + * linux/arch/alpha/kernel/ns87312.c + */ + +#include <linux/init.h> +#include <asm/io.h> +#include "proto.h" + + +/* + * The SRM console *disables* the IDE interface, this code ensures it's + * enabled. + * + * This code bangs on a control register of the 87312 Super I/O chip + * that implements parallel port/serial ports/IDE/FDI. Depending on + * the motherboard, the Super I/O chip can be configured through a + * pair of registers that are located either at I/O ports 0x26e/0x26f + * or 0x398/0x399. Unfortunately, autodetecting which base address is + * in use works only once (right after a reset). The Super I/O chip + * has the additional quirk that configuration register data must be + * written twice (I believe this is a safety feature to prevent + * accidental modification---fun, isn't it?). + */ + +void __init +ns87312_enable_ide(long ide_base) +{ + int data; + unsigned long flags; + + __save_and_cli(flags); + outb(0, ide_base); /* set the index register for reg #0 */ + data = inb(ide_base+1); /* read the current contents */ + outb(0, ide_base); /* set the index register for reg #0 */ + outb(data | 0x40, ide_base+1); /* turn on IDE */ + outb(data | 0x40, ide_base+1); /* turn on IDE, really! */ + __restore_flags(flags); +} diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 9ff616afa..e888c91e3 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -895,11 +895,12 @@ asmlinkage unsigned long osf_getsysinfo(unsigned long op, void *buffer, w = ieee_fpcr_to_swcr(fpcr); if (!(fpcr & FPCR_UNDZ)) { w &= ~IEEE_TRAP_ENABLE_UNF; - w |= current->tss.flags & IEEE_TRAP_ENABLE_UNF; + w |= (current->thread.flags + & IEEE_TRAP_ENABLE_UNF); } } else { /* Otherwise we are forced to do everything in sw. */ - w = current->tss.flags & IEEE_SW_MASK; + w = current->thread.flags & IEEE_SW_MASK; } if (put_user(w, (unsigned long *) buffer)) @@ -917,7 +918,7 @@ asmlinkage unsigned long osf_getsysinfo(unsigned long op, void *buffer, case GSI_UACPROC: if (nbytes < sizeof(unsigned int)) return -EINVAL; - w = (current->tss.flags >> UAC_SHIFT) & UAC_BITMASK; + w = (current->thread.flags >> UAC_SHIFT) & UAC_BITMASK; if (put_user(w, (unsigned int *)buffer)) return -EFAULT; return 1; @@ -927,6 +928,7 @@ asmlinkage unsigned long osf_getsysinfo(unsigned long op, void *buffer, return -EINVAL; cpu = (struct percpu_struct*) ((char*)hwrpb + hwrpb->processor_offset); + w = cpu->type; if (put_user(w, (unsigned long *)buffer)) return -EFAULT; return 1; @@ -963,8 +965,8 @@ asmlinkage unsigned long osf_setsysinfo(unsigned long op, void *buffer, /* Update softare trap enable bits. */ if (get_user(swcr, (unsigned long *)buffer)) return -EFAULT; - current->tss.flags &= ~IEEE_SW_MASK; - current->tss.flags |= swcr & IEEE_SW_MASK; + current->thread.flags &= ~IEEE_SW_MASK; + current->thread.flags |= swcr & IEEE_SW_MASK; /* Update the real fpcr. Keep UNFD off if not UNDZ. */ fpcr = rdfpcr(); @@ -996,9 +998,9 @@ asmlinkage unsigned long osf_setsysinfo(unsigned long op, void *buffer, return -EFAULT; switch (v) { case SSIN_UACPROC: - current->tss.flags &= + current->thread.flags &= ~(UAC_BITMASK << UAC_SHIFT); - current->tss.flags |= + current->thread.flags |= (w & UAC_BITMASK) << UAC_SHIFT; break; diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c new file mode 100644 index 000000000..a81ba4093 --- /dev/null +++ b/arch/alpha/kernel/pci.c @@ -0,0 +1,226 @@ +/* + * linux/arch/alpha/kernel/pci.c + * + * Extruded from code written by + * Dave Rusling (david.rusling@reo.mts.dec.com) + * David Mosberger (davidm@cs.arizona.edu) + */ + +#include <linux/string.h> +#include <linux/pci.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <asm/pci.h> +#include <asm/machvec.h> + +#include "proto.h" +#include "pci_impl.h" + + +/* + * Some string constants used by the various core logics. + */ + +const char *const pci_io_names[] = { + "PCI IO bus 0", "PCI IO bus 1", "PCI IO bus 2", "PCI IO bus 3" +}; + +const char *const pci_mem_names[] = { + "PCI mem bus 0", "PCI mem bus 1", "PCI mem bus 2", "PCI mem bus 3" +}; + +const char pci_hae0_name[] = "HAE0"; + + +/* + * The PCI controler list. + */ + +struct pci_controler *hose_head, **hose_tail = &hose_head; +struct pci_controler *probing_hose; + +/* + * Quirks. + */ + +static void __init +quirk_eisa_bridge(struct pci_dev *dev) +{ + dev->class = PCI_CLASS_BRIDGE_EISA; +} + +static void __init +quirk_isa_bridge(struct pci_dev *dev) +{ + dev->class = PCI_CLASS_BRIDGE_ISA; +} + +struct pci_fixup pcibios_fixups[] __initdata = { + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, + quirk_eisa_bridge }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378, + quirk_isa_bridge }, + { 0 } +}; + + +/* + * Pre-layout host-independant device initialization. + */ + +static void __init +pcibios_assign_special(void) +{ + struct pci_dev *dev; + int i; + + /* The first three resources of an IDE controler are often magic, + so leave them unchanged. This is true, for instance, of the + Contaq 82C693 as seen on SX164 and DP264. */ + + for (dev = pci_devices; dev; dev = dev->next) { + if (dev->class >> 8 != PCI_CLASS_STORAGE_IDE) + continue; + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + if (dev->resource[i].flags) + pci_claim_resource(dev, i); + } + } +} + + +void __init +pcibios_init(void) +{ + if (!alpha_mv.init_pci) + return; + alpha_mv.init_pci(); +} + +char * __init +pcibios_setup(char *str) +{ + return str; +} + +void __init +pcibios_fixup_bus(struct pci_bus *bus) +{ + /* Propogate hose info into the subordinate devices. */ + + struct pci_controler *hose = probing_hose; + struct pci_dev *dev; + + bus->resource[0] = hose->io_space; + bus->resource[1] = hose->mem_space; + for (dev = bus->devices; dev; dev = dev->sibling) + dev->sysdata = hose; +} + +void __init +pcibios_update_resource(struct pci_dev *dev, struct resource *root, + struct resource *res, int resource) +{ + unsigned long where, size; + u32 reg; + + where = PCI_BASE_ADDRESS_0 + (resource * 4); + size = res->end - res->start; + pci_read_config_dword(dev, where, ®); + reg = (reg & size) | (((u32)(res->start - root->start)) & ~size); + pci_write_config_dword(dev, where, reg); + + /* ??? FIXME -- record old value for shutdown. */ +} + +void __init +pcibios_update_irq(struct pci_dev *dev, int irq) +{ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); + + /* ??? FIXME -- record old value for shutdown. */ +} + +/* Most Alphas have straight-forward swizzling needs. */ + +u8 __init +common_swizzle(struct pci_dev *dev, u8 *pinp) +{ + struct pci_controler *hose = dev->sysdata; + + if (dev->bus->number != hose->first_busno) { + u8 pin = *pinp; + do { + pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)); + /* Move up the chain of bridges. */ + dev = dev->bus->self; + } while (dev->bus->self); + *pinp = pin; + + /* The slot is the slot of the last bridge. */ + } + + return PCI_SLOT(dev->devfn); +} + +void __init +common_init_pci(void) +{ + struct pci_controler *hose; + struct pci_bus *bus; + int next_busno; + + /* Scan all of the recorded PCI controlers. */ + for (next_busno = 0, hose = hose_head; hose; hose = hose->next) { + hose->first_busno = next_busno; + hose->last_busno = 0xff; + probing_hose = hose; + bus = pci_scan_bus(next_busno, alpha_mv.pci_ops, hose); + hose->bus = bus; + next_busno = hose->last_busno = bus->subordinate; + next_busno += 1; + } + probing_hose = NULL; + + pcibios_assign_special(); + pci_assign_unassigned_resources(alpha_mv.min_io_address, + alpha_mv.min_mem_address); + pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq); + pci_set_bus_ranges(); +} + + +struct pci_controler * __init +alloc_pci_controler(unsigned long *mem_start) +{ + unsigned long start = *mem_start; + struct pci_controler *hose; + if (start & 31) + start = (start | 31) + 1; + hose = (void *) start; + start = (unsigned long) (hose + 1); + *mem_start = start; + + memset(hose, 0, sizeof(*hose)); + + *hose_tail = hose; + hose_tail = &hose->next; + + return hose; +} + +struct resource * __init +alloc_resource(unsigned long *mem_start) +{ + unsigned long start = *mem_start; + struct resource *res; + if (start & 31) + start = (start | 31) + 1; + res = (void *) start; + start = (unsigned long) (res + 1); + *mem_start = start; + + memset(res, 0, sizeof(*res)); + + return res; +} diff --git a/arch/alpha/kernel/bios32.h b/arch/alpha/kernel/pci_impl.h index 8850517ba..c7c97f096 100644 --- a/arch/alpha/kernel/bios32.h +++ b/arch/alpha/kernel/pci_impl.h @@ -1,14 +1,13 @@ /* - * linux/arch/alpha/kernel/bios32.h + * linux/arch/alpha/kernel/pci_impl.h * * This file contains declarations and inline functions for interfacing - * with the PCI initialization routines in bios32.c. + * with the PCI initialization routines. */ +struct pci_dev; +struct pci_controler; -#define KB 1024 -#define MB (1024*KB) -#define GB (1024*MB) /* * We can't just blindly use 64K for machines with EISA busses; they @@ -21,15 +20,10 @@ * accesses to probe the bus. If a device's registers appear at 0xC000, * it may see an INx/OUTx at that address during BIOS emulation of the * VGA BIOS, and some cards, notably Adaptec 2940UW, take mortal offense. - * - * Note that we may need this stuff for SRM_SETUP also, since certain - * SRM consoles screw up and allocate I/O space addresses > 64K behind - * PCI-to_PCI bridges, which can't pass I/O addresses larger than 64K, - * AFAIK. */ -#define EISA_DEFAULT_IO_BASE 0x9000 /* start above 8th slot */ -#define DEFAULT_IO_BASE 0x8000 /* start at 8th slot */ +#define EISA_DEFAULT_IO_BASE 0x9000 /* start above 8th slot */ +#define DEFAULT_IO_BASE 0x8000 /* start at 8th slot */ /* * We try to make the DEFAULT_MEM_BASE addresses *always* have more than @@ -49,13 +43,13 @@ * We accept the risk that a broken Myrinet card will be put into a true XL * and thus can more easily run into the problem described below. */ -#define XL_DEFAULT_MEM_BASE (16*MB + 2*MB) /* 16M to 64M-1 is avail */ +#define XL_DEFAULT_MEM_BASE ((16+2)*1024*1024) /* 16M to 64M-1 is avail */ /* * APECS and LCA have only 34 bits for physical addresses, thus limiting PCI * bus memory addresses for SPARSE access to be less than 128Mb. */ -#define APECS_AND_LCA_DEFAULT_MEM_BASE (64*MB + 2*MB) +#define APECS_AND_LCA_DEFAULT_MEM_BASE ((32+2)*1024*1024) /* * Because the MCPCIA core logic supports more bits for physical addresses, @@ -63,37 +57,17 @@ * However, we do not use them all, in order to avoid the HAE manipulation * that would be needed. */ -#define RAWHIDE_DEFAULT_MEM_BASE (64*MB + 2*MB) +#define MCPCIA_DEFAULT_MEM_BASE ((32+2)*1024*1024) /* * Because CIA and PYXIS and T2 have more bits for physical addresses, * they support an expanded range of SPARSE memory addresses. */ -#define DEFAULT_MEM_BASE (128*MB + 16*MB) +#define DEFAULT_MEM_BASE ((128+16)*1024*1024) +/* ??? Experimenting with no HAE for CIA. */ +#define CIA_DEFAULT_MEM_BASE ((32+2)*1024*1024) -/* - * PCI_MODIFY - * - * If this 0, then do not write to any of the PCI registers, merely - * read them (i.e., use configuration as determined by SRM). The SRM - * seem do be doing a less than perfect job in configuring PCI - * devices, so for now we do it ourselves. Reconfiguring PCI devices - * breaks console (RPB) callbacks, but those don't work properly with - * 64 bit addresses anyways. - * - * The accepted convention seems to be that the console (POST - * software) should fully configure boot devices and configure the - * interrupt routing of *all* devices. In particular, the base - * addresses of non-boot devices need not be initialized. For - * example, on the AXPpci33 board, the base address a #9 GXE PCI - * graphics card reads as zero (this may, however, be due to a bug in - * the graphics card---there have been some rumor that the #9 BIOS - * incorrectly resets that address to 0...). - */ - -#define PCI_MODIFY (!alpha_use_srm_setup) - /* * A small note about bridges and interrupts. The DECchip 21050 (and @@ -133,22 +107,11 @@ * couple boards that do strange things, so we define this here. */ -static inline unsigned char -bridge_swizzle(unsigned char pin, unsigned int slot) +static inline u8 bridge_swizzle(u8 pin, u8 slot) { return (((pin-1) + slot) % 4) + 1; } -extern void layout_all_busses(unsigned long io_base, unsigned long mem_base); -extern void enable_ide(long ide_base); - -struct pci_dev; - -extern void -common_pci_fixup(int (*map_irq)(struct pci_dev *dev, int slot, int pin), - int (*swizzle)(struct pci_dev *dev, int *pin)); - -extern int common_swizzle(struct pci_dev *dev, int *pinp); /* The following macro is used to implement the table-based irq mapping function for all single-bus Alphas. */ @@ -161,6 +124,14 @@ extern int common_swizzle(struct pci_dev *dev, int *pinp); /* The hose list. */ -extern struct linux_hose_info *hose_head, **hose_tail; -extern int hose_count; -extern int pci_probe_enabled; +extern struct pci_controler *hose_head, **hose_tail; +extern struct pci_controler *probing_hose; + +extern void common_init_pci(void); +extern u8 common_swizzle(struct pci_dev *, u8 *); +extern struct pci_controler *alloc_pci_controler(unsigned long *); +extern struct resource *alloc_resource(unsigned long *); + +extern const char *const pci_io_names[]; +extern const char *const pci_mem_names[]; +extern const char pci_hae0_name[]; diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index ecd4387ae..354597ba2 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -43,7 +43,7 @@ #include <asm/fpu.h> #include "proto.h" -#include "bios32.h" +#include "pci_impl.h" /* * Initial task structure. Make this a per-architecture thing, @@ -55,7 +55,6 @@ unsigned long init_user_stack[1024] = { STACK_MAGIC, }; static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; -static struct file * init_fd_array[NR_OPEN] = { NULL, }; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; struct mm_struct init_mm = INIT_MM(init_mm); @@ -75,9 +74,8 @@ sys_sethae(unsigned long hae, unsigned long a1, unsigned long a2, return 0; } -#ifdef __SMP__ void -cpu_idle(void *unused) +cpu_idle(void) { /* An endless idle loop with no priority at all. */ current->priority = 0; @@ -95,30 +93,9 @@ cpu_idle(void *unused) } } } -#endif - -asmlinkage int -sys_idle(void) -{ - if (current->pid != 0) - return -EPERM; - - /* An endless idle loop with no priority at all. */ - current->priority = 0; - current->counter = -100; - init_idle(); - - while (1) { - /* FIXME -- EV6 and LCA45 know how to power down - the CPU. */ - - schedule(); - check_pgt_cache(); - } -} void -generic_kill_arch (int mode, char *restart_cmd) +common_kill_arch (int mode, char *restart_cmd) { /* The following currently only has any effect on SRM. We should fix MILO to understand it. Should be pretty easy. Also we can @@ -153,7 +130,7 @@ generic_kill_arch (int mode, char *restart_cmd) cpup->flags = flags; mb(); - reset_for_srm(); + /* reset_for_srm(); */ set_hae(srm_hae); #ifdef CONFIG_DUMMY_CONSOLE @@ -255,7 +232,7 @@ void flush_thread(void) that EV6 defines UNFD valid only with UNDZ, which we don't want for IEEE conformance -- so that disabled bit remains in software. */ - current->tss.flags &= ~IEEE_SW_MASK; + current->thread.flags &= ~IEEE_SW_MASK; wrfpcr(FPCR_DYN_NORMAL | FPCR_INVD | FPCR_DZED | FPCR_OVFD | FPCR_INED); } @@ -325,11 +302,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, #else childstack->r26 = (unsigned long) ret_from_sys_call; #endif - p->tss.usp = usp; - p->tss.ksp = (unsigned long) childstack; - p->tss.pal_flags = 1; /* set FEN, clear everything else */ - p->tss.flags = current->tss.flags; - p->tss.mm_context = p->tss.asn = 0; + p->thread.usp = usp; + p->thread.ksp = (unsigned long) childstack; + p->thread.pal_flags = 1; /* set FEN, clear everything else */ + p->thread.flags = current->thread.flags; return 0; } diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h index 8fa1fd7ea..2a196efa1 100644 --- a/arch/alpha/kernel/proto.h +++ b/arch/alpha/kernel/proto.h @@ -6,141 +6,48 @@ #define vuip volatile unsigned int * #define vulp volatile unsigned long * -struct linux_hose_info; +struct pt_regs; +struct task_struct; +struct pci_dev; /* core_apecs.c */ -extern int apecs_hose_read_config_byte (u8, u8, u8, u8 *value, - struct linux_hose_info *hose); -extern int apecs_hose_read_config_word (u8, u8, u8, u16 *value, - struct linux_hose_info *hose); -extern int apecs_hose_read_config_dword (u8, u8, u8, u32 *value, - struct linux_hose_info *hose); -extern int apecs_hose_write_config_byte (u8, u8, u8, u8 value, - struct linux_hose_info *hose); -extern int apecs_hose_write_config_word (u8, u8, u8, u16 value, - struct linux_hose_info *hose); -extern int apecs_hose_write_config_dword (u8, u8, u8, u32 value, - struct linux_hose_info *hose); +extern struct pci_ops apecs_pci_ops; extern void apecs_init_arch(unsigned long *, unsigned long *); - -extern volatile unsigned int apecs_mcheck_expected; -extern volatile unsigned int apecs_mcheck_taken; -extern int apecs_pci_clr_err(void); +extern void apecs_pci_clr_err(void); extern void apecs_machine_check(u64, u64, struct pt_regs *); /* core_cia.c */ -extern int cia_hose_read_config_byte (u8, u8, u8, u8 *value, - struct linux_hose_info *hose); -extern int cia_hose_read_config_word (u8, u8, u8, u16 *value, - struct linux_hose_info *hose); -extern int cia_hose_read_config_dword (u8, u8, u8, u32 *value, - struct linux_hose_info *hose); -extern int cia_hose_write_config_byte (u8, u8, u8, u8 value, - struct linux_hose_info *hose); -extern int cia_hose_write_config_word (u8, u8, u8, u16 value, - struct linux_hose_info *hose); -extern int cia_hose_write_config_dword (u8, u8, u8, u32 value, - struct linux_hose_info *hose); +extern struct pci_ops cia_pci_ops; extern void cia_init_arch(unsigned long *, unsigned long *); extern void cia_machine_check(u64, u64, struct pt_regs *); /* core_lca.c */ -extern int lca_hose_read_config_byte (u8, u8, u8, u8 *value, - struct linux_hose_info *hose); -extern int lca_hose_read_config_word (u8, u8, u8, u16 *value, - struct linux_hose_info *hose); -extern int lca_hose_read_config_dword (u8, u8, u8, u32 *value, - struct linux_hose_info *hose); -extern int lca_hose_write_config_byte (u8, u8, u8, u8 value, - struct linux_hose_info *hose); -extern int lca_hose_write_config_word (u8, u8, u8, u16 value, - struct linux_hose_info *hose); -extern int lca_hose_write_config_dword (u8, u8, u8, u32 value, - struct linux_hose_info *hose); +extern struct pci_ops lca_pci_ops; extern void lca_init_arch(unsigned long *, unsigned long *); extern void lca_machine_check(u64, u64, struct pt_regs *); /* core_mcpcia.c */ -extern int mcpcia_hose_read_config_byte (u8, u8, u8, u8 *value, - struct linux_hose_info *hose); -extern int mcpcia_hose_read_config_word (u8, u8, u8, u16 *value, - struct linux_hose_info *hose); -extern int mcpcia_hose_read_config_dword (u8, u8, u8, u32 *value, - struct linux_hose_info *hose); -extern int mcpcia_hose_write_config_byte (u8, u8, u8, u8 value, - struct linux_hose_info *hose); -extern int mcpcia_hose_write_config_word (u8, u8, u8, u16 value, - struct linux_hose_info *hose); -extern int mcpcia_hose_write_config_dword (u8, u8, u8, u32 value, - struct linux_hose_info *hose); +extern struct pci_ops mcpcia_pci_ops; extern void mcpcia_init_arch(unsigned long *, unsigned long *); extern void mcpcia_machine_check(u64, u64, struct pt_regs *); /* core_polaris.c */ -extern int polaris_hose_read_config_byte (u8, u8, u8, u8 *value, - struct linux_hose_info *hose); -extern int polaris_hose_read_config_word (u8, u8, u8, u16 *value, - struct linux_hose_info *hose); -extern int polaris_hose_read_config_dword (u8, u8, u8, u32 *value, - struct linux_hose_info *hose); -extern int polaris_hose_write_config_byte (u8, u8, u8, u8 value, - struct linux_hose_info *hose); -extern int polaris_hose_write_config_word (u8, u8, u8, u16 value, - struct linux_hose_info *hose); -extern int polaris_hose_write_config_dword (u8, u8, u8, u32 value, - struct linux_hose_info *hose); +extern struct pci_ops polaris_pci_ops; extern void polaris_init_arch(unsigned long *, unsigned long *); extern void polaris_machine_check(u64, u64, struct pt_regs *); /* core_pyxis.c */ -extern int pyxis_hose_read_config_byte (u8, u8, u8, u8 *value, - struct linux_hose_info *hose); -extern int pyxis_hose_read_config_word (u8, u8, u8, u16 *value, - struct linux_hose_info *hose); -extern int pyxis_hose_read_config_dword (u8, u8, u8, u32 *value, - struct linux_hose_info *hose); -extern int pyxis_hose_write_config_byte (u8, u8, u8, u8 value, - struct linux_hose_info *hose); -extern int pyxis_hose_write_config_word (u8, u8, u8, u16 value, - struct linux_hose_info *hose); -extern int pyxis_hose_write_config_dword (u8, u8, u8, u32 value, - struct linux_hose_info *hose); -extern void pyxis_enable_errors (void); -extern int pyxis_srm_window_setup (void); -extern void pyxis_native_window_setup(void); -extern void pyxis_finish_init_arch(void); +extern struct pci_ops pyxis_pci_ops; extern void pyxis_init_arch(unsigned long *, unsigned long *); extern void pyxis_machine_check(u64, u64, struct pt_regs *); /* core_t2.c */ -extern int t2_hose_read_config_byte (u8, u8, u8, u8 *value, - struct linux_hose_info *hose); -extern int t2_hose_read_config_word (u8, u8, u8, u16 *value, - struct linux_hose_info *hose); -extern int t2_hose_read_config_dword (u8, u8, u8, u32 *value, - struct linux_hose_info *hose); -extern int t2_hose_write_config_byte (u8, u8, u8, u8 value, - struct linux_hose_info *hose); -extern int t2_hose_write_config_word (u8, u8, u8, u16 value, - struct linux_hose_info *hose); -extern int t2_hose_write_config_dword (u8, u8, u8, u32 value, - struct linux_hose_info *hose); +extern struct pci_ops t2_pci_ops; extern void t2_init_arch(unsigned long *, unsigned long *); extern void t2_machine_check(u64, u64, struct pt_regs *); /* core_tsunami.c */ -extern int tsunami_hose_read_config_byte (u8, u8, u8, u8 *value, - struct linux_hose_info *hose); -extern int tsunami_hose_read_config_word (u8, u8, u8, u16 *value, - struct linux_hose_info *hose); -extern int tsunami_hose_read_config_dword (u8, u8, u8, u32 *value, - struct linux_hose_info *hose); -extern int tsunami_hose_write_config_byte (u8, u8, u8, u8 value, - struct linux_hose_info *hose); -extern int tsunami_hose_write_config_word (u8, u8, u8, u16 value, - struct linux_hose_info *hose); -extern int tsunami_hose_write_config_dword (u8, u8, u8, u32 value, - struct linux_hose_info *hose); +extern struct pci_ops tsunami_pci_ops; extern void tsunami_init_arch(unsigned long *, unsigned long *); extern void tsunami_machine_check(u64, u64, struct pt_regs *); @@ -155,12 +62,12 @@ extern void smp_percpu_timer_interrupt(struct pt_regs *); extern int smp_boot_cpuid; /* bios32.c */ -extern void reset_for_srm(void); +/* extern void reset_for_srm(void); */ /* time.c */ extern void timer_interrupt(int irq, void *dev, struct pt_regs * regs); extern void rtc_init_pit(void); -extern void generic_init_pit(void); +extern void common_init_pit(void); extern unsigned long est_cycle_freq; /* smc37c93x.c */ @@ -172,6 +79,9 @@ extern void SMC669_Init(int); /* es1888.c */ extern void es1888_init(void); +/* ns87312.c */ +extern void ns87312_enable_ide(long ide_base); + /* fpregs.c */ extern void alpha_write_fp_reg (unsigned long reg, unsigned long val); extern unsigned long alpha_read_fp_reg (unsigned long reg); @@ -192,12 +102,41 @@ extern void entUna(void); extern void entDbg(void); /* process.c */ -extern void generic_kill_arch (int mode, char *reboot_cmd); -extern void cpu_idle(void *) __attribute__((noreturn)); +extern void common_kill_arch (int mode, char *reboot_cmd); +extern void cpu_idle(void) __attribute__((noreturn)); /* ptrace.c */ extern int ptrace_set_bpt (struct task_struct *child); extern int ptrace_cancel_bpt (struct task_struct *child); +/* traps.c */ +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 *); + /* ../mm/init.c */ void srm_paging_stop(void); + +/* irq.h */ + +#ifdef __SMP__ +#define mcheck_expected(cpu) (cpu_data[cpu].mcheck_expected) +#define mcheck_taken(cpu) (cpu_data[cpu].mcheck_taken) +#define mcheck_extra(cpu) (cpu_data[cpu].mcheck_extra) +#else +extern struct mcheck_info +{ + unsigned char expected __attribute__((aligned(8))); + unsigned char taken; + unsigned char extra; +} __mcheck_info; + +#define mcheck_expected(cpu) (__mcheck_info.expected) +#define mcheck_taken(cpu) (__mcheck_info.taken) +#define mcheck_extra(cpu) (__mcheck_info.extra) +#endif + +#define DEBUG_MCHECK 0 /* 0 = minimal, 1 = debug, 2 = debug+dump. */ + +extern void process_mcheck_info(unsigned long vector, unsigned long la_ptr, + struct pt_regs *regs, const char *machine, + int expected); diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c index b590c0bdb..333bb63ec 100644 --- a/arch/alpha/kernel/ptrace.c +++ b/arch/alpha/kernel/ptrace.c @@ -106,7 +106,7 @@ get_reg_addr(struct task_struct * task, unsigned long regno) long *addr; if (regno == 30) { - addr = &task->tss.usp; + addr = &task->thread.usp; } else if (regno == 31 || regno > 64) { zero = 0; addr = &zero; @@ -175,31 +175,31 @@ ptrace_set_bpt(struct task_struct * child) * branch (emulation can be tricky for fp branches). */ displ = ((s32)(insn << 11)) >> 9; - child->tss.bpt_addr[nsaved++] = pc + 4; + child->thread.bpt_addr[nsaved++] = pc + 4; if (displ) /* guard against unoptimized code */ - child->tss.bpt_addr[nsaved++] = pc + 4 + displ; + child->thread.bpt_addr[nsaved++] = pc + 4 + displ; DBG(DBG_BPT, ("execing branch\n")); } else if (op_code == 0x1a) { reg_b = (insn >> 16) & 0x1f; - child->tss.bpt_addr[nsaved++] = get_reg(child, reg_b); + child->thread.bpt_addr[nsaved++] = get_reg(child, reg_b); DBG(DBG_BPT, ("execing jump\n")); } else { - child->tss.bpt_addr[nsaved++] = pc + 4; + child->thread.bpt_addr[nsaved++] = pc + 4; DBG(DBG_BPT, ("execing normal insn\n")); } /* install breakpoints: */ for (i = 0; i < nsaved; ++i) { - res = read_int(child, child->tss.bpt_addr[i], &insn); + res = read_int(child, child->thread.bpt_addr[i], &insn); if (res < 0) return res; - child->tss.bpt_insn[i] = insn; - DBG(DBG_BPT, (" -> next_pc=%lx\n", child->tss.bpt_addr[i])); - res = write_int(child, child->tss.bpt_addr[i], BREAKINST); + child->thread.bpt_insn[i] = insn; + DBG(DBG_BPT, (" -> next_pc=%lx\n", child->thread.bpt_addr[i])); + res = write_int(child, child->thread.bpt_addr[i], BREAKINST); if (res < 0) return res; } - child->tss.bpt_nsaved = nsaved; + child->thread.bpt_nsaved = nsaved; return 0; } @@ -210,9 +210,9 @@ ptrace_set_bpt(struct task_struct * child) int ptrace_cancel_bpt(struct task_struct * child) { - int i, nsaved = child->tss.bpt_nsaved; + int i, nsaved = child->thread.bpt_nsaved; - child->tss.bpt_nsaved = 0; + child->thread.bpt_nsaved = 0; if (nsaved > 2) { printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved); @@ -220,8 +220,8 @@ ptrace_cancel_bpt(struct task_struct * child) } for (i = 0; i < nsaved; ++i) { - write_int(child, child->tss.bpt_addr[i], - child->tss.bpt_insn[i]); + write_int(child, child->thread.bpt_addr[i], + child->thread.bpt_insn[i]); } return (nsaved != 0); } @@ -231,7 +231,6 @@ sys_ptrace(long request, long pid, long addr, long data, int a4, int a5, struct pt_regs regs) { struct task_struct *child; - unsigned long tmp; long ret; lock_kernel(); @@ -366,7 +365,7 @@ sys_ptrace(long request, long pid, long addr, long data, ret = -EIO; if ((unsigned long) data > _NSIG) goto out; - child->tss.bpt_nsaved = -1; /* mark single-stepping */ + child->thread.bpt_nsaved = -1; /* mark single-stepping */ child->flags &= ~PF_TRACESYS; wake_up_process(child); child->exit_code = data; diff --git a/arch/alpha/kernel/semaphore.c b/arch/alpha/kernel/semaphore.c new file mode 100644 index 000000000..d62b355e1 --- /dev/null +++ b/arch/alpha/kernel/semaphore.c @@ -0,0 +1,129 @@ +/* + * Generic semaphore code. Buyer beware. Do your own + * specific changes in <asm/semaphore-helper.h> + */ + +#include <linux/sched.h> +#include <asm/semaphore-helper.h> + +/* + * Semaphores are implemented using a two-way counter: + * The "count" variable is decremented for each process + * that tries to sleep, while the "waking" variable is + * incremented when the "up()" code goes to wake up waiting + * processes. + * + * Notably, the inline "up()" and "down()" functions can + * efficiently test if they need to do any extra work (up + * needs to do something only if count was negative before + * the increment operation. + * + * waking_non_zero() (from asm/semaphore.h) must execute + * atomically. + * + * When __up() is called, the count was negative before + * incrementing it, and we need to wake up somebody. + * + * This routine adds one to the count of processes that need to + * wake up and exit. ALL waiting processes actually wake up but + * only the one that gets to the "waking" field first will gate + * through and acquire the semaphore. The others will go back + * to sleep. + * + * Note that these functions are only called when there is + * contention on the lock, and as such all this is the + * "non-critical" part of the whole semaphore business. The + * critical part is the inline stuff in <asm/semaphore.h> + * where we want to avoid any extra jumps and calls. + */ +void __up(struct semaphore *sem) +{ + wake_one_more(sem); + wake_up(&sem->wait); +} + +/* + * Perform the "down" function. Return zero for semaphore acquired, + * return negative for signalled out of the function. + * + * If called from __down, the return is ignored and the wait loop is + * not interruptible. This means that a task waiting on a semaphore + * using "down()" cannot be killed until someone does an "up()" on + * the semaphore. + * + * If called from __down_interruptible, the return value gets checked + * upon return. If the return value is negative then the task continues + * with the negative value in the return register (it can be tested by + * the caller). + * + * Either form may be used in conjunction with "up()". + * + */ + +#define DOWN_VAR \ + struct task_struct *tsk = current; \ + wait_queue_t wait; \ + init_waitqueue_entry(&wait, tsk); + +#define DOWN_HEAD(task_state) \ + \ + \ + tsk->state = (task_state); \ + add_wait_queue(&sem->wait, &wait); \ + \ + /* \ + * Ok, we're set up. sem->count is known to be less than zero \ + * so we must wait. \ + * \ + * We can let go the lock for purposes of waiting. \ + * We re-acquire it after awaking so as to protect \ + * all semaphore operations. \ + * \ + * If "up()" is called before we call waking_non_zero() then \ + * we will catch it right away. If it is called later then \ + * we will have to go through a wakeup cycle to catch it. \ + * \ + * Multiple waiters contend for the semaphore lock to see \ + * who gets to gate through and who has to wait some more. \ + */ \ + for (;;) { + +#define DOWN_TAIL(task_state) \ + tsk->state = (task_state); \ + } \ + tsk->state = TASK_RUNNING; \ + remove_wait_queue(&sem->wait, &wait); + +void __down(struct semaphore * sem) +{ + DOWN_VAR + DOWN_HEAD(TASK_UNINTERRUPTIBLE) + if (waking_non_zero(sem)) + break; + schedule(); + DOWN_TAIL(TASK_UNINTERRUPTIBLE) +} + +int __down_interruptible(struct semaphore * sem) +{ + int ret = 0; + DOWN_VAR + DOWN_HEAD(TASK_INTERRUPTIBLE) + + ret = waking_non_zero_interruptible(sem, tsk); + if (ret) + { + if (ret == 1) + /* ret != 0 only if we get interrupted -arca */ + ret = 0; + break; + } + schedule(); + DOWN_TAIL(TASK_INTERRUPTIBLE) + return ret; +} + +int __down_trylock(struct semaphore * sem) +{ + return waking_non_zero_trylock(sem); +} diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c index 6c13fea3f..47a86c9fe 100644 --- a/arch/alpha/kernel/setup.c +++ b/arch/alpha/kernel/setup.c @@ -25,6 +25,7 @@ #include <linux/errno.h> #include <linux/init.h> #include <linux/string.h> +#include <linux/ioport.h> #ifdef CONFIG_RTC #include <linux/timex.h> @@ -39,16 +40,18 @@ #include <asm/hwrpb.h> #include <asm/dma.h> #include <asm/io.h> - +#include <asm/pci.h> #include "proto.h" +#include "pci_impl.h" + struct hwrpb_struct *hwrpb; unsigned long srm_hae; #ifdef CONFIG_ALPHA_GENERIC struct alpha_machine_vector alpha_mv; -int alpha_using_srm, alpha_use_srm_setup; +int alpha_using_srm; #endif unsigned char aux_device_present = 0xaa; @@ -90,6 +93,7 @@ struct screen_info screen_info = { orig_video_points: 16 }; + /* * Declare all of the machine vectors. */ @@ -136,6 +140,47 @@ WEAK(xlt_mv); #undef WEAK +/* + * I/O resources inherited from PeeCees. Except for perhaps the + * turbochannel alphas, everyone has these on some sort of SuperIO chip. + * + * ??? If this becomes less standard, move the struct out into the + * machine vector. + */ + +static void __init +reserve_std_resources(void) +{ + static struct resource standard_io_resources[] = { + { "rtc", -1, -1 }, + { "dma1", 0x00, 0x1f }, + { "pic1", 0x20, 0x3f }, + { "timer", 0x40, 0x5f }, + { "keyboard", 0x60, 0x6f }, + { "dma page reg", 0x80, 0x8f }, + { "pic2", 0xa0, 0xbf }, + { "dma2", 0xc0, 0xdf }, + }; + + struct resource *io = &ioport_resource; + long i; + + if (hose_head) { + struct pci_controler *hose; + for (hose = hose_head; hose; hose = hose->next) + if (hose->index == 0) { + io = hose->io_space; + break; + } + } + + /* Fix up for the Jensen's queer RTC placement. */ + standard_io_resources[0].start = RTC_PORT(0); + standard_io_resources[0].end = RTC_PORT(0) + 0x10; + + for (i = 0; i < N(standard_io_resources); ++i) + request_resource(io, standard_io_resources+i); +} void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, @@ -171,20 +216,10 @@ setup_arch(char **cmdline_p, unsigned long * memory_start_p, */ for (p = strtok(command_line, " \t"); p ; p = strtok(NULL, " \t")) { -#ifndef alpha_use_srm_setup - /* Allow a command-line option to respect the - SRM's configuration. */ - if (strncmp(p, "srm_setup=", 10) == 0) { - alpha_use_srm_setup = (p[10] != '0'); - continue; - } -#endif - if (strncmp(p, "alpha_mv=", 9) == 0) { vec = get_sysvec_byname(p+9); continue; } - if (strncmp(p, "cycle=", 6) == 0) { est_cycle_freq = simple_strtol(p+6, NULL, 0); continue; @@ -224,9 +259,15 @@ setup_arch(char **cmdline_p, unsigned long * memory_start_p, alpha_using_srm = strncmp((const char *)hwrpb->ssn, "MILO", 4) != 0; #endif - printk("Booting on %s%s%s using machine vector %s\n", + printk("Booting " +#ifdef CONFIG_ALPHA_GENERIC + "GENERIC " +#endif + "on %s%s%s using machine vector %s from %s\n", type_name, (*var_name ? " variation " : ""), - var_name, alpha_mv.vector_name); + var_name, alpha_mv.vector_name, + (alpha_using_srm ? "SRM" : "MILO")); + printk("Command line: %s\n", command_line); /* @@ -265,6 +306,9 @@ setup_arch(char **cmdline_p, unsigned long * memory_start_p, if (alpha_mv.init_arch) alpha_mv.init_arch(memory_start_p, memory_end_p); + /* Reserve standard resources. */ + reserve_std_resources(); + /* Initialize the timers. */ /* ??? There is some circumstantial evidence that this needs to be done now rather than later in time_init, which would diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index 832d72ee0..cd8f6e0ad 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c @@ -688,12 +688,8 @@ do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw, case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: - lock_kernel(); - if (current->binfmt - && current->binfmt->core_dump - && current->binfmt->core_dump(signr, regs)) + if (do_coredump(signr, regs)) exit_code |= 0x80; - unlock_kernel(); /* FALLTHRU */ default: diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index eef452e57..e35dd7c7e 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c @@ -7,12 +7,13 @@ #include <linux/kernel_stat.h> #include <linux/sched.h> #include <linux/mm.h> -#include <linux/tasks.h> +#include <linux/threads.h> #include <linux/smp.h> #include <linux/smp_lock.h> #include <linux/interrupt.h> #include <linux/init.h> #include <linux/delay.h> +#include <linux/spinlock.h> #include <asm/hwrpb.h> #include <asm/ptrace.h> @@ -22,7 +23,6 @@ #include <asm/irq.h> #include <asm/bitops.h> #include <asm/pgtable.h> -#include <asm/spinlock.h> #include <asm/hardirq.h> #include <asm/softirq.h> @@ -30,7 +30,7 @@ #include <asm/unistd.h> #include "proto.h" -#include "irq.h" +#include "irq_impl.h" #define DEBUG_SMP 0 @@ -75,18 +75,23 @@ extern void calibrate_delay(void); extern asmlinkage void entInt(void); -/* - * Process bootcommand SMP options, like "nosmp" and "maxcpus=". - */ -void __init -smp_setup(char *str, int *ints) +static int __init nosmp(char *str) +{ + max_cpus = 0; + return 1; +} + +__setup("nosmp", nosmp); + +static int __init maxcpus(char *str) { - if (ints && ints[0] > 0) - max_cpus = ints[1]; - else - max_cpus = 0; + get_option(&str, &max_cpus); + return 1; } +__setup("maxcpus", maxcpus); + + /* * Called by both boot and secondaries to move global data into * per-processor storage. @@ -97,6 +102,8 @@ smp_store_cpu_info(int cpuid) cpu_data[cpuid].loops_per_sec = loops_per_sec; cpu_data[cpuid].last_asn = (cpuid << WIDTH_HARDWARE_ASN) + ASN_FIRST_VERSION; + cpu_data[cpuid].irq_count = 0; + cpu_data[cpuid].bh_count = 0; } /* @@ -107,12 +114,6 @@ smp_setup_percpu_timer(int cpuid) { cpu_data[cpuid].prof_counter = 1; cpu_data[cpuid].prof_multiplier = 1; - -#ifdef NOT_YET_PROFILING - load_profile_irq(mid_xlate[cpu], lvl14_resolution); - if (cpu == smp_boot_cpuid) - enable_pil_irq(14); -#endif } /* @@ -137,6 +138,10 @@ smp_callin(void) /* Setup the scheduler for this processor. */ init_idle(); + /* ??? This should be in init_idle. */ + atomic_inc(&init_mm.mm_count); + current->active_mm = &init_mm; + /* Get our local ticker going. */ smp_setup_percpu_timer(cpuid); @@ -157,7 +162,7 @@ smp_callin(void) cpuid, current)); /* Do nothing. */ - cpu_idle(NULL); + cpu_idle(); } @@ -339,21 +344,21 @@ secondary_cpu_start(int cpuid, struct task_struct *idle) /* Initialize the CPU's HWPCB to something just good enough for us to get started. Immediately after starting, we'll swpctx - to the target idle task's tss. Reuse the stack in the mean + to the target idle task's ptb. Reuse the stack in the mean time. Precalculate the target PCBB. */ hwpcb->ksp = (unsigned long) idle + sizeof(union task_union) - 16; hwpcb->usp = 0; - hwpcb->ptbr = idle->tss.ptbr; + hwpcb->ptbr = idle->thread.ptbr; hwpcb->pcc = 0; hwpcb->asn = 0; - hwpcb->unique = virt_to_phys(&idle->tss); - hwpcb->flags = idle->tss.pal_flags; + hwpcb->unique = virt_to_phys(&idle->thread); + hwpcb->flags = idle->thread.pal_flags; hwpcb->res1 = hwpcb->res2 = 0; DBGS(("KSP 0x%lx PTBR 0x%lx VPTBR 0x%lx UNIQUE 0x%lx\n", hwpcb->ksp, hwpcb->ptbr, hwrpb->vptb, hwcpb->unique)); DBGS(("Starting secondary cpu %d: state 0x%lx pal_flags 0x%lx\n", - cpuid, idle->state, idle->tss.pal_flags)); + cpuid, idle->state, idle->thread.pal_flags)); /* Setup HWRPB fields that SRM uses to activate secondary CPU */ hwrpb->CPU_restart = __smp_callin; @@ -403,10 +408,13 @@ smp_boot_one_cpu(int cpuid, int cpunum) HWRPB.CPU_restart says to start. But this gets all the other task-y sort of data structures set up like we wish. */ kernel_thread((void *)__smp_callin, NULL, CLONE_PID|CLONE_VM); - idle = task[cpunum]; - if (!idle) - panic("No idle process for CPU %d", cpuid); - idle->processor = cpuid; + + idle = init_task.prev_task; + if (!idle) + panic("No idle process for CPU %d", cpunum); + del_from_runqueue(idle); + init_tasks[cpunum] = idle; + idle->processor = cpuid; /* Schedule the first task manually. */ /* ??? Ingo, what is this? */ @@ -516,6 +524,10 @@ smp_boot_cpus(void) init_idle(); + /* ??? This should be in init_idle. */ + atomic_inc(&init_mm.mm_count); + current->active_mm = &init_mm; + /* Nothing to do on a UP box, or when told not to. */ if (smp_num_probed == 1 || max_cpus == 0) { printk(KERN_INFO "SMP mode deactivated.\n"); @@ -586,14 +598,12 @@ void smp_percpu_timer_interrupt(struct pt_regs *regs) { int cpu = smp_processor_id(); - int user = user_mode(regs); + unsigned long user = user_mode(regs); struct cpuinfo_alpha *data = &cpu_data[cpu]; -#ifdef NOT_YET_PROFILING - clear_profile_irq(mid_xlate[cpu]); + /* Record kernel PC. */ if (!user) alpha_do_profile(regs->pc); -#endif if (!--data->prof_counter) { /* We need to make like a normal interrupt -- otherwise @@ -630,28 +640,7 @@ smp_percpu_timer_interrupt(struct pt_regs *regs) int __init setup_profiling_timer(unsigned int multiplier) { -#ifdef NOT_YET_PROFILING - int i; - unsigned long flags; - - /* Prevent level14 ticker IRQ flooding. */ - if((!multiplier) || (lvl14_resolution / multiplier) < 500) - return -EINVAL; - - save_and_cli(flags); - for (i = 0; i < NR_CPUS; i++) { - if (cpu_present_mask & (1L << i)) { - load_profile_irq(mid_xlate[i], - lvl14_resolution / multiplier); - prof_multiplier[i] = multiplier; - } - } - restore_flags(flags); - - return 0; -#else return -EINVAL; -#endif } @@ -886,16 +875,18 @@ static void ipi_flush_tlb_mm(void *x) { struct mm_struct *mm = (struct mm_struct *) x; - if (mm == current->mm) + if (mm == current->active_mm) flush_tlb_current(mm); } void flush_tlb_mm(struct mm_struct *mm) { - if (mm == current->mm) + if (mm == current->active_mm) { flush_tlb_current(mm); - else + if (atomic_read(&mm->mm_users) <= 1) + return; + } else flush_tlb_other(mm); if (smp_call_function(ipi_flush_tlb_mm, mm, 1, 1)) { @@ -913,7 +904,7 @@ static void ipi_flush_tlb_page(void *x) { struct flush_tlb_page_struct *data = (struct flush_tlb_page_struct *)x; - if (data->mm == current->mm) + if (data->mm == current->active_mm) flush_tlb_current_page(data->mm, data->vma, data->addr); } @@ -923,15 +914,17 @@ flush_tlb_page(struct vm_area_struct *vma, unsigned long addr) struct flush_tlb_page_struct data; struct mm_struct *mm = vma->vm_mm; + if (mm == current->active_mm) { + flush_tlb_current_page(mm, vma, addr); + if (atomic_read(&mm->mm_users) <= 1) + return; + } else + flush_tlb_other(mm); + data.vma = vma; data.mm = mm; data.addr = addr; - if (mm == current->mm) - flush_tlb_current_page(mm, vma, addr); - else - flush_tlb_other(mm); - if (smp_call_function(ipi_flush_tlb_page, &data, 1, 1)) { printk(KERN_CRIT "flush_tlb_page: timed out\n"); } diff --git a/arch/alpha/kernel/sys_alcor.c b/arch/alpha/kernel/sys_alcor.c index adcc91f34..fbc1b99ba 100644 --- a/arch/alpha/kernel/sys_alcor.c +++ b/arch/alpha/kernel/sys_alcor.c @@ -3,7 +3,7 @@ * * Copyright (C) 1995 David A Rusling * Copyright (C) 1996 Jay A Estabrook - * Copyright (C) 1998 Richard Henderson + * Copyright (C) 1998, 1999 Richard Henderson * * Code supporting the ALCOR and XLT (XL-300/366/433). */ @@ -27,9 +27,9 @@ #include <asm/core_cia.h> #include "proto.h" -#include "irq.h" -#include "bios32.h" -#include "machvec.h" +#include "irq_impl.h" +#include "pci_impl.h" +#include "machvec_impl.h" static void @@ -158,7 +158,7 @@ alcor_init_irq(void) */ static int __init -alcor_map_irq(struct pci_dev *dev, int slot, int pin) +alcor_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { static char irq_tab[7][5] __initlocaldata = { /*INT INTA INTB INTC INTD */ @@ -175,16 +175,8 @@ alcor_map_irq(struct pci_dev *dev, int slot, int pin) return COMMON_TABLE_LOOKUP; } -static void __init -alcor_pci_fixup(void) -{ - layout_all_busses(EISA_DEFAULT_IO_BASE, DEFAULT_MEM_BASE); - common_pci_fixup(alcor_map_irq, common_swizzle); -} - - static void -alcor_kill_arch (int mode, char *reboot_cmd) +alcor_kill_arch(int mode, char *reboot_cmd) { /* Who said DEC engineer's have no sense of humor? ;-) */ if (alpha_using_srm) { @@ -192,7 +184,7 @@ alcor_kill_arch (int mode, char *reboot_cmd) mb(); } - generic_kill_arch(mode, reboot_cmd); + common_kill_arch(mode, reboot_cmd); } @@ -209,6 +201,8 @@ struct alpha_machine_vector alcor_mv __initmv = { DO_CIA_BUS, machine_check: cia_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: EISA_DEFAULT_IO_BASE, + min_mem_address: CIA_DEFAULT_MEM_BASE, nr_irqs: 48, irq_probe_mask: ALCOR_PROBE_MASK, @@ -218,9 +212,11 @@ struct alpha_machine_vector alcor_mv __initmv = { init_arch: cia_init_arch, init_irq: alcor_init_irq, - init_pit: generic_init_pit, - pci_fixup: alcor_pci_fixup, + init_pit: common_init_pit, + init_pci: common_init_pci, kill_arch: alcor_kill_arch, + pci_map_irq: alcor_map_irq, + pci_swizzle: common_swizzle, sys: { cia: { gru_int_req_bits: ALCOR_GRU_INT_REQ_BITS @@ -238,6 +234,8 @@ struct alpha_machine_vector xlt_mv __initmv = { DO_CIA_BUS, machine_check: cia_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: EISA_DEFAULT_IO_BASE, + min_mem_address: CIA_DEFAULT_MEM_BASE, nr_irqs: 48, irq_probe_mask: ALCOR_PROBE_MASK, @@ -247,9 +245,11 @@ struct alpha_machine_vector xlt_mv __initmv = { init_arch: cia_init_arch, init_irq: alcor_init_irq, - init_pit: generic_init_pit, - pci_fixup: alcor_pci_fixup, + init_pit: common_init_pit, + init_pci: common_init_pci, kill_arch: alcor_kill_arch, + pci_map_irq: alcor_map_irq, + pci_swizzle: common_swizzle, sys: { cia: { gru_int_req_bits: XLT_GRU_INT_REQ_BITS diff --git a/arch/alpha/kernel/sys_cabriolet.c b/arch/alpha/kernel/sys_cabriolet.c index 37f29e147..244759d1f 100644 --- a/arch/alpha/kernel/sys_cabriolet.c +++ b/arch/alpha/kernel/sys_cabriolet.c @@ -3,7 +3,7 @@ * * Copyright (C) 1995 David A Rusling * Copyright (C) 1996 Jay A Estabrook - * Copyright (C) 1998 Richard Henderson + * Copyright (C) 1998, 1999 Richard Henderson * * Code supporting the Cabriolet (AlphaPC64), EB66+, and EB164, * PC164 and LX164. @@ -31,9 +31,9 @@ #include <asm/core_pyxis.h> #include "proto.h" -#include "irq.h" -#include "bios32.h" -#include "machvec.h" +#include "irq_impl.h" +#include "pci_impl.h" +#include "machvec_impl.h" static void @@ -124,7 +124,7 @@ cabriolet_init_irq(void) */ static inline int __init -eb66p_map_irq(struct pci_dev *dev, int slot, int pin) +eb66p_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { static char irq_tab[5][5] __initlocaldata = { /*INT INTA INTB INTC INTD */ @@ -138,14 +138,6 @@ eb66p_map_irq(struct pci_dev *dev, int slot, int pin) return COMMON_TABLE_LOOKUP; } -static inline void __init -eb66p_pci_fixup(void) -{ - layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE); - common_pci_fixup(eb66p_map_irq, common_swizzle); - enable_ide(0x398); -} - /* * The AlphaPC64 is very similar to the EB66+ except that its slots @@ -162,7 +154,7 @@ eb66p_pci_fixup(void) */ static inline int __init -cabriolet_map_irq(struct pci_dev *dev, int slot, int pin) +cabriolet_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { static char irq_tab[5][5] __initlocaldata = { /*INT INTA INTB INTC INTD */ @@ -177,19 +169,10 @@ cabriolet_map_irq(struct pci_dev *dev, int slot, int pin) } static inline void __init -cabriolet_pci_fixup(void) -{ - layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE); - common_pci_fixup(cabriolet_map_irq, common_swizzle); - enable_ide(0x398); -} - -static inline void __init -eb164_pci_fixup(void) +cabriolet_init_pci(void) { - layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); - common_pci_fixup(cabriolet_map_irq, common_swizzle); - enable_ide(0x398); + common_init_pci(); + ns87312_enable_ide(0x398); } @@ -236,7 +219,7 @@ eb164_pci_fixup(void) */ static inline int __init -alphapc164_map_irq(struct pci_dev *dev, int slot, int pin) +alphapc164_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { static char irq_tab[7][5] __initlocaldata = { /*INT INTA INTB INTC INTD */ @@ -253,13 +236,13 @@ alphapc164_map_irq(struct pci_dev *dev, int slot, int pin) } static inline void __init -alphapc164_pci_fixup(void) +alphapc164_init_pci(void) { - layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); - common_pci_fixup(alphapc164_map_irq, common_swizzle); + common_init_pci(); SMC93x_Init(); } + /* * The System Vector */ @@ -273,18 +256,22 @@ struct alpha_machine_vector cabriolet_mv __initmv = { DO_APECS_BUS, machine_check: apecs_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: DEFAULT_IO_BASE, + min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE, nr_irqs: 35, irq_probe_mask: _PROBE_MASK(35), update_irq_hw: cabriolet_update_irq_hw, - ack_irq: generic_ack_irq, + ack_irq: common_ack_irq, device_interrupt: cabriolet_device_interrupt, init_arch: apecs_init_arch, init_irq: cabriolet_init_irq, - init_pit: generic_init_pit, - pci_fixup: cabriolet_pci_fixup, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: cabriolet_init_pci, + kill_arch: common_kill_arch, + pci_map_irq: cabriolet_map_irq, + pci_swizzle: common_swizzle, }; ALIAS_MV(cabriolet) #endif @@ -298,18 +285,22 @@ struct alpha_machine_vector eb164_mv __initmv = { DO_CIA_BUS, machine_check: cia_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: DEFAULT_IO_BASE, + min_mem_address: CIA_DEFAULT_MEM_BASE, nr_irqs: 35, irq_probe_mask: _PROBE_MASK(35), update_irq_hw: cabriolet_update_irq_hw, - ack_irq: generic_ack_irq, + ack_irq: common_ack_irq, device_interrupt: cabriolet_device_interrupt, init_arch: cia_init_arch, init_irq: cabriolet_init_irq, - init_pit: generic_init_pit, - pci_fixup: eb164_pci_fixup, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: cabriolet_init_pci, + kill_arch: common_kill_arch, + pci_map_irq: cabriolet_map_irq, + pci_swizzle: common_swizzle, }; ALIAS_MV(eb164) #endif @@ -323,18 +314,22 @@ struct alpha_machine_vector eb66p_mv __initmv = { DO_LCA_BUS, machine_check: lca_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: DEFAULT_IO_BASE, + min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE, nr_irqs: 35, irq_probe_mask: _PROBE_MASK(35), update_irq_hw: cabriolet_update_irq_hw, - ack_irq: generic_ack_irq, + ack_irq: common_ack_irq, device_interrupt: cabriolet_device_interrupt, init_arch: lca_init_arch, init_irq: cabriolet_init_irq, - init_pit: generic_init_pit, - pci_fixup: eb66p_pci_fixup, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: cabriolet_init_pci, + kill_arch: common_kill_arch, + pci_map_irq: eb66p_map_irq, + pci_swizzle: common_swizzle, }; ALIAS_MV(eb66p) #endif @@ -348,18 +343,22 @@ struct alpha_machine_vector lx164_mv __initmv = { DO_PYXIS_BUS, machine_check: pyxis_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: DEFAULT_IO_BASE, + min_mem_address: DEFAULT_MEM_BASE, nr_irqs: 35, irq_probe_mask: _PROBE_MASK(35), update_irq_hw: cabriolet_update_irq_hw, - ack_irq: generic_ack_irq, + ack_irq: common_ack_irq, device_interrupt: cabriolet_device_interrupt, init_arch: pyxis_init_arch, init_irq: cabriolet_init_irq, - init_pit: generic_init_pit, - pci_fixup: alphapc164_pci_fixup, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: alphapc164_init_pci, + kill_arch: common_kill_arch, + pci_map_irq: alphapc164_map_irq, + pci_swizzle: common_swizzle, }; ALIAS_MV(lx164) #endif @@ -373,19 +372,22 @@ struct alpha_machine_vector pc164_mv __initmv = { DO_CIA_BUS, machine_check: cia_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: DEFAULT_IO_BASE, + min_mem_address: CIA_DEFAULT_MEM_BASE, nr_irqs: 35, irq_probe_mask: _PROBE_MASK(35), update_irq_hw: cabriolet_update_irq_hw, - ack_irq: generic_ack_irq, + ack_irq: common_ack_irq, device_interrupt: cabriolet_device_interrupt, init_arch: cia_init_arch, init_irq: cabriolet_init_irq, - init_pit: generic_init_pit, - pci_fixup: alphapc164_pci_fixup, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: alphapc164_init_pci, + kill_arch: common_kill_arch, + pci_map_irq: alphapc164_map_irq, + pci_swizzle: common_swizzle, }; ALIAS_MV(pc164) #endif - diff --git a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c index f465b3b4e..a5806275f 100644 --- a/arch/alpha/kernel/sys_dp264.c +++ b/arch/alpha/kernel/sys_dp264.c @@ -28,11 +28,10 @@ #include <asm/hwrpb.h> #include "proto.h" -#include "irq.h" -#include "bios32.h" -#include "machvec.h" +#include "irq_impl.h" +#include "pci_impl.h" +#include "machvec_impl.h" -#define dev2hose(d) (bus2hose[(d)->bus->number]->pci_hose_index) /* * HACK ALERT! only the boot cpu is used for interrupts. @@ -260,7 +259,7 @@ clipper_init_irq(void) */ static int __init -dp264_map_irq(struct pci_dev *dev, int slot, int pin) +dp264_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { static char irq_tab[6][5] __initlocaldata = { /*INT INTA INTB INTC INTD */ @@ -272,16 +271,18 @@ dp264_map_irq(struct pci_dev *dev, int slot, int pin) { 16+ 3, 16+ 3, 16+ 2, 16+ 1, 16+ 0} /* IdSel 10 slot 3 */ }; const long min_idsel = 5, max_idsel = 10, irqs_per_slot = 5; + + struct pci_controler *hose = dev->sysdata; int irq = COMMON_TABLE_LOOKUP; if (irq > 0) - irq += 16 * dev2hose(dev); + irq += 16 * hose->index; return irq; } static int __init -monet_map_irq(struct pci_dev *dev, int slot, int pin) +monet_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { static char irq_tab[13][5] __initlocaldata = { /*INT INTA INTB INTC INTD */ @@ -308,19 +309,23 @@ monet_map_irq(struct pci_dev *dev, int slot, int pin) return COMMON_TABLE_LOOKUP; } -static int __init -monet_swizzle(struct pci_dev *dev, int *pinp) +static u8 __init +monet_swizzle(struct pci_dev *dev, u8 *pinp) { + struct pci_controler *hose = dev->sysdata; int slot, pin = *pinp; - /* Check first for the built-in bridge on hose 1. */ - if (dev2hose(dev) == 1 && PCI_SLOT(dev->bus->self->devfn) == 8) { + if (hose->first_busno == dev->bus->number) { + slot = PCI_SLOT(dev->devfn); + } + /* Check for the built-in bridge on hose 1. */ + else if (hose->index == 1 && PCI_SLOT(dev->bus->self->devfn) == 8) { slot = PCI_SLOT(dev->devfn); } else { /* Must be a card-based bridge. */ do { /* Check for built-in bridge on hose 1. */ - if (dev2hose(dev) == 1 && + if (hose->index == 1 && PCI_SLOT(dev->bus->self->devfn) == 8) { slot = PCI_SLOT(dev->devfn); break; @@ -338,7 +343,7 @@ monet_swizzle(struct pci_dev *dev, int *pinp) } static int __init -webbrick_map_irq(struct pci_dev *dev, int slot, int pin) +webbrick_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { static char irq_tab[13][5] __initlocaldata = { /*INT INTA INTB INTC INTD */ @@ -359,7 +364,7 @@ webbrick_map_irq(struct pci_dev *dev, int slot, int pin) } static int __init -clipper_map_irq(struct pci_dev *dev, int slot, int pin) +clipper_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { static char irq_tab[7][5] __initlocaldata = { /*INT INTA INTB INTC INTD */ @@ -372,44 +377,29 @@ clipper_map_irq(struct pci_dev *dev, int slot, int pin) { -1, -1, -1, -1, -1} /* IdSel 7 ISA Bridge */ }; const long min_idsel = 1, max_idsel = 7, irqs_per_slot = 5; + + struct pci_controler *hose = dev->sysdata; int irq = COMMON_TABLE_LOOKUP; if (irq > 0) - irq += 16 * dev2hose(dev); + irq += 16 * hose->index; return irq; } static void __init -dp264_pci_fixup(void) +dp264_init_pci(void) { - layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); - common_pci_fixup(dp264_map_irq, common_swizzle); + common_init_pci(); SMC669_Init(0); } static void __init -monet_pci_fixup(void) +monet_init_pci(void) { - layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); - common_pci_fixup(monet_map_irq, monet_swizzle); - /* es1888_init(); */ /* later? */ + common_init_pci(); SMC669_Init(1); -} - -static void __init -webbrick_pci_fixup(void) -{ - layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); - common_pci_fixup(webbrick_map_irq, common_swizzle); - SMC669_Init(0); -} - -static void __init -clipper_pci_fixup(void) -{ - layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); - common_pci_fixup(clipper_map_irq, common_swizzle); + es1888_init(); } @@ -425,18 +415,22 @@ struct alpha_machine_vector dp264_mv __initmv = { DO_TSUNAMI_BUS, machine_check: tsunami_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: DEFAULT_IO_BASE, + min_mem_address: DEFAULT_MEM_BASE, nr_irqs: 64, irq_probe_mask: _PROBE_MASK(64), update_irq_hw: dp264_update_irq_hw, - ack_irq: generic_ack_irq, + ack_irq: common_ack_irq, device_interrupt: dp264_device_interrupt, init_arch: tsunami_init_arch, init_irq: dp264_init_irq, - init_pit: generic_init_pit, - pci_fixup: dp264_pci_fixup, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: dp264_init_pci, + kill_arch: common_kill_arch, + pci_map_irq: dp264_map_irq, + pci_swizzle: common_swizzle, }; ALIAS_MV(dp264) @@ -448,18 +442,22 @@ struct alpha_machine_vector monet_mv __initmv = { DO_TSUNAMI_BUS, machine_check: tsunami_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: DEFAULT_IO_BASE, + min_mem_address: DEFAULT_MEM_BASE, nr_irqs: 64, irq_probe_mask: _PROBE_MASK(64), update_irq_hw: dp264_update_irq_hw, - ack_irq: generic_ack_irq, + ack_irq: common_ack_irq, device_interrupt: dp264_device_interrupt, init_arch: tsunami_init_arch, init_irq: dp264_init_irq, - init_pit: generic_init_pit, - pci_fixup: monet_pci_fixup, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: monet_init_pci, + kill_arch: common_kill_arch, + pci_map_irq: monet_map_irq, + pci_swizzle: monet_swizzle, }; struct alpha_machine_vector webbrick_mv __initmv = { @@ -470,18 +468,22 @@ struct alpha_machine_vector webbrick_mv __initmv = { DO_TSUNAMI_BUS, machine_check: tsunami_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: DEFAULT_IO_BASE, + min_mem_address: DEFAULT_MEM_BASE, nr_irqs: 64, irq_probe_mask: _PROBE_MASK(64), update_irq_hw: dp264_update_irq_hw, - ack_irq: generic_ack_irq, + ack_irq: common_ack_irq, device_interrupt: dp264_device_interrupt, init_arch: tsunami_init_arch, init_irq: dp264_init_irq, - init_pit: generic_init_pit, - pci_fixup: webbrick_pci_fixup, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: dp264_init_pci, + kill_arch: common_kill_arch, + pci_map_irq: webbrick_map_irq, + pci_swizzle: common_swizzle, }; struct alpha_machine_vector clipper_mv __initmv = { @@ -492,18 +494,22 @@ struct alpha_machine_vector clipper_mv __initmv = { DO_TSUNAMI_BUS, machine_check: tsunami_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: DEFAULT_IO_BASE, + min_mem_address: DEFAULT_MEM_BASE, nr_irqs: 64, irq_probe_mask: _PROBE_MASK(64), update_irq_hw: clipper_update_irq_hw, - ack_irq: generic_ack_irq, + ack_irq: common_ack_irq, device_interrupt: dp264_device_interrupt, init_arch: tsunami_init_arch, init_irq: clipper_init_irq, - init_pit: generic_init_pit, - pci_fixup: clipper_pci_fixup, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: common_init_pci, + kill_arch: common_kill_arch, + pci_map_irq: clipper_map_irq, + pci_swizzle: common_swizzle, }; /* No alpha_mv alias for webbrick/monet/clipper, since we compile them diff --git a/arch/alpha/kernel/sys_eb64p.c b/arch/alpha/kernel/sys_eb64p.c index 683baa02e..09e0b0def 100644 --- a/arch/alpha/kernel/sys_eb64p.c +++ b/arch/alpha/kernel/sys_eb64p.c @@ -3,7 +3,7 @@ * * Copyright (C) 1995 David A Rusling * Copyright (C) 1996 Jay A Estabrook - * Copyright (C) 1998 Richard Henderson + * Copyright (C) 1998, 1999 Richard Henderson * * Code supporting the EB64+ and EB66. */ @@ -28,9 +28,9 @@ #include <asm/core_lca.h> #include "proto.h" -#include "irq.h" -#include "bios32.h" -#include "machvec.h" +#include "irq_impl.h" +#include "pci_impl.h" +#include "machvec_impl.h" static void @@ -142,7 +142,7 @@ eb64p_init_irq(void) */ static int __init -eb64p_map_irq(struct pci_dev *dev, int slot, int pin) +eb64p_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { static char irq_tab[5][5] __initlocaldata = { /*INT INTA INTB INTC INTD */ @@ -156,13 +156,6 @@ eb64p_map_irq(struct pci_dev *dev, int slot, int pin) return COMMON_TABLE_LOOKUP; } -static void __init -eb64p_pci_fixup(void) -{ - layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE); - common_pci_fixup(eb64p_map_irq, common_swizzle); -} - /* * The System Vector @@ -177,18 +170,22 @@ struct alpha_machine_vector eb64p_mv __initmv = { DO_APECS_BUS, machine_check: apecs_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: DEFAULT_IO_BASE, + min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE, nr_irqs: 32, irq_probe_mask: _PROBE_MASK(32), update_irq_hw: eb64p_update_irq_hw, - ack_irq: generic_ack_irq, + ack_irq: common_ack_irq, device_interrupt: eb64p_device_interrupt, init_arch: apecs_init_arch, init_irq: eb64p_init_irq, - init_pit: generic_init_pit, - pci_fixup: eb64p_pci_fixup, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: common_init_pci, + kill_arch: common_kill_arch, + pci_map_irq: eb64p_map_irq, + pci_swizzle: common_swizzle, }; ALIAS_MV(eb64p) #endif @@ -202,18 +199,22 @@ struct alpha_machine_vector eb66_mv __initmv = { DO_LCA_BUS, machine_check: lca_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: DEFAULT_IO_BASE, + min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE, nr_irqs: 32, irq_probe_mask: _PROBE_MASK(32), update_irq_hw: eb64p_update_irq_hw, - ack_irq: generic_ack_irq, + ack_irq: common_ack_irq, device_interrupt: eb64p_device_interrupt, init_arch: lca_init_arch, init_irq: eb64p_init_irq, - init_pit: generic_init_pit, - pci_fixup: eb64p_pci_fixup, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: common_init_pci, + kill_arch: common_kill_arch, + pci_map_irq: eb64p_map_irq, + pci_swizzle: common_swizzle, }; ALIAS_MV(eb66) #endif diff --git a/arch/alpha/kernel/sys_jensen.c b/arch/alpha/kernel/sys_jensen.c index 93a65e76e..0380574a8 100644 --- a/arch/alpha/kernel/sys_jensen.c +++ b/arch/alpha/kernel/sys_jensen.c @@ -2,7 +2,7 @@ * linux/arch/alpha/kernel/sys_jensen.c * * Copyright (C) 1995 Linus Torvalds - * Copyright (C) 1998 Richard Henderson + * Copyright (C) 1998, 1999 Richard Henderson * * Code supporting the Jensen. */ @@ -28,8 +28,8 @@ #include <asm/pgtable.h> #include "proto.h" -#include "irq.h" -#include "machvec.h" +#include "irq_impl.h" +#include "machvec_impl.h" static void @@ -124,7 +124,7 @@ jensen_machine_check (u64 vector, u64 la, struct pt_regs *regs) struct alpha_machine_vector jensen_mv __initmv = { vector_name: "Jensen", DO_EV4_MMU, - IO_LITE(JENSEN,jensen,jensen), + IO_LITE(JENSEN,jensen), BUS(jensen), machine_check: jensen_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, @@ -133,12 +133,13 @@ struct alpha_machine_vector jensen_mv __initmv = { nr_irqs: 16, irq_probe_mask: _PROBE_MASK(16), update_irq_hw: jensen_update_irq_hw, - ack_irq: generic_ack_irq, + ack_irq: common_ack_irq, device_interrupt: jensen_device_interrupt, init_arch: NULL, init_irq: jensen_init_irq, - init_pit: generic_init_pit, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: NULL, + kill_arch: common_kill_arch, }; ALIAS_MV(jensen) diff --git a/arch/alpha/kernel/sys_miata.c b/arch/alpha/kernel/sys_miata.c index f9c4b64c5..0bea4e3dd 100644 --- a/arch/alpha/kernel/sys_miata.c +++ b/arch/alpha/kernel/sys_miata.c @@ -3,7 +3,7 @@ * * Copyright (C) 1995 David A Rusling * Copyright (C) 1996 Jay A Estabrook - * Copyright (C) 1998 Richard Henderson + * Copyright (C) 1998, 1999 Richard Henderson * * Code supporting the MIATA (EV56+PYXIS). */ @@ -25,9 +25,9 @@ #include <asm/core_pyxis.h> #include "proto.h" -#include "irq.h" -#include "bios32.h" -#include "machvec.h" +#include "irq_impl.h" +#include "pci_impl.h" +#include "machvec_impl.h" static void @@ -202,7 +202,7 @@ miata_init_irq(void) */ static int __init -miata_map_irq(struct pci_dev *dev, int slot, int pin) +miata_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { static char irq_tab[18][5] __initlocaldata = { /*INT INTA INTB INTC INTD */ @@ -224,21 +224,24 @@ miata_map_irq(struct pci_dev *dev, int slot, int pin) {16+20, 16+20, 16+21, 16+22, 16+23}, /* IdSel 28, slot 1 */ {16+24, 16+24, 16+25, 16+26, 16+27}, /* IdSel 29, slot 2 */ {16+28, 16+28, 16+29, 16+30, 16+31}, /* IdSel 30, slot 3 */ - /* this bridge is on the main bus of the later original MIATA */ + /* This bridge is on the main bus of the later orig MIATA */ { -1, -1, -1, -1, -1}, /* IdSel 31, PCI-PCI */ }; const long min_idsel = 3, max_idsel = 20, irqs_per_slot = 5; return COMMON_TABLE_LOOKUP; } -static int __init -miata_swizzle(struct pci_dev *dev, int *pinp) +static u8 __init +miata_swizzle(struct pci_dev *dev, u8 *pinp) { int slot, pin = *pinp; - /* Check first for the built-in bridge. */ - if ((PCI_SLOT(dev->bus->self->devfn) == 8) || - (PCI_SLOT(dev->bus->self->devfn) == 20)) { + if (dev->bus->number == 0) { + slot = PCI_SLOT(dev->devfn); + } + /* Check for the built-in bridge. */ + else if ((PCI_SLOT(dev->bus->self->devfn) == 8) || + (PCI_SLOT(dev->bus->self->devfn) == 20)) { slot = PCI_SLOT(dev->devfn) + 9; } else @@ -263,14 +266,24 @@ miata_swizzle(struct pci_dev *dev, int *pinp) } static void __init -miata_pci_fixup(void) +miata_init_pci(void) { - layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); - common_pci_fixup(miata_map_irq, miata_swizzle); + common_init_pci(); SMC669_Init(0); /* it might be a GL (fails harmlessly if not) */ es1888_init(); } +static void +miata_kill_arch (int mode, char *reboot_cmd) +{ + /* Who said DEC engineers have no sense of humor? ;-) */ + if (alpha_using_srm) { + *(vuip) PYXIS_RESET = 0x0000dead; + mb(); + } + common_kill_arch(mode, reboot_cmd); +} + /* * The System Vector @@ -284,17 +297,21 @@ struct alpha_machine_vector miata_mv __initmv = { DO_PYXIS_BUS, machine_check: pyxis_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: DEFAULT_IO_BASE, + min_mem_address: DEFAULT_MEM_BASE, nr_irqs: 48, irq_probe_mask: _PROBE_MASK(48), update_irq_hw: miata_update_irq_hw, - ack_irq: generic_ack_irq, + ack_irq: common_ack_irq, device_interrupt: miata_device_interrupt, init_arch: pyxis_init_arch, init_irq: miata_init_irq, - init_pit: generic_init_pit, - pci_fixup: miata_pci_fixup, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: miata_init_pci, + kill_arch: miata_kill_arch, + pci_map_irq: miata_map_irq, + pci_swizzle: miata_swizzle, }; ALIAS_MV(miata) diff --git a/arch/alpha/kernel/sys_mikasa.c b/arch/alpha/kernel/sys_mikasa.c index 9952c311f..0c08d9fc0 100644 --- a/arch/alpha/kernel/sys_mikasa.c +++ b/arch/alpha/kernel/sys_mikasa.c @@ -3,7 +3,7 @@ * * Copyright (C) 1995 David A Rusling * Copyright (C) 1996 Jay A Estabrook - * Copyright (C) 1998 Richard Henderson + * Copyright (C) 1998, 1999 Richard Henderson * * Code supporting the MIKASA (AlphaServer 1000). */ @@ -28,9 +28,9 @@ #include <asm/core_cia.h> #include "proto.h" -#include "irq.h" -#include "bios32.h" -#include "machvec.h" +#include "irq_impl.h" +#include "pci_impl.h" +#include "machvec_impl.h" static void mikasa_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p) @@ -120,7 +120,7 @@ mikasa_init_irq(void) */ static int __init -mikasa_map_irq(struct pci_dev *dev, int slot, int pin) +mikasa_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { static char irq_tab[8][5] __initlocaldata = { /*INT INTA INTB INTC INTD */ @@ -137,105 +137,35 @@ mikasa_map_irq(struct pci_dev *dev, int slot, int pin) return COMMON_TABLE_LOOKUP; } -static void __init -mikasa_pci_fixup(void) -{ - layout_all_busses(EISA_DEFAULT_IO_BASE,APECS_AND_LCA_DEFAULT_MEM_BASE); - common_pci_fixup(mikasa_map_irq, common_swizzle); -} - -static void __init -mikasa_primo_pci_fixup(void) -{ - layout_all_busses(EISA_DEFAULT_IO_BASE, DEFAULT_MEM_BASE); - common_pci_fixup(mikasa_map_irq, common_swizzle); -} +#if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO) static void -mikasa_machine_check(unsigned long vector, unsigned long la_ptr, - struct pt_regs * regs) +mikasa_apecs_machine_check(unsigned long vector, unsigned long la_ptr, + struct pt_regs * regs) { #define MCHK_NO_DEVSEL 0x205L #define MCHK_NO_TABT 0x204L struct el_common *mchk_header; - struct el_apecs_procdata *mchk_procdata; - struct el_apecs_mikasa_sysdata_mcheck *mchk_sysdata; - unsigned long *ptr; - int i; + unsigned int code; mchk_header = (struct el_common *)la_ptr; - mchk_procdata = (struct el_apecs_procdata *) - (la_ptr + mchk_header->proc_offset - - sizeof(mchk_procdata->paltemp)); - - mchk_sysdata = (struct el_apecs_mikasa_sysdata_mcheck *) - (la_ptr + mchk_header->sys_offset); - -#ifdef DEBUG - printk("mikasa_machine_check: vector=0x%lx la_ptr=0x%lx\n", - vector, la_ptr); - printk(" pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", - regs->pc, mchk_header->size, mchk_header->proc_offset, - mchk_header->sys_offset); - printk("mikasa_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n", - apecs_mcheck_expected, mchk_sysdata->epic_dcsr, - mchk_sysdata->epic_pear); - ptr = (unsigned long *)la_ptr; - for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { - printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]); - } -#endif - - /* - * Check if machine check is due to a badaddr() and if so, - * ignore the machine check. - */ - - if (apecs_mcheck_expected - && ((unsigned int)mchk_header->code == MCHK_NO_DEVSEL - || (unsigned int)mchk_header->code == MCHK_NO_TABT)) { - apecs_mcheck_expected = 0; - apecs_mcheck_taken = 1; - mb(); - mb(); /* magic */ - apecs_pci_clr_err(); - wrmces(0x7); - mb(); - draina(); - } - else if (vector == 0x620 || vector == 0x630) { - /* Disable correctable from now on. */ - wrmces(0x1f); - mb(); - draina(); - printk("mikasa_machine_check: HW correctable (0x%lx)\n", - vector); - } - else { - printk(KERN_CRIT "APECS machine check:\n"); - printk(KERN_CRIT " vector=0x%lx la_ptr=0x%lx\n", - vector, la_ptr); - printk(KERN_CRIT - " pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", - regs->pc, mchk_header->size, mchk_header->proc_offset, - mchk_header->sys_offset); - printk(KERN_CRIT " expected %d DCSR 0x%lx PEAR 0x%lx\n", - apecs_mcheck_expected, mchk_sysdata->epic_dcsr, - mchk_sysdata->epic_pear); - - ptr = (unsigned long *)la_ptr; - for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { - printk(KERN_CRIT " +%lx %lx %lx\n", - i*sizeof(long), ptr[i], ptr[i+1]); - } -#if 0 - /* doesn't work with MILO */ - show_regs(regs); -#endif - } + /* Clear the error before any reporting. */ + mb(); + mb(); /* magic */ + draina(); + apecs_pci_clr_err(); + wrmces(0x7); + mb(); + + code = mchk_header->code; + process_mcheck_info(vector, la_ptr, regs, "MIKASA APECS", + (mcheck_expected(0) + && (code == MCHK_NO_DEVSEL + || code == MCHK_NO_TABT))); } +#endif /* @@ -249,20 +179,24 @@ struct alpha_machine_vector mikasa_mv __initmv = { DO_DEFAULT_RTC, DO_APECS_IO, DO_APECS_BUS, - machine_check: mikasa_machine_check, + machine_check: mikasa_apecs_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: DEFAULT_IO_BASE, + min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE, nr_irqs: 32, irq_probe_mask: _PROBE_MASK(32), update_irq_hw: mikasa_update_irq_hw, - ack_irq: generic_ack_irq, + ack_irq: common_ack_irq, device_interrupt: mikasa_device_interrupt, init_arch: apecs_init_arch, init_irq: mikasa_init_irq, - init_pit: generic_init_pit, - pci_fixup: mikasa_pci_fixup, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: common_init_pci, + kill_arch: common_kill_arch, + pci_map_irq: mikasa_map_irq, + pci_swizzle: common_swizzle, }; ALIAS_MV(mikasa) #endif @@ -274,20 +208,24 @@ struct alpha_machine_vector mikasa_primo_mv __initmv = { DO_DEFAULT_RTC, DO_CIA_IO, DO_CIA_BUS, - machine_check: mikasa_machine_check, + machine_check: cia_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: DEFAULT_IO_BASE, + min_mem_address: CIA_DEFAULT_MEM_BASE, nr_irqs: 32, irq_probe_mask: _PROBE_MASK(32), update_irq_hw: mikasa_update_irq_hw, - ack_irq: generic_ack_irq, + ack_irq: common_ack_irq, device_interrupt: mikasa_device_interrupt, init_arch: cia_init_arch, init_irq: mikasa_init_irq, - init_pit: generic_init_pit, - pci_fixup: mikasa_primo_pci_fixup, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: common_init_pci, + kill_arch: common_kill_arch, + pci_map_irq: mikasa_map_irq, + pci_swizzle: common_swizzle, }; ALIAS_MV(mikasa_primo) #endif diff --git a/arch/alpha/kernel/sys_noritake.c b/arch/alpha/kernel/sys_noritake.c index 2ade29654..adce91de2 100644 --- a/arch/alpha/kernel/sys_noritake.c +++ b/arch/alpha/kernel/sys_noritake.c @@ -3,7 +3,7 @@ * * Copyright (C) 1995 David A Rusling * Copyright (C) 1996 Jay A Estabrook - * Copyright (C) 1998 Richard Henderson + * Copyright (C) 1998, 1999 Richard Henderson * * Code supporting the NORITAKE (AlphaServer 1000A), * CORELLE (AlphaServer 800), and ALCOR Primo (AlphaStation 600A). @@ -29,9 +29,9 @@ #include <asm/core_cia.h> #include "proto.h" -#include "irq.h" -#include "bios32.h" -#include "machvec.h" +#include "irq_impl.h" +#include "pci_impl.h" +#include "machvec_impl.h" static void @@ -168,7 +168,7 @@ noritake_init_irq(void) */ static int __init -noritake_map_irq(struct pci_dev *dev, int slot, int pin) +noritake_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { static char irq_tab[15][5] __initlocaldata = { /*INT INTA INTB INTC INTD */ @@ -195,13 +195,16 @@ noritake_map_irq(struct pci_dev *dev, int slot, int pin) return COMMON_TABLE_LOOKUP; } -static int __init -noritake_swizzle(struct pci_dev *dev, int *pinp) +static u8 __init +noritake_swizzle(struct pci_dev *dev, u8 *pinp) { int slot, pin = *pinp; - /* Check first for the built-in bridge */ - if (PCI_SLOT(dev->bus->self->devfn) == 8) { + if (dev->bus->number == 0) { + slot = PCI_SLOT(dev->devfn); + } + /* Check for the built-in bridge */ + else if (PCI_SLOT(dev->bus->self->devfn) == 8) { slot = PCI_SLOT(dev->devfn) + 15; /* WAG! */ } else @@ -224,20 +227,6 @@ noritake_swizzle(struct pci_dev *dev, int *pinp) return slot; } -static void __init -noritake_pci_fixup(void) -{ - layout_all_busses(EISA_DEFAULT_IO_BASE,APECS_AND_LCA_DEFAULT_MEM_BASE); - common_pci_fixup(noritake_map_irq, noritake_swizzle); -} - -static void __init -noritake_primo_pci_fixup(void) -{ - layout_all_busses(EISA_DEFAULT_IO_BASE, DEFAULT_MEM_BASE); - common_pci_fixup(noritake_map_irq, noritake_swizzle); -} - /* * The System Vectors @@ -252,18 +241,22 @@ struct alpha_machine_vector noritake_mv __initmv = { DO_APECS_BUS, machine_check: apecs_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: EISA_DEFAULT_IO_BASE, + min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE, nr_irqs: 48, irq_probe_mask: _PROBE_MASK(48), update_irq_hw: noritake_update_irq_hw, - ack_irq: generic_ack_irq, + ack_irq: common_ack_irq, device_interrupt: noritake_device_interrupt, init_arch: apecs_init_arch, init_irq: noritake_init_irq, - init_pit: generic_init_pit, - pci_fixup: noritake_pci_fixup, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: common_init_pci, + kill_arch: common_kill_arch, + pci_map_irq: noritake_map_irq, + pci_swizzle: noritake_swizzle, }; ALIAS_MV(noritake) #endif @@ -277,18 +270,22 @@ struct alpha_machine_vector noritake_primo_mv __initmv = { DO_CIA_BUS, machine_check: cia_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: EISA_DEFAULT_IO_BASE, + min_mem_address: CIA_DEFAULT_MEM_BASE, nr_irqs: 48, irq_probe_mask: _PROBE_MASK(48), update_irq_hw: noritake_update_irq_hw, - ack_irq: generic_ack_irq, + ack_irq: common_ack_irq, device_interrupt: noritake_device_interrupt, init_arch: cia_init_arch, init_irq: noritake_init_irq, - init_pit: generic_init_pit, - pci_fixup: noritake_primo_pci_fixup, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: common_init_pci, + kill_arch: common_kill_arch, + pci_map_irq: noritake_map_irq, + pci_swizzle: noritake_swizzle, }; ALIAS_MV(noritake_primo) #endif diff --git a/arch/alpha/kernel/sys_rawhide.c b/arch/alpha/kernel/sys_rawhide.c index 19d79c060..1b5e1c3cf 100644 --- a/arch/alpha/kernel/sys_rawhide.c +++ b/arch/alpha/kernel/sys_rawhide.c @@ -3,7 +3,7 @@ * * Copyright (C) 1995 David A Rusling * Copyright (C) 1996 Jay A Estabrook - * Copyright (C) 1998 Richard Henderson + * Copyright (C) 1998, 1999 Richard Henderson * * Code supporting the RAWHIDE. */ @@ -26,9 +26,9 @@ #include <asm/core_mcpcia.h> #include "proto.h" -#include "irq.h" -#include "bios32.h" -#include "machvec.h" +#include "irq_impl.h" +#include "pci_impl.h" +#include "machvec_impl.h" static void @@ -36,19 +36,19 @@ rawhide_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p) { if (irq >= 40) { /* PCI bus 1 with builtin NCR810 SCSI */ - *(vuip)MCPCIA_INT_MASK0(1) = + *(vuip)MCPCIA_INT_MASK0(5) = (~((mask) >> 40) & 0x00ffffffU) | 0x00fe0000U; mb(); /* ... and read it back to make sure it got written. */ - *(vuip)MCPCIA_INT_MASK0(1); + *(vuip)MCPCIA_INT_MASK0(5); } else if (irq >= 16) { /* PCI bus 0 with EISA bridge */ - *(vuip)MCPCIA_INT_MASK0(0) = + *(vuip)MCPCIA_INT_MASK0(4) = (~((mask) >> 16) & 0x00ffffffU) | 0x00ff0000U; mb(); /* ... and read it back to make sure it got written. */ - *(vuip)MCPCIA_INT_MASK0(0); + *(vuip)MCPCIA_INT_MASK0(4); } else if (irq >= 8) outb(mask >> 8, 0xA1); /* ISA PIC2 */ @@ -63,6 +63,10 @@ rawhide_srm_device_interrupt(unsigned long vector, struct pt_regs * regs) ack = irq = (vector - 0x800) >> 4; + /* ??? A 4 bus RAWHIDE has 67 interrupts. Oops. We need + something wider than one word for our own internal + manipulations. */ + /* * The RAWHIDE SRM console reports PCI interrupts with a vector * 0x80 *higher* than one might expect, as PCI IRQ 0 (ie bit 0) @@ -90,17 +94,17 @@ rawhide_init_irq(void) STANDARD_INIT_IRQ_PROLOG; /* HACK ALERT! only PCI busses 0 and 1 are used currently, - and routing is only to CPU #1*/ + (MIDs 4 and 5 respectively) and routing is only to CPU #1*/ - *(vuip)MCPCIA_INT_MASK0(0) = + *(vuip)MCPCIA_INT_MASK0(4) = (~((alpha_irq_mask) >> 16) & 0x00ffffffU) | 0x00ff0000U; mb(); /* ... and read it back to make sure it got written. */ - *(vuip)MCPCIA_INT_MASK0(0); + *(vuip)MCPCIA_INT_MASK0(4); - *(vuip)MCPCIA_INT_MASK0(1) = + *(vuip)MCPCIA_INT_MASK0(5) = (~((alpha_irq_mask) >> 40) & 0x00ffffffU) | 0x00fe0000U; mb(); /* ... and read it back to make sure it got written. */ - *(vuip)MCPCIA_INT_MASK0(1); + *(vuip)MCPCIA_INT_MASK0(5); enable_irq(2); } @@ -139,7 +143,7 @@ rawhide_init_irq(void) */ static int __init -rawhide_map_irq(struct pci_dev *dev, int slot, int pin) +rawhide_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { static char irq_tab[5][5] __initlocaldata = { /*INT INTA INTB INTC INTD */ @@ -150,19 +154,14 @@ rawhide_map_irq(struct pci_dev *dev, int slot, int pin) { 16+12, 16+12, 16+13, 16+14, 16+15} /* IdSel 5 slot 5 */ }; const long min_idsel = 1, max_idsel = 5, irqs_per_slot = 5; + + struct pci_controler *hose = dev->sysdata; int irq = COMMON_TABLE_LOOKUP; if (irq >= 0) - irq += 24 * bus2hose[dev->bus->number]->pci_hose_index; + irq += 24 * hose->index; return irq; } -static void __init -rawhide_pci_fixup(void) -{ - layout_all_busses(DEFAULT_IO_BASE, RAWHIDE_DEFAULT_MEM_BASE); - common_pci_fixup(rawhide_map_irq, common_swizzle); -} - /* * The System Vector @@ -176,17 +175,21 @@ struct alpha_machine_vector rawhide_mv __initmv = { DO_MCPCIA_BUS, machine_check: mcpcia_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: DEFAULT_IO_BASE, + min_mem_address: MCPCIA_DEFAULT_MEM_BASE, nr_irqs: 64, irq_probe_mask: _PROBE_MASK(64), update_irq_hw: rawhide_update_irq_hw, - ack_irq: generic_ack_irq, + ack_irq: common_ack_irq, device_interrupt: rawhide_srm_device_interrupt, init_arch: mcpcia_init_arch, init_irq: rawhide_init_irq, - init_pit: generic_init_pit, - pci_fixup: rawhide_pci_fixup, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: common_init_pci, + kill_arch: common_kill_arch, + pci_map_irq: rawhide_map_irq, + pci_swizzle: common_swizzle, }; ALIAS_MV(rawhide) diff --git a/arch/alpha/kernel/sys_ruffian.c b/arch/alpha/kernel/sys_ruffian.c index 4d52c256b..f303a8255 100644 --- a/arch/alpha/kernel/sys_ruffian.c +++ b/arch/alpha/kernel/sys_ruffian.c @@ -3,7 +3,7 @@ * * Copyright (C) 1995 David A Rusling * Copyright (C) 1996 Jay A Estabrook - * Copyright (C) 1998 Richard Henderson + * Copyright (C) 1998, 1999 Richard Henderson * * Code supporting the RUFFIAN. */ @@ -26,9 +26,9 @@ #include <asm/core_pyxis.h> #include "proto.h" -#include "irq.h" -#include "bios32.h" -#include "machvec.h" +#include "irq_impl.h" +#include "pci_impl.h" +#include "machvec_impl.h" static void ruffian_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p) @@ -164,18 +164,6 @@ ruffian_init_irq(void) } -/* - * For RUFFIAN, we do not want to make any modifications to the PCI - * setup. But we may need to do some kind of init. - */ - -static void __init -ruffian_pci_fixup(void) -{ - /* layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); */ -} - - #ifdef BUILDING_FOR_MILO /* * The DeskStation Ruffian motherboard firmware does not place @@ -215,25 +203,9 @@ ruffian_get_bank_size(unsigned long offset) } #endif /* BUILDING_FOR_MILO */ -static void __init -ruffian_init_arch(unsigned long *mem_start, unsigned long *mem_end) -{ - /* FIXME: What do we do with ruffian_get_bank_size above? */ - - pyxis_enable_errors(); - if (!pyxis_srm_window_setup()) { - printk("ruffian_init_arch: Skipping window register rewrites." - "\n... Trust DeskStation firmware!\n"); - } - pyxis_finish_init_arch(); -} - static void ruffian_init_pit (void) { - /* Ruffian depends on the system timer established in MILO! */ - request_region(0x70, 0x10, "timer"); - outb(0xb6, 0x43); /* pit counter 2: speaker */ outb(0x31, 0x42); outb(0x13, 0x42); @@ -248,7 +220,15 @@ ruffian_kill_arch (int mode, char *reboot_cmd) *(vuip) PYXIS_RESET = 0x0000dead; mb(); #endif - generic_kill_arch(mode, reboot_cmd); + common_kill_arch(mode, reboot_cmd); +} + +static int __init +ruffian_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + /* We don't know anything about the PCI routing, so leave + the IRQ unchanged. */ + return dev->irq; } @@ -260,11 +240,12 @@ struct alpha_machine_vector ruffian_mv __initmv = { vector_name: "Ruffian", DO_EV5_MMU, DO_DEFAULT_RTC, - /* For the moment, do not use BWIO on RUFFIAN. */ - IO(PYXIS,pyxis,pyxis), + DO_PYXIS_IO, DO_PYXIS_BUS, machine_check: pyxis_machine_check, max_dma_address: ALPHA_RUFFIAN_MAX_DMA_ADDRESS, + min_io_address: DEFAULT_IO_BASE, + min_mem_address: DEFAULT_MEM_BASE, nr_irqs: 48, irq_probe_mask: RUFFIAN_PROBE_MASK, @@ -272,10 +253,12 @@ struct alpha_machine_vector ruffian_mv __initmv = { ack_irq: ruffian_ack_irq, device_interrupt: ruffian_device_interrupt, - init_arch: ruffian_init_arch, + init_arch: pyxis_init_arch, init_irq: ruffian_init_irq, init_pit: ruffian_init_pit, - pci_fixup: ruffian_pci_fixup, + init_pci: common_init_pci, kill_arch: ruffian_kill_arch, + pci_map_irq: ruffian_map_irq, + pci_swizzle: common_swizzle, }; ALIAS_MV(ruffian) diff --git a/arch/alpha/kernel/sys_rx164.c b/arch/alpha/kernel/sys_rx164.c index 5d2cf5288..c6a4ac5b3 100644 --- a/arch/alpha/kernel/sys_rx164.c +++ b/arch/alpha/kernel/sys_rx164.c @@ -3,7 +3,7 @@ * * Copyright (C) 1995 David A Rusling * Copyright (C) 1996 Jay A Estabrook - * Copyright (C) 1998 Richard Henderson + * Copyright (C) 1998, 1999 Richard Henderson * * Code supporting the RX164 (PCA56+POLARIS). */ @@ -26,9 +26,9 @@ #include <asm/core_polaris.h> #include "proto.h" -#include "irq.h" -#include "bios32.h" -#include "machvec.h" +#include "irq_impl.h" +#include "pci_impl.h" +#include "machvec_impl.h" static void @@ -45,10 +45,10 @@ rx164_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p) outb(mask, 0x21); /* ISA PIC1 */ } +#if 0 static void rx164_srm_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p) { -#if 0 if (irq >= 16) { if (unmask_p) cserve_ena(irq - 16); @@ -59,8 +59,8 @@ rx164_srm_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p) outb(mask >> 8, 0xA1); /* ISA PIC2 */ else outb(mask, 0x21); /* ISA PIC1 */ -#endif } +#endif static void rx164_isa_device_interrupt(unsigned long vector, struct pt_regs * regs) @@ -107,7 +107,8 @@ rx164_device_interrupt(unsigned long vector, struct pt_regs *regs) printk("PLD 0x%lx\n", pld); #endif - if (pld & 0xffffffff00000000UL) pld &= 0x00000000ffffffffUL; + if (pld & 0xffffffff00000000UL) + pld &= 0x00000000ffffffffUL; /* * Now for every possible bit set, work through them and call @@ -137,6 +138,8 @@ rx164_init_irq(void) enable_irq(16 + 20); /* enable ISA interrupts */ enable_irq(2); /* enable cascade */ } + + /* The RX164 changed its interrupt routing between pass1 and pass2... * * PASS1: @@ -170,7 +173,7 @@ rx164_init_irq(void) */ static int __init -rx164_map_irq(struct pci_dev *dev, int slot, int pin) +rx164_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { #if 0 char irq_tab_pass1[6][5] = { @@ -182,7 +185,7 @@ rx164_map_irq(struct pci_dev *dev, int slot, int pin) { 16+2, 16+2, 16+7, 16+12, 16+17}, /* IdSel 9, slot 3 */ { 16+1, 16+1, 16+6, 16+11, 16+16}, /* IdSel 10, slot 4 */ }; -#endif +#else char irq_tab[6][5] = { /*INT INTA INTB INTC INTD */ { 16+0, 16+0, 16+6, 16+11, 16+16}, /* IdSel 5, slot 0 */ @@ -192,20 +195,14 @@ rx164_map_irq(struct pci_dev *dev, int slot, int pin) { 16+3, 16+3, 16+9, 16+14, 16+19}, /* IdSel 9, slot 3 */ { 16+4, 16+4, 16+10, 16+15, 16+5}, /* IdSel 10, PCI-PCI */ }; +#endif const long min_idsel = 5, max_idsel = 10, irqs_per_slot = 5; + /* JRP - Need to figure out how to distinguish pass1 from pass2, - * and use the correct table... - */ + and use the correct table. */ return COMMON_TABLE_LOOKUP; } -void __init -rx164_pci_fixup(void) -{ - layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); - common_pci_fixup(rx164_map_irq, common_swizzle); -} - /* * The System Vector @@ -219,17 +216,21 @@ struct alpha_machine_vector rx164_mv __initmv = { DO_POLARIS_BUS, machine_check: polaris_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: DEFAULT_IO_BASE, + min_mem_address: DEFAULT_MEM_BASE, nr_irqs: 40, irq_probe_mask: _PROBE_MASK(40), update_irq_hw: rx164_update_irq_hw, - ack_irq: generic_ack_irq, + ack_irq: common_ack_irq, device_interrupt: rx164_device_interrupt, init_arch: polaris_init_arch, init_irq: rx164_init_irq, - init_pit: generic_init_pit, - pci_fixup: rx164_pci_fixup, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: common_init_pci, + kill_arch: common_kill_arch, + pci_map_irq: rx164_map_irq, + pci_swizzle: common_swizzle, }; ALIAS_MV(rx164) diff --git a/arch/alpha/kernel/sys_sable.c b/arch/alpha/kernel/sys_sable.c index b045f37f6..86b1d8371 100644 --- a/arch/alpha/kernel/sys_sable.c +++ b/arch/alpha/kernel/sys_sable.c @@ -3,7 +3,7 @@ * * Copyright (C) 1995 David A Rusling * Copyright (C) 1996 Jay A Estabrook - * Copyright (C) 1998 Richard Henderson + * Copyright (C) 1998, 1999 Richard Henderson * * Code supporting the Sable and Sable-Gamma systems. */ @@ -26,9 +26,9 @@ #include <asm/core_t2.h> #include "proto.h" -#include "irq.h" -#include "bios32.h" -#include "machvec.h" +#include "irq_impl.h" +#include "pci_impl.h" +#include "machvec_impl.h" /* @@ -198,7 +198,7 @@ sable_init_irq(void) */ static int __init -sable_map_irq(struct pci_dev *dev, int slot, int pin) +sable_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { static char irq_tab[9][5] __initlocaldata = { /*INT INTA INTB INTC INTD */ @@ -216,13 +216,6 @@ sable_map_irq(struct pci_dev *dev, int slot, int pin) return COMMON_TABLE_LOOKUP; } -void __init -sable_pci_fixup(void) -{ - layout_all_busses(EISA_DEFAULT_IO_BASE, DEFAULT_MEM_BASE); - common_pci_fixup(sable_map_irq, common_swizzle); -} - /* * The System Vectors @@ -242,6 +235,8 @@ struct alpha_machine_vector sable_mv __initmv = { DO_T2_BUS, machine_check: t2_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: EISA_DEFAULT_IO_BASE, + min_mem_address: DEFAULT_MEM_BASE, nr_irqs: 40, irq_probe_mask: _PROBE_MASK(40), @@ -251,9 +246,11 @@ struct alpha_machine_vector sable_mv __initmv = { init_arch: t2_init_arch, init_irq: sable_init_irq, - init_pit: generic_init_pit, - pci_fixup: sable_pci_fixup, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: common_init_pci, + kill_arch: common_kill_arch, + pci_map_irq: sable_map_irq, + pci_swizzle: common_swizzle, sys: { t2: { gamma_bias: 0 @@ -273,6 +270,8 @@ struct alpha_machine_vector sable_gamma_mv __initmv = { DO_T2_BUS, machine_check: t2_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: EISA_DEFAULT_IO_BASE, + min_mem_address: DEFAULT_MEM_BASE, nr_irqs: 40, irq_probe_mask: _PROBE_MASK(40), @@ -282,9 +281,11 @@ struct alpha_machine_vector sable_gamma_mv __initmv = { init_arch: t2_init_arch, init_irq: sable_init_irq, - init_pit: generic_init_pit, - pci_fixup: sable_pci_fixup, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: common_init_pci, + kill_arch: common_kill_arch, + pci_map_irq: sable_map_irq, + pci_swizzle: common_swizzle, sys: { t2: { gamma_bias: _GAMMA_BIAS diff --git a/arch/alpha/kernel/sys_sio.c b/arch/alpha/kernel/sys_sio.c index 70d8720e9..8e7fdb85f 100644 --- a/arch/alpha/kernel/sys_sio.c +++ b/arch/alpha/kernel/sys_sio.c @@ -3,7 +3,7 @@ * * Copyright (C) 1995 David A Rusling * Copyright (C) 1996 Jay A Estabrook - * Copyright (C) 1998 Richard Henderson + * Copyright (C) 1998, 1999 Richard Henderson * * Code for all boards that route the PCI interrupts through the SIO * PCI/ISA bridge. This includes Noname (AXPpci33), Multia (UDB), @@ -28,11 +28,12 @@ #include <asm/pgtable.h> #include <asm/core_apecs.h> #include <asm/core_lca.h> +#include <asm/pci.h> #include "proto.h" -#include "irq.h" -#include "bios32.h" -#include "machvec.h" +#include "irq_impl.h" +#include "pci_impl.h" +#include "machvec_impl.h" static void sio_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p) @@ -57,6 +58,8 @@ sio_init_irq(void) static inline void __init xl_init_arch(unsigned long *mem_start, unsigned long *mem_end) { + struct pci_controler *hose; + /* * Set up the PCI->physical memory translation windows. For * the XL we *must* use both windows, in order to maximize the @@ -86,6 +89,16 @@ xl_init_arch(unsigned long *mem_start, unsigned long *mem_end) */ *(vuip)APECS_IOC_HAXR2 = 0; mb(); + + /* + * Create our single hose. + */ + + hose = alloc_pci_controler(mem_start); + hose->io_space = &ioport_resource; + hose->mem_space = &iomem_resource; + hose->config_space = LCA_CONF; + hose->index = 0; } static inline void __init @@ -114,26 +127,12 @@ alphabook1_init_arch(unsigned long *mem_start, unsigned long *mem_end) * This is NOT how we should do it. PIRQ0-X should have * their own IRQ's, the way intel uses the IO-APIC irq's. */ -static unsigned long sio_route_tab __initdata = 0; static void __init -sio_pci_fixup(int (*map_irq)(struct pci_dev *dev, int sel, int pin), - unsigned long new_route_tab) +sio_pci_route(void) { - unsigned int route_tab; - - /* Examine or update the PCI routing table. */ - pcibios_read_config_dword(0, PCI_DEVFN(7, 0), 0x60, &route_tab); - - sio_route_tab = route_tab; - if (PCI_MODIFY) { - sio_route_tab = new_route_tab; - pcibios_write_config_dword(0, PCI_DEVFN(7, 0), 0x60, - new_route_tab); - } - - /* Update all the IRQs. */ - common_pci_fixup(map_irq, common_swizzle); + pcibios_write_config_dword(0, PCI_DEVFN(7, 0), 0x60, + alpha_mv.sys.sio.route_tab); } static unsigned int __init @@ -180,7 +179,7 @@ sio_fixup_irq_levels(unsigned int level_bits) } static inline int __init -noname_map_irq(struct pci_dev *dev, int slot, int pin) +noname_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { /* * The Noname board has 5 PCI slots with each of the 4 @@ -214,49 +213,12 @@ noname_map_irq(struct pci_dev *dev, int slot, int pin) }; const long min_idsel = 6, max_idsel = 14, irqs_per_slot = 5; int irq = COMMON_TABLE_LOOKUP, tmp; - tmp = __kernel_extbl(sio_route_tab, irq); + tmp = __kernel_extbl(alpha_mv.sys.sio.route_tab, irq); return irq >= 0 ? tmp : -1; } -static inline void __init -noname_pci_fixup(void) -{ - /* - * For UDB, the only available PCI slot must not map to IRQ 9, - * since that's the builtin MSS sound chip. That PCI slot - * will map to PIRQ1 (for INTA at least), so we give it IRQ 15 - * instead. - * - * Unfortunately we have to do this for NONAME as well, since - * they are co-indicated when the platform type "Noname" is - * selected... :-( - */ - layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE); - sio_pci_fixup(noname_map_irq, 0x0b0a0f0d); - sio_fixup_irq_levels(sio_collect_irq_levels()); - enable_ide(0x26e); -} - -static inline void __init -avanti_pci_fixup(void) -{ - layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE); - sio_pci_fixup(noname_map_irq, 0x0b0a0e0f); - sio_fixup_irq_levels(sio_collect_irq_levels()); - enable_ide(0x26e); -} - -static inline void __init -xl_pci_fixup(void) -{ - layout_all_busses(DEFAULT_IO_BASE, XL_DEFAULT_MEM_BASE); - sio_pci_fixup(noname_map_irq, 0x0b0a090f); - sio_fixup_irq_levels(sio_collect_irq_levels()); - enable_ide(0x26e); -} - static inline int __init -p2k_map_irq(struct pci_dev *dev, int slot, int pin) +p2k_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { static char irq_tab[][5] __initlocaldata = { /*INT A B C D */ @@ -270,29 +232,27 @@ p2k_map_irq(struct pci_dev *dev, int slot, int pin) }; const long min_idsel = 6, max_idsel = 12, irqs_per_slot = 5; int irq = COMMON_TABLE_LOOKUP, tmp; - tmp = __kernel_extbl(sio_route_tab, irq); + tmp = __kernel_extbl(alpha_mv.sys.sio.route_tab, irq); return irq >= 0 ? tmp : -1; } static inline void __init -p2k_pci_fixup(void) +noname_init_pci(void) { - layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE); - sio_pci_fixup(p2k_map_irq, 0x0b0a090f); + sio_pci_route(); + common_init_pci(); sio_fixup_irq_levels(sio_collect_irq_levels()); - enable_ide(0x26e); + ns87312_enable_ide(0x26e); } static inline void __init -alphabook1_pci_fixup(void) +alphabook1_init_pci(void) { struct pci_dev *dev; unsigned char orig, config; - layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE); - - /* For the AlphaBook1, NCR810 SCSI is 14, PCMCIA controller is 15. */ - sio_pci_fixup(noname_map_irq, 0x0e0f0a0a); + sio_pci_route(); + common_init_pci(); /* * On the AlphaBook1, the PCMCIA chip (Cirrus 6729) @@ -304,20 +264,17 @@ alphabook1_pci_fixup(void) * moment (2.0.29), ncr53c8xx.c does NOT do this, but * 53c7,8xx.c DOES. */ - for (dev = pci_devices; dev; dev = dev->next) { - if (dev->vendor == PCI_VENDOR_ID_NCR && - (dev->device == PCI_DEVICE_ID_NCR_53C810 || - dev->device == PCI_DEVICE_ID_NCR_53C815 || - dev->device == PCI_DEVICE_ID_NCR_53C820 || - dev->device == PCI_DEVICE_ID_NCR_53C825)) { - unsigned int io_port; + + dev = NULL; + while ((dev = pci_find_device(PCI_VENDOR_ID_NCR, PCI_ANY_ID, dev))) { + if (dev->device == PCI_DEVICE_ID_NCR_53C810 + || dev->device == PCI_DEVICE_ID_NCR_53C815 + || dev->device == PCI_DEVICE_ID_NCR_53C820 + || dev->device == PCI_DEVICE_ID_NCR_53C825) { + unsigned long io_port; unsigned char ctest4; - pcibios_read_config_dword(dev->bus->number, - dev->devfn, - PCI_BASE_ADDRESS_0, - &io_port); - io_port &= PCI_BASE_ADDRESS_IO_MASK; + io_port = dev->resource[0].start; ctest4 = inb(io_port+0x21); if (!(ctest4 & 0x80)) { printk("AlphaBook1 NCR init: setting" @@ -356,18 +313,27 @@ struct alpha_machine_vector alphabook1_mv __initmv = { DO_LCA_BUS, machine_check: lca_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: DEFAULT_IO_BASE, + min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE, nr_irqs: 16, irq_probe_mask: _PROBE_MASK(16), update_irq_hw: sio_update_irq_hw, - ack_irq: generic_ack_irq, + ack_irq: common_ack_irq, device_interrupt: isa_device_interrupt, init_arch: alphabook1_init_arch, init_irq: sio_init_irq, - init_pit: generic_init_pit, - pci_fixup: alphabook1_pci_fixup, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: alphabook1_init_pci, + kill_arch: common_kill_arch, + pci_map_irq: noname_map_irq, + pci_swizzle: common_swizzle, + + sys: { sio: { + /* NCR810 SCSI is 14, PCMCIA controller is 15. */ + route_tab: 0x0e0f0a0a, + }} }; ALIAS_MV(alphabook1) #endif @@ -381,18 +347,26 @@ struct alpha_machine_vector avanti_mv __initmv = { DO_APECS_BUS, machine_check: apecs_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: DEFAULT_IO_BASE, + min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE, nr_irqs: 16, irq_probe_mask: _PROBE_MASK(16), update_irq_hw: sio_update_irq_hw, - ack_irq: generic_ack_irq, + ack_irq: common_ack_irq, device_interrupt: isa_device_interrupt, init_arch: apecs_init_arch, init_irq: sio_init_irq, - init_pit: generic_init_pit, - pci_fixup: avanti_pci_fixup, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: noname_init_pci, + kill_arch: common_kill_arch, + pci_map_irq: noname_map_irq, + pci_swizzle: common_swizzle, + + sys: { sio: { + route_tab: 0x0b0a0e0f, + }} }; ALIAS_MV(avanti) #endif @@ -406,18 +380,35 @@ struct alpha_machine_vector noname_mv __initmv = { DO_LCA_BUS, machine_check: lca_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: DEFAULT_IO_BASE, + min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE, nr_irqs: 16, irq_probe_mask: _PROBE_MASK(16), update_irq_hw: sio_update_irq_hw, - ack_irq: generic_ack_irq, + ack_irq: common_ack_irq, device_interrupt: srm_device_interrupt, init_arch: lca_init_arch, init_irq: sio_init_irq, - init_pit: generic_init_pit, - pci_fixup: noname_pci_fixup, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: noname_init_pci, + kill_arch: common_kill_arch, + pci_map_irq: noname_map_irq, + pci_swizzle: common_swizzle, + + sys: { sio: { + /* For UDB, the only available PCI slot must not map to IRQ 9, + since that's the builtin MSS sound chip. That PCI slot + will map to PIRQ1 (for INTA at least), so we give it IRQ 15 + instead. + + Unfortunately we have to do this for NONAME as well, since + they are co-indicated when the platform type "Noname" is + selected... :-( */ + + route_tab: 0x0b0a0f0d, + }} }; ALIAS_MV(noname) #endif @@ -431,18 +422,26 @@ struct alpha_machine_vector p2k_mv __initmv = { DO_LCA_BUS, machine_check: lca_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: DEFAULT_IO_BASE, + min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE, nr_irqs: 16, irq_probe_mask: P2K_PROBE_MASK, update_irq_hw: sio_update_irq_hw, - ack_irq: generic_ack_irq, + ack_irq: common_ack_irq, device_interrupt: srm_device_interrupt, init_arch: lca_init_arch, init_irq: sio_init_irq, - init_pit: generic_init_pit, - pci_fixup: p2k_pci_fixup, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: noname_init_pci, + kill_arch: common_kill_arch, + pci_map_irq: p2k_map_irq, + pci_swizzle: common_swizzle, + + sys: { sio: { + route_tab: 0x0b0a090f, + }} }; ALIAS_MV(p2k) #endif @@ -456,18 +455,26 @@ struct alpha_machine_vector xl_mv __initmv = { BUS(apecs_xl), machine_check: apecs_machine_check, max_dma_address: ALPHA_XL_MAX_DMA_ADDRESS, + min_io_address: DEFAULT_IO_BASE, + min_mem_address: XL_DEFAULT_MEM_BASE, nr_irqs: 16, irq_probe_mask: _PROBE_MASK(16), update_irq_hw: sio_update_irq_hw, - ack_irq: generic_ack_irq, + ack_irq: common_ack_irq, device_interrupt: isa_device_interrupt, init_arch: xl_init_arch, init_irq: sio_init_irq, - init_pit: generic_init_pit, - pci_fixup: xl_pci_fixup, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: noname_init_pci, + kill_arch: common_kill_arch, + pci_map_irq: noname_map_irq, + pci_swizzle: common_swizzle, + + sys: { sio: { + route_tab: 0x0b0a090f, + }} }; ALIAS_MV(xl) #endif diff --git a/arch/alpha/kernel/sys_sx164.c b/arch/alpha/kernel/sys_sx164.c index a35fdd219..a8c7698fb 100644 --- a/arch/alpha/kernel/sys_sx164.c +++ b/arch/alpha/kernel/sys_sx164.c @@ -3,7 +3,7 @@ * * Copyright (C) 1995 David A Rusling * Copyright (C) 1996 Jay A Estabrook - * Copyright (C) 1998 Richard Henderson + * Copyright (C) 1998, 1999 Richard Henderson * * Code supporting the SX164 (PCA56+PYXIS). */ @@ -26,9 +26,9 @@ #include <asm/core_pyxis.h> #include "proto.h" -#include "irq.h" -#include "bios32.h" -#include "machvec.h" +#include "irq_impl.h" +#include "pci_impl.h" +#include "machvec_impl.h" static void @@ -164,7 +164,7 @@ sx164_init_irq(void) */ static int __init -sx164_map_irq(struct pci_dev *dev, int slot, int pin) +sx164_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { static char irq_tab[5][5] __initlocaldata = { /*INT INTA INTB INTC INTD */ @@ -179,10 +179,9 @@ sx164_map_irq(struct pci_dev *dev, int slot, int pin) } void __init -sx164_pci_fixup(void) +sx164_init_pci(void) { - layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); - common_pci_fixup(sx164_map_irq, common_swizzle); + common_init_pci(); SMC669_Init(0); } @@ -199,17 +198,21 @@ struct alpha_machine_vector sx164_mv __initmv = { DO_PYXIS_BUS, machine_check: pyxis_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: DEFAULT_IO_BASE, + min_mem_address: DEFAULT_MEM_BASE, nr_irqs: 40, irq_probe_mask: _PROBE_MASK(40), update_irq_hw: sx164_update_irq_hw, - ack_irq: generic_ack_irq, + ack_irq: common_ack_irq, device_interrupt: sx164_device_interrupt, init_arch: pyxis_init_arch, init_irq: sx164_init_irq, - init_pit: generic_init_pit, - pci_fixup: sx164_pci_fixup, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: sx164_init_pci, + kill_arch: common_kill_arch, + pci_map_irq: sx164_map_irq, + pci_swizzle: common_swizzle, }; ALIAS_MV(sx164) diff --git a/arch/alpha/kernel/sys_takara.c b/arch/alpha/kernel/sys_takara.c index c554a9fa1..c592ee65e 100644 --- a/arch/alpha/kernel/sys_takara.c +++ b/arch/alpha/kernel/sys_takara.c @@ -25,9 +25,9 @@ #include <asm/core_cia.h> #include "proto.h" -#include "irq.h" -#include "bios32.h" -#include "machvec.h" +#include "irq_impl.h" +#include "pci_impl.h" +#include "machvec_impl.h" static void @@ -127,7 +127,7 @@ takara_init_irq(void) */ static int __init -takara_map_irq(struct pci_dev *dev, int slot, int pin) +takara_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { static char irq_tab[15][5] __initlocaldata = { { 16+3, 16+3, 16+3, 16+3, 16+3}, /* slot 6 == device 3 */ @@ -150,16 +150,18 @@ takara_map_irq(struct pci_dev *dev, int slot, int pin) return COMMON_TABLE_LOOKUP; } -static int __init -takara_swizzle(struct pci_dev *dev, int *pinp) +static u8 __init +takara_swizzle(struct pci_dev *dev, u8 *pinp) { int slot = PCI_SLOT(dev->devfn); int pin = *pinp; unsigned int ctlreg = inl(0x500); unsigned int busslot = PCI_SLOT(dev->bus->self->devfn); - /* Check first for built-in bridges. */ - if (busslot > 16 && ((1<<(36-busslot)) & ctlreg)) { + /* Check for built-in bridges. */ + if (dev->bus->number != 0 + && busslot > 16 + && ((1<<(36-busslot)) & ctlreg)) { if (pin == 1) pin += (20 - busslot); else { @@ -174,11 +176,10 @@ takara_swizzle(struct pci_dev *dev, int *pinp) } static void __init -takara_pci_fixup(void) +takara_init_pci(void) { - layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); - common_pci_fixup(takara_map_irq, takara_swizzle); - /* enable_ide(0x26e); */ + common_init_pci(); + /* ns87312_enable_ide(0x26e); */ } @@ -194,17 +195,21 @@ struct alpha_machine_vector takara_mv __initmv = { DO_CIA_BUS, machine_check: cia_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, + min_io_address: DEFAULT_IO_BASE, + min_mem_address: CIA_DEFAULT_MEM_BASE, nr_irqs: 20, irq_probe_mask: _PROBE_MASK(20), update_irq_hw: takara_update_irq_hw, - ack_irq: generic_ack_irq, + ack_irq: common_ack_irq, device_interrupt: takara_device_interrupt, init_arch: cia_init_arch, init_irq: takara_init_irq, - init_pit: generic_init_pit, - pci_fixup: takara_pci_fixup, - kill_arch: generic_kill_arch, + init_pit: common_init_pit, + init_pci: takara_init_pci, + kill_arch: common_kill_arch, + pci_map_irq: takara_map_irq, + pci_swizzle: takara_swizzle, }; ALIAS_MV(takara) diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c index e7f32dc9a..a86c79cc1 100644 --- a/arch/alpha/kernel/time.c +++ b/arch/alpha/kernel/time.c @@ -40,7 +40,7 @@ #include <linux/timex.h> #include "proto.h" -#include "irq.h" +#include "irq_impl.h" extern rwlock_t xtime_lock; extern volatile unsigned long lost_ticks; /* kernel/sched.c */ @@ -94,6 +94,10 @@ void timer_interrupt(int irq, void *dev, struct pt_regs * regs) smp_percpu_timer_interrupt(regs); if (smp_processor_id() != smp_boot_cpuid) return; +#else + /* Not SMP, do kernel PC profiling here. */ + if (!user_mode(regs)) + alpha_do_profile(regs->pc); #endif write_lock(&xtime_lock); @@ -180,8 +184,6 @@ rtc_init_pit (void) CMOS_WRITE(control, RTC_CONTROL); (void) CMOS_READ(RTC_INTR_FLAGS); - request_region(0x40, 0x20, "timer"); /* reserve pit */ - /* Setup interval timer. */ outb(0x34, 0x43); /* binary, mode 2, LSB/MSB, ch 0 */ outb(LATCH & 0xff, 0x40); /* LSB */ @@ -194,7 +196,7 @@ rtc_init_pit (void) #endif void -generic_init_pit (void) +common_init_pit (void) { unsigned char x; @@ -215,8 +217,6 @@ generic_init_pit (void) } (void) CMOS_READ(RTC_INTR_FLAGS); - request_region(RTC_PORT(0), 0x10, "timer"); /* reserve rtc */ - outb(0x36, 0x43); /* pit counter 0: system timer */ outb(0x00, 0x40); outb(0x00, 0x40); diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c index 1b490b9c1..59f021a77 100644 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c @@ -22,7 +22,7 @@ #include "proto.h" -static void +void dik_show_regs(struct pt_regs *regs, unsigned long *r9_15) { printk("pc = [<%016lx>] ra = [<%016lx>] ps = %04lx\n", @@ -103,12 +103,12 @@ die_if_kernel(char * str, struct pt_regs *regs, long err, unsigned long *r9_15) dik_show_code((unsigned int *)regs->pc); dik_show_trace((unsigned long *)(regs+1)); - if (current->tss.flags & (1UL << 63)) { + if (current->thread.flags & (1UL << 63)) { printk("die_if_kernel recursion detected.\n"); sti(); while (1); } - current->tss.flags |= (1UL << 63); + current->thread.flags |= (1UL << 63); do_exit(SIGSEGV); } @@ -154,7 +154,9 @@ do_entIF(unsigned long type, unsigned long a1, unsigned long a2, unsigned long a3, unsigned long a4, unsigned long a5, struct pt_regs regs) { - die_if_kernel("Instruction fault", ®s, type, 0); + die_if_kernel((type == 1 ? "Kernel Bug" : "Instruction fault"), + ®s, type, 0); + switch (type) { case 0: /* breakpoint */ if (ptrace_cancel_bpt(current)) { @@ -494,12 +496,12 @@ got_exception: dik_show_code((unsigned int *)pc); dik_show_trace((unsigned long *)(®s+1)); - if (current->tss.flags & (1UL << 63)) { + if (current->thread.flags & (1UL << 63)) { printk("die_if_kernel recursion detected.\n"); sti(); while (1); } - current->tss.flags |= (1UL << 63); + current->thread.flags |= (1UL << 63); do_exit(SIGSEGV); } @@ -601,7 +603,7 @@ do_entUnaUser(void * va, unsigned long opcode, /* Check the UAC bits to decide what the user wants us to do with the unaliged access. */ - uac_bits = (current->tss.flags >> UAC_SHIFT) & UAC_BITMASK; + uac_bits = (current->thread.flags >> UAC_SHIFT) & UAC_BITMASK; if (!(uac_bits & UAC_NOPRINT)) { if (cnt >= 5 && jiffies - last_time > 5*HZ) { cnt = 0; |