1 /* $OpenBSD: central.c,v 1.10 2017/09/08 05:36:52 deraadt 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(parent, match, aux) 64 struct device *parent; 65 void *match, *aux; 66 { 67 struct mainbus_attach_args *ma = aux; 68 69 if (strcmp(ma->ma_name, "central") == 0) 70 return (1); 71 return (0); 72 } 73 74 void 75 central_attach(parent, self, aux) 76 struct device *parent, *self; 77 void *aux; 78 { 79 struct central_softc *sc = (struct central_softc *)self; 80 struct mainbus_attach_args *ma = aux; 81 int node0, node; 82 83 sc->sc_bt = ma->ma_bustag; 84 sc->sc_node = ma->ma_node; 85 sc->sc_cbt = central_alloc_bus_tag(sc); 86 87 getprop(sc->sc_node, "ranges", sizeof(struct central_range), 88 &sc->sc_nrange, (void **)&sc->sc_range); 89 90 printf("\n"); 91 92 node0 = firstchild(sc->sc_node); 93 for (node = node0; node; node = nextsibling(node)) { 94 struct central_attach_args ca; 95 96 bzero(&ca, sizeof(ca)); 97 ca.ca_node = node; 98 ca.ca_bustag = sc->sc_cbt; 99 if (central_get_string(ca.ca_node, "name", &ca.ca_name)) { 100 printf("can't fetch name for node 0x%x\n", node); 101 continue; 102 } 103 104 getprop(node, "reg", sizeof(struct central_reg), 105 &ca.ca_nreg, (void **)&ca.ca_reg); 106 107 (void)config_found(&sc->sc_dv, (void *)&ca, central_print); 108 109 free(ca.ca_name, M_DEVBUF, 0); 110 } 111 } 112 113 int 114 central_get_string(int node, char *name, char **buf) 115 { 116 int len; 117 118 len = getproplen(node, name); 119 if (len < 0) 120 return (len); 121 *buf = (char *)malloc(len + 1, M_DEVBUF, M_NOWAIT); 122 if (*buf == NULL) 123 return (-1); 124 125 if (len != 0) 126 getpropstringA(node, name, *buf); 127 (*buf)[len] = '\0'; 128 return (0); 129 } 130 131 int 132 central_print(void *args, const char *busname) 133 { 134 struct central_attach_args *ca = args; 135 char *class; 136 137 if (busname != NULL) { 138 printf("\"%s\" at %s", ca->ca_name, busname); 139 class = getpropstring(ca->ca_node, "device_type"); 140 if (*class != '\0') 141 printf(" class %s", class); 142 } 143 return (UNCONF); 144 } 145 146 bus_space_tag_t 147 central_alloc_bus_tag(struct central_softc *sc) 148 { 149 struct sparc_bus_space_tag *bt; 150 151 bt = malloc(sizeof(*bt), M_DEVBUF, M_NOWAIT | M_ZERO); 152 if (bt == NULL) 153 panic("central: couldn't alloc bus tag"); 154 155 strlcpy(bt->name, sc->sc_dv.dv_xname, sizeof(bt->name)); 156 bt->cookie = sc; 157 bt->parent = sc->sc_bt; 158 bt->asi = bt->parent->asi; 159 bt->sasi = bt->parent->sasi; 160 bt->sparc_bus_map = _central_bus_map; 161 /* XXX bt->sparc_bus_mmap = central_bus_mmap; */ 162 /* XXX bt->sparc_intr_establish = upa_intr_establish; */ 163 return (bt); 164 } 165 166 int 167 _central_bus_map(bus_space_tag_t t, bus_space_tag_t t0, bus_addr_t addr, 168 bus_size_t size, int flags, bus_space_handle_t *hp) 169 { 170 struct central_softc *sc = t->cookie; 171 int64_t slot = BUS_ADDR_IOSPACE(addr); 172 int64_t offset = BUS_ADDR_PADDR(addr); 173 int i; 174 175 if (t->parent == NULL || t->parent->sparc_bus_map == NULL) { 176 printf("\ncentral_bus_map: invalid parent"); 177 return (EINVAL); 178 } 179 180 if (flags & BUS_SPACE_MAP_PROMADDRESS) 181 return ((*t->parent->sparc_bus_map)(t, t0, addr, 182 size, flags, hp)); 183 184 for (i = 0; i < sc->sc_nrange; i++) { 185 bus_addr_t paddr; 186 187 if (sc->sc_range[i].cspace != slot) 188 continue; 189 190 paddr = offset - sc->sc_range[i].coffset; 191 paddr += sc->sc_range[i].poffset; 192 paddr |= ((bus_addr_t)sc->sc_range[i].pspace << 32); 193 194 return ((*t->parent->sparc_bus_map)(t->parent, t0, paddr, 195 size, flags, hp)); 196 } 197 198 return (EINVAL); 199 } 200 201 struct cfattach central_ca = { 202 sizeof(struct central_softc), central_match, central_attach 203 }; 204 205 struct cfdriver central_cd = { 206 NULL, "central", DV_DULL 207 }; 208