1 /* $OpenBSD: central.c,v 1.12 2022/10/16 01:22:39 jsg Exp $ */ 2 3 /* 4 * Copyright (c) 2004 Jason L. Wright (jason@thought.net) 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/param.h> 30 #include <sys/systm.h> 31 #include <sys/kernel.h> 32 #include <sys/device.h> 33 #include <sys/conf.h> 34 #include <sys/timeout.h> 35 #include <sys/malloc.h> 36 37 #include <machine/bus.h> 38 #include <machine/autoconf.h> 39 #include <machine/openfirm.h> 40 41 #include <sparc64/dev/centralvar.h> 42 43 struct central_softc { 44 struct device sc_dv; 45 bus_space_tag_t sc_bt; 46 bus_space_tag_t sc_cbt; 47 int sc_node; 48 int sc_nrange; 49 struct central_range *sc_range; 50 }; 51 52 int central_match(struct device *, void *, void *); 53 void central_attach(struct device *, struct device *, void *); 54 55 int central_print(void *, const char *); 56 int central_get_string(int, char *, char **); 57 58 bus_space_tag_t central_alloc_bus_tag(struct central_softc *); 59 int _central_bus_map(bus_space_tag_t, bus_space_tag_t, bus_addr_t, bus_size_t, 60 int, bus_space_handle_t *); 61 62 int 63 central_match(struct device *parent, void *match, void *aux) 64 { 65 struct mainbus_attach_args *ma = aux; 66 67 if (strcmp(ma->ma_name, "central") == 0) 68 return (1); 69 return (0); 70 } 71 72 void 73 central_attach(struct device *parent, struct device *self, void *aux) 74 { 75 struct central_softc *sc = (struct central_softc *)self; 76 struct mainbus_attach_args *ma = aux; 77 int node0, node; 78 79 sc->sc_bt = ma->ma_bustag; 80 sc->sc_node = ma->ma_node; 81 sc->sc_cbt = central_alloc_bus_tag(sc); 82 83 getprop(sc->sc_node, "ranges", sizeof(struct central_range), 84 &sc->sc_nrange, (void **)&sc->sc_range); 85 86 printf("\n"); 87 88 node0 = firstchild(sc->sc_node); 89 for (node = node0; node; node = nextsibling(node)) { 90 struct central_attach_args ca; 91 92 bzero(&ca, sizeof(ca)); 93 ca.ca_node = node; 94 ca.ca_bustag = sc->sc_cbt; 95 if (central_get_string(ca.ca_node, "name", &ca.ca_name)) { 96 printf("can't fetch name for node 0x%x\n", node); 97 continue; 98 } 99 100 getprop(node, "reg", sizeof(struct central_reg), 101 &ca.ca_nreg, (void **)&ca.ca_reg); 102 103 (void)config_found(&sc->sc_dv, (void *)&ca, central_print); 104 105 free(ca.ca_name, M_DEVBUF, 0); 106 } 107 } 108 109 int 110 central_get_string(int node, char *name, char **buf) 111 { 112 int len; 113 114 len = getproplen(node, name); 115 if (len < 0) 116 return (len); 117 *buf = (char *)malloc(len + 1, M_DEVBUF, M_NOWAIT); 118 if (*buf == NULL) 119 return (-1); 120 121 if (len != 0) 122 getpropstringA(node, name, *buf); 123 (*buf)[len] = '\0'; 124 return (0); 125 } 126 127 int 128 central_print(void *args, const char *busname) 129 { 130 struct central_attach_args *ca = args; 131 char *class; 132 133 if (busname != NULL) { 134 printf("\"%s\" at %s", ca->ca_name, busname); 135 class = getpropstring(ca->ca_node, "device_type"); 136 if (*class != '\0') 137 printf(" class %s", class); 138 } 139 return (UNCONF); 140 } 141 142 bus_space_tag_t 143 central_alloc_bus_tag(struct central_softc *sc) 144 { 145 struct sparc_bus_space_tag *bt; 146 147 bt = malloc(sizeof(*bt), M_DEVBUF, M_NOWAIT | M_ZERO); 148 if (bt == NULL) 149 panic("central: couldn't alloc bus tag"); 150 151 strlcpy(bt->name, sc->sc_dv.dv_xname, sizeof(bt->name)); 152 bt->cookie = sc; 153 bt->parent = sc->sc_bt; 154 bt->asi = bt->parent->asi; 155 bt->sasi = bt->parent->sasi; 156 bt->sparc_bus_map = _central_bus_map; 157 /* XXX bt->sparc_bus_mmap = central_bus_mmap; */ 158 /* XXX bt->sparc_intr_establish = upa_intr_establish; */ 159 return (bt); 160 } 161 162 int 163 _central_bus_map(bus_space_tag_t t, bus_space_tag_t t0, bus_addr_t addr, 164 bus_size_t size, int flags, bus_space_handle_t *hp) 165 { 166 struct central_softc *sc = t->cookie; 167 int64_t slot = BUS_ADDR_IOSPACE(addr); 168 int64_t offset = BUS_ADDR_PADDR(addr); 169 int i; 170 171 if (t->parent == NULL || t->parent->sparc_bus_map == NULL) { 172 printf("\ncentral_bus_map: invalid parent"); 173 return (EINVAL); 174 } 175 176 if (flags & BUS_SPACE_MAP_PROMADDRESS) 177 return ((*t->parent->sparc_bus_map)(t, t0, addr, 178 size, flags, hp)); 179 180 for (i = 0; i < sc->sc_nrange; i++) { 181 bus_addr_t paddr; 182 183 if (sc->sc_range[i].cspace != slot) 184 continue; 185 186 paddr = offset - sc->sc_range[i].coffset; 187 paddr += sc->sc_range[i].poffset; 188 paddr |= ((bus_addr_t)sc->sc_range[i].pspace << 32); 189 190 return ((*t->parent->sparc_bus_map)(t->parent, t0, paddr, 191 size, flags, hp)); 192 } 193 194 return (EINVAL); 195 } 196 197 const struct cfattach central_ca = { 198 sizeof(struct central_softc), central_match, central_attach 199 }; 200 201 struct cfdriver central_cd = { 202 NULL, "central", DV_DULL 203 }; 204