code:
// SPDX-License-Identifier: GPL-2.0
/*
 *	linux/arch/alpha/kernel/sys_alcor.c
 *
 *	Copyright (C) 1995 David A Rusling
 *	Copyright (C) 1996 Jay A Estabrook
 *	Copyright (C) 1998, 1999 Richard Henderson
 *
 * Code supporting the ALCOR and XLT (XL-300/366/433).
 */

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/reboot.h>
#include <linux/bitops.h>

#include <asm/ptrace.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <asm/mmu_context.h>
#include <asm/irq.h>
#include <asm/core_cia.h>
#include <asm/tlbflush.h>

#include "proto.h"
#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"

/* Note mask bit is true for ENABLED irqs.  */
static unsigned long cached_irq_mask;

static inline void
alcor_update_irq_hw(unsigned long mask)
{
	*(vuip)GRU_INT_MASK = mask;
	mb();
}

static inline void
alcor_enable_irq(struct irq_data *d)
{
	alcor_update_irq_hw(cached_irq_mask |= 1UL << (d->irq - 16));
}

static void
alcor_disable_irq(struct irq_data *d)
{
	alcor_update_irq_hw(cached_irq_mask &= ~(1UL << (d->irq - 16)));
}

static void
alcor_mask_and_ack_irq(struct irq_data *d)
{
	alcor_disable_irq(d);

	/* On ALCOR/XLT, need to dismiss interrupt via GRU. */
	*(vuip)GRU_INT_CLEAR = 1 << (d->irq - 16); mb();
	*(vuip)GRU_INT_CLEAR = 0; mb();
}

static void
alcor_isa_mask_and_ack_irq(struct irq_data *d)
{
	i8259a_mask_and_ack_irq(d);

	/* On ALCOR/XLT, need to dismiss interrupt via GRU. */
	*(vuip)GRU_INT_CLEAR = 0x80000000; mb();
	*(vuip)GRU_INT_CLEAR = 0; mb();
}

static struct irq_chip alcor_irq_type = {
	.name		= "ALCOR",
	.irq_unmask	= alcor_enable_irq,
	.irq_mask	= alcor_disable_irq,
	.irq_mask_ack	= alcor_mask_and_ack_irq,
};

static void
alcor_device_interrupt(unsigned long vector)
{
	unsigned long pld;
	unsigned int i;

	/* Read the interrupt summary register of the GRU */
	pld = (*(vuip)GRU_INT_REQ) & GRU_INT_REQ_BITS;

	/*
	 * Now for every possible bit set, work through them and call
	 * the appropriate interrupt handler.
	 */
	while (pld) {
		i = ffz(~pld);
		pld &= pld - 1; /* clear least bit set */
		if (i == 31) {
			isa_device_interrupt(vector);
		} else {
			handle_irq(16 + i);
		}
	}
}

static void __init
alcor_init_irq(void)
{
	long i;

	if (alpha_using_srm)
		alpha_mv.device_interrupt = srm_device_interrupt;

	*(vuip)GRU_INT_MASK  = 0; mb();			/* all disabled */
	*(vuip)GRU_INT_EDGE  = 0; mb();			/* all are level */
	*(vuip)GRU_INT_HILO  = 0x80000000U; mb();	/* ISA only HI */
	*(vuip)GRU_INT_CLEAR = 0; mb();			/* all clear */

	for (i = 16; i < 48; ++i) {
		/* On Alcor, at least, lines 20..30 are not connected
		   and can generate spurious interrupts if we turn them
		   on while IRQ probing.  */
		if (i >= 16+20 && i <= 16+30)
			continue;
		irq_set_chip_and_handler(i, &alcor_irq_type, handle_level_irq);
		irq_set_status_flags(i, IRQ_LEVEL);
	}
	i8259a_irq_type.irq_ack = alcor_isa_mask_and_ack_irq;

	init_i8259a_irqs();
	common_init_isa_dma();

	if (request_irq(16 + 31, no_action, 0, "isa-cascade", NULL))
		pr_err("Failed to register isa-cascade interrupt\n");
}

/*
 * PCI Fixup configuration.
 *
 * Summary @ GRU_INT_REQ:
 * Bit      Meaning
 * 0        Interrupt Line A from slot 2
 * 1        Interrupt Line B from slot 2
 * 2        Interrupt Line C from slot 2
 * 3        Interrupt Line D from slot 2
 * 4        Interrupt Line A from slot 1
 * 5        Interrupt line B from slot 1
 * 6        Interrupt Line C from slot 1
 * 7        Interrupt Line D from slot 1
 * 8        Interrupt Line A from slot 0
 * 9        Interrupt Line B from slot 0
 *10        Interrupt Line C from slot 0
 *11        Interrupt Line D from slot 0
 *12        Interrupt Line A from slot 4
 *13        Interrupt Line B from slot 4
 *14        Interrupt Line C from slot 4
 *15        Interrupt Line D from slot 4
 *16        Interrupt Line D from slot 3
 *17        Interrupt Line D from slot 3
 *18        Interrupt Line D from slot 3
 *19        Interrupt Line D from slot 3
 *20-30     Reserved
 *31        EISA interrupt
 *
 * The device to slot mapping looks like:
 *
 * Slot     Device
 *  6       built-in TULIP (XLT only)
 *  7       PCI on board slot 0
 *  8       PCI on board slot 3
 *  9       PCI on board slot 4
 * 10       PCEB (PCI-EISA bridge)
 * 11       PCI on board slot 2
 * 12       PCI on board slot 1
 *
 *
 * This two layered interrupt approach means that we allocate IRQ 16 and
 * above for PCI interrupts.  The IRQ relates to which bit the interrupt
 * comes in on.  This makes interrupt processing much easier.
 */

static int
alcor_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
	static char irq_tab[7][5] = {
		/*INT    INTA   INTB   INTC   INTD */
		/* note: IDSEL 17 is XLT only */
		{16+13, 16+13, 16+13, 16+13, 16+13},	/* IdSel 17,  TULIP  */
		{ 16+8,  16+8,  16+9, 16+10, 16+11},	/* IdSel 18,  slot 0 */
		{16+16, 16+16, 16+17, 16+18, 16+19},	/* IdSel 19,  slot 3 */
		{16+12, 16+12, 16+13, 16+14, 16+15},	/* IdSel 20,  slot 4 */
		{   -1,    -1,    -1,    -1,    -1},	/* IdSel 21,  PCEB   */
		{ 16+0,  16+0,  16+1,  16+2,  16+3},	/* IdSel 22,  slot 2 */
		{ 16+4,  16+4,  16+5,  16+6,  16+7},	/* IdSel 23,  slot 1 */
	};
	const long min_idsel = 6, max_idsel = 12, irqs_per_slot = 5;
	return COMMON_TABLE_LOOKUP;
}

static void
alcor_kill_arch(int mode)
{
	cia_kill_arch(mode);

#ifndef ALPHA_RESTORE_SRM_SETUP
	switch(mode) {
	case LINUX_REBOOT_CMD_RESTART:
		/* Who said DEC engineer's have no sense of humor? ;-)  */
		if (alpha_using_srm) {
			*(vuip) GRU_RESET = 0x0000dead;
			mb();
		}
		break;
	case LINUX_REBOOT_CMD_HALT:
		break;
	case LINUX_REBOOT_CMD_POWER_OFF:
		break;
	}

	halt();
#endif
}

static void __init
alcor_init_pci(void)
{
	struct pci_dev *dev;

	cia_init_pci();

	/*
	 * Now we can look to see if we are really running on an XLT-type
	 * motherboard, by looking for a 21040 TULIP in slot 6, which is
	 * built into XLT and BRET/MAVERICK, but not available on ALCOR.
	 */
	dev = pci_get_device(PCI_VENDOR_ID_DEC,
			      PCI_DEVICE_ID_DEC_TULIP,
			      NULL);
	if (dev && dev->devfn == PCI_DEVFN(6,0)) {
		alpha_mv.sys.cia.gru_int_req_bits = XLT_GRU_INT_REQ_BITS;
		printk(KERN_INFO "%s: Detected AS500 or XLT motherboard.\n",
		       __func__);
	}
	pci_dev_put(dev);
}

/*
 * The System Vectors
 */

struct alpha_machine_vector alcor_mv __initmv = {
	.vector_name		= "Alcor",
	DO_EV5_MMU,
	DO_DEFAULT_RTC,
	DO_CIA_IO,
	.machine_check		= cia_machine_check,
	.max_isa_dma_address	= ALPHA_ALCOR_MAX_ISA_DMA_ADDRESS,
	.min_io_address		= EISA_DEFAULT_IO_BASE,
	.min_mem_address	= CIA_DEFAULT_MEM_BASE,

	.nr_irqs		= 48,
	.device_interrupt	= alcor_device_interrupt,

	.init_arch		= cia_init_arch,
	.init_irq		= alcor_init_irq,
	.init_rtc		= common_init_rtc,
	.init_pci		= alcor_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
	}}
};
ALIAS_MV(alcor)

struct alpha_machine_vector xlt_mv __initmv = {
	.vector_name		= "XLT",
	DO_EV5_MMU,
	DO_DEFAULT_RTC,
	DO_CIA_IO,
	.machine_check		= cia_machine_check,
	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
	.min_io_address		= EISA_DEFAULT_IO_BASE,
	.min_mem_address	= CIA_DEFAULT_MEM_BASE,

	.nr_irqs		= 48,
	.device_interrupt	= alcor_device_interrupt,

	.init_arch		= cia_init_arch,
	.init_irq		= alcor_init_irq,
	.init_rtc		= common_init_rtc,
	.init_pci		= alcor_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
	}}
};

/* No alpha_mv alias for XLT, since we compile it in unconditionally
   with ALCOR; setup_arch knows how to cope.  */


code:
// SPDX-License-Identifier: GPL-2.0
/*
 *	linux/arch/alpha/kernel/sys_cabriolet.c
 *
 *	Copyright (C) 1995 David A Rusling
 *	Copyright (C) 1996 Jay A Estabrook
 *	Copyright (C) 1998, 1999, 2000 Richard Henderson
 *
 * Code supporting the Cabriolet (AlphaPC64), EB66+, and EB164,
 * PC164 and LX164.
 */

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/bitops.h>

#include <asm/ptrace.h>
#include <asm/dma.h>
#include <asm/irq.h>
#include <asm/mmu_context.h>
#include <asm/io.h>
#include <asm/core_apecs.h>
#include <asm/core_cia.h>
#include <asm/core_lca.h>
#include <asm/tlbflush.h>

#include "proto.h"
#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"
#include "pc873xx.h"

/* Note mask bit is true for DISABLED irqs.  */
static unsigned long cached_irq_mask = ~0UL;

static inline void
cabriolet_update_irq_hw(unsigned int irq, unsigned long mask)
{
	int ofs = (irq - 16) / 8;
	outb(mask >> (16 + ofs * 8), 0x804 + ofs);
}

static inline void
cabriolet_enable_irq(struct irq_data *d)
{
	cabriolet_update_irq_hw(d->irq, cached_irq_mask &= ~(1UL << d->irq));
}

static void
cabriolet_disable_irq(struct irq_data *d)
{
	cabriolet_update_irq_hw(d->irq, cached_irq_mask |= 1UL << d->irq);
}

static struct irq_chip cabriolet_irq_type = {
	.name		= "CABRIOLET",
	.irq_unmask	= cabriolet_enable_irq,
	.irq_mask	= cabriolet_disable_irq,
	.irq_mask_ack	= cabriolet_disable_irq,
};

static void
cabriolet_device_interrupt(unsigned long v)
{
	unsigned long pld;
	unsigned int i;

	/* Read the interrupt summary registers */
	pld = inb(0x804) | (inb(0x805) << 8) | (inb(0x806) << 16);

	/*
	 * Now for every possible bit set, work through them and call
	 * the appropriate interrupt handler.
	 */
	while (pld) {
		i = ffz(~pld);
		pld &= pld - 1;	/* clear least bit set */
		if (i == 4) {
			isa_device_interrupt(v);
		} else {
			handle_irq(16 + i);
		}
	}
}

static void __init
common_init_irq(void (*srm_dev_int)(unsigned long v))
{
	init_i8259a_irqs();

	if (alpha_using_srm) {
		alpha_mv.device_interrupt = srm_dev_int;
		init_srm_irqs(35, 0);
	}
	else {
		long i;

		outb(0xff, 0x804);
		outb(0xff, 0x805);
		outb(0xff, 0x806);

		for (i = 16; i < 35; ++i) {
			irq_set_chip_and_handler(i, &cabriolet_irq_type,
						 handle_level_irq);
			irq_set_status_flags(i, IRQ_LEVEL);
		}
	}

	common_init_isa_dma();
	if (request_irq(16 + 4, no_action, 0, "isa-cascade", NULL))
		pr_err("Failed to register isa-cascade interrupt\n");
}

#ifndef CONFIG_ALPHA_PC164
static void __init
cabriolet_init_irq(void)
{
	common_init_irq(srm_device_interrupt);
}
#endif

#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PC164)
/* In theory, the PC164 has the same interrupt hardware as the other
   Cabriolet based systems.  However, something got screwed up late
   in the development cycle which broke the interrupt masking hardware.
   Repeat, it is not possible to mask and ack interrupts.  At all.

   In an attempt to work around this, while processing interrupts,
   we do not allow the IPL to drop below what it is currently.  This
   prevents the possibility of recursion.

   ??? Another option might be to force all PCI devices to use edge
   triggered rather than level triggered interrupts.  That might be
   too invasive though.  */

static void
pc164_srm_device_interrupt(unsigned long v)
{
	__min_ipl = getipl();
	srm_device_interrupt(v);
	__min_ipl = 0;
}

static void
pc164_device_interrupt(unsigned long v)
{
	__min_ipl = getipl();
	cabriolet_device_interrupt(v);
	__min_ipl = 0;
}

static void __init
pc164_init_irq(void)
{
	common_init_irq(pc164_srm_device_interrupt);
}
#endif

/*
 * The EB66+ is very similar to the EB66 except that it does not have
 * the on-board NCR and Tulip chips.  In the code below, I have used
 * slot number to refer to the id select line and *not* the slot
 * number used in the EB66+ documentation.  However, in the table,
 * I've given the slot number, the id select line and the Jxx number
 * that's printed on the board.  The interrupt pins from the PCI slots
 * are wired into 3 interrupt summary registers at 0x804, 0x805 and
 * 0x806 ISA.
 *
 * In the table, -1 means don't assign an IRQ number.  This is usually
 * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip.
 */

static inline int
eb66p_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
	static char irq_tab[5][5] = {
		/*INT  INTA  INTB  INTC   INTD */
		{16+0, 16+0, 16+5,  16+9, 16+13},  /* IdSel 6,  slot 0, J25 */
		{16+1, 16+1, 16+6, 16+10, 16+14},  /* IdSel 7,  slot 1, J26 */
		{  -1,   -1,   -1,    -1,    -1},  /* IdSel 8,  SIO         */
		{16+2, 16+2, 16+7, 16+11, 16+15},  /* IdSel 9,  slot 2, J27 */
		{16+3, 16+3, 16+8, 16+12,  16+6}   /* IdSel 10, slot 3, J28 */
	};
	const long min_idsel = 6, max_idsel = 10, irqs_per_slot = 5;
	return COMMON_TABLE_LOOKUP;
}

/*
 * The AlphaPC64 is very similar to the EB66+ except that its slots
 * are numbered differently.  In the code below, I have used slot
 * number to refer to the id select line and *not* the slot number
 * used in the AlphaPC64 documentation.  However, in the table, I've
 * given the slot number, the id select line and the Jxx number that's
 * printed on the board.  The interrupt pins from the PCI slots are
 * wired into 3 interrupt summary registers at 0x804, 0x805 and 0x806
 * ISA.
 *
 * In the table, -1 means don't assign an IRQ number.  This is usually
 * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip.
 */

static inline int
cabriolet_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
	static char irq_tab[5][5] = {
		/*INT   INTA  INTB  INTC   INTD */
		{ 16+2, 16+2, 16+7, 16+11, 16+15}, /* IdSel 5,  slot 2, J21 */
		{ 16+0, 16+0, 16+5,  16+9, 16+13}, /* IdSel 6,  slot 0, J19 */
		{ 16+1, 16+1, 16+6, 16+10, 16+14}, /* IdSel 7,  slot 1, J20 */
		{   -1,   -1,   -1,    -1,    -1}, /* IdSel 8,  SIO         */
		{ 16+3, 16+3, 16+8, 16+12, 16+16}  /* IdSel 9,  slot 3, J22 */
	};
	const long min_idsel = 5, max_idsel = 9, irqs_per_slot = 5;
	return COMMON_TABLE_LOOKUP;
}

static inline void __init
cabriolet_enable_ide(void)
{
	if (pc873xx_probe() == -1) {
		printk(KERN_ERR "Probing for PC873xx Super IO chip failed.\n");
	 } else {
		printk(KERN_INFO "Found %s Super IO chip at 0x%x\n",
			pc873xx_get_model(), pc873xx_get_base());

		pc873xx_enable_ide();
	}
}

static inline void __init
cabriolet_init_pci(void)
{
	common_init_pci();
	cabriolet_enable_ide();
}

static inline void __init
cia_cab_init_pci(void)
{
	cia_init_pci();
	cabriolet_enable_ide();
}

/*
 * The PC164 and LX164 have 19 PCI interrupts, four from each of the four
 * PCI slots, the SIO, PCI/IDE, and USB.
 *
 * Each of the interrupts can be individually masked. This is
 * accomplished by setting the appropriate bit in the mask register.
 * A bit is set by writing a "1" to the desired position in the mask
 * register and cleared by writing a "0". There are 3 mask registers
 * located at ISA address 804h, 805h and 806h.
 *
 * An I/O read at ISA address 804h, 805h, 806h will return the
 * state of the 11 PCI interrupts and not the state of the MASKED
 * interrupts.
 *
 * Note: A write to I/O 804h, 805h, and 806h the mask register will be
 * updated.
 *
 *
 * 				ISA DATA<7:0>
 * ISA     +--------------------------------------------------------------+
 * ADDRESS |   7   |   6   |   5   |   4   |   3   |   2  |   1   |   0   |
 *         +==============================================================+
 * 0x804   | INTB0 |  USB  |  IDE  |  SIO  | INTA3 |INTA2 | INTA1 | INTA0 |
 *         +--------------------------------------------------------------+
 * 0x805   | INTD0 | INTC3 | INTC2 | INTC1 | INTC0 |INTB3 | INTB2 | INTB1 |
 *         +--------------------------------------------------------------+
 * 0x806   | Rsrv  | Rsrv  | Rsrv  | Rsrv  | Rsrv  |INTD3 | INTD2 | INTD1 |
 *         +--------------------------------------------------------------+
 *         * Rsrv = reserved bits
 *         Note: The mask register is write-only.
 *
 * IdSel
 *   5	 32 bit PCI option slot 2
 *   6	 64 bit PCI option slot 0
 *   7	 64 bit PCI option slot 1
 *   8	 Saturn I/O
 *   9	 32 bit PCI option slot 3
 *  10	 USB
 *  11	 IDE
 *
 */

static inline int
alphapc164_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
	static char irq_tab[7][5] = {
		/*INT   INTA  INTB   INTC   INTD */
		{ 16+2, 16+2, 16+9,  16+13, 16+17}, /* IdSel  5, slot 2, J20 */
		{ 16+0, 16+0, 16+7,  16+11, 16+15}, /* IdSel  6, slot 0, J29 */
		{ 16+1, 16+1, 16+8,  16+12, 16+16}, /* IdSel  7, slot 1, J26 */
		{   -1,   -1,   -1,    -1,    -1},  /* IdSel  8, SIO */
		{ 16+3, 16+3, 16+10, 16+14, 16+18}, /* IdSel  9, slot 3, J19 */
		{ 16+6, 16+6, 16+6,  16+6,  16+6},  /* IdSel 10, USB */
		{ 16+5, 16+5, 16+5,  16+5,  16+5}   /* IdSel 11, IDE */
	};
	const long min_idsel = 5, max_idsel = 11, irqs_per_slot = 5;
	return COMMON_TABLE_LOOKUP;
}

static inline void __init
alphapc164_init_pci(void)
{
	cia_init_pci();
	SMC93x_Init();
}

/*
 * The System Vector
 */

#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_CABRIOLET)
struct alpha_machine_vector cabriolet_mv __initmv = {
	.vector_name		= "Cabriolet",
	DO_EV4_MMU,
	DO_DEFAULT_RTC,
	DO_APECS_IO,
	.machine_check		= apecs_machine_check,
	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
	.min_io_address		= DEFAULT_IO_BASE,
	.min_mem_address	= APECS_AND_LCA_DEFAULT_MEM_BASE,

	.nr_irqs		= 35,
	.device_interrupt	= cabriolet_device_interrupt,

	.init_arch		= apecs_init_arch,
	.init_irq		= cabriolet_init_irq,
	.init_rtc		= common_init_rtc,
	.init_pci		= cabriolet_init_pci,
	.pci_map_irq		= cabriolet_map_irq,
	.pci_swizzle		= common_swizzle,
};
#ifndef CONFIG_ALPHA_EB64P
ALIAS_MV(cabriolet)
#endif
#endif

#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB164)
struct alpha_machine_vector eb164_mv __initmv = {
	.vector_name		= "EB164",
	DO_EV5_MMU,
	DO_DEFAULT_RTC,
	DO_CIA_IO,
	.machine_check		= cia_machine_check,
	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
	.min_io_address		= DEFAULT_IO_BASE,
	.min_mem_address	= CIA_DEFAULT_MEM_BASE,

	.nr_irqs		= 35,
	.device_interrupt	= cabriolet_device_interrupt,

	.init_arch		= cia_init_arch,
	.init_irq		= cabriolet_init_irq,
	.init_rtc		= common_init_rtc,
	.init_pci		= cia_cab_init_pci,
	.kill_arch		= cia_kill_arch,
	.pci_map_irq		= cabriolet_map_irq,
	.pci_swizzle		= common_swizzle,
};
ALIAS_MV(eb164)
#endif

#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB66P)
struct alpha_machine_vector eb66p_mv __initmv = {
	.vector_name		= "EB66+",
	DO_EV4_MMU,
	DO_DEFAULT_RTC,
	DO_LCA_IO,
	.machine_check		= lca_machine_check,
	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
	.min_io_address		= DEFAULT_IO_BASE,
	.min_mem_address	= APECS_AND_LCA_DEFAULT_MEM_BASE,

	.nr_irqs		= 35,
	.device_interrupt	= cabriolet_device_interrupt,

	.init_arch		= lca_init_arch,
	.init_irq		= cabriolet_init_irq,
	.init_rtc		= common_init_rtc,
	.init_pci		= cabriolet_init_pci,
	.pci_map_irq		= eb66p_map_irq,
	.pci_swizzle		= common_swizzle,
};
ALIAS_MV(eb66p)
#endif

#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_LX164)
struct alpha_machine_vector lx164_mv __initmv = {
	.vector_name		= "LX164",
	DO_EV5_MMU,
	DO_DEFAULT_RTC,
	DO_PYXIS_IO,
	.machine_check		= cia_machine_check,
	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
	.min_io_address		= DEFAULT_IO_BASE,
	.min_mem_address	= DEFAULT_MEM_BASE,
	.pci_dac_offset		= PYXIS_DAC_OFFSET,

	.nr_irqs		= 35,
	.device_interrupt	= cabriolet_device_interrupt,

	.init_arch		= pyxis_init_arch,
	.init_irq		= cabriolet_init_irq,
	.init_rtc		= common_init_rtc,
	.init_pci		= alphapc164_init_pci,
	.kill_arch		= cia_kill_arch,
	.pci_map_irq		= alphapc164_map_irq,
	.pci_swizzle		= common_swizzle,
};
ALIAS_MV(lx164)
#endif

#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PC164)
struct alpha_machine_vector pc164_mv __initmv = {
	.vector_name		= "PC164",
	DO_EV5_MMU,
	DO_DEFAULT_RTC,
	DO_CIA_IO,
	.machine_check		= cia_machine_check,
	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
	.min_io_address		= DEFAULT_IO_BASE,
	.min_mem_address	= CIA_DEFAULT_MEM_BASE,

	.nr_irqs		= 35,
	.device_interrupt	= pc164_device_interrupt,

	.init_arch		= cia_init_arch,
	.init_irq		= pc164_init_irq,
	.init_rtc		= common_init_rtc,
	.init_pci		= alphapc164_init_pci,
	.kill_arch		= cia_kill_arch,
	.pci_map_irq		= alphapc164_map_irq,
	.pci_swizzle		= common_swizzle,
};
ALIAS_MV(pc164)
#endif

repo_name: angery/linux


code:
// SPDX-License-Identifier: GPL-2.0
/*
 *	linux/arch/alpha/kernel/sys_dp264.c
 *
 *	Copyright (C) 1995 David A Rusling
 *	Copyright (C) 1996, 1999 Jay A Estabrook
 *	Copyright (C) 1998, 1999 Richard Henderson
 *
 *	Modified by Christopher C. Chimelis, 2001 to
 *	add support for the addition of Shark to the
 *	Tsunami family.
 *
 * Code supporting the DP264 (EV6+TSUNAMI).
 */

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/bitops.h>

#include <asm/ptrace.h>
#include <asm/dma.h>
#include <asm/irq.h>
#include <asm/mmu_context.h>
#include <asm/io.h>
#include <asm/core_tsunami.h>
#include <asm/hwrpb.h>
#include <asm/tlbflush.h>

#include "proto.h"
#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"

/* Note mask bit is true for ENABLED irqs.  */
static unsigned long cached_irq_mask;
/* dp264 boards handle at max four CPUs */
static unsigned long cpu_irq_affinity[4] = { 0UL, 0UL, 0UL, 0UL };

DEFINE_SPINLOCK(dp264_irq_lock);

static void
tsunami_update_irq_hw(unsigned long mask)
{
	register tsunami_cchip *cchip = TSUNAMI_cchip;
	unsigned long isa_enable = 1UL << 55;
	register int bcpu = boot_cpuid;

#ifdef CONFIG_SMP
	volatile unsigned long *dim0, *dim1, *dim2, *dim3;
	unsigned long mask0, mask1, mask2, mask3, dummy;

	mask &= ~isa_enable;
	mask0 = mask & cpu_irq_affinity[0];
	mask1 = mask & cpu_irq_affinity[1];
	mask2 = mask & cpu_irq_affinity[2];
	mask3 = mask & cpu_irq_affinity[3];

	if (bcpu == 0) mask0 |= isa_enable;
	else if (bcpu == 1) mask1 |= isa_enable;
	else if (bcpu == 2) mask2 |= isa_enable;
	else mask3 |= isa_enable;

	dim0 = &cchip->dim0.csr;
	dim1 = &cchip->dim1.csr;
	dim2 = &cchip->dim2.csr;
	dim3 = &cchip->dim3.csr;
	if (!cpu_possible(0)) dim0 = &dummy;
	if (!cpu_possible(1)) dim1 = &dummy;
	if (!cpu_possible(2)) dim2 = &dummy;
	if (!cpu_possible(3)) dim3 = &dummy;

	*dim0 = mask0;
	*dim1 = mask1;
	*dim2 = mask2;
	*dim3 = mask3;
	mb();
	*dim0;
	*dim1;
	*dim2;
	*dim3;
#else
	volatile unsigned long *dimB;
	if (bcpu == 0) dimB = &cchip->dim0.csr;
	else if (bcpu == 1) dimB = &cchip->dim1.csr;
	else if (bcpu == 2) dimB = &cchip->dim2.csr;
	else dimB = &cchip->dim3.csr;

	*dimB = mask | isa_enable;
	mb();
	*dimB;
#endif
}

static void
dp264_enable_irq(struct irq_data *d)
{
	spin_lock(&dp264_irq_lock);
	cached_irq_mask |= 1UL << d->irq;
	tsunami_update_irq_hw(cached_irq_mask);
	spin_unlock(&dp264_irq_lock);
}

static void
dp264_disable_irq(struct irq_data *d)
{
	spin_lock(&dp264_irq_lock);
	cached_irq_mask &= ~(1UL << d->irq);
	tsunami_update_irq_hw(cached_irq_mask);
	spin_unlock(&dp264_irq_lock);
}

static void
clipper_enable_irq(struct irq_data *d)
{
	spin_lock(&dp264_irq_lock);
	cached_irq_mask |= 1UL << (d->irq - 16);
	tsunami_update_irq_hw(cached_irq_mask);
	spin_unlock(&dp264_irq_lock);
}

static void
clipper_disable_irq(struct irq_data *d)
{
	spin_lock(&dp264_irq_lock);
	cached_irq_mask &= ~(1UL << (d->irq - 16));
	tsunami_update_irq_hw(cached_irq_mask);
	spin_unlock(&dp264_irq_lock);
}

static void
cpu_set_irq_affinity(unsigned int irq, cpumask_t affinity)
{
	int cpu;

	for (cpu = 0; cpu < 4; cpu++) {
		unsigned long aff = cpu_irq_affinity[cpu];
		if (cpumask_test_cpu(cpu, &affinity))
			aff |= 1UL << irq;
		else
			aff &= ~(1UL << irq);
		cpu_irq_affinity[cpu] = aff;
	}
}

static int
dp264_set_affinity(struct irq_data *d, const struct cpumask *affinity,
		   bool force)
{
	spin_lock(&dp264_irq_lock);
	cpu_set_irq_affinity(d->irq, *affinity);
	tsunami_update_irq_hw(cached_irq_mask);
	spin_unlock(&dp264_irq_lock);

	return 0;
}

static int
clipper_set_affinity(struct irq_data *d, const struct cpumask *affinity,
		     bool force)
{
	spin_lock(&dp264_irq_lock);
	cpu_set_irq_affinity(d->irq - 16, *affinity);
	tsunami_update_irq_hw(cached_irq_mask);
	spin_unlock(&dp264_irq_lock);

	return 0;
}

static struct irq_chip dp264_irq_type = {
	.name			= "DP264",
	.irq_unmask		= dp264_enable_irq,
	.irq_mask		= dp264_disable_irq,
	.irq_mask_ack		= dp264_disable_irq,
	.irq_set_affinity	= dp264_set_affinity,
};

static struct irq_chip clipper_irq_type = {
	.name			= "CLIPPER",
	.irq_unmask		= clipper_enable_irq,
	.irq_mask		= clipper_disable_irq,
	.irq_mask_ack		= clipper_disable_irq,
	.irq_set_affinity	= clipper_set_affinity,
};

static void
dp264_device_interrupt(unsigned long vector)
{
	unsigned long pld;
	unsigned int i;

	/* Read the interrupt summary register of TSUNAMI */
	pld = TSUNAMI_cchip->dir0.csr;

	/*
	 * Now for every possible bit set, work through them and call
	 * the appropriate interrupt handler.
	 */
	while (pld) {
		i = ffz(~pld);
		pld &= pld - 1; /* clear least bit set */
		if (i == 55)
			isa_device_interrupt(vector);
		else
			handle_irq(16 + i);
	}
}

static void
dp264_srm_device_interrupt(unsigned long vector)
{
	int irq;

	irq = (vector - 0x800) >> 4;

	/*
	 * The SRM console reports PCI interrupts with a vector calculated by:
	 *
	 *	0x900 + (0x10 * DRIR-bit)
	 *
	 * So bit 16 shows up as IRQ 32, etc.
	 *
	 * On DP264/BRICK/MONET, we adjust it down by 16 because at least
	 * that many of the low order bits of the DRIR are not used, and
	 * so we don't count them.
	 */
	if (irq >= 32)
		irq -= 16;

	handle_irq(irq);
}

static void
clipper_srm_device_interrupt(unsigned long vector)
{
	int irq;

	irq = (vector - 0x800) >> 4;

/*
	 * The SRM console reports PCI interrupts with a vector calculated by:
	 *
	 *	0x900 + (0x10 * DRIR-bit)
	 *
	 * So bit 16 shows up as IRQ 32, etc.
	 *
	 * CLIPPER uses bits 8-47 for PCI interrupts, so we do not need
	 * to scale down the vector reported, we just use it.
	 *
	 * Eg IRQ 24 is DRIR bit 8, etc, etc
	 */
	handle_irq(irq);
}

static void __init
init_tsunami_irqs(struct irq_chip * ops, int imin, int imax)
{
	long i;
	for (i = imin; i <= imax; ++i) {
		irq_set_chip_and_handler(i, ops, handle_level_irq);
		irq_set_status_flags(i, IRQ_LEVEL);
	}
}

static void __init
dp264_init_irq(void)
{
	outb(0, DMA1_RESET_REG);
	outb(0, DMA2_RESET_REG);
	outb(DMA_MODE_CASCADE, DMA2_MODE_REG);
	outb(0, DMA2_MASK_REG);

	if (alpha_using_srm)
		alpha_mv.device_interrupt = dp264_srm_device_interrupt;

	tsunami_update_irq_hw(0);

	init_i8259a_irqs();
	init_tsunami_irqs(&dp264_irq_type, 16, 47);
}

static void __init
clipper_init_irq(void)
{
	outb(0, DMA1_RESET_REG);
	outb(0, DMA2_RESET_REG);
	outb(DMA_MODE_CASCADE, DMA2_MODE_REG);
	outb(0, DMA2_MASK_REG);

	if (alpha_using_srm)
		alpha_mv.device_interrupt = clipper_srm_device_interrupt;

	tsunami_update_irq_hw(0);

	init_i8259a_irqs();
	init_tsunami_irqs(&clipper_irq_type, 24, 63);
}

/*
 * PCI Fixup configuration.
 *
 * Summary @ TSUNAMI_CSR_DIM0:
 * Bit      Meaning
 * 0-17     Unused
 *18        Interrupt SCSI B (Adaptec 7895 builtin)
 *19        Interrupt SCSI A (Adaptec 7895 builtin)
 *20        Interrupt Line D from slot 2 PCI0
 *21        Interrupt Line C from slot 2 PCI0
 *22        Interrupt Line B from slot 2 PCI0
 *23        Interrupt Line A from slot 2 PCI0
 *24        Interrupt Line D from slot 1 PCI0
 *25        Interrupt Line C from slot 1 PCI0
 *26        Interrupt Line B from slot 1 PCI0
 *27        Interrupt Line A from slot 1 PCI0
 *28        Interrupt Line D from slot 0 PCI0
 *29        Interrupt Line C from slot 0 PCI0
 *30        Interrupt Line B from slot 0 PCI0
 *31        Interrupt Line A from slot 0 PCI0
 *
 *32        Interrupt Line D from slot 3 PCI1
 *33        Interrupt Line C from slot 3 PCI1
 *34        Interrupt Line B from slot 3 PCI1
 *35        Interrupt Line A from slot 3 PCI1
 *36        Interrupt Line D from slot 2 PCI1
 *37        Interrupt Line C from slot 2 PCI1
 *38        Interrupt Line B from slot 2 PCI1
 *39        Interrupt Line A from slot 2 PCI1
 *40        Interrupt Line D from slot 1 PCI1
 *41        Interrupt Line C from slot 1 PCI1
 *42        Interrupt Line B from slot 1 PCI1
 *43        Interrupt Line A from slot 1 PCI1
 *44        Interrupt Line D from slot 0 PCI1
 *45        Interrupt Line C from slot 0 PCI1
 *46        Interrupt Line B from slot 0 PCI1
 *47        Interrupt Line A from slot 0 PCI1
 *48-52     Unused
 *53        PCI0 NMI (from Cypress)
 *54        PCI0 SMI INT (from Cypress)
 *55        PCI0 ISA Interrupt (from Cypress)
 *56-60     Unused
 *61        PCI1 Bus Error
 *62        PCI0 Bus Error
 *63        Reserved
 *
 * IdSel
 *   5	 Cypress Bridge I/O
 *   6	 SCSI Adaptec builtin
 *   7	 64 bit PCI option slot 0 (all busses)
 *   8	 64 bit PCI option slot 1 (all busses)
 *   9	 64 bit PCI option slot 2 (all busses)
 *  10	 64 bit PCI option slot 3 (not bus 0)
 */

static int
isa_irq_fixup(const struct pci_dev *dev, int irq)
{
	u8 irq8;

	if (irq > 0)
		return irq;

	/* This interrupt is routed via ISA bridge, so we'll
	   just have to trust whatever value the console might
	   have assigned.  */
	pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq8);

	return irq8 & 0xf;
}

static int
dp264_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
	static char irq_tab[6][5] = {
		/*INT    INTA   INTB   INTC   INTD */
		{    -1,    -1,    -1,    -1,    -1}, /* IdSel 5 ISA Bridge */
		{ 16+ 3, 16+ 3, 16+ 2, 16+ 2, 16+ 2}, /* IdSel 6 SCSI builtin*/
		{ 16+15, 16+15, 16+14, 16+13, 16+12}, /* IdSel 7 slot 0 */
		{ 16+11, 16+11, 16+10, 16+ 9, 16+ 8}, /* IdSel 8 slot 1 */
		{ 16+ 7, 16+ 7, 16+ 6, 16+ 5, 16+ 4}, /* IdSel 9 slot 2 */
		{ 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_controller *hose = dev->sysdata;
	int irq = COMMON_TABLE_LOOKUP;

	if (irq > 0)
		irq += 16 * hose->index;

	return isa_irq_fixup(dev, irq);
}

static int
monet_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
	static char irq_tab[13][5] = {
		/*INT    INTA   INTB   INTC   INTD */
		{    45,    45,    45,    45,    45}, /* IdSel 3 21143 PCI1 */
		{    -1,    -1,    -1,    -1,    -1}, /* IdSel 4 unused */
		{    -1,    -1,    -1,    -1,    -1}, /* IdSel 5 unused */
		{    47,    47,    47,    47,    47}, /* IdSel 6 SCSI PCI1 */
		{    -1,    -1,    -1,    -1,    -1}, /* IdSel 7 ISA Bridge */
		{    -1,    -1,    -1,    -1,    -1}, /* IdSel 8 P2P PCI1 */
#if 1
		{    28,    28,    29,    30,    31}, /* IdSel 14 slot 4 PCI2*/
		{    24,    24,    25,    26,    27}, /* IdSel 15 slot 5 PCI2*/
#else
		{    -1,    -1,    -1,    -1,    -1}, /* IdSel 9 unused */
		{    -1,    -1,    -1,    -1,    -1}, /* IdSel 10 unused */
#endif
		{    40,    40,    41,    42,    43}, /* IdSel 11 slot 1 PCI0*/
		{    36,    36,    37,    38,    39}, /* IdSel 12 slot 2 PCI0*/
		{    32,    32,    33,    34,    35}, /* IdSel 13 slot 3 PCI0*/
		{    28,    28,    29,    30,    31}, /* IdSel 14 slot 4 PCI2*/
		{    24,    24,    25,    26,    27}  /* IdSel 15 slot 5 PCI2*/
	};
	const long min_idsel = 3, max_idsel = 15, irqs_per_slot = 5;

	return isa_irq_fixup(dev, COMMON_TABLE_LOOKUP);
}

static u8
monet_swizzle(struct pci_dev *dev, u8 *pinp)
{
	struct pci_controller *hose = dev->sysdata;
	int slot, pin = *pinp;

	if (!dev->bus->parent) {
		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 (hose->index == 1 &&
			    PCI_SLOT(dev->bus->self->devfn) == 8) {
				slot = PCI_SLOT(dev->devfn);
				break;
			}
			pin = pci_swizzle_interrupt_pin(dev, pin);

			/* Move up the chain of bridges.  */
			dev = dev->bus->self;
			/* Slot of the next bridge.  */
			slot = PCI_SLOT(dev->devfn);
		} while (dev->bus->self);
	}
	*pinp = pin;
	return slot;
}

static int
webbrick_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
	static char irq_tab[13][5] = {
		/*INT    INTA   INTB   INTC   INTD */
		{    -1,    -1,    -1,    -1,    -1}, /* IdSel 7 ISA Bridge */
		{    -1,    -1,    -1,    -1,    -1}, /* IdSel 8 unused */
		{    29,    29,    29,    29,    29}, /* IdSel 9 21143 #1 */
		{    -1,    -1,    -1,    -1,    -1}, /* IdSel 10 unused */
		{    30,    30,    30,    30,    30}, /* IdSel 11 21143 #2 */
		{    -1,    -1,    -1,    -1,    -1}, /* IdSel 12 unused */
		{    -1,    -1,    -1,    -1,    -1}, /* IdSel 13 unused */
		{    35,    35,    34,    33,    32}, /* IdSel 14 slot 0 */
		{    39,    39,    38,    37,    36}, /* IdSel 15 slot 1 */
		{    43,    43,    42,    41,    40}, /* IdSel 16 slot 2 */
		{    47,    47,    46,    45,    44}, /* IdSel 17 slot 3 */
	};
	const long min_idsel = 7, max_idsel = 17, irqs_per_slot = 5;

	return isa_irq_fixup(dev, COMMON_TABLE_LOOKUP);
}

static int
clipper_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
	static char irq_tab[7][5] = {
		/*INT    INTA   INTB   INTC   INTD */
		{ 16+ 8, 16+ 8, 16+ 9, 16+10, 16+11}, /* IdSel 1 slot 1 */
		{ 16+12, 16+12, 16+13, 16+14, 16+15}, /* IdSel 2 slot 2 */
		{ 16+16, 16+16, 16+17, 16+18, 16+19}, /* IdSel 3 slot 3 */
		{ 16+20, 16+20, 16+21, 16+22, 16+23}, /* IdSel 4 slot 4 */
		{ 16+24, 16+24, 16+25, 16+26, 16+27}, /* IdSel 5 slot 5 */
		{ 16+28, 16+28, 16+29, 16+30, 16+31}, /* IdSel 6 slot 6 */
		{    -1,    -1,    -1,    -1,    -1}  /* IdSel 7 ISA Bridge */
	};
	const long min_idsel = 1, max_idsel = 7, irqs_per_slot = 5;
	struct pci_controller *hose = dev->sysdata;
	int irq = COMMON_TABLE_LOOKUP;

	if (irq > 0)
		irq += 16 * hose->index;

	return isa_irq_fixup(dev, irq);
}

static void __init
dp264_init_pci(void)
{
	common_init_pci();
	SMC669_Init(0);
	locate_and_init_vga(NULL);
}

static void __init
monet_init_pci(void)
{
	common_init_pci();
	SMC669_Init(1);
	es1888_init();
	locate_and_init_vga(NULL);
}

static void __init
clipper_init_pci(void)
{
	common_init_pci();
	locate_and_init_vga(NULL);
}

static void __init
webbrick_init_arch(void)
{
	tsunami_init_arch();

	/* Tsunami caches 4 PTEs at a time; DS10 has only 1 hose. */
	hose_head->sg_isa->align_entry = 4;
	hose_head->sg_pci->align_entry = 4;
}

/*
 * The System Vectors
 */

struct alpha_machine_vector dp264_mv __initmv = {
	.vector_name		= "DP264",
	DO_EV6_MMU,
	DO_DEFAULT_RTC,
	DO_TSUNAMI_IO,
	.machine_check		= tsunami_machine_check,
	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
	.min_io_address		= DEFAULT_IO_BASE,
	.min_mem_address	= DEFAULT_MEM_BASE,
	.pci_dac_offset		= TSUNAMI_DAC_OFFSET,

	.nr_irqs		= 64,
	.device_interrupt	= dp264_device_interrupt,

	.init_arch		= tsunami_init_arch,
	.init_irq		= dp264_init_irq,
	.init_rtc		= common_init_rtc,
	.init_pci		= dp264_init_pci,
	.kill_arch		= tsunami_kill_arch,
	.pci_map_irq		= dp264_map_irq,
	.pci_swizzle		= common_swizzle,
};
ALIAS_MV(dp264)

struct alpha_machine_vector monet_mv __initmv = {
	.vector_name		= "Monet",
	DO_EV6_MMU,
	DO_DEFAULT_RTC,
	DO_TSUNAMI_IO,
	.machine_check		= tsunami_machine_check,
	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
	.min_io_address		= DEFAULT_IO_BASE,
	.min_mem_address	= DEFAULT_MEM_BASE,
	.pci_dac_offset		= TSUNAMI_DAC_OFFSET,

	.nr_irqs		= 64,
	.device_interrupt	= dp264_device_interrupt,

	.init_arch		= tsunami_init_arch,
	.init_irq		= dp264_init_irq,
	.init_rtc		= common_init_rtc,
	.init_pci		= monet_init_pci,
	.kill_arch		= tsunami_kill_arch,
	.pci_map_irq		= monet_map_irq,
	.pci_swizzle		= monet_swizzle,
};

struct alpha_machine_vector webbrick_mv __initmv = {
	.vector_name		= "Webbrick",
	DO_EV6_MMU,
	DO_DEFAULT_RTC,
	DO_TSUNAMI_IO,
	.machine_check		= tsunami_machine_check,
	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
	.min_io_address		= DEFAULT_IO_BASE,
	.min_mem_address	= DEFAULT_MEM_BASE,
	.pci_dac_offset		= TSUNAMI_DAC_OFFSET,

	.nr_irqs		= 64,
	.device_interrupt	= dp264_device_interrupt,

	.init_arch		= webbrick_init_arch,
	.init_irq		= dp264_init_irq,
	.init_rtc		= common_init_rtc,
	.init_pci		= common_init_pci,
	.kill_arch		= tsunami_kill_arch,
	.pci_map_irq		= webbrick_map_irq,
	.pci_swizzle		= common_swizzle,
};

struct alpha_machine_vector clipper_mv __initmv = {
	.vector_name		= "Clipper",
	DO_EV6_MMU,
	DO_DEFAULT_RTC,
	DO_TSUNAMI_IO,
	.machine_check		= tsunami_machine_check,
	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
	.min_io_address		= DEFAULT_IO_BASE,
	.min_mem_address	= DEFAULT_MEM_BASE,
	.pci_dac_offset		= TSUNAMI_DAC_OFFSET,

	.nr_irqs		= 64,
	.device_interrupt	= dp264_device_interrupt,

	.init_arch		= tsunami_init_arch,
	.init_irq		= clipper_init_irq,
	.init_rtc		= common_init_rtc,
	.init_pci		= clipper_init_pci,
	.kill_arch		= tsunami_kill_arch,
	.pci_map_irq		= clipper_map_irq,
	.pci_swizzle		= common_swizzle,
};

/* Sharks strongly resemble Clipper, at least as far
 * as interrupt routing, etc, so we're using the
 * same functions as Clipper does
 */

struct alpha_machine_vector shark_mv __initmv = {
	.vector_name		= "Shark",
	DO_EV6_MMU,
	DO_DEFAULT_RTC,
	DO_TSUNAMI_IO,
	.machine_check		= tsunami_machine_check,
	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
	.min_io_address		= DEFAULT_IO_BASE,
	.min_mem_address	= DEFAULT_MEM_BASE,
	.pci_dac_offset		= TSUNAMI_DAC_OFFSET,

	.nr_irqs		= 64,
	.device_interrupt	= dp264_device_interrupt,

	.init_arch		= tsunami_init_arch,
	.init_irq		= clipper_init_irq,
	.init_rtc		= common_init_rtc,
	.init_pci		= common_init_pci,
	.kill_arch		= tsunami_kill_arch,
	.pci_map_irq		= clipper_map_irq,
	.pci_swizzle		= common_swizzle,
};

/* No alpha_mv alias for webbrick/monet/clipper, since we compile them
   in unconditionally with DP264; setup_arch knows how to cope.  */


code:
// SPDX-License-Identifier: GPL-2.0
/*
 *	linux/arch/alpha/kernel/sys_eb64p.c
 *
 *	Copyright (C) 1995 David A Rusling
 *	Copyright (C) 1996 Jay A Estabrook
 *	Copyright (C) 1998, 1999 Richard Henderson
 *
 * Code supporting the EB64+ and EB66.
 */

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/bitops.h>

#include <asm/ptrace.h>
#include <asm/dma.h>
#include <asm/irq.h>
#include <asm/mmu_context.h>
#include <asm/io.h>
#include <asm/core_apecs.h>
#include <asm/core_lca.h>
#include <asm/hwrpb.h>
#include <asm/tlbflush.h>

#include "proto.h"
#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"

/* Note mask bit is true for DISABLED irqs.  */
static unsigned int cached_irq_mask = -1;

static inline void
eb64p_update_irq_hw(unsigned int irq, unsigned long mask)
{
	outb(mask >> (irq >= 24 ? 24 : 16), (irq >= 24 ? 0x27 : 0x26));
}

static inline void
eb64p_enable_irq(struct irq_data *d)
{
	eb64p_update_irq_hw(d->irq, cached_irq_mask &= ~(1 << d->irq));
}

static void
eb64p_disable_irq(struct irq_data *d)
{
	eb64p_update_irq_hw(d->irq, cached_irq_mask |= 1 << d->irq);
}

static struct irq_chip eb64p_irq_type = {
	.name		= "EB64P",
	.irq_unmask	= eb64p_enable_irq,
	.irq_mask	= eb64p_disable_irq,
	.irq_mask_ack	= eb64p_disable_irq,
};

static void
eb64p_device_interrupt(unsigned long vector)
{
	unsigned long pld;
	unsigned int i;

	/* Read the interrupt summary registers */
	pld = inb(0x26) | (inb(0x27) << 8);

	/*
	 * Now, for every possible bit set, work through
	 * them and call the appropriate interrupt handler.
	 */
	while (pld) {
		i = ffz(~pld);
		pld &= pld - 1;	/* clear least bit set */

		if (i == 5) {
			isa_device_interrupt(vector);
		} else {
			handle_irq(16 + i);
		}
	}
}

static void __init
eb64p_init_irq(void)
{
	long i;

#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_CABRIOLET)
	/*
	 * CABRIO SRM may not set variation correctly, so here we test
	 * the high word of the interrupt summary register for the RAZ
	 * bits, and hope that a true EB64+ would read all ones...
	 */
	if (inw(0x806) != 0xffff) {
		extern struct alpha_machine_vector cabriolet_mv;

		printk("Detected Cabriolet: correcting HWRPB.\n");

		hwrpb->sys_variation |= 2L << 10;
		hwrpb_update_checksum(hwrpb);

		alpha_mv = cabriolet_mv;
		alpha_mv.init_irq();
		return;
	}
#endif /* GENERIC */

	outb(0xff, 0x26);
	outb(0xff, 0x27);

	init_i8259a_irqs();

	for (i = 16; i < 32; ++i) {
		irq_set_chip_and_handler(i, &eb64p_irq_type, handle_level_irq);
		irq_set_status_flags(i, IRQ_LEVEL);
	}

	common_init_isa_dma();
	if (request_irq(16 + 5, no_action, 0, "isa-cascade", NULL))
		pr_err("Failed to register isa-cascade interrupt\n");
}

/*
 * PCI Fixup configuration.
 *
 * There are two 8 bit external summary registers as follows:
 *
 * Summary @ 0x26:
 * Bit      Meaning
 * 0        Interrupt Line A from slot 0
 * 1        Interrupt Line A from slot 1
 * 2        Interrupt Line B from slot 0
 * 3        Interrupt Line B from slot 1
 * 4        Interrupt Line C from slot 0
 * 5        Interrupt line from the two ISA PICs
 * 6        Tulip
 * 7        NCR SCSI
 *
 * Summary @ 0x27
 * Bit      Meaning
 * 0        Interrupt Line C from slot 1
 * 1        Interrupt Line D from slot 0
 * 2        Interrupt Line D from slot 1
 * 3        RAZ
 * 4        RAZ
 * 5        RAZ
 * 6        RAZ
 * 7        RAZ
 *
 * The device to slot mapping looks like:
 *
 * Slot     Device
 *  5       NCR SCSI controller
 *  6       PCI on board slot 0
 *  7       PCI on board slot 1
 *  8       Intel SIO PCI-ISA bridge chip
 *  9       Tulip - DECchip 21040 Ethernet controller
 *
 *
 * This two layered interrupt approach means that we allocate IRQ 16 and
 * above for PCI interrupts.  The IRQ relates to which bit the interrupt
 * comes in on.  This makes interrupt processing much easier.
 */

static int
eb64p_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
	static char irq_tab[5][5] = {
		/*INT  INTA  INTB  INTC   INTD */
		{16+7, 16+7, 16+7, 16+7,  16+7},  /* IdSel 5,  slot ?, ?? */
		{16+0, 16+0, 16+2, 16+4,  16+9},  /* IdSel 6,  slot ?, ?? */
		{16+1, 16+1, 16+3, 16+8, 16+10},  /* IdSel 7,  slot ?, ?? */
		{  -1,   -1,   -1,   -1,    -1},  /* IdSel 8,  SIO */
		{16+6, 16+6, 16+6, 16+6,  16+6},  /* IdSel 9,  TULIP */
	};
	const long min_idsel = 5, max_idsel = 9, irqs_per_slot = 5;
	return COMMON_TABLE_LOOKUP;
}

/*
 * The System Vector
 */

#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB64P)
struct alpha_machine_vector eb64p_mv __initmv = {
	.vector_name		= "EB64+",
	DO_EV4_MMU,
	DO_DEFAULT_RTC,
	DO_APECS_IO,
	.machine_check		= apecs_machine_check,
	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
	.min_io_address		= DEFAULT_IO_BASE,
	.min_mem_address	= APECS_AND_LCA_DEFAULT_MEM_BASE,

	.nr_irqs		= 32,
	.device_interrupt	= eb64p_device_interrupt,

	.init_arch		= apecs_init_arch,
	.init_irq		= eb64p_init_irq,
	.init_rtc		= common_init_rtc,
	.init_pci		= common_init_pci,
	.kill_arch		= NULL,
	.pci_map_irq		= eb64p_map_irq,
	.pci_swizzle		= common_swizzle,
};
ALIAS_MV(eb64p)
#endif

#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB66)
struct alpha_machine_vector eb66_mv __initmv = {
	.vector_name		= "EB66",
	DO_EV4_MMU,
	DO_DEFAULT_RTC,
	DO_LCA_IO,
	.machine_check		= lca_machine_check,
	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
	.min_io_address		= DEFAULT_IO_BASE,
	.min_mem_address	= APECS_AND_LCA_DEFAULT_MEM_BASE,

	.nr_irqs		= 32,
	.device_interrupt	= eb64p_device_interrupt,

	.init_arch		= lca_init_arch,
	.init_irq		= eb64p_init_irq,
	.init_rtc		= common_init_rtc,
	.init_pci		= common_init_pci,
	.pci_map_irq		= eb64p_map_irq,
	.pci_swizzle		= common_swizzle,
};
ALIAS_MV(eb66)
#endif


code:
// SPDX-License-Identifier: GPL-2.0
/*
 *	linux/arch/alpha/kernel/sys_eiger.c
 *
 *	Copyright (C) 1995 David A Rusling
 *	Copyright (C) 1996, 1999 Jay A Estabrook
 *	Copyright (C) 1998, 1999 Richard Henderson
 *	Copyright (C) 1999 Iain Grant
 *
 * Code supporting the EIGER (EV6+TSUNAMI).
 */

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/bitops.h>

#include <asm/ptrace.h>
#include <asm/dma.h>
#include <asm/irq.h>
#include <asm/mmu_context.h>
#include <asm/io.h>
#include <asm/core_tsunami.h>
#include <asm/hwrpb.h>
#include <asm/tlbflush.h>

#include "proto.h"
#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"

/* Note that this interrupt code is identical to TAKARA.  */

/* Note mask bit is true for DISABLED irqs.  */
static unsigned long cached_irq_mask[2] = { -1, -1 };

static inline void
eiger_update_irq_hw(unsigned long irq, unsigned long mask)
{
	int regaddr;

	mask = (irq >= 64 ? mask << 16 : mask >> ((irq - 16) & 0x30));
	regaddr = 0x510 + (((irq - 16) >> 2) & 0x0c);
	outl(mask & 0xffff0000UL, regaddr);
}

static inline void
eiger_enable_irq(struct irq_data *d)
{
	unsigned int irq = d->irq;
	unsigned long mask;
	mask = (cached_irq_mask[irq >= 64] &= ~(1UL << (irq & 63)));
	eiger_update_irq_hw(irq, mask);
}

static void
eiger_disable_irq(struct irq_data *d)
{
	unsigned int irq = d->irq;
	unsigned long mask;
	mask = (cached_irq_mask[irq >= 64] |= 1UL << (irq & 63));
	eiger_update_irq_hw(irq, mask);
}

static struct irq_chip eiger_irq_type = {
	.name		= "EIGER",
	.irq_unmask	= eiger_enable_irq,
	.irq_mask	= eiger_disable_irq,
	.irq_mask_ack	= eiger_disable_irq,
};

static void
eiger_device_interrupt(unsigned long vector)
{
	unsigned intstatus;

	/*
	 * The PALcode will have passed us vectors 0x800 or 0x810,
	 * which are fairly arbitrary values and serve only to tell
	 * us whether an interrupt has come in on IRQ0 or IRQ1. If
	 * it's IRQ1 it's a PCI interrupt; if it's IRQ0, it's
	 * probably ISA, but PCI interrupts can come through IRQ0
	 * as well if the interrupt controller isn't in accelerated
	 * mode.
	 *
	 * OTOH, the accelerator thing doesn't seem to be working
	 * overly well, so what we'll do instead is try directly
	 * examining the Master Interrupt Register to see if it's a
	 * PCI interrupt, and if _not_ then we'll pass it on to the
	 * ISA handler.
	 */

	intstatus = inw(0x500) & 15;
	if (intstatus) {
		/*
		 * This is a PCI interrupt. Check each bit and
		 * despatch an interrupt if it's set.
		 */

		if (intstatus & 8) handle_irq(16+3);
		if (intstatus & 4) handle_irq(16+2);
		if (intstatus & 2) handle_irq(16+1);
		if (intstatus & 1) handle_irq(16+0);
	} else {
		isa_device_interrupt(vector);
	}
}

static void
eiger_srm_device_interrupt(unsigned long vector)
{
	int irq = (vector - 0x800) >> 4;
	handle_irq(irq);
}

static void __init
eiger_init_irq(void)
{
	long i;

	outb(0, DMA1_RESET_REG);
	outb(0, DMA2_RESET_REG);
	outb(DMA_MODE_CASCADE, DMA2_MODE_REG);
	outb(0, DMA2_MASK_REG);

	if (alpha_using_srm)
		alpha_mv.device_interrupt = eiger_srm_device_interrupt;

	for (i = 16; i < 128; i += 16)
		eiger_update_irq_hw(i, -1);

	init_i8259a_irqs();

	for (i = 16; i < 128; ++i) {
		irq_set_chip_and_handler(i, &eiger_irq_type, handle_level_irq);
		irq_set_status_flags(i, IRQ_LEVEL);
	}
}

static int
eiger_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
	u8 irq_orig;

	/* The SRM console has already calculated out the IRQ value's for
	   option cards. As this works lets just read in the value already
	   set and change it to a useable value by Linux.

	   All the IRQ values generated by the console are greater than 90,
	   so we subtract 80 because it is (90 - allocated ISA IRQ's).  */

	pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq_orig);

	return irq_orig - 0x80;
}

static u8
eiger_swizzle(struct pci_dev *dev, u8 *pinp)
{
	struct pci_controller *hose = dev->sysdata;
	int slot, pin = *pinp;
	int bridge_count = 0;

	/* Find the number of backplane bridges.  */
	int backplane = inw(0x502) & 0x0f;

	switch (backplane)
	{
	   case 0x00: bridge_count = 0; break; /* No bridges */
	   case 0x01: bridge_count = 1; break; /* 1 */
	   case 0x03: bridge_count = 2; break; /* 2 */
	   case 0x07: bridge_count = 3; break; /* 3 */
	   case 0x0f: bridge_count = 4; break; /* 4 */
	}

	slot = PCI_SLOT(dev->devfn);
	while (dev->bus->self) {
		/* Check for built-in bridges on hose 0. */
		if (hose->index == 0
		    && (PCI_SLOT(dev->bus->self->devfn)
			> 20 - bridge_count)) {
			slot = PCI_SLOT(dev->devfn);
			break;
		}
		/* Must be a card-based bridge.  */
		pin = pci_swizzle_interrupt_pin(dev, pin);

		/* Move up the chain of bridges.  */
		dev = dev->bus->self;
	}
	*pinp = pin;
	return slot;
}

/*
 * The System Vectors
 */

struct alpha_machine_vector eiger_mv __initmv = {
	.vector_name		= "Eiger",
	DO_EV6_MMU,
	DO_DEFAULT_RTC,
	DO_TSUNAMI_IO,
	.machine_check		= tsunami_machine_check,
	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
	.min_io_address		= DEFAULT_IO_BASE,
	.min_mem_address	= DEFAULT_MEM_BASE,
	.pci_dac_offset		= TSUNAMI_DAC_OFFSET,

	.nr_irqs		= 128,
	.device_interrupt	= eiger_device_interrupt,

	.init_arch		= tsunami_init_arch,
	.init_irq		= eiger_init_irq,
	.init_rtc		= common_init_rtc,
	.init_pci		= common_init_pci,
	.kill_arch		= tsunami_kill_arch,
	.pci_map_irq		= eiger_map_irq,
	.pci_swizzle		= eiger_swizzle,
};
ALIAS_MV(eiger)


code:
// SPDX-License-Identifier: GPL-2.0
/*
 *	linux/arch/alpha/kernel/sys_jensen.c
 *
 *	Copyright (C) 1995 Linus Torvalds
 *	Copyright (C) 1998, 1999 Richard Henderson
 *
 * Code supporting the Jensen.
 */
#define __EXTERN_INLINE
#include <asm/io.h>
#include <asm/jensen.h>
#undef  __EXTERN_INLINE

#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/init.h>

#include <asm/ptrace.h>

#include <asm/dma.h>
#include <asm/irq.h>
#include <asm/mmu_context.h>
#include <asm/tlbflush.h>

#include "proto.h"
#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"

/*
 * Jensen is special: the vector is 0x8X0 for EISA interrupt X, and
 * 0x9X0 for the local motherboard interrupts.
 *
 * Note especially that those local interrupts CANNOT be masked,
 * which causes much of the pain below...
 *
 *	0x660 - NMI
 *
 *	0x800 - IRQ0  interval timer (not used, as we use the RTC timer)
 *	0x810 - IRQ1  line printer (duh..)
 *	0x860 - IRQ6  floppy disk
 *
 *	0x900 - COM1
 *	0x920 - COM2
 *	0x980 - keyboard
 *	0x990 - mouse
 *
 * PCI-based systems are more sane: they don't have the local
 * interrupts at all, and have only normal PCI interrupts from
 * devices.  Happily it's easy enough to do a sane mapping from the
 * Jensen.
 *
 * Note that this means that we may have to do a hardware
 * "local_op" to a different interrupt than we report to the rest of the
 * world.
 */

static void
jensen_local_enable(struct irq_data *d)
{
	/* the parport is really hw IRQ 1, silly Jensen.  */
	if (d->irq == 7)
		i8259a_enable_irq(d);
}

static void
jensen_local_disable(struct irq_data *d)
{
	/* the parport is really hw IRQ 1, silly Jensen.  */
	if (d->irq == 7)
		i8259a_disable_irq(d);
}

static void
jensen_local_mask_ack(struct irq_data *d)
{
	/* the parport is really hw IRQ 1, silly Jensen.  */
	if (d->irq == 7)
		i8259a_mask_and_ack_irq(d);
}

static struct irq_chip jensen_local_irq_type = {
	.name		= "LOCAL",
	.irq_unmask	= jensen_local_enable,
	.irq_mask	= jensen_local_disable,
	.irq_mask_ack	= jensen_local_mask_ack,
};

static void
jensen_device_interrupt(unsigned long vector)
{
	int irq;

	switch (vector) {
	case 0x660:
		printk("Whee.. NMI received. Probable hardware error\n");
		printk("61=%02x, 461=%02x\n", inb(0x61), inb(0x461));
		return;

	/* local device interrupts: */
	case 0x900: irq = 4; break;		/* com1 -> irq 4 */
	case 0x920: irq = 3; break;		/* com2 -> irq 3 */
	case 0x980: irq = 1; break;		/* kbd -> irq 1 */
	case 0x990: irq = 9; break;		/* mouse -> irq 9 */

	default:
		if (vector > 0x900) {
			printk("Unknown local interrupt %lx\n", vector);
			return;
		}

		irq = (vector - 0x800) >> 4;
		if (irq == 1)
			irq = 7;
		break;
	}

	/* If there is no handler yet... */
	if (!irq_has_action(irq)) {
	    /* If it is a local interrupt that cannot be masked... */
	    if (vector >= 0x900)
	    {
	        /* Clear keyboard/mouse state */
	    	inb(0x64);
		inb(0x60);
		/* Reset serial ports */
		inb(0x3fa);
		inb(0x2fa);
		outb(0x0c, 0x3fc);
		outb(0x0c, 0x2fc);
		/* Clear NMI */
		outb(0,0x61);
		outb(0,0x461);
	    }
	}

#if 0
        /* A useful bit of code to find out if an interrupt is going wild.  */
        {
          static unsigned int last_msg = 0, last_cc = 0;
          static int last_irq = -1, count = 0;
          unsigned int cc;

          __asm __volatile("rpcc %0" : "=r"(cc));
          ++count;
#define JENSEN_CYCLES_PER_SEC	(150000000)
          if (cc - last_msg > ((JENSEN_CYCLES_PER_SEC) * 3) ||
	      irq != last_irq) {
                printk(KERN_CRIT " irq %d count %d cc %u @ %lx\n",
                       irq, count, cc-last_cc, get_irq_regs()->pc);
                count = 0;
                last_msg = cc;
                last_irq = irq;
          }
          last_cc = cc;
        }
#endif

	handle_irq(irq);
}

static void __init
jensen_init_irq(void)
{
	init_i8259a_irqs();

	irq_set_chip_and_handler(1, &jensen_local_irq_type, handle_level_irq);
	irq_set_chip_and_handler(4, &jensen_local_irq_type, handle_level_irq);
	irq_set_chip_and_handler(3, &jensen_local_irq_type, handle_level_irq);
	irq_set_chip_and_handler(7, &jensen_local_irq_type, handle_level_irq);
	irq_set_chip_and_handler(9, &jensen_local_irq_type, handle_level_irq);

	common_init_isa_dma();
}

static void __init
jensen_init_arch(void)
{
	struct pci_controller *hose;
#ifdef CONFIG_PCI
	static struct pci_dev fake_isa_bridge = { .dma_mask = 0xffffffffUL, };

	isa_bridge = &fake_isa_bridge;
#endif

	/* Create a hose so that we can report i/o base addresses to
	   userland.  */

	pci_isa_hose = hose = alloc_pci_controller();
	hose->io_space = &ioport_resource;
	hose->mem_space = &iomem_resource;
	hose->index = 0;

	hose->sparse_mem_base = EISA_MEM - IDENT_ADDR;
	hose->dense_mem_base = 0;
	hose->sparse_io_base = EISA_IO - IDENT_ADDR;
	hose->dense_io_base = 0;

	hose->sg_isa = hose->sg_pci = NULL;
	__direct_map_base = 0;
	__direct_map_size = 0xffffffff;
}

static void
jensen_machine_check(unsigned long vector, unsigned long la)
{
	printk(KERN_CRIT "Machine check\n");
}

/*
 * The System Vector
 */

struct alpha_machine_vector jensen_mv __initmv = {
	.vector_name		= "Jensen",
	DO_EV4_MMU,
	IO_LITE(JENSEN,jensen),
	.machine_check		= jensen_machine_check,
	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
	.rtc_port		= 0x170,

	.nr_irqs		= 16,
	.device_interrupt	= jensen_device_interrupt,

	.init_arch		= jensen_init_arch,
	.init_irq		= jensen_init_irq,
	.init_rtc		= common_init_rtc,
	.init_pci		= NULL,
	.kill_arch		= NULL,
};
ALIAS_MV(jensen)


code:
// SPDX-License-Identifier: GPL-2.0
/*
 * linux/arch/alpha/kernel/sys_marvel.c
 *
 * Marvel / IO7 support
 */

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/bitops.h>

#include <asm/ptrace.h>
#include <asm/dma.h>
#include <asm/irq.h>
#include <asm/mmu_context.h>
#include <asm/io.h>
#include <asm/core_marvel.h>
#include <asm/hwrpb.h>
#include <asm/tlbflush.h>
#include <asm/vga.h>

#include "proto.h"
#include "err_impl.h"
#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"

#if NR_IRQS < MARVEL_NR_IRQS
# error NR_IRQS < MARVEL_NR_IRQS !!!
#endif

/*
 * Interrupt handling.
 */
static void
io7_device_interrupt(unsigned long vector)
{
	unsigned int pid;
	unsigned int irq;

	/*
	 * Vector is 0x800 + (interrupt)
	 *
	 * where (interrupt) is:
	 *
	 *	...16|15 14|13     4|3 0
	 *	-----+-----+--------+---
	 *	  PE |  0  |   irq  | 0
	 *
	 * where (irq) is
	 *
	 *       0x0800 - 0x0ff0	 - 0x0800 + (LSI id << 4)
	 *	 0x1000 - 0x2ff0	 - 0x1000 + (MSI_DAT<8:0> << 4)
	 */
	pid = vector >> 16;
	irq = ((vector & 0xffff) - 0x800) >> 4;

	irq += 16;				/* offset for legacy */
	irq &= MARVEL_IRQ_VEC_IRQ_MASK;		/* not too many bits */
	irq |= pid << MARVEL_IRQ_VEC_PE_SHIFT;	/* merge the pid     */

	handle_irq(irq);
}

static volatile unsigned long *
io7_get_irq_ctl(unsigned int irq, struct io7 **pio7)
{
	volatile unsigned long *ctl;
	unsigned int pid;
	struct io7 *io7;

	pid = irq >> MARVEL_IRQ_VEC_PE_SHIFT;

	if (!(io7 = marvel_find_io7(pid))) {
		printk(KERN_ERR
		       "%s for nonexistent io7 -- vec %x, pid %d\n",
		       __func__, irq, pid);
		return NULL;
	}

	irq &= MARVEL_IRQ_VEC_IRQ_MASK;	/* isolate the vector    */
	irq -= 16;			/* subtract legacy bias  */

	if (irq >= 0x180) {
		printk(KERN_ERR
		       "%s for invalid irq -- pid %d adjusted irq %x\n",
		       __func__, pid, irq);
		return NULL;
	}

	ctl = &io7->csrs->PO7_LSI_CTL[irq & 0xff].csr; /* assume LSI */
	if (irq >= 0x80)	     	/* MSI */
		ctl = &io7->csrs->PO7_MSI_CTL[((irq - 0x80) >> 5) & 0x0f].csr;

	if (pio7) *pio7 = io7;
	return ctl;
}

static void
io7_enable_irq(struct irq_data *d)
{
	volatile unsigned long *ctl;
	unsigned int irq = d->irq;
	struct io7 *io7;

	ctl = io7_get_irq_ctl(irq, &io7);
	if (!ctl || !io7) {
		printk(KERN_ERR "%s: get_ctl failed for irq %x\n",
		       __func__, irq);
		return;
	}

	raw_spin_lock(&io7->irq_lock);
	*ctl |= 1UL << 24;
	mb();
	*ctl;
	raw_spin_unlock(&io7->irq_lock);
}

static void
io7_disable_irq(struct irq_data *d)
{
	volatile unsigned long *ctl;
	unsigned int irq = d->irq;
	struct io7 *io7;

	ctl = io7_get_irq_ctl(irq, &io7);
	if (!ctl || !io7) {
		printk(KERN_ERR "%s: get_ctl failed for irq %x\n",
		       __func__, irq);
		return;
	}

	raw_spin_lock(&io7->irq_lock);
	*ctl &= ~(1UL << 24);
	mb();
	*ctl;
	raw_spin_unlock(&io7->irq_lock);
}

static void
marvel_irq_noop(struct irq_data *d)
{
	return;
}

static struct irq_chip marvel_legacy_irq_type = {
	.name		= "LEGACY",
	.irq_mask	= marvel_irq_noop,
	.irq_unmask	= marvel_irq_noop,
};

static struct irq_chip io7_lsi_irq_type = {
	.name		= "LSI",
	.irq_unmask	= io7_enable_irq,
	.irq_mask	= io7_disable_irq,
	.irq_mask_ack	= io7_disable_irq,
};

static struct irq_chip io7_msi_irq_type = {
	.name		= "MSI",
	.irq_unmask	= io7_enable_irq,
	.irq_mask	= io7_disable_irq,
	.irq_ack	= marvel_irq_noop,
};

static void
io7_redirect_irq(struct io7 *io7,
		 volatile unsigned long *csr,
		 unsigned int where)
{
	unsigned long val;

	val = *csr;
	val &= ~(0x1ffUL << 24);		/* clear the target pid   */
	val |= ((unsigned long)where << 24);	/* set the new target pid */

	*csr = val;
	mb();
	*csr;
}

static void
io7_redirect_one_lsi(struct io7 *io7, unsigned int which, unsigned int where)
{
	unsigned long val;

	/*
	 * LSI_CTL has target PID @ 14
	 */
	val = io7->csrs->PO7_LSI_CTL[which].csr;
	val &= ~(0x1ffUL << 14);		/* clear the target pid */
	val |= ((unsigned long)where << 14);	/* set the new target pid */

	io7->csrs->PO7_LSI_CTL[which].csr = val;
	mb();
	io7->csrs->PO7_LSI_CTL[which].csr;
}

static void
io7_redirect_one_msi(struct io7 *io7, unsigned int which, unsigned int where)
{
	unsigned long val;

	/*
	 * MSI_CTL has target PID @ 14
	 */
	val = io7->csrs->PO7_MSI_CTL[which].csr;
	val &= ~(0x1ffUL << 14);		/* clear the target pid */
	val |= ((unsigned long)where << 14);	/* set the new target pid */

	io7->csrs->PO7_MSI_CTL[which].csr = val;
	mb();
	io7->csrs->PO7_MSI_CTL[which].csr;
}

static void __init
init_one_io7_lsi(struct io7 *io7, unsigned int which, unsigned int where)
{
	/*
	 * LSI_CTL has target PID @ 14
	 */
	io7->csrs->PO7_LSI_CTL[which].csr = ((unsigned long)where << 14);
	mb();
	io7->csrs->PO7_LSI_CTL[which].csr;
}

static void __init
init_one_io7_msi(struct io7 *io7, unsigned int which, unsigned int where)
{
	/*
	 * MSI_CTL has target PID @ 14
	 */
	io7->csrs->PO7_MSI_CTL[which].csr = ((unsigned long)where << 14);
	mb();
	io7->csrs->PO7_MSI_CTL[which].csr;
}

static void __init
init_io7_irqs(struct io7 *io7,
	      struct irq_chip *lsi_ops,
	      struct irq_chip *msi_ops)
{
	long base = (io7->pe << MARVEL_IRQ_VEC_PE_SHIFT) + 16;
	long i;

	printk("Initializing interrupts for IO7 at PE %u - base %lx\n",
		io7->pe, base);

	/*
	 * Where should interrupts from this IO7 go?
	 *
	 * They really should be sent to the local CPU to avoid having to
	 * traverse the mesh, but if it's not an SMP kernel, they have to
	 * go to the boot CPU. Send them all to the boot CPU for now,
	 * as each secondary starts, it can redirect it's local device
	 * interrupts.
	 */
	printk("  Interrupts reported to CPU at PE %u\n", boot_cpuid);

	raw_spin_lock(&io7->irq_lock);

	/* set up the error irqs */
	io7_redirect_irq(io7, &io7->csrs->HLT_CTL.csr, boot_cpuid);
	io7_redirect_irq(io7, &io7->csrs->HPI_CTL.csr, boot_cpuid);
	io7_redirect_irq(io7, &io7->csrs->CRD_CTL.csr, boot_cpuid);
	io7_redirect_irq(io7, &io7->csrs->STV_CTL.csr, boot_cpuid);
	io7_redirect_irq(io7, &io7->csrs->HEI_CTL.csr, boot_cpuid);

	/* Set up the lsi irqs.  */
	for (i = 0; i < 128; ++i) {
		irq_set_chip_and_handler(base + i, lsi_ops, handle_level_irq);
		irq_set_status_flags(i, IRQ_LEVEL);
	}

	/* Disable the implemented irqs in hardware.  */
	for (i = 0; i < 0x60; ++i)
		init_one_io7_lsi(io7, i, boot_cpuid);

	init_one_io7_lsi(io7, 0x74, boot_cpuid);
	init_one_io7_lsi(io7, 0x75, boot_cpuid);

	/* Set up the msi irqs.  */
	for (i = 128; i < (128 + 512); ++i) {
		irq_set_chip_and_handler(base + i, msi_ops, handle_level_irq);
		irq_set_status_flags(i, IRQ_LEVEL);
	}

	for (i = 0; i < 16; ++i)
		init_one_io7_msi(io7, i, boot_cpuid);

	raw_spin_unlock(&io7->irq_lock);
}

static void __init
marvel_init_irq(void)
{
	int i;
	struct io7 *io7 = NULL;

	/* Reserve the legacy irqs.  */
	for (i = 0; i < 16; ++i) {
		irq_set_chip_and_handler(i, &marvel_legacy_irq_type,
					 handle_level_irq);
	}

	/* Init the io7 irqs.  */
	for (io7 = NULL; (io7 = marvel_next_io7(io7)) != NULL; )
		init_io7_irqs(io7, &io7_lsi_irq_type, &io7_msi_irq_type);
}

static int
marvel_map_irq(const struct pci_dev *cdev, u8 slot, u8 pin)
{
	struct pci_dev *dev = (struct pci_dev *)cdev;
	struct pci_controller *hose = dev->sysdata;
	struct io7_port *io7_port = hose->sysdata;
	struct io7 *io7 = io7_port->io7;
	int msi_loc, msi_data_off;
	u16 msg_ctl;
	u16 msg_dat;
	u8 intline;
	int irq;

	pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &intline);
	irq = intline;

	msi_loc = dev->msi_cap;
	msg_ctl = 0;
	if (msi_loc)
		pci_read_config_word(dev, msi_loc + PCI_MSI_FLAGS, &msg_ctl);

	if (msg_ctl & PCI_MSI_FLAGS_ENABLE) {
 		msi_data_off = PCI_MSI_DATA_32;
		if (msg_ctl & PCI_MSI_FLAGS_64BIT)
			msi_data_off = PCI_MSI_DATA_64;
		pci_read_config_word(dev, msi_loc + msi_data_off, &msg_dat);

		irq = msg_dat & 0x1ff;		/* we use msg_data<8:0> */
		irq += 0x80;			/* offset for lsi       */

#if 1
		printk("PCI:%d:%d:%d (hose %d) is using MSI\n",
		       dev->bus->number,
		       PCI_SLOT(dev->devfn),
		       PCI_FUNC(dev->devfn),
		       hose->index);
		printk("  %d message(s) from 0x%04x\n",
		       1 << ((msg_ctl & PCI_MSI_FLAGS_QSIZE) >> 4),
		       msg_dat);
		printk("  reporting on %d IRQ(s) from %d (0x%x)\n",
		       1 << ((msg_ctl & PCI_MSI_FLAGS_QSIZE) >> 4),
		       (irq + 16) | (io7->pe << MARVEL_IRQ_VEC_PE_SHIFT),
		       (irq + 16) | (io7->pe << MARVEL_IRQ_VEC_PE_SHIFT));
#endif

#if 0
		pci_write_config_word(dev, msi_loc + PCI_MSI_FLAGS,
				      msg_ctl & ~PCI_MSI_FLAGS_ENABLE);
		pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &intline);
		irq = intline;

		printk("  forcing LSI interrupt on irq %d [0x%x]\n", irq, irq);
#endif
	}

	irq += 16;					/* offset for legacy */
	irq |= io7->pe << MARVEL_IRQ_VEC_PE_SHIFT;	/* merge the pid     */

	return irq;
}

static void __init
marvel_init_pci(void)
{
	struct io7 *io7;

	marvel_register_error_handlers();

	/* Indicate that we trust the console to configure things properly */
	pci_set_flags(PCI_PROBE_ONLY);
	common_init_pci();
	locate_and_init_vga(NULL);

	/* Clear any io7 errors.  */
	for (io7 = NULL; (io7 = marvel_next_io7(io7)) != NULL; )
		io7_clear_errors(io7);
}

static void __init
marvel_init_rtc(void)
{
	init_rtc_irq(NULL);
}

static void
marvel_smp_callin(void)
{
	int cpuid = hard_smp_processor_id();
	struct io7 *io7 = marvel_find_io7(cpuid);
	unsigned int i;

	if (!io7)
		return;

	/*
	 * There is a local IO7 - redirect all of its interrupts here.
	 */
	printk("Redirecting IO7 interrupts to local CPU at PE %u\n", cpuid);

	/* Redirect the error IRQS here.  */
	io7_redirect_irq(io7, &io7->csrs->HLT_CTL.csr, cpuid);
	io7_redirect_irq(io7, &io7->csrs->HPI_CTL.csr, cpuid);
	io7_redirect_irq(io7, &io7->csrs->CRD_CTL.csr, cpuid);
	io7_redirect_irq(io7, &io7->csrs->STV_CTL.csr, cpuid);
	io7_redirect_irq(io7, &io7->csrs->HEI_CTL.csr, cpuid);

	/* Redirect the implemented LSIs here.  */
	for (i = 0; i < 0x60; ++i)
		io7_redirect_one_lsi(io7, i, cpuid);

	io7_redirect_one_lsi(io7, 0x74, cpuid);
	io7_redirect_one_lsi(io7, 0x75, cpuid);

	/* Redirect the MSIs here.  */
	for (i = 0; i < 16; ++i)
		io7_redirect_one_msi(io7, i, cpuid);
}

/*
 * System Vectors
 */
struct alpha_machine_vector marvel_ev7_mv __initmv = {
	.vector_name		= "MARVEL/EV7",
	DO_EV7_MMU,
	.rtc_port		= 0x70,
	.rtc_boot_cpu_only	= 1,
	DO_MARVEL_IO,
	.machine_check		= marvel_machine_check,
	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
	.min_io_address		= DEFAULT_IO_BASE,
	.min_mem_address	= DEFAULT_MEM_BASE,
	.pci_dac_offset		= IO7_DAC_OFFSET,

	.nr_irqs		= MARVEL_NR_IRQS,
	.device_interrupt	= io7_device_interrupt,

	.agp_info		= marvel_agp_info,

	.smp_callin		= marvel_smp_callin,
	.init_arch		= marvel_init_arch,
	.init_irq		= marvel_init_irq,
	.init_rtc		= marvel_init_rtc,
	.init_pci		= marvel_init_pci,
	.kill_arch		= marvel_kill_arch,
	.pci_map_irq		= marvel_map_irq,
	.pci_swizzle		= common_swizzle,
};
ALIAS_MV(marvel_ev7)


code:
// SPDX-License-Identifier: GPL-2.0
/*
 *	linux/arch/alpha/kernel/sys_miata.c
 *
 *	Copyright (C) 1995 David A Rusling
 *	Copyright (C) 1996 Jay A Estabrook
 *	Copyright (C) 1998, 1999, 2000 Richard Henderson
 *
 * Code supporting the MIATA (EV56+PYXIS).
 */

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/reboot.h>

#include <asm/ptrace.h>
#include <asm/dma.h>
#include <asm/irq.h>
#include <asm/mmu_context.h>
#include <asm/io.h>
#include <asm/core_cia.h>
#include <asm/tlbflush.h>

#include "proto.h"
#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"

static void
miata_srm_device_interrupt(unsigned long vector)
{
	int irq;

	irq = (vector - 0x800) >> 4;

	/*
	 * I really hate to do this, but the MIATA SRM console ignores the
	 *  low 8 bits in the interrupt summary register, and reports the
	 *  vector 0x80 *lower* than I expected from the bit numbering in
	 *  the documentation.
	 * This was done because the low 8 summary bits really aren't used
	 *  for reporting any interrupts (the PCI-ISA bridge, bit 7, isn't
	 *  used for this purpose, as PIC interrupts are delivered as the
	 *  vectors 0x800-0x8f0).
	 * But I really don't want to change the fixup code for allocation
	 *  of IRQs, nor the alpha_irq_mask maintenance stuff, both of which
	 *  look nice and clean now.
	 * So, here's this grotty hack... :-(
	 */
	if (irq >= 16)
		irq = irq + 8;

	handle_irq(irq);
}

static void __init
miata_init_irq(void)
{
	if (alpha_using_srm)
		alpha_mv.device_interrupt = miata_srm_device_interrupt;

#if 0
	/* These break on MiataGL so we'll try not to do it at all.  */
	*(vulp)PYXIS_INT_HILO = 0x000000B2UL; mb();	/* ISA/NMI HI */
	*(vulp)PYXIS_RT_COUNT = 0UL; mb();		/* clear count */
#endif

	init_i8259a_irqs();

	/* Not interested in the bogus interrupts (3,10), Fan Fault (0),
           NMI (1), or EIDE (9).

	   We also disable the risers (4,5), since we don't know how to
	   route the interrupts behind the bridge.  */
	init_pyxis_irqs(0x63b0000);

	common_init_isa_dma();
	if (request_irq(16 + 2, no_action, 0, "halt-switch", NULL))
		pr_err("Failed to register halt-switch interrupt\n");
	if (request_irq(16 + 6, no_action, 0, "timer-cascade", NULL))
		pr_err("Failed to register timer-cascade interrupt\n");
}

/*
 * PCI Fixup configuration.
 *
 * Summary @ PYXIS_INT_REQ:
 * Bit      Meaning
 * 0        Fan Fault
 * 1        NMI
 * 2        Halt/Reset switch
 * 3        none
 * 4        CID0 (Riser ID)
 * 5        CID1 (Riser ID)
 * 6        Interval timer
 * 7        PCI-ISA Bridge
 * 8        Ethernet
 * 9        EIDE (deprecated, ISA 14/15 used)
 *10        none
 *11        USB
 *12        Interrupt Line A from slot 4
 *13        Interrupt Line B from slot 4
 *14        Interrupt Line C from slot 4
 *15        Interrupt Line D from slot 4
 *16        Interrupt Line A from slot 5
 *17        Interrupt line B from slot 5
 *18        Interrupt Line C from slot 5
 *19        Interrupt Line D from slot 5
 *20        Interrupt Line A from slot 1
 *21        Interrupt Line B from slot 1
 *22        Interrupt Line C from slot 1
 *23        Interrupt Line D from slot 1
 *24        Interrupt Line A from slot 2
 *25        Interrupt Line B from slot 2
 *26        Interrupt Line C from slot 2
 *27        Interrupt Line D from slot 2
 *27        Interrupt Line A from slot 3
 *29        Interrupt Line B from slot 3
 *30        Interrupt Line C from slot 3
 *31        Interrupt Line D from slot 3
 *
 * The device to slot mapping looks like:
 *
 * Slot     Device
 *  3       DC21142 Ethernet
 *  4       EIDE CMD646
 *  5       none
 *  6       USB
 *  7       PCI-ISA bridge
 *  8       PCI-PCI Bridge      (SBU Riser)
 *  9       none
 * 10       none
 * 11       PCI on board slot 4 (SBU Riser)
 * 12       PCI on board slot 5 (SBU Riser)
 *
 *  These are behind the bridge, so I'm not sure what to do...
 *
 * 13       PCI on board slot 1 (SBU Riser)
 * 14       PCI on board slot 2 (SBU Riser)
 * 15       PCI on board slot 3 (SBU Riser)
 *
 *
 * This two layered interrupt approach means that we allocate IRQ 16 and
 * above for PCI interrupts.  The IRQ relates to which bit the interrupt
 * comes in on.  This makes interrupt processing much easier.
 */

static int
miata_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
        static char irq_tab[18][5] = {
		/*INT    INTA   INTB   INTC   INTD */
		{16+ 8, 16+ 8, 16+ 8, 16+ 8, 16+ 8},  /* IdSel 14,  DC21142 */
		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 15,  EIDE    */
		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 16,  none    */
		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 17,  none    */
		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 18,  PCI-ISA */
		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 19,  PCI-PCI */
		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 20,  none    */
		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 21,  none    */
		{16+12, 16+12, 16+13, 16+14, 16+15},  /* IdSel 22,  slot 4  */
		{16+16, 16+16, 16+17, 16+18, 16+19},  /* IdSel 23,  slot 5  */
		/* the next 7 are actually on PCI bus 1, across the bridge */
		{16+11, 16+11, 16+11, 16+11, 16+11},  /* IdSel 24,  QLISP/GL*/
		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 25,  none    */
		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 26,  none    */
		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 27,  none    */
		{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 orig MIATA */
		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 31,  PCI-PCI */
        };
	const long min_idsel = 3, max_idsel = 20, irqs_per_slot = 5;

	/* the USB function of the 82c693 has it's interrupt connected to
           the 2nd 8259 controller. So we have to check for it first. */

	if((slot == 7) && (PCI_FUNC(dev->devfn) == 3)) {
		u8 irq=0;
		struct pci_dev *pdev = pci_get_slot(dev->bus, dev->devfn & ~7);
		if(pdev == NULL || pci_read_config_byte(pdev, 0x40,&irq) != PCIBIOS_SUCCESSFUL) {
			pci_dev_put(pdev);
			return -1;
		}
		else	{
			pci_dev_put(pdev);
			return irq;
		}
	}

	return COMMON_TABLE_LOOKUP;
}

static u8
miata_swizzle(struct pci_dev *dev, u8 *pinp)
{
	int slot, pin = *pinp;

	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
	{
		/* Must be a card-based bridge.  */
		do {
			if ((PCI_SLOT(dev->bus->self->devfn) == 8) ||
			    (PCI_SLOT(dev->bus->self->devfn) == 20)) {
				slot = PCI_SLOT(dev->devfn) + 9;
				break;
			}
			pin = pci_swizzle_interrupt_pin(dev, pin);

			/* Move up the chain of bridges.  */
			dev = dev->bus->self;
			/* Slot of the next bridge.  */
			slot = PCI_SLOT(dev->devfn);
		} while (dev->bus->self);
	}
	*pinp = pin;
	return slot;
}

static void __init
miata_init_pci(void)
{
	cia_init_pci();
	SMC669_Init(0); /* it might be a GL (fails harmlessly if not) */
	es1888_init();
}

static void
miata_kill_arch(int mode)
{
	cia_kill_arch(mode);

#ifndef ALPHA_RESTORE_SRM_SETUP
	switch(mode) {
	case LINUX_REBOOT_CMD_RESTART:
		/* Who said DEC engineers have no sense of humor? ;-)  */
		if (alpha_using_srm) {
			*(vuip) PYXIS_RESET = 0x0000dead;
			mb();
		}
		break;
	case LINUX_REBOOT_CMD_HALT:
		break;
	case LINUX_REBOOT_CMD_POWER_OFF:
		break;
	}

	halt();
#endif
}

/*
 * The System Vector
 */

struct alpha_machine_vector miata_mv __initmv = {
	.vector_name		= "Miata",
	DO_EV5_MMU,
	DO_DEFAULT_RTC,
	DO_PYXIS_IO,
	.machine_check		= cia_machine_check,
	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
	.min_io_address		= DEFAULT_IO_BASE,
	.min_mem_address	= DEFAULT_MEM_BASE,
	.pci_dac_offset		= PYXIS_DAC_OFFSET,

	.nr_irqs		= 48,
	.device_interrupt	= pyxis_device_interrupt,

	.init_arch		= pyxis_init_arch,
	.init_irq		= miata_init_irq,
	.init_rtc		= common_init_rtc,
	.init_pci		= miata_init_pci,
	.kill_arch		= miata_kill_arch,
	.pci_map_irq		= miata_map_irq,
	.pci_swizzle		= miata_swizzle,
};
ALIAS_MV(miata)


code:
// SPDX-License-Identifier: GPL-2.0
/*
 *	linux/arch/alpha/kernel/sys_mikasa.c
 *
 *	Copyright (C) 1995 David A Rusling
 *	Copyright (C) 1996 Jay A Estabrook
 *	Copyright (C) 1998, 1999 Richard Henderson
 *
 * Code supporting the MIKASA (AlphaServer 1000).
 */

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/bitops.h>

#include <asm/ptrace.h>
#include <asm/mce.h>
#include <asm/dma.h>
#include <asm/irq.h>
#include <asm/mmu_context.h>
#include <asm/io.h>
#include <asm/core_apecs.h>
#include <asm/core_cia.h>
#include <asm/tlbflush.h>

#include "proto.h"
#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"

/* Note mask bit is true for ENABLED irqs.  */
static int cached_irq_mask;

static inline void
mikasa_update_irq_hw(int mask)
{
	outw(mask, 0x536);
}

static inline void
mikasa_enable_irq(struct irq_data *d)
{
	mikasa_update_irq_hw(cached_irq_mask |= 1 << (d->irq - 16));
}

static void
mikasa_disable_irq(struct irq_data *d)
{
	mikasa_update_irq_hw(cached_irq_mask &= ~(1 << (d->irq - 16)));
}

static struct irq_chip mikasa_irq_type = {
	.name		= "MIKASA",
	.irq_unmask	= mikasa_enable_irq,
	.irq_mask	= mikasa_disable_irq,
	.irq_mask_ack	= mikasa_disable_irq,
};

static void
mikasa_device_interrupt(unsigned long vector)
{
	unsigned long pld;
	unsigned int i;

	/* Read the interrupt summary registers */
	pld = (((~inw(0x534) & 0x0000ffffUL) << 16)
	       | (((unsigned long) inb(0xa0)) << 8)
	       | inb(0x20));

	/*
	 * Now for every possible bit set, work through them and call
	 * the appropriate interrupt handler.
	 */
	while (pld) {
		i = ffz(~pld);
		pld &= pld - 1; /* clear least bit set */
		if (i < 16) {
			isa_device_interrupt(vector);
		} else {
			handle_irq(i);
		}
	}
}

static void __init
mikasa_init_irq(void)
{
	long i;

	if (alpha_using_srm)
		alpha_mv.device_interrupt = srm_device_interrupt;

	mikasa_update_irq_hw(0);

	for (i = 16; i < 32; ++i) {
		irq_set_chip_and_handler(i, &mikasa_irq_type,
					 handle_level_irq);
		irq_set_status_flags(i, IRQ_LEVEL);
	}

	init_i8259a_irqs();
	common_init_isa_dma();
}

/*
 * PCI Fixup configuration.
 *
 * Summary @ 0x536:
 * Bit      Meaning
 * 0        Interrupt Line A from slot 0
 * 1        Interrupt Line B from slot 0
 * 2        Interrupt Line C from slot 0
 * 3        Interrupt Line D from slot 0
 * 4        Interrupt Line A from slot 1
 * 5        Interrupt line B from slot 1
 * 6        Interrupt Line C from slot 1
 * 7        Interrupt Line D from slot 1
 * 8        Interrupt Line A from slot 2
 * 9        Interrupt Line B from slot 2
 *10        Interrupt Line C from slot 2
 *11        Interrupt Line D from slot 2
 *12        NCR 810 SCSI
 *13        Power Supply Fail
 *14        Temperature Warn
 *15        Reserved
 *
 * The device to slot mapping looks like:
 *
 * Slot     Device
 *  6       NCR SCSI controller
 *  7       Intel PCI-EISA bridge chip
 * 11       PCI on board slot 0
 * 12       PCI on board slot 1
 * 13       PCI on board slot 2
 *
 *
 * This two layered interrupt approach means that we allocate IRQ 16 and
 * above for PCI interrupts.  The IRQ relates to which bit the interrupt
 * comes in on.  This makes interrupt processing much easier.
 */

static int
mikasa_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
	static char irq_tab[8][5] = {
		/*INT    INTA   INTB   INTC   INTD */
		{16+12, 16+12, 16+12, 16+12, 16+12},	/* IdSel 17,  SCSI */
		{   -1,    -1,    -1,    -1,    -1},	/* IdSel 18,  PCEB */
		{   -1,    -1,    -1,    -1,    -1},	/* IdSel 19,  ???? */
		{   -1,    -1,    -1,    -1,    -1},	/* IdSel 20,  ???? */
		{   -1,    -1,    -1,    -1,    -1},	/* IdSel 21,  ???? */
		{ 16+0,  16+0,  16+1,  16+2,  16+3},	/* IdSel 22,  slot 0 */
		{ 16+4,  16+4,  16+5,  16+6,  16+7},	/* IdSel 23,  slot 1 */
		{ 16+8,  16+8,  16+9, 16+10, 16+11},	/* IdSel 24,  slot 2 */
	};
	const long min_idsel = 6, max_idsel = 13, irqs_per_slot = 5;
	return COMMON_TABLE_LOOKUP;
}

#if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO)
static void
mikasa_apecs_machine_check(unsigned long vector, unsigned long la_ptr)
{
#define MCHK_NO_DEVSEL 0x205U
#define MCHK_NO_TABT 0x204U

	struct el_common *mchk_header;
	unsigned int code;

	mchk_header = (struct el_common *)la_ptr;

	/* 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, "MIKASA APECS",
			    (mcheck_expected(0)
			     && (code == MCHK_NO_DEVSEL
			         || code == MCHK_NO_TABT)));
}
#endif

/*
 * The System Vector
 */

#if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO)
struct alpha_machine_vector mikasa_mv __initmv = {
	.vector_name		= "Mikasa",
	DO_EV4_MMU,
	DO_DEFAULT_RTC,
	DO_APECS_IO,
	.machine_check		= mikasa_apecs_machine_check,
	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
	.min_io_address		= DEFAULT_IO_BASE,
	.min_mem_address	= APECS_AND_LCA_DEFAULT_MEM_BASE,

	.nr_irqs		= 32,
	.device_interrupt	= mikasa_device_interrupt,

	.init_arch		= apecs_init_arch,
	.init_irq		= mikasa_init_irq,
	.init_rtc		= common_init_rtc,
	.init_pci		= common_init_pci,
	.pci_map_irq		= mikasa_map_irq,
	.pci_swizzle		= common_swizzle,
};
ALIAS_MV(mikasa)
#endif

#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PRIMO)
struct alpha_machine_vector mikasa_primo_mv __initmv = {
	.vector_name		= "Mikasa-Primo",
	DO_EV5_MMU,
	DO_DEFAULT_RTC,
	DO_CIA_IO,
	.machine_check		= cia_machine_check,
	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
	.min_io_address		= DEFAULT_IO_BASE,
	.min_mem_address	= CIA_DEFAULT_MEM_BASE,

	.nr_irqs		= 32,
	.device_interrupt	= mikasa_device_interrupt,

	.init_arch		= cia_init_arch,
	.init_irq		= mikasa_init_irq,
	.init_rtc		= common_init_rtc,
	.init_pci		= cia_init_pci,
	.kill_arch		= cia_kill_arch,
	.pci_map_irq		= mikasa_map_irq,
	.pci_swizzle		= common_swizzle,
};
ALIAS_MV(mikasa_primo)
#endif


code:
// SPDX-License-Identifier: GPL-2.0
/*
 *	linux/arch/alpha/kernel/sys_nautilus.c
 *
 *	Copyright (C) 1995 David A Rusling
 *	Copyright (C) 1998 Richard Henderson
 *	Copyright (C) 1999 Alpha Processor, Inc.,
 *		(David Daniel, Stig Telfer, Soohoon Lee)
 *
 * Code supporting NAUTILUS systems.
 *
 *
 * NAUTILUS has the following I/O features:
 *
 * a) Driven by AMD 751 aka IRONGATE (northbridge):
 *     4 PCI slots
 *     1 AGP slot
 *
 * b) Driven by ALI M1543C (southbridge)
 *     2 ISA slots
 *     2 IDE connectors
 *     1 dual drive capable FDD controller
 *     2 serial ports
 *     1 ECP/EPP/SP parallel port
 *     2 USB ports
 */

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/reboot.h>
#include <linux/memblock.h>
#include <linux/bitops.h>

#include <asm/ptrace.h>
#include <asm/dma.h>
#include <asm/irq.h>
#include <asm/mmu_context.h>
#include <asm/io.h>
#include <asm/core_irongate.h>
#include <asm/hwrpb.h>
#include <asm/tlbflush.h>

#include "proto.h"
#include "err_impl.h"
#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"

static void __init
nautilus_init_irq(void)
{
	if (alpha_using_srm) {
		alpha_mv.device_interrupt = srm_device_interrupt;
	}

	init_i8259a_irqs();
	common_init_isa_dma();
}

static int
nautilus_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
	/* Preserve the IRQ set up by the console.  */

	u8 irq;
	/* UP1500: AGP INTA is actually routed to IRQ 5, not IRQ 10 as
	   console reports. Check the device id of AGP bridge to distinguish
	   UP1500 from UP1000/1100. Note: 'pin' is 2 due to bridge swizzle. */
	if (slot == 1 && pin == 2 &&
	    dev->bus->self && dev->bus->self->device == 0x700f)
		return 5;
	pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
	return irq;
}

void
nautilus_kill_arch(int mode)
{
	struct pci_bus *bus = pci_isa_hose->bus;
	u32 pmuport;
	int off;

	switch (mode) {
	case LINUX_REBOOT_CMD_RESTART:
		if (! alpha_using_srm) {
			u8 t8;
			pci_bus_read_config_byte(bus, 0x38, 0x43, &t8);
			pci_bus_write_config_byte(bus, 0x38, 0x43, t8 | 0x80);
			outb(1, 0x92);
			outb(0, 0x92);
			/* NOTREACHED */
		}
		break;

	case LINUX_REBOOT_CMD_POWER_OFF:
		/* Assume M1543C */
		off = 0x2000;		/* SLP_TYPE = 0, SLP_EN = 1 */
		pci_bus_read_config_dword(bus, 0x88, 0x10, &pmuport);
		if (!pmuport) {
			/* M1535D/D+ */
			off = 0x3400;	/* SLP_TYPE = 5, SLP_EN = 1 */
			pci_bus_read_config_dword(bus, 0x88, 0xe0, &pmuport);
		}
		pmuport &= 0xfffe;
		outw(0xffff, pmuport);	/* Clear pending events. */
		outw(off, pmuport + 4);
		/* NOTREACHED */
		break;
	}
}

/* Perform analysis of a machine check that arrived from the system (NMI) */

static void
naut_sys_machine_check(unsigned long vector, unsigned long la_ptr,
		       struct pt_regs *regs)
{
	printk("PC %lx RA %lx\n", regs->pc, regs->r26);
	irongate_pci_clr_err();
}

/* Machine checks can come from two sources - those on the CPU and those
   in the system.  They are analysed separately but all starts here.  */

void
nautilus_machine_check(unsigned long vector, unsigned long la_ptr)
{
	char *mchk_class;

	/* Now for some analysis.  Machine checks fall into two classes --
	   those picked up by the system, and those picked up by the CPU.
	   Add to that the two levels of severity - correctable or not.  */

	if (vector == SCB_Q_SYSMCHK
	    && ((IRONGATE0->dramms & 0x300) == 0x300)) {
		unsigned long nmi_ctl;

		/* Clear ALI NMI */
		nmi_ctl = inb(0x61);
		nmi_ctl |= 0x0c;
		outb(nmi_ctl, 0x61);
		nmi_ctl &= ~0x0c;
		outb(nmi_ctl, 0x61);

		/* Write again clears error bits.  */
		IRONGATE0->stat_cmd = IRONGATE0->stat_cmd & ~0x100;
		mb();
		IRONGATE0->stat_cmd;

		/* Write again clears error bits.  */
		IRONGATE0->dramms = IRONGATE0->dramms;
		mb();
		IRONGATE0->dramms;

		draina();
		wrmces(0x7);
		mb();
		return;
	}

	if (vector == SCB_Q_SYSERR)
		mchk_class = "Correctable";
	else if (vector == SCB_Q_SYSMCHK)
		mchk_class = "Fatal";
	else {
		ev6_machine_check(vector, la_ptr);
		return;
	}

	printk(KERN_CRIT "NAUTILUS Machine check 0x%lx "
			 "[%s System Machine Check (NMI)]\n",
	       vector, mchk_class);

	naut_sys_machine_check(vector, la_ptr, get_irq_regs());

	/* Tell the PALcode to clear the machine check */
	draina();
	wrmces(0x7);
	mb();
}

extern void pcibios_claim_one_bus(struct pci_bus *);

static struct resource irongate_mem = {
	.name	= "Irongate PCI MEM",
	.flags	= IORESOURCE_MEM,
};
static struct resource busn_resource = {
	.name	= "PCI busn",
	.start	= 0,
	.end	= 255,
	.flags	= IORESOURCE_BUS,
};

void __init
nautilus_init_pci(void)
{
	struct pci_controller *hose = hose_head;
	struct pci_host_bridge *bridge;
	struct pci_bus *bus;
	unsigned long bus_align, bus_size, pci_mem;
	unsigned long memtop = max_low_pfn << PAGE_SHIFT;

	bridge = pci_alloc_host_bridge(0);
	if (!bridge)
		return;

	/* Use default IO. */
	pci_add_resource(&bridge->windows, &ioport_resource);
	/* Irongate PCI memory aperture, calculate required size before
	   setting it up. */
	pci_add_resource(&bridge->windows, &irongate_mem);

	pci_add_resource(&bridge->windows, &busn_resource);
	bridge->dev.parent = NULL;
	bridge->sysdata = hose;
	bridge->busnr = 0;
	bridge->ops = alpha_mv.pci_ops;
	bridge->swizzle_irq = alpha_mv.pci_swizzle;
	bridge->map_irq = alpha_mv.pci_map_irq;
	bridge->size_windows = 1;

	/* Scan our single hose.  */
	if (pci_scan_root_bus_bridge(bridge)) {
		pci_free_host_bridge(bridge);
		return;
	}
	bus = hose->bus = bridge->bus;
	pcibios_claim_one_bus(bus);

	pci_bus_size_bridges(bus);

	/* Now we've got the size and alignment of PCI memory resources
	   stored in irongate_mem. Set up the PCI memory range: limit is
	   hardwired to 0xffffffff, base must be aligned to 16Mb. */
	bus_align = irongate_mem.start;
	bus_size = irongate_mem.end + 1 - bus_align;
	if (bus_align < 0x1000000UL)
		bus_align = 0x1000000UL;

	pci_mem = (0x100000000UL - bus_size) & -bus_align;
	irongate_mem.start = pci_mem;
	irongate_mem.end = 0xffffffffUL;

	/* Register our newly calculated PCI memory window in the resource
	   tree. */
	if (request_resource(&iomem_resource, &irongate_mem) < 0)
		printk(KERN_ERR "Failed to request MEM on hose 0\n");

	printk(KERN_INFO "Irongate pci_mem %pR\n", &irongate_mem);

	if (pci_mem < memtop)
		memtop = pci_mem;
	if (memtop > alpha_mv.min_mem_address) {
		free_reserved_area(__va(alpha_mv.min_mem_address),
				   __va(memtop), -1, NULL);
		printk(KERN_INFO "nautilus_init_pci: %ldk freed\n",
			(memtop - alpha_mv.min_mem_address) >> 10);
	}
	if ((IRONGATE0->dev_vendor >> 16) > 0x7006)	/* Albacore? */
		IRONGATE0->pci_mem = pci_mem;

	pci_bus_assign_resources(bus);
	pci_bus_add_devices(bus);
}

/*
 * The System Vectors
 */

struct alpha_machine_vector nautilus_mv __initmv = {
	.vector_name		= "Nautilus",
	DO_EV6_MMU,
	DO_DEFAULT_RTC,
	DO_IRONGATE_IO,
	.machine_check		= nautilus_machine_check,
	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
	.min_io_address		= DEFAULT_IO_BASE,
	.min_mem_address	= IRONGATE_DEFAULT_MEM_BASE,

	.nr_irqs		= 16,
	.device_interrupt	= isa_device_interrupt,

	.init_arch		= irongate_init_arch,
	.init_irq		= nautilus_init_irq,
	.init_rtc		= common_init_rtc,
	.init_pci		= nautilus_init_pci,
	.kill_arch		= nautilus_kill_arch,
	.pci_map_irq		= nautilus_map_irq,
	.pci_swizzle		= common_swizzle,
};
ALIAS_MV(nautilus)


code:
// SPDX-License-Identifier: GPL-2.0
/*
 *	linux/arch/alpha/kernel/sys_noritake.c
 *
 *	Copyright (C) 1995 David A Rusling
 *	Copyright (C) 1996 Jay A Estabrook
 *	Copyright (C) 1998, 1999 Richard Henderson
 *
 * Code supporting the NORITAKE (AlphaServer 1000A),
 * CORELLE (AlphaServer 800), and ALCOR Primo (AlphaStation 600A).
 */

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/bitops.h>

#include <asm/ptrace.h>
#include <asm/mce.h>
#include <asm/dma.h>
#include <asm/irq.h>
#include <asm/mmu_context.h>
#include <asm/io.h>
#include <asm/core_apecs.h>
#include <asm/core_cia.h>
#include <asm/tlbflush.h>

#include "proto.h"
#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"

/* Note mask bit is true for ENABLED irqs.  */
static int cached_irq_mask;

static inline void
noritake_update_irq_hw(int irq, int mask)
{
	int port = 0x54a;
	if (irq >= 32) {
	    mask >>= 16;
	    port = 0x54c;
	}
	outw(mask, port);
}

static void
noritake_enable_irq(struct irq_data *d)
{
	noritake_update_irq_hw(d->irq, cached_irq_mask |= 1 << (d->irq - 16));
}

static void
noritake_disable_irq(struct irq_data *d)
{
	noritake_update_irq_hw(d->irq, cached_irq_mask &= ~(1 << (d->irq - 16)));
}

static struct irq_chip noritake_irq_type = {
	.name		= "NORITAKE",
	.irq_unmask	= noritake_enable_irq,
	.irq_mask	= noritake_disable_irq,
	.irq_mask_ack	= noritake_disable_irq,
};

static void
noritake_device_interrupt(unsigned long vector)
{
	unsigned long pld;
	unsigned int i;

	/* Read the interrupt summary registers of NORITAKE */
	pld = (((unsigned long) inw(0x54c) << 32)
	       | ((unsigned long) inw(0x54a) << 16)
	       | ((unsigned long) inb(0xa0) << 8)
	       | inb(0x20));

	/*
	 * Now for every possible bit set, work through them and call
	 * the appropriate interrupt handler.
	 */
	while (pld) {
		i = ffz(~pld);
		pld &= pld - 1; /* clear least bit set */
		if (i < 16) {
			isa_device_interrupt(vector);
		} else {
			handle_irq(i);
		}
	}
}

static void
noritake_srm_device_interrupt(unsigned long vector)
{
	int irq;

	irq = (vector - 0x800) >> 4;

	/*
	 * I really hate to do this, too, but the NORITAKE SRM console also
	 * reports PCI vectors *lower* than I expected from the bit numbers
	 * in the documentation.
	 * But I really don't want to change the fixup code for allocation
	 * of IRQs, nor the alpha_irq_mask maintenance stuff, both of which
	 * look nice and clean now.
	 * So, here's this additional grotty hack... :-(
	 */
	if (irq >= 16)
		irq = irq + 1;

	handle_irq(irq);
}

static void __init
noritake_init_irq(void)
{
	long i;

	if (alpha_using_srm)
		alpha_mv.device_interrupt = noritake_srm_device_interrupt;

	outw(0, 0x54a);
	outw(0, 0x54c);

	for (i = 16; i < 48; ++i) {
		irq_set_chip_and_handler(i, &noritake_irq_type,
					 handle_level_irq);
		irq_set_status_flags(i, IRQ_LEVEL);
	}

	init_i8259a_irqs();
	common_init_isa_dma();
}

/*
 * PCI Fixup configuration.
 *
 * Summary @ 0x542, summary register #1:
 * Bit      Meaning
 * 0        All valid ints from summary regs 2 & 3
 * 1        QLOGIC ISP1020A SCSI
 * 2        Interrupt Line A from slot 0
 * 3        Interrupt Line B from slot 0
 * 4        Interrupt Line A from slot 1
 * 5        Interrupt line B from slot 1
 * 6        Interrupt Line A from slot 2
 * 7        Interrupt Line B from slot 2
 * 8        Interrupt Line A from slot 3
 * 9        Interrupt Line B from slot 3
 *10        Interrupt Line A from slot 4
 *11        Interrupt Line B from slot 4
 *12        Interrupt Line A from slot 5
 *13        Interrupt Line B from slot 5
 *14        Interrupt Line A from slot 6
 *15        Interrupt Line B from slot 6
 *
 * Summary @ 0x544, summary register #2:
 * Bit      Meaning
 * 0        OR of all unmasked ints in SR #2
 * 1        OR of secondary bus ints
 * 2        Interrupt Line C from slot 0
 * 3        Interrupt Line D from slot 0
 * 4        Interrupt Line C from slot 1
 * 5        Interrupt line D from slot 1
 * 6        Interrupt Line C from slot 2
 * 7        Interrupt Line D from slot 2
 * 8        Interrupt Line C from slot 3
 * 9        Interrupt Line D from slot 3
 *10        Interrupt Line C from slot 4
 *11        Interrupt Line D from slot 4
 *12        Interrupt Line C from slot 5
 *13        Interrupt Line D from slot 5
 *14        Interrupt Line C from slot 6
 *15        Interrupt Line D from slot 6
 *
 * The device to slot mapping looks like:
 *
 * Slot     Device
 *  7       Intel PCI-EISA bridge chip
 *  8       DEC PCI-PCI bridge chip
 * 11       PCI on board slot 0
 * 12       PCI on board slot 1
 * 13       PCI on board slot 2
 *
 *
 * This two layered interrupt approach means that we allocate IRQ 16 and
 * above for PCI interrupts.  The IRQ relates to which bit the interrupt
 * comes in on.  This makes interrupt processing much easier.
 */

static int
noritake_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
	static char irq_tab[15][5] = {
		/*INT    INTA   INTB   INTC   INTD */
		/* note: IDSELs 16, 17, and 25 are CORELLE only */
		{ 16+1,  16+1,  16+1,  16+1,  16+1},  /* IdSel 16,  QLOGIC */
		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 17, S3 Trio64 */
		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 18,  PCEB */
		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 19,  PPB  */
		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 20,  ???? */
		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 21,  ???? */
		{ 16+2,  16+2,  16+3,  32+2,  32+3},  /* IdSel 22,  slot 0 */
		{ 16+4,  16+4,  16+5,  32+4,  32+5},  /* IdSel 23,  slot 1 */
		{ 16+6,  16+6,  16+7,  32+6,  32+7},  /* IdSel 24,  slot 2 */
		{ 16+8,  16+8,  16+9,  32+8,  32+9},  /* IdSel 25,  slot 3 */
		/* The following 5 are actually on PCI bus 1, which is
		   across the built-in bridge of the NORITAKE only.  */
		{ 16+1,  16+1,  16+1,  16+1,  16+1},  /* IdSel 16,  QLOGIC */
		{ 16+8,  16+8,  16+9,  32+8,  32+9},  /* IdSel 17,  slot 3 */
		{16+10, 16+10, 16+11, 32+10, 32+11},  /* IdSel 18,  slot 4 */
		{16+12, 16+12, 16+13, 32+12, 32+13},  /* IdSel 19,  slot 5 */
		{16+14, 16+14, 16+15, 32+14, 32+15},  /* IdSel 20,  slot 6 */
	};
	const long min_idsel = 5, max_idsel = 19, irqs_per_slot = 5;
	return COMMON_TABLE_LOOKUP;
}

static u8
noritake_swizzle(struct pci_dev *dev, u8 *pinp)
{
	int slot, pin = *pinp;

	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
	{
		/* Must be a card-based bridge.  */
		do {
			if (PCI_SLOT(dev->bus->self->devfn) == 8) {
				slot = PCI_SLOT(dev->devfn) + 15;
				break;
			}
			pin = pci_swizzle_interrupt_pin(dev, pin);

			/* Move up the chain of bridges.  */
			dev = dev->bus->self;
			/* Slot of the next bridge.  */
			slot = PCI_SLOT(dev->devfn);
		} while (dev->bus->self);
	}
	*pinp = pin;
	return slot;
}

#if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO)
static void
noritake_apecs_machine_check(unsigned long vector, unsigned long la_ptr)
{
#define MCHK_NO_DEVSEL 0x205U
#define MCHK_NO_TABT 0x204U

        struct el_common *mchk_header;
        unsigned int code;

        mchk_header = (struct el_common *)la_ptr;

        /* 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, "NORITAKE APECS",
                            (mcheck_expected(0)
                             && (code == MCHK_NO_DEVSEL
                                 || code == MCHK_NO_TABT)));
}
#endif

/*
 * The System Vectors
 */

#if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO)
struct alpha_machine_vector noritake_mv __initmv = {
	.vector_name		= "Noritake",
	DO_EV4_MMU,
	DO_DEFAULT_RTC,
	DO_APECS_IO,
	.machine_check		= noritake_apecs_machine_check,
	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
	.min_io_address		= EISA_DEFAULT_IO_BASE,
	.min_mem_address	= APECS_AND_LCA_DEFAULT_MEM_BASE,

	.nr_irqs		= 48,
	.device_interrupt	= noritake_device_interrupt,

	.init_arch		= apecs_init_arch,
	.init_irq		= noritake_init_irq,
	.init_rtc		= common_init_rtc,
	.init_pci		= common_init_pci,
	.pci_map_irq		= noritake_map_irq,
	.pci_swizzle		= noritake_swizzle,
};
ALIAS_MV(noritake)
#endif

#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PRIMO)
struct alpha_machine_vector noritake_primo_mv __initmv = {
	.vector_name		= "Noritake-Primo",
	DO_EV5_MMU,
	DO_DEFAULT_RTC,
	DO_CIA_IO,
	.machine_check		= cia_machine_check,
	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
	.min_io_address		= EISA_DEFAULT_IO_BASE,
	.min_mem_address	= CIA_DEFAULT_MEM_BASE,

	.nr_irqs		= 48,
	.device_interrupt	= noritake_device_interrupt,

	.init_arch		= cia_init_arch,
	.init_irq		= noritake_init_irq,
	.init_rtc		= common_init_rtc,
	.init_pci		= cia_init_pci,
	.kill_arch		= cia_kill_arch,
	.pci_map_irq		= noritake_map_irq,
	.pci_swizzle		= noritake_swizzle,
};
ALIAS_MV(noritake_primo)
#endif