1/*- 2 * Copyright (c) 1998 The NetBSD Foundation, Inc. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to The NetBSD Foundation 6 * by Paul Kranenburg. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the NetBSD 19 * Foundation, Inc. and its contributors. 20 * 4. Neither the name of The NetBSD Foundation nor the names of its 21 * contributors may be used to endorse or promote products derived 22 * from this software without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 27 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 28 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * POSSIBILITY OF SUCH DAMAGE. 35 */ 36/*- 37 * Copyright (c) 1992, 1993 38 * The Regents of the University of California. All rights reserved. 39 * 40 * This software was developed by the Computer Systems Engineering group 41 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 42 * contributed to Berkeley. 43 * 44 * All advertising materials mentioning features or use of this software 45 * must display the following acknowledgement: 46 * This product includes software developed by the University of 47 * California, Lawrence Berkeley Laboratory. 48 * 49 * Redistribution and use in source and binary forms, with or without 50 * modification, are permitted provided that the following conditions 51 * are met: 52 * 1. Redistributions of source code must retain the above copyright 53 * notice, this list of conditions and the following disclaimer. 54 * 2. Redistributions in binary form must reproduce the above copyright 55 * notice, this list of conditions and the following disclaimer in the 56 * documentation and/or other materials provided with the distribution. 57 * 4. Neither the name of the University nor the names of its contributors 58 * may be used to endorse or promote products derived from this software 59 * without specific prior written permission. 60 * 61 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 62 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 63 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 64 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 65 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 66 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 67 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 68 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 69 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 70 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 71 * SUCH DAMAGE. 72 */ 73/*- 74 * Copyright (c) 1999 Eduardo Horvath 75 * Copyright (c) 2002 by Thomas Moestl <tmm@FreeBSD.org>. 76 * Copyright (c) 2005 Marius Strobl <marius@FreeBSD.org> 77 * All rights reserved. 78 * 79 * Redistribution and use in source and binary forms, with or without 80 * modification, are permitted provided that the following conditions 81 * are met: 82 * 1. Redistributions of source code must retain the above copyright 83 * notice, this list of conditions and the following disclaimer. 84 * 85 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 86 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 87 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 88 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 89 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 90 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 91 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 92 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 93 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 94 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 95 * SUCH DAMAGE. 96 * 97 * from: @(#)sbus.c 8.1 (Berkeley) 6/11/93 98 * from: NetBSD: sbus.c,v 1.46 2001/10/07 20:30:41 eeh Exp 99 */ 100 101#include <sys/cdefs.h>
| 1/*- 2 * Copyright (c) 1998 The NetBSD Foundation, Inc. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to The NetBSD Foundation 6 * by Paul Kranenburg. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the NetBSD 19 * Foundation, Inc. and its contributors. 20 * 4. Neither the name of The NetBSD Foundation nor the names of its 21 * contributors may be used to endorse or promote products derived 22 * from this software without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 27 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 28 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * POSSIBILITY OF SUCH DAMAGE. 35 */ 36/*- 37 * Copyright (c) 1992, 1993 38 * The Regents of the University of California. All rights reserved. 39 * 40 * This software was developed by the Computer Systems Engineering group 41 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 42 * contributed to Berkeley. 43 * 44 * All advertising materials mentioning features or use of this software 45 * must display the following acknowledgement: 46 * This product includes software developed by the University of 47 * California, Lawrence Berkeley Laboratory. 48 * 49 * Redistribution and use in source and binary forms, with or without 50 * modification, are permitted provided that the following conditions 51 * are met: 52 * 1. Redistributions of source code must retain the above copyright 53 * notice, this list of conditions and the following disclaimer. 54 * 2. Redistributions in binary form must reproduce the above copyright 55 * notice, this list of conditions and the following disclaimer in the 56 * documentation and/or other materials provided with the distribution. 57 * 4. Neither the name of the University nor the names of its contributors 58 * may be used to endorse or promote products derived from this software 59 * without specific prior written permission. 60 * 61 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 62 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 63 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 64 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 65 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 66 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 67 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 68 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 69 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 70 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 71 * SUCH DAMAGE. 72 */ 73/*- 74 * Copyright (c) 1999 Eduardo Horvath 75 * Copyright (c) 2002 by Thomas Moestl <tmm@FreeBSD.org>. 76 * Copyright (c) 2005 Marius Strobl <marius@FreeBSD.org> 77 * All rights reserved. 78 * 79 * Redistribution and use in source and binary forms, with or without 80 * modification, are permitted provided that the following conditions 81 * are met: 82 * 1. Redistributions of source code must retain the above copyright 83 * notice, this list of conditions and the following disclaimer. 84 * 85 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 86 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 87 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 88 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 89 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 90 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 91 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 92 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 93 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 94 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 95 * SUCH DAMAGE. 96 * 97 * from: @(#)sbus.c 8.1 (Berkeley) 6/11/93 98 * from: NetBSD: sbus.c,v 1.46 2001/10/07 20:30:41 eeh Exp 99 */ 100 101#include <sys/cdefs.h>
|
103 104/* 105 * SBus support. 106 */ 107 108#include <sys/param.h> 109#include <sys/systm.h> 110#include <sys/bus.h> 111#include <sys/kernel.h> 112#include <sys/malloc.h> 113#include <sys/module.h> 114#include <sys/pcpu.h> 115#include <sys/queue.h> 116#include <sys/reboot.h> 117#include <sys/rman.h> 118 119#include <dev/ofw/ofw_bus.h> 120#include <dev/ofw/ofw_bus_subr.h> 121#include <dev/ofw/openfirm.h> 122 123#include <machine/bus.h> 124#include <machine/bus_common.h> 125#include <machine/bus_private.h> 126#include <machine/iommureg.h> 127#include <machine/iommuvar.h> 128#include <machine/resource.h> 129 130#include <sparc64/sbus/ofw_sbus.h> 131#include <sparc64/sbus/sbusreg.h> 132#include <sparc64/sbus/sbusvar.h> 133 134struct sbus_devinfo { 135 int sdi_burstsz; 136 int sdi_clockfreq; 137 int sdi_slot; 138 139 struct ofw_bus_devinfo sdi_obdinfo; 140 struct resource_list sdi_rl; 141}; 142 143/* Range descriptor, allocated for each sc_range. */ 144struct sbus_rd { 145 bus_addr_t rd_poffset; 146 bus_addr_t rd_pend; 147 int rd_slot; 148 bus_addr_t rd_coffset; 149 bus_addr_t rd_cend; 150 struct rman rd_rman; 151 bus_space_handle_t rd_bushandle; 152 struct resource *rd_res; 153}; 154 155struct sbus_softc { 156 device_t sc_dev; 157 bus_dma_tag_t sc_cdmatag; 158 bus_space_tag_t sc_cbustag; 159 int sc_clockfreq; /* clock frequency (in Hz) */ 160 int sc_nrange; 161 struct sbus_rd *sc_rd; 162 int sc_burst; /* burst transfer sizes supp. */ 163 164 struct resource *sc_sysio_res; 165 int sc_ign; /* IGN for this sysio */ 166 struct iommu_state sc_is; /* IOMMU state (iommuvar.h) */ 167 168 struct resource *sc_ot_ires; 169 void *sc_ot_ihand; 170 struct resource *sc_pf_ires; 171 void *sc_pf_ihand; 172}; 173 174#define SYSIO_READ8(sc, off) \ 175 bus_read_8((sc)->sc_sysio_res, (off)) 176#define SYSIO_WRITE8(sc, off, v) \ 177 bus_write_8((sc)->sc_sysio_res, (off), (v)) 178 179static device_probe_t sbus_probe; 180static device_attach_t sbus_attach; 181static bus_print_child_t sbus_print_child; 182static bus_probe_nomatch_t sbus_probe_nomatch; 183static bus_read_ivar_t sbus_read_ivar; 184static bus_get_resource_list_t sbus_get_resource_list; 185static bus_setup_intr_t sbus_setup_intr; 186static bus_alloc_resource_t sbus_alloc_resource; 187static bus_release_resource_t sbus_release_resource; 188static bus_activate_resource_t sbus_activate_resource; 189static bus_deactivate_resource_t sbus_deactivate_resource; 190static bus_get_dma_tag_t sbus_get_dma_tag; 191static ofw_bus_get_devinfo_t sbus_get_devinfo; 192 193static int sbus_inlist(const char *, const char **); 194static struct sbus_devinfo * sbus_setup_dinfo(device_t, struct sbus_softc *, 195 phandle_t); 196static void sbus_destroy_dinfo(struct sbus_devinfo *); 197static void sbus_intr_enable(void *); 198static void sbus_intr_disable(void *); 199static void sbus_intr_assign(void *); 200static void sbus_intr_clear(void *); 201static int sbus_find_intrmap(struct sbus_softc *, u_int, bus_addr_t *, 202 bus_addr_t *); 203static bus_space_tag_t sbus_alloc_bustag(struct sbus_softc *); 204static driver_intr_t sbus_overtemp; 205static driver_intr_t sbus_pwrfail; 206static int sbus_print_res(struct sbus_devinfo *); 207 208static device_method_t sbus_methods[] = { 209 /* Device interface */ 210 DEVMETHOD(device_probe, sbus_probe), 211 DEVMETHOD(device_attach, sbus_attach), 212 DEVMETHOD(device_shutdown, bus_generic_shutdown), 213 DEVMETHOD(device_suspend, bus_generic_suspend), 214 DEVMETHOD(device_resume, bus_generic_resume), 215 216 /* Bus interface */ 217 DEVMETHOD(bus_print_child, sbus_print_child), 218 DEVMETHOD(bus_probe_nomatch, sbus_probe_nomatch), 219 DEVMETHOD(bus_read_ivar, sbus_read_ivar), 220 DEVMETHOD(bus_setup_intr, sbus_setup_intr), 221 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 222 DEVMETHOD(bus_alloc_resource, sbus_alloc_resource), 223 DEVMETHOD(bus_activate_resource, sbus_activate_resource), 224 DEVMETHOD(bus_deactivate_resource, sbus_deactivate_resource), 225 DEVMETHOD(bus_release_resource, sbus_release_resource), 226 DEVMETHOD(bus_get_resource_list, sbus_get_resource_list), 227 DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), 228 DEVMETHOD(bus_get_dma_tag, sbus_get_dma_tag), 229 230 /* ofw_bus interface */ 231 DEVMETHOD(ofw_bus_get_devinfo, sbus_get_devinfo), 232 DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), 233 DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), 234 DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), 235 DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), 236 DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), 237 238 { 0, 0 } 239}; 240 241static driver_t sbus_driver = { 242 "sbus", 243 sbus_methods, 244 sizeof(struct sbus_softc), 245}; 246 247static devclass_t sbus_devclass; 248 249DRIVER_MODULE(sbus, nexus, sbus_driver, sbus_devclass, 0, 0);
| 103 104/* 105 * SBus support. 106 */ 107 108#include <sys/param.h> 109#include <sys/systm.h> 110#include <sys/bus.h> 111#include <sys/kernel.h> 112#include <sys/malloc.h> 113#include <sys/module.h> 114#include <sys/pcpu.h> 115#include <sys/queue.h> 116#include <sys/reboot.h> 117#include <sys/rman.h> 118 119#include <dev/ofw/ofw_bus.h> 120#include <dev/ofw/ofw_bus_subr.h> 121#include <dev/ofw/openfirm.h> 122 123#include <machine/bus.h> 124#include <machine/bus_common.h> 125#include <machine/bus_private.h> 126#include <machine/iommureg.h> 127#include <machine/iommuvar.h> 128#include <machine/resource.h> 129 130#include <sparc64/sbus/ofw_sbus.h> 131#include <sparc64/sbus/sbusreg.h> 132#include <sparc64/sbus/sbusvar.h> 133 134struct sbus_devinfo { 135 int sdi_burstsz; 136 int sdi_clockfreq; 137 int sdi_slot; 138 139 struct ofw_bus_devinfo sdi_obdinfo; 140 struct resource_list sdi_rl; 141}; 142 143/* Range descriptor, allocated for each sc_range. */ 144struct sbus_rd { 145 bus_addr_t rd_poffset; 146 bus_addr_t rd_pend; 147 int rd_slot; 148 bus_addr_t rd_coffset; 149 bus_addr_t rd_cend; 150 struct rman rd_rman; 151 bus_space_handle_t rd_bushandle; 152 struct resource *rd_res; 153}; 154 155struct sbus_softc { 156 device_t sc_dev; 157 bus_dma_tag_t sc_cdmatag; 158 bus_space_tag_t sc_cbustag; 159 int sc_clockfreq; /* clock frequency (in Hz) */ 160 int sc_nrange; 161 struct sbus_rd *sc_rd; 162 int sc_burst; /* burst transfer sizes supp. */ 163 164 struct resource *sc_sysio_res; 165 int sc_ign; /* IGN for this sysio */ 166 struct iommu_state sc_is; /* IOMMU state (iommuvar.h) */ 167 168 struct resource *sc_ot_ires; 169 void *sc_ot_ihand; 170 struct resource *sc_pf_ires; 171 void *sc_pf_ihand; 172}; 173 174#define SYSIO_READ8(sc, off) \ 175 bus_read_8((sc)->sc_sysio_res, (off)) 176#define SYSIO_WRITE8(sc, off, v) \ 177 bus_write_8((sc)->sc_sysio_res, (off), (v)) 178 179static device_probe_t sbus_probe; 180static device_attach_t sbus_attach; 181static bus_print_child_t sbus_print_child; 182static bus_probe_nomatch_t sbus_probe_nomatch; 183static bus_read_ivar_t sbus_read_ivar; 184static bus_get_resource_list_t sbus_get_resource_list; 185static bus_setup_intr_t sbus_setup_intr; 186static bus_alloc_resource_t sbus_alloc_resource; 187static bus_release_resource_t sbus_release_resource; 188static bus_activate_resource_t sbus_activate_resource; 189static bus_deactivate_resource_t sbus_deactivate_resource; 190static bus_get_dma_tag_t sbus_get_dma_tag; 191static ofw_bus_get_devinfo_t sbus_get_devinfo; 192 193static int sbus_inlist(const char *, const char **); 194static struct sbus_devinfo * sbus_setup_dinfo(device_t, struct sbus_softc *, 195 phandle_t); 196static void sbus_destroy_dinfo(struct sbus_devinfo *); 197static void sbus_intr_enable(void *); 198static void sbus_intr_disable(void *); 199static void sbus_intr_assign(void *); 200static void sbus_intr_clear(void *); 201static int sbus_find_intrmap(struct sbus_softc *, u_int, bus_addr_t *, 202 bus_addr_t *); 203static bus_space_tag_t sbus_alloc_bustag(struct sbus_softc *); 204static driver_intr_t sbus_overtemp; 205static driver_intr_t sbus_pwrfail; 206static int sbus_print_res(struct sbus_devinfo *); 207 208static device_method_t sbus_methods[] = { 209 /* Device interface */ 210 DEVMETHOD(device_probe, sbus_probe), 211 DEVMETHOD(device_attach, sbus_attach), 212 DEVMETHOD(device_shutdown, bus_generic_shutdown), 213 DEVMETHOD(device_suspend, bus_generic_suspend), 214 DEVMETHOD(device_resume, bus_generic_resume), 215 216 /* Bus interface */ 217 DEVMETHOD(bus_print_child, sbus_print_child), 218 DEVMETHOD(bus_probe_nomatch, sbus_probe_nomatch), 219 DEVMETHOD(bus_read_ivar, sbus_read_ivar), 220 DEVMETHOD(bus_setup_intr, sbus_setup_intr), 221 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 222 DEVMETHOD(bus_alloc_resource, sbus_alloc_resource), 223 DEVMETHOD(bus_activate_resource, sbus_activate_resource), 224 DEVMETHOD(bus_deactivate_resource, sbus_deactivate_resource), 225 DEVMETHOD(bus_release_resource, sbus_release_resource), 226 DEVMETHOD(bus_get_resource_list, sbus_get_resource_list), 227 DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), 228 DEVMETHOD(bus_get_dma_tag, sbus_get_dma_tag), 229 230 /* ofw_bus interface */ 231 DEVMETHOD(ofw_bus_get_devinfo, sbus_get_devinfo), 232 DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), 233 DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), 234 DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), 235 DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), 236 DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), 237 238 { 0, 0 } 239}; 240 241static driver_t sbus_driver = { 242 "sbus", 243 sbus_methods, 244 sizeof(struct sbus_softc), 245}; 246 247static devclass_t sbus_devclass; 248 249DRIVER_MODULE(sbus, nexus, sbus_driver, sbus_devclass, 0, 0);
|
250 251#define OFW_SBUS_TYPE "sbus" 252#define OFW_SBUS_NAME "sbus" 253 254static const struct intr_controller sbus_ic = { 255 sbus_intr_enable, 256 sbus_intr_disable, 257 sbus_intr_assign, 258 sbus_intr_clear 259}; 260 261struct sbus_icarg { 262 struct sbus_softc *sica_sc; 263 bus_addr_t sica_map; 264 bus_addr_t sica_clr; 265}; 266 267static const char *sbus_order_first[] = { 268 "auxio", 269 "dma", 270 NULL 271}; 272 273static int 274sbus_inlist(const char *name, const char **list) 275{ 276 int i; 277 278 if (name == NULL) 279 return (0); 280 for (i = 0; list[i] != NULL; i++) { 281 if (strcmp(name, list[i]) == 0) 282 return (1); 283 } 284 return (0); 285} 286 287static int 288sbus_probe(device_t dev) 289{ 290 const char *t; 291 292 t = ofw_bus_get_type(dev); 293 if (((t == NULL || strcmp(t, OFW_SBUS_TYPE) != 0)) && 294 strcmp(ofw_bus_get_name(dev), OFW_SBUS_NAME) != 0) 295 return (ENXIO); 296 device_set_desc(dev, "U2S UPA-SBus bridge"); 297 return (0); 298} 299 300static int 301sbus_attach(device_t dev) 302{ 303 struct sbus_softc *sc; 304 struct sbus_devinfo *sdi; 305 struct sbus_icarg *sica; 306 struct sbus_ranges *range; 307 struct resource *res; 308 struct resource_list *rl; 309 device_t cdev; 310 bus_addr_t intrclr, intrmap, phys; 311 bus_size_t size; 312 u_long vec; 313 phandle_t child, node; 314 int clock, i, intr, rid; 315 316 sc = device_get_softc(dev); 317 sc->sc_dev = dev; 318 node = ofw_bus_get_node(dev); 319 320 rid = 0; 321 sc->sc_sysio_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 322 RF_ACTIVE); 323 if (sc->sc_sysio_res == NULL) 324 panic("%s: cannot allocate device memory", __func__); 325 326 if (OF_getprop(node, "interrupts", &intr, sizeof(intr)) == -1) 327 panic("%s: cannot get IGN", __func__); 328 sc->sc_ign = INTIGN(intr); 329 sc->sc_cbustag = sbus_alloc_bustag(sc); 330 331 /* 332 * Record clock frequency for synchronous SCSI. 333 * IS THIS THE CORRECT DEFAULT?? 334 */ 335 if (OF_getprop(node, "clock-frequency", &clock, sizeof(clock)) == -1) 336 clock = 25000000; 337 sc->sc_clockfreq = clock; 338 clock /= 1000; 339 device_printf(dev, "clock %d.%03d MHz\n", clock / 1000, clock % 1000); 340 341 /* 342 * Collect address translations from the OBP. 343 */ 344 if ((sc->sc_nrange = OF_getprop_alloc(node, "ranges", 345 sizeof(*range), (void **)&range)) == -1) { 346 panic("%s: error getting ranges property", __func__); 347 } 348 sc->sc_rd = (struct sbus_rd *)malloc(sizeof(*sc->sc_rd) * sc->sc_nrange, 349 M_DEVBUF, M_NOWAIT); 350 if (sc->sc_rd == NULL) 351 panic("%s: cannot allocate rmans", __func__); 352 /* 353 * Preallocate all space that the SBus bridge decodes, so that nothing 354 * else gets in the way; set up rmans etc. 355 */ 356 rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev); 357 for (i = 0; i < sc->sc_nrange; i++) { 358 phys = range[i].poffset | ((bus_addr_t)range[i].pspace << 32); 359 size = range[i].size; 360 sc->sc_rd[i].rd_slot = range[i].cspace; 361 sc->sc_rd[i].rd_coffset = range[i].coffset; 362 sc->sc_rd[i].rd_cend = sc->sc_rd[i].rd_coffset + size; 363 rid = resource_list_add_next(rl, SYS_RES_MEMORY, phys, 364 phys + size - 1, size); 365 if ((res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 366 RF_ACTIVE)) == NULL) 367 panic("%s: cannot allocate decoded range", __func__); 368 sc->sc_rd[i].rd_bushandle = rman_get_bushandle(res); 369 sc->sc_rd[i].rd_rman.rm_type = RMAN_ARRAY; 370 sc->sc_rd[i].rd_rman.rm_descr = "SBus Device Memory"; 371 if (rman_init(&sc->sc_rd[i].rd_rman) != 0 || 372 rman_manage_region(&sc->sc_rd[i].rd_rman, 0, size) != 0) 373 panic("%s: failed to set up memory rman", __func__); 374 sc->sc_rd[i].rd_poffset = phys; 375 sc->sc_rd[i].rd_pend = phys + size; 376 sc->sc_rd[i].rd_res = res; 377 } 378 free(range, M_OFWPROP); 379 380 /* 381 * Get the SBus burst transfer size if burst transfers are supported. 382 * XXX: is the default correct? 383 */ 384 if (OF_getprop(node, "burst-sizes", &sc->sc_burst, 385 sizeof(sc->sc_burst)) == -1 || sc->sc_burst == 0) 386 sc->sc_burst = SBUS_BURST_DEF; 387 388 /* initalise the IOMMU */ 389 390 /* punch in our copies */ 391 sc->sc_is.is_pmaxaddr = IOMMU_MAXADDR(SBUS_IOMMU_BITS); 392 sc->sc_is.is_bustag = rman_get_bustag(sc->sc_sysio_res); 393 sc->sc_is.is_bushandle = rman_get_bushandle(sc->sc_sysio_res); 394 sc->sc_is.is_iommu = SBR_IOMMU; 395 sc->sc_is.is_dtag = SBR_IOMMU_TLB_TAG_DIAG; 396 sc->sc_is.is_ddram = SBR_IOMMU_TLB_DATA_DIAG; 397 sc->sc_is.is_dqueue = SBR_IOMMU_QUEUE_DIAG; 398 sc->sc_is.is_dva = SBR_IOMMU_SVADIAG; 399 sc->sc_is.is_dtcmp = 0; 400 sc->sc_is.is_sb[0] = SBR_STRBUF; 401 sc->sc_is.is_sb[1] = 0; 402 403 /* 404 * Note: the SBus IOMMU ignores the high bits of an address, so a NULL 405 * DMA pointer will be translated by the first page of the IOTSB. 406 * To detect bugs we'll allocate and ignore the first entry. 407 */ 408 iommu_init(device_get_nameunit(dev), &sc->sc_is, 3, -1, 1); 409 410 /* Create the DMA tag. */ 411 if (bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0, 412 sc->sc_is.is_pmaxaddr, ~0, NULL, NULL, sc->sc_is.is_pmaxaddr, 413 0xff, 0xffffffff, 0, NULL, NULL, &sc->sc_cdmatag) != 0) 414 panic("%s: bus_dma_tag_create failed", __func__); 415 /* Customize the tag. */ 416 sc->sc_cdmatag->dt_cookie = &sc->sc_is; 417 sc->sc_cdmatag->dt_mt = &iommu_dma_methods; 418 419 /* 420 * Hunt through all the interrupt mapping regs and register our 421 * interrupt controller for the corresponding interrupt vectors. 422 */ 423 for (i = 0; i <= SBUS_MAX_INO; i++) { 424 if (sbus_find_intrmap(sc, i, &intrmap, &intrclr) == 0) 425 continue; 426 sica = malloc(sizeof(*sica), M_DEVBUF, M_NOWAIT); 427 if (sica == NULL) 428 panic("%s: could not allocate interrupt controller " 429 "argument", __func__); 430 sica->sica_sc = sc; 431 sica->sica_map = intrmap; 432 sica->sica_clr = intrclr; 433#ifdef SBUS_DEBUG 434 device_printf(dev, 435 "intr map (INO %d, %s) %#lx: %#lx, clr: %#lx\n", 436 i, (i & INTMAP_OBIO_MASK) == 0 ? "SBus slot" : "OBIO", 437 (u_long)intrmap, (u_long)SYSIO_READ8(sc, intrmap), 438 (u_long)intrclr); 439#endif 440 if (intr_controller_register(INTMAP_VEC(sc->sc_ign, i), 441 &sbus_ic, sica) != 0) 442 panic("%s: could not register interrupt controller " 443 "for INO %d", __func__, i); 444 } 445 446 /* Enable the over-temperature and power-fail interrupts. */ 447 rid = 4; 448 sc->sc_ot_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 449 RF_ACTIVE); 450 if (sc->sc_ot_ires == NULL || 451 INTIGN(vec = rman_get_start(sc->sc_ot_ires)) != sc->sc_ign || 452 INTVEC(SYSIO_READ8(sc, SBR_THERM_INT_MAP)) != vec || 453 intr_vectors[vec].iv_ic != &sbus_ic || 454 bus_setup_intr(dev, sc->sc_ot_ires, INTR_TYPE_MISC, 455 NULL, sbus_overtemp, sc, &sc->sc_ot_ihand) != 0) 456 panic("%s: failed to set up temperature interrupt", __func__); 457 rid = 3; 458 sc->sc_pf_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 459 RF_ACTIVE); 460 if (sc->sc_pf_ires == NULL || 461 INTIGN(vec = rman_get_start(sc->sc_pf_ires)) != sc->sc_ign || 462 INTVEC(SYSIO_READ8(sc, SBR_POWER_INT_MAP)) != vec || 463 intr_vectors[vec].iv_ic != &sbus_ic || 464 bus_setup_intr(dev, sc->sc_pf_ires, INTR_TYPE_MISC, 465 NULL, sbus_pwrfail, sc, &sc->sc_pf_ihand) != 0) 466 panic("%s: failed to set up power fail interrupt", __func__); 467 468 /* Initialize the counter-timer. */ 469 sparc64_counter_init(device_get_nameunit(dev), 470 rman_get_bustag(sc->sc_sysio_res), 471 rman_get_bushandle(sc->sc_sysio_res), SBR_TC0); 472 473 /* 474 * Loop through ROM children, fixing any relative addresses 475 * and then configuring each device. 476 */ 477 for (child = OF_child(node); child != 0; child = OF_peer(child)) { 478 if ((sdi = sbus_setup_dinfo(dev, sc, child)) == NULL) 479 continue; 480 /* 481 * For devices where there are variants that are actually 482 * split into two SBus devices (as opposed to the first 483 * half of the device being a SBus device and the second 484 * half hanging off of the first one) like 'auxio' and 485 * 'SUNW,fdtwo' or 'dma' and 'esp' probe the SBus device 486 * which is a prerequisite to the driver attaching to the 487 * second one with a lower order. Saves us from dealing 488 * with different probe orders in the respective device 489 * drivers which generally is more hackish. 490 */ 491 cdev = device_add_child_ordered(dev, (OF_child(child) == 0 && 492 sbus_inlist(sdi->sdi_obdinfo.obd_name, sbus_order_first)) ? 493 SBUS_ORDER_FIRST : SBUS_ORDER_NORMAL, NULL, -1); 494 if (cdev == NULL) { 495 device_printf(dev, 496 "<%s>: device_add_child_ordered failed\n", 497 sdi->sdi_obdinfo.obd_name); 498 sbus_destroy_dinfo(sdi); 499 continue; 500 } 501 device_set_ivars(cdev, sdi); 502 } 503 return (bus_generic_attach(dev)); 504} 505 506static struct sbus_devinfo * 507sbus_setup_dinfo(device_t dev, struct sbus_softc *sc, phandle_t node) 508{ 509 struct sbus_devinfo *sdi; 510 struct sbus_regs *reg; 511 u_int32_t base, iv, *intr; 512 int i, nreg, nintr, slot, rslot; 513 514 sdi = malloc(sizeof(*sdi), M_DEVBUF, M_ZERO | M_WAITOK); 515 if (ofw_bus_gen_setup_devinfo(&sdi->sdi_obdinfo, node) != 0) { 516 free(sdi, M_DEVBUF); 517 return (NULL); 518 } 519 resource_list_init(&sdi->sdi_rl); 520 slot = -1; 521 nreg = OF_getprop_alloc(node, "reg", sizeof(*reg), (void **)®); 522 if (nreg == -1) { 523 if (sdi->sdi_obdinfo.obd_type == NULL || 524 strcmp(sdi->sdi_obdinfo.obd_type, "hierarchical") != 0) { 525 device_printf(dev, "<%s>: incomplete\n", 526 sdi->sdi_obdinfo.obd_name); 527 goto fail; 528 } 529 } else { 530 for (i = 0; i < nreg; i++) { 531 base = reg[i].sbr_offset; 532 if (SBUS_ABS(base)) { 533 rslot = SBUS_ABS_TO_SLOT(base); 534 base = SBUS_ABS_TO_OFFSET(base); 535 } else 536 rslot = reg[i].sbr_slot; 537 if (slot != -1 && slot != rslot) { 538 device_printf(dev, "<%s>: multiple slots\n", 539 sdi->sdi_obdinfo.obd_name); 540 free(reg, M_OFWPROP); 541 goto fail; 542 } 543 slot = rslot; 544 545 resource_list_add(&sdi->sdi_rl, SYS_RES_MEMORY, i, 546 base, base + reg[i].sbr_size, reg[i].sbr_size); 547 } 548 free(reg, M_OFWPROP); 549 } 550 sdi->sdi_slot = slot; 551 552 /* 553 * The `interrupts' property contains the SBus interrupt level. 554 */ 555 nintr = OF_getprop_alloc(node, "interrupts", sizeof(*intr), 556 (void **)&intr); 557 if (nintr != -1) { 558 for (i = 0; i < nintr; i++) { 559 iv = intr[i]; 560 /* 561 * SBus card devices need the slot number encoded into 562 * the vector as this is generally not done. 563 */ 564 if ((iv & INTMAP_OBIO_MASK) == 0) 565 iv |= slot << 3; 566 iv = INTMAP_VEC(sc->sc_ign, iv); 567 resource_list_add(&sdi->sdi_rl, SYS_RES_IRQ, i, 568 iv, iv, 1); 569 } 570 free(intr, M_OFWPROP); 571 } 572 if (OF_getprop(node, "burst-sizes", &sdi->sdi_burstsz, 573 sizeof(sdi->sdi_burstsz)) == -1) 574 sdi->sdi_burstsz = sc->sc_burst; 575 else 576 sdi->sdi_burstsz &= sc->sc_burst; 577 if (OF_getprop(node, "clock-frequency", &sdi->sdi_clockfreq, 578 sizeof(sdi->sdi_clockfreq)) == -1) 579 sdi->sdi_clockfreq = sc->sc_clockfreq; 580 581 return (sdi); 582 583fail: 584 sbus_destroy_dinfo(sdi); 585 return (NULL); 586} 587 588static void 589sbus_destroy_dinfo(struct sbus_devinfo *dinfo) 590{ 591 592 resource_list_free(&dinfo->sdi_rl); 593 ofw_bus_gen_destroy_devinfo(&dinfo->sdi_obdinfo); 594 free(dinfo, M_DEVBUF); 595} 596 597static int 598sbus_print_child(device_t dev, device_t child) 599{ 600 int rv; 601 602 rv = bus_print_child_header(dev, child); 603 rv += sbus_print_res(device_get_ivars(child)); 604 rv += bus_print_child_footer(dev, child); 605 return (rv); 606} 607 608static void 609sbus_probe_nomatch(device_t dev, device_t child) 610{ 611 const char *type; 612 613 device_printf(dev, "<%s>", ofw_bus_get_name(child)); 614 sbus_print_res(device_get_ivars(child)); 615 type = ofw_bus_get_type(child); 616 printf(" type %s (no driver attached)\n", 617 type != NULL ? type : "unknown"); 618} 619 620static int 621sbus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 622{ 623 struct sbus_softc *sc; 624 struct sbus_devinfo *dinfo; 625 626 sc = device_get_softc(dev); 627 if ((dinfo = device_get_ivars(child)) == NULL) 628 return (ENOENT); 629 switch (which) { 630 case SBUS_IVAR_BURSTSZ: 631 *result = dinfo->sdi_burstsz; 632 break; 633 case SBUS_IVAR_CLOCKFREQ: 634 *result = dinfo->sdi_clockfreq; 635 break; 636 case SBUS_IVAR_IGN: 637 *result = sc->sc_ign; 638 break; 639 case SBUS_IVAR_SLOT: 640 *result = dinfo->sdi_slot; 641 break; 642 default: 643 return (ENOENT); 644 } 645 return (0); 646} 647 648static struct resource_list * 649sbus_get_resource_list(device_t dev, device_t child) 650{ 651 struct sbus_devinfo *sdi; 652 653 sdi = device_get_ivars(child); 654 return (&sdi->sdi_rl); 655} 656 657static void 658sbus_intr_enable(void *arg) 659{ 660 struct intr_vector *iv = arg; 661 struct sbus_icarg *sica = iv->iv_icarg; 662 663 SYSIO_WRITE8(sica->sica_sc, sica->sica_map, 664 INTMAP_ENABLE(iv->iv_vec, iv->iv_mid)); 665} 666 667static void 668sbus_intr_disable(void *arg) 669{ 670 struct intr_vector *iv = arg; 671 struct sbus_icarg *sica = iv->iv_icarg; 672 673 SYSIO_WRITE8(sica->sica_sc, sica->sica_map, iv->iv_vec); 674} 675 676static void 677sbus_intr_assign(void *arg) 678{ 679 struct intr_vector *iv = arg; 680 struct sbus_icarg *sica = iv->iv_icarg; 681 682 SYSIO_WRITE8(sica->sica_sc, sica->sica_map, INTMAP_TID( 683 SYSIO_READ8(sica->sica_sc, sica->sica_map), iv->iv_mid)); 684} 685 686static void 687sbus_intr_clear(void *arg) 688{ 689 struct intr_vector *iv = arg; 690 struct sbus_icarg *sica = iv->iv_icarg; 691 692 SYSIO_WRITE8(sica->sica_sc, sica->sica_clr, 0); 693} 694 695static int 696sbus_find_intrmap(struct sbus_softc *sc, u_int ino, bus_addr_t *intrmapptr, 697 bus_addr_t *intrclrptr) 698{ 699 bus_addr_t intrclr, intrmap; 700 int i; 701 702 if (ino > SBUS_MAX_INO) { 703 device_printf(sc->sc_dev, "out of range INO %d requested\n", 704 ino); 705 return (0); 706 } 707 708 if ((ino & INTMAP_OBIO_MASK) == 0) { 709 intrmap = SBR_SLOT0_INT_MAP + INTSLOT(ino) * 8; 710 intrclr = SBR_SLOT0_INT_CLR + 711 (INTSLOT(ino) * 8 * 8) + (INTPRI(ino) * 8); 712 } else { 713 intrclr = 0; 714 for (i = 0, intrmap = SBR_SCSI_INT_MAP; 715 intrmap <= SBR_RESERVED_INT_MAP; intrmap += 8, i++) { 716 if (INTVEC(SYSIO_READ8(sc, intrmap)) == 717 INTMAP_VEC(sc->sc_ign, ino)) { 718 intrclr = SBR_SCSI_INT_CLR + i * 8; 719 break; 720 } 721 } 722 if (intrclr == 0) 723 return (0); 724 } 725 if (intrmapptr != NULL) 726 *intrmapptr = intrmap; 727 if (intrclrptr != NULL) 728 *intrclrptr = intrclr; 729 return (1); 730} 731 732static int 733sbus_setup_intr(device_t dev, device_t child, struct resource *ires, int flags, 734 driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep) 735{ 736 struct sbus_softc *sc; 737 u_long vec; 738 739 sc = device_get_softc(dev); 740 /* 741 * Make sure the vector is fully specified and we registered 742 * our interrupt controller for it. 743 */ 744 vec = rman_get_start(ires); 745 if (INTIGN(vec) != sc->sc_ign || intr_vectors[vec].iv_ic != &sbus_ic) { 746 device_printf(dev, "invalid interrupt vector 0x%lx\n", vec); 747 return (EINVAL); 748 } 749 return (bus_generic_setup_intr(dev, child, ires, flags, filt, intr, 750 arg, cookiep)); 751} 752 753static struct resource * 754sbus_alloc_resource(device_t bus, device_t child, int type, int *rid, 755 u_long start, u_long end, u_long count, u_int flags) 756{ 757 struct sbus_softc *sc; 758 struct rman *rm; 759 struct resource *rv; 760 struct resource_list *rl; 761 struct resource_list_entry *rle; 762 device_t schild; 763 bus_space_handle_t bh; 764 bus_addr_t toffs; 765 bus_size_t tend; 766 int i, slot; 767 int isdefault, needactivate, passthrough; 768 769 isdefault = (start == 0UL && end == ~0UL); 770 needactivate = flags & RF_ACTIVE; 771 passthrough = (device_get_parent(child) != bus); 772 rle = NULL; 773 sc = device_get_softc(bus); 774 rl = BUS_GET_RESOURCE_LIST(bus, child); 775 switch (type) { 776 case SYS_RES_IRQ: 777 return (resource_list_alloc(rl, bus, child, type, rid, start, 778 end, count, flags)); 779 case SYS_RES_MEMORY: 780 if (!passthrough) { 781 rle = resource_list_find(rl, type, *rid); 782 if (rle == NULL) 783 return (NULL); 784 if (rle->res != NULL) 785 panic("%s: resource entry is busy", __func__); 786 if (isdefault) { 787 start = rle->start; 788 count = ulmax(count, rle->count); 789 end = ulmax(rle->end, start + count - 1); 790 } 791 } 792 rm = NULL; 793 bh = toffs = tend = 0; 794 schild = child; 795 while (device_get_parent(schild) != bus) 796 schild = device_get_parent(schild); 797 slot = sbus_get_slot(schild); 798 for (i = 0; i < sc->sc_nrange; i++) { 799 if (sc->sc_rd[i].rd_slot != slot || 800 start < sc->sc_rd[i].rd_coffset || 801 start > sc->sc_rd[i].rd_cend) 802 continue; 803 /* Disallow cross-range allocations. */ 804 if (end > sc->sc_rd[i].rd_cend) 805 return (NULL); 806 /* We've found the connection to the parent bus */ 807 toffs = start - sc->sc_rd[i].rd_coffset; 808 tend = end - sc->sc_rd[i].rd_coffset; 809 rm = &sc->sc_rd[i].rd_rman; 810 bh = sc->sc_rd[i].rd_bushandle; 811 break; 812 } 813 if (rm == NULL) 814 return (NULL); 815 flags &= ~RF_ACTIVE; 816 rv = rman_reserve_resource(rm, toffs, tend, count, flags, 817 child); 818 if (rv == NULL) 819 return (NULL); 820 rman_set_rid(rv, *rid); 821 rman_set_bustag(rv, sc->sc_cbustag); 822 rman_set_bushandle(rv, bh + rman_get_start(rv)); 823 if (needactivate) { 824 if (bus_activate_resource(child, type, *rid, rv)) { 825 rman_release_resource(rv); 826 return (NULL); 827 } 828 } 829 if (!passthrough) 830 rle->res = rv; 831 return (rv); 832 default: 833 return (NULL); 834 } 835} 836 837static int 838sbus_activate_resource(device_t bus, device_t child, int type, int rid, 839 struct resource *r) 840{ 841 void *p; 842 int error; 843 844 if (type == SYS_RES_IRQ) { 845 return (BUS_ACTIVATE_RESOURCE(device_get_parent(bus), 846 child, type, rid, r)); 847 } 848 if (type == SYS_RES_MEMORY) { 849 /* 850 * Need to memory-map the device space, as some drivers depend 851 * on the virtual address being set and useable. 852 */ 853 error = sparc64_bus_mem_map(rman_get_bustag(r), 854 rman_get_bushandle(r), rman_get_size(r), 0, 0, &p); 855 if (error != 0) 856 return (error); 857 rman_set_virtual(r, p); 858 } 859 return (rman_activate_resource(r)); 860} 861 862static int 863sbus_deactivate_resource(device_t bus, device_t child, int type, int rid, 864 struct resource *r) 865{ 866 867 if (type == SYS_RES_IRQ) { 868 return (BUS_DEACTIVATE_RESOURCE(device_get_parent(bus), 869 child, type, rid, r)); 870 } 871 if (type == SYS_RES_MEMORY) { 872 sparc64_bus_mem_unmap(rman_get_virtual(r), rman_get_size(r)); 873 rman_set_virtual(r, NULL); 874 } 875 return (rman_deactivate_resource(r)); 876} 877 878static int 879sbus_release_resource(device_t bus, device_t child, int type, int rid, 880 struct resource *r) 881{ 882 struct resource_list *rl; 883 struct resource_list_entry *rle; 884 int error, passthrough; 885 886 passthrough = (device_get_parent(child) != bus); 887 rl = BUS_GET_RESOURCE_LIST(bus, child); 888 if (type == SYS_RES_IRQ) 889 return (resource_list_release(rl, bus, child, type, rid, r)); 890 if ((rman_get_flags(r) & RF_ACTIVE) != 0) { 891 error = bus_deactivate_resource(child, type, rid, r); 892 if (error != 0) 893 return (error); 894 } 895 error = rman_release_resource(r); 896 if (error != 0 || passthrough) 897 return (error); 898 rle = resource_list_find(rl, type, rid); 899 if (rle == NULL) 900 panic("%s: cannot find resource", __func__); 901 if (rle->res == NULL) 902 panic("%s: resource entry is not busy", __func__); 903 rle->res = NULL; 904 return (0); 905} 906 907static bus_dma_tag_t 908sbus_get_dma_tag(device_t bus, device_t child) 909{ 910 struct sbus_softc *sc; 911 912 sc = device_get_softc(bus); 913 return (sc->sc_cdmatag); 914} 915 916static const struct ofw_bus_devinfo * 917sbus_get_devinfo(device_t bus, device_t child) 918{ 919 struct sbus_devinfo *sdi; 920 921 sdi = device_get_ivars(child); 922 return (&sdi->sdi_obdinfo); 923} 924 925/* 926 * Handle an overtemp situation. 927 * 928 * SPARCs have temperature sensors which generate interrupts 929 * if the machine's temperature exceeds a certain threshold. 930 * This handles the interrupt and powers off the machine. 931 * The same needs to be done to PCI controller drivers. 932 */ 933static void 934sbus_overtemp(void *arg) 935{ 936 static int shutdown; 937 938 /* As the interrupt is cleared we may be called multiple times. */ 939 if (shutdown != 0) 940 return; 941 shutdown++; 942 printf("DANGER: OVER TEMPERATURE detected\nShutting down NOW.\n"); 943 shutdown_nice(RB_POWEROFF); 944} 945 946/* Try to shut down in time in case of power failure. */ 947static void 948sbus_pwrfail(void *arg) 949{ 950 static int shutdown; 951 952 /* As the interrupt is cleared we may be called multiple times. */ 953 if (shutdown != 0) 954 return; 955 shutdown++; 956 printf("Power failure detected\nShutting down NOW.\n"); 957 shutdown_nice(0); 958} 959 960static bus_space_tag_t 961sbus_alloc_bustag(struct sbus_softc *sc) 962{ 963 bus_space_tag_t sbt; 964 965 sbt = (bus_space_tag_t)malloc(sizeof(struct bus_space_tag), M_DEVBUF, 966 M_NOWAIT | M_ZERO); 967 if (sbt == NULL) 968 panic("%s: out of memory", __func__); 969 970 sbt->bst_cookie = sc; 971 sbt->bst_parent = rman_get_bustag(sc->sc_sysio_res); 972 sbt->bst_type = SBUS_BUS_SPACE; 973 return (sbt); 974} 975 976static int 977sbus_print_res(struct sbus_devinfo *sdi) 978{ 979 int rv; 980 981 rv = 0; 982 rv += resource_list_print_type(&sdi->sdi_rl, "mem", SYS_RES_MEMORY, 983 "%#lx"); 984 rv += resource_list_print_type(&sdi->sdi_rl, "irq", SYS_RES_IRQ, 985 "%ld"); 986 return (rv); 987}
| 251 252#define OFW_SBUS_TYPE "sbus" 253#define OFW_SBUS_NAME "sbus" 254 255static const struct intr_controller sbus_ic = { 256 sbus_intr_enable, 257 sbus_intr_disable, 258 sbus_intr_assign, 259 sbus_intr_clear 260}; 261 262struct sbus_icarg { 263 struct sbus_softc *sica_sc; 264 bus_addr_t sica_map; 265 bus_addr_t sica_clr; 266}; 267 268static const char *sbus_order_first[] = { 269 "auxio", 270 "dma", 271 NULL 272}; 273 274static int 275sbus_inlist(const char *name, const char **list) 276{ 277 int i; 278 279 if (name == NULL) 280 return (0); 281 for (i = 0; list[i] != NULL; i++) { 282 if (strcmp(name, list[i]) == 0) 283 return (1); 284 } 285 return (0); 286} 287 288static int 289sbus_probe(device_t dev) 290{ 291 const char *t; 292 293 t = ofw_bus_get_type(dev); 294 if (((t == NULL || strcmp(t, OFW_SBUS_TYPE) != 0)) && 295 strcmp(ofw_bus_get_name(dev), OFW_SBUS_NAME) != 0) 296 return (ENXIO); 297 device_set_desc(dev, "U2S UPA-SBus bridge"); 298 return (0); 299} 300 301static int 302sbus_attach(device_t dev) 303{ 304 struct sbus_softc *sc; 305 struct sbus_devinfo *sdi; 306 struct sbus_icarg *sica; 307 struct sbus_ranges *range; 308 struct resource *res; 309 struct resource_list *rl; 310 device_t cdev; 311 bus_addr_t intrclr, intrmap, phys; 312 bus_size_t size; 313 u_long vec; 314 phandle_t child, node; 315 int clock, i, intr, rid; 316 317 sc = device_get_softc(dev); 318 sc->sc_dev = dev; 319 node = ofw_bus_get_node(dev); 320 321 rid = 0; 322 sc->sc_sysio_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 323 RF_ACTIVE); 324 if (sc->sc_sysio_res == NULL) 325 panic("%s: cannot allocate device memory", __func__); 326 327 if (OF_getprop(node, "interrupts", &intr, sizeof(intr)) == -1) 328 panic("%s: cannot get IGN", __func__); 329 sc->sc_ign = INTIGN(intr); 330 sc->sc_cbustag = sbus_alloc_bustag(sc); 331 332 /* 333 * Record clock frequency for synchronous SCSI. 334 * IS THIS THE CORRECT DEFAULT?? 335 */ 336 if (OF_getprop(node, "clock-frequency", &clock, sizeof(clock)) == -1) 337 clock = 25000000; 338 sc->sc_clockfreq = clock; 339 clock /= 1000; 340 device_printf(dev, "clock %d.%03d MHz\n", clock / 1000, clock % 1000); 341 342 /* 343 * Collect address translations from the OBP. 344 */ 345 if ((sc->sc_nrange = OF_getprop_alloc(node, "ranges", 346 sizeof(*range), (void **)&range)) == -1) { 347 panic("%s: error getting ranges property", __func__); 348 } 349 sc->sc_rd = (struct sbus_rd *)malloc(sizeof(*sc->sc_rd) * sc->sc_nrange, 350 M_DEVBUF, M_NOWAIT); 351 if (sc->sc_rd == NULL) 352 panic("%s: cannot allocate rmans", __func__); 353 /* 354 * Preallocate all space that the SBus bridge decodes, so that nothing 355 * else gets in the way; set up rmans etc. 356 */ 357 rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev); 358 for (i = 0; i < sc->sc_nrange; i++) { 359 phys = range[i].poffset | ((bus_addr_t)range[i].pspace << 32); 360 size = range[i].size; 361 sc->sc_rd[i].rd_slot = range[i].cspace; 362 sc->sc_rd[i].rd_coffset = range[i].coffset; 363 sc->sc_rd[i].rd_cend = sc->sc_rd[i].rd_coffset + size; 364 rid = resource_list_add_next(rl, SYS_RES_MEMORY, phys, 365 phys + size - 1, size); 366 if ((res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 367 RF_ACTIVE)) == NULL) 368 panic("%s: cannot allocate decoded range", __func__); 369 sc->sc_rd[i].rd_bushandle = rman_get_bushandle(res); 370 sc->sc_rd[i].rd_rman.rm_type = RMAN_ARRAY; 371 sc->sc_rd[i].rd_rman.rm_descr = "SBus Device Memory"; 372 if (rman_init(&sc->sc_rd[i].rd_rman) != 0 || 373 rman_manage_region(&sc->sc_rd[i].rd_rman, 0, size) != 0) 374 panic("%s: failed to set up memory rman", __func__); 375 sc->sc_rd[i].rd_poffset = phys; 376 sc->sc_rd[i].rd_pend = phys + size; 377 sc->sc_rd[i].rd_res = res; 378 } 379 free(range, M_OFWPROP); 380 381 /* 382 * Get the SBus burst transfer size if burst transfers are supported. 383 * XXX: is the default correct? 384 */ 385 if (OF_getprop(node, "burst-sizes", &sc->sc_burst, 386 sizeof(sc->sc_burst)) == -1 || sc->sc_burst == 0) 387 sc->sc_burst = SBUS_BURST_DEF; 388 389 /* initalise the IOMMU */ 390 391 /* punch in our copies */ 392 sc->sc_is.is_pmaxaddr = IOMMU_MAXADDR(SBUS_IOMMU_BITS); 393 sc->sc_is.is_bustag = rman_get_bustag(sc->sc_sysio_res); 394 sc->sc_is.is_bushandle = rman_get_bushandle(sc->sc_sysio_res); 395 sc->sc_is.is_iommu = SBR_IOMMU; 396 sc->sc_is.is_dtag = SBR_IOMMU_TLB_TAG_DIAG; 397 sc->sc_is.is_ddram = SBR_IOMMU_TLB_DATA_DIAG; 398 sc->sc_is.is_dqueue = SBR_IOMMU_QUEUE_DIAG; 399 sc->sc_is.is_dva = SBR_IOMMU_SVADIAG; 400 sc->sc_is.is_dtcmp = 0; 401 sc->sc_is.is_sb[0] = SBR_STRBUF; 402 sc->sc_is.is_sb[1] = 0; 403 404 /* 405 * Note: the SBus IOMMU ignores the high bits of an address, so a NULL 406 * DMA pointer will be translated by the first page of the IOTSB. 407 * To detect bugs we'll allocate and ignore the first entry. 408 */ 409 iommu_init(device_get_nameunit(dev), &sc->sc_is, 3, -1, 1); 410 411 /* Create the DMA tag. */ 412 if (bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0, 413 sc->sc_is.is_pmaxaddr, ~0, NULL, NULL, sc->sc_is.is_pmaxaddr, 414 0xff, 0xffffffff, 0, NULL, NULL, &sc->sc_cdmatag) != 0) 415 panic("%s: bus_dma_tag_create failed", __func__); 416 /* Customize the tag. */ 417 sc->sc_cdmatag->dt_cookie = &sc->sc_is; 418 sc->sc_cdmatag->dt_mt = &iommu_dma_methods; 419 420 /* 421 * Hunt through all the interrupt mapping regs and register our 422 * interrupt controller for the corresponding interrupt vectors. 423 */ 424 for (i = 0; i <= SBUS_MAX_INO; i++) { 425 if (sbus_find_intrmap(sc, i, &intrmap, &intrclr) == 0) 426 continue; 427 sica = malloc(sizeof(*sica), M_DEVBUF, M_NOWAIT); 428 if (sica == NULL) 429 panic("%s: could not allocate interrupt controller " 430 "argument", __func__); 431 sica->sica_sc = sc; 432 sica->sica_map = intrmap; 433 sica->sica_clr = intrclr; 434#ifdef SBUS_DEBUG 435 device_printf(dev, 436 "intr map (INO %d, %s) %#lx: %#lx, clr: %#lx\n", 437 i, (i & INTMAP_OBIO_MASK) == 0 ? "SBus slot" : "OBIO", 438 (u_long)intrmap, (u_long)SYSIO_READ8(sc, intrmap), 439 (u_long)intrclr); 440#endif 441 if (intr_controller_register(INTMAP_VEC(sc->sc_ign, i), 442 &sbus_ic, sica) != 0) 443 panic("%s: could not register interrupt controller " 444 "for INO %d", __func__, i); 445 } 446 447 /* Enable the over-temperature and power-fail interrupts. */ 448 rid = 4; 449 sc->sc_ot_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 450 RF_ACTIVE); 451 if (sc->sc_ot_ires == NULL || 452 INTIGN(vec = rman_get_start(sc->sc_ot_ires)) != sc->sc_ign || 453 INTVEC(SYSIO_READ8(sc, SBR_THERM_INT_MAP)) != vec || 454 intr_vectors[vec].iv_ic != &sbus_ic || 455 bus_setup_intr(dev, sc->sc_ot_ires, INTR_TYPE_MISC, 456 NULL, sbus_overtemp, sc, &sc->sc_ot_ihand) != 0) 457 panic("%s: failed to set up temperature interrupt", __func__); 458 rid = 3; 459 sc->sc_pf_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 460 RF_ACTIVE); 461 if (sc->sc_pf_ires == NULL || 462 INTIGN(vec = rman_get_start(sc->sc_pf_ires)) != sc->sc_ign || 463 INTVEC(SYSIO_READ8(sc, SBR_POWER_INT_MAP)) != vec || 464 intr_vectors[vec].iv_ic != &sbus_ic || 465 bus_setup_intr(dev, sc->sc_pf_ires, INTR_TYPE_MISC, 466 NULL, sbus_pwrfail, sc, &sc->sc_pf_ihand) != 0) 467 panic("%s: failed to set up power fail interrupt", __func__); 468 469 /* Initialize the counter-timer. */ 470 sparc64_counter_init(device_get_nameunit(dev), 471 rman_get_bustag(sc->sc_sysio_res), 472 rman_get_bushandle(sc->sc_sysio_res), SBR_TC0); 473 474 /* 475 * Loop through ROM children, fixing any relative addresses 476 * and then configuring each device. 477 */ 478 for (child = OF_child(node); child != 0; child = OF_peer(child)) { 479 if ((sdi = sbus_setup_dinfo(dev, sc, child)) == NULL) 480 continue; 481 /* 482 * For devices where there are variants that are actually 483 * split into two SBus devices (as opposed to the first 484 * half of the device being a SBus device and the second 485 * half hanging off of the first one) like 'auxio' and 486 * 'SUNW,fdtwo' or 'dma' and 'esp' probe the SBus device 487 * which is a prerequisite to the driver attaching to the 488 * second one with a lower order. Saves us from dealing 489 * with different probe orders in the respective device 490 * drivers which generally is more hackish. 491 */ 492 cdev = device_add_child_ordered(dev, (OF_child(child) == 0 && 493 sbus_inlist(sdi->sdi_obdinfo.obd_name, sbus_order_first)) ? 494 SBUS_ORDER_FIRST : SBUS_ORDER_NORMAL, NULL, -1); 495 if (cdev == NULL) { 496 device_printf(dev, 497 "<%s>: device_add_child_ordered failed\n", 498 sdi->sdi_obdinfo.obd_name); 499 sbus_destroy_dinfo(sdi); 500 continue; 501 } 502 device_set_ivars(cdev, sdi); 503 } 504 return (bus_generic_attach(dev)); 505} 506 507static struct sbus_devinfo * 508sbus_setup_dinfo(device_t dev, struct sbus_softc *sc, phandle_t node) 509{ 510 struct sbus_devinfo *sdi; 511 struct sbus_regs *reg; 512 u_int32_t base, iv, *intr; 513 int i, nreg, nintr, slot, rslot; 514 515 sdi = malloc(sizeof(*sdi), M_DEVBUF, M_ZERO | M_WAITOK); 516 if (ofw_bus_gen_setup_devinfo(&sdi->sdi_obdinfo, node) != 0) { 517 free(sdi, M_DEVBUF); 518 return (NULL); 519 } 520 resource_list_init(&sdi->sdi_rl); 521 slot = -1; 522 nreg = OF_getprop_alloc(node, "reg", sizeof(*reg), (void **)®); 523 if (nreg == -1) { 524 if (sdi->sdi_obdinfo.obd_type == NULL || 525 strcmp(sdi->sdi_obdinfo.obd_type, "hierarchical") != 0) { 526 device_printf(dev, "<%s>: incomplete\n", 527 sdi->sdi_obdinfo.obd_name); 528 goto fail; 529 } 530 } else { 531 for (i = 0; i < nreg; i++) { 532 base = reg[i].sbr_offset; 533 if (SBUS_ABS(base)) { 534 rslot = SBUS_ABS_TO_SLOT(base); 535 base = SBUS_ABS_TO_OFFSET(base); 536 } else 537 rslot = reg[i].sbr_slot; 538 if (slot != -1 && slot != rslot) { 539 device_printf(dev, "<%s>: multiple slots\n", 540 sdi->sdi_obdinfo.obd_name); 541 free(reg, M_OFWPROP); 542 goto fail; 543 } 544 slot = rslot; 545 546 resource_list_add(&sdi->sdi_rl, SYS_RES_MEMORY, i, 547 base, base + reg[i].sbr_size, reg[i].sbr_size); 548 } 549 free(reg, M_OFWPROP); 550 } 551 sdi->sdi_slot = slot; 552 553 /* 554 * The `interrupts' property contains the SBus interrupt level. 555 */ 556 nintr = OF_getprop_alloc(node, "interrupts", sizeof(*intr), 557 (void **)&intr); 558 if (nintr != -1) { 559 for (i = 0; i < nintr; i++) { 560 iv = intr[i]; 561 /* 562 * SBus card devices need the slot number encoded into 563 * the vector as this is generally not done. 564 */ 565 if ((iv & INTMAP_OBIO_MASK) == 0) 566 iv |= slot << 3; 567 iv = INTMAP_VEC(sc->sc_ign, iv); 568 resource_list_add(&sdi->sdi_rl, SYS_RES_IRQ, i, 569 iv, iv, 1); 570 } 571 free(intr, M_OFWPROP); 572 } 573 if (OF_getprop(node, "burst-sizes", &sdi->sdi_burstsz, 574 sizeof(sdi->sdi_burstsz)) == -1) 575 sdi->sdi_burstsz = sc->sc_burst; 576 else 577 sdi->sdi_burstsz &= sc->sc_burst; 578 if (OF_getprop(node, "clock-frequency", &sdi->sdi_clockfreq, 579 sizeof(sdi->sdi_clockfreq)) == -1) 580 sdi->sdi_clockfreq = sc->sc_clockfreq; 581 582 return (sdi); 583 584fail: 585 sbus_destroy_dinfo(sdi); 586 return (NULL); 587} 588 589static void 590sbus_destroy_dinfo(struct sbus_devinfo *dinfo) 591{ 592 593 resource_list_free(&dinfo->sdi_rl); 594 ofw_bus_gen_destroy_devinfo(&dinfo->sdi_obdinfo); 595 free(dinfo, M_DEVBUF); 596} 597 598static int 599sbus_print_child(device_t dev, device_t child) 600{ 601 int rv; 602 603 rv = bus_print_child_header(dev, child); 604 rv += sbus_print_res(device_get_ivars(child)); 605 rv += bus_print_child_footer(dev, child); 606 return (rv); 607} 608 609static void 610sbus_probe_nomatch(device_t dev, device_t child) 611{ 612 const char *type; 613 614 device_printf(dev, "<%s>", ofw_bus_get_name(child)); 615 sbus_print_res(device_get_ivars(child)); 616 type = ofw_bus_get_type(child); 617 printf(" type %s (no driver attached)\n", 618 type != NULL ? type : "unknown"); 619} 620 621static int 622sbus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 623{ 624 struct sbus_softc *sc; 625 struct sbus_devinfo *dinfo; 626 627 sc = device_get_softc(dev); 628 if ((dinfo = device_get_ivars(child)) == NULL) 629 return (ENOENT); 630 switch (which) { 631 case SBUS_IVAR_BURSTSZ: 632 *result = dinfo->sdi_burstsz; 633 break; 634 case SBUS_IVAR_CLOCKFREQ: 635 *result = dinfo->sdi_clockfreq; 636 break; 637 case SBUS_IVAR_IGN: 638 *result = sc->sc_ign; 639 break; 640 case SBUS_IVAR_SLOT: 641 *result = dinfo->sdi_slot; 642 break; 643 default: 644 return (ENOENT); 645 } 646 return (0); 647} 648 649static struct resource_list * 650sbus_get_resource_list(device_t dev, device_t child) 651{ 652 struct sbus_devinfo *sdi; 653 654 sdi = device_get_ivars(child); 655 return (&sdi->sdi_rl); 656} 657 658static void 659sbus_intr_enable(void *arg) 660{ 661 struct intr_vector *iv = arg; 662 struct sbus_icarg *sica = iv->iv_icarg; 663 664 SYSIO_WRITE8(sica->sica_sc, sica->sica_map, 665 INTMAP_ENABLE(iv->iv_vec, iv->iv_mid)); 666} 667 668static void 669sbus_intr_disable(void *arg) 670{ 671 struct intr_vector *iv = arg; 672 struct sbus_icarg *sica = iv->iv_icarg; 673 674 SYSIO_WRITE8(sica->sica_sc, sica->sica_map, iv->iv_vec); 675} 676 677static void 678sbus_intr_assign(void *arg) 679{ 680 struct intr_vector *iv = arg; 681 struct sbus_icarg *sica = iv->iv_icarg; 682 683 SYSIO_WRITE8(sica->sica_sc, sica->sica_map, INTMAP_TID( 684 SYSIO_READ8(sica->sica_sc, sica->sica_map), iv->iv_mid)); 685} 686 687static void 688sbus_intr_clear(void *arg) 689{ 690 struct intr_vector *iv = arg; 691 struct sbus_icarg *sica = iv->iv_icarg; 692 693 SYSIO_WRITE8(sica->sica_sc, sica->sica_clr, 0); 694} 695 696static int 697sbus_find_intrmap(struct sbus_softc *sc, u_int ino, bus_addr_t *intrmapptr, 698 bus_addr_t *intrclrptr) 699{ 700 bus_addr_t intrclr, intrmap; 701 int i; 702 703 if (ino > SBUS_MAX_INO) { 704 device_printf(sc->sc_dev, "out of range INO %d requested\n", 705 ino); 706 return (0); 707 } 708 709 if ((ino & INTMAP_OBIO_MASK) == 0) { 710 intrmap = SBR_SLOT0_INT_MAP + INTSLOT(ino) * 8; 711 intrclr = SBR_SLOT0_INT_CLR + 712 (INTSLOT(ino) * 8 * 8) + (INTPRI(ino) * 8); 713 } else { 714 intrclr = 0; 715 for (i = 0, intrmap = SBR_SCSI_INT_MAP; 716 intrmap <= SBR_RESERVED_INT_MAP; intrmap += 8, i++) { 717 if (INTVEC(SYSIO_READ8(sc, intrmap)) == 718 INTMAP_VEC(sc->sc_ign, ino)) { 719 intrclr = SBR_SCSI_INT_CLR + i * 8; 720 break; 721 } 722 } 723 if (intrclr == 0) 724 return (0); 725 } 726 if (intrmapptr != NULL) 727 *intrmapptr = intrmap; 728 if (intrclrptr != NULL) 729 *intrclrptr = intrclr; 730 return (1); 731} 732 733static int 734sbus_setup_intr(device_t dev, device_t child, struct resource *ires, int flags, 735 driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep) 736{ 737 struct sbus_softc *sc; 738 u_long vec; 739 740 sc = device_get_softc(dev); 741 /* 742 * Make sure the vector is fully specified and we registered 743 * our interrupt controller for it. 744 */ 745 vec = rman_get_start(ires); 746 if (INTIGN(vec) != sc->sc_ign || intr_vectors[vec].iv_ic != &sbus_ic) { 747 device_printf(dev, "invalid interrupt vector 0x%lx\n", vec); 748 return (EINVAL); 749 } 750 return (bus_generic_setup_intr(dev, child, ires, flags, filt, intr, 751 arg, cookiep)); 752} 753 754static struct resource * 755sbus_alloc_resource(device_t bus, device_t child, int type, int *rid, 756 u_long start, u_long end, u_long count, u_int flags) 757{ 758 struct sbus_softc *sc; 759 struct rman *rm; 760 struct resource *rv; 761 struct resource_list *rl; 762 struct resource_list_entry *rle; 763 device_t schild; 764 bus_space_handle_t bh; 765 bus_addr_t toffs; 766 bus_size_t tend; 767 int i, slot; 768 int isdefault, needactivate, passthrough; 769 770 isdefault = (start == 0UL && end == ~0UL); 771 needactivate = flags & RF_ACTIVE; 772 passthrough = (device_get_parent(child) != bus); 773 rle = NULL; 774 sc = device_get_softc(bus); 775 rl = BUS_GET_RESOURCE_LIST(bus, child); 776 switch (type) { 777 case SYS_RES_IRQ: 778 return (resource_list_alloc(rl, bus, child, type, rid, start, 779 end, count, flags)); 780 case SYS_RES_MEMORY: 781 if (!passthrough) { 782 rle = resource_list_find(rl, type, *rid); 783 if (rle == NULL) 784 return (NULL); 785 if (rle->res != NULL) 786 panic("%s: resource entry is busy", __func__); 787 if (isdefault) { 788 start = rle->start; 789 count = ulmax(count, rle->count); 790 end = ulmax(rle->end, start + count - 1); 791 } 792 } 793 rm = NULL; 794 bh = toffs = tend = 0; 795 schild = child; 796 while (device_get_parent(schild) != bus) 797 schild = device_get_parent(schild); 798 slot = sbus_get_slot(schild); 799 for (i = 0; i < sc->sc_nrange; i++) { 800 if (sc->sc_rd[i].rd_slot != slot || 801 start < sc->sc_rd[i].rd_coffset || 802 start > sc->sc_rd[i].rd_cend) 803 continue; 804 /* Disallow cross-range allocations. */ 805 if (end > sc->sc_rd[i].rd_cend) 806 return (NULL); 807 /* We've found the connection to the parent bus */ 808 toffs = start - sc->sc_rd[i].rd_coffset; 809 tend = end - sc->sc_rd[i].rd_coffset; 810 rm = &sc->sc_rd[i].rd_rman; 811 bh = sc->sc_rd[i].rd_bushandle; 812 break; 813 } 814 if (rm == NULL) 815 return (NULL); 816 flags &= ~RF_ACTIVE; 817 rv = rman_reserve_resource(rm, toffs, tend, count, flags, 818 child); 819 if (rv == NULL) 820 return (NULL); 821 rman_set_rid(rv, *rid); 822 rman_set_bustag(rv, sc->sc_cbustag); 823 rman_set_bushandle(rv, bh + rman_get_start(rv)); 824 if (needactivate) { 825 if (bus_activate_resource(child, type, *rid, rv)) { 826 rman_release_resource(rv); 827 return (NULL); 828 } 829 } 830 if (!passthrough) 831 rle->res = rv; 832 return (rv); 833 default: 834 return (NULL); 835 } 836} 837 838static int 839sbus_activate_resource(device_t bus, device_t child, int type, int rid, 840 struct resource *r) 841{ 842 void *p; 843 int error; 844 845 if (type == SYS_RES_IRQ) { 846 return (BUS_ACTIVATE_RESOURCE(device_get_parent(bus), 847 child, type, rid, r)); 848 } 849 if (type == SYS_RES_MEMORY) { 850 /* 851 * Need to memory-map the device space, as some drivers depend 852 * on the virtual address being set and useable. 853 */ 854 error = sparc64_bus_mem_map(rman_get_bustag(r), 855 rman_get_bushandle(r), rman_get_size(r), 0, 0, &p); 856 if (error != 0) 857 return (error); 858 rman_set_virtual(r, p); 859 } 860 return (rman_activate_resource(r)); 861} 862 863static int 864sbus_deactivate_resource(device_t bus, device_t child, int type, int rid, 865 struct resource *r) 866{ 867 868 if (type == SYS_RES_IRQ) { 869 return (BUS_DEACTIVATE_RESOURCE(device_get_parent(bus), 870 child, type, rid, r)); 871 } 872 if (type == SYS_RES_MEMORY) { 873 sparc64_bus_mem_unmap(rman_get_virtual(r), rman_get_size(r)); 874 rman_set_virtual(r, NULL); 875 } 876 return (rman_deactivate_resource(r)); 877} 878 879static int 880sbus_release_resource(device_t bus, device_t child, int type, int rid, 881 struct resource *r) 882{ 883 struct resource_list *rl; 884 struct resource_list_entry *rle; 885 int error, passthrough; 886 887 passthrough = (device_get_parent(child) != bus); 888 rl = BUS_GET_RESOURCE_LIST(bus, child); 889 if (type == SYS_RES_IRQ) 890 return (resource_list_release(rl, bus, child, type, rid, r)); 891 if ((rman_get_flags(r) & RF_ACTIVE) != 0) { 892 error = bus_deactivate_resource(child, type, rid, r); 893 if (error != 0) 894 return (error); 895 } 896 error = rman_release_resource(r); 897 if (error != 0 || passthrough) 898 return (error); 899 rle = resource_list_find(rl, type, rid); 900 if (rle == NULL) 901 panic("%s: cannot find resource", __func__); 902 if (rle->res == NULL) 903 panic("%s: resource entry is not busy", __func__); 904 rle->res = NULL; 905 return (0); 906} 907 908static bus_dma_tag_t 909sbus_get_dma_tag(device_t bus, device_t child) 910{ 911 struct sbus_softc *sc; 912 913 sc = device_get_softc(bus); 914 return (sc->sc_cdmatag); 915} 916 917static const struct ofw_bus_devinfo * 918sbus_get_devinfo(device_t bus, device_t child) 919{ 920 struct sbus_devinfo *sdi; 921 922 sdi = device_get_ivars(child); 923 return (&sdi->sdi_obdinfo); 924} 925 926/* 927 * Handle an overtemp situation. 928 * 929 * SPARCs have temperature sensors which generate interrupts 930 * if the machine's temperature exceeds a certain threshold. 931 * This handles the interrupt and powers off the machine. 932 * The same needs to be done to PCI controller drivers. 933 */ 934static void 935sbus_overtemp(void *arg) 936{ 937 static int shutdown; 938 939 /* As the interrupt is cleared we may be called multiple times. */ 940 if (shutdown != 0) 941 return; 942 shutdown++; 943 printf("DANGER: OVER TEMPERATURE detected\nShutting down NOW.\n"); 944 shutdown_nice(RB_POWEROFF); 945} 946 947/* Try to shut down in time in case of power failure. */ 948static void 949sbus_pwrfail(void *arg) 950{ 951 static int shutdown; 952 953 /* As the interrupt is cleared we may be called multiple times. */ 954 if (shutdown != 0) 955 return; 956 shutdown++; 957 printf("Power failure detected\nShutting down NOW.\n"); 958 shutdown_nice(0); 959} 960 961static bus_space_tag_t 962sbus_alloc_bustag(struct sbus_softc *sc) 963{ 964 bus_space_tag_t sbt; 965 966 sbt = (bus_space_tag_t)malloc(sizeof(struct bus_space_tag), M_DEVBUF, 967 M_NOWAIT | M_ZERO); 968 if (sbt == NULL) 969 panic("%s: out of memory", __func__); 970 971 sbt->bst_cookie = sc; 972 sbt->bst_parent = rman_get_bustag(sc->sc_sysio_res); 973 sbt->bst_type = SBUS_BUS_SPACE; 974 return (sbt); 975} 976 977static int 978sbus_print_res(struct sbus_devinfo *sdi) 979{ 980 int rv; 981 982 rv = 0; 983 rv += resource_list_print_type(&sdi->sdi_rl, "mem", SYS_RES_MEMORY, 984 "%#lx"); 985 rv += resource_list_print_type(&sdi->sdi_rl, "irq", SYS_RES_IRQ, 986 "%ld"); 987 return (rv); 988}
|