1 /* $NetBSD: obio.c,v 1.11 2002/10/02 16:02:24 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1996 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Adam Glass, Gordon W. Ross, and Matthew Fredette. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/device.h> 42 43 #include <uvm/uvm_extern.h> 44 45 #include <machine/autoconf.h> 46 #include <machine/pmap.h> 47 #include <machine/pte.h> 48 49 #include <sun2/sun2/control.h> 50 #include <sun2/sun2/machdep.h> 51 52 /* Does this machine have a Multibus? */ 53 extern int cpu_has_multibus; 54 55 static int obio_match __P((struct device *, struct cfdata *, void *)); 56 static void obio_attach __P((struct device *, struct device *, void *)); 57 58 struct obio_softc { 59 struct device sc_dev; /* base device */ 60 bus_space_tag_t sc_bustag; /* parent bus tag */ 61 bus_dma_tag_t sc_dmatag; /* parent bus dma tag */ 62 }; 63 64 CFATTACH_DECL(obio, sizeof(struct obio_softc), 65 obio_match, obio_attach, NULL, NULL); 66 67 static paddr_t obio_bus_mmap __P((bus_space_tag_t, bus_type_t, bus_addr_t, 68 off_t, int, int)); 69 static int _obio_bus_map __P((bus_space_tag_t, bus_type_t, bus_addr_t, 70 bus_size_t, int, 71 vaddr_t, bus_space_handle_t *)); 72 static int _obio_addr_bad __P((bus_space_tag_t, bus_space_handle_t, 73 bus_size_t, size_t)); 74 static int _obio_bus_peek __P((bus_space_tag_t, bus_space_handle_t, 75 bus_size_t, size_t, void *)); 76 static int _obio_bus_poke __P((bus_space_tag_t, bus_space_handle_t, 77 bus_size_t, size_t, u_int32_t)); 78 79 static struct sun68k_bus_space_tag obio_space_tag = { 80 NULL, /* cookie */ 81 NULL, /* parent bus tag */ 82 _obio_bus_map, /* bus_space_map */ 83 NULL, /* bus_space_unmap */ 84 NULL, /* bus_space_subregion */ 85 NULL, /* bus_space_barrier */ 86 obio_bus_mmap, /* bus_space_mmap */ 87 NULL, /* bus_intr_establish */ 88 _obio_bus_peek, /* bus_space_peek_N */ 89 _obio_bus_poke /* bus_space_poke_N */ 90 }; 91 92 static int 93 obio_match(parent, cf, aux) 94 struct device *parent; 95 struct cfdata *cf; 96 void *aux; 97 { 98 struct mainbus_attach_args *ma = aux; 99 100 return (ma->ma_name == NULL || strcmp(cf->cf_name, ma->ma_name) == 0); 101 } 102 103 static void 104 obio_attach(parent, self, aux) 105 struct device *parent; 106 struct device *self; 107 void *aux; 108 { 109 struct mainbus_attach_args *ma = aux; 110 struct obio_softc *sc = (struct obio_softc *)self; 111 struct obio_attach_args oba; 112 const char *const *cpp; 113 static const char *const special[] = { 114 /* find these first */ 115 NULL 116 }; 117 118 /* 119 * There is only one obio bus 120 */ 121 if (self->dv_unit > 0) { 122 printf(" unsupported\n"); 123 return; 124 } 125 printf("\n"); 126 127 sc->sc_bustag = ma->ma_bustag; 128 sc->sc_dmatag = ma->ma_dmatag; 129 130 obio_space_tag.cookie = sc; 131 obio_space_tag.parent = sc->sc_bustag; 132 133 /* 134 * Prepare the skeleton attach arguments for our devices. 135 * The values we give in the locators are indications to 136 * sun68k_bus_search about which locators must and must not 137 * be defined. 138 */ 139 oba = *ma; 140 oba.oba_bustag = &obio_space_tag; 141 oba.oba_paddr = LOCATOR_REQUIRED; 142 oba.oba_pri = LOCATOR_OPTIONAL; 143 144 /* Find all `early' obio devices */ 145 for (cpp = special; *cpp != NULL; cpp++) { 146 oba.oba_name = *cpp; 147 (void)config_search(sun68k_bus_search, self, &oba); 148 } 149 150 /* Find all other obio devices */ 151 oba.oba_name = NULL; 152 (void)config_search(sun68k_bus_search, self, &oba); 153 } 154 155 int 156 _obio_bus_map(t, btype, paddr, size, flags, vaddr, hp) 157 bus_space_tag_t t; 158 bus_type_t btype; 159 bus_addr_t paddr; 160 bus_size_t size; 161 vaddr_t vaddr; 162 int flags; 163 164 bus_space_handle_t *hp; 165 { 166 struct obio_softc *sc = t->cookie; 167 168 return (bus_space_map2(sc->sc_bustag, PMAP_OBIO, paddr, 169 size, flags | _SUN68K_BUS_MAP_USE_PROM, vaddr, hp)); 170 } 171 172 paddr_t 173 obio_bus_mmap(t, btype, paddr, off, prot, flags) 174 bus_space_tag_t t; 175 bus_type_t btype; 176 bus_addr_t paddr; 177 off_t off; 178 int prot; 179 int flags; 180 { 181 struct obio_softc *sc = t->cookie; 182 183 return (bus_space_mmap2(sc->sc_bustag, PMAP_OBIO, paddr, off, 184 prot, flags)); 185 } 186 187 /* 188 * The sun2 obio bus doesn't give bus errors, so we check on 189 * probed obio physical addresses to make sure they're ok. 190 */ 191 int 192 _obio_addr_bad(t, h, o, s) 193 bus_space_tag_t t; 194 bus_space_handle_t h; 195 bus_size_t o; 196 size_t s; 197 { 198 u_int pte; 199 paddr_t pa; 200 201 /* Get the physical address for this page. */ 202 pte = get_pte((vaddr_t) (h + o)); 203 if (!(pte & PG_VALID)) 204 return (-1); 205 pa = PG_PA(pte); 206 207 /* 208 * Return nonzero if it's bad. All sun2 Multibus 209 * machines have all obio devices between 0x2000 210 * and 0x4000, and all sun2 VME machines have all 211 * obio devices outside of this range. 212 */ 213 return ((!!cpu_has_multibus) != (pa >= 0x2000 && pa < 0x4000)); 214 } 215 216 int 217 _obio_bus_peek(t, h, o, s, vp) 218 bus_space_tag_t t; 219 bus_space_handle_t h; 220 bus_size_t o; 221 size_t s; 222 void *vp; 223 { 224 struct obio_softc *sc = t->cookie; 225 226 return (_obio_addr_bad(t, h, o, s) || 227 _bus_space_peek(sc->sc_bustag, h, o, s, vp)); 228 } 229 230 int 231 _obio_bus_poke(t, h, o, s, v) 232 bus_space_tag_t t; 233 bus_space_handle_t h; 234 bus_size_t o; 235 size_t s; 236 u_int32_t v; 237 { 238 struct obio_softc *sc = t->cookie; 239 240 return (_obio_addr_bad(t, h, o, s) || 241 _bus_space_poke(sc->sc_bustag, h, o, s, v)); 242 } 243