code:
/* $OpenBSD: mcpciareg.h,v 1.1 2007/03/16 21:22:27 robert Exp $ */
/* $NetBSD: mcpciareg.h,v 1.7 2006/05/17 21:32:59 drochner Exp $ */

/*
 * Copyright (c) 1998 by Matthew Jacob
 * NASA AMES Research Center.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice immediately at the beginning of the file, without modification,
 *    this list of conditions, and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * Taken from:
 *
 *	``RAWHIDE Systems Programmer's Manual, Revision 1.4''
 */

#define	REGVAL(r)	(*(volatile int32_t *)ALPHA_PHYS_TO_K0SEG(r))

/*
 * There are 4 possible PCI busses per MCBUS.
 *
 * (from mcpcia.h, Digital Unix 4.0E):
 *
 * I/O Space Per PCI Node (8GBytes per)
 * ------------------------------------
 * (8+x)8 0000 0000 - (8+x)9 FFFF FFFF  - I/O Space for PCI0
 * (8+x)A 0000 0000 - (8+x)B FFFF FFFF  - I/O Space for PCI1
 * (8+x)C 0000 0000 - (8+x)D FFFF FFFF  - I/O Space for PCI2
 * (8+x)E 0000 0000 - (8+x)F FFFF FFFF  - I/O Space for PCI3
 *
 * CPU to PCI Address Mapping:
 * ---------------------------
 *
 * +---+-------+-------+--+--+--+--+--+--+---------------+----------+-----+
 * | 1 |  GID  |  MID  |  |  |  |  |  |  | Byte Aligned  | Byte Len | Zero|
 * |   |       |       |  |  |  |  |  |  | I/O Address   |   Field  |     |
 * +---+-------+-------+--+--+--+--+--+--+---------------+----------+-----+
 *  39  38   36 35   33 32 31 30 29 28 27 26            5 4        3  2  0
 *
 * <39> - I/O Select (Always 1 for direct I/O access)
 *
 * <38-36> - Global Bus slot # (MCBUS #)
 *      GID slot #0->7 (MCBUS #0->7)
 *
 * <35-33> - MCBUS Slot #
 *      MCBUS slot 0->7
 *
 * <32-27> - PCI Address Space
 *      0.xxxxx = Sparse Memory Space   (  4GB on MCBUS; 128MB on PCI)
 *      1.0xxxx = Dense Memory Space    (  2GB on MCBUS;   2GB on PCI)
 *      1.10xxx = Sparse IO Space       (  1GB on MCBUS;  32MB on PCI)
 *      1.110xx = Sparse Config Space   (512MB on MCBUS;  16MB on PCI)
 *      1.1110x = PCI Bridge CSR Space  (256MB on MCBUS) -- Sparse-mapped!
 *      1.11110 = Interrupt Acknowledge (128MB on MCBUS)
 *      1.11111 = Unused                (128MB on MCBUS)
 *
 * ------------------------------------------------------------
 * CPU to PCI Address Mapping for MCBUS-PCIy Bridge on MCBUS x:
 * ------------------------------------------------------------
 *
 * CPU Address Range            PCI Address Range       PCI Address Space
 * ------------------------     ---------------------   ------------------------
 * (8+x)(8+y*2).0000.0000       0000.0000 - 00FF.FFFF   PCIy Sparse Memory Space
 * - (8+x)(8+y*2).1FFF.FFFF                              (fixed, lower 16MB)
 *
 * (8+x)(8+y*2).2000.0000       0100.0000 - 07FF.FFFF   PCIy Sparse Memory Space
 * - (8+x)(8+y*2).FFFF.FFFF                              (variable, offset = 0)
 *
 * (8+x)(9+y*2).0000.0000       0000.0000 - 7FFF.FFFF   PCIy Dense Memory Space
 * - (8+x)(9+y*2).7FFF.FFFF  or 8000.0000 - FFFF.FFFF      if HAE_DENSE_MEM = 1
 *
 * (8+x)(9+y*2).8000.0000       0000.0000 - 0000.FFFF   PCIy Sparse IO Space
 * - (8+x)(9+y*2).801F.FFFF                              (fixed, lower 64K)
 *
 * (8+x)(9+y*2).8020.0000       0001.0000 - 01FF.FFFF   PCIy Sparse IO Space
 * - (8+x)(9+y*2).BFFF.FFFF                              (variable, offset = 0)
 *
 * (8+x)(9+y*2).C000.0000       0000.0000 - 0FFF.FFFF   PCIy Config Space (16MB)
 * - (8+x)(9+y*2).DFFF.FFFF
 *
 * (8+x)(9+y*2).E000.0000               N/A             PCIy-Bridge CSR Space
 *							(8MB)
 * - (8+x)(9+y*2).EFFF.FFFF
 *
 * (8+x)(9+y*2).F000.0000               N/A             Unused
 * - (8+x)(9+y*2).F000.3EFF
 *
 * (8+x)(9+y*2).F000.3F00,              N/A             PCIy Interrupt ACK0
 * (8+x)(9+y*2).F000.3F40                               PCIy INteruppt ACK1
 *
 * (8+x)(9+y*2).F000.3F80               N/A             Unused
 * - (8+x)(9+y*2).FFFF.FFFF
 *
 */

/*
 * MC-PCI Bus Bridge CSRs
 *
 * Address Map Overview:
 *
 * Offset                Selected Space
 * ----------------      -------------------------------------------------
 * 0x00000000            General config, control, diag, error logging regs.
 * 0x00001000            PCI Error Status
 * 0x00001300            PCI Scatter/Gather Regs.
 * 0x00001800            Scatter/Gather TLB Regs.
 * 0x00004000            MDPA Error Status & Diagnostic Control
 * 0x00008000            MDPB Error Status & Diagnostic Control
 * 0x000E0000 -          Flash Rom Space --
 * 0x000FFFFF            offset address into PCI Dense Mem Space
 * 0x10003F00            Interrupt Acknowledge
 *
 */

/*
 * Address Space Cookies
 */

#define	MCPCIA_PCI_SPARSE	0x000000000UL
#define	MCPCIA_PCI_DENSE	0x100000000UL
#define	MCPCIA_PCI_IOSPACE	0x180000000UL
#define	MCPCIA_PCI_CONF		0x1C0000000UL
#define	MCPCIA_PCI_BRIDGE	0x1E0000000UL
#define	MCPCIA_PCI_IACK		0x1F0000000UL

/*
 * MCPCIA Bus Bridge Registers
 *
 * These are offsets that don't include GBUS, MID, or address space offsets.
 */

#define	_MCPCIA_PCI_REV		0x000000000	/* PCI Revision Register (R) */
#define	_MCPCIA_WHOAMI		0x000000040	/* PCI Who Am I (R) */
#define	_MCPCIA_PCI_LAT		0x000000080	/* PCI Latency Timer (RW) */
#define	_MCPCIA_CAP_CTRL	0x000000100	/* PCI Bridge Control (RW) */
#define	_MCPCIA_HAE_MEM		0x000000400	/* PCI HAE Sparse Memory (RW) */
#define	_MCPCIA_HAE_IO		0x000000440	/* PCI HAE Sparse I/O (RW) */
#define	_MCPCIA_IACK_SC		0x000000480	/* PCI Special Cycle Ack */
#define	_MCPCIA_HAE_DENSE	0x0000004C0	/* PCI HAE Dense Memory (RW) */

#define	_MCPCIA_INT_CTL		0x000000500	/* PCI Interrupt Control */
#define	_MCPCIA_INT_REQ		0x000000540	/* PCI Interrupt Request */
#define	_MCPCIA_INT_TARG	0x000000580	/* PCI Int Tgt Devices */
#define	_MCPCIA_INT_ADR		0x0000005C0	/* PCI Int Tgt Address */
#define	_MCPCIA_INT_ADR_EXT	0x000000600	/* PCI Int Tgt Addr Ext */
#define	_MCPCIA_INT_MASK0	0x000000640	/* PCI Int Mask 0 */
#define	_MCPCIA_INT_MASK1	0x000000680	/* PCI Int Mask 1 */

#define	_MCPCIA_INT_ACK0	0x100003F00	/* PCI Int Ack 0 */
#define	_MCPCIA_INT_ACK1	0x100003F40	/* PCI Int Ack 1 */

#define	_MCPCIA_PERF_MON	0x000000300	/* PCI Perf Monitor */
#define	_MCPCIA_PERF_CONT	0x000000340	/* PCI Perf Monitor Control */

#define	_MCPCIA_CAP_DIAG	0x000000700	/* MC-PCI Diagnostic Control */
#define	_MCPCIA_SCRATCH0	0x000000740	/* Diag General */
#define	_MCPCIA_SCRATCH1	0x000000780	/* Diag General */
#define	_MCPCIA_TOM		0x0000007C0	/* Top Of Memory */
#define	_MCPCIA_MC_ERR0		0x000000800	/* MC Err Info 0 */
#define	_MCPCIA_MC_ERR1		0x000000840	/* MC Err Info 1 */
#define	_MCPCIA_CAP_ERR		0x000000880	/* CAP Error Register */

#define	_MCPCIA_PCI_ERR1	0x000001040	/* PCI Error Status */

#define	_MCPCIA_MDPA_STAT	0x000004000	/* MDPA Status */
#define	_MCPCIA_MDPA_SYN	0x000004040	/* MDPA Syndrome */
#define	_MCPCIA_MDPA_DIAG	0x000004080	/* Diag Check MDPA */

#define	_MCPCIA_MDPB_STAT	0x000008000	/* MDPB Status */
#define	_MCPCIA_MDPB_SYN	0x000008040	/* MDPB Syndrome */
#define	_MCPCIA_MDPB_DIAG	0x000008080	/* Diag Check MDPB */

#define	_MCPCIA_SG_TBIA		0x000001300	/* Scatter/Gather TBIA */
#define	_MCPCIA_HBASE		0x000001340	/* PC "Hole" Compatibility */
#define	_MCPCIA_W0_BASE		0x000001400	/* Window Base 0 */
#define	_MCPCIA_W0_MASK		0x000001440	/* Window Mask 0 */
#define	_MCPCIA_T0_BASE		0x000001480	/* Translated Base 0 */
#define	_MCPCIA_W1_BASE		0x000001500	/* Window Base 1 */
#define	_MCPCIA_W1_MASK		0x000001540	/* Window Mask 1 */
#define	_MCPCIA_T1_BASE		0x000001580	/* Translated Base 1 */
#define	_MCPCIA_W2_BASE		0x000001600	/* Window Base 2 */
#define	_MCPCIA_W2_MASK		0x000001640	/* Window Mask 2 */
#define	_MCPCIA_T2_BASE		0x000001680	/* Translated Base 2 */
#define	_MCPCIA_W3_BASE		0x000001700	/* Window Base 3 */
#define	_MCPCIA_W3_MASK		0x000001740	/* Window Mask 3 */
#define	_MCPCIA_T3_BASE		0x000001780	/* Translated Base 3 */
#define	_MCPCIA_W_DAC		0x0000017C0	/* Window DAC Base */

/*
 * Handier defines- uses precalculated offset in softc.
 */
#define	_SYBRIDGE(ccp)	((ccp)->cc_sysbase | MCPCIA_PCI_BRIDGE)

#define	MCPCIA_PCI_REV(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_PCI_REV)
#define	MCPCIA_WHOAMI(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_WHOAMI)
#define	MCPCIA_PCI_LAT(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_PCI_LAT)
#define	MCPCIA_CAP_CTRL(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_CAP_CTRL)
#define	MCPCIA_HAE_MEM(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_HAE_MEM)
#define	MCPCIA_HAE_IO(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_HAE_IO)
#define	MCPCIA_IACK_SC(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_IACK_SC)
#define	MCPCIA_HAE_DENSE(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_HAE_DENSE)
#define	MCPCIA_INT_CTL(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_INT_CTL)
#define	MCPCIA_INT_REQ(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_INT_REQ)
#define	MCPCIA_INT_TARG(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_INT_TARG)
#define	MCPCIA_INT_ADR(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_INT_ADR)
#define	MCPCIA_INT_ADR_EXT(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_INT_ADR_EXT)
#define	MCPCIA_INT_MASK0(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_INT_MASK0)
#define	MCPCIA_INT_MASK1(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_INT_MASK1)
#define	MCPCIA_INT_ACK0(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_INT_ACK0)
#define	MCPCIA_INT_ACK1(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_INT_ACK1)
#define	MCPCIA_PERF_MON(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_PERF_MON)
#define	MCPCIA_PERF_CONT(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_PERF_CONT)
#define	MCPCIA_CAP_DIAG(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_CAP_DIAG)
#define	MCPCIA_SCRATCH0(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_SCRATCH0)
#define	MCPCIA_SCRATCH1(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_SCRATCH1)
#define	MCPCIA_TOM(ccp)		(_SYBRIDGE(ccp) | _MCPCIA_TOM)
#define	MCPCIA_MC_ERR0(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_MC_ERR0)
#define	MCPCIA_MC_ERR1(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_MC_ERR1)
#define	MCPCIA_CAP_ERR(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_CAP_ERR)
#define	MCPCIA_PCI_ERR1(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_PCI_ERR1)
#define	MCPCIA_MDPA_STAT(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_MDPA_STAT)
#define	MCPCIA_MDPA_SYN(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_MDPA_SYN)
#define	MCPCIA_MDPA_DIAG(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_MDPA_DIAG)
#define	MCPCIA_MDPB_STAT(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_MDPB_STAT)
#define	MCPCIA_MDPB_SYN(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_MDPB_SYN)
#define	MCPCIA_MDPB_DIAG(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_MDPB_DIAG)
#define	MCPCIA_SG_TBIA(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_SG_TBIA)
#define	MCPCIA_HBASE(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_HBASE)
#define	MCPCIA_W0_BASE(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_W0_BASE)
#define	MCPCIA_W0_MASK(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_W0_MASK)
#define	MCPCIA_T0_BASE(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_T0_BASE)
#define	MCPCIA_W1_BASE(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_W1_BASE)
#define	MCPCIA_W1_MASK(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_W1_MASK)
#define	MCPCIA_T1_BASE(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_T1_BASE)
#define	MCPCIA_W2_BASE(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_W2_BASE)
#define	MCPCIA_W2_MASK(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_W2_MASK)
#define	MCPCIA_T2_BASE(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_T2_BASE)
#define	MCPCIA_W3_BASE(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_W3_BASE)
#define	MCPCIA_W3_MASK(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_W3_MASK)
#define	MCPCIA_T3_BASE(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_T3_BASE)
#define	MCPCIA_W_DAC(ccp)	(_SYBRIDGE(ccp) | _MCPCIA_W_DAC)

/*
 * This is here for what error handling will get as a collected subpacket.
 */

struct mcpcia_iodsnap {
	u_int64_t	base_addr;
	u_int32_t	whami;
	u_int32_t	rsvd0;
	u_int32_t	pci_rev;
	u_int32_t	cap_ctrl;
	u_int32_t	hae_mem;
	u_int32_t	hae_io;
	u_int32_t	int_ctl;
	u_int32_t	int_reg;
	u_int32_t	int_mask0;
	u_int32_t	int_mask1;
	u_int32_t	mc_err0;
	u_int32_t	mc_err1;
	u_int32_t	cap_err;
	u_int32_t	sys_env;
	u_int32_t	pci_err1;
	u_int32_t	mdpa_stat;
	u_int32_t	mdpa_syn;
	u_int32_t	mdpb_stat;
	u_int32_t	mdpb_syn;
	u_int32_t	rsvd2;
	u_int32_t	rsvd3;
	u_int32_t	rsvd4;
};

/*
 * PCI_REV Register definitions
 */
#define	CAP_REV(reg)		((reg) & 0xf)
#define	HORSE_REV(reg)		(((reg) >> 4) & 0xf)
#define	SADDLE_REV(reg)		(((reg) >> 8) & 0xf)
#define	SADDLE_TYPE(reg)	(((reg) >> 12) & 0x3)
#define	EISA_PRESENT(reg)	((reg) & (1 << 15))
#define	IS_MCPCIA_MAGIC(reg)	(((reg) & 0xffff0000) == 0x6000000)

/*
 * WHOAMI Register definitions
 *
 * The Device ID is an echo of the MID of the CPU reading this register-
 * cheezy way to figure out who you are (ask someone else!).
 */
#define	MCBUS_CPU_MID(x)		((x) & 0x7)
#define	MCBUS_CPU_INFO(x)		(((x) >> 6) & 0xff)
#define		CPU_Fill_Err	0x80
#define		CPU_DTAG_Perr	0x40
#define		CPU_RevMask	0x38
#define		CPU_RevShift	3
#define		CPU_BCacheMask	0x3
#define			CPU_BCache_0MB	0
#define			CPU_BCache_1MB	1
#define			CPU_BCache_2MB	2
#define			CPU_BCache_4MB	3

/*
 * PCI Latency Register Definitions
 */
#define	PCI_LAT_SHIFT	8	/* it's in the 2nd byte. */

/*
 * CAP Control Register Definitions
 */
#define	CAP_LED_ON	0x00000001	/* Selftest LED passed */
#define	CAP_EV56_BW_EN	0x00000002	/* BW Enables (EV56, EV6 only) */
#define	CAP_DLY_RD_EN	0x00000010	/* PCI Delayed Reads Enabled */
#define	CAP_MEM_EN	0x00000020	/* Respond to PCI transactions */
#define	CAP_REQ64_EN	0x00000040	/* Request 64 bit data transactions */
#define	CAP_ACK64_EN	0x00000080	/* Respond to 64 bit data "" */
#define	CAP_ADR_PAR_EN	0x00000100	/* Check PCI address Parity */
#define	CAP_MC_CA_PAR	0x00000200	/* Check MC bus CMD/Address Parity */
#define	CAP_MC_NXM_EN	0x00000400	/* Check for MC NXM */
#define	CAP_BUS_MON	0x00000800	/* Check for PCI errs (as bystander) */
/* bits 19:16 control number of pending write transactions */
#define		SHORT	0
#define		MED	1
#define		LONG	2
#define	CAP_MEMRD_PREFETCH_SHIFT	20
#define	CAP_MEMRDLN_PREFETCH_SHIFT	22
#define	CAP_MEMRDMULT_PREFETCH_SHIFT	24
#define	CAP_PARTIAL_WRITE	(1 << 26)

#define	CAP_ARB_BPRI	0x00000000	/* Bridge Priority Arb */
#define	CAP_ARB_RROBIN	0x40000000	/* "" Round Robin */
#define	CAP_ARB_RROBIN1	0x80000000	/* "" Round Robin #1 */

/*
 * Diagnostic Register Bits
 */
/* CAP_DIAG register */
#define	CAP_DIAG_PCIRESET	0x1	/*
					 * WriteOnly. Assert 1 for 100usec min.,
					 * then write zero. NOTE: deadlocks
					 * exist in h/w if anything but this
					 * register is accessed while reset
					 * is asserted.
					 */
#define	CAP_DIAG_MC_ADRPE	(1<<30)	/* Invert MC Bus Address/Parity */
#define	CAP_DIAG_PCI_ADRPE	(1<<31)	/* Force bad PCI parity (low 32) */

/* MDPA_DIAG or MDPB_DIAG registers */
#define	MDPX_ECC_ENA		(1<<28)	/* Enable ECC on MC Bus (default 1) */
#define	MDPX_PAR_ENA		(1<<29)	/* Enable Parity on PCI (default 0) */
#define	MDPX_DIAG_FPE_PCI	(1<<30)	/* Force PCI parity error */
#define	MDPX_DIAG_USE_CHK	(1<<31)	/*
					 * When set, DMA write cycles use the
					 * value in the low 8 bits of this
					 * register (MDPA or MDPB) as ECC
					 * sent onto main memory.
					 */

/*
 * Interrupt Specific bits...
 *
 * Mostly we don't have to mess with any of the interrupt specific registers
 * as the SRM has set most of this pretty complex stuff up for us.
 *
 * However, to enable specific interrupts, we need to set some bits
 * in imask0 if we want to have them vectored to PALcode for appropriate
 * dispatch.
 */

/*
 * bits 0-15 correspond to 4 slots (time 4 buspins) for each PCI bus.
 * bit 16 is the NCR810 onboard SCSI interrupt.
 * bits 19-20 are reserved.
 */

#define	MCPCIA_I2C_CTRL_INTR		(1<<17)
#define	MCPCIA_I2C_CTRL_BUS_ERR		(1<<18)

#define	MCPCIA_8259_NMI_INTR		(1<<21)
#define	MCPCIA_SOFT_ERR_INTR		(1<<22)
#define	MCPCIA_HARD_ERR_INTR		(1<<23)

#ifdef	YET
#define	MCPCIA_GEN_IENABL	\
	(MCPCIA_I2C_CTRL_BUS_ERR|MCPCIA_SOFT_ERR_INTR|MCPCIA_HARD_ERR_INTR)
#else
#define	MCPCIA_GEN_IENABL	\
	(MCPCIA_SOFT_ERR_INTR|MCPCIA_HARD_ERR_INTR)
#endif

/*
 * DMA Address Specific bits...
 */

#define	MCPCIA_WBASE_EN			0x1
#define	MCPCIA_WBASE_SG			0x2
#define	MCPCIA_WBASE_DAC		0x8
#define	MCPCIA_WBASE_BSHIFT		20

#define	MCPCIA_WMASK_1M			0x00000000
#define	MCPCIA_WMASK_2M			0x00100000
#define	MCPCIA_WMASK_4M			0x00300000
#define	MCPCIA_WMASK_8M			0x00700000
#define	MCPCIA_WMASK_16M		0x00f00000
#define	MCPCIA_WMASK_32M		0x01f00000
#define	MCPCIA_WMASK_64M		0x03f00000
#define	MCPCIA_WMASK_128M		0x07f00000
#define	MCPCIA_WMASK_256M		0x0ff00000
#define	MCPCIA_WMASK_512M		0x1ff00000
#define	MCPCIA_WMASK_1G			0x3ff00000
#define	MCPCIA_WMASK_2G			0x7ff00000
#define	MCPCIA_WMASK_4G			0xfff00000

/*
 * The WBASEX register contains bits 39:10 of a physical address
 * shifted to bits 31:2 of this 32 bit register. Namely, shifted
 * right by 8 bits.
 */
#define	MCPCIA_TBASEX_SHIFT		8


code:
/* $OpenBSD: mcpciavar.h,v 1.1 2007/03/16 21:22:27 robert Exp $ */
/* $NetBSD: mcpciavar.h,v 1.4 1999/04/16 02:18:07 thorpej Exp $ */

/*
 * Copyright (c) 1998 by Matthew Jacob
 * NASA AMES Research Center.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice immediately at the beginning of the file, without modification,
 *    this list of conditions, and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <dev/pci/pcivar.h>
#include <sys/extent.h>

#include <alpha/pci/pci_sgmap_pte64.h>

#define	_FSTORE	(EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long))

/*
 * MPCIA configuration.
 */
struct mcpcia_config {
	int				cc_gid;	/* GID of this MCbus */
	int				cc_mid;	/* MCbus Module ID */
	int				cc_initted;
	int				cc_mallocsafe;
	struct alpha_bus_space		cc_iot;
	struct alpha_bus_space		cc_memt;
	struct extent *			cc_io_ex;
	struct extent *			cc_d_mem_ex;
	struct extent *			cc_s_mem_ex;
	struct alpha_pci_chipset	cc_pc;
	struct mcpcia_softc *		cc_sc;	/* back pointer */
	long				cc_io_exstorage[_FSTORE];
	long				cc_dmem_exstorage[_FSTORE];
	long				cc_smem_exstorage[_FSTORE];
	unsigned long			cc_sysbase;	/* shorthand */
	struct alpha_bus_dma_tag	cc_dmat_direct;
	struct alpha_bus_dma_tag	cc_dmat_pci_sgmap;
	struct alpha_bus_dma_tag	cc_dmat_isa_sgmap;
	struct alpha_sgmap		cc_pci_sgmap;
	struct alpha_sgmap		cc_isa_sgmap;
	char				pc_io_ex_name[16];
	char				pc_mem_dex_name[16];
	char				pc_mem_sex_name[16];
	long				pc_io_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];
	long				pc_mem_dex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];
	long				pc_mem_sex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];
};

struct mcpcia_softc {
	struct device		mcpcia_dev;
	struct mcpcia_config	*mcpcia_cc;	/* config info */
};

void	mcpcia_init (void);
void	mcpcia_init0 (struct mcpcia_config *, int);
void	mcpcia_pci_init (pci_chipset_tag_t, void *);
void	mcpcia_dma_init (struct mcpcia_config *);

void	mcpcia_bus_io_init (bus_space_tag_t, void *);
void	mcpcia_bus_mem_init (bus_space_tag_t, void *);

/*
 * IO Interrupt handler.
 */
void 	mcpcia_iointr (void *, unsigned long);

/*
 * There are four PCI slots per MCPCIA PCI bus here, but some are 'hidden'-
 * none seems to be higher than 6 though.
 */
#define	MCPCIA_MAXDEV	6
#define	MCPCIA_MAXSLOT	8

/*
 * Interrupt Stuff for MCPCIA systems.
 *
 * EISA interrupts (at vector 0x800) have to be shared interrupts-
 * and that can be easily managed. All the PCI interrupts are deterministic
 * in that they start at vector 0x900, 0x40 per PCI slot, 0x200 per
 * MCPCIA, 4 MCPCIAs per GCBUS....
 */
#define MCPCIA_EISA_KEYB_IRQ	1
#define MCPCIA_EISA_MOUSE_IRQ	12
#define MCPCIA_VEC_EISA		0x800
#define MCPCIA_VEC_PCI		0x900

/*
 * Special Vectors
 */
#define	MCPCIA_I2C_CVEC		0xA90
#define	MCPCIA_I2C_BVEC		0xAA0

license: unknown


code:
/* $OpenBSD: pci_1000.c,v 1.11 2015/07/26 05:09:44 miod Exp $ */
/* $NetBSD: pci_1000.c,v 1.12 2001/07/27 00:25:20 thorpej Exp $ */

/*
 * Copyright (c) 1998 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is based on pci_kn20aa.c, written by Chris G. Demetriou at
 * Carnegie-Mellon University. Platform support for Mikasa and Mikasa/Pinnacle
 * (Pinkasa) by Ross Harvey with copyright assignment by permission of Avalon
 * Computer Systems, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Copyright (c) 1995, 1996 Carnegie-Mellon University.
 * All rights reserved.
 *
 * Author: Chris G. Demetriou
 *
 * Permission to use, copy, modify and distribute this software and
 * its documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie the
 * rights to redistribute these changes.
 */

#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/malloc.h>
#include <sys/device.h>

#include <uvm/uvm_extern.h>

#include <machine/autoconf.h>

#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/ppbreg.h>

#include <alpha/pci/pci_1000.h>

#include "sio.h"
#if NSIO > 0 || NPCEB > 0
#include <alpha/pci/siovar.h>
#endif

static bus_space_tag_t another_mystery_icu_iot;
static bus_space_handle_t another_mystery_icu_ioh;

int	dec_1000_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
const char *dec_1000_intr_string(void *, pci_intr_handle_t);
int	dec_1000_intr_line(void *, pci_intr_handle_t);
void	*dec_1000_intr_establish(void *, pci_intr_handle_t,
	    int, int (*func)(void *), void *, const char *);
void	dec_1000_intr_disestablish(void *, void *);

#define	PCI_NIRQ	16
#define	PCI_STRAY_MAX	5

struct alpha_shared_intr *dec_1000_pci_intr;

void dec_1000_iointr(void *arg, unsigned long vec);
void dec_1000_enable_intr(int irq);
void dec_1000_disable_intr(int irq);
void pci_1000_imi(void);

void
pci_1000_pickintr(core, iot, memt, pc)
	void *core;
	bus_space_tag_t iot, memt;
	pci_chipset_tag_t pc;
{
	int i;

	another_mystery_icu_iot = iot;

	if (bus_space_map(iot, 0x536, 2, 0, &another_mystery_icu_ioh))
		panic("pci_1000_pickintr");
        pc->pc_intr_v = core;
        pc->pc_intr_map = dec_1000_intr_map;
        pc->pc_intr_string = dec_1000_intr_string;
	pc->pc_intr_line = dec_1000_intr_line;
        pc->pc_intr_establish = dec_1000_intr_establish;
        pc->pc_intr_disestablish = dec_1000_intr_disestablish;

	pc->pc_pciide_compat_intr_establish = NULL;
	pc->pc_pciide_compat_intr_disestablish = NULL;

	dec_1000_pci_intr =
	    alpha_shared_intr_alloc(PCI_NIRQ);
	for (i = 0; i < PCI_NIRQ; i++) {
		alpha_shared_intr_set_maxstrays(dec_1000_pci_intr, i,
		    PCI_STRAY_MAX);
	}

	pci_1000_imi();
#if NSIO > 0 || NPCEB > 0
	sio_intr_setup(pc, iot);
#endif
}

int
dec_1000_intr_map(pa, ihp)
	struct pci_attach_args *pa;
        pci_intr_handle_t *ihp;
{
	pcitag_t bustag = pa->pa_intrtag;
	int buspin, device, line = pa->pa_intrline;

	/*
	 * The console places the interrupt mapping in the "line" value.
	 * We trust it whenever possible.
	 */
	if (line >= 0 && line < PCI_NIRQ) {
		*ihp = line;
		return 0;
	}

	if (pa->pa_bridgetag) {
		buspin = PPB_INTERRUPT_SWIZZLE(pa->pa_rawintrpin,
		    pa->pa_device);
		if (pa->pa_bridgeih[buspin - 1] == 0)
			return 1;

		*ihp = pa->pa_bridgeih[buspin - 1];
		return 0;
	}

	buspin = pa->pa_intrpin;
	pci_decompose_tag(pa->pa_pc, bustag, NULL, &device, NULL);

	switch (device) {
	case 6:
		if (buspin != 1)
			break;
		*ihp = 0xc;		/* integrated ncr scsi */
		return 0;
	case 11:
	case 12:
	case 13:
		*ihp = (device - 11) * 4 + buspin - 1;
		return 0;
	}

	return 1;
}

const char *
dec_1000_intr_string(ccv, ih)
	void *ccv;
	pci_intr_handle_t ih;
{
	static const char irqmsg_fmt[] = "dec_1000 irq %ld";
        static char irqstr[sizeof irqmsg_fmt];

        if (ih >= PCI_NIRQ)
                panic("dec_1000_intr_string: bogus dec_1000 IRQ 0x%lx", ih);

        snprintf(irqstr, sizeof irqstr, irqmsg_fmt, ih);
        return (irqstr);
}

int
dec_1000_intr_line(ccv, ih)
	void *ccv;
	pci_intr_handle_t ih;
{
#if NSIO > 0
	return sio_intr_line(NULL /*XXX*/, ih);
#else
	return (ih);
#endif
}

void *
dec_1000_intr_establish(ccv, ih, level, func, arg, name)
        void *ccv;
        pci_intr_handle_t ih;
        int level;
        int (*func)(void *);
	void *arg;
	const char *name;
{
	void *cookie;

        if (ih >= PCI_NIRQ)
                panic("dec_1000_intr_establish: IRQ too high, 0x%lx", ih);

	cookie = alpha_shared_intr_establish(dec_1000_pci_intr, ih, IST_LEVEL,
	    level, func, arg, name);

	if (cookie != NULL &&
	    alpha_shared_intr_firstactive(dec_1000_pci_intr, ih)) {
		scb_set(0x900 + SCB_IDXTOVEC(ih), dec_1000_iointr, NULL);
		dec_1000_enable_intr(ih);
	}
	return (cookie);
}

void
dec_1000_intr_disestablish(ccv, cookie)
        void *ccv, *cookie;
{
	struct alpha_shared_intrhand *ih = cookie;
	unsigned int irq = ih->ih_num;
	int s;

	s = splhigh();

	alpha_shared_intr_disestablish(dec_1000_pci_intr, cookie);
	if (alpha_shared_intr_isactive(dec_1000_pci_intr, irq) == 0) {
		dec_1000_disable_intr(irq);
		alpha_shared_intr_set_dfltsharetype(dec_1000_pci_intr, irq,
		    IST_NONE);
		scb_free(0x900 + SCB_IDXTOVEC(irq));
	}

	splx(s);
}

void
dec_1000_iointr(arg, vec)
	void *arg;
	unsigned long vec;
{
	int irq;

	irq = SCB_VECTOIDX(vec - 0x900);

	if (!alpha_shared_intr_dispatch(dec_1000_pci_intr, irq)) {
		alpha_shared_intr_stray(dec_1000_pci_intr, irq,
		    "dec_1000 irq");
		if (ALPHA_SHARED_INTR_DISABLE(dec_1000_pci_intr, irq))
			dec_1000_disable_intr(irq);
	} else
		alpha_shared_intr_reset_strays(dec_1000_pci_intr, irq);
}

/*
 * Read and write the mystery ICU IMR registers
 */

#define	IR() bus_space_read_2(another_mystery_icu_iot,		\
				another_mystery_icu_ioh, 0)

#define	IW(v) bus_space_write_2(another_mystery_icu_iot,	\
				another_mystery_icu_ioh, 0, (v))

/*
 * Enable and disable interrupts at the ICU level
 */

void
dec_1000_enable_intr(irq)
	int irq;
{
	IW(IR() | 1 << irq);
}

void
dec_1000_disable_intr(irq)
	int irq;
{
	IW(IR() & ~(1 << irq));
}
/*
 * Initialize mystery ICU
 */
void
pci_1000_imi()
{
	IW(0);					/* XXX ?? */
}


code:
/* $OpenBSD: pci_1000.h,v 1.2 2008/06/26 05:42:09 ray Exp $ */
/* $NetBSD: pci_1000.h,v 1.1 1998/06/26 21:45:56 ross Exp $ */

/*
 * Copyright (c) 1998 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * Platform support for Mikasa and Mikasa/Pinnacle (Pinkasa) by Ross Harvey
 * with copyright assignment by permission of Avalon Computer Systems, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

void	pci_1000_pickintr(void *, bus_space_tag_t, bus_space_tag_t,
				pci_chipset_tag_t);


code:
/* $OpenBSD: pci_1000a.c,v 1.13 2015/07/26 05:09:44 miod Exp $ */
/* $NetBSD: pci_1000a.c,v 1.14 2001/07/27 00:25:20 thorpej Exp $ */

/*
 * Copyright (c) 1998 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is based on pci_kn20aa.c, written by Chris G. Demetriou at
 * Carnegie-Mellon University. Platform support for Noritake, Pintake, and
 * Corelle by Ross Harvey with copyright assignment by permission of Avalon
 * Computer Systems, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Copyright (c) 1995, 1996 Carnegie-Mellon University.
 * All rights reserved.
 *
 * Author: Chris G. Demetriou
 *
 * Permission to use, copy, modify and distribute this software and
 * its documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie the
 * rights to redistribute these changes.
 */

#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/malloc.h>
#include <sys/device.h>

#include <uvm/uvm_extern.h>

#include <machine/autoconf.h>

#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/ppbreg.h>

#include <alpha/pci/pci_1000a.h>

#include "sio.h"
#if NSIO > 0 || NPCEB > 0
#include <alpha/pci/siovar.h>
#endif

#define	PCI_NIRQ	32
#define	PCI_STRAY_MAX	5

#define IMR2IRQ(bn) ((bn) - 1)
#define IRQ2IMR(irq) ((irq) + 1)

static bus_space_tag_t mystery_icu_iot;
static bus_space_handle_t mystery_icu_ioh[2];

int	dec_1000a_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
const char *dec_1000a_intr_string(void *, pci_intr_handle_t);
int	dec_1000a_intr_line(void *, pci_intr_handle_t);
void	*dec_1000a_intr_establish(void *, pci_intr_handle_t,
	    int, int (*func)(void *), void *, const char *);
void	dec_1000a_intr_disestablish(void *, void *);

struct alpha_shared_intr *dec_1000a_pci_intr;

void dec_1000a_iointr(void *arg, unsigned long vec);
void dec_1000a_enable_intr(int irq);
void dec_1000a_disable_intr(int irq);
void pci_1000a_imi(void);

void
pci_1000a_pickintr(core, iot, memt, pc)
	void *core;
	bus_space_tag_t iot, memt;
	pci_chipset_tag_t pc;
{
	int i;

	mystery_icu_iot = iot;

	if (bus_space_map(iot, 0x54a, 2, 0, mystery_icu_ioh + 0)
	||  bus_space_map(iot, 0x54c, 2, 0, mystery_icu_ioh + 1))
		panic("pci_1000a_pickintr");
        pc->pc_intr_v = core;
        pc->pc_intr_map = dec_1000a_intr_map;
        pc->pc_intr_string = dec_1000a_intr_string;
	pc->pc_intr_line = dec_1000a_intr_line;
        pc->pc_intr_establish = dec_1000a_intr_establish;
        pc->pc_intr_disestablish = dec_1000a_intr_disestablish;

	pc->pc_pciide_compat_intr_establish = NULL;
	pc->pc_pciide_compat_intr_disestablish = NULL;

	dec_1000a_pci_intr = alpha_shared_intr_alloc(PCI_NIRQ);
	for (i = 0; i < PCI_NIRQ; i++) {
		alpha_shared_intr_set_maxstrays(dec_1000a_pci_intr, i,
		    PCI_STRAY_MAX);
	}

	pci_1000a_imi();
#if NSIO > 0 || NPCEB > 0
	sio_intr_setup(pc, iot);
#endif
}

int
dec_1000a_intr_map(pa, ihp)
	struct pci_attach_args *pa;
        pci_intr_handle_t *ihp;
{
	pcitag_t bustag = pa->pa_intrtag;
	int buspin, line = pa->pa_intrline;
	int imrbit = 0, bus, device;
	/*
	 * Get bit number in mystery ICU imr
	 */
	static const signed char imrmap[][4] = {
#		define	IRQSPLIT(o) { (o), (o)+1, (o)+16, (o)+16+1 }
#		define	IRQNONE		 { 0, 0, 0, 0 }
		/*  0  */ { 1, 0, 0, 0 },	/* Noritake and Pintake */
		/*  1  */ IRQSPLIT(8),
		/*  2  */ IRQSPLIT(10),
		/*  3  */ IRQSPLIT(12),
		/*  4  */ IRQSPLIT(14),
		/*  5  */ { 1, 0, 0, 0 },	/* Corelle */
		/*  6  */ { 10, 0, 0, 0 },	/* Corelle */
		/*  7  */ IRQNONE,
		/*  8  */ IRQNONE,		/* see imrmap2[] below */
		/*  9  */ IRQNONE,
		/* 10  */ IRQNONE,
		/* 11  */ IRQSPLIT(2),
		/* 12  */ IRQSPLIT(4),
		/* 13  */ IRQSPLIT(6),
		/* 14  */ IRQSPLIT(8)		/* Corelle */
	}, imrmap2[][4] = {
		/*  0 */ { 1, 0, 0, 0 },	/* isp */
		/*  1 */  IRQSPLIT(8),
		/*  2 */  IRQSPLIT(10),
		/*  3 */  IRQSPLIT(12),
		/*  4 */  IRQSPLIT(14)
	};

	/*
	 * The console places the interrupt mapping in the "line" value.
	 * We trust it whenever possible.
	 */
	if (line >= 0 && line < PCI_NIRQ) {
		imrbit = line + 1;
	} else {
		if (pa->pa_bridgetag) {
			buspin = pa->pa_rawintrpin;
			bus = pa->pa_bus;
			device = pa->pa_device;

			if (bus == 2) {
				/*
				 * Devices behind ppb1 (pci bus #2).
				 * Those use fixed per-slot assignments.
				 */
				if (0 <= device && device <
				    sizeof imrmap2 / sizeof imrmap2[0]) {
					imrbit = imrmap2[device][buspin - 1];
				}
			} else {
				/*
				 * Devices behind further ppb.
				 * Those reuse ppb configured interrupts.
				 */
				buspin = PPB_INTERRUPT_SWIZZLE(buspin, device);
				if (pa->pa_bridgeih[buspin - 1] != 0) {
					imrbit =
					   IRQ2IMR(pa->pa_bridgeih[buspin - 1]);
				}
			}
		} else {
			pci_decompose_tag(pa->pa_pc, bustag, &bus, &device,
			    NULL);
			buspin = pa->pa_intrpin;
			if (0 <= device &&
			    device < sizeof imrmap / sizeof imrmap[0])
				imrbit = imrmap[device][buspin - 1];
		}
	}

	if (imrbit) {
		*ihp = IMR2IRQ(imrbit);
		return 0;
	}

	return 1;
}

const char *
dec_1000a_intr_string(ccv, ih)
	void *ccv;
	pci_intr_handle_t ih;
{
	static const char irqmsg_fmt[] = "dec_1000a irq %ld";
        static char irqstr[sizeof irqmsg_fmt];

        if (ih >= PCI_NIRQ)
                panic("dec_1000a_intr_string: bogus dec_1000a IRQ 0x%lx", ih);

        snprintf(irqstr, sizeof irqstr, irqmsg_fmt, ih);
        return (irqstr);
}

int
dec_1000a_intr_line(ccv, ih)
	void *ccv;
	pci_intr_handle_t ih;
{
#if NSIO > 0
	return sio_intr_line(NULL /*XXX*/, ih);
#else
	return (ih);
#endif
}

void *
dec_1000a_intr_establish(ccv, ih, level, func, arg, name)
        void *ccv;
        pci_intr_handle_t ih;
        int level;
        int (*func)(void *);
	void *arg;
	const char *name;
{
	void *cookie;

        if (ih >= PCI_NIRQ)
                panic("dec_1000a_intr_establish: IRQ too high, 0x%lx", ih);

	cookie = alpha_shared_intr_establish(dec_1000a_pci_intr, ih, IST_LEVEL,
	    level, func, arg, name);

	if (cookie != NULL &&
	    alpha_shared_intr_firstactive(dec_1000a_pci_intr, ih)) {
		scb_set(0x900 + SCB_IDXTOVEC(ih), dec_1000a_iointr, NULL);
		dec_1000a_enable_intr(ih);

	}
	return (cookie);
}

void
dec_1000a_intr_disestablish(ccv, cookie)
        void *ccv, *cookie;
{
	struct alpha_shared_intrhand *ih = cookie;
	unsigned int irq = ih->ih_num;
	int s;

	s = splhigh();

	alpha_shared_intr_disestablish(dec_1000a_pci_intr, cookie);
	if (alpha_shared_intr_isactive(dec_1000a_pci_intr, irq) == 0) {
		dec_1000a_disable_intr(irq);
		alpha_shared_intr_set_dfltsharetype(dec_1000a_pci_intr, irq,
		    IST_NONE);
		scb_free(0x900 + SCB_IDXTOVEC(irq));
	}

	splx(s);
}

void
dec_1000a_iointr(framep, vec)
	void *framep;
	unsigned long vec;
{
	int irq;

	irq = SCB_VECTOIDX(vec - 0x900);

	if (!alpha_shared_intr_dispatch(dec_1000a_pci_intr, irq)) {
		alpha_shared_intr_stray(dec_1000a_pci_intr, irq,
		    "dec_1000a irq");
		if (ALPHA_SHARED_INTR_DISABLE(dec_1000a_pci_intr, irq))
			dec_1000a_disable_intr(irq);
	} else
		alpha_shared_intr_reset_strays(dec_1000a_pci_intr, irq);
}

/*
 * Read and write the mystery ICU IMR registers
 */

#define	IR(h) bus_space_read_2(mystery_icu_iot, mystery_icu_ioh[h], 0)
#define	IW(h, v) bus_space_write_2(mystery_icu_iot, mystery_icu_ioh[h], 0, (v))

/*
 * Enable and disable interrupts at the ICU level
 */

void
dec_1000a_enable_intr(irq)
	int irq;
{
	int imrval = IRQ2IMR(irq);
	int i = imrval >= 16;

	IW(i, IR(i) | 1 << (imrval & 0xf));
}

void
dec_1000a_disable_intr(irq)
	int irq;
{
	int imrval = IRQ2IMR(irq);
	int i = imrval >= 16;

	IW(i, IR(i) & ~(1 << (imrval & 0xf)));
}
/*
 * Initialize mystery ICU
 */
void
pci_1000a_imi()
{
	IW(0, IR(0) & 1);
	IW(1, IR(0) & 3);
}


code:
/* $OpenBSD: pci_1000a.h,v 1.2 2008/06/26 05:42:09 ray Exp $ */
/* $NetBSD: pci_1000a.h,v 1.2 1998/06/26 21:59:46 ross Exp $ */

/*
 * Copyright (c) 1998 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * Platform support for Noritake, Pintake, and Corelle by Ross Harvey
 * with copyright assignment by permission of Avalon Computer Systems, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

void	pci_1000a_pickintr(void *, bus_space_tag_t, bus_space_tag_t,
				pci_chipset_tag_t);


code:
/*	$OpenBSD: pci_2100_a50.c,v 1.23 2015/07/26 05:09:44 miod Exp $	*/
/*	$NetBSD: pci_2100_a50.c,v 1.12 1996/11/13 21:13:29 cgd Exp $	*/

/*
 * Copyright (c) 1995, 1996 Carnegie-Mellon University.
 * All rights reserved.
 *
 * Author: Chris G. Demetriou
 *
 * Permission to use, copy, modify and distribute this software and
 * its documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie the
 * rights to redistribute these changes.
 */

#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/device.h>
#include <uvm/uvm_extern.h>

#include <machine/autoconf.h>
#include <machine/bus.h>
#include <machine/intr.h>

#include <dev/isa/isavar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/ppbreg.h>

#include <alpha/pci/apecsvar.h>

#include <alpha/pci/pci_2100_a50.h>
#include <alpha/pci/siovar.h>
#include <alpha/pci/sioreg.h>

#include "sio.h"

int	dec_2100_a50_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
const char *dec_2100_a50_intr_string(void *, pci_intr_handle_t);
int	 dec_2100_a50_intr_line(void *, pci_intr_handle_t);
void    *dec_2100_a50_intr_establish(void *, pci_intr_handle_t,
	    int, int (*func)(void *), void *, const char *);
void    dec_2100_a50_intr_disestablish(void *, void *);

#define	APECS_SIO_DEVICE	7	/* XXX */

void
pci_2100_a50_pickintr(acp)
	struct apecs_config *acp;
{
	bus_space_tag_t iot = &acp->ac_iot;
	pci_chipset_tag_t pc = &acp->ac_pc;
	pcireg_t sioclass;
	int sioII;

	/* XXX MAGIC NUMBER */
	sioclass = pci_conf_read(pc, pci_make_tag(pc, 0, 7, 0), PCI_CLASS_REG);
        sioII = (sioclass & 0xff) >= 3;

	if (!sioII)
		printf("WARNING: SIO NOT SIO II... NO BETS...\n");

	pc->pc_intr_v = acp;
	pc->pc_intr_map = dec_2100_a50_intr_map;
	pc->pc_intr_string = dec_2100_a50_intr_string;
	pc->pc_intr_line = dec_2100_a50_intr_line;
	pc->pc_intr_establish = dec_2100_a50_intr_establish;
	pc->pc_intr_disestablish = dec_2100_a50_intr_disestablish;

	/* Not supported on 2100 A50. */
	pc->pc_pciide_compat_intr_establish = NULL;
	pc->pc_pciide_compat_intr_disestablish = NULL;

#if NSIO
        sio_intr_setup(pc, iot);
#else
	panic("pci_2100_a50_pickintr: no I/O interrupt handler (no sio)");
#endif
}

int
dec_2100_a50_intr_map(pa, ihp)
	struct pci_attach_args *pa;
	pci_intr_handle_t *ihp;
{
	pcitag_t bustag = pa->pa_intrtag;
	pci_chipset_tag_t pc = pa->pa_pc;
	int buspin, device, pirq;
	pcireg_t pirqreg;
	u_int8_t pirqline;

	if (pa->pa_bridgetag) {
		buspin = PPB_INTERRUPT_SWIZZLE(pa->pa_rawintrpin,
		    pa->pa_device);
		if (pa->pa_bridgeih[buspin - 1] != 0) {
			*ihp = pa->pa_bridgeih[buspin - 1];
			return 0;
		}

		return 1;
	}

	buspin = pa->pa_intrpin;
	pci_decompose_tag(pc, bustag, NULL, &device, NULL);

	switch (device) {
	case 6:					/* NCR SCSI */
		pirq = 3;
		break;

	case 11:				/* slot 1 */
	case 14:				/* slot 3 */
		switch (buspin) {
		default:
		case PCI_INTERRUPT_PIN_A:
		case PCI_INTERRUPT_PIN_D:
			pirq = 0;
			break;
		case PCI_INTERRUPT_PIN_B:
			pirq = 2;
			break;
		case PCI_INTERRUPT_PIN_C:
			pirq = 1;
			break;
		};
			break;

	case 12:				/* slot 2 */
		switch (buspin) {
		default:
		case PCI_INTERRUPT_PIN_A:
		case PCI_INTERRUPT_PIN_D:
			pirq = 1;
			break;
		case PCI_INTERRUPT_PIN_B:
			pirq = 0;
			break;
		case PCI_INTERRUPT_PIN_C:
			pirq = 2;
			break;
	};
	break;

	case 13:				/* slot 3 */
		switch (buspin) {
		default:
		case PCI_INTERRUPT_PIN_A:
		case PCI_INTERRUPT_PIN_D:
			pirq = 2;
			break;
		case PCI_INTERRUPT_PIN_B:
			pirq = 1;
			break;
		case PCI_INTERRUPT_PIN_C:
			pirq = 0;
			break;
		};
		break;

	default:
		printf("dec_2100_a50_intr_map: don't know how to setup %d/%d/%d\n",
		    pa->pa_bus, pa->pa_device, pa->pa_function);
                return 1;
	}

	pirqreg = pci_conf_read(pc, pci_make_tag(pc, 0, APECS_SIO_DEVICE, 0),
	    SIO_PCIREG_PIRQ_RTCTRL);
	pirqline = (pirqreg >> (pirq * 8)) & 0xff;
	if ((pirqline & 0x80) != 0)
		return 1;
	pirqline &= 0xf;

	*ihp = pirqline;
	return 0;
}

const char *
dec_2100_a50_intr_string(acv, ih)
	void *acv;
	pci_intr_handle_t ih;
{
	return sio_intr_string(NULL /*XXX*/, ih);
}

int
dec_2100_a50_intr_line(acv, ih)
	void *acv;
	pci_intr_handle_t ih;
{
	return sio_intr_line(NULL /*XXX*/, ih);
}

void *
dec_2100_a50_intr_establish(acv, ih, level, func, arg, name)
	void *acv, *arg;
	pci_intr_handle_t ih;
	int level;
	int (*func)(void *);
	const char *name;
{
	return sio_intr_establish(NULL /*XXX*/, ih, IST_LEVEL, level, func,
	    arg, name);
}

void
dec_2100_a50_intr_disestablish(acv, cookie)
	void *acv, *cookie;
{
	sio_intr_disestablish(NULL /*XXX*/, cookie);
}


code:
/*	$OpenBSD: pci_2100_a50.h,v 1.5 2002/03/14 01:26:27 millert Exp $	*/
/*	$NetBSD: pci_2100_a50.h,v 1.3 1996/04/12 06:08:42 cgd Exp $	*/

/*
 * Copyright (c) 1995, 1996 Carnegie-Mellon University.
 * All rights reserved.
 *
 * Author: Chris G. Demetriou
 *
 * Permission to use, copy, modify and distribute this software and
 * its documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie the
 * rights to redistribute these changes.
 */

void	pci_2100_a50_pickintr(struct apecs_config *);


code:
/* $OpenBSD: pci_550.c,v 1.23 2015/07/26 05:09:44 miod Exp $ */
/* $NetBSD: pci_550.c,v 1.18 2000/06/29 08:58:48 mrg Exp $ */

/*-
 * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
 * NASA Ames Research Center, and by Andrew Gallatin.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Copyright (c) 1995, 1996 Carnegie-Mellon University.
 * All rights reserved.
 *
 * Author: Chris G. Demetriou
 *
 * Permission to use, copy, modify and distribute this software and
 * its documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie the
 * rights to redistribute these changes.
 */

#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/malloc.h>
#include <sys/device.h>
#include <sys/syslog.h>

#include <uvm/uvm_extern.h>

#include <machine/autoconf.h>
#include <machine/rpb.h>

#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/ppbreg.h>
#include <dev/pci/pciidereg.h>
#include <dev/pci/pciidevar.h>

#include <alpha/pci/ciareg.h>
#include <alpha/pci/ciavar.h>

#include <alpha/pci/pci_550.h>

#include "sio.h"
#if NSIO
#include <alpha/pci/siovar.h>
#endif

int	dec_550_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
const char *dec_550_intr_string(void *, pci_intr_handle_t);
int	dec_550_intr_line(void *, pci_intr_handle_t);
void	*dec_550_intr_establish(void *, pci_intr_handle_t,
	    int, int (*func)(void *), void *, const char *);
void	dec_550_intr_disestablish(void *, void *);

void	*dec_550_pciide_compat_intr_establish(void *, struct device *,
	    struct pci_attach_args *, int, int (*)(void *), void *);
void    dec_550_pciide_compat_intr_disestablish(void *, void *);

#define	DEC_550_PCI_IRQ_BEGIN	8
#define	DEC_550_MAX_IRQ		(64 - DEC_550_PCI_IRQ_BEGIN)

/*
 * The Miata has a Pyxis, which seems to have problems with stray
 * interrupts.  Work around this by just ignoring strays.
 */
#define	PCI_STRAY_MAX		0

/*
 * Some Miata models, notably models with a Cypress PCI-ISA bridge, have
 * a PCI device (the OHCI USB controller) with interrupts tied to ISA IRQ
 * lines.  This IRQ is encoded as: line = FLAG | isa_irq. Usually FLAG
 * is 0xe0, however it can be 0xf0.  We don't allow 0xf0 | irq15.
 */
#define	DEC_550_LINE_IS_ISA(line)	((line) >= 0xe0 && (line) <= 0xfe)
#define	DEC_550_LINE_ISA_IRQ(line)	((line) & 0x0f)

struct alpha_shared_intr *dec_550_pci_intr;

void	dec_550_iointr(void *arg, unsigned long vec);
void	dec_550_intr_enable(int irq);
void	dec_550_intr_disable(int irq);

void
pci_550_pickintr(ccp)
	struct cia_config *ccp;
{
	bus_space_tag_t iot = &ccp->cc_iot;
	pci_chipset_tag_t pc = &ccp->cc_pc;
#if 0
	char *cp;
#endif
	int i;

        pc->pc_intr_v = ccp;
        pc->pc_intr_map = dec_550_intr_map;
        pc->pc_intr_string = dec_550_intr_string;
        pc->pc_intr_line = dec_550_intr_line;
        pc->pc_intr_establish = dec_550_intr_establish;
        pc->pc_intr_disestablish = dec_550_intr_disestablish;

	pc->pc_pciide_compat_intr_establish =
	    dec_550_pciide_compat_intr_establish;
	pc->pc_pciide_compat_intr_disestablish =
	    dec_550_pciide_compat_intr_disestablish;

	/*
	 * DEC 550's interrupts are enabled via the Pyxis interrupt
	 * mask register.  Nothing to map.
	 */

	for (i = 0; i < DEC_550_MAX_IRQ; i++)
		dec_550_intr_disable(i);

	dec_550_pci_intr = alpha_shared_intr_alloc(DEC_550_MAX_IRQ);
	for (i = 0; i < DEC_550_MAX_IRQ; i++) {
		alpha_shared_intr_set_maxstrays(dec_550_pci_intr, i,
		    PCI_STRAY_MAX);
		alpha_shared_intr_set_private(dec_550_pci_intr, i, ccp);
	}

#if NSIO
	sio_intr_setup(pc, iot);
#endif
}

int
dec_550_intr_map(pa, ihp)
	struct pci_attach_args *pa;
        pci_intr_handle_t *ihp;
{
	int buspin, line = pa->pa_intrline;

	/*
	 * There are two main variants of Miata: Miata 1 (Intel SIO)
	 * and Miata {1.5,2} (Cypress).
	 *
	 * The Miata 1 has a CMD PCI IDE wired to compatibility mode at
	 * device 4 of bus 0.  This variant apparently also has the
	 * Pyxis DMA bug.
	 *
	 * On the Miata 1.5 and Miata 2, the Cypress PCI-ISA bridge lives
	 * on device 7 of bus 0.  This device has PCI IDE wired to
	 * compatibility mode on functions 1 and 2.
	 *
	 * There will be no interrupt mapping for these devices, so just
	 * bail out now.
	 */
	if (pa->pa_bus == 0) {
		if ((hwrpb->rpb_variation & SV_ST_MASK) < SV_ST_MIATA_1_5) {
			/* Miata 1 */
			if (pa->pa_device == 7)
				panic("dec_550_intr_map: SIO device");
			else if (pa->pa_device == 4)
				return (1);
		} else {
			/* Miata 1.5 or Miata 2 */
			if (pa->pa_device == 7) {
				if (pa->pa_function == 0)
					panic("dec_550_intr_map: SIO device");
				if (pa->pa_function == 1 ||
				    pa->pa_function == 2)
					return (1);
			}
		}
	}

	/*
	 * The console places the interrupt mapping in the "line" value.
	 * We trust it whenever possible.
	 */
	if (line >= 0 && line < DEC_550_MAX_IRQ) {
		*ihp = line;
		return 0;
	}
	if (DEC_550_LINE_IS_ISA(line)) {
#if NSIO > 0
		*ihp = line;
		return 0;
#else
		printf("dec_550_intr_map: ISA IRQ %d for %d/%d/%d\n",
		    DEC_550_LINE_ISA_IRQ(line),
		    pa->pa_bus, pa->pa_device, pa->pa_function);
		return 1;
#endif
	}

	if (pa->pa_bridgetag) {
		buspin = PPB_INTERRUPT_SWIZZLE(pa->pa_rawintrpin,
		    pa->pa_device);
		if (pa->pa_bridgeih[buspin - 1] != 0) {
			*ihp = pa->pa_bridgeih[buspin - 1];
			return 0;
		}
	}

	return 1;
}

const char *
dec_550_intr_string(ccv, ih)
	void *ccv;
	pci_intr_handle_t ih;
{
#if 0
	struct cia_config *ccp = ccv;
#endif
	static char irqstr[16];		/* 12 + 2 + NULL + sanity */

#if NSIO
	if (DEC_550_LINE_IS_ISA(ih))
		return (sio_intr_string(NULL /*XXX*/,
		    DEC_550_LINE_ISA_IRQ(ih)));
#endif

	if (ih >= DEC_550_MAX_IRQ)
		panic("dec_550_intr_string: bogus 550 IRQ 0x%lx", ih);
	snprintf(irqstr, sizeof irqstr, "dec 550 irq %ld", ih);
	return (irqstr);
}

int
dec_550_intr_line(ccv, ih)
	void *ccv;
	pci_intr_handle_t ih;
{
#if NSIO
	if (DEC_550_LINE_IS_ISA(ih))
		return (sio_intr_line(NULL /*XXX*/, DEC_550_LINE_ISA_IRQ(ih)));
#endif

	return (ih);
}

void *
dec_550_intr_establish(ccv, ih, level, func, arg, name)
	void *ccv, *arg;
	pci_intr_handle_t ih;
	int level;
	int (*func)(void *);
	const char *name;
{
#if 0
	struct cia_config *ccp = ccv;
#endif
	void *cookie;

#if NSIO
	if (DEC_550_LINE_IS_ISA(ih))
		return (sio_intr_establish(NULL /*XXX*/,
		    DEC_550_LINE_ISA_IRQ(ih), IST_LEVEL, level, func, arg,
		    name));
#endif

	if (ih >= DEC_550_MAX_IRQ)
		panic("dec_550_intr_establish: bogus dec 550 IRQ 0x%lx", ih);

	cookie = alpha_shared_intr_establish(dec_550_pci_intr, ih, IST_LEVEL,
	    level, func, arg, name);

	if (cookie != NULL &&
	    alpha_shared_intr_firstactive(dec_550_pci_intr, ih)) {
		scb_set(0x900 + SCB_IDXTOVEC(ih), dec_550_iointr, NULL);
		dec_550_intr_enable(ih);
	}
	return (cookie);
}

void
dec_550_intr_disestablish(ccv, cookie)
        void *ccv, *cookie;
{
	struct cia_config *ccp = ccv;
	struct alpha_shared_intrhand *ih = cookie;
	unsigned int irq = ih->ih_num;
	int s;

#if NSIO
	/*
	 * We have to determine if this is an ISA IRQ or not!  We do this
	 * by checking to see if the intrhand points back to an intrhead
	 * that points to our cia_config.  If not, it's an ISA IRQ.  Pretty
	 * disgusting, eh?
	 */
	if (ih->ih_intrhead->intr_private != ccp) {
		sio_intr_disestablish(NULL /*XXX*/, cookie);
		return;
	}
#endif

	s = splhigh();

	alpha_shared_intr_disestablish(dec_550_pci_intr, cookie);
	if (alpha_shared_intr_isactive(dec_550_pci_intr, irq) == 0) {
		dec_550_intr_disable(irq);
		alpha_shared_intr_set_dfltsharetype(dec_550_pci_intr, irq,
		    IST_NONE);
		scb_free(0x900 + SCB_IDXTOVEC(irq));
	}

	splx(s);
}

void *
dec_550_pciide_compat_intr_establish(v, dev, pa, chan, func, arg)
	void *v;
	struct device *dev;
	struct pci_attach_args *pa;
	int chan;
	int (*func)(void *);
	void *arg;
{
	pci_chipset_tag_t pc = pa->pa_pc;
	void *cookie = NULL;
	int bus, irq;

	pci_decompose_tag(pc, pa->pa_tag, &bus, NULL, NULL);

	/*
	 * If this isn't PCI bus #0, all bets are off.
	 */
	if (bus != 0)
		return (NULL);

	irq = PCIIDE_COMPAT_IRQ(chan);
#if NSIO
	cookie = sio_intr_establish(NULL /*XXX*/, irq, IST_EDGE, IPL_BIO,
	    func, arg, dev->dv_xname);
#endif
	return (cookie);
}

void
dec_550_pciide_compat_intr_disestablish(v, cookie)
	void *v;
	void *cookie;
{
	sio_intr_disestablish(NULL, cookie);
}

void
dec_550_iointr(arg, vec)
	void *arg;
	unsigned long vec;
{
	int irq;

	irq = SCB_VECTOIDX(vec - 0x900);

	if (irq >= DEC_550_MAX_IRQ)
		panic("550_iointr: vec 0x%lx out of range", vec);

	if (!alpha_shared_intr_dispatch(dec_550_pci_intr, irq)) {
		alpha_shared_intr_stray(dec_550_pci_intr, irq,
		    "dec 550 irq");
		if (ALPHA_SHARED_INTR_DISABLE(dec_550_pci_intr, irq))
			dec_550_intr_disable(irq);
	} else
		alpha_shared_intr_reset_strays(dec_550_pci_intr, irq);
}

void
dec_550_intr_enable(irq)
	int irq;
{

	cia_pyxis_intr_enable(irq + DEC_550_PCI_IRQ_BEGIN, 1);
}

void
dec_550_intr_disable(irq)
	int irq;
{

	cia_pyxis_intr_enable(irq + DEC_550_PCI_IRQ_BEGIN, 0);
}


code:
/* $OpenBSD: pci_550.h,v 1.3 2002/03/14 01:26:27 millert Exp $ */
/* $NetBSD: pci_550.h,v 1.4 2000/06/05 21:47:23 thorpej Exp $ */

/*
 * Copyright (c) 1995, 1996 Carnegie-Mellon University.
 * All rights reserved.
 *
 * Author: Chris G. Demetriou
 *
 * Permission to use, copy, modify and distribute this software and
 * its documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie the
 * rights to redistribute these changes.
 */

void	pci_550_pickintr(struct cia_config *);


code:
/* $OpenBSD: pci_6600.c,v 1.21 2015/07/26 05:09:44 miod Exp $ */
/* $NetBSD: pci_6600.c,v 1.5 2000/06/06 00:50:15 thorpej Exp $ */

/*-
 * Copyright (c) 1999 by Ross Harvey.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by Ross Harvey.
 * 4. The name of Ross Harvey may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY ROSS HARVEY ``AS IS'' AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURP0SE
 * ARE DISCLAIMED.  IN NO EVENT SHALL ROSS HARVEY BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/malloc.h>

#include <machine/autoconf.h>
#define _ALPHA_BUS_DMA_PRIVATE
#include <machine/bus.h>
#include <machine/rpb.h>

#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/ppbreg.h>
#include <dev/pci/pciidereg.h>
#include <dev/pci/pciidevar.h>

#include <alpha/pci/tsreg.h>
#include <alpha/pci/tsvar.h>
#include <alpha/pci/pci_6600.h>

#define pci_6600() { Generate ctags(1) key. }

#include "sio.h"
#if NSIO
#include <alpha/pci/siovar.h>
#endif

#define	PCI_NIRQ		64
#define	PCI_STRAY_MAX		5

/*
 * Some Tsunami models have a PCI device (the USB controller) with interrupts
 * tied to ISA IRQ lines.  The IRQ is encoded as:
 *
 *	line = 0xe0 | isa_irq;
 */
#define	DEC_6600_LINE_IS_ISA(line)	((line) >= 0xe0 && (line) <= 0xef)
#define	DEC_6600_LINE_ISA_IRQ(line)	((line) & 0x0f)

static struct tsp_config *sioprimary;

void dec_6600_intr_disestablish(void *, void *);
void *dec_6600_intr_establish(void *, pci_intr_handle_t, int,
    int (*func)(void *), void *, const char *);
const char *dec_6600_intr_string(void *, pci_intr_handle_t);
int dec_6600_intr_line(void *, pci_intr_handle_t);
int dec_6600_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
void *dec_6600_pciide_compat_intr_establish(void *, struct device *,
    struct pci_attach_args *, int, int (*)(void *), void *);
void  dec_6600_pciide_compat_intr_disestablish(void *, void *);

struct alpha_shared_intr *dec_6600_pci_intr;

void dec_6600_iointr(void *arg, unsigned long vec);
extern void dec_6600_intr_enable(int irq);
extern void dec_6600_intr_disable(int irq);

void
pci_6600_pickintr(pcp)
	struct tsp_config *pcp;
{
	bus_space_tag_t iot = &pcp->pc_iot;
	pci_chipset_tag_t pc = &pcp->pc_pc;
#if 0
	char *cp;
#endif
	int i;

        pc->pc_intr_v = pcp;
        pc->pc_intr_map = dec_6600_intr_map;
        pc->pc_intr_string = dec_6600_intr_string;
        pc->pc_intr_line = dec_6600_intr_line;
        pc->pc_intr_establish = dec_6600_intr_establish;
        pc->pc_intr_disestablish = dec_6600_intr_disestablish;
	pc->pc_pciide_compat_intr_establish = NULL;

	/*
	 * System-wide and Pchip-0-only logic...
	 */
	if (dec_6600_pci_intr == NULL) {
		sioprimary = pcp;
		pc->pc_pciide_compat_intr_establish =
		    dec_6600_pciide_compat_intr_establish;
		dec_6600_pci_intr = alpha_shared_intr_alloc(PCI_NIRQ);
		for (i = 0; i < PCI_NIRQ; i++) {
			alpha_shared_intr_set_maxstrays(dec_6600_pci_intr, i,
			    PCI_STRAY_MAX);
			alpha_shared_intr_set_private(dec_6600_pci_intr, i,
			    sioprimary);
		}
#if NSIO
		sio_intr_setup(pc, iot);
		dec_6600_intr_enable(55);	/* irq line for sio */
#endif
	}
}

int
dec_6600_intr_map(pa, ihp)
	struct pci_attach_args *pa;
        pci_intr_handle_t *ihp;
{
	int buspin, line = pa->pa_intrline;

	/*
	 * The console places the interrupt mapping in the "line" value.
	 * We trust it whenever possible.
	 */
	if (line >= 0 && line < PCI_NIRQ) {
		*ihp = line;
		return 0;
	}
	if (DEC_6600_LINE_IS_ISA(line)) {
#if NSIO > 0
		*ihp = line;
		return 0;
#else
		printf("dec_6600_intr_map: ISA IRQ %d for %d/%d/%d\n",
		    DEC_6600_LINE_ISA_IRQ(line),
		    pa->pa_bus, pa->pa_device, pa->pa_function);
		return 1;
#endif
	}

	if (pa->pa_bridgetag) {
		buspin = PPB_INTERRUPT_SWIZZLE(pa->pa_rawintrpin,
		    pa->pa_device);
		if (pa->pa_bridgeih[buspin - 1] != 0) {
			*ihp = pa->pa_bridgeih[buspin - 1];
			return 0;
		}
	}

	return 1;
}

const char *
dec_6600_intr_string(acv, ih)
	void *acv;
	pci_intr_handle_t ih;
{

	static const char irqfmt[] = "dec 6600 irq %ld";
	static char irqstr[sizeof irqfmt];

#if NSIO
	if (DEC_6600_LINE_IS_ISA(ih))
		return (sio_intr_string(NULL /*XXX*/,
		    DEC_6600_LINE_ISA_IRQ(ih)));
#endif

	snprintf(irqstr, sizeof irqstr, irqfmt, ih);
	return (irqstr);
}

int
dec_6600_intr_line(acv, ih)
	void *acv;
	pci_intr_handle_t ih;
{

#if NSIO
	if (DEC_6600_LINE_IS_ISA(ih))
		return (sio_intr_line(NULL /*XXX*/,
		    DEC_6600_LINE_ISA_IRQ(ih)));
#endif

	return (ih);
}

void *
dec_6600_intr_establish(acv, ih, level, func, arg, name)
        void *acv, *arg;
        pci_intr_handle_t ih;
        int level;
        int (*func)(void *);
	const char *name;
{
	void *cookie;

#if NSIO
	if (DEC_6600_LINE_IS_ISA(ih))
		return (sio_intr_establish(NULL /*XXX*/,
		    DEC_6600_LINE_ISA_IRQ(ih), IST_LEVEL, level, func, arg,
	            name));
#endif

	if (ih >= PCI_NIRQ)
		panic("dec_6600_intr_establish: bogus dec 6600 IRQ 0x%lx",
		    ih);

	cookie = alpha_shared_intr_establish(dec_6600_pci_intr, ih, IST_LEVEL,
	    level, func, arg, name);

	if (cookie != NULL &&
	    alpha_shared_intr_firstactive(dec_6600_pci_intr, ih)) {
		scb_set(0x900 + SCB_IDXTOVEC(ih), dec_6600_iointr, NULL);
		dec_6600_intr_enable(ih);
	}
	return (cookie);
}

void
dec_6600_intr_disestablish(acv, cookie)
        void *acv, *cookie;
{
	struct alpha_shared_intrhand *ih = cookie;
	unsigned int irq = ih->ih_num;
	int s;

#if NSIO
	/*
	 * We have to determine if this is an ISA IRQ or not!  We do this
	 * by checking to see if the intrhand points back to an intrhead
	 * that points to the sioprimary TSP.  If not, it's an ISA IRQ.
	 * Pretty disgusting, eh?
	 */
	if (ih->ih_intrhead->intr_private != sioprimary) {
		sio_intr_disestablish(NULL /*XXX*/, cookie);
		return;
	}
#endif

	s = splhigh();

	alpha_shared_intr_disestablish(dec_6600_pci_intr, cookie);
	if (alpha_shared_intr_isactive(dec_6600_pci_intr, irq) == 0) {
		dec_6600_intr_disable(irq);
		alpha_shared_intr_set_dfltsharetype(dec_6600_pci_intr, irq,
		    IST_NONE);
		scb_free(0x900 + SCB_IDXTOVEC(irq));
	}

	splx(s);
}

void
dec_6600_iointr(arg, vec)
	void *arg;
	unsigned long vec;
{
	int irq;

	irq = SCB_VECTOIDX(vec - 0x900);

	if (irq >= PCI_NIRQ)
		panic("dec_6600_iointr: irq %d is too high", irq);

	if (!alpha_shared_intr_dispatch(dec_6600_pci_intr, irq)) {
		alpha_shared_intr_stray(dec_6600_pci_intr, irq, "6600 irq");
		if (ALPHA_SHARED_INTR_DISABLE(dec_6600_pci_intr, irq))
			dec_6600_intr_disable(irq);
	} else
		alpha_shared_intr_reset_strays(dec_6600_pci_intr, irq);
}

void
dec_6600_intr_enable(irq)
	int irq;
{
	alpha_mb();
	STQP(TS_C_DIM0) |= 1UL << irq;
	alpha_mb();
}

void
dec_6600_intr_disable(irq)
	int irq;
{
	alpha_mb();
	STQP(TS_C_DIM0) &= ~(1UL << irq);
	alpha_mb();
}

void *
dec_6600_pciide_compat_intr_establish(v, dev, pa, chan, func, arg)
	void *v;
	struct device *dev;
	struct pci_attach_args *pa;
	int chan;
	int (*func)(void *);
	void *arg;
{
	pci_chipset_tag_t pc = pa->pa_pc;
	void *cookie = NULL;
	int bus, irq;

	pci_decompose_tag(pc, pa->pa_tag, &bus, NULL, NULL);

	/*
	 * If this isn't PCI bus #0 on the TSP that holds the PCI-ISA
	 * bridge, all bets are off.
	 */
	if (bus != 0 || pc->pc_intr_v != sioprimary)
		return (NULL);

	irq = PCIIDE_COMPAT_IRQ(chan);
#if NSIO
	cookie = sio_intr_establish(NULL /*XXX*/, irq, IST_EDGE, IPL_BIO,
	    func, arg, dev->dv_xname);

	if (cookie == NULL)
		return (NULL);
#endif
	return (cookie);
}

void
dec_6600_pciide_compat_intr_disestablish(v, cookie)
	void *v;
	void *cookie;
{
	sio_intr_disestablish(NULL, cookie);
}


code:
/* $OpenBSD: pci_6600.h,v 1.2 2002/03/14 01:26:27 millert Exp $ */
/* $NetBSD$ */

/* Public Domain */

void pci_6600_pickintr(struct tsp_config *);


code:
/* $OpenBSD: pci_alphabook1.c,v 1.3 2015/07/26 05:09:44 miod Exp $ */
/* $NetBSD: pci_alphabook1.c,v 1.16 2012/02/06 02:14:15 matt Exp $ */

/*-
 * Copyright (c) 1998 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
 * NASA Ames Research Center.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Copyright (c) 1995, 1996 Carnegie-Mellon University.
 * All rights reserved.
 *
 * Authors: Jeffrey Hsu and Chris G. Demetriou
 *
 * Permission to use, copy, modify and distribute this software and
 * its documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie the
 * rights to redistribute these changes.
 */

#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/device.h>

#include <machine/intr.h>

#include <dev/isa/isavar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/ppbreg.h>

#include <alpha/pci/lcavar.h>

#include <alpha/pci/pci_alphabook1.h>
#include <alpha/pci/siovar.h>
#include <alpha/pci/sioreg.h>

#include "sio.h"

int     dec_alphabook1_intr_map(struct pci_attach_args *,
	    pci_intr_handle_t *);
const char *dec_alphabook1_intr_string(void *, pci_intr_handle_t);
int	 dec_alphabook1_intr_line(void *, pci_intr_handle_t);
void    *dec_alphabook1_intr_establish(void *, pci_intr_handle_t,
	    int, int (*func)(void *), void *, const char *);
void    dec_alphabook1_intr_disestablish(void *, void *);

#define	LCA_SIO_DEVICE	7	/* XXX */

void
pci_alphabook1_pickintr(struct lca_config *lcp)
{
	bus_space_tag_t iot = &lcp->lc_iot;
	pci_chipset_tag_t pc = &lcp->lc_pc;
	pcireg_t sioclass;
	int sioII;

	/* XXX MAGIC NUMBER */
	sioclass = pci_conf_read(pc, pci_make_tag(pc, 0, LCA_SIO_DEVICE, 0),
	    PCI_CLASS_REG);
	sioII = (sioclass & 0xff) >= 3;

	if (!sioII)
		printf("WARNING: SIO NOT SIO II... NO BETS...\n");

	pc->pc_intr_v = lcp;
	pc->pc_intr_map = dec_alphabook1_intr_map;
	pc->pc_intr_string = dec_alphabook1_intr_string;
	pc->pc_intr_line = dec_alphabook1_intr_line;
	pc->pc_intr_establish = dec_alphabook1_intr_establish;
	pc->pc_intr_disestablish = dec_alphabook1_intr_disestablish;

	/* Not supported on AlphaBook. */
	pc->pc_pciide_compat_intr_establish = NULL;

#if NSIO
	sio_intr_setup(pc, iot);
#else
	panic("pci_alphabook1_pickintr: no I/O interrupt handler (no sio)");
#endif
}

int
dec_alphabook1_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
{
	pcitag_t bustag = pa->pa_intrtag;
	int buspin, device;

#ifdef notyet
	if (pa->pa_bridgetag) {
		buspin = PPB_INTERRUPT_SWIZZLE(pa->pa_rawintrpin,
		    pa->pa_device);
		if (pa->pa_bridgeih[buspin - 1] == 0)
			return 1;

		*ihp = pa->pa_bridgeih[buspin - 1];
		return 0;
	}
#endif

	buspin = pa->pa_intrpin;
	pci_decompose_tag(pa->pa_pc, bustag, NULL, &device, NULL);

	/*
	 * There are only two interrupting PCI devices on the AlphaBook:
	 * the SCSI and PCMCIA controllers. The other PCI device is the
	 * SIO, and there are no option slots available.
	 *
	 * NOTE!  Apparently, there was a later AlphaBook which uses
	 * a different interrupt scheme, and has a built-in Tulip Ethernet
	 * interface!  We do not handle that here!
	 */

	switch (device) {
	case 6:					/* NCR SCSI */
		*ihp = 14;
		return 0;
	case 8:					/* Cirrus CL-PD6729 */
		*ihp = 15;
		return 0;
	default:
	        return 1;
	}
}

const char *
dec_alphabook1_intr_string(void *lcv, pci_intr_handle_t ih)
{
	return sio_intr_string(NULL /*XXX*/, ih);
}

int
dec_alphabook1_intr_line(void *lcv, pci_intr_handle_t ih)
{
	return sio_intr_line(NULL /*XXX*/, ih);
}

void *
dec_alphabook1_intr_establish(void *lcv, pci_intr_handle_t ih,
    int level, int (*func)(void *), void *arg, const char *name)
{
	/*
	 * PCI interrupts on that platform are ISA interrupts in disguise,
	 * and are edge- rather than level-triggered.
	 */
	return sio_intr_establish(NULL /*XXX*/, ih, IST_EDGE, level, func,
	    arg, name);
}

void
dec_alphabook1_intr_disestablish(void *lcv, void *cookie)
{
	sio_intr_disestablish(NULL /*XXX*/, cookie);
}


code:
/* $NetBSD: pci_alphabook1.h,v 1.2 2009/03/14 14:45:53 dsl Exp $ */

/*
 * Copyright (c) 1995, 1996 Carnegie-Mellon University.
 * All rights reserved.
 *
 * Author: Chris G. Demetriou
 *
 * Permission to use, copy, modify and distribute this software and
 * its documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie the
 * rights to redistribute these changes.
 */

void	pci_alphabook1_pickintr(struct lca_config *);


code:
/*	$OpenBSD: pci_axppci_33.c,v 1.21 2015/07/26 05:09:44 miod Exp $	*/
/*	$NetBSD: pci_axppci_33.c,v 1.10 1996/11/13 21:13:29 cgd Exp $	*/

/*
 * Copyright (c) 1995, 1996 Carnegie-Mellon University.
 * All rights reserved.
 *
 * Authors: Jeffrey Hsu and Chris G. Demetriou
 *
 * Permission to use, copy, modify and distribute this software and
 * its documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie the
 * rights to redistribute these changes.
 */

#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/device.h>
#include <uvm/uvm_extern.h>

#include <machine/autoconf.h>
#include <machine/bus.h>
#include <machine/intr.h>

#include <dev/isa/isavar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/ppbreg.h>

#include <alpha/pci/lcavar.h>

#include <alpha/pci/pci_axppci_33.h>
#include <alpha/pci/siovar.h>
#include <alpha/pci/sioreg.h>

#include "sio.h"

int     dec_axppci_33_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
const char *dec_axppci_33_intr_string(void *, pci_intr_handle_t);
int	dec_axppci_33_intr_line(void *, pci_intr_handle_t);
void    *dec_axppci_33_intr_establish(void *, pci_intr_handle_t,
	    int, int (*func)(void *), void *, const char *);
void    dec_axppci_33_intr_disestablish(void *, void *);

#define	LCA_SIO_DEVICE	7	/* XXX */

void
pci_axppci_33_pickintr(lcp)
	struct lca_config *lcp;
{
	bus_space_tag_t iot = &lcp->lc_iot;
	pci_chipset_tag_t pc = &lcp->lc_pc;
	pcireg_t sioclass;
	int sioII;

	/* XXX MAGIC NUMBER */
	sioclass = pci_conf_read(pc, pci_make_tag(pc, 0, LCA_SIO_DEVICE, 0),
	    PCI_CLASS_REG);
        sioII = (sioclass & 0xff) >= 3;

	if (!sioII)
		printf("WARNING: SIO NOT SIO II... NO BETS...\n");

	pc->pc_intr_v = lcp;
	pc->pc_intr_map = dec_axppci_33_intr_map;
	pc->pc_intr_string = dec_axppci_33_intr_string;
	pc->pc_intr_line = dec_axppci_33_intr_line;
	pc->pc_intr_establish = dec_axppci_33_intr_establish;
	pc->pc_intr_disestablish = dec_axppci_33_intr_disestablish;

        /* Not supported on AXPpci33. */
        pc->pc_pciide_compat_intr_establish = NULL;
        pc->pc_pciide_compat_intr_disestablish = NULL;

#if NSIO > 0
	sio_intr_setup(pc, iot);
#else
	panic("pci_axppci_33_pickintr: no I/O interrupt handler (no sio)");
#endif
}

int
dec_axppci_33_intr_map(pa, ihp)
	struct pci_attach_args *pa;
	pci_intr_handle_t *ihp;
{
	pcitag_t bustag = pa->pa_intrtag;
	pci_chipset_tag_t pc = pa->pa_pc;
	int buspin, device, pirq;
	pcireg_t pirqreg;
	u_int8_t pirqline;

	if (pa->pa_bridgetag) {
		buspin = PPB_INTERRUPT_SWIZZLE(pa->pa_rawintrpin,
		    pa->pa_device);
		if (pa->pa_bridgeih[buspin - 1] != 0) {
			*ihp = pa->pa_bridgeih[buspin - 1];
			return 0;
		}

		return 1;
	}

	buspin = pa->pa_intrpin;
	pci_decompose_tag(pc, bustag, NULL, &device, NULL);

	switch (device) {
	case 6:					/* NCR SCSI */
		pirq = 3;
		break;

	case 11:				/* slot 1 */
		switch (buspin) {
		default:
		case PCI_INTERRUPT_PIN_A:
		case PCI_INTERRUPT_PIN_D:
			pirq = 0;
			break;
		case PCI_INTERRUPT_PIN_B:
			pirq = 2;
			break;
		case PCI_INTERRUPT_PIN_C:
			pirq = 1;
			break;
		};
		break;

	case 12:				/* slot 2 */
		switch (buspin) {
		default:
		case PCI_INTERRUPT_PIN_A:
		case PCI_INTERRUPT_PIN_D:
			pirq = 1;
			break;
		case PCI_INTERRUPT_PIN_B:
			pirq = 0;
			break;
		case PCI_INTERRUPT_PIN_C:
			pirq = 2;
			break;
		};
		break;

	case 8:				/* slot 3 */
		switch (buspin) {
		default:
		case PCI_INTERRUPT_PIN_A:
		case PCI_INTERRUPT_PIN_D:
			pirq = 2;
			break;
		case PCI_INTERRUPT_PIN_B:
			pirq = 1;
			break;
		case PCI_INTERRUPT_PIN_C:
			pirq = 0;
			break;
		};
		break;

	default:
                return 1;
	}

	pirqreg = pci_conf_read(pc, pci_make_tag(pc, 0, LCA_SIO_DEVICE, 0),
	    SIO_PCIREG_PIRQ_RTCTRL);

	pirqline = (pirqreg >> (pirq * 8)) & 0xff;
	if ((pirqline & 0x80) != 0)
		return 1;			/* not routed? */
	pirqline &= 0xf;

	*ihp = pirqline;
	return (0);
}

const char *
dec_axppci_33_intr_string(lcv, ih)
	void *lcv;
	pci_intr_handle_t ih;
{
	return sio_intr_string(NULL /*XXX*/, ih);
}

int
dec_axppci_33_intr_line(lcv, ih)
	void *lcv;
	pci_intr_handle_t ih;
{
	return sio_intr_line(NULL /*XXX*/, ih);
}

void *
dec_axppci_33_intr_establish(lcv, ih, level, func, arg, name)
	void *lcv, *arg;
	pci_intr_handle_t ih;
	int level;
	int (*func)(void *);
	const char *name;
{
	return sio_intr_establish(NULL /*XXX*/, ih, IST_LEVEL, level, func,
	    arg, name);
}

void
dec_axppci_33_intr_disestablish(lcv, cookie)
	void *lcv, *cookie;
{
	sio_intr_disestablish(NULL /*XXX*/, cookie);
}


code:
/*	$OpenBSD: pci_axppci_33.h,v 1.5 2002/03/14 01:26:27 millert Exp $	*/
/*	$NetBSD: pci_axppci_33.h,v 1.3 1996/04/12 06:08:47 cgd Exp $	*/

/*
 * Copyright (c) 1995, 1996 Carnegie-Mellon University.
 * All rights reserved.
 *
 * Author: Chris G. Demetriou
 *
 * Permission to use, copy, modify and distribute this software and
 * its documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie the
 * rights to redistribute these changes.
 */

void	pci_axppci_33_pickintr(struct lca_config *);