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