code:
/* $OpenBSD: pci_bwx_bus_io_chipdep.c,v 1.9 2009/12/25 20:52:34 miod Exp $ */
/* $NetBSD: pcs_bus_io_common.c,v 1.14 1996/12/02 22:19:35 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.
 */

/*
 * Common PCI Chipset "bus I/O" functions, for chipsets which have to
 * deal with only a single PCI interface chip in a machine.
 *
 * uses:
 *	CHIP		name of the 'chip' it's being compiled for.
 *	CHIP_IO_BASE	Sparse I/O space base to use.
 */

#include <sys/extent.h>

#include <machine/bwx.h>

#define	__C(A,B)	__CONCAT(A,B)
#define	__S(S)		__STRING(S)

#ifndef	CHIP_EXTENT_NAME
#define	CHIP_EXTENT_NAME(v)	__S(__C(CHIP,_bus_io))
#endif

#ifndef	CHIP_EXTENT_STORAGE
#define CHIP_EXTENT_STORAGE(v)	__C(CHIP,_io_ex_storage)
static long
    __C(CHIP,_io_ex_storage)[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];
#endif

/* mapping/unmapping */
int		__C(CHIP,_io_map)(void *, bus_addr_t, bus_size_t, int,
		    bus_space_handle_t *);
void		__C(CHIP,_io_unmap)(void *, bus_space_handle_t,
		    bus_size_t);
int		__C(CHIP,_io_subregion)(void *, bus_space_handle_t,
		    bus_size_t, bus_size_t, bus_space_handle_t *);

/* allocation/deallocation */
int		__C(CHIP,_io_alloc)(void *, bus_addr_t, bus_addr_t,
		    bus_size_t, bus_size_t, bus_addr_t, int, bus_addr_t *,
                    bus_space_handle_t *);
void		__C(CHIP,_io_free)(void *, bus_space_handle_t,
		    bus_size_t);

/* get kernel virtual address */
void *		__C(CHIP,_io_vaddr)(void *, bus_space_handle_t);

/* barrier */
inline void	__C(CHIP,_io_barrier)(void *, bus_space_handle_t,
		    bus_size_t, bus_size_t, int);

/* read (single) */
inline u_int8_t	__C(CHIP,_io_read_1)(void *, bus_space_handle_t,
		    bus_size_t);
inline u_int16_t __C(CHIP,_io_read_2)(void *, bus_space_handle_t,
		    bus_size_t);
inline u_int32_t __C(CHIP,_io_read_4)(void *, bus_space_handle_t,
		    bus_size_t);
inline u_int64_t __C(CHIP,_io_read_8)(void *, bus_space_handle_t,
		    bus_size_t);

/* read multiple */
void		__C(CHIP,_io_read_multi_1)(void *, bus_space_handle_t,
		    bus_size_t, u_int8_t *, bus_size_t);
void		__C(CHIP,_io_read_multi_2)(void *, bus_space_handle_t,
		    bus_size_t, u_int16_t *, bus_size_t);
void		__C(CHIP,_io_read_multi_4)(void *, bus_space_handle_t,
		    bus_size_t, u_int32_t *, bus_size_t);
void		__C(CHIP,_io_read_multi_8)(void *, bus_space_handle_t,
		    bus_size_t, u_int64_t *, bus_size_t);

/* read region */
void		__C(CHIP,_io_read_region_1)(void *, bus_space_handle_t,
		    bus_size_t, u_int8_t *, bus_size_t);
void		__C(CHIP,_io_read_region_2)(void *, bus_space_handle_t,
		    bus_size_t, u_int16_t *, bus_size_t);
void		__C(CHIP,_io_read_region_4)(void *, bus_space_handle_t,
		    bus_size_t, u_int32_t *, bus_size_t);
void		__C(CHIP,_io_read_region_8)(void *, bus_space_handle_t,
		    bus_size_t, u_int64_t *, bus_size_t);

/* write (single) */
inline void	__C(CHIP,_io_write_1)(void *, bus_space_handle_t,
		    bus_size_t, u_int8_t);
inline void	__C(CHIP,_io_write_2)(void *, bus_space_handle_t,
		    bus_size_t, u_int16_t);
inline void	__C(CHIP,_io_write_4)(void *, bus_space_handle_t,
		    bus_size_t, u_int32_t);
inline void	__C(CHIP,_io_write_8)(void *, bus_space_handle_t,
		    bus_size_t, u_int64_t);

/* write multiple */
void		__C(CHIP,_io_write_multi_1)(void *, bus_space_handle_t,
		    bus_size_t, const u_int8_t *, bus_size_t);
void		__C(CHIP,_io_write_multi_2)(void *, bus_space_handle_t,
		    bus_size_t, const u_int16_t *, bus_size_t);
void		__C(CHIP,_io_write_multi_4)(void *, bus_space_handle_t,
		    bus_size_t, const u_int32_t *, bus_size_t);
void		__C(CHIP,_io_write_multi_8)(void *, bus_space_handle_t,
		    bus_size_t, const u_int64_t *, bus_size_t);

/* write region */
void		__C(CHIP,_io_write_region_1)(void *, bus_space_handle_t,
		    bus_size_t, const u_int8_t *, bus_size_t);
void		__C(CHIP,_io_write_region_2)(void *, bus_space_handle_t,
		    bus_size_t, const u_int16_t *, bus_size_t);
void		__C(CHIP,_io_write_region_4)(void *, bus_space_handle_t,
		    bus_size_t, const u_int32_t *, bus_size_t);
void		__C(CHIP,_io_write_region_8)(void *, bus_space_handle_t,
		    bus_size_t, const u_int64_t *, bus_size_t);

/* set multiple */
void		__C(CHIP,_io_set_multi_1)(void *, bus_space_handle_t,
		    bus_size_t, u_int8_t, bus_size_t);
void		__C(CHIP,_io_set_multi_2)(void *, bus_space_handle_t,
		    bus_size_t, u_int16_t, bus_size_t);
void		__C(CHIP,_io_set_multi_4)(void *, bus_space_handle_t,
		    bus_size_t, u_int32_t, bus_size_t);
void		__C(CHIP,_io_set_multi_8)(void *, bus_space_handle_t,
		    bus_size_t, u_int64_t, bus_size_t);

/* set region */
void		__C(CHIP,_io_set_region_1)(void *, bus_space_handle_t,
		    bus_size_t, u_int8_t, bus_size_t);
void		__C(CHIP,_io_set_region_2)(void *, bus_space_handle_t,
		    bus_size_t, u_int16_t, bus_size_t);
void		__C(CHIP,_io_set_region_4)(void *, bus_space_handle_t,
		    bus_size_t, u_int32_t, bus_size_t);
void		__C(CHIP,_io_set_region_8)(void *, bus_space_handle_t,
		    bus_size_t, u_int64_t, bus_size_t);

/* copy */
void		__C(CHIP,_io_copy_1)(void *, bus_space_handle_t,
		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t);
void		__C(CHIP,_io_copy_2)(void *, bus_space_handle_t,
		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t);
void		__C(CHIP,_io_copy_4)(void *, bus_space_handle_t,
		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t);
void		__C(CHIP,_io_copy_8)(void *, bus_space_handle_t,
		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t);

/* read multiple raw */
void		__C(CHIP,_io_read_raw_multi_2)(void *, bus_space_handle_t,
		    bus_size_t, u_int8_t *, bus_size_t);
void		__C(CHIP,_io_read_raw_multi_4)(void *, bus_space_handle_t,
		    bus_size_t, u_int8_t *, bus_size_t);
void		__C(CHIP,_io_read_raw_multi_8)(void *, bus_space_handle_t,
		    bus_size_t, u_int8_t *, bus_size_t);

/* write multiple raw */
void		__C(CHIP,_io_write_raw_multi_2)(void *,
		    bus_space_handle_t, bus_size_t, const u_int8_t *,
		    bus_size_t);
void		__C(CHIP,_io_write_raw_multi_4)(void *,
		    bus_space_handle_t, bus_size_t, const u_int8_t *,
		    bus_size_t);
void		__C(CHIP,_io_write_raw_multi_8)(void *,
		    bus_space_handle_t, bus_size_t, const u_int8_t *,
		    bus_size_t);

void
__C(CHIP,_bus_io_init)(t, v)
	bus_space_tag_t t;
	void *v;
{
	struct extent *ex;

	/*
	 * Initialize the bus space tag.
	 */

	/* cookie */
	t->abs_cookie =		v;

	/* mapping/unmapping */
	t->abs_map =		__C(CHIP,_io_map);
	t->abs_unmap =		__C(CHIP,_io_unmap);
	t->abs_subregion =	__C(CHIP,_io_subregion);

	/* allocation/deallocation */
	t->abs_alloc =		__C(CHIP,_io_alloc);
	t->abs_free = 		__C(CHIP,_io_free);

	/* get kernel virtual address */
	t->abs_vaddr =		__C(CHIP,_io_vaddr);

	/* barrier */
	t->abs_barrier =	__C(CHIP,_io_barrier);

	/* read (single) */
	t->abs_r_1 =		__C(CHIP,_io_read_1);
	t->abs_r_2 =		__C(CHIP,_io_read_2);
	t->abs_r_4 =		__C(CHIP,_io_read_4);
	t->abs_r_8 =		__C(CHIP,_io_read_8);

	/* read multiple */
	t->abs_rm_1 =		__C(CHIP,_io_read_multi_1);
	t->abs_rm_2 =		__C(CHIP,_io_read_multi_2);
	t->abs_rm_4 =		__C(CHIP,_io_read_multi_4);
	t->abs_rm_8 =		__C(CHIP,_io_read_multi_8);

	/* read region */
	t->abs_rr_1 =		__C(CHIP,_io_read_region_1);
	t->abs_rr_2 =		__C(CHIP,_io_read_region_2);
	t->abs_rr_4 =		__C(CHIP,_io_read_region_4);
	t->abs_rr_8 =		__C(CHIP,_io_read_region_8);

	/* write (single) */
	t->abs_w_1 =		__C(CHIP,_io_write_1);
	t->abs_w_2 =		__C(CHIP,_io_write_2);
	t->abs_w_4 =		__C(CHIP,_io_write_4);
	t->abs_w_8 =		__C(CHIP,_io_write_8);

	/* write multiple */
	t->abs_wm_1 =		__C(CHIP,_io_write_multi_1);
	t->abs_wm_2 =		__C(CHIP,_io_write_multi_2);
	t->abs_wm_4 =		__C(CHIP,_io_write_multi_4);
	t->abs_wm_8 =		__C(CHIP,_io_write_multi_8);

	/* write region */
	t->abs_wr_1 =		__C(CHIP,_io_write_region_1);
	t->abs_wr_2 =		__C(CHIP,_io_write_region_2);
	t->abs_wr_4 =		__C(CHIP,_io_write_region_4);
	t->abs_wr_8 =		__C(CHIP,_io_write_region_8);

	/* set multiple */
	t->abs_sm_1 =		__C(CHIP,_io_set_multi_1);
	t->abs_sm_2 =		__C(CHIP,_io_set_multi_2);
	t->abs_sm_4 =		__C(CHIP,_io_set_multi_4);
	t->abs_sm_8 =		__C(CHIP,_io_set_multi_8);

	/* set region */
	t->abs_sr_1 =		__C(CHIP,_io_set_region_1);
	t->abs_sr_2 =		__C(CHIP,_io_set_region_2);
	t->abs_sr_4 =		__C(CHIP,_io_set_region_4);
	t->abs_sr_8 =		__C(CHIP,_io_set_region_8);

	/* copy */
	t->abs_c_1 =		__C(CHIP,_io_copy_1);
	t->abs_c_2 =		__C(CHIP,_io_copy_2);
	t->abs_c_4 =		__C(CHIP,_io_copy_4);
	t->abs_c_8 =		__C(CHIP,_io_copy_8);

	/* read multiple raw */
	t->abs_rrm_2 =		__C(CHIP,_io_read_raw_multi_2);
	t->abs_rrm_4 =		__C(CHIP,_io_read_raw_multi_4);
	t->abs_rrm_8 =		__C(CHIP,_io_read_raw_multi_8);

	/* write multiple raw*/
	t->abs_wrm_2 =		__C(CHIP,_io_write_raw_multi_2);
	t->abs_wrm_4 =		__C(CHIP,_io_write_raw_multi_4);
	t->abs_wrm_8 =		__C(CHIP,_io_write_raw_multi_8);

	ex = extent_create(CHIP_EXTENT_NAME(v), 0x0UL, 0xffffffffUL,
	    M_DEVBUF, (caddr_t)CHIP_EXTENT_STORAGE(v),
	    sizeof(CHIP_EXTENT_STORAGE(v)), EX_NOWAIT|EX_NOCOALESCE);

	CHIP_IO_EXTENT(v) = ex;
}

int
__C(CHIP,_io_map)(v, ioaddr, iosize, flags, iohp)
	void *v;
	bus_addr_t ioaddr;
	bus_size_t iosize;
	int flags;
	bus_space_handle_t *iohp;
{
	int error;

	/*
	 * Can't map i/o space linearly.
	 */
	if (flags & BUS_SPACE_MAP_LINEAR)
		return (EOPNOTSUPP);

#ifdef EXTENT_DEBUG
	printf("io: allocating 0x%lx to 0x%lx\n", ioaddr, ioaddr + iosize - 1);
#endif
        error = extent_alloc_region(CHIP_IO_EXTENT(v), ioaddr, iosize,
            EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0));
	if (error) {
#ifdef EXTENT_DEBUG
		printf("io: allocation failed (%d)\n", error);
		extent_print(CHIP_IO_EXTENT(v));
#endif
		return (error);
	}

	*iohp = ALPHA_PHYS_TO_K0SEG(CHIP_IO_SYS_START(v)) + ioaddr;

	return (0);
}

void
__C(CHIP,_io_unmap)(v, ioh, iosize)
	void *v;
	bus_space_handle_t ioh;
	bus_size_t iosize;
{
	bus_addr_t ioaddr;
	int error;

#ifdef EXTENT_DEBUG
	printf("io: freeing handle 0x%lx for 0x%lx\n", ioh, iosize);
#endif

	ioaddr = ioh - ALPHA_PHYS_TO_K0SEG(CHIP_IO_SYS_START(v));

#ifdef EXTENT_DEBUG
	printf("io: freeing 0x%lx to 0x%lx\n", ioaddr, ioaddr + iosize - 1);
#endif
        error = extent_free(CHIP_IO_EXTENT(v), ioaddr, iosize,
            EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0));
	if (error) {
		printf("%s: WARNING: could not unmap 0x%lx-0x%lx (error %d)\n",
		   __S(__C(CHIP,_io_unmap)), ioaddr, ioaddr + iosize - 1,
		   error);
#ifdef EXTENT_DEBUG
		extent_print(CHIP_IO_EXTENT(v));
#endif
	}
}

int
__C(CHIP,_io_subregion)(v, ioh, offset, size, nioh)
	void *v;
	bus_space_handle_t ioh, *nioh;
	bus_size_t offset, size;
{

	*nioh = ioh + offset;
	return (0);
}

int
__C(CHIP,_io_alloc)(v, rstart, rend, size, align, boundary, flags,
    addrp, bshp)
	void *v;
	bus_addr_t rstart, rend, *addrp;
	bus_size_t size, align, boundary;
	int flags;
	bus_space_handle_t *bshp;
{

	/* XXX XXX XXX XXX XXX XXX */
	panic("%s not implemented", __S(__C(CHIP,_io_alloc)));
}

void
__C(CHIP,_io_free)(v, bsh, size)
	void *v;
	bus_space_handle_t bsh;
	bus_size_t size;
{

	/* XXX XXX XXX XXX XXX XXX */
	panic("%s not implemented", __S(__C(CHIP,_io_free)));
}

void *
__C(CHIP,_io_vaddr)(v, bsh)
	void *v;
	bus_space_handle_t bsh;
{
	/*
	 * _io_map() catches BUS_SPACE_MAP_LINEAR,
	 * so we shouldn't get here
	 */
	panic("_io_vaddr");
}

inline void
__C(CHIP,_io_barrier)(v, h, o, l, f)
	void *v;
	bus_space_handle_t h;
	bus_size_t o, l;
	int f;
{

	if ((f & BUS_SPACE_BARRIER_READ) != 0)
		alpha_mb();
	else if ((f & BUS_SPACE_BARRIER_WRITE) != 0)
		alpha_wmb();
}

inline u_int8_t
__C(CHIP,_io_read_1)(v, ioh, off)
	void *v;
	bus_space_handle_t ioh;
	bus_size_t off;
{
	bus_addr_t addr;

	addr = ioh + off;
	alpha_mb();
	return (alpha_ldbu((u_int8_t *)addr));
}

inline u_int16_t
__C(CHIP,_io_read_2)(v, ioh, off)
	void *v;
	bus_space_handle_t ioh;
	bus_size_t off;
{
	bus_addr_t addr;

	addr = ioh + off;
#ifdef DIAGNOSTIC
	if (addr & 1)
		panic(__S(__C(CHIP,_io_read_2)) ": addr 0x%lx not aligned",
		    addr);
#endif
	alpha_mb();
	return (alpha_ldwu((u_int16_t *)addr));
}

inline u_int32_t
__C(CHIP,_io_read_4)(v, ioh, off)
	void *v;
	bus_space_handle_t ioh;
	bus_size_t off;
{
	bus_addr_t addr;

	addr = ioh + off;
#ifdef DIAGNOSTIC
	if (addr & 3)
		panic(__S(__C(CHIP,_io_read_4)) ": addr 0x%lx not aligned",
		    addr);
#endif
	alpha_mb();
	return (*(u_int32_t *)addr);
}

inline u_int64_t
__C(CHIP,_io_read_8)(v, ioh, off)
	void *v;
	bus_space_handle_t ioh;
	bus_size_t off;
{

	/* XXX XXX XXX */
	panic("%s not implemented", __S(__C(CHIP,_io_read_8)));
}

#define CHIP_io_read_multi_N(BYTES,TYPE)				\
void									\
__C(__C(CHIP,_io_read_multi_),BYTES)(v, h, o, a, c)			\
	void *v;							\
	bus_space_handle_t h;						\
	bus_size_t o, c;						\
	TYPE *a;							\
{									\
									\
	while (c-- > 0) {						\
		__C(CHIP,_io_barrier)(v, h, o, sizeof *a,		\
		    BUS_SPACE_BARRIER_READ);				\
		*a++ = __C(__C(CHIP,_io_read_),BYTES)(v, h, o);		\
	}								\
}
CHIP_io_read_multi_N(1,u_int8_t)
CHIP_io_read_multi_N(2,u_int16_t)
CHIP_io_read_multi_N(4,u_int32_t)
CHIP_io_read_multi_N(8,u_int64_t)

#define CHIP_io_read_region_N(BYTES,TYPE)				\
void									\
__C(__C(CHIP,_io_read_region_),BYTES)(v, h, o, a, c)			\
	void *v;							\
	bus_space_handle_t h;						\
	bus_size_t o, c;						\
	TYPE *a;							\
{									\
									\
	while (c-- > 0) {						\
		*a++ = __C(__C(CHIP,_io_read_),BYTES)(v, h, o);		\
		o += sizeof *a;						\
	}								\
}
CHIP_io_read_region_N(1,u_int8_t)
CHIP_io_read_region_N(2,u_int16_t)
CHIP_io_read_region_N(4,u_int32_t)
CHIP_io_read_region_N(8,u_int64_t)

inline void
__C(CHIP,_io_write_1)(v, ioh, off, val)
	void *v;
	bus_space_handle_t ioh;
	bus_size_t off;
	u_int8_t val;
{
	bus_addr_t addr;

	addr = ioh + off;
	alpha_stb((u_int8_t *)addr, val);
        alpha_mb();
}

inline void
__C(CHIP,_io_write_2)(v, ioh, off, val)
	void *v;
	bus_space_handle_t ioh;
	bus_size_t off;
	u_int16_t val;
{
	bus_addr_t addr;

	addr = ioh + off;
#ifdef DIAGNOSTIC
	if (addr & 1)
		panic(__S(__C(CHIP,_io_write_2)) ": addr 0x%lx not aligned",
		    addr);
#endif
	alpha_stw((u_int16_t *)addr, val);
	alpha_mb();
}

inline void
__C(CHIP,_io_write_4)(v, ioh, off, val)
	void *v;
	bus_space_handle_t ioh;
	bus_size_t off;
	u_int32_t val;
{
	bus_addr_t addr;

	addr = ioh + off;
#ifdef DIAGNOSTIC
	if (addr & 3)
		panic(__S(__C(CHIP,_io_write_4)) ": addr 0x%lx not aligned",
		    addr);
#endif
	*(u_int32_t *)addr = val;
	alpha_mb();
}

inline void
__C(CHIP,_io_write_8)(v, ioh, off, val)
	void *v;
	bus_space_handle_t ioh;
	bus_size_t off;
	u_int64_t val;
{

	/* XXX XXX XXX */
	panic("%s not implemented", __S(__C(CHIP,_io_write_8)));
	alpha_mb();
}

#define CHIP_io_write_multi_N(BYTES,TYPE)				\
void									\
__C(__C(CHIP,_io_write_multi_),BYTES)(v, h, o, a, c)			\
	void *v;							\
	bus_space_handle_t h;						\
	bus_size_t o, c;						\
	const TYPE *a;							\
{									\
									\
	while (c-- > 0) {						\
		__C(__C(CHIP,_io_write_),BYTES)(v, h, o, *a++);		\
		__C(CHIP,_io_barrier)(v, h, o, sizeof *a,		\
		    BUS_SPACE_BARRIER_WRITE);				\
	}								\
}
CHIP_io_write_multi_N(1,u_int8_t)
CHIP_io_write_multi_N(2,u_int16_t)
CHIP_io_write_multi_N(4,u_int32_t)
CHIP_io_write_multi_N(8,u_int64_t)

#define CHIP_io_write_region_N(BYTES,TYPE)				\
void									\
__C(__C(CHIP,_io_write_region_),BYTES)(v, h, o, a, c)			\
	void *v;							\
	bus_space_handle_t h;						\
	bus_size_t o, c;						\
	const TYPE *a;							\
{									\
									\
	while (c-- > 0) {						\
		__C(__C(CHIP,_io_write_),BYTES)(v, h, o, *a++);		\
		o += sizeof *a;						\
	}								\
}
CHIP_io_write_region_N(1,u_int8_t)
CHIP_io_write_region_N(2,u_int16_t)
CHIP_io_write_region_N(4,u_int32_t)
CHIP_io_write_region_N(8,u_int64_t)

#define CHIP_io_set_multi_N(BYTES,TYPE)					\
void									\
__C(__C(CHIP,_io_set_multi_),BYTES)(v, h, o, val, c)			\
	void *v;							\
	bus_space_handle_t h;						\
	bus_size_t o, c;						\
	TYPE val;							\
{									\
									\
	while (c-- > 0) {						\
		__C(__C(CHIP,_io_write_),BYTES)(v, h, o, val);		\
		__C(CHIP,_io_barrier)(v, h, o, sizeof val,		\
		    BUS_SPACE_BARRIER_WRITE);				\
	}								\
}
CHIP_io_set_multi_N(1,u_int8_t)
CHIP_io_set_multi_N(2,u_int16_t)
CHIP_io_set_multi_N(4,u_int32_t)
CHIP_io_set_multi_N(8,u_int64_t)

#define CHIP_io_set_region_N(BYTES,TYPE)				\
void									\
__C(__C(CHIP,_io_set_region_),BYTES)(v, h, o, val, c)			\
	void *v;							\
	bus_space_handle_t h;						\
	bus_size_t o, c;						\
	TYPE val;							\
{									\
									\
	while (c-- > 0) {						\
		__C(__C(CHIP,_io_write_),BYTES)(v, h, o, val);		\
		o += sizeof val;					\
	}								\
}
CHIP_io_set_region_N(1,u_int8_t)
CHIP_io_set_region_N(2,u_int16_t)
CHIP_io_set_region_N(4,u_int32_t)
CHIP_io_set_region_N(8,u_int64_t)

#define	CHIP_io_copy_N(BYTES)						\
void									\
__C(__C(CHIP,_io_copy_),BYTES)(v, h1, o1, h2, o2, c)			\
	void *v;							\
	bus_space_handle_t h1, h2;					\
	bus_size_t o1, o2, c;						\
{									\
	bus_size_t i, o;						\
									\
	for (i = 0, o = 0; i < c; i++, o += BYTES)			\
		__C(__C(CHIP,_io_write_),BYTES)(v, h2, o2 + o,		\
		    __C(__C(CHIP,_io_read_),BYTES)(v, h1, o1 + o));	\
}
CHIP_io_copy_N(1)
CHIP_io_copy_N(2)
CHIP_io_copy_N(4)
CHIP_io_copy_N(8)

#define CHIP_io_read_raw_multi_N(BYTES,TYPE)				\
void									\
__C(__C(CHIP,_io_read_raw_multi_),BYTES)(v, h, o, a, c)			\
	void *v;							\
	bus_space_handle_t h;						\
	bus_size_t o, c;						\
	u_int8_t *a;							\
{									\
	TYPE temp;							\
	int i;								\
									\
	while (c > 0) {							\
		__C(CHIP,_io_barrier)(v, h, o, BYTES,			\
		    BUS_SPACE_BARRIER_READ);				\
		temp = __C(__C(CHIP,_io_read_),BYTES)(v, h, o);		\
		i = MIN(c, BYTES);					\
		c -= i;							\
		while (i--) {						\
			*a++ = temp & 0xff;				\
			temp >>= 8;					\
		}							\
	}								\
}
CHIP_io_read_raw_multi_N(2,u_int16_t)
CHIP_io_read_raw_multi_N(4,u_int32_t)
CHIP_io_read_raw_multi_N(8,u_int64_t)

#define CHIP_io_write_raw_multi_N(BYTES,TYPE)				\
void									\
__C(__C(CHIP,_io_write_raw_multi_),BYTES)(v, h, o, a, c)		\
	void *v;							\
	bus_space_handle_t h;						\
	bus_size_t o, c;						\
	const u_int8_t *a;						\
{									\
	TYPE temp;							\
	int i;								\
									\
	while (c > 0) {							\
		temp = 0;						\
		for (i = BYTES - 1; i >= 0; i--) {			\
			temp <<= 8;					\
			if (i < c)					\
				temp |= *(a + i);			\
		}							\
		__C(__C(CHIP,_io_write_),BYTES)(v, h, o, temp);		\
		__C(CHIP,_io_barrier)(v, h, o, BYTES,			\
		    BUS_SPACE_BARRIER_WRITE);				\
		i = MIN(c, BYTES); 					\
		c -= i;							\
		a += i;							\
	}								\
}
CHIP_io_write_raw_multi_N(2,u_int16_t)
CHIP_io_write_raw_multi_N(4,u_int32_t)
CHIP_io_write_raw_multi_N(8,u_int64_t)


code:
/* $OpenBSD: pci_bwx_bus_mem_chipdep.c,v 1.10 2014/02/23 12:26:18 jsg Exp $ */
/* $NetBSD: pcs_bus_mem_common.c,v 1.15 1996/12/02 22:19:36 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.
 */

/*
 * Common PCI Chipset "bus I/O" functions, for chipsets which have to
 * deal with only a single PCI interface chip in a machine.
 *
 * uses:
 *	CHIP		name of the 'chip' it's being compiled for.
 *	CHIP_MEM_BASE   Mem space base to use.
 *	CHIP_MEM_EX_STORE
 *			If defined, device-provided static storage area
 *			for the memory space extent.  If this is
 *			defined, CHIP_MEM_EX_STORE_SIZE must also be
 *			defined.  If this is not defined, a static area
 *			will be declared.
 *	CHIP_MEM_EX_STORE_SIZE
 *			Size of the device-provided static storage area
 *			for the memory space extent.
 */

#include <sys/extent.h>
#include <machine/bwx.h>

#define	__C(A,B)	__CONCAT(A,B)
#define	__S(S)		__STRING(S)

#ifndef	CHIP_EXTENT_NAME
#define	CHIP_EXTENT_NAME(v)	__S(__C(CHIP,_bus_dmem))
#endif

#ifndef	CHIP_EXTENT_STORAGE
#define CHIP_EXTENT_STORAGE(v)	__C(CHIP,_mem_ex_storage)
static long
    __C(CHIP,_mem_ex_storage)[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];
#endif

/* mapping/unmapping */
int		__C(CHIP,_mem_map)(void *, bus_addr_t, bus_size_t, int,
		    bus_space_handle_t *);
void		__C(CHIP,_mem_unmap)(void *, bus_space_handle_t,
		    bus_size_t);
int		__C(CHIP,_mem_subregion)(void *, bus_space_handle_t,
		    bus_size_t, bus_size_t, bus_space_handle_t *);

/* allocation/deallocation */
int		__C(CHIP,_mem_alloc)(void *, bus_addr_t, bus_addr_t,
		    bus_size_t, bus_size_t, bus_addr_t, int, bus_addr_t *,
                    bus_space_handle_t *);
void		__C(CHIP,_mem_free)(void *, bus_space_handle_t,
		    bus_size_t);

/* get kernel virtual address */
void *		__C(CHIP,_mem_vaddr)(void *, bus_space_handle_t);

/* barrier */
inline void	__C(CHIP,_mem_barrier)(void *, bus_space_handle_t,
		    bus_size_t, bus_size_t, int);

/* read (single) */
inline u_int8_t	__C(CHIP,_mem_read_1)(void *, bus_space_handle_t,
		    bus_size_t);
inline u_int16_t __C(CHIP,_mem_read_2)(void *, bus_space_handle_t,
		    bus_size_t);
inline u_int32_t __C(CHIP,_mem_read_4)(void *, bus_space_handle_t,
		    bus_size_t);
inline u_int64_t __C(CHIP,_mem_read_8)(void *, bus_space_handle_t,
		    bus_size_t);

/* read multiple */
void		__C(CHIP,_mem_read_multi_1)(void *, bus_space_handle_t,
		    bus_size_t, u_int8_t *, bus_size_t);
void		__C(CHIP,_mem_read_multi_2)(void *, bus_space_handle_t,
		    bus_size_t, u_int16_t *, bus_size_t);
void		__C(CHIP,_mem_read_multi_4)(void *, bus_space_handle_t,
		    bus_size_t, u_int32_t *, bus_size_t);
void		__C(CHIP,_mem_read_multi_8)(void *, bus_space_handle_t,
		    bus_size_t, u_int64_t *, bus_size_t);

/* read region */
void		__C(CHIP,_mem_read_region_1)(void *, bus_space_handle_t,
		    bus_size_t, u_int8_t *, bus_size_t);
void		__C(CHIP,_mem_read_region_2)(void *, bus_space_handle_t,
		    bus_size_t, u_int16_t *, bus_size_t);
void		__C(CHIP,_mem_read_region_4)(void *, bus_space_handle_t,
		    bus_size_t, u_int32_t *, bus_size_t);
void		__C(CHIP,_mem_read_region_8)(void *, bus_space_handle_t,
		    bus_size_t, u_int64_t *, bus_size_t);

/* write (single) */
inline void	__C(CHIP,_mem_write_1)(void *, bus_space_handle_t,
		    bus_size_t, u_int8_t);
inline void	__C(CHIP,_mem_write_2)(void *, bus_space_handle_t,
		    bus_size_t, u_int16_t);
inline void	__C(CHIP,_mem_write_4)(void *, bus_space_handle_t,
		    bus_size_t, u_int32_t);
inline void	__C(CHIP,_mem_write_8)(void *, bus_space_handle_t,
		    bus_size_t, u_int64_t);

/* write multiple */
void		__C(CHIP,_mem_write_multi_1)(void *, bus_space_handle_t,
		    bus_size_t, const u_int8_t *, bus_size_t);
void		__C(CHIP,_mem_write_multi_2)(void *, bus_space_handle_t,
		    bus_size_t, const u_int16_t *, bus_size_t);
void		__C(CHIP,_mem_write_multi_4)(void *, bus_space_handle_t,
		    bus_size_t, const u_int32_t *, bus_size_t);
void		__C(CHIP,_mem_write_multi_8)(void *, bus_space_handle_t,
		    bus_size_t, const u_int64_t *, bus_size_t);

/* write region */
void		__C(CHIP,_mem_write_region_1)(void *, bus_space_handle_t,
		    bus_size_t, const u_int8_t *, bus_size_t);
void		__C(CHIP,_mem_write_region_2)(void *, bus_space_handle_t,
		    bus_size_t, const u_int16_t *, bus_size_t);
void		__C(CHIP,_mem_write_region_4)(void *, bus_space_handle_t,
		    bus_size_t, const u_int32_t *, bus_size_t);
void		__C(CHIP,_mem_write_region_8)(void *, bus_space_handle_t,
		    bus_size_t, const u_int64_t *, bus_size_t);

/* set multiple */
void		__C(CHIP,_mem_set_multi_1)(void *, bus_space_handle_t,
		    bus_size_t, u_int8_t, bus_size_t);
void		__C(CHIP,_mem_set_multi_2)(void *, bus_space_handle_t,
		    bus_size_t, u_int16_t, bus_size_t);
void		__C(CHIP,_mem_set_multi_4)(void *, bus_space_handle_t,
		    bus_size_t, u_int32_t, bus_size_t);
void		__C(CHIP,_mem_set_multi_8)(void *, bus_space_handle_t,
		    bus_size_t, u_int64_t, bus_size_t);

/* set region */
void		__C(CHIP,_mem_set_region_1)(void *, bus_space_handle_t,
		    bus_size_t, u_int8_t, bus_size_t);
void		__C(CHIP,_mem_set_region_2)(void *, bus_space_handle_t,
		    bus_size_t, u_int16_t, bus_size_t);
void		__C(CHIP,_mem_set_region_4)(void *, bus_space_handle_t,
		    bus_size_t, u_int32_t, bus_size_t);
void		__C(CHIP,_mem_set_region_8)(void *, bus_space_handle_t,
		    bus_size_t, u_int64_t, bus_size_t);

/* copy */
void		__C(CHIP,_mem_copy_1)(void *, bus_space_handle_t,
		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t);
void		__C(CHIP,_mem_copy_2)(void *, bus_space_handle_t,
		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t);
void		__C(CHIP,_mem_copy_4)(void *, bus_space_handle_t,
		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t);
void		__C(CHIP,_mem_copy_8)(void *, bus_space_handle_t,
		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t);

/* read multiple raw */
void		__C(CHIP,_mem_read_raw_multi_2)(void *,
		    bus_space_handle_t, bus_size_t, u_int8_t *, bus_size_t);
void		__C(CHIP,_mem_read_raw_multi_4)(void *,
		    bus_space_handle_t, bus_size_t, u_int8_t *, bus_size_t);
void		__C(CHIP,_mem_read_raw_multi_8)(void *,
		    bus_space_handle_t, bus_size_t, u_int8_t *, bus_size_t);

/* write multiple raw */
void		__C(CHIP,_mem_write_raw_multi_2)(void *,
		    bus_space_handle_t, bus_size_t, const u_int8_t *,
		    bus_size_t);
void		__C(CHIP,_mem_write_raw_multi_4)(void *,
		    bus_space_handle_t, bus_size_t, const u_int8_t *,
		    bus_size_t);
void		__C(CHIP,_mem_write_raw_multi_8)(void *,
		    bus_space_handle_t, bus_size_t, const u_int8_t *,
		    bus_size_t);

void
__C(CHIP,_bus_mem_init)(t, v)
	bus_space_tag_t t;
	void *v;
{
	struct extent *ex;

	/*
	 * Initialize the bus space tag.
	 */

	/* cookie */
	t->abs_cookie =		v;

	/* mapping/unmapping */
	t->abs_map =		__C(CHIP,_mem_map);
	t->abs_unmap =		__C(CHIP,_mem_unmap);
	t->abs_subregion =	__C(CHIP,_mem_subregion);

	/* allocation/deallocation */
	t->abs_alloc =		__C(CHIP,_mem_alloc);
	t->abs_free = 		__C(CHIP,_mem_free);

	/* get kernel virtual address */
	t->abs_vaddr =		__C(CHIP,_mem_vaddr);

	/* barrier */
	t->abs_barrier =	__C(CHIP,_mem_barrier);

	/* read (single) */
	t->abs_r_1 =		__C(CHIP,_mem_read_1);
	t->abs_r_2 =		__C(CHIP,_mem_read_2);
	t->abs_r_4 =		__C(CHIP,_mem_read_4);
	t->abs_r_8 =		__C(CHIP,_mem_read_8);

	/* read multiple */
	t->abs_rm_1 =		__C(CHIP,_mem_read_multi_1);
	t->abs_rm_2 =		__C(CHIP,_mem_read_multi_2);
	t->abs_rm_4 =		__C(CHIP,_mem_read_multi_4);
	t->abs_rm_8 =		__C(CHIP,_mem_read_multi_8);

	/* read region */
	t->abs_rr_1 =		__C(CHIP,_mem_read_region_1);
	t->abs_rr_2 =		__C(CHIP,_mem_read_region_2);
	t->abs_rr_4 =		__C(CHIP,_mem_read_region_4);
	t->abs_rr_8 =		__C(CHIP,_mem_read_region_8);

	/* write (single) */
	t->abs_w_1 =		__C(CHIP,_mem_write_1);
	t->abs_w_2 =		__C(CHIP,_mem_write_2);
	t->abs_w_4 =		__C(CHIP,_mem_write_4);
	t->abs_w_8 =		__C(CHIP,_mem_write_8);

	/* write multiple */
	t->abs_wm_1 =		__C(CHIP,_mem_write_multi_1);
	t->abs_wm_2 =		__C(CHIP,_mem_write_multi_2);
	t->abs_wm_4 =		__C(CHIP,_mem_write_multi_4);
	t->abs_wm_8 =		__C(CHIP,_mem_write_multi_8);

	/* write region */
	t->abs_wr_1 =		__C(CHIP,_mem_write_region_1);
	t->abs_wr_2 =		__C(CHIP,_mem_write_region_2);
	t->abs_wr_4 =		__C(CHIP,_mem_write_region_4);
	t->abs_wr_8 =		__C(CHIP,_mem_write_region_8);

	/* set multiple */
	t->abs_sm_1 =		__C(CHIP,_mem_set_multi_1);
	t->abs_sm_2 =		__C(CHIP,_mem_set_multi_2);
	t->abs_sm_4 =		__C(CHIP,_mem_set_multi_4);
	t->abs_sm_8 =		__C(CHIP,_mem_set_multi_8);

	/* set region */
	t->abs_sr_1 =		__C(CHIP,_mem_set_region_1);
	t->abs_sr_2 =		__C(CHIP,_mem_set_region_2);
	t->abs_sr_4 =		__C(CHIP,_mem_set_region_4);
	t->abs_sr_8 =		__C(CHIP,_mem_set_region_8);

	/* copy */
	t->abs_c_1 =		__C(CHIP,_mem_copy_1);
	t->abs_c_2 =		__C(CHIP,_mem_copy_2);
	t->abs_c_4 =		__C(CHIP,_mem_copy_4);
	t->abs_c_8 =		__C(CHIP,_mem_copy_8);

	/* read multiple raw */
	t->abs_rrm_2 =		__C(CHIP,_mem_read_raw_multi_2);
	t->abs_rrm_4 =		__C(CHIP,_mem_read_raw_multi_4);
	t->abs_rrm_8 =		__C(CHIP,_mem_read_raw_multi_8);

	/* write multiple raw*/
	t->abs_wrm_2 =		__C(CHIP,_mem_write_raw_multi_2);
	t->abs_wrm_4 =		__C(CHIP,_mem_write_raw_multi_4);
	t->abs_wrm_8 =		__C(CHIP,_mem_write_raw_multi_8);

	ex = extent_create(CHIP_EXTENT_NAME(v), 0x0UL,
	    0xffffffffffffffffUL, M_DEVBUF,
	    (caddr_t)CHIP_EXTENT_STORAGE(v),
	    sizeof(CHIP_EXTENT_STORAGE(v)), EX_NOWAIT|EX_NOCOALESCE);

        CHIP_MEM_EXTENT(v) = ex;
}

int
__C(CHIP,_mem_map)(v, memaddr, memsize, flags, memhp)
	void *v;
	bus_addr_t memaddr;
	bus_size_t memsize;
	int flags;
	bus_space_handle_t *memhp;
{
	int error;

#ifdef EXTENT_DEBUG
	printf("mem: allocating 0x%lx to 0x%lx\n", memaddr,
	    memaddr + memsize - 1);
#endif
	error = extent_alloc_region(CHIP_MEM_EXTENT(v), memaddr, memsize,
	    EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0));
	if (error) {
#ifdef EXTENT_DEBUG
		printf("mem: allocation failed (%d)\n", error);
		extent_print(CHIP_MEM_EXTENT(v));
#endif
		return (error);
	}

	*memhp = ALPHA_PHYS_TO_K0SEG(CHIP_MEM_SYS_START(v)) + memaddr;

	return (0);
}

void
__C(CHIP,_mem_unmap)(v, memh, memsize)
	void *v;
	bus_space_handle_t memh;
	bus_size_t memsize;
{
	bus_addr_t memaddr;
	int error;

#ifdef EXTENT_DEBUG
	printf("mem: freeing handle 0x%lx for 0x%lx\n", memh, memsize);
#endif
	memaddr = memh - ALPHA_PHYS_TO_K0SEG(CHIP_MEM_SYS_START(v));

#ifdef EXTENT_DEBUG
	printf("mem: freeing 0x%lx to 0x%lx\n", memaddr, memaddr + memsize - 1);
#endif
	error = extent_free(CHIP_MEM_EXTENT(v), memaddr, memsize,
	    EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0));
	if (error) {
		printf("%s: WARNING: could not unmap 0x%lx-0x%lx (error %d)\n",
		    __S(__C(CHIP,_mem_unmap)), memaddr, memaddr + memsize - 1,
		    error);
#ifdef EXTENT_DEBUG
	extent_print(CHIP_MEM_EXTENT(v));
#endif
	}
}

int
__C(CHIP,_mem_subregion)(v, memh, offset, size, nmemh)
	void *v;
	bus_space_handle_t memh, *nmemh;
	bus_size_t offset, size;
{

	*nmemh = memh + offset;
	return (0);
}

int
__C(CHIP,_mem_alloc)(v, rstart, rend, size, align, boundary, flags,
    addrp, bshp)
	void *v;
	bus_addr_t rstart, rend, *addrp;
	bus_size_t size, align, boundary;
	int flags;
	bus_space_handle_t *bshp;
{
	bus_addr_t memaddr;
	int error;

	/*
	 * Do the requested allocation.
	 */
#ifdef EXTENT_DEBUG
	printf("mem: allocating from 0x%lx to 0x%lx\n", rstart, rend);
#endif
	error = extent_alloc_subregion(CHIP_MEM_EXTENT(v), rstart, rend,
	    size, align, 0, boundary,
	    EX_FAST | EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0),
	    &memaddr);
	if (error) {
#ifdef EXTENT_DEBUG
		printf("mem: allocation failed (%d)\n", error);
		extent_print(CHIP_MEM_EXTENT(v));
#endif
	}

#ifdef EXTENT_DEBUG
	printf("mem: allocated 0x%lx to 0x%lx\n", memaddr, memaddr + size - 1);
#endif

	*addrp = memaddr;
	*bshp = ALPHA_PHYS_TO_K0SEG(CHIP_MEM_SYS_START(v)) + memaddr;

	return (0);
}

void
__C(CHIP,_mem_free)(v, bsh, size)
	void *v;
	bus_space_handle_t bsh;
	bus_size_t size;
{

	/* Unmap does all we need to do. */
	__C(CHIP,_mem_unmap)(v, bsh, size);
}

void *
__C(CHIP,_mem_vaddr)(v, bsh)
	void *v;
	bus_space_handle_t bsh;
{

	return ((void *)bsh);
}

inline void
__C(CHIP,_mem_barrier)(v, h, o, l, f)
	void *v;
	bus_space_handle_t h;
	bus_size_t o, l;
	int f;
{

	if ((f & BUS_SPACE_BARRIER_READ) != 0)
		alpha_mb();
	else if ((f & BUS_SPACE_BARRIER_WRITE) != 0)
		alpha_wmb();
}

inline u_int8_t
__C(CHIP,_mem_read_1)(v, memh, off)
	void *v;
	bus_space_handle_t memh;
	bus_size_t off;
{
	bus_addr_t addr;

	addr = memh + off;
	alpha_mb();
	return (alpha_ldbu((u_int8_t *)addr));
}

inline u_int16_t
__C(CHIP,_mem_read_2)(v, memh, off)
	void *v;
	bus_space_handle_t memh;
	bus_size_t off;
{
	bus_addr_t addr;

	addr = memh + off;
#ifdef DIAGNOSTIC
	if (addr & 1)
		panic(__S(__C(CHIP,_mem_read_2)) ": addr 0x%lx not aligned",
		    addr);
#endif
	alpha_mb();
	return (alpha_ldwu((u_int16_t *)addr));
}

inline u_int32_t
__C(CHIP,_mem_read_4)(v, memh, off)
	void *v;
	bus_space_handle_t memh;
	bus_size_t off;
{
	bus_addr_t addr;

	addr = memh + off;
#ifdef DIAGNOSTIC
	if (addr & 3)
		panic(__S(__C(CHIP,_mem_read_4)) ": addr 0x%lx not aligned",
		    addr);
#endif
	alpha_mb();
	return (*(u_int32_t *)addr);
}

inline u_int64_t
__C(CHIP,_mem_read_8)(v, memh, off)
	void *v;
	bus_space_handle_t memh;
	bus_size_t off;
{

	alpha_mb();

	/* XXX XXX XXX */
	panic("%s not implemented", __S(__C(CHIP,_mem_read_8)));
}

#define CHIP_mem_read_multi_N(BYTES,TYPE)				\
void									\
__C(__C(CHIP,_mem_read_multi_),BYTES)(v, h, o, a, c)			\
	void *v;							\
	bus_space_handle_t h;						\
	bus_size_t o, c;						\
	TYPE *a;							\
{									\
									\
	while (c-- > 0) {						\
		__C(CHIP,_mem_barrier)(v, h, o, sizeof *a,		\
		    BUS_SPACE_BARRIER_READ);				\
		*a++ = __C(__C(CHIP,_mem_read_),BYTES)(v, h, o);	\
	}								\
}
CHIP_mem_read_multi_N(1,u_int8_t)
CHIP_mem_read_multi_N(2,u_int16_t)
CHIP_mem_read_multi_N(4,u_int32_t)
CHIP_mem_read_multi_N(8,u_int64_t)

#define CHIP_mem_read_region_N(BYTES,TYPE)				\
void									\
__C(__C(CHIP,_mem_read_region_),BYTES)(v, h, o, a, c)			\
	void *v;							\
	bus_space_handle_t h;						\
	bus_size_t o, c;						\
	TYPE *a;							\
{									\
									\
	while (c-- > 0) {						\
		*a++ = __C(__C(CHIP,_mem_read_),BYTES)(v, h, o);	\
		o += sizeof *a;						\
	}								\
}
CHIP_mem_read_region_N(1,u_int8_t)
CHIP_mem_read_region_N(2,u_int16_t)
CHIP_mem_read_region_N(4,u_int32_t)
CHIP_mem_read_region_N(8,u_int64_t)

inline void
__C(CHIP,_mem_write_1)(v, memh, off, val)
	void *v;
	bus_space_handle_t memh;
	bus_size_t off;
	u_int8_t val;
{
	bus_addr_t addr;

	addr = memh + off;
	alpha_stb((u_int8_t *)addr, val);
	alpha_mb();
}

inline void
__C(CHIP,_mem_write_2)(v, memh, off, val)
	void *v;
	bus_space_handle_t memh;
	bus_size_t off;
	u_int16_t val;
{
	bus_addr_t addr;

	addr = memh + off;
#ifdef DIAGNOSTIC
	if (addr & 1)
		panic(__S(__C(CHIP,_mem_write_2)) ": addr 0x%lx not aligned",
		   addr);
#endif
	alpha_stw((u_int16_t *)addr, val);
	alpha_mb();
}

inline void
__C(CHIP,_mem_write_4)(v, memh, off, val)
	void *v;
	bus_space_handle_t memh;
	bus_size_t off;
	u_int32_t val;
{
	bus_addr_t addr;

	addr = memh + off;
#ifdef DIAGNOSTIC
	if (addr & 3)
		panic(__S(__C(CHIP,_mem_write_4)) ": addr 0x%lx not aligned",
		    addr);
#endif
	*(u_int32_t *)addr = val;
	alpha_mb();
}

inline void
__C(CHIP,_mem_write_8)(v, memh, off, val)
	void *v;
	bus_space_handle_t memh;
	bus_size_t off;
	u_int64_t val;
{

	/* XXX XXX XXX */
	panic("%s not implemented", __S(__C(CHIP,_mem_write_8)));
	alpha_mb();
}

#define CHIP_mem_write_multi_N(BYTES,TYPE)				\
void									\
__C(__C(CHIP,_mem_write_multi_),BYTES)(v, h, o, a, c)			\
	void *v;							\
	bus_space_handle_t h;						\
	bus_size_t o, c;						\
	const TYPE *a;							\
{									\
									\
	while (c-- > 0) {						\
		__C(__C(CHIP,_mem_write_),BYTES)(v, h, o, *a++);	\
		__C(CHIP,_mem_barrier)(v, h, o, sizeof *a,		\
		    BUS_SPACE_BARRIER_WRITE);				\
	}								\
}
CHIP_mem_write_multi_N(1,u_int8_t)
CHIP_mem_write_multi_N(2,u_int16_t)
CHIP_mem_write_multi_N(4,u_int32_t)
CHIP_mem_write_multi_N(8,u_int64_t)

#define CHIP_mem_write_region_N(BYTES,TYPE)				\
void									\
__C(__C(CHIP,_mem_write_region_),BYTES)(v, h, o, a, c)			\
	void *v;							\
	bus_space_handle_t h;						\
	bus_size_t o, c;						\
	const TYPE *a;							\
{									\
									\
	while (c-- > 0) {						\
		__C(__C(CHIP,_mem_write_),BYTES)(v, h, o, *a++);	\
		o += sizeof *a;						\
	}								\
}
CHIP_mem_write_region_N(1,u_int8_t)
CHIP_mem_write_region_N(2,u_int16_t)
CHIP_mem_write_region_N(4,u_int32_t)
CHIP_mem_write_region_N(8,u_int64_t)

#define CHIP_mem_set_multi_N(BYTES,TYPE)				\
void									\
__C(__C(CHIP,_mem_set_multi_),BYTES)(v, h, o, val, c)			\
	void *v;							\
	bus_space_handle_t h;						\
	bus_size_t o, c;						\
	TYPE val;							\
{									\
									\
	while (c-- > 0) {						\
		__C(__C(CHIP,_mem_write_),BYTES)(v, h, o, val);		\
		__C(CHIP,_mem_barrier)(v, h, o, sizeof val,		\
		    BUS_SPACE_BARRIER_WRITE);				\
	}								\
}
CHIP_mem_set_multi_N(1,u_int8_t)
CHIP_mem_set_multi_N(2,u_int16_t)
CHIP_mem_set_multi_N(4,u_int32_t)
CHIP_mem_set_multi_N(8,u_int64_t)

#define CHIP_mem_set_region_N(BYTES,TYPE)				\
void									\
__C(__C(CHIP,_mem_set_region_),BYTES)(v, h, o, val, c)			\
	void *v;							\
	bus_space_handle_t h;						\
	bus_size_t o, c;						\
	TYPE val;							\
{									\
									\
	while (c-- > 0) {						\
		__C(__C(CHIP,_mem_write_),BYTES)(v, h, o, val);		\
		o += sizeof val;					\
	}								\
}
CHIP_mem_set_region_N(1,u_int8_t)
CHIP_mem_set_region_N(2,u_int16_t)
CHIP_mem_set_region_N(4,u_int32_t)
CHIP_mem_set_region_N(8,u_int64_t)

#define	CHIP_mem_copy_N(BYTES)						\
void									\
__C(__C(CHIP,_mem_copy_),BYTES)(v, h1, o1, h2, o2, c)			\
	void *v;							\
	bus_space_handle_t h1, h2;					\
	bus_size_t o1, o2, c;						\
{									\
	bus_size_t i, o;						\
									\
	if ((h1 >> 63) != 0 && (h2 >> 63) != 0) {			\
		bcopy((void *)(h1 + o1), (void *)(h2 + o2), c * BYTES);	\
		return;							\
	}								\
									\
	/* Circumvent a common case of overlapping problems */		\
	if (h1 == h2 && o2 > o1)					\
		for (i = 0, o = (c - 1) * BYTES; i < c; i++, o -= BYTES)\
			__C(__C(CHIP,_mem_write_),BYTES)(v, h2, o2 + o,	\
			    __C(__C(CHIP,_mem_read_),BYTES)(v, h1, o1 + o));\
	else								\
		for (i = 0, o = 0; i < c; i++, o += BYTES)		\
			__C(__C(CHIP,_mem_write_),BYTES)(v, h2, o2 + o,	\
			    __C(__C(CHIP,_mem_read_),BYTES)(v, h1, o1 + o));\
}
CHIP_mem_copy_N(1)
CHIP_mem_copy_N(2)
CHIP_mem_copy_N(4)
CHIP_mem_copy_N(8)

#define CHIP_mem_read_raw_multi_N(BYTES,TYPE)				\
void									\
__C(__C(CHIP,_mem_read_raw_multi_),BYTES)(v, h, o, a, c)			\
	void *v;							\
	bus_space_handle_t h;						\
	bus_size_t o, c;						\
	u_int8_t *a;							\
{									\
	TYPE temp;							\
	int i;								\
									\
	while (c > 0) {							\
		__C(CHIP,_mem_barrier)(v, h, o, BYTES,			\
		    BUS_SPACE_BARRIER_READ);				\
		temp = __C(__C(CHIP,_mem_read_),BYTES)(v, h, o);	\
		i = MIN(c, BYTES);					\
		c -= i;							\
		while (i--) {						\
			*a++ = temp & 0xff;				\
			temp >>= 8;					\
		}							\
	}								\
}
CHIP_mem_read_raw_multi_N(2,u_int16_t)
CHIP_mem_read_raw_multi_N(4,u_int32_t)
CHIP_mem_read_raw_multi_N(8,u_int64_t)

#define CHIP_mem_write_raw_multi_N(BYTES,TYPE)				\
void									\
__C(__C(CHIP,_mem_write_raw_multi_),BYTES)(v, h, o, a, c)		\
	void *v;							\
	bus_space_handle_t h;						\
	bus_size_t o, c;						\
	const u_int8_t *a;						\
{									\
	TYPE temp;							\
	int i;								\
									\
	while (c > 0) {							\
		temp = 0;						\
		for (i = BYTES - 1; i >= 0; i--) {			\
			temp <<= 8;					\
			if (i < c)					\
				temp |= *(a + i);			\
		}							\
		__C(__C(CHIP,_mem_write_),BYTES)(v, h, o, temp);	\
		__C(CHIP,_mem_barrier)(v, h, o, BYTES,			\
		    BUS_SPACE_BARRIER_WRITE);				\
		i = MIN(c, BYTES);					\
		c -= i;							\
		a += i;							\
	}								\
}
CHIP_mem_write_raw_multi_N(2,u_int16_t)
CHIP_mem_write_raw_multi_N(4,u_int32_t)
CHIP_mem_write_raw_multi_N(8,u_int64_t)

license: unknown


code:
/* $OpenBSD: pci_eb164.c,v 1.27 2015/07/26 05:09:44 miod Exp $ */
/* $NetBSD: pci_eb164.c,v 1.27 2000/06/06 00:50:15 thorpej 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.
 *
 * 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 <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_eb164.h>

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

int	dec_eb164_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
const char *dec_eb164_intr_string(void *, pci_intr_handle_t);
int	dec_eb164_intr_line(void *, pci_intr_handle_t);
void	*dec_eb164_intr_establish(void *, pci_intr_handle_t,
	    int, int (*func)(void *), void *, const char *);
void	dec_eb164_intr_disestablish(void *, void *);

void	*dec_eb164_pciide_compat_intr_establish(void *, struct device *,
	    struct pci_attach_args *, int, int (*)(void *), void *);
void    dec_eb164_pciide_compat_intr_disestablish(void *, void *);

#define	EB164_SIO_IRQ	4
#define	EB164_MAX_IRQ	24
#define	PCI_STRAY_MAX	5

struct alpha_shared_intr *eb164_pci_intr;

bus_space_tag_t eb164_intrgate_iot;
bus_space_handle_t eb164_intrgate_ioh;

void	eb164_iointr(void *arg, unsigned long vec);
extern void	eb164_intr_enable(int irq);	/* pci_eb164_intr.S */
extern void	eb164_intr_disable(int irq);	/* pci_eb164_intr.S */

void
pci_eb164_pickintr(ccp)
	struct cia_config *ccp;
{
	bus_space_tag_t iot = &ccp->cc_iot;
	pci_chipset_tag_t pc = &ccp->cc_pc;
	int i;

        pc->pc_intr_v = ccp;
        pc->pc_intr_map = dec_eb164_intr_map;
        pc->pc_intr_string = dec_eb164_intr_string;
        pc->pc_intr_line = dec_eb164_intr_line;
        pc->pc_intr_establish = dec_eb164_intr_establish;
        pc->pc_intr_disestablish = dec_eb164_intr_disestablish;

	pc->pc_pciide_compat_intr_establish =
	    dec_eb164_pciide_compat_intr_establish;
	pc->pc_pciide_compat_intr_disestablish =
	    dec_eb164_pciide_compat_intr_disestablish;

	eb164_intrgate_iot = iot;
	if (bus_space_map(eb164_intrgate_iot, 0x804, 3, 0,
	    &eb164_intrgate_ioh) != 0)
		panic("pci_eb164_pickintr: couldn't map interrupt PLD");
	for (i = 0; i < EB164_MAX_IRQ; i++)
		eb164_intr_disable(i);

	eb164_pci_intr = alpha_shared_intr_alloc(EB164_MAX_IRQ);
	for (i = 0; i < EB164_MAX_IRQ; i++) {
		/*
		 * Systems with a Pyxis seem to have problems with
		 * stray interrupts, so just ignore them.  Sigh,
		 * I hate buggy hardware.
		 */
		alpha_shared_intr_set_maxstrays(eb164_pci_intr, i,
			(ccp->cc_flags & CCF_ISPYXIS) ? 0 : PCI_STRAY_MAX);
	}

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

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

	/*
	 *
	 * The AlphaPC 164 and AlphaPC 164LX have a CMD PCI IDE controller
	 * at bus 0 device 11.  These are wired to compatibility mode,
	 * so do not map their interrupts.
	 *
	 * The AlphaPC 164SX has PCI IDE on functions 1 and 2 of the
	 * Cypress PCI-ISA bridge at bus 0 device 8.  These, too, are
	 * wired to compatibility mode.
	 *
	 * Real EB164s have ISA IDE on the Super I/O chip.
	 */
	variation = hwrpb->rpb_variation & SV_ST_MASK;
	if (pa->pa_bus == 0) {
		if (variation >= SV_ST_ALPHAPC164_366 &&
		    variation <= SV_ST_ALPHAPC164LX_600) {
			if (pa->pa_device == 8)
				panic("dec_eb164_intr_map: SIO device");
			if (pa->pa_device == 11)
				return (1);
		} else if (variation >= SV_ST_ALPHAPC164SX_400 &&
			   variation <= SV_ST_ALPHAPC164SX_600) {
			if (pa->pa_device == 8) {
				if (pa->pa_function == 0)
					panic("dec_eb164_intr_map: SIO device");
				return (1);
			}
		} else {
			if (pa->pa_device == 8)
				panic("dec_eb164_intr_map: SIO device");
		}
	}

	/*
	 * The console places the interrupt mapping in the "line" value.
	 * We trust it whenever possible.
	 */
	if (line >= 0 && line < EB164_MAX_IRQ) {
		*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) {
			*ihp = pa->pa_bridgeih[buspin - 1];
			return 0;
		}
	}

	return 1;
}

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

        if (ih >= EB164_MAX_IRQ)
                panic("dec_eb164_intr_string: bogus eb164 IRQ 0x%lx", ih);
        snprintf(irqstr, sizeof irqstr, "eb164 irq %ld", ih);
        return (irqstr);
}

int
dec_eb164_intr_line(ccv, ih)
	void *ccv;
	pci_intr_handle_t ih;
{
	return (ih);
}

void *
dec_eb164_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 (ih >= EB164_MAX_IRQ)
		panic("dec_eb164_intr_establish: bogus eb164 IRQ 0x%lx", ih);

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

	if (cookie != NULL &&
	    alpha_shared_intr_firstactive(eb164_pci_intr, ih)) {
		scb_set(0x900 + SCB_IDXTOVEC(ih), eb164_iointr, NULL);
		eb164_intr_enable(ih);
	}
	return (cookie);
}

void
dec_eb164_intr_disestablish(ccv, cookie)
        void *ccv, *cookie;
{
#if 0
	struct cia_config *ccp = ccv;
#endif
	struct alpha_shared_intrhand *ih = cookie;
	unsigned int irq = ih->ih_num;
	int s;

	s = splhigh();

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

	splx(s);
}

void *
dec_eb164_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);
	if (cookie == NULL)
		return (NULL);
#endif
	return (cookie);
}

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

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

	irq = SCB_VECTOIDX(vec - 0x900);

	if (!alpha_shared_intr_dispatch(eb164_pci_intr, irq)) {
		alpha_shared_intr_stray(eb164_pci_intr, irq,
		    "eb164 irq");
		if (ALPHA_SHARED_INTR_DISABLE(eb164_pci_intr, irq))
			eb164_intr_disable(irq);
	} else
		alpha_shared_intr_reset_strays(eb164_pci_intr, irq);
}

#if 0		/* THIS DOES NOT WORK!  see pci_eb164_intr.S. */
u_int8_t eb164_intr_mask[3] = { 0xff, 0xff, 0xff };

void
eb164_intr_enable(irq)
	int irq;
{
	int byte = (irq / 8), bit = (irq % 8);

#if 1
	printf("eb164_intr_enable: enabling %d (%d:%d)\n", irq, byte, bit);
#endif
	eb164_intr_mask[byte] &= ~(1 << bit);

	bus_space_write_1(eb164_intrgate_iot, eb164_intrgate_ioh, byte,
	    eb164_intr_mask[byte]);
}

void
eb164_intr_disable(irq)
	int irq;
{
	int byte = (irq / 8), bit = (irq % 8);

#if 1
	printf("eb164_intr_disable: disabling %d (%d:%d)\n", irq, byte, bit);
#endif
	eb164_intr_mask[byte] |= (1 << bit);

	bus_space_write_1(eb164_intrgate_iot, eb164_intrgate_ioh, byte,
	    eb164_intr_mask[byte]);
}
#endif


code:
/*	$OpenBSD: pci_eb164.h,v 1.4 2004/06/28 02:28:43 aaron Exp $	*/
/*	$NetBSD: pci_eb164.h,v 1.1 1996/11/11 21:08:13 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_eb164_pickintr(struct cia_config *);


code:
/*	$OpenBSD: pci_eb164_intr.s,v 1.3 2002/08/15 17:01:38 deraadt Exp $	*/
/*	$NetBSD: pci_eb164_intr.s,v 1.1 1996/11/25 03:47:07 cgd Exp $	*/

/*
 * Copyright (c) 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.
 */

/*
 * The description of how to enable and disable interrupts in the
 * AlphaPC 164 motherboard technical reference manual is incorrect,
 * at least for the OSF/1 PALcode.
 *
 * These functions were written by disassembling a Digital UNIX kernel's
 * eb164_intrdsabl and eb164_intrenabl functions (because they had
 * interesting names), and then playing with them to see how to call
 * them correctly.
 *
 * It looks like the right thing to do is to call them with the interrupt
 * request that you want to enable or disable (presumably in the range
 * 0 -> 23, since there are 3 8-bit interrupt-enable bits in the
 * interrupt mask PLD).
 */

#include <machine/asm.h>

	.text
LEAF(eb164_intr_enable,1)
	mov	a0, a1
	ldiq	a0, 0x34
	call_pal PAL_cserve
	RET
	END(eb164_intr_enable)

	.text
LEAF(eb164_intr_disable,1)
	mov	a0, a1
	ldiq	a0, 0x35
	call_pal PAL_cserve
	RET
	END(eb164_intr_disable)


code:
/* $OpenBSD: pci_eb64plus.c,v 1.15 2015/07/26 05:09:44 miod Exp $ */
/* $NetBSD: pci_eb64plus.c,v 1.10 2001/07/27 00:25:20 thorpej 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.
 *
 * 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 <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/ppbreg.h>

#include <alpha/pci/apecsreg.h>
#include <alpha/pci/apecsvar.h>

#include <alpha/pci/pci_eb64plus.h>

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

int	dec_eb64plus_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
const char *dec_eb64plus_intr_string(void *, pci_intr_handle_t);
void	*dec_eb64plus_intr_establish(void *, pci_intr_handle_t,
	    int, int (*func)(void *), void *, const char *);
void	dec_eb64plus_intr_disestablish(void *, void *);

#define	EB64PLUS_MAX_IRQ	32
#define	PCI_STRAY_MAX		5

struct alpha_shared_intr *eb64plus_pci_intr;

bus_space_tag_t eb64plus_intrgate_iot;
bus_space_handle_t eb64plus_intrgate_ioh;

void	eb64plus_iointr(void *arg, unsigned long vec);
extern void	eb64plus_intr_enable(int irq);  /* pci_eb64plus_intr.S */
extern void	eb64plus_intr_disable(int irq); /* pci_eb64plus_intr.S */

void
pci_eb64plus_pickintr(acp)
	struct apecs_config *acp;
{
	bus_space_tag_t iot = &acp->ac_iot;
	pci_chipset_tag_t pc = &acp->ac_pc;
	int i;

        pc->pc_intr_v = acp;
        pc->pc_intr_map = dec_eb64plus_intr_map;
        pc->pc_intr_string = dec_eb64plus_intr_string;
        pc->pc_intr_establish = dec_eb64plus_intr_establish;
        pc->pc_intr_disestablish = dec_eb64plus_intr_disestablish;

	/* Not supported on the EB64+. */
	pc->pc_pciide_compat_intr_establish = NULL;

	eb64plus_intrgate_iot = iot;
	if (bus_space_map(eb64plus_intrgate_iot, 0x804, 3, 0,
	    &eb64plus_intrgate_ioh) != 0)
		panic("pci_eb64plus_pickintr: couldn't map interrupt PLD");
	for (i = 0; i < EB64PLUS_MAX_IRQ; i++)
		eb64plus_intr_disable(i);

	eb64plus_pci_intr = alpha_shared_intr_alloc(EB64PLUS_MAX_IRQ);
	for (i = 0; i < EB64PLUS_MAX_IRQ; i++) {
		alpha_shared_intr_set_maxstrays(eb64plus_pci_intr, i,
			PCI_STRAY_MAX);
	}

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

int
dec_eb64plus_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 < EB64PLUS_MAX_IRQ) {
		*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) {
			*ihp = pa->pa_bridgeih[buspin - 1];
			return 0;
		}
	}

	return 1;
}

const char *
dec_eb64plus_intr_string(acv, ih)
	void *acv;
	pci_intr_handle_t ih;
{
        static char irqstr[15];          /* 11 + 2 + NULL + sanity */

        if (ih >= EB64PLUS_MAX_IRQ)
                panic("dec_eb64plus_intr_string: bogus eb64+ IRQ 0x%lx", ih);
        snprintf(irqstr, sizeof irqstr, "eb64+ irq %ld", ih);
        return (irqstr);
}

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

	if (ih >= EB64PLUS_MAX_IRQ)
		panic("dec_eb64plus_intr_establish: bogus eb64+ IRQ 0x%lx",
		    ih);

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

	if (cookie != NULL &&
	    alpha_shared_intr_firstactive(eb64plus_pci_intr, ih)) {
		scb_set(0x900 + SCB_IDXTOVEC(ih), eb64plus_iointr, NULL);
		eb64plus_intr_enable(ih);
	}
	return (cookie);
}

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

	s = splhigh();

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

	splx(s);
}

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

	irq = SCB_VECTOIDX(vec - 0x900);

	if (!alpha_shared_intr_dispatch(eb64plus_pci_intr, irq)) {
		alpha_shared_intr_stray(eb64plus_pci_intr, irq,
		    "eb64+ irq");
		if (ALPHA_SHARED_INTR_DISABLE(eb64plus_pci_intr, irq))
			eb64plus_intr_disable(irq);
	} else
		alpha_shared_intr_reset_strays(eb64plus_pci_intr, irq);
}

#if 0		/* THIS DOES NOT WORK!  see pci_eb64plus_intr.S. */
u_int8_t eb64plus_intr_mask[3] = { 0xff, 0xff, 0xff };

void
eb64plus_intr_enable(irq)
	int irq;
{
	int byte = (irq / 8), bit = (irq % 8);

#if 1
	printf("eb64plus_intr_enable: enabling %d (%d:%d)\n", irq, byte, bit);
#endif
	eb64plus_intr_mask[byte] &= ~(1 << bit);

	bus_space_write_1(eb64plus_intrgate_iot, eb64plus_intrgate_ioh, byte,
	    eb64plus_intr_mask[byte]);
}

void
eb64plus_intr_disable(irq)
	int irq;
{
	int byte = (irq / 8), bit = (irq % 8);

#if 1
	printf("eb64plus_intr_disable: disabling %d (%d:%d)\n", irq, byte, bit);
#endif
	eb64plus_intr_mask[byte] |= (1 << bit);

	bus_space_write_1(eb64plus_intrgate_iot, eb64plus_intrgate_ioh, byte,
	    eb64plus_intr_mask[byte]);
}
#endif


code:
/* $OpenBSD: pci_eb64plus.h,v 1.3 2009/06/21 00:38:22 martynas Exp $ */
/* $NetBSD: pci_eb64plus.h,v 1.2 2000/06/05 21:47:26 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_eb64plus_pickintr(struct apecs_config *);


code:
/* $OpenBSD: pci_eb64plus_intr.s,v 1.2 2003/01/08 17:26:21 miod Exp $ */
/* $NetBSD: pci_eb64plus_intr.s,v 1.2 1997/09/02 13:19:43 thorpej Exp $ */

/*
 * Copyright (c) 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.
 */

/*
 * This file hacked from pci_eb164_intr.s
 *
 * These functions were written by disassembling a Digital UNIX kernel's
 * eb64p_intrdsabl and eb64p_intrenabl functions (because they had
 * interesting names, and looked like the eb164 versions which were
 * known to already work), and then playing with them to see how to call
 * them correctly.
 *
 * It looks like the right thing to do is to call them with the interrupt
 * request that you want to enable or disable (presumably in the range
 * 0 -> 23, since there are 3 8-bit interrupt-enable bits in the
 * interrupt mask PLD).
 */

#include <machine/asm.h>

	.text
LEAF(eb64plus_intr_enable,1)
	mov	a0, a1
	ldiq	a0, 0x34
	call_pal PAL_cserve
	RET
	END(eb64plus_intr_enable)

	.text
LEAF(eb64plus_intr_disable,1)
	mov	a0, a1
	ldiq	a0, 0x35
	call_pal PAL_cserve
	RET
	END(eb64plus_intr_disable)


code:
/*	$OpenBSD: pci_kn20aa.c,v 1.28 2015/07/26 05:09:44 miod Exp $	*/
/*	$NetBSD: pci_kn20aa.c,v 1.21 1996/11/17 02:05:27 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/malloc.h>
#include <sys/device.h>
#include <sys/syslog.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/ciareg.h>
#include <alpha/pci/ciavar.h>

#include <alpha/pci/pci_kn20aa.h>

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

int	dec_kn20aa_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
const char *dec_kn20aa_intr_string(void *, pci_intr_handle_t);
int	dec_kn20aa_intr_line(void *, pci_intr_handle_t);
void	*dec_kn20aa_intr_establish(void *, pci_intr_handle_t,
	    int, int (*func)(void *), void *, const char *);
void	dec_kn20aa_intr_disestablish(void *, void *);

#define	KN20AA_PCEB_IRQ	31
#define	KN20AA_MAX_IRQ	32
#define	PCI_STRAY_MAX	5

struct alpha_shared_intr *kn20aa_pci_intr;
struct evcount kn20aa_intr_count;

void	kn20aa_iointr(void *arg, unsigned long vec);
void	kn20aa_enable_intr(int irq);
void	kn20aa_disable_intr(int irq);

void
pci_kn20aa_pickintr(ccp)
	struct cia_config *ccp;
{
	int i;
	bus_space_tag_t iot = &ccp->cc_iot;
	pci_chipset_tag_t pc = &ccp->cc_pc;

        pc->pc_intr_v = ccp;
        pc->pc_intr_map = dec_kn20aa_intr_map;
        pc->pc_intr_string = dec_kn20aa_intr_string;
        pc->pc_intr_line = dec_kn20aa_intr_line;
        pc->pc_intr_establish = dec_kn20aa_intr_establish;
        pc->pc_intr_disestablish = dec_kn20aa_intr_disestablish;

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

	kn20aa_pci_intr = alpha_shared_intr_alloc(KN20AA_MAX_IRQ);
	for (i = 0; i < KN20AA_MAX_IRQ; i++)
		alpha_shared_intr_set_maxstrays(kn20aa_pci_intr, i,
		    PCI_STRAY_MAX);

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

int
dec_kn20aa_intr_map(pa, ihp)
	struct pci_attach_args *pa;
        pci_intr_handle_t *ihp;
{
	pcitag_t bustag = pa->pa_intrtag;
	int buspin = pa->pa_intrpin;
	pci_chipset_tag_t pc = pa->pa_pc;
	int device;
	int kn20aa_irq;

	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;
	}

	/*
	 * Slot->interrupt translation.  Appears to work, though it
	 * may not hold up forever.
	 *
	 * The DEC engineers who did this hardware obviously engaged
	 * in random drug testing.
	 */
	pci_decompose_tag(pc, bustag, NULL, &device, NULL);
	switch (device) {
	case 11:
	case 12:
		kn20aa_irq = ((device - 11) + 0) * 4;
		break;

	case 7:
		kn20aa_irq = 8;
		break;

	case 9:
		kn20aa_irq = 12;
		break;

	case 6:					/* 21040 on AlphaStation 500 */
		kn20aa_irq = 13;
		break;

	case 8:
		kn20aa_irq = 16;
		break;

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

	if (kn20aa_irq != 13)
		kn20aa_irq += buspin - 1;

	if (kn20aa_irq >= KN20AA_MAX_IRQ) {
		printf("dec_kn20aa_intr_map: kn20aa_irq %d too large for %d/%d/%d\n",
		    kn20aa_irq, pa->pa_bus, pa->pa_device, pa->pa_function);
		return 1;
	}

	*ihp = kn20aa_irq;
	return 0;
}

const char *
dec_kn20aa_intr_string(ccv, ih)
	void *ccv;
	pci_intr_handle_t ih;
{
        static char irqstr[15];          /* 11 + 2 + NULL + sanity */

        if (ih > KN20AA_MAX_IRQ)
		panic("dec_kn20aa_intr_string: bogus kn20aa IRQ 0x%lx", ih);

        snprintf(irqstr, sizeof irqstr, "kn20aa irq %ld", ih);
        return (irqstr);
}

int
dec_kn20aa_intr_line(ccv, ih)
	void *ccv;
	pci_intr_handle_t ih;
{
	return (ih);
}

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

        if (ih > KN20AA_MAX_IRQ)
                panic("dec_kn20aa_intr_establish: bogus kn20aa IRQ 0x%lx",
		    ih);

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

	if (cookie != NULL &&
	    alpha_shared_intr_firstactive(kn20aa_pci_intr, ih)) {
		scb_set(0x900 + SCB_IDXTOVEC(ih), kn20aa_iointr, NULL);
		kn20aa_enable_intr(ih);
	}
	return (cookie);
}

void
dec_kn20aa_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(kn20aa_pci_intr, cookie);
	if (alpha_shared_intr_isactive(kn20aa_pci_intr, irq) == 0) {
		kn20aa_disable_intr(irq);
		alpha_shared_intr_set_dfltsharetype(kn20aa_pci_intr, irq,
		    IST_NONE);
		scb_free(0x900 + SCB_IDXTOVEC(irq));
	}
	splx(s);
}

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

	irq = SCB_VECTOIDX(vec - 0x900);

	if (!alpha_shared_intr_dispatch(kn20aa_pci_intr, irq)) {
		alpha_shared_intr_stray(kn20aa_pci_intr, irq,
		    "kn20aa irq");
		if (ALPHA_SHARED_INTR_DISABLE(kn20aa_pci_intr, irq))
			kn20aa_disable_intr(irq);
	} else
		alpha_shared_intr_reset_strays(kn20aa_pci_intr, irq);
}

void
kn20aa_enable_intr(irq)
	int irq;
{

	/*
	 * From disassembling small bits of the OSF/1 kernel:
	 * the following appears to enable a given interrupt request.
	 * "blech."  I'd give valuable body parts for better docs or
	 * for a good decompiler.
	 */
	alpha_mb();
	REGVAL(0x8780000000L + 0x40L) |= (1 << irq);	/* XXX */
	alpha_mb();
}

void
kn20aa_disable_intr(irq)
	int irq;
{

	alpha_mb();
	REGVAL(0x8780000000L + 0x40L) &= ~(1 << irq);	/* XXX */
	alpha_mb();
}


code:
/*	$OpenBSD: pci_kn20aa.h,v 1.6 2004/06/28 02:28:43 aaron Exp $	*/
/*	$NetBSD: pci_kn20aa.h,v 1.2 1996/04/13 00:24:35 cgd Exp $	*/

/*
 * Copyright (c) 1995 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_kn20aa_pickintr(struct cia_config *);


code:
/* $OpenBSD: pci_kn300.c,v 1.7 2015/07/26 05:09:44 miod Exp $ */
/* $NetBSD: pci_kn300.c,v 1.28 2005/12/11 12:16:17 christos 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 <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 <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/ppbreg.h>

#include <alpha/mcbus/mcbusvar.h>
#include <alpha/mcbus/mcbusreg.h>
#include <alpha/pci/mcpciareg.h>
#include <alpha/pci/mcpciavar.h>
#include <alpha/pci/pci_kn300.h>

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

int	dec_kn300_intr_map(struct pci_attach_args *, pci_intr_handle_t *);

const char *dec_kn300_intr_string(void *, pci_intr_handle_t);
void	*dec_kn300_intr_establish(void *, pci_intr_handle_t,
	    int, int (*func)(void *), void *, const char *);
void	dec_kn300_intr_disestablish(void *, void *);

#define	KN300_PCEB_IRQ	16
#define	NPIN		4

#define	NIRQ	(MAX_MC_BUS * MCPCIA_PER_MCBUS * MCPCIA_MAXSLOT * NPIN)
static int savirqs[NIRQ];

static struct alpha_shared_intr *kn300_pci_intr;

static struct mcpcia_config *mcpcia_eisaccp = NULL;

void	kn300_iointr (void *, unsigned long);
void	kn300_enable_intr (struct mcpcia_config *, int);
void	kn300_disable_intr (struct mcpcia_config *, int);

void
pci_kn300_pickintr(ccp, first)
	struct mcpcia_config *ccp;
	int first;
{
	pci_chipset_tag_t pc = &ccp->cc_pc;

	if (first) {
		int g;

		kn300_pci_intr = alpha_shared_intr_alloc(NIRQ);
		for (g = 0; g < NIRQ; g++) {
			alpha_shared_intr_set_maxstrays(kn300_pci_intr, g, 25);
			savirqs[g] = (char) -1;
		}
	}

	pc->pc_intr_v = ccp;
	pc->pc_intr_map = dec_kn300_intr_map;
	pc->pc_intr_string = dec_kn300_intr_string;
	pc->pc_intr_establish = dec_kn300_intr_establish;
	pc->pc_intr_disestablish = dec_kn300_intr_disestablish;

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

	if (EISA_PRESENT(REGVAL(MCPCIA_PCI_REV(ccp)))) {
		mcpcia_eisaccp = ccp;
#if NSIO > 0 || NPCEB > 0
		sio_intr_setup(pc, &ccp->cc_iot);
		kn300_enable_intr(ccp, KN300_PCEB_IRQ);
#endif
	}
}

int
dec_kn300_intr_map(pa, ihp)
	struct pci_attach_args *pa;
	pci_intr_handle_t *ihp;
{
	pcitag_t bustag = pa->pa_intrtag;
	int buspin = pa->pa_intrpin;
	pci_chipset_tag_t pc = pa->pa_pc;
	struct mcpcia_config *ccp = (struct mcpcia_config *)pc->pc_intr_v;
	int device;
	int mcpcia_irq;

	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;
	}

	pci_decompose_tag(pc, bustag, NULL, &device, NULL);

	/*
	 * On MID 5 device 1 is the internal NCR 53c810.
	 */
	if (ccp->cc_mid == 5 && device == 1) {
		mcpcia_irq = 16;
	} else if (device >= 2 && device <= 5) {
		mcpcia_irq = (device - 2) * 4 + buspin - 1;
	} else {
		printf("dec_kn300_intr_map: don't know how to setup %d/%d/%d\n",
		    pa->pa_bus, pa->pa_device, pa->pa_function);
		return 1;
	}

	/*
	 * handle layout:
	 *
	 *	Determine kn300 IRQ (encoded in SCB vector):
	 *	bits 0..1	buspin-1
	 *	bits 2..4	PCI Slot (0..7- yes, some don't exist)
	 *	bits 5..7	MID-4
	 *	bits 8..10	7-GID
	 *
	 *	Software only:
	 *	bits 11-15	MCPCIA IRQ
	 */
	*ihp = (pci_intr_handle_t)
		(buspin - 1			    )	|
		((device & 0x7)			<< 2)	|
		((ccp->cc_mid - 4)		<< 5)	|
		((7 - ccp->cc_gid)		<< 8)	|
		(mcpcia_irq			<< 11);

	return (0);
}

const char *
dec_kn300_intr_string(ccv, ih)
	void *ccv;
	pci_intr_handle_t ih;
{
	static char irqstr[64];
	int irq;

	irq = ih & 0x3ff;
	if (irq >= NIRQ)
		panic("dec_kn300_intr_string: bogus kn300 IRQ 0x%x", irq);

	snprintf(irqstr, sizeof irqstr, "kn300 irq %d", irq);

	return (irqstr);
}

void *
dec_kn300_intr_establish(ccv, ih, level, func, arg, name)
        void *ccv, *arg;
        pci_intr_handle_t ih;
        int level;
        int (*func) (void *);
	const char *name;
{
	struct mcpcia_config *ccp = ccv;
	void *cookie;
	int irq;

	irq = ih & 0x3ff;
	if (irq >= NIRQ)
		panic("dec_kn300_intr_establish: bogus kn300 IRQ 0x%x", irq);

	cookie = alpha_shared_intr_establish(kn300_pci_intr, irq, IST_LEVEL,
	    level, func, arg, "kn300 irq");

	if (cookie != NULL &&
	    alpha_shared_intr_firstactive(kn300_pci_intr, irq)) {
		scb_set(MCPCIA_VEC_PCI + SCB_IDXTOVEC(irq),
		    kn300_iointr, NULL);
		alpha_shared_intr_set_private(kn300_pci_intr, irq, ccp);
		savirqs[irq] = (ih >> 11) & 0x1f;
		kn300_enable_intr(ccp, savirqs[irq]);
		alpha_mb();
	}
	return (cookie);
}

void
dec_kn300_intr_disestablish(ccv, cookie)
	void *ccv, *cookie;
{
	panic("dec_kn300_intr_disestablish not implemented");
}

void
kn300_iointr(arg, vec)
	void *arg;
	unsigned long vec;
{
	struct mcpcia_softc *mcp;
	u_long irq;

	irq = SCB_VECTOIDX(vec - MCPCIA_VEC_PCI);

	if (alpha_shared_intr_dispatch(kn300_pci_intr, irq)) {
		/*
		 * Any claim of an interrupt at this level is a hint to
		 * reset the stray interrupt count- elsewise a slow leak
		 * over time will cause this level to be shutdown.
		 */
		alpha_shared_intr_reset_strays(kn300_pci_intr, irq);
		return;
	}

	/*
	 * If we haven't finished configuring yet, or there is no mcp
	 * registered for this level yet, just return.
	 */
	mcp = alpha_shared_intr_get_private(kn300_pci_intr, irq);
	if (mcp == NULL || mcp->mcpcia_cc == NULL)
		return;

	/*
	 * We're getting an interrupt for a device we haven't enabled.
	 * We had better not try and use -1 to find the right bit to disable.
	 */
	if (savirqs[irq] == -1) {
		printf("kn300_iointr: stray interrupt vector 0x%lx\n", vec);
		return;
	}

	/*
	 * Stray interrupt; disable the IRQ on the appropriate MCPCIA
	 * if we've reached the limit.
	 */
	alpha_shared_intr_stray(kn300_pci_intr, irq, "kn300 irq");
	if (ALPHA_SHARED_INTR_DISABLE(kn300_pci_intr, irq) == 0)
		return;
	kn300_disable_intr(mcp->mcpcia_cc, savirqs[irq]);
}

void
kn300_enable_intr(ccp, irq)
	struct mcpcia_config *ccp;
	int irq;
{
	alpha_mb();
	REGVAL(MCPCIA_INT_MASK0(ccp)) |= (1 << irq);
	alpha_mb();
}

void
kn300_disable_intr(ccp, irq)
	struct mcpcia_config *ccp;
	int irq;
{
	alpha_mb();
	REGVAL(MCPCIA_INT_MASK0(ccp)) &= ~(1 << irq);
	alpha_mb();
}


code:
/* $OpenBSD: pci_kn300.h,v 1.1 2007/03/16 21:22:27 robert Exp $ */

/*
 * Copyright (c) 2007 Robert Nagy <robert@openbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

void	pci_kn300_pickintr(struct mcpcia_config *, int);


code:
/*	$OpenBSD: pci_machdep.c,v 1.20 2015/07/26 05:09:44 miod Exp $	*/
/*	$NetBSD: pci_machdep.c,v 1.7 1996/11/19 04:57:32 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.
 */

/*
 * Machine-specific functions for PCI autoconfiguration.
 */

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

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

#include "vga.h"
#if NVGA_PCI
#include <dev/pci/vga_pcivar.h>
#endif

#include "tga.h"
#if NTGA
#include <dev/pci/tgavar.h>
#endif

struct alpha_pci_chipset *alpha_pci_chipset;

void
pci_display_console(iot, memt, pc, bus, device, function)
	bus_space_tag_t iot, memt;
	pci_chipset_tag_t pc;
	int bus, device, function;
{
	pcitag_t tag;
	pcireg_t id, class;
	int match;
#if NVGA_PCI || NTGA
	int nmatch;
#endif
	int (*fn)(bus_space_tag_t, bus_space_tag_t, pci_chipset_tag_t,
	    int, int, int);

	tag = pci_make_tag(pc, bus, device, function);
	id = pci_conf_read(pc, tag, PCI_ID_REG);
	if (id == 0 || id == 0xffffffff)
		panic("pci_display_console: no device at %d/%d/%d",
		    bus, device, function);
	class = pci_conf_read(pc, tag, PCI_CLASS_REG);

	match = 0;
	fn = NULL;

#if NVGA_PCI
	nmatch = DEVICE_IS_VGA_PCI(class);
	if (nmatch > match) {
		match = nmatch;
		fn = vga_pci_cnattach;
	}
#endif
#if NTGA
	nmatch = DEVICE_IS_TGA(class, id);
	if (nmatch > match) {
		match = nmatch;
		fn = tga_cnattach;
	}
#endif

	if (fn != NULL)
		(*fn)(iot, memt, pc, bus, device, function);
	else
		panic("pci_display_console: unconfigured device at %d/%d/%d",
		    bus, device, function);
}

int
alpha_sysctl_chipset(int *name, u_int namelen, char *where, size_t *sizep)
{
	if (namelen != 1)
		return (ENOTDIR);

	if (alpha_pci_chipset == NULL)
		return (EOPNOTSUPP);

	switch (name[0]) {
	case CPU_CHIPSET_TYPE:
		return (sysctl_rdstring(where, sizep, NULL,
		    alpha_pci_chipset->pc_name));
	case CPU_CHIPSET_BWX:
		return (sysctl_rdint(where, sizep, NULL,
		    alpha_pci_chipset->pc_bwx));
	case CPU_CHIPSET_MEM:
		return (sysctl_rdquad(where, sizep, NULL,
		    alpha_pci_chipset->pc_mem));
	case CPU_CHIPSET_DENSE:
		return (sysctl_rdquad(where, sizep, NULL,
		    alpha_pci_chipset->pc_dense));
	case CPU_CHIPSET_PORTS:
		return (sysctl_rdquad(where, sizep, NULL,
		    alpha_pci_chipset->pc_ports));
	case CPU_CHIPSET_HAE_MASK:
		return (sysctl_rdquad(where, sizep, NULL,
		    alpha_pci_chipset->pc_hae_mask));
	default:
		return (EOPNOTSUPP);
	}
	/* NOTREACHED */
}

int
pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
{
	if (pa->pa_intrpin == 0)	/* No IRQ used. */
		return 1;

	if (!(1 <= pa->pa_intrpin && pa->pa_intrpin <= 4))
		return 1;

	return (*(pa->pa_pc)->pc_intr_map)(pa, ihp);
}


code:
/*	$OpenBSD: pci_machdep.h,v 1.29 2015/07/26 05:09:44 miod Exp $	*/
/*	$NetBSD: pci_machdep.h,v 1.6 1996/11/19 04:49:21 cgd Exp $	*/

/*
 * Copyright (c) 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.
 */

/*
 * Machine-specific definitions for PCI autoconfiguration.
 */

/*
 * Types provided to machine-independent PCI code
 */
typedef struct alpha_pci_chipset *pci_chipset_tag_t;
typedef u_long pcitag_t;
typedef u_long pci_intr_handle_t;

/*
 * Forward declarations.
 */
struct pci_attach_args;

/*
 * alpha-specific PCI structure and type definitions.
 * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE.
 */
struct alpha_pci_chipset {
	void		*pc_conf_v;
	void		(*pc_attach_hook)(struct device *,
			    struct device *, struct pcibus_attach_args *);
	int		(*pc_bus_maxdevs)(void *, int);
	pcitag_t	(*pc_make_tag)(void *, int, int, int);
	void		(*pc_decompose_tag)(void *, pcitag_t, int *,
			    int *, int *);
	int		(*pc_conf_size)(void *, pcitag_t);
	pcireg_t	(*pc_conf_read)(void *, pcitag_t, int);
	void		(*pc_conf_write)(void *, pcitag_t, int, pcireg_t);

	void		*pc_intr_v;
	int		(*pc_intr_map)(struct pci_attach_args *,
			    pci_intr_handle_t *);
	const char	*(*pc_intr_string)(void *, pci_intr_handle_t);
	int		(*pc_intr_line)(void *, pci_intr_handle_t);
	void		*(*pc_intr_establish)(void *, pci_intr_handle_t,
			    int, int (*)(void *), void *, const char *);
	void		(*pc_intr_disestablish)(void *, void *);

        /* alpha-specific */
        void            *(*pc_pciide_compat_intr_establish)(void *,
                            struct device *, struct pci_attach_args *, int,
                            int (*)(void *), void *);
	void            (*pc_pciide_compat_intr_disestablish)(void *,
			    void *);
	char 		*pc_name;	/* PCI chipset name */
	vaddr_t		pc_mem;		/* PCI memory address */
	vaddr_t		pc_dense;	/* PCI dense memory address */
	vaddr_t		pc_ports;	/* PCI port address */
	long		pc_hae_mask;	/* PCI chipset mask for HAE register */
	int		pc_bwx;		/* chipset supports BWX */
};

extern struct alpha_pci_chipset *alpha_pci_chipset;
int alpha_sysctl_chipset(int *, u_int, char *, size_t *);

/*
 * Functions provided to machine-independent PCI code.
 */
#define	pci_attach_hook(p, s, pba)					\
    (*(pba)->pba_pc->pc_attach_hook)((p), (s), (pba))
#define	pci_bus_maxdevs(c, b)						\
    (*(c)->pc_bus_maxdevs)((c)->pc_conf_v, (b))
#define	pci_make_tag(c, b, d, f)					\
    (*(c)->pc_make_tag)((c)->pc_conf_v, (b), (d), (f))
#define	pci_decompose_tag(c, t, bp, dp, fp)				\
    (*(c)->pc_decompose_tag)((c)->pc_conf_v, (t), (bp), (dp), (fp))
#define	pci_conf_size(c, t)						\
    (*(c)->pc_conf_size)((c)->pc_conf_v, (t))
#define	pci_conf_read(c, t, r)						\
    (*(c)->pc_conf_read)((c)->pc_conf_v, (t), (r))
#define	pci_conf_write(c, t, r, v)					\
    (*(c)->pc_conf_write)((c)->pc_conf_v, (t), (r), (v))
#define	pci_intr_map_msi(pa, ihp)	(-1)
#define	pci_intr_string(c, ih)						\
    (*(c)->pc_intr_string)((c)->pc_intr_v, (ih))
#define	pci_intr_line(c, ih)						\
    (*(c)->pc_intr_line)((c)->pc_intr_v, (ih))
#define	pci_intr_establish(c, ih, l, h, a, nm)				\
    (*(c)->pc_intr_establish)((c)->pc_intr_v, (ih), (l), (h), (a), (nm))
#define	pci_intr_disestablish(c, iv)					\
    (*(c)->pc_intr_disestablish)((c)->pc_intr_v, (iv))
#define	pci_probe_device_hook(c, a)	(0)

#define	pci_min_powerstate(c, t)	(PCI_PMCSR_STATE_D3)
#define	pci_set_powerstate_md(c, t, s, p)

/*
 * alpha-specific PCI functions.
 * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE.
 */
void	pci_display_console(bus_space_tag_t, bus_space_tag_t,
	    pci_chipset_tag_t, int, int, int);
#define alpha_pciide_compat_intr_establish(c, d, p, ch, f, a)		\
    ((c)->pc_pciide_compat_intr_establish == NULL ? NULL :		\
     (*(c)->pc_pciide_compat_intr_establish)((c)->pc_conf_v, (d), (p),	\
        (ch), (f), (a)))

#define alpha_pciide_compat_intr_disestablish(c, cookie)		\
    do { if ((c)->pc_pciide_compat_intr_disestablish != NULL)		\
	    ((c)->pc_pciide_compat_intr_disestablish)((c)->pc_conf_v,	\
            (cookie)); } while (0)

#define	pci_dev_postattach(a, b)

#ifdef _KERNEL
void	pci_display_console(bus_space_tag_t, bus_space_tag_t, pci_chipset_tag_t,
	    int, int, int);
int	pci_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
#endif /* _KERNEL */


code:
/* $OpenBSD: pci_sgmap_pte64.c,v 1.6 2008/06/26 05:42:09 ray Exp $ */
/* $NetBSD: pci_sgmap_pte64.c,v 1.4 2000/06/29 08:58:49 mrg Exp $ */

/*-
 * Copyright (c) 1997 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.
 */

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

#include <uvm/uvm_extern.h>

#include <machine/bus.h>

#include <alpha/pci/pci_sgmap_pte64.h>

#include <alpha/dev/sgmap_typedep.c>


code:
/* $OpenBSD: pci_sgmap_pte64.h,v 1.4 2008/06/26 05:42:09 ray Exp $ */
/* $NetBSD: pci_sgmap_pte64.h,v 1.2 1997/06/06 23:59:29 thorpej Exp $ */

/*-
 * Copyright (c) 1997 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.
 */

#define	SGMAP_TYPE		pci_sgmap_pte64
#define	SGMAP_PTE_TYPE		u_int64_t
#define	SGMAP_PTE_SPACING	1

/*
 * A 64-bit PCI SGMAP page table entry looks like this:
 *
 * 63                           n+1 n             1   0
 * |                               | Page address | V |
 *
 * The page address is bits <n:13> of the physical address of the
 * page.  The V bit is set if the PTE holds a valid mapping.
 */
#define SGPTE_PGADDR_SHIFT      12
#define SGPTE_VALID             0x0000000000000001UL

#include <alpha/dev/sgmapvar.h>
#include <alpha/dev/sgmap_typedep.h>