psycho.c revision 93046
12061Sjkh/*
232427Sjb * Copyright (c) 1999, 2000 Matthew R. Green
32061Sjkh * All rights reserved.
432427Sjb * Copyright 2001 by Thomas Moestl <tmm@FreeBSD.org>.  All rights reserved.
532427Sjb *
632427Sjb * Redistribution and use in source and binary forms, with or without
732427Sjb * modification, are permitted provided that the following conditions
832427Sjb * are met:
932427Sjb * 1. Redistributions of source code must retain the above copyright
1032427Sjb *    notice, this list of conditions and the following disclaimer.
112061Sjkh * 2. Redistributions in binary form must reproduce the above copyright
1215603Smarkm *    notice, this list of conditions and the following disclaimer in the
1330169Sjkh *    documentation and/or other materials provided with the distribution.
1420710Sasami * 3. The name of the author may not be used to endorse or promote products
1520710Sasami *    derived from this software without specific prior written permission.
163197Scsgr *
172061Sjkh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1812483Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
192160Scsgr * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
202834Swollman * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
212061Sjkh * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
222061Sjkh * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
232160Scsgr * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2417308Speter * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2519320Sadam * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2627788Sasami * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2730169Sjkh * SUCH DAMAGE.
2825980Sasami *
291594Srgrimes *	from: NetBSD: psycho.c,v 1.39 2001/10/07 20:30:41 eeh Exp
3017308Speter *
3117308Speter * $FreeBSD: head/sys/sparc64/pci/psycho.c 93046 2002-03-23 20:04:10Z tmm $
3227910Sasami */
3327910Sasami
3427910Sasami/*
3517308Speter * Support for `psycho' and `psycho+' UPA to PCI bridge and
3617308Speter * UltraSPARC IIi and IIe `sabre' PCI controllers.
3717308Speter */
3819175Sbde
3919175Sbde#include "opt_psycho.h"
4019175Sbde
4119175Sbde#include <sys/param.h>
4217308Speter#include <sys/systm.h>
4327910Sasami#include <sys/bus.h>
4425647Sbde#include <sys/kernel.h>
4527910Sasami#include <sys/malloc.h>
4617308Speter
472061Sjkh#include <ofw/openfirm.h>
482061Sjkh#include <ofw/ofw_pci.h>
491594Srgrimes
5030169Sjkh#include <machine/bus.h>
5130169Sjkh#include <machine/iommureg.h>
5230169Sjkh#include <machine/bus_common.h>
5330169Sjkh#include <machine/frame.h>
5430169Sjkh#include <machine/intr_machdep.h>
5530169Sjkh#include <machine/nexusvar.h>
5630169Sjkh#include <machine/ofw_upa.h>
5730169Sjkh#include <machine/resource.h>
587407Srgrimes
597108Sphk#include <sys/rman.h>
607108Sphk
617108Sphk#include <machine/iommuvar.h>
627407Srgrimes
637407Srgrimes#include <pci/pcivar.h>
647407Srgrimes#include <pci/pcireg.h>
657108Sphk
662061Sjkh#include <sparc64/pci/ofw_pci.h>
672061Sjkh#include <sparc64/pci/psychoreg.h>
682061Sjkh#include <sparc64/pci/psychovar.h>
6917308Speter
702061Sjkh#include "pcib_if.h"
712061Sjkh#include "sparcbus_if.h"
722061Sjkh
732061Sjkhstatic void psycho_get_ranges(phandle_t, struct upa_ranges **, int *);
742061Sjkhstatic void psycho_set_intr(struct psycho_softc *, int, device_t, bus_addr_t,
7530169Sjkh    int, driver_intr_t);
7630169Sjkhstatic int psycho_find_intrmap(struct psycho_softc *, int, bus_addr_t *,
772626Scsgr    bus_addr_t *, u_long *);
782061Sjkhstatic void psycho_intr_stub(void *);
792061Sjkh#ifdef PSYCHO_STRAY
802061Sjkhstatic void psycho_intr_stray(void *);
812061Sjkh#endif
822061Sjkhstatic bus_space_tag_t psycho_alloc_bus_tag(struct psycho_softc *, int);
832061Sjkh
8419320Sadam
852061Sjkh/* Interrupt handlers */
862061Sjkhstatic void psycho_ue(void *);
872061Sjkhstatic void psycho_ce(void *);
882061Sjkhstatic void psycho_bus_a(void *);
892061Sjkhstatic void psycho_bus_b(void *);
902061Sjkhstatic void psycho_powerfail(void *);
912061Sjkh#ifdef PSYCHO_MAP_WAKEUP
922061Sjkhstatic void psycho_wakeup(void *);
932061Sjkh#endif
942061Sjkh
952061Sjkh/* IOMMU support */
962834Swollmanstatic void psycho_iommu_init(struct psycho_softc *, int);
972834Swollman
982834Swollman/*
992834Swollman * bus space and bus dma support for UltraSPARC `psycho'.  note that most
1002834Swollman * of the bus dma support is provided by the iommu dvma controller.
1012834Swollman */
1021594Srgrimesstatic int psycho_dmamap_create(bus_dma_tag_t, int, bus_dmamap_t *);
1034486Sphkstatic int psycho_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);
1044486Sphkstatic int psycho_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t,
1054486Sphk    bus_dmamap_callback_t *, void *, int);
1064486Sphkstatic void psycho_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
1074486Sphkstatic void psycho_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_dmasync_op_t);
1082061Sjkhstatic int psycho_dmamem_alloc(bus_dma_tag_t, void **, int, bus_dmamap_t *);
1092061Sjkhstatic void psycho_dmamem_free(bus_dma_tag_t, void *, bus_dmamap_t);
11025979Sjkh
11125979Sjkh/*
11225979Sjkh * autoconfiguration
11325979Sjkh */
1142061Sjkhstatic int psycho_probe(device_t);
11525979Sjkhstatic int psycho_attach(device_t);
1162061Sjkhstatic int psycho_read_ivar(device_t, device_t, int, u_long *);
1172061Sjkhstatic int psycho_setup_intr(device_t, device_t, struct resource *, int,
11817308Speter    driver_intr_t *, void *, void **);
1192061Sjkhstatic int psycho_teardown_intr(device_t, device_t, struct resource *, void *);
1202061Sjkhstatic struct resource *psycho_alloc_resource(device_t, device_t, int, int *,
1212061Sjkh    u_long, u_long, u_long, u_int);
1222061Sjkhstatic int psycho_activate_resource(device_t, device_t, int, int,
1232061Sjkh    struct resource *);
12412483Speterstatic int psycho_deactivate_resource(device_t, device_t, int, int,
12512483Speter    struct resource *);
12612483Speterstatic int psycho_release_resource(device_t, device_t, int, int,
12712483Speter    struct resource *);
1282061Sjkhstatic int psycho_maxslots(device_t);
1292061Sjkhstatic u_int32_t psycho_read_config(device_t, u_int, u_int, u_int, u_int, int);
1308854Srgrimesstatic void psycho_write_config(device_t, u_int, u_int, u_int, u_int, u_int32_t,
1312061Sjkh    int);
1322061Sjkhstatic int psycho_route_interrupt(device_t, device_t, int);
13312483Speterstatic int psycho_intr_pending(device_t, int);
1342061Sjkhstatic bus_space_handle_t psycho_get_bus_handle(device_t dev, enum sbbt_id id,
13527910Sasami    bus_space_handle_t childhdl, bus_space_tag_t *tag);
13627910Sasami
13718714Sachestatic device_method_t psycho_methods[] = {
13817308Speter	/* Device interface */
13917308Speter	DEVMETHOD(device_probe,		psycho_probe),
14017308Speter	DEVMETHOD(device_attach,	psycho_attach),
14117308Speter
14221536Sjmacd	/* Bus interface */
14315603Smarkm	DEVMETHOD(bus_print_child,	bus_generic_print_child),
14417308Speter	DEVMETHOD(bus_read_ivar,	psycho_read_ivar),
14517308Speter	DEVMETHOD(bus_setup_intr, 	psycho_setup_intr),
14617308Speter	DEVMETHOD(bus_teardown_intr,	psycho_teardown_intr),
14717308Speter	DEVMETHOD(bus_alloc_resource,	psycho_alloc_resource),
14817308Speter	DEVMETHOD(bus_activate_resource,	psycho_activate_resource),
14917308Speter	DEVMETHOD(bus_deactivate_resource,	psycho_deactivate_resource),
15017308Speter	DEVMETHOD(bus_release_resource,	psycho_release_resource),
15117308Speter
15217308Speter	/* pcib interface */
15318362Sjkh	DEVMETHOD(pcib_maxslots,	psycho_maxslots),
15419966Sache	DEVMETHOD(pcib_read_config,	psycho_read_config),
15518362Sjkh	DEVMETHOD(pcib_write_config,	psycho_write_config),
15617308Speter	DEVMETHOD(pcib_route_interrupt,	psycho_route_interrupt),
15727910Sasami
15817308Speter	/* sparcbus interface */
15917308Speter	DEVMETHOD(sparcbus_intr_pending,	psycho_intr_pending),
16017308Speter	DEVMETHOD(sparcbus_get_bus_handle,	psycho_get_bus_handle),
16128803Speter
16227910Sasami	{ 0, 0 }
16328803Speter};
16430113Sjkh
16527910Sasamistatic driver_t psycho_driver = {
16617308Speter	"pcib",
1672061Sjkh	psycho_methods,
16827910Sasami	sizeof(struct psycho_softc),
1692061Sjkh};
17028803Speter
17127910Sasamistatic devclass_t psycho_devclass;
1722061Sjkh
17317308SpeterDRIVER_MODULE(psycho, nexus, psycho_driver, psycho_devclass, 0, 0);
17427910Sasami
17517308Speterstatic int psycho_ndevs;
17627910Sasamistatic struct psycho_softc *psycho_softcs[4];
17727910Sasami
17827910Sasamistruct psycho_clr {
17917308Speter	struct psycho_softc	*pci_sc;
18027910Sasami	bus_addr_t	pci_clr;	/* clear register */
18117308Speter	driver_intr_t	*pci_handler;	/* handler to call */
18227910Sasami	void		*pci_arg;	/* argument for the handler */
18327910Sasami	void		*pci_cookie;	/* interrupt cookie of parent bus */
18427910Sasami};
18527910Sasami
18627910Sasamistruct psycho_strayclr {
18727910Sasami	struct psycho_softc	*psc_sc;
18827910Sasami	bus_addr_t	psc_clr;	/* clear register */
18927910Sasami};
19027910Sasami
19127910Sasami#define	PSYCHO_READ8(sc, off) \
19227910Sasami	bus_space_read_8((sc)->sc_bustag, (sc)->sc_bushandle, (off))
19327910Sasami#define	PSYCHO_WRITE8(sc, off, v) \
19427910Sasami	bus_space_write_8((sc)->sc_bustag, (sc)->sc_bushandle, (off), (v))
19527910Sasami#define	PCICTL_READ8(sc, off) \
19627910Sasami	PSYCHO_READ8((sc), (sc)->sc_pcictl + (off))
19727910Sasami#define	PCICTL_WRITE8(sc, off, v) \
19827910Sasami	PSYCHO_WRITE8((sc), (sc)->sc_pcictl + (off), (v))
19927910Sasami
20027910Sasami/*
20127910Sasami * "sabre" is the UltraSPARC IIi onboard UPA to PCI bridge.  It manages a
20227910Sasami * single PCI bus and does not have a streaming buffer.  It often has an APB
20327910Sasami * (advanced PCI bridge) connected to it, which was designed specifically for
20427910Sasami * the IIi.  The APB let's the IIi handle two independednt PCI buses, and
20527910Sasami * appears as two "simba"'s underneath the sabre.
20627910Sasami *
20727910Sasami * "psycho" and "psycho+" is a dual UPA to PCI bridge.  It sits on the UPA bus
20827910Sasami * and manages two PCI buses.  "psycho" has two 64-bit 33MHz buses, while
20927910Sasami * "psycho+" controls both a 64-bit 33Mhz and a 64-bit 66Mhz PCI bus.  You
21027910Sasami * will usually find a "psycho+" since I don't think the original "psycho"
21127910Sasami * ever shipped, and if it did it would be in the U30.
21227910Sasami *
21327910Sasami * Each "psycho" PCI bus appears as a separate OFW node, but since they are
21427910Sasami * both part of the same IC, they only have a single register space.  As such,
21527910Sasami * they need to be configured together, even though the autoconfiguration will
21627910Sasami * attach them separately.
21727910Sasami *
21827910Sasami * On UltraIIi machines, "sabre" itself usually takes pci0, with "simba" often
21917308Speter * as pci1 and pci2, although they have been implemented with other PCI bus
22017308Speter * numbers on some machines.
22127910Sasami *
22217308Speter * On UltraII machines, there can be any number of "psycho+" ICs, each
22327910Sasami * providing two PCI buses.
22427910Sasami *
22527910Sasami *
22627910Sasami * XXXX The psycho/sabre node has an `interrupts' attribute.  They contain
22717466Speter * the values of the following interrupts in this order:
22817308Speter *
22927910Sasami * PCI Bus Error	(30)
23017308Speter * DMA UE		(2e)
23127910Sasami * DMA CE		(2f)
23230277Sasami * Power Fail		(25)
23327910Sasami *
23430277Sasami * We really should attach handlers for each.
23530277Sasami */
23630277Sasami#define	OFW_PCI_TYPE		"pci"
23730277Sasami#define OFW_SABRE_MODEL		"SUNW,sabre"
23830113Sjkh#define OFW_SABRE_COMPAT	"pci108e,a001"
23930277Sasami#define OFW_SIMBA_MODEL		"SUNW,simba"
24030277Sasami#define OFW_PSYCHO_MODEL	"SUNW,psycho"
24117308Speter
24217308Speterstatic int
24327910Sasamipsycho_probe(device_t dev)
24417308Speter{
24527910Sasami	phandle_t node;
24627910Sasami	char *dtype, *model;
24717308Speter	static char compat[32];
24817308Speter
24927910Sasami	node = nexus_get_node(dev);
25017308Speter	if (OF_getprop(node, "compatible", compat, sizeof(compat)) == -1)
25130113Sjkh		compat[0] = '\0';
25227910Sasami
25327910Sasami	dtype = nexus_get_device_type(dev);
25417308Speter	model = nexus_get_model(dev);
25517308Speter	/* match on a type of "pci" and a sabre or a psycho */
25627910Sasami	if (nexus_get_reg(dev) != NULL && dtype != NULL &&
25717308Speter	    strcmp(dtype, OFW_PCI_TYPE) == 0 &&
25830113Sjkh	    ((model != NULL && (strcmp(model, OFW_SABRE_MODEL) == 0 ||
25927910Sasami	      strcmp(model, OFW_PSYCHO_MODEL) == 0)) ||
26017308Speter	      strcmp(compat, OFW_SABRE_COMPAT) == 0)) {
26117308Speter		device_set_desc(dev, "U2P UPA-PCI bridge");
26227910Sasami		return (0);
26317308Speter	}
26427910Sasami
26517308Speter	return (ENXIO);
26617308Speter}
26727910Sasami
26817308Speter/*
26927910Sasami * SUNW,psycho initialisation ..
27017308Speter *	- find the per-psycho registers
27117308Speter *	- figure out the IGN.
27227910Sasami *	- find our partner psycho
27317308Speter *	- configure ourselves
27429503Sbde *	- bus range, bus,
27517962Speter *	- interrupt map,
27617962Speter *	- setup the chipsets.
27727910Sasami *	- if we're the first of the pair, initialise the IOMMU, otherwise
27817962Speter *	  just copy it's tags and addresses.
27927910Sasami */
28017962Speterstatic int
28117962Speterpsycho_attach(device_t dev)
28227910Sasami{
28317962Speter	struct psycho_softc *sc;
28427910Sasami	struct psycho_softc *osc = NULL;
28517962Speter	struct psycho_softc *asc;
28617962Speter	struct upa_regs *reg;
28727910Sasami	char compat[32];
28817962Speter	char *model;
28927910Sasami	phandle_t node;
29017308Speter	u_int64_t csr;
29117308Speter	u_long pcictl_offs, mlen;
29227910Sasami	int psycho_br[2];
29317308Speter	int n, i, nreg, rid;
29430205Sbde#if defined(PSYCHO_DEBUG) || defined(PSYCHO_STRAY)
29517308Speter	bus_addr_t map, clr;
29617308Speter	u_int64_t mr;
29727910Sasami#endif
29817962Speter#ifdef PSYCHO_STRAY
29927910Sasami	struct psycho_strayclr *sclr;
3002061Sjkh#endif
30117308Speter
30227910Sasami	node = nexus_get_node(dev);
30327910Sasami	sc = device_get_softc(dev);
30427910Sasami	if (OF_getprop(node, "compatible", compat, sizeof(compat)) == -1)
30527910Sasami		compat[0] = '\0';
30627910Sasami
30727910Sasami	sc->sc_node = node;
30827910Sasami	sc->sc_dev = dev;
30927910Sasami	sc->sc_dmatag = nexus_get_dmatag(dev);
31017308Speter
31117308Speter	/*
31217308Speter	 * call the model-specific initialisation routine.
31317308Speter	 */
31417308Speter	model = nexus_get_model(dev);
31517308Speter	if ((model != NULL &&
31617308Speter	     strcmp(model, OFW_SABRE_MODEL) == 0) ||
31712483Speter	    strcmp(compat, OFW_SABRE_COMPAT) == 0) {
31817308Speter		sc->sc_mode = PSYCHO_MODE_SABRE;
31912483Speter		if (model == NULL)
32017308Speter			model = "sabre";
32112483Speter	} else if (model != NULL &&
3222061Sjkh	    strcmp(model, OFW_PSYCHO_MODEL) == 0)
32317962Speter		sc->sc_mode = PSYCHO_MODE_PSYCHO;
32417962Speter	else
32517308Speter		panic("psycho_attach: unknown model!");
32617962Speter
32717962Speter	/*
32817962Speter	 * The psycho gets three register banks:
32917962Speter	 * (0) per-PBM configuration and status registers
33017308Speter	 * (1) per-PBM PCI configuration space, containing only the
3312061Sjkh	 *     PBM 256-byte PCI header
33217308Speter	 * (2) the shared psycho configuration registers (struct psychoreg)
33317308Speter	 *
33417308Speter	 * XXX use the prom address for the psycho registers?  we do so far.
33517308Speter	 */
33617308Speter	reg = nexus_get_reg(dev);
33717308Speter	nreg = nexus_get_nreg(dev);
3382302Spaul	/* Register layouts are different.  stuupid. */
3392302Spaul	if (sc->sc_mode == PSYCHO_MODE_PSYCHO) {
3402302Spaul		if (nreg <= 2)
3412302Spaul			panic("psycho_attach: %d not enough registers", nreg);
3422302Spaul		sc->sc_basepaddr = (vm_offset_t)UPA_REG_PHYS(&reg[2]);
34318714Sache		mlen = UPA_REG_SIZE(&reg[2]);
34410760Sache		pcictl_offs = UPA_REG_PHYS(&reg[0]);
34518714Sache	} else {
3462302Spaul		if (nreg <= 0)
34710760Sache			panic("psycho_attach: %d not enough registers", nreg);
34818714Sache		sc->sc_basepaddr = (vm_offset_t)UPA_REG_PHYS(&reg[0]);
34910760Sache		mlen = UPA_REG_SIZE(reg);
35010760Sache		pcictl_offs = sc->sc_basepaddr + PSR_PCICTL0;
3512302Spaul	}
3522302Spaul
3532302Spaul	/*
3542302Spaul	 * Match other psycho's that are already configured against
35530132Sfsmp	 * the base physical address. This will be the same for a
3562302Spaul	 * pair of devices that share register space.
3572302Spaul	 */
35817308Speter	for (n = 0; n < psycho_ndevs && n < sizeof(psycho_softcs) /
35917308Speter	     sizeof(psycho_softcs[0]); n++) {
36017308Speter		asc = (struct psycho_softc *)psycho_softcs[n];
36117308Speter
36217308Speter		if (asc == NULL || asc == sc)
36317308Speter			/* This entry is not there or it is me */
3642061Sjkh			continue;
36517308Speter
3662061Sjkh		if (asc->sc_basepaddr != sc->sc_basepaddr)
36730205Sbde			/* This is an unrelated psycho */
36830205Sbde			continue;
36930205Sbde
37030205Sbde		/* Found partner */
37130205Sbde		osc = asc;
37230205Sbde		break;
37330205Sbde	}
37430205Sbde
37530169Sjkh	if (osc == NULL) {
37630205Sbde		rid = 0;
37717308Speter		sc->sc_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
37817308Speter		    sc->sc_basepaddr, sc->sc_basepaddr + mlen - 1, mlen,
37930205Sbde		    RF_ACTIVE);
38017308Speter		if (sc->sc_mem_res == NULL ||
3812061Sjkh		    rman_get_start(sc->sc_mem_res) != sc->sc_basepaddr)
38217308Speter			panic("psycho_attach: can't allocate device memory");
38317308Speter		sc->sc_bustag = rman_get_bustag(sc->sc_mem_res);
38417308Speter		sc->sc_bushandle = rman_get_bushandle(sc->sc_mem_res);
38517308Speter	} else {
38617308Speter		/*
38717308Speter		 * There's another psycho using the same register space. Copy the
3883626Swollman		 * relevant stuff.
3893626Swollman		 */
3903626Swollman		sc->sc_mem_res = NULL;
3913626Swollman		sc->sc_bustag = osc->sc_bustag;
39230205Sbde		sc->sc_bushandle = osc->sc_bushandle;
39330205Sbde	}
39430205Sbde	if (pcictl_offs < sc->sc_basepaddr)
39530205Sbde		panic("psycho_attach: bogus pci control register location");
39630205Sbde	sc->sc_pcictl = pcictl_offs - sc->sc_basepaddr;
39730205Sbde	csr = PSYCHO_READ8(sc, PSR_CS);
39830205Sbde	sc->sc_ign = 0x7c0; /* APB IGN is always 0x7c */
39930205Sbde	if (sc->sc_mode == PSYCHO_MODE_PSYCHO)
40030169Sjkh		sc->sc_ign = PSYCHO_GCSR_IGN(csr) << 6;
40130205Sbde
4023626Swollman	device_printf(dev, "%s: impl %d, version %d: ign %x ",
4033626Swollman		model, (int)PSYCHO_GCSR_IMPL(csr), (int)PSYCHO_GCSR_VERS(csr),
40430205Sbde		sc->sc_ign);
4053626Swollman
4063626Swollman	/*
40717308Speter	 * Setup the PCI control register
40817308Speter	 */
40917308Speter	csr = PCICTL_READ8(sc, PCR_CS);
41017308Speter	csr |= PCICTL_MRLM | PCICTL_ARB_PARK | PCICTL_ERRINTEN | PCICTL_4ENABLE;
41117308Speter	csr &= ~(PCICTL_SERR | PCICTL_CPU_PRIO | PCICTL_ARB_PRIO |
41217308Speter	    PCICTL_RTRYWAIT);
41317308Speter	PCICTL_WRITE8(sc, PCR_CS, csr);
41417308Speter
41517308Speter	/* grab the psycho ranges */
41617308Speter	psycho_get_ranges(sc->sc_node, &sc->sc_range, &sc->sc_nrange);
4173626Swollman
41817308Speter	/* get the bus-range for the psycho */
41917308Speter	n = OF_getprop(node, "bus-range", (void *)psycho_br, sizeof(psycho_br));
42017308Speter	if (n == -1)
42117308Speter		panic("could not get psycho bus-range");
42217308Speter	if (n != sizeof(psycho_br))
42317308Speter		panic("broken psycho bus-range (%d)", n);
42417308Speter
42517308Speter	printf("bus range %u to %u; PCI bus %d\n", psycho_br[0], psycho_br[1],
42617308Speter	    psycho_br[0]);
42717308Speter
42817308Speter	sc->sc_busno = psycho_br[0];
42917308Speter
43027910Sasami	/* Initialize memory and i/o rmans */
43127910Sasami	sc->sc_io_rman.rm_type = RMAN_ARRAY;
43227910Sasami	sc->sc_io_rman.rm_descr = "Psycho PCI I/O Ports";
43327910Sasami	if (rman_init(&sc->sc_io_rman) != 0 ||
43427910Sasami	    rman_manage_region(&sc->sc_io_rman, 0, PSYCHO_IO_SIZE) != 0)
43527910Sasami		panic("psycho_probe: failed to set up i/o rman");
43617820Sjkh	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
43730113Sjkh	sc->sc_mem_rman.rm_descr = "Psycho PCI Memory";
43830113Sjkh	if (rman_init(&sc->sc_mem_rman) != 0 ||
43917820Sjkh	    rman_manage_region(&sc->sc_mem_rman, 0, PSYCHO_MEM_SIZE) != 0)
44030113Sjkh		panic("psycho_probe: failed to set up memory rman");
44130113Sjkh	/*
44217820Sjkh	 * Find the addresses of the various bus spaces.
44330170Sjkh	 * There should not be multiple ones of one kind.
44430113Sjkh	 * The physical start addresses of the ranges are the configuration,
44529938Smckay	 * memory and IO handles.
44629938Smckay	 */
44729938Smckay	for (n = 0; n < sc->sc_nrange; n++) {
44817308Speter		i = UPA_RANGE_CS(&sc->sc_range[n]);
44917308Speter		if (sc->sc_bh[i] != 0)
45017308Speter			panic("psycho_attach: duplicate range for space %d", i);
45117308Speter		sc->sc_bh[i] = UPA_RANGE_PHYS(&sc->sc_range[n]);
45217308Speter	}
45327910Sasami	/*
45427910Sasami	 * Check that all needed handles are present. The PCI_CS_MEM64 one is
45527910Sasami	 * not currently used.
45617308Speter	 */
45717308Speter	for (n = 0; n < 3; n++) {
45830113Sjkh		if (sc->sc_bh[n] == 0)
45930113Sjkh			panic("psycho_attach: range %d missing", n);
46030113Sjkh	}
46117308Speter
46217308Speter	/* allocate our tags */
46317308Speter	sc->sc_memt = psycho_alloc_bus_tag(sc, PCI_MEMORY_BUS_SPACE);
46417308Speter	sc->sc_iot = psycho_alloc_bus_tag(sc, PCI_IO_BUS_SPACE);
46514119Speter	sc->sc_cfgt = psycho_alloc_bus_tag(sc, PCI_CONFIG_BUS_SPACE);
4662061Sjkh	if (bus_dma_tag_create(sc->sc_dmatag, 8, 1, 0, 0x3ffffffff, NULL, NULL,
4677130Srgrimes	    0x3ffffffff, 0xff, 0xffffffff, 0, &sc->sc_dmat) != 0)
4687130Srgrimes		panic("psycho_attach: bus_dma_tag_create failed");
4697130Srgrimes	/* Customize the tag */
4702061Sjkh	sc->sc_dmat->cookie = sc;
47130113Sjkh	sc->sc_dmat->dmamap_create = psycho_dmamap_create;
47217308Speter	sc->sc_dmat->dmamap_destroy = psycho_dmamap_destroy;
47330169Sjkh	sc->sc_dmat->dmamap_load = psycho_dmamap_load;
47430169Sjkh	sc->sc_dmat->dmamap_unload = psycho_dmamap_unload;
4752685Srgrimes	sc->sc_dmat->dmamap_sync = psycho_dmamap_sync;
4766927Snate	sc->sc_dmat->dmamem_alloc = psycho_dmamem_alloc;
47727790Sasami	sc->sc_dmat->dmamem_free = psycho_dmamem_free;
47827790Sasami	/* XXX: register as root dma tag (kluge). */
47927790Sasami	sparc64_root_dma_tag = sc->sc_dmat;
48030169Sjkh
48130169Sjkh	if ((sc->sc_nintrmap = OF_getprop_alloc(sc->sc_node, "interrupt-map",
48230169Sjkh	    sizeof(*sc->sc_intrmap), (void **)&sc->sc_intrmap)) == -1 ||
4833197Scsgr	    OF_getprop(sc->sc_node, "interrupt-map-mask", &sc->sc_intrmapmsk,
48430169Sjkh		sizeof(sc->sc_intrmapmsk)) == -1) {
48530169Sjkh		if (sc->sc_intrmap != NULL) {
48630169Sjkh			free(sc->sc_intrmap, M_OFWPROP);
48730169Sjkh			sc->sc_intrmap = NULL;
48830169Sjkh		}
48930169Sjkh	}
49030169Sjkh
49130169Sjkh	/* Register the softc, this is needed for paired psychos. */
49230169Sjkh	if (psycho_ndevs < sizeof(psycho_softcs) / sizeof(psycho_softcs[0]))
49330169Sjkh		psycho_softcs[psycho_ndevs] = sc;
49432427Sjb	else
49532427Sjb		device_printf(dev, "XXX: bump the number of psycho_softcs");
49632427Sjb	psycho_ndevs++;
49726152Speter	/*
4982061Sjkh	 * And finally, if we're a sabre or the first of a pair of psycho's to
4992061Sjkh	 * arrive here, start up the IOMMU and get a config space tag.
50030169Sjkh	 */
5012061Sjkh	if (osc == NULL) {
50216786Snate		/*
5032883Sphk		 * Establish handlers for interesting interrupts....
50427790Sasami		 *
50517308Speter		 * XXX We need to remember these and remove this to support
5067281Srgrimes		 * hotplug on the UPA/FHC bus.
5073242Spaul		 *
5083242Spaul		 * XXX Not all controllers have these, but installing them
50930169Sjkh		 * is better than trying to sort through this mess.
5107171Sats		 */
5112061Sjkh		psycho_set_intr(sc, 0, dev, PSR_UE_INT_MAP, INTR_FAST,
5123213Spst		    psycho_ue);
51330169Sjkh		psycho_set_intr(sc, 1, dev, PSR_CE_INT_MAP, 0, psycho_ce);
51430169Sjkh		psycho_set_intr(sc, 2, dev, PSR_PCIAERR_INT_MAP, INTR_FAST,
51530169Sjkh		    psycho_bus_a);
51630169Sjkh		psycho_set_intr(sc, 3, dev, PSR_PCIBERR_INT_MAP, INTR_FAST,
51717308Speter		    psycho_bus_b);
5185749Swollman		psycho_set_intr(sc, 4, dev, PSR_POWER_INT_MAP, INTR_FAST,
5195772Swollman		    psycho_powerfail);
52017308Speter#ifdef PSYCHO_MAP_WAKEUP
52117308Speter		/*
52230169Sjkh		 * On some models, this is mapped to the same interrupt as
52326504Sjhay		 * pciberr by default, so leave it alone for now since
52430169Sjkh		 * psycho_wakeup() doesn't do anything useful anyway.
52530169Sjkh		 */
5262061Sjkh		psycho_set_intr(sc, 5, dev, PSR_PWRMGT_INT_MAP, 0,
52717308Speter		    psycho_wakeup);
52817308Speter#endif /* PSYCHO_MAP_WAKEUP */
52917308Speter
53027910Sasami
53127910Sasami		/* Initialize the counter-timer if we handle a psycho. */
5325366Snate		if (sc->sc_mode == PSYCHO_MODE_PSYCHO) {
53327910Sasami			sparc64_counter_init(sc->sc_bustag, sc->sc_bushandle,
53427910Sasami			    PSR_TC0);
53527910Sasami		}
53627910Sasami
53727910Sasami		/*
53827910Sasami		 * Setup IOMMU and PCI configuration if we're the first
53927910Sasami		 * of a pair of psycho's to arrive here.
54027910Sasami		 *
54127910Sasami		 * We should calculate a TSB size based on amount of RAM
54227910Sasami		 * and number of bus controllers and number an type of
54327910Sasami		 * child devices.
54427910Sasami		 *
54527910Sasami		 * For the moment, 32KB should be more than enough.
54627910Sasami		 */
54727910Sasami		sc->sc_is = malloc(sizeof(struct iommu_state), M_DEVBUF,
54830113Sjkh		    M_NOWAIT);
54930113Sjkh		if (sc->sc_is == NULL)
55027910Sasami			panic("psycho_attach: malloc iommu_state failed");
5515366Snate		sc->sc_is->is_sb[0] = 0;
55217308Speter		sc->sc_is->is_sb[1] = 0;
55317308Speter		if (OF_getproplen(sc->sc_node, "no-streaming-cache") < 0)
55417308Speter			sc->sc_is->is_sb[0] = sc->sc_pcictl + PCR_STRBUF;
5552061Sjkh		psycho_iommu_init(sc, 2);
55632427Sjb	} else {
55732427Sjb		/* Just copy IOMMU state, config tag and address */
55830113Sjkh		sc->sc_is = osc->sc_is;
55930113Sjkh		if (OF_getproplen(sc->sc_node, "no-streaming-cache") < 0)
56024754Sjdp			sc->sc_is->is_sb[1] = sc->sc_pcictl + PCR_STRBUF;
5618295Srgrimes		iommu_reset(sc->sc_is);
56217820Sjkh	}
56330113Sjkh
56430113Sjkh	/*
5658295Srgrimes	 * Enable all interrupts, clear all interrupt states, and install an
5668489Srgrimes	 * interrupt handler for OBIO interrupts, which can be ISA ones
56717820Sjkh	 * (to frob the interrupt clear registers).
56830113Sjkh	 * This aids the debugging of interrupt routing problems, and is needed
56930113Sjkh	 * for isa drivers that use isa_irq_pending (otherwise the registers
5708489Srgrimes	 * will never be cleared).
5718489Srgrimes	 */
57217820Sjkh#if defined(PSYCHO_DEBUG) || defined(PSYCHO_STRAY)
57330113Sjkh	for (map = PSR_PCIA0_INT_MAP, clr = PSR_PCIA0_INT_CLR, n = 0;
57430113Sjkh	     map <= PSR_PCIB3_INT_MAP; map += 8, clr += 32, n++) {
5758489Srgrimes		mr = PSYCHO_READ8(sc, map);
5768295Srgrimes#ifdef PSYCHO_DEBUG
57717820Sjkh		device_printf(dev, "intr map (pci) %d: %#lx\n", n, (u_long)mr);
57830113Sjkh#endif
57930113Sjkh		PSYCHO_WRITE8(sc, map, mr & ~INTMAP_V);
5808295Srgrimes		for (i = 0; i < 4; i++)
5812160Scsgr			PCICTL_WRITE8(sc, clr + i * 8, 0);
58217820Sjkh		PSYCHO_WRITE8(sc, map, mr | INTMAP_V);
58330113Sjkh	}
58430113Sjkh	for (map = PSR_SCSI_INT_MAP, clr = PSR_SCSI_INT_CLR, n = 0;
5852160Scsgr	     map <= PSR_FFB1_INT_MAP; map += 8, clr += 8, n++) {
5862279Spaul		mr = PSYCHO_READ8(sc, map);
58717820Sjkh#ifdef PSYCHO_DEBUG
58830113Sjkh		device_printf(dev, "intr map (obio) %d: %#lx, clr: %#lx\n", n,
58930113Sjkh		    (u_long)mr, (u_long)clr);
5902279Spaul#endif
59117234Sjraynard		PSYCHO_WRITE8(sc, map, mr & ~INTMAP_V);
59217820Sjkh		PSYCHO_WRITE8(sc, clr, 0);
59330113Sjkh#ifdef PSYCHO_STRAY
59430113Sjkh		/*
59511772Snate		 * This can cause interrupt storms, and is therefore disabled
59630170Sjkh		 * by default.
59730127Smarkm		 * XXX: use intr_setup() to not confuse higher level code
59830113Sjkh		 */
59930113Sjkh		if (INTVEC(mr) != 0x7e6 && INTVEC(mr) != 0x7e7 &&
6002626Scsgr		    INTVEC(mr) != 0) {
6018304Srgrimes			sclr = malloc(sizeof(*sclr), M_DEVBUF, M_WAITOK);
60217820Sjkh			sclr->psc_sc = sc;
60330113Sjkh			sclr->psc_clr = clr;
60430113Sjkh			intr_setup(PIL_LOW, intr_dequeue, INTVEC(mr),
6058304Srgrimes			    psycho_intr_stray, sclr);
6062061Sjkh		}
60717308Speter#endif
60817308Speter		PSYCHO_WRITE8(sc, map, mr | INTMAP_V);
60917308Speter	}
61027910Sasami#endif
61127910Sasami
61227910Sasami	/*
61327910Sasami	 * Initialize the interrupt registers of all devices hanging from
61427910Sasami	 * the host bridge directly or indirectly via PCI-PCI bridges.
61527910Sasami	 * The MI code (and the PCI spec) assume that this is done during
61617308Speter	 * system initialization, however the firmware does not do this
61711806Sphk	 * at least on some models, and we probably shouldn't trust that
61819175Sbde	 * the firmware uses the same model as this driver if it does.
61927910Sasami	 */
62027910Sasami	ofw_pci_init_intr(dev, sc->sc_node, sc->sc_intrmap, sc->sc_nintrmap,
62127910Sasami	    &sc->sc_intrmapmsk);
62227910Sasami
62327910Sasami	device_add_child(dev, "pci", device_get_unit(dev));
62427910Sasami	return (bus_generic_attach(dev));
62527910Sasami}
62627910Sasami
62727910Sasamistatic void
62827910Sasamipsycho_set_intr(struct psycho_softc *sc, int index,
62927910Sasami    device_t dev, bus_addr_t map, int iflags, driver_intr_t handler)
63027910Sasami{
63127910Sasami	int rid, vec;
63227910Sasami	u_int64_t mr;
63327910Sasami
63427910Sasami	mr = PSYCHO_READ8(sc, map);
63527910Sasami	vec = INTVEC(mr);
63627910Sasami	sc->sc_irq_res[index] = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
63727910Sasami	    vec, vec, 1, RF_ACTIVE);
63827910Sasami	if (sc->sc_irq_res[index] == NULL)
63927910Sasami		panic("psycho_set_intr: failed to get interrupt");
64027910Sasami	bus_setup_intr(dev, sc->sc_irq_res[index], INTR_TYPE_MISC | iflags,
64127910Sasami	    handler, sc, &sc->sc_ihand[index]);
64221673Sjkh	PSYCHO_WRITE8(sc, map, mr | INTMAP_V);
64327910Sasami}
64427910Sasami
64527910Sasamistatic int
64627910Sasamipsycho_find_intrmap(struct psycho_softc *sc, int ino, bus_addr_t *intrmapptr,
64727910Sasami    bus_addr_t *intrclrptr, bus_addr_t *intrdiagptr)
64827910Sasami{
64927910Sasami	bus_addr_t intrmap, intrclr;
65027910Sasami	u_int64_t im;
65127910Sasami	u_long diag;
65227910Sasami	int found;
65327910Sasami
65427910Sasami	found = 0;
65527910Sasami	/* Hunt thru obio first */
65627910Sasami	diag = PSYCHO_READ8(sc, PSR_OBIO_INT_DIAG);
65727910Sasami	for (intrmap = PSR_SCSI_INT_MAP, intrclr = PSR_SCSI_INT_CLR;
65827910Sasami	     intrmap <= PSR_FFB1_INT_MAP; intrmap += 8, intrclr += 8,
65927910Sasami	     diag >>= 2) {
66027910Sasami		im = PSYCHO_READ8(sc, intrmap);
66119175Sbde		if (INTINO(im) == ino) {
66227910Sasami			diag &= 2;
66327910Sasami			found = 1;
66427910Sasami			break;
66527910Sasami		}
66627910Sasami	}
66727910Sasami
66827910Sasami	if (!found) {
66927910Sasami		diag = PSYCHO_READ8(sc, PSR_PCI_INT_DIAG);
67027910Sasami		/* Now do PCI interrupts */
67127910Sasami		for (intrmap = PSR_PCIA0_INT_MAP, intrclr = PSR_PCIA0_INT_CLR;
67227910Sasami		     intrmap <= PSR_PCIB3_INT_MAP; intrmap += 8, intrclr += 32,
67327910Sasami		     diag >>= 8) {
67419175Sbde			im = PSYCHO_READ8(sc, intrmap);
67530113Sjkh			if (((im ^ ino) & 0x3c) == 0) {
67630113Sjkh				intrclr += 8 * (ino & 3);
67719175Sbde				diag = (diag >> ((ino & 3) * 2)) & 2;
6782061Sjkh				found = 1;
67930113Sjkh				break;
68030113Sjkh			}
68130113Sjkh		}
68230113Sjkh	}
68330113Sjkh	if (intrmapptr != NULL)
68430113Sjkh		*intrmapptr = intrmap;
68530113Sjkh	if (intrclrptr != NULL)
68630113Sjkh		*intrclrptr = intrclr;
68730113Sjkh	if (intrdiagptr != NULL)
68830113Sjkh		*intrdiagptr = diag;
68930113Sjkh	return (found);
69030113Sjkh}
69130113Sjkh
69230113Sjkh/* grovel the OBP for various psycho properties */
69330113Sjkhstatic void
69430113Sjkhpsycho_get_ranges(phandle_t node, struct upa_ranges **rp, int *np)
69530113Sjkh{
69632427Sjb
69732427Sjb	*np = OF_getprop_alloc(node, "ranges", sizeof(**rp), (void **)rp);
6981594Srgrimes	if (*np == -1)
699		panic("could not get psycho ranges");
700}
701
702/*
703 * Interrupt handlers.
704 */
705static void
706psycho_ue(void *arg)
707{
708	struct psycho_softc *sc = (struct psycho_softc *)arg;
709	u_int64_t afar, afsr;
710
711	afar = PSYCHO_READ8(sc, PSR_UE_AFA);
712	afsr = PSYCHO_READ8(sc, PSR_UE_AFS);
713	/* It's uncorrectable.  Dump the regs and panic. */
714	panic("%s: uncorrectable DMA error AFAR %#lx AFSR %#lx\n",
715	    device_get_name(sc->sc_dev), (u_long)afar, (u_long)afsr);
716}
717
718static void
719psycho_ce(void *arg)
720{
721	struct psycho_softc *sc = (struct psycho_softc *)arg;
722	u_int64_t afar, afsr;
723
724	PSYCHO_WRITE8(sc, PSR_CE_INT_CLR, 0);
725	afar = PSYCHO_READ8(sc, PSR_CE_AFA);
726	afsr = PSYCHO_READ8(sc, PSR_CE_AFS);
727	/* It's correctable.  Dump the regs and continue. */
728	printf("%s: correctable DMA error AFAR %#lx AFSR %#lx\n",
729	    device_get_name(sc->sc_dev), (u_long)afar, (u_long)afsr);
730}
731
732static void
733psycho_bus_a(void *arg)
734{
735	struct psycho_softc *sc = (struct psycho_softc *)arg;
736	u_int64_t afar, afsr;
737
738	afar = PSYCHO_READ8(sc, PSR_PCICTL0 + PCR_AFA);
739	afsr = PSYCHO_READ8(sc, PSR_PCICTL0 + PCR_AFS);
740	/* It's uncorrectable.  Dump the regs and panic. */
741	panic("%s: PCI bus A error AFAR %#lx AFSR %#lx\n",
742	    device_get_name(sc->sc_dev), (u_long)afar, (u_long)afsr);
743}
744
745static void
746psycho_bus_b(void *arg)
747{
748	struct psycho_softc *sc = (struct psycho_softc *)arg;
749	u_int64_t afar, afsr;
750
751	afar = PSYCHO_READ8(sc, PSR_PCICTL1 + PCR_AFA);
752	afsr = PSYCHO_READ8(sc, PSR_PCICTL1 + PCR_AFS);
753	/* It's uncorrectable.  Dump the regs and panic. */
754	panic("%s: PCI bus B error AFAR %#lx AFSR %#lx\n",
755	    device_get_name(sc->sc_dev), (u_long)afar, (u_long)afsr);
756}
757
758static void
759psycho_powerfail(void *arg)
760{
761
762	/* We lost power.  Try to shut down NOW. */
763#ifdef DEBUGGER_ON_POWERFAIL
764	struct psycho_softc *sc = (struct psycho_softc *)arg;
765
766	Debugger("powerfail");
767	PSYCHO_WRITE8(sc, PSR_POWER_INT_CLR, 0);
768#else
769	printf("Power Failure Detected: Shutting down NOW.\n");
770	shutdown_nice(0);
771#endif
772}
773
774#ifdef PSYCHO_MAP_WAKEUP
775static void
776psycho_wakeup(void *arg)
777{
778	struct psycho_softc *sc = (struct psycho_softc *)arg;
779
780	PSYCHO_WRITE8(sc, PSR_PWRMGT_INT_CLR, 0);
781	/* Gee, we don't really have a framework to deal with this properly. */
782	printf("%s: power management wakeup\n",	device_get_name(sc->sc_dev));
783}
784#endif /* PSYCHO_MAP_WAKEUP */
785
786/* initialise the IOMMU... */
787void
788psycho_iommu_init(struct psycho_softc *sc, int tsbsize)
789{
790	char *name;
791	struct iommu_state *is = sc->sc_is;
792	u_int32_t iobase = -1;
793	int *vdma = NULL;
794	int nitem;
795
796	/* punch in our copies */
797	is->is_bustag = sc->sc_bustag;
798	is->is_bushandle = sc->sc_bushandle;
799	is->is_iommu = PSR_IOMMU;
800	is->is_dtag = PSR_IOMMU_TLB_TAG_DIAG;
801	is->is_ddram = PSR_IOMMU_TLB_DATA_DIAG;
802	is->is_dqueue = PSR_IOMMU_QUEUE_DIAG;
803	is->is_dva = PSR_IOMMU_SVADIAG;
804	is->is_dtcmp = PSR_IOMMU_TLB_CMP_DIAG;
805
806	/*
807	 * Separate the men from the boys.  Get the `virtual-dma'
808	 * property for sabre and use that to make sure the damn
809	 * iommu works.
810	 *
811	 * We could query the `#virtual-dma-size-cells' and
812	 * `#virtual-dma-addr-cells' and DTRT, but I'm lazy.
813	 */
814	nitem = OF_getprop_alloc(sc->sc_node, "virtual-dma", sizeof(vdma),
815	    (void **)&vdma);
816	if (nitem > 0) {
817		iobase = vdma[0];
818		tsbsize = ffs(vdma[1]);
819		if (tsbsize < 25 || tsbsize > 31 ||
820		    (vdma[1] & ~(1 << (tsbsize - 1))) != 0) {
821			printf("bogus tsb size %x, using 7\n", vdma[1]);
822			tsbsize = 31;
823		}
824		tsbsize -= 24;
825		free(vdma, M_OFWPROP);
826	}
827
828	/* give us a nice name.. */
829	name = (char *)malloc(32, M_DEVBUF, M_NOWAIT);
830	if (name == 0)
831		panic("couldn't malloc iommu name");
832	snprintf(name, 32, "%s dvma", device_get_name(sc->sc_dev));
833
834	iommu_init(name, is, tsbsize, iobase);
835}
836
837static int
838psycho_maxslots(device_t dev)
839{
840
841	/*
842	 * XXX: is this correct? At any rate, a number that is too high
843	 * shouldn't do any harm, if only because of the way things are
844	 * handled in psycho_read_config.
845	 */
846	return (31);
847}
848
849/*
850 * Keep a table of quirky PCI devices that need fixups before the MI PCI code
851 * creates the resource lists. This needs to be moved around once other bus
852 * drivers are added. Moving it to the MI code should maybe be reconsidered
853 * if one of these devices appear in non-sparc64 boxen. It's likely that not
854 * all BIOSes/firmwares can deal with them.
855 */
856struct psycho_dquirk {
857	u_int32_t	dq_devid;
858	int		dq_quirk;
859};
860
861/* Quirk types. May be or'ed together. */
862#define	DQT_BAD_INTPIN	1	/* Intpin reg 0, but intpin used */
863
864static struct psycho_dquirk dquirks[] = {
865	{ 0x1001108e, DQT_BAD_INTPIN },	/* Sun HME (PCIO func. 1) */
866	{ 0x1101108e, DQT_BAD_INTPIN },	/* Sun GEM (PCIO2 func. 1) */
867	{ 0x1102108e, DQT_BAD_INTPIN },	/* Sun FireWire ctl. (PCIO2 func. 2) */
868	{ 0x1103108e, DQT_BAD_INTPIN },	/* Sun USB ctl. (PCIO2 func. 3) */
869};
870
871#define	NDQUIRKS	(sizeof(dquirks) / sizeof(dquirks[0]))
872
873static u_int32_t
874psycho_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
875	int width)
876{
877	struct psycho_softc *sc;
878	bus_space_handle_t bh;
879	u_long offset = 0;
880	u_int32_t r, devid;
881	int i;
882
883	/*
884	 * The psycho bridge does not tolerate accesses to unconfigured PCI
885	 * devices' or function's config space, so look up the device in the
886	 * firmware device tree first, and if it is not present, return a value
887	 * that will make the detection code think that there is no device here.
888	 * This is ugly...
889	 */
890	if (reg == 0 && ofw_pci_find_node(bus, slot, func) == 0)
891		return (0xffffffff);
892	sc = (struct psycho_softc *)device_get_softc(dev);
893	offset = PSYCHO_CONF_OFF(bus, slot, func, reg);
894	bh = sc->sc_bh[PCI_CS_CONFIG];
895	switch (width) {
896	case 1:
897		r = bus_space_read_1(sc->sc_cfgt, bh, offset);
898		break;
899	case 2:
900		r = bus_space_read_2(sc->sc_cfgt, bh, offset);
901		break;
902	case 4:
903		r = bus_space_read_4(sc->sc_cfgt, bh, offset);
904		break;
905	default:
906		panic("psycho_read_config: bad width");
907	}
908	if (reg == PCIR_INTPIN && r == 0) {
909		/* Check for DQT_BAD_INTPIN quirk. */
910		devid = psycho_read_config(dev, bus, slot, func,
911		    PCIR_DEVVENDOR, 4);
912		for (i = 0; i < NDQUIRKS; i++) {
913			if (dquirks[i].dq_devid == devid) {
914				/*
915				 * Need to set the intpin to a value != 0 so
916				 * that the MI code will think that this device
917				 * has an interrupt.
918				 * Just use 1 (intpin a) for now. This is, of
919				 * course, bogus, but since interrupts are
920				 * routed in advance, this does not really
921				 * matter.
922				 */
923				if ((dquirks[i].dq_quirk & DQT_BAD_INTPIN) != 0)
924					r = 1;
925				break;
926			}
927		}
928	}
929	return (r);
930}
931
932static void
933psycho_write_config(device_t dev, u_int bus, u_int slot, u_int func,
934	u_int reg, u_int32_t val, int width)
935{
936	struct psycho_softc *sc;
937	bus_space_handle_t bh;
938	u_long offset = 0;
939
940	sc = (struct psycho_softc *)device_get_softc(dev);
941	offset = PSYCHO_CONF_OFF(bus, slot, func, reg);
942	bh = sc->sc_bh[PCI_CS_CONFIG];
943	switch (width) {
944	case 1:
945		bus_space_write_1(sc->sc_cfgt, bh, offset, val);
946		break;
947	case 2:
948		bus_space_write_2(sc->sc_cfgt, bh, offset, val);
949		break;
950	case 4:
951		bus_space_write_4(sc->sc_cfgt, bh, offset, val);
952		break;
953	default:
954		panic("psycho_write_config: bad width");
955	}
956}
957
958static int
959psycho_route_interrupt(device_t bus, device_t dev, int pin)
960{
961
962	/*
963	 * Since we preinitialize all interrupt line registers, this should not
964	 * happen for any built-in device.
965	 * Devices on bridges that route interrupts cannot work now - the
966	 * interrupt pin mappings are not known from the firmware...
967	 */
968	panic("psycho_route_interrupt");
969}
970
971static int
972psycho_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
973{
974	struct psycho_softc *sc;
975
976	sc = (struct psycho_softc *)device_get_softc(dev);
977	switch (which) {
978	case PCIB_IVAR_BUS:
979		*result = sc->sc_busno;
980		return (0);
981	}
982	return (ENOENT);
983}
984
985/* Write to the correct clr register, and call the actual handler. */
986static void
987psycho_intr_stub(void *arg)
988{
989	struct psycho_clr *pc;
990
991	pc = (struct psycho_clr *)arg;
992	pc->pci_handler(pc->pci_arg);
993	PSYCHO_WRITE8(pc->pci_sc, pc->pci_clr, 0);
994}
995
996#ifdef PSYCHO_STRAY
997/*
998 * Write to the correct clr register and return. arg is the address of the clear
999 * register to be used.
1000 * XXX: print a message?
1001 */
1002static void
1003psycho_intr_stray(void *arg)
1004{
1005	struct psycho_strayclr *sclr = arg;
1006
1007	PSYCHO_WRITE8(sclr->psc_sc, sclr->psc_clr, 0);
1008}
1009#endif
1010
1011static int
1012psycho_setup_intr(device_t dev, device_t child,
1013    struct resource *ires,  int flags, driver_intr_t *intr, void *arg,
1014    void **cookiep)
1015{
1016	struct psycho_softc *sc;
1017	struct psycho_clr *pc;
1018	bus_addr_t intrmapptr, intrclrptr;
1019	long vec = rman_get_start(ires);
1020	u_int64_t mr;
1021	int ino, error;
1022
1023	sc = (struct psycho_softc *)device_get_softc(dev);
1024	pc = (struct psycho_clr *)malloc(sizeof(*pc), M_DEVBUF, M_NOWAIT);
1025	if (pc == NULL)
1026		return (NULL);
1027
1028	/*
1029	 * Hunt through all the interrupt mapping regs to look for our
1030	 * interrupt vector.
1031	 *
1032	 * XXX We only compare INOs rather than IGNs since the firmware may
1033	 * not provide the IGN and the IGN is constant for all device on that
1034	 * PCI controller.  This could cause problems for the FFB/external
1035	 * interrupt which has a full vector that can be set arbitrarily.
1036	 */
1037	ino = INTINO(vec);
1038
1039	if (!psycho_find_intrmap(sc, ino, &intrmapptr, &intrclrptr, NULL)) {
1040		printf("Cannot find interrupt vector %lx\n", vec);
1041		free(pc, M_DEVBUF);
1042		return (NULL);
1043	}
1044
1045#ifdef PSYCHO_DEBUG
1046	device_printf(dev, "psycho_setup_intr: INO %d, map %#lx, clr %#lx\n",
1047	    ino, (u_long)intrmapptr, (u_long)intrclrptr);
1048#endif
1049	pc->pci_sc = sc;
1050	pc->pci_arg = arg;
1051	pc->pci_handler = intr;
1052	pc->pci_clr = intrclrptr;
1053	/* Disable the interrupt while we fiddle with it */
1054	mr = PSYCHO_READ8(sc, intrmapptr);
1055	PSYCHO_WRITE8(sc, intrmapptr, mr & ~INTMAP_V);
1056	error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags,
1057	    psycho_intr_stub, pc, cookiep);
1058	if (error != 0) {
1059		free(pc, M_DEVBUF);
1060		return (error);
1061	}
1062	pc->pci_cookie = *cookiep;
1063	*cookiep = pc;
1064
1065	/*
1066	 * Clear the interrupt, it might have been triggered before it was
1067	 * set up.
1068	 */
1069	PSYCHO_WRITE8(sc, intrclrptr, 0);
1070	/*
1071	 * Enable the interrupt now we have the handler installed.
1072	 * Read the current value as we can't change it besides the
1073	 * valid bit so so make sure only this bit is changed.
1074	 */
1075	PSYCHO_WRITE8(sc, intrmapptr, mr | INTMAP_V);
1076	return (error);
1077}
1078
1079static int
1080psycho_teardown_intr(device_t dev, device_t child,
1081    struct resource *vec, void *cookie)
1082{
1083	struct psycho_clr *pc;
1084	int error;
1085
1086	pc = (struct psycho_clr *)cookie;
1087	error = BUS_TEARDOWN_INTR(device_get_parent(dev), child, vec,
1088	    pc->pci_cookie);
1089	/*
1090	 * Don't disable the interrupt for now, so that stray interupts get
1091	 * detected...
1092	 */
1093	if (error != 0)
1094		free(pc, M_DEVBUF);
1095	return (error);
1096}
1097
1098static struct resource *
1099psycho_alloc_resource(device_t bus, device_t child, int type, int *rid,
1100    u_long start, u_long end, u_long count, u_int flags)
1101{
1102	struct psycho_softc *sc;
1103	struct resource *rv;
1104	struct rman *rm;
1105	bus_space_tag_t bt;
1106	bus_space_handle_t bh;
1107	int needactivate = flags & RF_ACTIVE;
1108
1109	flags &= ~RF_ACTIVE;
1110
1111	sc = (struct psycho_softc *)device_get_softc(bus);
1112	if (type == SYS_RES_IRQ) {
1113		/*
1114		 * XXX: Don't accept blank ranges for now, only single
1115		 * interrupts. The other case should not happen with the MI pci
1116		 * code...
1117		 * XXX: This may return a resource that is out of the range
1118		 * that was specified. Is this correct...?
1119		 */
1120		if (start != end)
1121			panic("psycho_alloc_resource: XXX: interrupt range");
1122		start = end |= sc->sc_ign;
1123		return (bus_alloc_resource(bus, type, rid, start, end,
1124		    count, flags));
1125	}
1126	switch (type) {
1127	case SYS_RES_MEMORY:
1128		rm = &sc->sc_mem_rman;
1129		bt = sc->sc_memt;
1130		bh = sc->sc_bh[PCI_CS_MEM32];
1131		break;
1132	case SYS_RES_IOPORT:
1133		rm = &sc->sc_io_rman;
1134		bt = sc->sc_iot;
1135		/* XXX: probably should use ranges property here. */
1136		bh = sc->sc_bh[PCI_CS_IO];
1137		break;
1138	default:
1139		return (NULL);
1140	}
1141
1142	rv = rman_reserve_resource(rm, start, end, count, flags, child);
1143	if (rv == NULL)
1144		return (NULL);
1145
1146	bh += rman_get_start(rv);
1147	rman_set_bustag(rv, bt);
1148	rman_set_bushandle(rv, bh);
1149
1150	if (needactivate) {
1151		if (bus_activate_resource(child, type, *rid, rv)) {
1152			rman_release_resource(rv);
1153			return (NULL);
1154		}
1155	}
1156
1157	return (rv);
1158}
1159
1160static int
1161psycho_activate_resource(device_t bus, device_t child, int type, int rid,
1162    struct resource *r)
1163{
1164
1165	if (type == SYS_RES_IRQ)
1166		return (bus_activate_resource(bus, type, rid, r));
1167	return (rman_activate_resource(r));
1168}
1169
1170static int
1171psycho_deactivate_resource(device_t bus, device_t child, int type, int rid,
1172    struct resource *r)
1173{
1174
1175	if (type == SYS_RES_IRQ)
1176		return (bus_deactivate_resource(bus, type, rid, r));
1177	return (rman_deactivate_resource(r));
1178}
1179
1180static int
1181psycho_release_resource(device_t bus, device_t child, int type, int rid,
1182    struct resource *r)
1183{
1184	int error;
1185
1186	if (type == SYS_RES_IRQ)
1187		return (bus_release_resource(bus, type, rid, r));
1188	if (rman_get_flags(r) & RF_ACTIVE) {
1189		error = bus_deactivate_resource(child, type, rid, r);
1190		if (error)
1191			return error;
1192	}
1193	return (rman_release_resource(r));
1194}
1195
1196static int
1197psycho_intr_pending(device_t dev, int intr)
1198{
1199	struct psycho_softc *sc;
1200	u_long diag;
1201
1202	sc = (struct psycho_softc *)device_get_softc(dev);
1203	if (!psycho_find_intrmap(sc, intr, NULL, NULL, &diag)) {
1204		printf("psycho_intr_pending: mapping not found for %d\n", intr);
1205		return (0);
1206	}
1207	return (diag != 0);
1208}
1209
1210static bus_space_handle_t
1211psycho_get_bus_handle(device_t dev, enum sbbt_id id,
1212    bus_space_handle_t childhdl, bus_space_tag_t *tag)
1213{
1214	struct psycho_softc *sc;
1215
1216	sc = (struct psycho_softc *)device_get_softc(dev);
1217	switch(id) {
1218	case SBBT_IO:
1219		*tag = sc->sc_iot;
1220		return (sc->sc_bh[PCI_CS_IO] + childhdl);
1221	case SBBT_MEM:
1222		*tag = sc->sc_memt;
1223		return (sc->sc_bh[PCI_CS_MEM32] + childhdl);
1224	default:
1225		panic("psycho_get_bus_handle: illegal space\n");
1226	}
1227}
1228
1229/*
1230 * below here is bus space and bus dma support
1231 */
1232static bus_space_tag_t
1233psycho_alloc_bus_tag(struct psycho_softc *sc, int type)
1234{
1235	bus_space_tag_t bt;
1236
1237	bt = (bus_space_tag_t)malloc(sizeof(struct bus_space_tag), M_DEVBUF,
1238	    M_NOWAIT | M_ZERO);
1239	if (bt == NULL)
1240		panic("psycho_alloc_bus_tag: out of memory");
1241
1242	bzero(bt, sizeof *bt);
1243	bt->cookie = sc;
1244	bt->parent = sc->sc_bustag;
1245	bt->type = type;
1246	return (bt);
1247}
1248
1249/*
1250 * hooks into the iommu dvma calls.
1251 */
1252static int
1253psycho_dmamem_alloc(bus_dma_tag_t dmat, void **vaddr, int flags, bus_dmamap_t *mapp)
1254{
1255	struct psycho_softc *sc;
1256
1257	sc = (struct psycho_softc *)dmat->cookie;
1258	return (iommu_dvmamem_alloc(dmat, sc->sc_is, vaddr, flags, mapp));
1259}
1260
1261static void
1262psycho_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map)
1263{
1264	struct psycho_softc *sc;
1265
1266	sc = (struct psycho_softc *)dmat->cookie;
1267	iommu_dvmamem_free(dmat, sc->sc_is, vaddr, map);
1268}
1269
1270static int
1271psycho_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp)
1272{
1273	struct psycho_softc *sc;
1274
1275	sc = (struct psycho_softc *)dmat->cookie;
1276	return (iommu_dvmamap_create(dmat, sc->sc_is, flags, mapp));
1277
1278}
1279
1280static int
1281psycho_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map)
1282{
1283	struct psycho_softc *sc;
1284
1285	sc = (struct psycho_softc *)dmat->cookie;
1286	return (iommu_dvmamap_destroy(dmat, sc->sc_is, map));
1287}
1288
1289static int
1290psycho_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
1291    bus_size_t buflen, bus_dmamap_callback_t *callback, void *callback_arg,
1292    int flags)
1293{
1294	struct psycho_softc *sc;
1295
1296	sc = (struct psycho_softc *)dmat->cookie;
1297	return (iommu_dvmamap_load(dmat, sc->sc_is, map, buf, buflen, callback,
1298	    callback_arg, flags));
1299}
1300
1301static void
1302psycho_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map)
1303{
1304	struct psycho_softc *sc;
1305
1306	sc = (struct psycho_softc *)dmat->cookie;
1307	iommu_dvmamap_unload(dmat, sc->sc_is, map);
1308}
1309
1310static void
1311psycho_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map,
1312    bus_dmasync_op_t op)
1313{
1314	struct psycho_softc *sc;
1315
1316	sc = (struct psycho_softc *)dmat->cookie;
1317	iommu_dvmamap_sync(dmat, sc->sc_is, map, op);
1318}
1319