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(®[2]); 34318714Sache mlen = UPA_REG_SIZE(®[2]); 34410760Sache pcictl_offs = UPA_REG_PHYS(®[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(®[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