1 /* $OpenBSD: central.c,v 1.6 2008/01/17 22:53:18 kettenis 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 if (ca.ca_name != NULL) 111 free(ca.ca_name, M_DEVBUF); 112 } 113 } 114 115 int 116 central_get_string(int node, char *name, char **buf) 117 { 118 int len; 119 120 len = getproplen(node, name); 121 if (len < 0) 122 return (len); 123 *buf = (char *)malloc(len + 1, M_DEVBUF, M_NOWAIT); 124 if (*buf == NULL) 125 return (-1); 126 127 if (len != 0) 128 getpropstringA(node, name, *buf); 129 (*buf)[len] = '\0'; 130 return (0); 131 } 132 133 int 134 central_print(void *args, const char *busname) 135 { 136 struct central_attach_args *ca = args; 137 char *class; 138 139 if (busname != NULL) { 140 printf("\"%s\" at %s", ca->ca_name, busname); 141 class = getpropstring(ca->ca_node, "device_type"); 142 if (*class != '\0') 143 printf(" class %s", class); 144 } 145 return (UNCONF); 146 } 147 148 bus_space_tag_t 149 central_alloc_bus_tag(struct central_softc *sc) 150 { 151 struct sparc_bus_space_tag *bt; 152 153 bt = malloc(sizeof(*bt), M_DEVBUF, M_NOWAIT | M_ZERO); 154 if (bt == NULL) 155 panic("central: couldn't alloc bus tag"); 156 157 snprintf(bt->name, sizeof(bt->name), "%s", sc->sc_dv.dv_xname); 158 bt->cookie = sc; 159 bt->parent = sc->sc_bt; 160 bt->asi = bt->parent->asi; 161 bt->sasi = bt->parent->sasi; 162 bt->sparc_bus_map = _central_bus_map; 163 /* XXX bt->sparc_bus_mmap = central_bus_mmap; */ 164 /* XXX bt->sparc_intr_establish = upa_intr_establish; */ 165 return (bt); 166 } 167 168 int 169 _central_bus_map(bus_space_tag_t t, bus_space_tag_t t0, bus_addr_t addr, 170 bus_size_t size, int flags, bus_space_handle_t *hp) 171 { 172 struct central_softc *sc = t->cookie; 173 int64_t slot = BUS_ADDR_IOSPACE(addr); 174 int64_t offset = BUS_ADDR_PADDR(addr); 175 int i; 176 177 if (t->parent == NULL || t->parent->sparc_bus_map == NULL) { 178 printf("\ncentral_bus_map: invalid parent"); 179 return (EINVAL); 180 } 181 182 if (flags & BUS_SPACE_MAP_PROMADDRESS) 183 return ((*t->parent->sparc_bus_map)(t, t0, addr, 184 size, flags, hp)); 185 186 for (i = 0; i < sc->sc_nrange; i++) { 187 bus_addr_t paddr; 188 189 if (sc->sc_range[i].cspace != slot) 190 continue; 191 192 paddr = offset - sc->sc_range[i].coffset; 193 paddr += sc->sc_range[i].poffset; 194 paddr |= ((bus_addr_t)sc->sc_range[i].pspace << 32); 195 196 return ((*t->parent->sparc_bus_map)(t->parent, t0, paddr, 197 size, flags, hp)); 198 } 199 200 return (EINVAL); 201 } 202 203 struct cfattach central_ca = { 204 sizeof(struct central_softc), central_match, central_attach 205 }; 206 207 struct cfdriver central_cd = { 208 NULL, "central", DV_DULL 209 }; 210