code:
/*	$OpenBSD: apecs.c,v 1.22 2009/03/30 21:43:13 kettenis Exp $	*/
/*	$NetBSD: apecs.c,v 1.16 1996/12/05 01:39:34 cgd Exp $	*/

/*-
 * Copyright (c) 2000 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Jason R. Thorpe.
 *
 * 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/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/device.h>
#include <uvm/uvm_extern.h>

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

#include <dev/isa/isareg.h>
#include <dev/isa/isavar.h>

#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <alpha/pci/apecsreg.h>
#include <alpha/pci/apecsvar.h>
#ifdef DEC_2100_A50
#include <alpha/pci/pci_2100_a50.h>
#endif
#ifdef DEC_EB64PLUS
#include <alpha/pci/pci_eb64plus.h>
#endif
#ifdef DEC_1000A
#include <alpha/pci/pci_1000a.h>
#endif
#ifdef DEC_1000
#include <alpha/pci/pci_1000.h>
#endif

int	apecsmatch(struct device *, void *, void *);
void	apecsattach(struct device *, struct device *, void *);

struct cfattach apecs_ca = {
	sizeof(struct device), apecsmatch, apecsattach,
};

struct cfdriver apecs_cd = {
	NULL, "apecs", DV_DULL,
};

int	apecsprint(void *, const char *pnp);

/* There can be only one. */
int apecsfound;
struct apecs_config apecs_configuration;

int
apecsmatch(parent, match, aux)
	struct device *parent;
	void *match;
	void *aux;
{
	struct mainbus_attach_args *ma = aux;

	/* Make sure that we're looking for an APECS. */
	if (strcmp(ma->ma_name, apecs_cd.cd_name) != 0)
		return (0);

	if (apecsfound)
		return (0);

	return (1);
}

/*
 * Set up the chipset's function pointers.
 */
void
apecs_init(acp, mallocsafe)
	struct apecs_config *acp;
	int mallocsafe;
{
	acp->ac_comanche_pass2 =
	    (REGVAL(COMANCHE_ED) & COMANCHE_ED_PASS2) != 0;
	acp->ac_memwidth =
	    (REGVAL(COMANCHE_GCR) & COMANCHE_GCR_WIDEMEM) != 0 ? 128 : 64;
	acp->ac_epic_pass2 =
	    (REGVAL(EPIC_DCSR) & EPIC_DCSR_PASS2) != 0;

	acp->ac_haxr1 = REGVAL(EPIC_HAXR1);
	acp->ac_haxr2 = REGVAL(EPIC_HAXR2);

	if (!acp->ac_initted) {
		/* don't do these twice since they set up extents */
		apecs_bus_io_init(&acp->ac_iot, acp);
		apecs_bus_mem_init(&acp->ac_memt, acp);

#if 0
		/*
		 * We have two I/O windows and 3 MEM windows.
		 */
		alpha_bus_window_count[ALPHA_BUS_TYPE_PCI_IO] = 2;
		alpha_bus_window_count[ALPHA_BUS_TYPE_PCI_MEM] = 3;
		alpha_bus_get_window = apecs_bus_get_window;
#endif
	}
	acp->ac_mallocsafe = mallocsafe;

	apecs_pci_init(&acp->ac_pc, acp);
	alpha_pci_chipset = &acp->ac_pc;
	alpha_pci_chipset->pc_name = "apecs";
	alpha_pci_chipset->pc_mem = APECS_PCI_SPARSE;
	alpha_pci_chipset->pc_dense = APECS_PCI_DENSE;
	alpha_pci_chipset->pc_ports = APECS_PCI_SIO;
	alpha_pci_chipset->pc_bwx = 0;
	alpha_pci_chipset->pc_hae_mask = EPIC_HAXR1_EADDR;

	acp->ac_initted = 1;
}

void
apecsattach(parent, self, aux)
	struct device *parent, *self;
	void *aux;
{
	struct apecs_config *acp;
	struct pcibus_attach_args pba;

	/* note that we've attached the chipset; can't have 2 APECSes. */
	apecsfound = 1;

	/*
	 * set up the chipset's info; done once at console init time
	 * (maybe), but doesn't hurt to do twice.
	 */
	acp = &apecs_configuration;
	apecs_init(acp, 1);

	apecs_dma_init(acp);

	printf(": DECchip %s Core Logic chipset\n",
	    acp->ac_memwidth == 128 ? "21072" : "21071");
	printf("%s: DC21071-CA pass %d, %d-bit memory bus\n",
	    self->dv_xname, acp->ac_comanche_pass2 ? 2 : 1, acp->ac_memwidth);
	printf("%s: DC21071-DA pass %d\n", self->dv_xname,
	    acp->ac_epic_pass2 ? 2 : 1);
	/* XXX print bcache size */

	if (!acp->ac_epic_pass2)
		printf("WARNING: 21071-DA NOT PASS2... NO BETS...\n");

	switch (cputype) {
#ifdef DEC_2100_A50
	case ST_DEC_2100_A50:
		pci_2100_a50_pickintr(acp);
		break;
#endif

#ifdef DEC_EB64PLUS
	case ST_EB64P:
		pci_eb64plus_pickintr(acp);
		break;
#endif

#ifdef DEC_1000A
	case ST_DEC_1000A:
		pci_1000a_pickintr(acp, &acp->ac_iot, &acp->ac_memt,
			&acp->ac_pc);
		break;
#endif

#ifdef DEC_1000
	case ST_DEC_1000:
		pci_1000_pickintr(acp, &acp->ac_iot, &acp->ac_memt,
			&acp->ac_pc);
		break;
#endif

	default:
		panic("apecsattach: shouldn't be here, really...");
	}

	bzero(&pba, sizeof(pba));
	pba.pba_busname = "pci";
	pba.pba_iot = &acp->ac_iot;
	pba.pba_memt = &acp->ac_memt;
	pba.pba_dmat =
	    alphabus_dma_get_tag(&acp->ac_dmat_direct, ALPHA_BUS_PCI);
	pba.pba_pc = &acp->ac_pc;
	pba.pba_domain = pci_ndomains++;
	pba.pba_bus = 0;
#ifdef notyet
	pba.pba_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED |
	    PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | PCI_FLAGS_MWI_OKAY;
#endif
	config_found(self, &pba, apecsprint);
}

int
apecsprint(aux, pnp)
	void *aux;
	const char *pnp;
{
	register struct pcibus_attach_args *pba = aux;

	/* only PCIs can attach to APECSes; easy. */
	if (pnp)
		printf("%s at %s", pba->pba_busname, pnp);
	printf(" bus %d", pba->pba_bus);
	return (UNCONF);
}

#if 0
int
apecs_bus_get_window(type, window, abst)
	int type, window;
	struct alpha_bus_space_translation *abst;
{
	struct apecs_config *acp = &apecs_configuration;
	bus_space_tag_t st;

	switch (type) {
	case ALPHA_BUS_TYPE_PCI_IO:
		st = &acp->ac_iot;
		break;

	case ALPHA_BUS_TYPE_PCI_MEM:
		st = &acp->ac_memt;
		break;

	default:
		panic("apecs_bus_get_window");
	}

	return (alpha_bus_space_get_window(st, window, abst));
}
#endif


code:
/*	$OpenBSD: apecs_bus_io.c,v 1.6 2001/11/06 19:53:13 miod Exp $	*/
/* $NetBSD: apecs_bus_io.c,v 1.8 1997/09/02 13:19:10 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.
 */

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

#include <uvm/uvm_extern.h>

#include <machine/bus.h>

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

#define	CHIP		apecs

#define	CHIP_EX_MALLOC_SAFE(v)	(((struct apecs_config *)(v))->ac_mallocsafe)
#define	CHIP_IO_EXTENT(v)	(((struct apecs_config *)(v))->ac_io_ex)

/* IO region 1 */
#define	CHIP_IO_W1_BUS_START(v)	0x00000000UL
#define	CHIP_IO_W1_BUS_END(v)	0x0003ffffUL
#define	CHIP_IO_W1_SYS_START(v)	APECS_PCI_SIO
#define	CHIP_IO_W1_SYS_END(v)	(APECS_PCI_SIO + (0x00040000UL << 5) - 1)

/* IO region 2 */
#define	CHIP_IO_W2_BUS_START(v)						\
    ((((struct apecs_config *)(v))->ac_haxr2 & EPIC_HAXR2_EADDR) +	\
      0x00040000UL)
#define	CHIP_IO_W2_BUS_END(v)						\
    ((((struct apecs_config *)(v))->ac_haxr2 & EPIC_HAXR2_EADDR) +	\
      0x00ffffffUL)
#define	CHIP_IO_W2_SYS_START(v)	(APECS_PCI_SIO + (0x00040000UL << 5))
#define	CHIP_IO_W2_SYS_END(v)	(APECS_PCI_SIO + (0x01000000UL << 5) - 1)

#include <alpha/pci/pci_swiz_bus_io_chipdep.c>

license: unknown


code:
/*	$OpenBSD: apecs_bus_mem.c,v 1.6 2001/11/06 19:53:13 miod Exp $	*/
/* $NetBSD: apecs_bus_mem.c,v 1.8 1997/09/02 13:19:12 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.
 */

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

#include <uvm/uvm_extern.h>

#include <machine/bus.h>

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

#define	CHIP	apecs

#define	CHIP_EX_MALLOC_SAFE(v)	(((struct apecs_config *)(v))->ac_mallocsafe)
#define	CHIP_D_MEM_EXTENT(v)	(((struct apecs_config *)(v))->ac_d_mem_ex)
#define	CHIP_S_MEM_EXTENT(v)	(((struct apecs_config *)(v))->ac_s_mem_ex)

/* Dense region 1 */
#define	CHIP_D_MEM_W1_BUS_START(v)	0x00000000UL
#define	CHIP_D_MEM_W1_BUS_END(v)	0xffffffffUL
#define	CHIP_D_MEM_W1_SYS_START(v)	APECS_PCI_DENSE
#define	CHIP_D_MEM_W1_SYS_END(v)	(APECS_PCI_DENSE + 0xffffffffUL)

/* Sparse region 1 */
#define	CHIP_S_MEM_W1_BUS_START(v)	0x00000000UL
#define	CHIP_S_MEM_W1_BUS_END(v)	0x00ffffffUL
#define	CHIP_S_MEM_W1_SYS_START(v)	APECS_PCI_SPARSE
#define	CHIP_S_MEM_W1_SYS_END(v)					\
    (APECS_PCI_SPARSE + (0x01000000UL << 5) - 1)

/* Sparse region 2 */
#define	CHIP_S_MEM_W2_BUS_START(v)					\
    ((((struct apecs_config *)(v))->ac_haxr1 & EPIC_HAXR1_EADDR) +	\
      0x01000000UL)
#define	CHIP_S_MEM_W2_BUS_END(v)					\
    ((((struct apecs_config *)(v))->ac_haxr1 & EPIC_HAXR1_EADDR) +	\
      0x07ffffffUL)
#define	CHIP_S_MEM_W2_SYS_START(v)					\
    (APECS_PCI_SPARSE + (0x01000000UL << 5))
#define	CHIP_S_MEM_W2_SYS_END(v)					\
    (APECS_PCI_SPARSE + (0x08000000UL << 5) - 1)

#include <alpha/pci/pci_swiz_bus_mem_chipdep.c>


code:
/* $OpenBSD: apecs_dma.c,v 1.7 2009/02/01 14:34:00 miod Exp $ */
/* $NetBSD: apecs_dma.c,v 1.13 2000/06/29 08:58:45 mrg Exp $ */

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

/*
 * XXX - We should define this before including bus.h, but since other stuff
 *       pulls in bus.h we must do this here.
 */
#define _ALPHA_BUS_DMA_PRIVATE

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

#include <uvm/uvm_extern.h>

#include <machine/bus.h>

#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <alpha/pci/apecsreg.h>
#include <alpha/pci/apecsvar.h>

bus_dma_tag_t apecs_dma_get_tag(bus_dma_tag_t, alpha_bus_t);

int	apecs_bus_dmamap_load_sgmap(bus_dma_tag_t, bus_dmamap_t, void *,
	    bus_size_t, struct proc *, int);

int	apecs_bus_dmamap_load_mbuf_sgmap(bus_dma_tag_t, bus_dmamap_t,
	    struct mbuf *, int);

int	apecs_bus_dmamap_load_uio_sgmap(bus_dma_tag_t, bus_dmamap_t,
	    struct uio *, int);

int	apecs_bus_dmamap_load_raw_sgmap(bus_dma_tag_t, bus_dmamap_t,
	    bus_dma_segment_t *, int, bus_size_t, int);

void	apecs_bus_dmamap_unload_sgmap(bus_dma_tag_t, bus_dmamap_t);

/*
 * Direct-mapped window: 1G at 1G
 */
#define	APECS_DIRECT_MAPPED_BASE (1*1024*1024*1024)
#define	APECS_DIRECT_MAPPED_SIZE (1*1024*1024*1024)

/*
 * SGMAP window: 8M at 8M
 */
#define	APECS_SGMAP_MAPPED_BASE	(8*1024*1024)
#define	APECS_SGMAP_MAPPED_SIZE	(8*1024*1024)

/*
 * Macro to flush APECS scatter/gather TLB.
 */
#define	APECS_TLB_INVALIDATE() \
do { \
	alpha_mb(); \
	REGVAL(EPIC_TBIA) = 0; \
	alpha_mb(); \
} while (0)

void
apecs_dma_init(acp)
	struct apecs_config *acp;
{
	bus_addr_t tbase;
	bus_dma_tag_t t;

	/*
	 * Initialize the DMA tag used for direct-mapped DMA.
	 */
	t = &acp->ac_dmat_direct;
	t->_cookie = acp;
	t->_wbase = APECS_DIRECT_MAPPED_BASE;
	t->_wsize = APECS_DIRECT_MAPPED_SIZE;
	t->_next_window = NULL;
	t->_boundary = 0;
	t->_sgmap = NULL;
	t->_get_tag = apecs_dma_get_tag;
	t->_dmamap_create = _bus_dmamap_create;
	t->_dmamap_destroy = _bus_dmamap_destroy;
	t->_dmamap_load = _bus_dmamap_load_direct;
	t->_dmamap_load_mbuf = _bus_dmamap_load_mbuf_direct;
	t->_dmamap_load_uio = _bus_dmamap_load_uio_direct;
	t->_dmamap_load_raw = _bus_dmamap_load_raw_direct;
	t->_dmamap_unload = _bus_dmamap_unload;
	t->_dmamap_sync = _bus_dmamap_sync;

	t->_dmamem_alloc = _bus_dmamem_alloc;
	t->_dmamem_free = _bus_dmamem_free;
	t->_dmamem_map = _bus_dmamem_map;
	t->_dmamem_unmap = _bus_dmamem_unmap;
	t->_dmamem_mmap = _bus_dmamem_mmap;

	/*
	 * Initialize the DMA tag used for sgmap-mapped DMA.
	 */
	t = &acp->ac_dmat_sgmap;
	t->_cookie = acp;
	t->_wbase = APECS_SGMAP_MAPPED_BASE;
	t->_wsize = APECS_SGMAP_MAPPED_SIZE;
	t->_next_window = NULL;
	t->_boundary = 0;
	t->_sgmap = &acp->ac_sgmap;
	t->_get_tag = apecs_dma_get_tag;
	t->_dmamap_create = alpha_sgmap_dmamap_create;
	t->_dmamap_destroy = alpha_sgmap_dmamap_destroy;
	t->_dmamap_load = apecs_bus_dmamap_load_sgmap;
	t->_dmamap_load_mbuf = apecs_bus_dmamap_load_mbuf_sgmap;
	t->_dmamap_load_uio = apecs_bus_dmamap_load_uio_sgmap;
	t->_dmamap_load_raw = apecs_bus_dmamap_load_raw_sgmap;
	t->_dmamap_unload = apecs_bus_dmamap_unload_sgmap;
	t->_dmamap_sync = _bus_dmamap_sync;

	t->_dmamem_alloc = _bus_dmamem_alloc;
	t->_dmamem_free = _bus_dmamem_free;
	t->_dmamem_map = _bus_dmamem_map;
	t->_dmamem_unmap = _bus_dmamem_unmap;
	t->_dmamem_mmap = _bus_dmamem_mmap;

	/*
	 * The firmware has set up window 2 as a 1G direct-mapped DMA
	 * window beginning at 1G.  We leave it alone.  Disable
	 * window 1.
	 */
	REGVAL(EPIC_PCI_BASE_1) = 0;
	alpha_mb();

	/*
	 * Initialize the SGMAP.
	 */
	alpha_sgmap_init(t, &acp->ac_sgmap, "apecs_sgmap",
	    APECS_SGMAP_MAPPED_BASE, 0, APECS_SGMAP_MAPPED_SIZE,
	    sizeof(u_int64_t), NULL, 0);

	/*
	 * Set up window 1 as an 8MB SGMAP-mapped window
	 * starting at 8MB.
	 */
	REGVAL(EPIC_PCI_BASE_1) = APECS_SGMAP_MAPPED_BASE |
	    EPIC_PCI_BASE_SGEN | EPIC_PCI_BASE_WENB;
	alpha_mb();

	REGVAL(EPIC_PCI_MASK_1) = EPIC_PCI_MASK_8M;
	alpha_mb();

	tbase = acp->ac_sgmap.aps_ptpa >> EPIC_TBASE_SHIFT;
	if ((tbase & EPIC_TBASE_T_BASE) != tbase)
		panic("apecs_dma_init: bad page table address");
	REGVAL(EPIC_TBASE_1) = tbase;
	alpha_mb();

	APECS_TLB_INVALIDATE();

	/* XXX XXX BEGIN XXX XXX */
	{							/* XXX */
		extern paddr_t alpha_XXX_dmamap_or;		/* XXX */
		alpha_XXX_dmamap_or = APECS_DIRECT_MAPPED_BASE;	/* XXX */
	}							/* XXX */
	/* XXX XXX END XXX XXX */
}

/*
 * Return the bus dma tag to be used for the specified bus type.
 * INTERNAL USE ONLY!
 */
bus_dma_tag_t
apecs_dma_get_tag(t, bustype)
	bus_dma_tag_t t;
	alpha_bus_t bustype;
{
	struct apecs_config *acp = t->_cookie;

	switch (bustype) {
	case ALPHA_BUS_PCI:
	case ALPHA_BUS_EISA:
		/*
		 * Systems with an APECS can only support 1G
		 * of memory, so we use the direct-mapped window
		 * on busses that have 32-bit DMA.
		 */
		return (&acp->ac_dmat_direct);

	case ALPHA_BUS_ISA:
		/*
		 * ISA doesn't have enough address bits to use
		 * the direct-mapped DMA window, so we must use
		 * SGMAPs.
		 */
		return (&acp->ac_dmat_sgmap);

	default:
		panic("apecs_dma_get_tag: shouldn't be here, really...");
	}
}

/*
 * Load an APECS SGMAP-mapped DMA map with a linear buffer.
 */
int
apecs_bus_dmamap_load_sgmap(t, map, buf, buflen, p, flags)
	bus_dma_tag_t t;
	bus_dmamap_t map;
	void *buf;
	bus_size_t buflen;
	struct proc *p;
	int flags;
{
	int error;

	error = pci_sgmap_pte64_load(t, map, buf, buflen, p, flags,
	    t->_sgmap);
	if (error == 0)
		APECS_TLB_INVALIDATE();

	return (error);
}

/*
 * Load an APECS SGMAP-mapped DMA map with an mbuf chain.
 */
int
apecs_bus_dmamap_load_mbuf_sgmap(t, map, m, flags)
	bus_dma_tag_t t;
	bus_dmamap_t map;
	struct mbuf *m;
	int flags;
{
	int error;

	error = pci_sgmap_pte64_load_mbuf(t, map, m, flags, t->_sgmap);
	if (error == 0)
		APECS_TLB_INVALIDATE();

	return (error);
}

/*
 * Load an APECS SGMAP-mapped DMA map with a uio.
 */
int
apecs_bus_dmamap_load_uio_sgmap(t, map, uio, flags)
	bus_dma_tag_t t;
	bus_dmamap_t map;
	struct uio *uio;
	int flags;
{
	int error;

	error = pci_sgmap_pte64_load_uio(t, map, uio, flags, t->_sgmap);
	if (error == 0)
		APECS_TLB_INVALIDATE();

	return (error);
}

/*
 * Load an APECS SGMAP-mapped DMA map with raw memory.
 */
int
apecs_bus_dmamap_load_raw_sgmap(t, map, segs, nsegs, size, flags)
	bus_dma_tag_t t;
	bus_dmamap_t map;
	bus_dma_segment_t *segs;
	int nsegs;
	bus_size_t size;
	int flags;
{
	int error;

	error = pci_sgmap_pte64_load_raw(t, map, segs, nsegs, size, flags,
	    t->_sgmap);
	if (error == 0)
		APECS_TLB_INVALIDATE();

	return (error);
}

/*
 * Unload an APECS DMA map.
 */
void
apecs_bus_dmamap_unload_sgmap(t, map)
	bus_dma_tag_t t;
	bus_dmamap_t map;
{

	/*
	 * Invalidate any SGMAP page table entries used by this
	 * mapping.
	 */
	pci_sgmap_pte64_unload(t, map, t->_sgmap);
	APECS_TLB_INVALIDATE();

	/*
	 * Do the generic bits of the unload.
	 */
	_bus_dmamap_unload(t, map);
}


code:
/*	$OpenBSD: apecs_pci.c,v 1.11 2010/12/04 17:06:31 miod Exp $	*/
/*	$NetBSD: apecs_pci.c,v 1.10 1996/11/13 21:13:25 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/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/device.h>

#include <uvm/uvm_extern.h>

#include <machine/autoconf.h>	/* badaddr() proto */

#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <alpha/pci/apecsreg.h>
#include <alpha/pci/apecsvar.h>

void		apecs_attach_hook(struct device *, struct device *,
		    struct pcibus_attach_args *);
int		apecs_bus_maxdevs(void *, int);
pcitag_t	apecs_make_tag(void *, int, int, int);
void		apecs_decompose_tag(void *, pcitag_t, int *, int *,
		    int *);
int		apecs_conf_size(void *, pcitag_t);
pcireg_t	apecs_conf_read(void *, pcitag_t, int);
void		apecs_conf_write(void *, pcitag_t, int, pcireg_t);

void
apecs_pci_init(pc, v)
	pci_chipset_tag_t pc;
	void *v;
{

	pc->pc_conf_v = v;
	pc->pc_attach_hook = apecs_attach_hook;
	pc->pc_bus_maxdevs = apecs_bus_maxdevs;
	pc->pc_make_tag = apecs_make_tag;
	pc->pc_decompose_tag = apecs_decompose_tag;
	pc->pc_conf_size = apecs_conf_size;
	pc->pc_conf_read = apecs_conf_read;
	pc->pc_conf_write = apecs_conf_write;
}

void
apecs_attach_hook(parent, self, pba)
	struct device *parent, *self;
	struct pcibus_attach_args *pba;
{
}

int
apecs_bus_maxdevs(cpv, busno)
	void *cpv;
	int busno;
{

	return 32;
}

pcitag_t
apecs_make_tag(cpv, b, d, f)
	void *cpv;
	int b, d, f;
{

	return (b << 16) | (d << 11) | (f << 8);
}

void
apecs_decompose_tag(cpv, tag, bp, dp, fp)
	void *cpv;
	pcitag_t tag;
	int *bp, *dp, *fp;
{

	if (bp != NULL)
		*bp = (tag >> 16) & 0xff;
	if (dp != NULL)
		*dp = (tag >> 11) & 0x1f;
	if (fp != NULL)
		*fp = (tag >> 8) & 0x7;
}

int
apecs_conf_size(void *cpv, pcitag_t tag)
{
	return PCI_CONFIG_SPACE_SIZE;
}

pcireg_t
apecs_conf_read(cpv, tag, offset)
	void *cpv;
	pcitag_t tag;
	int offset;
{
	struct apecs_config *acp = cpv;
	pcireg_t *datap, data;
	int s, secondary, ba;
	int32_t old_haxr2;					/* XXX */

	s = 0;					/* XXX gcc -Wuninitialized */
	old_haxr2 = 0;				/* XXX gcc -Wuninitialized */

	/* secondary if bus # != 0 */
	pci_decompose_tag(&acp->ac_pc, tag, &secondary, 0, 0);
	if (secondary) {
		s = splhigh();
		old_haxr2 = REGVAL(EPIC_HAXR2);
		alpha_mb();
		REGVAL(EPIC_HAXR2) = old_haxr2 | 0x1;
		alpha_mb();
	}

	datap = (pcireg_t *)ALPHA_PHYS_TO_K0SEG(APECS_PCI_CONF |
	    tag << 5UL |					/* XXX */
	    (offset & ~0x03) << 5 |				/* XXX */
	    0 << 5 |						/* XXX */
	    0x3 << 3);						/* XXX */
	data = (pcireg_t)-1;
	if (!(ba = badaddr(datap, sizeof *datap)))
		data = *datap;

	if (secondary) {
		alpha_mb();
		REGVAL(EPIC_HAXR2) = old_haxr2;
		alpha_mb();
		splx(s);
	}

#if 0
	printf("apecs_conf_read: tag 0x%lx, reg 0x%lx -> %x @ %p%s\n", tag, reg,
	    data, datap, ba ? " (badaddr)" : "");
#endif

	return data;
}

void
apecs_conf_write(cpv, tag, offset, data)
	void *cpv;
	pcitag_t tag;
	int offset;
	pcireg_t data;
{
	struct apecs_config *acp = cpv;
	pcireg_t *datap;
	int s, secondary;
	int32_t old_haxr2;					/* XXX */

	s = 0;					/* XXX gcc -Wuninitialized */
	old_haxr2 = 0;				/* XXX gcc -Wuninitialized */

	/* secondary if bus # != 0 */
	pci_decompose_tag(&acp->ac_pc, tag, &secondary, 0, 0);
	if (secondary) {
		s = splhigh();
		old_haxr2 = REGVAL(EPIC_HAXR2);
		alpha_mb();
		REGVAL(EPIC_HAXR2) = old_haxr2 | 0x1;
		alpha_mb();
	}

	datap = (pcireg_t *)ALPHA_PHYS_TO_K0SEG(APECS_PCI_CONF |
	    tag << 5UL |					/* XXX */
	    (offset & ~0x03) << 5 |				/* XXX */
	    0 << 5 |						/* XXX */
	    0x3 << 3);						/* XXX */

	alpha_mb();
	*datap = data;
	alpha_mb();
	alpha_mb();

	if (secondary) {
		alpha_mb();
		REGVAL(EPIC_HAXR2) = old_haxr2;
		alpha_mb();
		splx(s);
	}

#if 0
	printf("apecs_conf_write: tag 0x%lx, reg 0x%lx -> 0x%x @ %p\n", tag,
	    reg, data, datap);
#endif
}


code:
/* $OpenBSD: apecsreg.h,v 1.6 2001/02/16 08:23:39 jason Exp $ */
/* $NetBSD: apecsreg.h,v 1.5.2.2 1997/06/06 20:26:53 thorpej 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.
 */

/*
 * APECS Chipset registers and constants.
 *
 * Taken from ``DECchip 21071 and DECchip 21072 Core Logic Chipsets Data
 * Sheet'' (DEC order number EC-QAEMA-TE), pages 4-1 - 4-27, 10-21 - 10-38.
 */

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

/*
 * Base addresses
 */
#define	COMANCHE_BASE	 0x180000000L			/* 21071-CA Regs */
#define	EPIC_BASE	 0x1a0000000L			/* 21071-DA Regs */
#define	APECS_PCI_IACK	 0x1b0000000L			/* PCI Int. Ack. */
#define	APECS_PCI_SIO	 0x1c0000000L			/* PCI Sp. I/O Space */
#define	APECS_PCI_CONF	 0x1e0000000L			/* PCI Conf. Space */
#define	APECS_PCI_SPARSE 0x200000000L			/* PCI Sparse Space */
#define	APECS_PCI_DENSE	 0x300000000L			/* PCI Dense Space */

/*
 * 21071-CA Registers
 */

/*
 * 21071-CA General Registers
 */
#define	COMANCHE_GCR	(COMANCHE_BASE + 0x0000)	/* General Control */
#define		COMANCHE_GCR_RSVD	0xc009
#define		COMANCHE_GCR_SYSARB	0x0006
#define		COMANCHE_GCR_WIDEMEM	0x0010
#define		COMANCHE_GCR_BC_EN	0x0020
#define		COMANCHE_GCR_BC_NOALLOC	0x0040
#define		COMANCHE_GCR_BC_LONGWR	0x0080
#define		COMANCHE_GCR_BC_IGNTAG	0x0100
#define		COMANCHE_GCR_BC_FRCTAG	0x0200
#define		COMANCHE_GCR_BC_FRCD	0x0400
#define		COMANCHE_GCR_BC_FRCV	0x0800
#define		COMANCHE_GCR_BC_FRCP	0x1000
#define		COMANCHE_GCR_BC_BADAP	0x2000

#define	COMANCHE_RSVD	(COMANCHE_BASE + 0x0020)	/* Reserved */

#define	COMANCHE_ED	(COMANCHE_BASE + 0x0040)	/* Err & Diag Status */
#define		COMANCHE_ED_LOSTERR	0x0001
#define		COMANCHE_ED_BC_TAPERR	0x0002
#define		COMANCHE_ED_BC_TCPERR	0x0004
#define		COMANCHE_ED_NXMERR	0x0008
#define		COMANCHE_ED_DMACAUSE	0x0010
#define		COMANCHE_ED_VICCAUSE	0x0020
#define		COMANCHE_ED_CREQCAUSE	0x01c0
#define		COMANCHE_ED_RSVD	0x1e00
#define		COMANCHE_ED_PASS2	0x2000
#define		COMANCHE_ED_IDXLLOCK	0x4000
#define		COMANCHE_ED_WRPEND	0x8000

#define	COMANCHE_TAGENB	(COMANCHE_BASE + 0x0060)	/* Tag Enable */
#define		COMANCHE_TAGENB_RSVD	0x0001

#define		COMANCHE_TAGENB_C_4G	0x0000
#define		COMANCHE_TAGENB_C_2G	0x8000
#define		COMANCHE_TAGENB_C_1G	0xc000
#define		COMANCHE_TAGENB_C_512M	0xe000
#define		COMANCHE_TAGENB_C_256M	0xf000
#define		COMANCHE_TAGENB_C_128M	0xf800
#define		COMANCHE_TAGENB_C_64M	0xfc00
#define		COMANCHE_TAGENB_C_32M	0xfe00
#define		COMANCHE_TAGENB_C_16M	0xff00
#define		COMANCHE_TAGENB_C_8M	0xff80
#define		COMANCHE_TAGENB_C_4M	0xffc0
#define		COMANCHE_TAGENB_C_2M	0xffe0
#define		COMANCHE_TAGENB_C_1M	0xfff0
#define		COMANCHE_TAGENB_C_512K	0xfff8
#define		COMANCHE_TAGENB_C_256K	0xfffc
#define		COMANCHE_TAGENB_C_128K	0xfffe

#define		COMANCHE_TAGENB_M_4G	0xffff
#define		COMANCHE_TAGENB_M_2G	0x7fff
#define		COMANCHE_TAGENB_M_1G	0x3fff
#define		COMANCHE_TAGENB_M_512M	0x1fff
#define		COMANCHE_TAGENB_M_256M	0x0fff
#define		COMANCHE_TAGENB_M_128M	0x07ff
#define		COMANCHE_TAGENB_M_64M	0x03ff
#define		COMANCHE_TAGENB_M_32M	0x01ff
#define		COMANCHE_TAGENB_M_16M	0x00ff
#define		COMANCHE_TAGENB_M_8M	0x007f
#define		COMANCHE_TAGENB_M_4M	0x003f
#define		COMANCHE_TAGENB_M_2M	0x001f
#define		COMANCHE_TAGENB_M_1M	0x000e
#define		COMANCHE_TAGENB_M_512K	0x0006
#define		COMANCHE_TAGENB_M_256K	0x0002
#define		COMANCHE_TAGENB_M_128K	0x0000

#define	COMANCHE_ERR_LO	(COMANCHE_BASE + 0x0080)	/* Error Low Address */

#define	COMANCHE_ERR_HI	(COMANCHE_BASE + 0x00a0)	/* Error High Address */
#define		COMANCHE_ERR_HI_RSVD	0xe000

#define	COMANCHE_LCK_LO	(COMANCHE_BASE + 0x00c0)	/* LDx_L Low Address */

#define	COMANCHE_LCK_HI	(COMANCHE_BASE + 0x00e0)	/* LDx_L High Address */
#define		COMANCHE_LOCK_HI_RSVD	0xe000

/*
 * 21071-CA Memory Registers
 */
#define	COMANCHE_GTIM	(COMANCHE_BASE + 0x0200)	 /* Global Timing */
#define		COMANCHE_LOCK_HI_RSVD	0xe000

#define	COMANCHE_RTIM	(COMANCHE_BASE + 0x0220)	 /* Refresh Timing */

#define	COMANCHE_VFP	(COMANCHE_BASE + 0x0240)	 /* Video Frame Ptr. */
#define		COMANCHE_VFP_COL	0x001f
#define		COMANCHE_VFP_ROW	0x3fe0
#define		COMANCHE_VFP_SUBBANK	0x4000
#define		COMANCHE_VFP_RSVD	0x8000

#define	COMANCHE_PD_LO	(COMANCHE_BASE + 0x0260)	/* Pres Detect Low */

#define	COMANCHE_PD_HI	(COMANCHE_BASE + 0x0280)	/* Pres Detect High */

/*
 * 21071-CA Memory banks' Base Address Register format
 */
#define	COMANCHE_B0_BAR	(COMANCHE_BASE + 0x0800)	/* Bank 0 BA */
#define	COMANCHE_B1_BAR	(COMANCHE_BASE + 0x0820)	/* Bank 1 BA */
#define	COMANCHE_B2_BAR	(COMANCHE_BASE + 0x0840)	/* Bank 2 BA */
#define	COMANCHE_B3_BAR	(COMANCHE_BASE + 0x0860)	/* Bank 3 BA */
#define	COMANCHE_B4_BAR	(COMANCHE_BASE + 0x0880)	/* Bank 4 BA */
#define	COMANCHE_B5_BAR	(COMANCHE_BASE + 0x08a0)	/* Bank 5 BA */
#define	COMANCHE_B6_BAR	(COMANCHE_BASE + 0x08c0)	/* Bank 6 BA */
#define	COMANCHE_B7_BAR	(COMANCHE_BASE + 0x08e0)	/* Bank 7 BA */
#define	COMANCHE_B8_BAR	(COMANCHE_BASE + 0x0900)	/* Bank 8 BA */
#define		COMANCHE_BAR_RSVD	0x001f

/*
 * 21071-CA Memory banks' Configuration Register format
 */
#define	COMANCHE_B0_CR	(COMANCHE_BASE + 0x0a00)	/* Bank 0 Config */
#define	COMANCHE_B1_CR	(COMANCHE_BASE + 0x0a20)	/* Bank 1 Config */
#define	COMANCHE_B2_CR	(COMANCHE_BASE + 0x0a40)	/* Bank 2 Config */
#define	COMANCHE_B3_CR	(COMANCHE_BASE + 0x0a60)	/* Bank 3 Config */
#define	COMANCHE_B4_CR	(COMANCHE_BASE + 0x0a80)	/* Bank 4 Config */
#define	COMANCHE_B5_CR	(COMANCHE_BASE + 0x0aa0)	/* Bank 5 Config */
#define	COMANCHE_B6_CR	(COMANCHE_BASE + 0x0ac0)	/* Bank 6 Config */
#define	COMANCHE_B7_CR	(COMANCHE_BASE + 0x0ae0)	/* Bank 7 Config */
#define	COMANCHE_B8_CR	(COMANCHE_BASE + 0x0b00)	/* Bank 8 Config */
#define		COMANCHE_CR_VALID	0x0001
#define		COMANCHE_CR_SIZE	0x001e
#define		COMANCHE_CR_SUBENA	0x0020
#define		COMANCHE_CR_COLSEL	0x01c0
#define		COMANCHE_CR_S0_RSVD	0xfe00
#define		COMANCHE_CR_S8_CHECK	0x0200
#define		COMANCHE_CR_S8_RSVD	0xfc00

/*
 * 21071-CA Memory banks' Timing Register A format
 */
#define	COMANCHE_B0_TRA	(COMANCHE_BASE + 0x0c00)	/* Bank 0 Timing A */
#define	COMANCHE_B1_TRA	(COMANCHE_BASE + 0x0c20)	/* Bank 1 Timing A */
#define	COMANCHE_B2_TRA	(COMANCHE_BASE + 0x0c40)	/* Bank 2 Timing A */
#define	COMANCHE_B3_TRA	(COMANCHE_BASE + 0x0c60)	/* Bank 3 Timing A */
#define	COMANCHE_B4_TRA	(COMANCHE_BASE + 0x0c80)	/* Bank 4 Timing A */
#define	COMANCHE_B5_TRA	(COMANCHE_BASE + 0x0ca0)	/* Bank 5 Timing A */
#define	COMANCHE_B6_TRA	(COMANCHE_BASE + 0x0cc0)	/* Bank 6 Timing A */
#define	COMANCHE_B7_TRA	(COMANCHE_BASE + 0x0ce0)	/* Bank 7 Timing A */
#define	COMANCHE_B8_TRA	(COMANCHE_BASE + 0x0d00)	/* Bank 8 Timing A */
#define		COMANCHE_TRA_ROWSETUP	0x0003
#define		COMANCHE_TRA_ROWHOLD	0x000c
#define		COMANCHE_TRA_COLSETUP	0x0070
#define		COMANCHE_TRA_COLHOLD	0x0180
#define		COMANCHE_TRA_RDLYROW	0x0e00
#define		COMANCHE_TRA_RDLYCOL	0x7000
#define		COMANCHE_TRA_RSVD	0x8000

/*
 * 21071-CA Memory banks' Timing Register B format
 */
#define	COMANCHE_B0_TRB	(COMANCHE_BASE + 0x0e00)	/* Bank 0 Timing B */
#define	COMANCHE_B1_TRB	(COMANCHE_BASE + 0x0e20)	/* Bank 1 Timing B */
#define	COMANCHE_B2_TRB	(COMANCHE_BASE + 0x0e40)	/* Bank 2 Timing B */
#define	COMANCHE_B3_TRB	(COMANCHE_BASE + 0x0e60)	/* Bank 3 Timing B */
#define	COMANCHE_B4_TRB	(COMANCHE_BASE + 0x0e80)	/* Bank 4 Timing B */
#define	COMANCHE_B5_TRB	(COMANCHE_BASE + 0x0ea0)	/* Bank 5 Timing B */
#define	COMANCHE_B6_TRB	(COMANCHE_BASE + 0x0ec0)	/* Bank 6 Timing B */
#define	COMANCHE_B7_TRB	(COMANCHE_BASE + 0x0ee0)	/* Bank 7 Timing B */
#define	COMANCHE_B8_TRB	(COMANCHE_BASE + 0x0f00)	/* Bank 8 Timing B */
#define		COMANCHE_TRB_RTCAS	0x0007
#define		COMANCHE_TRB_WTCAS	0x0038
#define		COMANCHE_TRB_TCP	0x00c0
#define		COMANCHE_TRB_WHOLD0ROW	0x0700
#define		COMANCHE_TRB_WHOLD0COL	0x3800
#define		COMANCHE_TRB_RSVD	0xc000

/*
 * 21071-DA Registers
 */
#define	EPIC_DCSR	(EPIC_BASE + 0x0000)		/* Diagnostic CSR */
#define		EPIC_DCSR_TENB		0x00000001
#define		EPIC_DCSR_RSVD		0x7fc00082
#define		EPIC_DCSR_PENB		0x00000004
#define		EPIC_DCSR_DCEI		0x00000008
#define		EPIC_DCSR_DPEC		0x00000010
#define		EPIC_DCSR_IORT		0x00000020
#define		EPIC_DCSR_LOST		0x00000040
#define		EPIC_DCSR_DDPE		0x00000100
#define		EPIC_DCSR_IOPE		0x00000200
#define		EPIC_DCSR_TABT		0x00000400
#define		EPIC_DCSR_NDEV		0x00000800
#define		EPIC_DCSR_CMRD		0x00001000
#define		EPIC_DCSR_UMRD		0x00002000
#define		EPIC_DCSR_IPTL		0x00004000
#define		EPIC_DCSR_MERR		0x00008000
#define		EPIC_DCSR_DBYP		0x00030000
#define		EPIC_DCSR_PCMD		0x003c0000
#define		EPIC_DCSR_PASS2		0x80000000

#define	EPIC_PEAR	(EPIC_BASE + 0x0020)		/* PCI Err Addr. */

#define	EPIC_SEAR	(EPIC_BASE + 0x0040)		/* sysBus Err Addr. */
#define		EPIC_SEAR_RSVD		0x0000000f
#define		EPIC_SEAR_SYS_ERR	0xfffffff0

#define	EPIC_DUMMY_1	(EPIC_BASE + 0x0060)		/* Dummy 1 */
#define	EPIC_DUMMY_2	(EPIC_BASE + 0x0080)		/* Dummy 2 */
#define	EPIC_DUMMY_3	(EPIC_BASE + 0x00a0)		/* Dummy 3 */

#define	EPIC_TBASE_1	(EPIC_BASE + 0x00c0)		/* Trans. Base 1 */
#define	EPIC_TBASE_2	(EPIC_BASE + 0x00e0)		/* Trans. Base 2 */
#define		EPIC_TBASE_RSVD		0x000001ff
#define		EPIC_TBASE_T_BASE	0xfffffe00
#define		EPIC_TBASE_SHIFT	1

#define	EPIC_PCI_BASE_1	(EPIC_BASE + 0x0100)		/* PCI Base 1 */
#define	EPIC_PCI_BASE_2	(EPIC_BASE + 0x0120)		/* PCI Base 2 */
#define		EPIC_PCI_BASE_RSVD	0x0003ffff
#define		EPIC_PCI_BASE_SGEN	0x00040000
#define		EPIC_PCI_BASE_WENB	0x00080000
#define		EPIC_PCI_BASE_PCI_BASE	0xfff00000

#define	EPIC_PCI_MASK_1	(EPIC_BASE + 0x0140)		/* PCI Mask 1 */
#define	EPIC_PCI_MASK_2	(EPIC_BASE + 0x0160)		/* PCI Mask 2 */
#define		EPIC_PCI_MASK_RSVD	0x000fffff
#define		EPIC_PCI_MASK_PCI_MASK	0xfff00000
#define		EPIC_PCI_MASK_1M	0x00000000
#define		EPIC_PCI_MASK_2M	0x00100000
#define		EPIC_PCI_MASK_4M	0x00300000
#define		EPIC_PCI_MASK_8M	0x00700000
#define		EPIC_PCI_MASK_16M	0x00f00000
#define		EPIC_PCI_MASK_32M	0x01f00000
#define		EPIC_PCI_MASK_64M	0x03f00000
#define		EPIC_PCI_MASK_128M	0x07f00000
#define		EPIC_PCI_MASK_256M	0x0ff00000
#define		EPIC_PCI_MASK_512M	0x1ff00000
#define		EPIC_PCI_MASK_1G	0x3ff00000
#define		EPIC_PCI_MASK_2G	0x7ff00000
#define		EPIC_PCI_MASK_4G	0xfff00000

#define	EPIC_HAXR0	(EPIC_BASE + 0x0180)		/* Host Addr Extn 0 */

#define	EPIC_HAXR1	(EPIC_BASE + 0x01a0)		/* Host Addr Extn 1 */
#define		EPIC_HAXR1_RSVD		0x07ffffff
#define		EPIC_HAXR1_EADDR	0xf8000000

#define	EPIC_HAXR2	(EPIC_BASE + 0x01c0)		/* Host Addr Extn 2 */
#define		EPIC_HAXR2_CONF_TYPE	0x00000003
#define		EPIC_HAXR2_CONF_TYPO0	0x00000000
#define		EPIC_HAXR2_CONF_TYPE1	0x00000001
#define		EPIC_HAXR2_RSVD		0x00fffffc
#define		EPIC_HAXR2_EADDR	0xff000000

#define	EPIC_PMLT	(EPIC_BASE + 0x01e0)		/* PCI Mstr Lat Tmr */
#define		EPIC_PMLT_PMLC		0x000000ff
#define		EPIC_PMLT_RSVD		0xffffff00

#define	EPIC_TLB_TAG_0	(EPIC_BASE + 0x0200)		/* TLB Tag 0 */
#define	EPIC_TLB_TAG_1	(EPIC_BASE + 0x0220)		/* TLB Tag 1 */
#define	EPIC_TLB_TAG_2	(EPIC_BASE + 0x0240)		/* TLB Tag 2 */
#define	EPIC_TLB_TAG_3	(EPIC_BASE + 0x0260)		/* TLB Tag 3 */
#define	EPIC_TLB_TAG_4	(EPIC_BASE + 0x0280)		/* TLB Tag 4 */
#define	EPIC_TLB_TAG_5	(EPIC_BASE + 0x02a0)		/* TLB Tag 5 */
#define	EPIC_TLB_TAG_6	(EPIC_BASE + 0x02c0)		/* TLB Tag 6 */
#define	EPIC_TLB_TAG_7	(EPIC_BASE + 0x02e0)		/* TLB Tag 7 */
#define		EPIC_TLB_TAG_RSVD	0x00000fff
#define		EPIC_TLB_TAG_EVAL	0x00001000
#define		EPIC_TLB_TAG_PCI_PAGE	0xffffe000

#define	EPIC_TLB_DATA_0	(EPIC_BASE + 0x0300)		/* TLB Data 0 */
#define	EPIC_TLB_DATA_1	(EPIC_BASE + 0x0320)		/* TLB Data 1 */
#define	EPIC_TLB_DATA_2	(EPIC_BASE + 0x0340)		/* TLB Data 2 */
#define	EPIC_TLB_DATA_3	(EPIC_BASE + 0x0360)		/* TLB Data 3 */
#define	EPIC_TLB_DATA_4	(EPIC_BASE + 0x0380)		/* TLB Data 4 */
#define	EPIC_TLB_DATA_5	(EPIC_BASE + 0x03a0)		/* TLB Data 5 */
#define	EPIC_TLB_DATA_6	(EPIC_BASE + 0x03c0)		/* TLB Data 6 */
#define	EPIC_TLB_DATA_7	(EPIC_BASE + 0x03e0)		/* TLB Data 7 */
#define		EPIC_TLB_DATA_RSVD	0xffe00001
#define		EPIC_TLB_DATA_CPU_PAGE	0x001ffffe

#define	EPIC_TBIA	(EPIC_BASE + 0x0400)		/* TLB Invl All */

/*
 * EPIC Scatter-Gather Map Entries
 */

struct sgmapent {
	u_int64_t val;
};
#define	SGMAPENT_EVAL	0x0000000000000001L
#define	SGMAPENT_PFN	0x00000000001ffffeL
#define	SGMAPENT_RSVD	0xffffffffffe00000L

#define	SGMAP_MAKEENTRY(pfn)	(SGMAPENT_EVAL | ((pfn) << 1))


code:
/*	$OpenBSD: apecsvar.h,v 1.10 2006/03/16 22:32:44 miod Exp $	*/
/*	$NetBSD: apecsvar.h,v 1.5 1996/11/25 03:49: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.
 */

#include <dev/isa/isavar.h>
#include <dev/pci/pcivar.h>
#include <alpha/pci/pci_sgmap_pte64.h>

/*
 * An APECS chipset's configuration.
 *
 * All of the information that the chipset-specific functions need to
 * do their dirty work (and more!).
 */
struct apecs_config {
	int	ac_initted;

	int	ac_comanche_pass2;
	int	ac_epic_pass2;
	int	ac_memwidth;

	struct alpha_bus_space ac_iot, ac_memt;
	struct alpha_pci_chipset ac_pc;

	struct alpha_bus_dma_tag ac_dmat_direct;
	struct alpha_bus_dma_tag ac_dmat_sgmap;

	struct alpha_sgmap ac_sgmap;

	u_int32_t ac_haxr1, ac_haxr2;

	struct extent *ac_io_ex, *ac_d_mem_ex, *ac_s_mem_ex;
	int	ac_mallocsafe;
};

void	apecs_init(struct apecs_config *, int);
void	apecs_pci_init(pci_chipset_tag_t, void *);
void	apecs_dma_init(struct apecs_config *);

void apecs_bus_io_init(bus_space_tag_t, void *);
void apecs_bus_mem_init(bus_space_tag_t, void *);


code:
/* $OpenBSD: cia.c,v 1.25 2009/03/30 21:43:13 kettenis Exp $ */
/* $NetBSD: cia.c,v 1.56 2000/06/29 08:58:45 mrg Exp $ */

/*-
 * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
 * NASA Ames Research Center.
 *
 * 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/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/device.h>
#include <uvm/uvm_extern.h>

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

#include <dev/isa/isareg.h>
#include <dev/isa/isavar.h>

#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <alpha/pci/ciareg.h>
#include <alpha/pci/ciavar.h>

#ifdef DEC_KN20AA
#include <alpha/pci/pci_kn20aa.h>
#endif
#ifdef DEC_EB164
#include <alpha/pci/pci_eb164.h>
#endif
#ifdef DEC_550
#include <alpha/pci/pci_550.h>
#endif
#ifdef DEC_1000A
#include <alpha/pci/pci_1000a.h>
#endif
#ifdef DEC_1000
#include <alpha/pci/pci_1000.h>
#endif

int	ciamatch(struct device *, void *, void *);
void	ciaattach(struct device *, struct device *, void *);

struct cfattach cia_ca = {
	sizeof(struct device), ciamatch, ciaattach,
};

struct cfdriver cia_cd = {
	NULL, "cia", DV_DULL,
};

static int	ciaprint(void *, const char *pnp);

/* There can be only one. */
int ciafound;
struct cia_config cia_configuration;

/*
 * This determines if we attempt to use BWX for PCI bus and config space
 * access.  Some systems, notably with Pyxis, don't fare so well unless
 * BWX is used.
 *
 * EXCEPT!  Some devices have a really hard time if BWX is used (WHY?!).
 * So, we decouple the uses for PCI config space and PCI bus space.
 *
 * FURTHERMORE!  The Pyxis, most notably earlier revs, really don't
 * do so well if you don't use BWX for bus access.  So we default to
 * forcing BWX on those chips.
 *
 * Geez.
 */

#ifndef CIA_PCI_USE_BWX
#define	CIA_PCI_USE_BWX	1
#endif

#ifndef	CIA_BUS_USE_BWX
#define	CIA_BUS_USE_BWX	1
#endif

#ifndef CIA_PYXIS_FORCE_BWX
#define	CIA_PYXIS_FORCE_BWX 1
#endif

int	cia_pci_use_bwx = CIA_PCI_USE_BWX;
int	cia_bus_use_bwx = CIA_BUS_USE_BWX;
int	cia_pyxis_force_bwx = CIA_PYXIS_FORCE_BWX;

int
ciamatch(parent, match, aux)
	struct device *parent;
	void *match;
	void *aux;
{
	struct mainbus_attach_args *ma = aux;

	/* Make sure that we're looking for a CIA. */
	if (strcmp(ma->ma_name, cia_cd.cd_name) != 0)
		return (0);

	if (ciafound)
		return (0);

	return (1);
}

/*
 * Set up the chipset's function pointers.
 */
void
cia_init(ccp, mallocsafe)
	struct cia_config *ccp;
	int mallocsafe;
{
	int pci_use_bwx = cia_pci_use_bwx;
	int bus_use_bwx = cia_bus_use_bwx;

	ccp->cc_hae_mem = REGVAL(CIA_CSR_HAE_MEM);
	ccp->cc_hae_io = REGVAL(CIA_CSR_HAE_IO);
	ccp->cc_rev = REGVAL(CIA_CSR_REV) & REV_MASK;

	/*
	 * Determine if we have a Pyxis.  Only two systypes can
	 * have this: the EB164 systype (AlphaPC164LX and AlphaPC164SX)
	 * and the DEC_550 systype (Miata).
	 */
	if ((cputype == ST_EB164 &&
	     (hwrpb->rpb_variation & SV_ST_MASK) >= SV_ST_ALPHAPC164LX_400) ||
	    cputype == ST_DEC_550) {
		ccp->cc_flags |= CCF_ISPYXIS;
		if (cia_pyxis_force_bwx)
			pci_use_bwx = bus_use_bwx = 1;
	}

	/*
	 * ALCOR/ALCOR2 Revisions >= 2 and Pyxis have the CNFG register.
	 */
	if (ccp->cc_rev >= 2 || (ccp->cc_flags & CCF_ISPYXIS) != 0)
		ccp->cc_cnfg = REGVAL(CIA_CSR_CNFG);
	else
		ccp->cc_cnfg = 0;

	/*
	 * Use BWX iff:
	 *
	 *	- It hasn't been disabled by the user,
	 *	- it's enabled in CNFG,
	 *	- we're implementation version ev5,
	 *	- BWX is enabled in the CPU's capabilities mask (yes,
	 *	  the bit is really cleared if the capability exists...)
	 */
	if ((pci_use_bwx || bus_use_bwx) &&
	    (ccp->cc_cnfg & CNFG_BWEN) != 0 &&
	    (cpu_amask & ALPHA_AMASK_BWX) != 0) {
		u_int32_t ctrl;

		if (pci_use_bwx)
			ccp->cc_flags |= CCF_PCI_USE_BWX;
		if (bus_use_bwx)
			ccp->cc_flags |= CCF_BUS_USE_BWX;

		/*
		 * For whatever reason, the firmware seems to enable PCI
		 * loopback mode if it also enables BWX.  Make sure it's
		 * enabled if we have an old, buggy firmware rev.
		 */
		alpha_mb();
		ctrl = REGVAL(CIA_CSR_CTRL);
		if ((ctrl & CTRL_PCI_LOOP_EN) == 0) {
			REGVAL(CIA_CSR_CTRL) = ctrl | CTRL_PCI_LOOP_EN;
			alpha_mb();
		}
	}

	if (!ccp->cc_initted) {
		/* don't do these twice since they set up extents */
		if (ccp->cc_flags & CCF_BUS_USE_BWX) {
			cia_bwx_bus_io_init(&ccp->cc_iot, ccp);
			cia_bwx_bus_mem_init(&ccp->cc_memt, ccp);
		} else {
			cia_bus_io_init(&ccp->cc_iot, ccp);
			cia_bus_mem_init(&ccp->cc_memt, ccp);
		}
	}
	ccp->cc_mallocsafe = mallocsafe;

	cia_pci_init(&ccp->cc_pc, ccp);
	alpha_pci_chipset = &ccp->cc_pc;
	alpha_pci_chipset->pc_name = "cia";
	alpha_pci_chipset->pc_dense = CIA_PCI_DENSE;
	alpha_pci_chipset->pc_hae_mask = 7L << 29;
	if (ccp->cc_flags & CCF_BUS_USE_BWX) {
		alpha_pci_chipset->pc_mem = CIA_EV56_BWMEM;
		alpha_pci_chipset->pc_ports = CIA_EV56_BWIO;
		alpha_pci_chipset->pc_bwx = 1;
	} else {
		alpha_pci_chipset->pc_mem = CIA_PCI_SMEM1;
		alpha_pci_chipset->pc_ports = CIA_PCI_SIO1;
		alpha_pci_chipset->pc_bwx = 0;
	}

	ccp->cc_initted = 1;
}

void
ciaattach(parent, self, aux)
	struct device *parent, *self;
	void *aux;
{
	struct cia_config *ccp;
	struct pcibus_attach_args pba;
	const char *name;
	int pass;

	/* note that we've attached the chipset; can't have 2 CIAs. */
	ciafound = 1;

	/*
	 * set up the chipset's info; done once at console init time
	 * (maybe), but we must do it here as well to take care of things
	 * that need to use memory allocation.
	 */
	ccp = &cia_configuration;
	cia_init(ccp, 1);

	if (ccp->cc_flags & CCF_ISPYXIS) {
		name = "Pyxis";
		pass = ccp->cc_rev;
	} else {
		name = "ALCOR/ALCOR2";
		pass = ccp->cc_rev + 1;
	}

	printf(": DECchip 2117x Core Logic Chipset (%s), pass %d\n",
	    name, pass);

	if (ccp->cc_cnfg)
		printf("%s: extended capabilities: %b\n", self->dv_xname,
		    ccp->cc_cnfg, CIA_CSR_CNFG_BITS);

	switch (ccp->cc_flags & (CCF_PCI_USE_BWX|CCF_BUS_USE_BWX)) {
	case CCF_PCI_USE_BWX|CCF_BUS_USE_BWX:
		name = "PCI config and bus";
		break;
	case CCF_PCI_USE_BWX:
		name = "PCI config";
		break;
	case CCF_BUS_USE_BWX:
		name = "bus";
		break;
	default:
		name = NULL;
		break;
	}
	if (name != NULL)
		printf("%s: using BWX for %s access\n", self->dv_xname, name);

#ifdef DEC_550
	if (cputype == ST_DEC_550 &&
	    (hwrpb->rpb_variation & SV_ST_MASK) < SV_ST_MIATA_1_5) {
		/*
		 * Miata 1 systems have a bug: DMA cannot cross
		 * an 8k boundary!  Make sure PCI read prefetching
		 * is disabled on these chips.  Note that secondary
		 * PCI busses don't have this problem, because of
		 * the way PPBs handle PCI read requests.
		 *
		 * In the 21174 Technical Reference Manual, this is
		 * actually documented as "Pyxis Pass 1", but apparently
		 * there are chips that report themselves as "Pass 1"
		 * which do not have the bug!  Miatas with the Cypress
		 * PCI-ISA bridge (i.e. Miata 1.5 and Miata 2) do not
		 * have the bug, so we use this check.
		 *
		 * NOTE: This bug is actually worked around in cia_dma.c,
		 * when direct-mapped DMA maps are created.
		 *
		 * XXX WE NEED TO THINK ABOUT HOW TO HANDLE THIS FOR
		 * XXX SGMAP DMA MAPPINGS!
		 */
		u_int32_t ctrl;

		/* XXX no bets... */
		printf("%s: WARNING: Pyxis pass 1 DMA bug; no bets...\n",
		    self->dv_xname);

		ccp->cc_flags |= CCF_PYXISBUG;

		alpha_mb();
		ctrl = REGVAL(CIA_CSR_CTRL);
		ctrl &= ~(CTRL_RD_TYPE|CTRL_RL_TYPE|CTRL_RM_TYPE);
		REGVAL(CIA_CSR_CTRL) = ctrl;
		alpha_mb();
	}
#endif /* DEC_550 */

	cia_dma_init(ccp);

	switch (cputype) {
#ifdef DEC_KN20AA
	case ST_DEC_KN20AA:
		pci_kn20aa_pickintr(ccp);
		break;
#endif

#ifdef DEC_EB164
	case ST_EB164:
		pci_eb164_pickintr(ccp);
		break;
#endif

#ifdef DEC_550
	case ST_DEC_550:
		pci_550_pickintr(ccp);
		break;
#endif

#ifdef DEC_1000A
	case ST_DEC_1000A:
		pci_1000a_pickintr(ccp, &ccp->cc_iot, &ccp->cc_memt,
			&ccp->cc_pc);
		break;
#endif

#ifdef DEC_1000
	case ST_DEC_1000:
		pci_1000_pickintr(ccp, &ccp->cc_iot, &ccp->cc_memt,
			&ccp->cc_pc);
		break;
#endif

	default:
		panic("ciaattach: shouldn't be here, really...");
	}

	bzero(&pba, sizeof(pba));
	pba.pba_busname = "pci";
	pba.pba_iot = &ccp->cc_iot;
	pba.pba_memt = &ccp->cc_memt;
	pba.pba_dmat =
	    alphabus_dma_get_tag(&ccp->cc_dmat_direct, ALPHA_BUS_PCI);
	pba.pba_pc = &ccp->cc_pc;
	pba.pba_domain = pci_ndomains++;
	pba.pba_bus = 0;
#ifdef notyet
	pba.pba_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED;
	if ((ccp->cc_flags & CCF_PYXISBUG) == 0)
		pba.pba_flags |= PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY |
		    PCI_FLAGS_MWI_OKAY;
#endif
	config_found(self, &pba, ciaprint);
}

static int
ciaprint(aux, pnp)
	void *aux;
	const char *pnp;
{
	register struct pcibus_attach_args *pba = aux;

	/* only PCIs can attach to CIAs; easy. */
	if (pnp)
		printf("%s at %s", pba->pba_busname, pnp);
	printf(" bus %d", pba->pba_bus);
	return (UNCONF);
}

void
cia_pyxis_intr_enable(irq, onoff)
	int irq, onoff;
{
	u_int64_t imask;
	int s;

#if 0
	printf("cia_pyxis_intr_enable: %s %d\n",
	    onoff ? "enabling" : "disabling", irq);
#endif

	s = splhigh();
	alpha_mb();
	imask = REGVAL64(PYXIS_INT_MASK);
	if (onoff)
		imask |= (1UL << irq);
	else
		imask &= ~(1UL << irq);
	REGVAL64(PYXIS_INT_MASK) = imask;
	alpha_mb();
	splx(s);
}


code:
/*	$OpenBSD: cia_bus_io.c,v 1.8 2001/11/06 19:53:13 miod Exp $	*/
/*	$NetBSD: cia_bus_io.c,v 1.6 1996/11/25 03:46: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.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/syslog.h>
#include <sys/device.h>
#include <uvm/uvm_extern.h>

#include <machine/bus.h>

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

#define	CHIP		cia

#define	CHIP_EX_MALLOC_SAFE(v)	(((struct cia_config *)(v))->cc_mallocsafe)
#define	CHIP_IO_EXTENT(v)	(((struct cia_config *)(v))->cc_io_ex)

/* IO region 1 */
#define CHIP_IO_W1_BUS_START(v)						\
	    HAE_IO_REG1_START(((struct cia_config *)(v))->cc_hae_io)
#define CHIP_IO_W1_BUS_END(v)						\
	    (CHIP_IO_W1_BUS_START(v) + HAE_IO_REG1_MASK)
#define CHIP_IO_W1_SYS_START(v)						\
	    CIA_PCI_SIO1
#define CHIP_IO_W1_SYS_END(v)						\
	    (CIA_PCI_SIO1 + ((HAE_IO_REG1_MASK + 1) << 5) - 1)

/* IO region 2 */
#define CHIP_IO_W2_BUS_START(v)						\
	    HAE_IO_REG2_START(((struct cia_config *)(v))->cc_hae_io)
#define CHIP_IO_W2_BUS_END(v)						\
	    (CHIP_IO_W2_BUS_START(v) + HAE_IO_REG2_MASK)
#define CHIP_IO_W2_SYS_START(v)						\
	    CIA_PCI_SIO2
#define CHIP_IO_W2_SYS_END(v)						\
	    (CIA_PCI_SIO2 + ((HAE_IO_REG2_MASK + 1) << 5) - 1)

#include "pci_swiz_bus_io_chipdep.c"


code:
/*	$OpenBSD: cia_bus_mem.c,v 1.8 2001/11/06 19:53:13 miod Exp $	*/
/*	$NetBSD: cia_bus_mem.c,v 1.7 1996/11/25 03:46:09 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.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/syslog.h>
#include <sys/device.h>
#include <uvm/uvm_extern.h>

#include <machine/bus.h>

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

#define	CHIP		cia

#define	CHIP_EX_MALLOC_SAFE(v)	(((struct cia_config *)(v))->cc_mallocsafe)
#define	CHIP_D_MEM_EXTENT(v)	(((struct cia_config *)(v))->cc_d_mem_ex)
#define	CHIP_S_MEM_EXTENT(v)	(((struct cia_config *)(v))->cc_s_mem_ex)

/* Dense region 1 */
#define	CHIP_D_MEM_W1_BUS_START(v)	0x00000000UL
#define	CHIP_D_MEM_W1_BUS_END(v)	0xffffffffUL
#define	CHIP_D_MEM_W1_SYS_START(v)	CIA_PCI_DENSE
#define	CHIP_D_MEM_W1_SYS_END(v)	(CIA_PCI_DENSE + 0xffffffffUL)

/* Sparse region 1 */
#define	CHIP_S_MEM_W1_BUS_START(v)					\
	    HAE_MEM_REG1_START(((struct cia_config *)(v))->cc_hae_mem)
#define	CHIP_S_MEM_W1_BUS_END(v)					\
	    (CHIP_S_MEM_W1_BUS_START(v) + HAE_MEM_REG1_MASK)
#define	CHIP_S_MEM_W1_SYS_START(v)					\
	    CIA_PCI_SMEM1
#define	CHIP_S_MEM_W1_SYS_END(v)					\
	    (CIA_PCI_SMEM1 + ((HAE_MEM_REG1_MASK + 1) << 5) - 1)

/* Sparse region 2 */
#define	CHIP_S_MEM_W2_BUS_START(v)					\
	    HAE_MEM_REG2_START(((struct cia_config *)(v))->cc_hae_mem)
#define	CHIP_S_MEM_W2_BUS_END(v)					\
	    (CHIP_S_MEM_W2_BUS_START(v) + HAE_MEM_REG2_MASK)
#define	CHIP_S_MEM_W2_SYS_START(v)					\
	    CIA_PCI_SMEM2
#define	CHIP_S_MEM_W2_SYS_END(v)					\
	    (CIA_PCI_SMEM2 + ((HAE_MEM_REG2_MASK + 1) << 5) - 1)

/* Sparse region 3 */
#define	CHIP_S_MEM_W3_BUS_START(v)					\
	    HAE_MEM_REG3_START(((struct cia_config *)(v))->cc_hae_mem)
#define	CHIP_S_MEM_W3_BUS_END(v)					\
	    (CHIP_S_MEM_W3_BUS_START(v) + HAE_MEM_REG3_MASK)
#define	CHIP_S_MEM_W3_SYS_START(v)					\
	    CIA_PCI_SMEM3
#define	CHIP_S_MEM_W3_SYS_END(v)					\
	    (CIA_PCI_SMEM3 + ((HAE_MEM_REG3_MASK + 1) << 5) - 1)

#include "pci_swiz_bus_mem_chipdep.c"


code:
/* $OpenBSD: cia_bwx_bus_io.c,v 1.3 2001/11/06 19:53:13 miod Exp $ */
/* $NetBSD: cia_bwx_bus_io.c,v 1.3 2000/06/29 08:58:46 mrg 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.
 */

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

#include <uvm/uvm_extern.h>

#include <machine/bus.h>

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

#define	CHIP		cia_bwx

#define	CHIP_EX_MALLOC_SAFE(v)	(((struct cia_config *)(v))->cc_mallocsafe)
#define	CHIP_IO_EXTENT(v)	(((struct cia_config *)(v))->cc_io_ex)

#define	CHIP_IO_SYS_START(v)	CIA_EV56_BWIO

/*
 * CIA core logic with BWX enabled appears on EV56 and PCA56.  We
 * require at least EV56 support for the assembler to emit BWX opcodes.
 */
__asm(".arch ev56");

#include <alpha/pci/pci_bwx_bus_io_chipdep.c>


code:
/* $OpenBSD: cia_bwx_bus_mem.c,v 1.3 2001/11/06 19:53:13 miod Exp $ */
/* $NetBSD: cia_bwx_bus_mem.c,v 1.3 2000/06/29 08:58:46 mrg 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.
 */

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

#include <uvm/uvm_extern.h>

#include <machine/bus.h>

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

#define	CHIP		cia_bwx

#define	CHIP_EX_MALLOC_SAFE(v)	(((struct cia_config *)(v))->cc_mallocsafe)
#define	CHIP_MEM_EXTENT(v)	(((struct cia_config *)(v))->cc_d_mem_ex)

#define	CHIP_MEM_SYS_START(v)	CIA_EV56_BWMEM

/*
 * CIA core logic with BWX enabled appears on EV56 and PCA56.  We
 * require at least EV56 support for the assembler to emit BWX opcodes.
 */
__asm(".arch ev56");

#include <alpha/pci/pci_bwx_bus_mem_chipdep.c>


code:
/* $OpenBSD: cia_dma.c,v 1.11 2014/06/14 23:11:20 jmatthew Exp $ */
/* $NetBSD: cia_dma.c,v 1.16 2000/06/29 08:58:46 mrg Exp $ */

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

/*
 * XXX - We should define this before including bus.h, but since other stuff
 *       pulls in bus.h we must do this here.
 */
#define _ALPHA_BUS_DMA_PRIVATE

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

#include <uvm/uvm_extern.h>

#include <machine/bus.h>

#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <alpha/pci/ciareg.h>
#include <alpha/pci/ciavar.h>

bus_dma_tag_t cia_dma_get_tag(bus_dma_tag_t, alpha_bus_t);

int	cia_bus_dmamap_create_direct(bus_dma_tag_t, bus_size_t, int,
	    bus_size_t, bus_size_t, int, bus_dmamap_t *);
void	cia_bus_dmamap_destroy_direct(bus_dma_tag_t, bus_dmamap_t);

int	cia_bus_dmamap_load_sgmap(bus_dma_tag_t, bus_dmamap_t, void *,
	    bus_size_t, struct proc *, int);

int	cia_bus_dmamap_load_mbuf_sgmap(bus_dma_tag_t, bus_dmamap_t,
	    struct mbuf *, int);

int	cia_bus_dmamap_load_uio_sgmap(bus_dma_tag_t, bus_dmamap_t,
	    struct uio *, int);

int	cia_bus_dmamap_load_raw_sgmap(bus_dma_tag_t, bus_dmamap_t,
	    bus_dma_segment_t *, int, bus_size_t, int);

void	cia_bus_dmamap_unload_sgmap(bus_dma_tag_t, bus_dmamap_t);

/*
 * Direct-mapped window: 1G at 1G
 */
#define	CIA_DIRECT_MAPPED_BASE	(1*1024*1024*1024)
#define	CIA_DIRECT_MAPPED_SIZE	(1*1024*1024*1024)

/*
 * SGMAP window: 8M at 8M
 */
#define	CIA_SGMAP_MAPPED_BASE	(8*1024*1024)
#define	CIA_SGMAP_MAPPED_SIZE	(8*1024*1024)

void	cia_tlb_invalidate(void);
void	cia_broken_pyxis_tlb_invalidate(void);

void	(*cia_tlb_invalidate_fn)(void);

#define	CIA_TLB_INVALIDATE()	(*cia_tlb_invalidate_fn)()

struct alpha_sgmap cia_pyxis_bug_sgmap;
#define	CIA_PYXIS_BUG_BASE	(128*1024*1024)
#define	CIA_PYXIS_BUG_SIZE	(2*1024*1024)

void
cia_dma_init(ccp)
	struct cia_config *ccp;
{
	bus_addr_t tbase;
	bus_dma_tag_t t;

	/*
	 * Initialize the DMA tag used for direct-mapped DMA.
	 */
	t = &ccp->cc_dmat_direct;
	t->_cookie = ccp;
	t->_wbase = CIA_DIRECT_MAPPED_BASE;
	t->_wsize = CIA_DIRECT_MAPPED_SIZE;
	t->_next_window = &ccp->cc_dmat_sgmap;
	t->_boundary = 0;
	t->_sgmap = NULL;
	t->_get_tag = cia_dma_get_tag;
	t->_dmamap_create = cia_bus_dmamap_create_direct;
	t->_dmamap_destroy = cia_bus_dmamap_destroy_direct;
	t->_dmamap_load = _bus_dmamap_load_direct;
	t->_dmamap_load_mbuf = _bus_dmamap_load_mbuf_direct;
	t->_dmamap_load_uio = _bus_dmamap_load_uio_direct;
	t->_dmamap_load_raw = _bus_dmamap_load_raw_direct;
	t->_dmamap_unload = _bus_dmamap_unload;
	t->_dmamap_sync = _bus_dmamap_sync;

	t->_dmamem_alloc = _bus_dmamem_alloc;
	t->_dmamem_free = _bus_dmamem_free;
	t->_dmamem_map = _bus_dmamem_map;
	t->_dmamem_unmap = _bus_dmamem_unmap;
	t->_dmamem_mmap = _bus_dmamem_mmap;

	/*
	 * Initialize the DMA tag used for sgmap-mapped DMA.
	 */
	t = &ccp->cc_dmat_sgmap;
	t->_cookie = ccp;
	t->_wbase = CIA_SGMAP_MAPPED_BASE;
	t->_wsize = CIA_SGMAP_MAPPED_SIZE;
	t->_next_window = NULL;
	t->_boundary = 0;
	t->_sgmap = &ccp->cc_sgmap;
	t->_get_tag = cia_dma_get_tag;
	t->_dmamap_create = alpha_sgmap_dmamap_create;
	t->_dmamap_destroy = alpha_sgmap_dmamap_destroy;
	t->_dmamap_load = cia_bus_dmamap_load_sgmap;
	t->_dmamap_load_mbuf = cia_bus_dmamap_load_mbuf_sgmap;
	t->_dmamap_load_uio = cia_bus_dmamap_load_uio_sgmap;
	t->_dmamap_load_raw = cia_bus_dmamap_load_raw_sgmap;
	t->_dmamap_unload = cia_bus_dmamap_unload_sgmap;
	t->_dmamap_sync = _bus_dmamap_sync;

	t->_dmamem_alloc = _bus_dmamem_alloc;
	t->_dmamem_free = _bus_dmamem_free;
	t->_dmamem_map = _bus_dmamem_map;
	t->_dmamem_unmap = _bus_dmamem_unmap;
	t->_dmamem_mmap = _bus_dmamem_mmap;

	/*
	 * The firmware has set up window 1 as a 1G direct-mapped DMA
	 * window beginning at 1G.  We leave it alone.  Leave window
	 * 0 alone until we reconfigure it for SGMAP-mapped DMA.
	 * Windows 2 and 3 are already disabled.
	 */

	/*
	 * Initialize the SGMAP.  Must align page table to 32k
	 * (hardware bug?).
	 */
	alpha_sgmap_init(t, &ccp->cc_sgmap, "cia_sgmap",
	    CIA_SGMAP_MAPPED_BASE, 0, CIA_SGMAP_MAPPED_SIZE,
	    sizeof(u_int64_t), NULL, (32*1024));

	/*
	 * Set up window 0 as an 8MB SGMAP-mapped window
	 * starting at 8MB.
	 */
	REGVAL(CIA_PCI_W0BASE) = CIA_SGMAP_MAPPED_BASE |
	    CIA_PCI_WnBASE_SG_EN | CIA_PCI_WnBASE_W_EN;
	alpha_mb();

	REGVAL(CIA_PCI_W0MASK) = CIA_PCI_WnMASK_8M;
	alpha_mb();

	tbase = ccp->cc_sgmap.aps_ptpa >> CIA_PCI_TnBASE_SHIFT;
	if ((tbase & CIA_PCI_TnBASE_MASK) != tbase)
		panic("cia_dma_init: bad page table address");
	REGVAL(CIA_PCI_T0BASE) = tbase;
	alpha_mb();

	/*
	 * Pass 1 and 2 (i.e. revision <= 1) of the Pyxis have a
	 * broken scatter/gather TLB; it cannot be invalidated.  To
	 * work around this problem, we configure window 2 as an SG
	 * 2M window at 128M, which we use in DMA loopback mode to
	 * read a spill page.  This works by causing TLB misses,
	 * causing the old entries to be purged to make room for
	 * the new entries coming in for the spill page.
	 */
	if ((ccp->cc_flags & CCF_ISPYXIS) != 0 && ccp->cc_rev <= 1) {
		u_int64_t *page_table;
		int i;

		cia_tlb_invalidate_fn =
		    cia_broken_pyxis_tlb_invalidate;

		alpha_sgmap_init(t, &cia_pyxis_bug_sgmap,
		    "pyxis_bug_sgmap", CIA_PYXIS_BUG_BASE, 0,
		    CIA_PYXIS_BUG_SIZE, sizeof(u_int64_t), NULL,
		    (32*1024));

		REGVAL(CIA_PCI_W2BASE) = CIA_PYXIS_BUG_BASE |
		    CIA_PCI_WnBASE_SG_EN | CIA_PCI_WnBASE_W_EN;
		alpha_mb();

		REGVAL(CIA_PCI_W2MASK) = CIA_PCI_WnMASK_2M;
		alpha_mb();

		tbase = cia_pyxis_bug_sgmap.aps_ptpa >>
		    CIA_PCI_TnBASE_SHIFT;
		if ((tbase & CIA_PCI_TnBASE_MASK) != tbase)
			panic("cia_dma_init: bad page table address");
		REGVAL(CIA_PCI_T2BASE) = tbase;
		alpha_mb();

		/*
		 * Initialize the page table to point at the spill
		 * page.  Leave the last entry invalid.
		 */
		pci_sgmap_pte64_init_spill_page_pte();
		for (i = 0, page_table = cia_pyxis_bug_sgmap.aps_pt;
		     i < (CIA_PYXIS_BUG_SIZE / PAGE_SIZE) - 1; i++) {
			page_table[i] =
			    pci_sgmap_pte64_prefetch_spill_page_pte;
		}
		alpha_mb();
	} else
		cia_tlb_invalidate_fn = cia_tlb_invalidate;

	CIA_TLB_INVALIDATE();

	/* XXX XXX BEGIN XXX XXX */
	{							/* XXX */
		extern paddr_t alpha_XXX_dmamap_or;		/* XXX */
		alpha_XXX_dmamap_or = CIA_DIRECT_MAPPED_BASE;	/* XXX */
	}							/* XXX */
	/* XXX XXX END XXX XXX */
}

/*
 * Return the bus dma tag to be used for the specified bus type.
 * INTERNAL USE ONLY!
 */
bus_dma_tag_t
cia_dma_get_tag(t, bustype)
	bus_dma_tag_t t;
	alpha_bus_t bustype;
{
	struct cia_config *ccp = t->_cookie;

	switch (bustype) {
	case ALPHA_BUS_PCI:
	case ALPHA_BUS_EISA:
		/*
		 * Systems with a CIA can only support 1G
		 * of memory, so we use the direct-mapped window
		 * on busses that have 32-bit DMA.
		 *
		 * Ahem:  I have a PWS 500au with 1.5G of memory, and it
		 * had problems doing DMA because it was not falling back
		 * to using SGMAPs.  I've fixed that and my PWS now works with
		 * 1.5G.  There have been other reports about failures with
		 * more than 1.0G of memory.  Michael Hitch
		 */
		return (&ccp->cc_dmat_direct);

	case ALPHA_BUS_ISA:
		/*
		 * ISA doesn't have enough address bits to use
		 * the direct-mapped DMA window, so we must use
		 * SGMAPs.
		 */
		return (&ccp->cc_dmat_sgmap);

	default:
		panic("cia_dma_get_tag: shouldn't be here, really...");
	}
}

/*
 * Create a CIA direct-mapped DMA map.
 */
int
cia_bus_dmamap_create_direct(t, size, nsegments, maxsegsz, boundary,
    flags, dmamp)
	bus_dma_tag_t t;
	bus_size_t size;
	int nsegments;
	bus_size_t maxsegsz;
	bus_size_t boundary;
	int flags;
	bus_dmamap_t *dmamp;
{
	struct cia_config *ccp = t->_cookie;
	bus_dmamap_t map;
	int error;

	error = _bus_dmamap_create(t, size, nsegments, maxsegsz,
	    boundary, flags, dmamp);
	if (error)
		return (error);

	/*
	 * Since we fall back to sgmap if the direct mapping fails,
	 * we need to set up for sgmap in any case.
	 */
	map = *dmamp;
	if (alpha_sgmap_dmamap_setup(map, nsegments, flags)) {
		_bus_dmamap_destroy(t, map);
		return (ENOMEM);
	}

	if ((ccp->cc_flags & CCF_PYXISBUG) != 0 &&
	    map->_dm_segcnt > 1) {
		/*
		 * We have a Pyxis with the DMA page crossing bug, make
		 * sure we don't coalesce adjacent DMA segments.
		 *
		 * NOTE: We can only do this if the max segment count
		 * is greater than 1.  This is because many network
		 * drivers allocate large contiguous blocks of memory
		 * for control data structures, even though they won't
		 * do any single DMA that crosses a page boundary.
		 *	-- thorpej@netbsd.org, 2/5/2000
		 */
		map->_dm_flags |= DMAMAP_NO_COALESCE;
	}

	return (0);
}

/*
 * Destroy a CIA direct-mapped DMA map.
 */
void
cia_bus_dmamap_destroy_direct(t, map)
	bus_dma_tag_t t;
	bus_dmamap_t map;
{
	alpha_sgmap_dmamap_teardown(map);
	_bus_dmamap_destroy(t, map);
}

/*
 * Load a CIA SGMAP-mapped DMA map with a linear buffer.
 */
int
cia_bus_dmamap_load_sgmap(t, map, buf, buflen, p, flags)
	bus_dma_tag_t t;
	bus_dmamap_t map;
	void *buf;
	bus_size_t buflen;
	struct proc *p;
	int flags;
{
	int error;

	error = pci_sgmap_pte64_load(t, map, buf, buflen, p, flags,
	    t->_sgmap);
	if (error == 0)
		CIA_TLB_INVALIDATE();

	return (error);
}

/*
 * Load a CIA SGMAP-mapped DMA map with an mbuf chain.
 */
int
cia_bus_dmamap_load_mbuf_sgmap(t, map, m, flags)
	bus_dma_tag_t t;
	bus_dmamap_t map;
	struct mbuf *m;
	int flags;
{
	int error;

	error = pci_sgmap_pte64_load_mbuf(t, map, m, flags, t->_sgmap);
	if (error == 0)
		CIA_TLB_INVALIDATE();

	return (error);
}

/*
 * Load a CIA SGMAP-mapped DMA map with a uio.
 */
int
cia_bus_dmamap_load_uio_sgmap(t, map, uio, flags)
	bus_dma_tag_t t;
	bus_dmamap_t map;
	struct uio *uio;
	int flags;
{
	int error;

	error = pci_sgmap_pte64_load_uio(t, map, uio, flags, t->_sgmap);
	if (error == 0)
		CIA_TLB_INVALIDATE();

	return (error);
}

/*
 * Load a CIA SGMAP-mapped DMA map with raw memory.
 */
int
cia_bus_dmamap_load_raw_sgmap(t, map, segs, nsegs, size, flags)
	bus_dma_tag_t t;
	bus_dmamap_t map;
	bus_dma_segment_t *segs;
	int nsegs;
	bus_size_t size;
	int flags;
{
	int error;

	error = pci_sgmap_pte64_load_raw(t, map, segs, nsegs, size, flags,
	    t->_sgmap);
	if (error == 0)
		CIA_TLB_INVALIDATE();

	return (error);
}

/*
 * Unload a CIA DMA map.
 */
void
cia_bus_dmamap_unload_sgmap(t, map)
	bus_dma_tag_t t;
	bus_dmamap_t map;
{

	/*
	 * Invalidate any SGMAP page table entries used by this
	 * mapping.
	 */
	pci_sgmap_pte64_unload(t, map, t->_sgmap);
	CIA_TLB_INVALIDATE();

	/*
	 * Do the generic bits of the unload.
	 */
	_bus_dmamap_unload(t, map);
}

/*
 * Flush the CIA scatter/gather TLB.
 */
void
cia_tlb_invalidate()
{

	alpha_mb();
	REGVAL(CIA_PCI_TBIA) = CIA_PCI_TBIA_ALL;
	alpha_mb();
}

/*
 * Flush the scatter/gather TLB on broken Pyxis chips.
 */
void
cia_broken_pyxis_tlb_invalidate()
{
	volatile u_int64_t dummy;
	u_int32_t ctrl;
	int i, s;

	s = splhigh();

	/*
	 * Put the Pyxis into PCI loopback mode.
	 */
	alpha_mb();
	ctrl = REGVAL(CIA_CSR_CTRL);
	REGVAL(CIA_CSR_CTRL) = ctrl | CTRL_PCI_LOOP_EN;
	alpha_mb();

	/*
	 * Now, read from PCI dense memory space at offset 128M (our
	 * target window base), skipping 64k on each read.  This forces
	 * S/G TLB misses.
	 *
	 * XXX Looks like the TLB entries are `not quite LRU'.  We need
	 * XXX to read more times than there are actual tags!
	 */
	for (i = 0; i < CIA_TLB_NTAGS + 4; i++) {
		dummy = *((volatile u_int64_t *)
		    ALPHA_PHYS_TO_K0SEG(CIA_PCI_DENSE + CIA_PYXIS_BUG_BASE +
		    (i * 65536)));
	}

	/*
	 * Restore normal PCI operation.
	 */
	alpha_mb();
	REGVAL(CIA_CSR_CTRL) = ctrl;
	alpha_mb();

	splx(s);
}


code:
/* $OpenBSD: cia_pci.c,v 1.12 2010/12/04 17:06:31 miod Exp $ */
/* $NetBSD: cia_pci.c,v 1.25 2000/06/29 08:58:46 mrg 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/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/device.h>

#include <uvm/uvm_extern.h>

#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <alpha/pci/ciareg.h>
#include <alpha/pci/ciavar.h>

void		cia_attach_hook(struct device *, struct device *,
		    struct pcibus_attach_args *);
int		cia_bus_maxdevs(void *, int);
pcitag_t	cia_make_tag(void *, int, int, int);
void		cia_decompose_tag(void *, pcitag_t, int *, int *,
		    int *);
int		cia_conf_size(void *, pcitag_t);
pcireg_t	cia_conf_read(void *, pcitag_t, int);
void		cia_conf_write(void *, pcitag_t, int, pcireg_t);

void
cia_pci_init(pc, v)
	pci_chipset_tag_t pc;
	void *v;
{

	pc->pc_conf_v = v;
	pc->pc_attach_hook = cia_attach_hook;
	pc->pc_bus_maxdevs = cia_bus_maxdevs;
	pc->pc_make_tag = cia_make_tag;
	pc->pc_decompose_tag = cia_decompose_tag;
	pc->pc_conf_size = cia_conf_size;
	pc->pc_conf_read = cia_conf_read;
	pc->pc_conf_write = cia_conf_write;
}

void
cia_attach_hook(parent, self, pba)
	struct device *parent, *self;
	struct pcibus_attach_args *pba;
{
}

int
cia_bus_maxdevs(cpv, busno)
	void *cpv;
	int busno;
{

	return 32;
}

pcitag_t
cia_make_tag(cpv, b, d, f)
	void *cpv;
	int b, d, f;
{

	return (b << 16) | (d << 11) | (f << 8);
}

void
cia_decompose_tag(cpv, tag, bp, dp, fp)
	void *cpv;
	pcitag_t tag;
	int *bp, *dp, *fp;
{

	if (bp != NULL)
		*bp = (tag >> 16) & 0xff;
	if (dp != NULL)
		*dp = (tag >> 11) & 0x1f;
	if (fp != NULL)
		*fp = (tag >> 8) & 0x7;
}

int
cia_conf_size(void *cpv, pcitag_t tag)
{
	return PCI_CONFIG_SPACE_SIZE;
}

pcireg_t
cia_conf_read(cpv, tag, offset)
	void *cpv;
	pcitag_t tag;
	int offset;
{
	struct cia_config *ccp = cpv;
	pcireg_t *datap, data;
	int s, secondary, ba;
	u_int32_t old_cfg, errbits;

#ifdef __GNUC__
	s = 0;					/* XXX gcc -Wuninitialized */
	old_cfg = 0;				/* XXX gcc -Wuninitialized */
#endif

	/*
	 * Some (apparently common) revisions of EB164 and AlphaStation
	 * firmware do the Wrong thing with PCI master and target aborts,
	 * which are caused by accessing the configuration space of devices
	 * that don't exist (for example).
	 *
	 * To work around this, we clear the CIA error register's PCI
	 * master and target abort bits before touching PCI configuration
	 * space and check it afterwards.  If it indicates a master or target
	 * abort, the device wasn't there so we return 0xffffffff.
	 */
	REGVAL(CIA_CSR_CIA_ERR) = CIA_ERR_RCVD_MAS_ABT|CIA_ERR_RCVD_TAR_ABT;
	alpha_mb();
	alpha_pal_draina();

	/* secondary if bus # != 0 */
	pci_decompose_tag(&ccp->cc_pc, tag, &secondary, 0, 0);
	if (secondary) {
		s = splhigh();
		old_cfg = REGVAL(CIA_CSR_CFG);
		alpha_mb();
		REGVAL(CIA_CSR_CFG) = old_cfg | 0x1;
		alpha_mb();
	}

	/*
	 * We just inline the BWX support, since this is the only
	 * difference between BWX and swiz for config space.
	 */
	if (ccp->cc_flags & CCF_PCI_USE_BWX) {
		if (secondary) {
			datap =
			    (pcireg_t *)ALPHA_PHYS_TO_K0SEG(CIA_EV56_BWCONF1 |
				tag | (offset & ~0x03));
		} else {
			datap =
			    (pcireg_t *)ALPHA_PHYS_TO_K0SEG(CIA_EV56_BWCONF0 |
				tag | (offset & ~0x03));
		}
	} else {
		datap = (pcireg_t *)ALPHA_PHYS_TO_K0SEG(CIA_PCI_CONF |
		    tag << 5UL |				/* XXX */
		    (offset & ~0x03) << 5 |			/* XXX */
		    0 << 5 |					/* XXX */
		    0x3 << 3);					/* XXX */
	}
	data = (pcireg_t)-1;
	alpha_mb();
	if (!(ba = badaddr(datap, sizeof *datap)))
		data = *datap;
	alpha_mb();
	alpha_mb();

	if (secondary) {
		alpha_mb();
		REGVAL(CIA_CSR_CFG) = old_cfg;
		alpha_mb();
		splx(s);
	}

	alpha_pal_draina();
	alpha_mb();
	errbits = REGVAL(CIA_CSR_CIA_ERR);
	if (errbits & (CIA_ERR_RCVD_MAS_ABT|CIA_ERR_RCVD_TAR_ABT)) {
		ba = 1;
		data = 0xffffffff;
	}

	if (errbits) {
		REGVAL(CIA_CSR_CIA_ERR) = errbits;
		alpha_mb();
		alpha_pal_draina();
	}

#if 0
	printf("cia_conf_read: tag 0x%lx, reg 0x%lx -> %x @ %p%s\n", tag, reg,
	    data, datap, ba ? " (badaddr)" : "");
#endif

	return data;
}

void
cia_conf_write(cpv, tag, offset, data)
	void *cpv;
	pcitag_t tag;
	int offset;
	pcireg_t data;
{
	struct cia_config *ccp = cpv;
	pcireg_t *datap;
	int s, secondary;
	u_int32_t old_cfg;

#ifdef __GNUC__
	s = 0;					/* XXX gcc -Wuninitialized */
	old_cfg = 0;				/* XXX gcc -Wuninitialized */
#endif

	/* secondary if bus # != 0 */
	pci_decompose_tag(&ccp->cc_pc, tag, &secondary, 0, 0);
	if (secondary) {
		s = splhigh();
		old_cfg = REGVAL(CIA_CSR_CFG);
		alpha_mb();
		REGVAL(CIA_CSR_CFG) = old_cfg | 0x1;
		alpha_mb();
	}

	/*
	 * We just inline the BWX support, since this is the only
	 * difference between BWX and swiz for config space.
	 */
	if (ccp->cc_flags & CCF_PCI_USE_BWX) {
		if (secondary) {
			datap =
			    (pcireg_t *)ALPHA_PHYS_TO_K0SEG(CIA_EV56_BWCONF1 |
				tag | (offset & ~0x03));
		} else {
			datap =
			    (pcireg_t *)ALPHA_PHYS_TO_K0SEG(CIA_EV56_BWCONF0 |
				tag | (offset & ~0x03));
		}
	} else {
		datap = (pcireg_t *)ALPHA_PHYS_TO_K0SEG(CIA_PCI_CONF |
		    tag << 5UL |				/* XXX */
		    (offset & ~0x03) << 5 |			/* XXX */
		    0 << 5 |					/* XXX */
		    0x3 << 3);					/* XXX */
	}
	alpha_mb();
	*datap = data;
	alpha_mb();
	alpha_mb();

	if (secondary) {
		alpha_mb();
		REGVAL(CIA_CSR_CFG) = old_cfg;
		alpha_mb();
		splx(s);
	}

#if 0
	printf("cia_conf_write: tag 0x%lx, reg 0x%lx -> 0x%x @ %p\n", tag,
	    reg, data, datap);
#endif
}


code:
/* $OpenBSD: ciareg.h,v 1.9 2000/11/08 20:59:25 ericj Exp $ */
/* $NetBSD: ciareg.h,v 1.22 1998/06/06 20:40:14 thorpej Exp $ */

/*
 * Copyright (c) 1995, 1996 Carnegie-Mellon University.
 * All rights reserved.
 *
 * Authors: Chris G. Demetriou, Jason R. Thorpe
 *
 * 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.
 */

/*
 * 21171 Chipset registers and constants.
 *
 * Taken from EC-QE18B-TE.
 */

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

/*
 * Base addresses
 */
#define	CIA_PCI_SMEM1	0x8000000000UL
#define	CIA_PCI_SMEM2	0x8400000000UL
#define	CIA_PCI_SMEM3	0x8500000000UL
#define	CIA_PCI_SIO1	0x8580000000UL
#define	CIA_PCI_SIO2	0x85c0000000UL
#define	CIA_PCI_DENSE	0x8600000000UL
#define	CIA_PCI_CONF	0x8700000000UL
#define	CIA_PCI_IACK	0x8720000000UL
#define	CIA_CSRS	0x8740000000UL
#define	CIA_PCI_MC_CSRS	0x8750000000UL
#define	CIA_PCI_ATRANS	0x8760000000UL
#define	CIA_PCI_TBIA	0x8760000100UL
#define	CIA_EV56_BWMEM	0x8800000000UL
#define	CIA_EV56_BWIO	0x8900000000UL
#define	CIA_EV56_BWCONF0 0x8a00000000UL
#define	CIA_EV56_BWCONF1 0x8b00000000UL

#define	CIA_PCI_W0BASE	0x8760000400UL
#define	CIA_PCI_W0MASK	0x8760000440UL
#define	CIA_PCI_T0BASE	0x8760000480UL

#define	CIA_PCI_W1BASE	0x8760000500UL
#define	CIA_PCI_W1MASK	0x8760000540UL
#define	CIA_PCI_T1BASE	0x8760000580UL

#define	CIA_PCI_W2BASE	0x8760000600UL
#define	CIA_PCI_W2MASK	0x8760000640UL
#define	CIA_PCI_T2BASE	0x8760000680UL

#define	CIA_PCI_W3BASE	0x8760000700UL
#define	CIA_PCI_W3MASK	0x8760000740UL
#define	CIA_PCI_T3BASE	0x8760000780UL

#define	PYXIS_INT_REQ	0x87a0000000UL
#define	PYXIS_INT_MASK	0x87a0000040UL
#define	PYXIS_GPO	0x87a0000180UL

/*
 * Values for CIA_PCI_TBIA
 */
#define	CIA_PCI_TBIA_NOOP	0	/* no operation */
#define	CIA_PCI_TBIA_LOCKED	1	/* invalidate and unlock locked tags */
#define	CIA_PCI_TBIA_UNLOCKED	2	/* invalidate unlocked tags */
#define	CIA_PCI_TBIA_ALL	3	/* invalidate and unlock all tags */

#define	CIA_TLB_NTAGS		8	/* number of TLB entries */

/*
 * Values for CIA_PCI_WnBASE
 */
#define	CIA_PCI_WnBASE_W_BASE	0xfff00000
#define	CIA_PCI_WnBASE_DAC_EN	0x00000008	/* W3BASE only */
#define	CIA_PCI_WnBASE_MEMCS_EN	0x00000004	/* W0BASE only */
#define	CIA_PCI_WnBASE_SG_EN	0x00000002
#define	CIA_PCI_WnBASE_W_EN	0x00000001

/*
 * Values for CIA_PCI_WnMASK
 */
#define	CIA_PCI_WnMASK_W_MASK	0xfff00000
#define	CIA_PCI_WnMASK_1M	0x00000000
#define	CIA_PCI_WnMASK_2M	0x00100000
#define	CIA_PCI_WnMASK_4M	0x00300000
#define	CIA_PCI_WnMASK_8M	0x00700000
#define	CIA_PCI_WnMASK_16M	0x00f00000
#define	CIA_PCI_WnMASK_32M	0x01f00000
#define	CIA_PCI_WnMASK_64M	0x03f00000
#define	CIA_PCI_WnMASK_128M	0x07f00000
#define	CIA_PCI_WnMASK_256M	0x0ff00000
#define	CIA_PCI_WnMASK_512M	0x1ff00000
#define	CIA_PCI_WnMASK_1G	0x3ff00000
#define	CIA_PCI_WnMASK_2G	0x7ff00000
#define	CIA_PCI_WnMASK_4G	0xfff00000

/*
 * Values for CIA_PCI_TnBASE
 */
#define	CIA_PCI_TnBASE_MASK	0xfffffff0
#define	CIA_PCI_TnBASE_SHIFT	2

/*
 * General CSRs
 */

#define	CIA_CSR_REV	(CIA_CSRS + 0x80)

#define		REV_MASK		0x000000ff
#define		REV_ALT_MEM		0x00000100	/* not on Pyxis */

#define		REV_PYXIS_ID_MASK	0x0000ff00
#define		REV_PYXIS_ID_21174	0x00000100

#define	CIA_CSR_CTRL	(CIA_CSRS + 0x100)

#define		CTRL_RCI_EN		0x00000001
#define		CTRL_PCI_LOCK_EN	0x00000002
#define		CTRL_PCI_LOOP_EN	0x00000004
#define		CTRL_FST_BB_EN		0x00000008
#define		CTRL_PCI_MST_EN		0x00000010
#define		CTRL_PCI_MEM_EN		0x00000020
#define		CTRL_PCI_REQ64_EN	0x00000040
#define		CTRL_PCI_ACK64_EN	0x00000080
#define		CTRL_ADDR_PE_EN		0x00000100
#define		CTRL_PERR_EN		0x00000200
#define		CTRL_FILL_ERR_EN	0x00000400
#define		CTRL_ECC_CHK_EN		0x00001000
#define		CTRL_CACK_EN_PE		0x00002000
#define		CTRL_CON_IDLE_BC	0x00004000
#define		CTRL_CSR_IOA_BYPASS	0x00008000
#define		CTRL_IO_FLUSHREQ_EN	0x00010000
#define		CTRL_CPU_CLUSHREQ_EN	0x00020000
#define		CTRL_ARB_EV5_EN		0x00040000
#define		CTRL_EN_ARB_LINK	0x00080000
#define		CTRL_RD_TYPE		0x00300000
#define		CTRL_RL_TYPE		0x03000000
#define		CTRL_RM_TYPE		0x30000000

/* a.k.a. CIA_CSR_PYXIS_CTRL1 */
#define	CIA_CSR_CNFG	(CIA_CSRS + 0x140)

#define		CNFG_BWEN		0x00000001
#define		CNFG_MWEN		0x00000010
#define		CNFG_DWEN		0x00000020
#define		CNFG_WLEN		0x00000100

#define	CIA_CSR_CNFG_BITS	"\20\11WLEN\6DWEN\5MWEN\1BWEN"

#define	CIA_CSR_HAE_MEM	(CIA_CSRS + 0x400)

#define		HAE_MEM_REG1_START(x)	(((u_int32_t)(x) & 0xe0000000UL) << 0)
#define		HAE_MEM_REG1_MASK	0x1fffffffUL
#define		HAE_MEM_REG2_START(x)	(((u_int32_t)(x) & 0x0000f800UL) << 16)
#define		HAE_MEM_REG2_MASK	0x07ffffffUL
#define		HAE_MEM_REG3_START(x)	(((u_int32_t)(x) & 0x000000fcUL) << 24)
#define		HAE_MEM_REG3_MASK	0x03ffffffUL

#define	CIA_CSR_HAE_IO	(CIA_CSRS + 0x440)

#define		HAE_IO_REG1_START(x)	0UL
#define		HAE_IO_REG1_MASK	0x01ffffffUL
#define		HAE_IO_REG2_START(x)	(((u_int32_t)(x) & 0xfe000000UL) << 0)
#define		HAE_IO_REG2_MASK	0x01ffffffUL

#define	CIA_CSR_CFG	(CIA_CSRS + 0x480)

#define		CFG_CFG_MASK		0x00000003UL

#define	CIA_CSR_CIA_ERR	(CIA_CSRS + 0x8200)

#define		CIA_ERR_COR_ERR		  0x00000001
#define		CIA_ERR_UN_COR_ERR	  0x00000002
#define		CIA_ERR_CPU_PE		  0x00000004
#define		CIA_ERR_MEM_NEM		  0x00000008
#define		CIA_ERR_PCI_SERR	  0x00000010
#define		CIA_ERR_PERR		  0x00000020
#define		CIA_ERR_PCI_ADDR_PE	  0x00000040
#define		CIA_ERR_RCVD_MAS_ABT	  0x00000080
#define		CIA_ERR_RCVD_TAR_ABT	  0x00000100
#define		CIA_ERR_PA_PTE_INV	  0x00000200
#define		CIA_ERR_FROM_WRT_ERR	  0x00000400
#define		CIA_ERR_IOA_TIMEOUT	  0x00000800
#define		CIA_ERR_LOST_COR_ERR	  0x00010000
#define		CIA_ERR_LOST_UN_COR_ERR	  0x00020000
#define		CIA_ERR_LOST_CPU_PE	  0x00040000
#define		CIA_ERR_LOST_MEM_NEM	  0x00080000
#define		CIA_ERR_LOST_PERR	  0x00200000
#define		CIA_ERR_LOST_PCI_ADDR_PE  0x00400000
#define		CIA_ERR_LOST_RCVD_MAS_ABT 0x00800000
#define		CIA_ERR_LOST_RCVD_TAR_ABT 0x01000000
#define		CIA_ERR_LOST_PA_PTE_INV	  0x02000000
#define		CIA_ERR_LOST_FROM_WRT_ERR 0x04000000
#define		CIA_ERR_LOST_IOA_TIMEOUT  0x08000000
#define		CIA_ERR_VALID		  0x80000000


code:
/* $OpenBSD: ciavar.h,v 1.13 2006/03/16 22:32:44 miod Exp $ */
/* $NetBSD: ciavar.h,v 1.17 2000/03/19 01:43:25 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.
 */

#include <dev/isa/isavar.h>
#include <dev/pci/pcivar.h>
#include <alpha/pci/pci_sgmap_pte64.h>

/*
 * A 21171 chipset's configuration.
 *
 * All of the information that the chipset-specific functions need to
 * do their dirty work (and more!).
 */
struct cia_config {
	int	cc_initted;

	struct alpha_bus_space cc_iot, cc_memt;
	struct alpha_pci_chipset cc_pc;

	struct alpha_bus_dma_tag cc_dmat_direct;
	struct alpha_bus_dma_tag cc_dmat_sgmap;

	struct alpha_sgmap cc_sgmap;

	u_int32_t cc_hae_mem;
	u_int32_t cc_hae_io;

	u_int32_t cc_rev;
	u_int32_t cc_cnfg;

	int	cc_flags;

#define	CCF_ISPYXIS	0x01		/* chip is a 21174 Pyxis */
#define	CCF_PYXISBUG	0x02
#define	CCF_PCI_USE_BWX	0x04		/* use BWX for PCI config space */
#define	CCF_BUS_USE_BWX	0x08		/* use BWX for bus space */

	struct extent *cc_io_ex, *cc_d_mem_ex, *cc_s_mem_ex;
	int	cc_mallocsafe;
};

void	cia_init(struct cia_config *, int);
void	cia_pci_init(pci_chipset_tag_t, void *);
void	cia_dma_init(struct cia_config *);

void	cia_bwx_bus_io_init(bus_space_tag_t, void *);
void	cia_bwx_bus_mem_init(bus_space_tag_t, void *);

void	cia_bus_io_init(bus_space_tag_t, void *);
void	cia_bus_mem_init(bus_space_tag_t, void *);

void	cia_pyxis_intr_enable(int, int);


code:
/*	$OpenBSD: irongate.c,v 1.11 2009/03/30 21:43:13 kettenis Exp $	*/
/* $NetBSD: irongate.c,v 1.3 2000/11/29 06:29:10 thorpej Exp $ */

/*-
 * Copyright (c) 2000 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Jason R. Thorpe.
 *
 * 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/device.h>
#include <sys/malloc.h>

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

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

#include <alpha/pci/irongatereg.h>
#include <alpha/pci/irongatevar.h>

#ifdef API_UP1000
#include <alpha/pci/pci_up1000.h>
#endif

int	irongate_match(struct device *, void *, void *);
void	irongate_attach(struct device *, struct device *, void *);

struct cfattach irongate_ca = {
	sizeof(struct device), irongate_match, irongate_attach,
};

int	irongate_print(void *, const char *pnp);

struct cfdriver irongate_cd = {
	NULL, "irongate", DV_DULL,
};

/* There can be only one. */
struct irongate_config irongate_configuration;
int	irongate_found;

#if 0
int	irongate_bus_get_window(int, int,
	    struct alpha_bus_space_translation *);
#endif

/*
 * Set up the chipset's function pointers.
 */
void
irongate_init(struct irongate_config *icp, int mallocsafe)
{
	pcitag_t tag;
	pcireg_t reg;

	icp->ic_mallocsafe = mallocsafe;

	/*
	 * Set up PCI configuration space; we can only read the
	 * revision info through configuration space.
	 */
	irongate_pci_init(&icp->ic_pc, icp);
	alpha_pci_chipset = &icp->ic_pc;
	alpha_pci_chipset->pc_name = "irongate";
	alpha_pci_chipset->pc_mem = IRONGATE_MEM_BASE;
	alpha_pci_chipset->pc_mem = IRONGATE_MEM_BASE;
	alpha_pci_chipset->pc_bwx = 1;

	tag = pci_make_tag(&icp->ic_pc, 0, IRONGATE_PCIHOST_DEV, 0);

	/* Read the revision. */
	reg = irongate_conf_read0(icp, tag, PCI_CLASS_REG);
	icp->ic_rev = PCI_REVISION(reg);

	if (icp->ic_initted == 0) {
		/* Don't do these twice, since they set up extents. */
		irongate_bus_io_init(&icp->ic_iot, icp);
		irongate_bus_mem_init(&icp->ic_memt, icp);

#if 0
		/* Only one each PCI I/O and MEM window. */
		alpha_bus_window_count[ALPHA_BUS_TYPE_PCI_IO] = 1;
		alpha_bus_window_count[ALPHA_BUS_TYPE_PCI_MEM] = 1;

		alpha_bus_get_window = irongate_bus_get_window;
#endif
	}

	icp->ic_initted = 1;
}

int
irongate_match(struct device *parent, void *match, void *aux)
{
	struct mainbus_attach_args *ma = aux;

	/* Make sure we're looking for an Irongate. */
	if (strcmp(ma->ma_name, irongate_cd.cd_name) != 0)
		return (0);

	if (irongate_found)
		return (0);

	return (1);
}

void
irongate_attach(struct device *parent, struct device *self, void *aux)
{
	struct irongate_config *icp;
	struct pcibus_attach_args pba;

	/* Note that we've attached the chipset; can't have 2 Irongates. */
	irongate_found = 1;

	/*
	 * Set up the chipset's info; done once at console init time
	 * (maybe), but we must do it here as well to take care of things
	 * that need to use memory allocation.
	 */
	icp = &irongate_configuration;
	irongate_init(icp, 1);

	printf(": rev. %d\n", icp->ic_rev);

	irongate_dma_init(icp);

	/*
	 * Do PCI memory initialization that needs to be deferred until
	 * malloc is safe.
	 */
	irongate_bus_mem_init2(&icp->ic_memt, icp);

	switch (cputype) {
#ifdef API_UP1000
	case ST_API_NAUTILUS:
		pci_up1000_pickintr(icp);
		break;
#endif

	default:
		panic("irongate_attach: shouldn't be here, really...");
	}

	bzero(&pba, sizeof(pba));
	pba.pba_busname = "pci";
	pba.pba_iot = &icp->ic_iot;
	pba.pba_memt = &icp->ic_memt;
	pba.pba_dmat =
	    alphabus_dma_get_tag(&icp->ic_dmat_pci, ALPHA_BUS_PCI);
	pba.pba_pc = &icp->ic_pc;
	pba.pba_domain = pci_ndomains++;
	pba.pba_bus = 0;
#ifdef notyet
	pba.pba_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED |
	    PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | PCI_FLAGS_MWI_OKAY;
#endif
	config_found(self, &pba, irongate_print);
}

int
irongate_print(void *aux, const char *pnp)
{
	struct pcibus_attach_args *pba = aux;

	/* Only PCIs can attach to Irongates; easy. */
	if (pnp != NULL)
		printf("%s at %s", pba->pba_busname, pnp);
	printf(" bus %d", pba->pba_bus);
	return (UNCONF);
}

#if 0
int
irongate_bus_get_window(int type, int window,
    struct alpha_bus_space_translation *abst)
{
	struct irongate_config *icp = &irongate_configuration;
	bus_space_tag_t st;
	int error;

	switch (type) {
	case ALPHA_BUS_TYPE_PCI_IO:
		st = &icp->ic_iot;
		break;

	case ALPHA_BUS_TYPE_PCI_MEM:
		st = &icp->ic_memt;
		break;

	default:
		panic("irongate_bus_get_window");
	}

	error = alpha_bus_space_get_window(st, window, abst);
	if (error)
		return (error);

	abst->abst_sys_start = IRONGATE_PHYSADDR(abst->abst_sys_start);
	abst->abst_sys_end = IRONGATE_PHYSADDR(abst->abst_sys_end);

	return (0);
}
#endif


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

/*-
 * Copyright (c) 2000 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Jason R. Thorpe.
 *
 * 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/malloc.h>
#include <sys/syslog.h>
#include <sys/device.h>

#include <uvm/uvm_extern.h>

#include <machine/bus.h>

#include <alpha/pci/irongatereg.h>
#include <alpha/pci/irongatevar.h>

#define	CHIP		irongate

#define	CHIP_EX_MALLOC_SAFE(v)	(((struct irongate_config *)(v))->ic_mallocsafe)
#define	CHIP_IO_EXTENT(v)	(((struct irongate_config *)(v))->ic_io_ex)

#define	CHIP_IO_SYS_START(v)	IRONGATE_IO_BASE

/*
 * AMD 751 core logic appears on EV6.  We require at least EV56
 * support for the assembler to emit BWX opcodes.
 */
__asm(".arch ev6");

#include <alpha/pci/pci_bwx_bus_io_chipdep.c>