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