1 /* $NetBSD: obio.c,v 1.37 2001/09/05 13:21:10 tsutsui 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 and Gordon W. Ross. 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 <machine/autoconf.h> 44 #include <machine/mon.h> 45 #include <machine/pte.h> 46 47 #include <sun3/sun3/control.h> 48 #include <sun3/sun3/machdep.h> 49 #include <sun3/sun3/obio.h> 50 51 static int obio_match __P((struct device *, struct cfdata *, void *)); 52 static void obio_attach __P((struct device *, struct device *, void *)); 53 static int obio_print __P((void *, const char *parentname)); 54 static int obio_submatch __P((struct device *, struct cfdata *, void *)); 55 56 struct cfattach obio_ca = { 57 sizeof(struct device), obio_match, obio_attach 58 }; 59 60 static int 61 obio_match(parent, cf, aux) 62 struct device *parent; 63 struct cfdata *cf; 64 void *aux; 65 { 66 struct confargs *ca = aux; 67 68 if (ca->ca_bustype != BUS_OBIO) 69 return (0); 70 return(1); 71 } 72 73 /* 74 * We need control over the order of attachment on OBIO, 75 * so do "direct" style autoconfiguration with addresses 76 * tried in sequence starting at zero and incrementing 77 * by OBIO_INCR. Sun3 OBIO addresses are fixed forever. 78 */ 79 #define OBIO_INCR 0x020000 80 #define OBIO_END 0x200000 81 82 static void 83 obio_attach(parent, self, aux) 84 struct device *parent; 85 struct device *self; 86 void *aux; 87 { 88 struct confargs *ca = aux; 89 int addr; 90 91 printf("\n"); 92 93 /* Configure these in order of address. */ 94 for (addr = 0; addr < OBIO_END; addr += OBIO_INCR) { 95 /* Our parent set ca->ca_bustype already. */ 96 ca->ca_paddr = addr; 97 /* These are filled-in by obio_submatch. */ 98 ca->ca_intpri = -1; 99 ca->ca_intvec = -1; 100 (void) config_found_sm(self, ca, obio_print, obio_submatch); 101 } 102 } 103 104 /* 105 * Print out the confargs. The (parent) name is non-NULL 106 * when there was no match found by config_found(). 107 */ 108 static int 109 obio_print(args, name) 110 void *args; 111 const char *name; 112 { 113 114 /* Be quiet about empty OBIO locations. */ 115 if (name) 116 return(QUIET); 117 118 /* Otherwise do the usual. */ 119 return(bus_print(args, name)); 120 } 121 122 int 123 obio_submatch(parent, cf, aux) 124 struct device *parent; 125 struct cfdata *cf; 126 void *aux; 127 { 128 struct confargs *ca = aux; 129 cfmatch_t submatch; 130 131 /* 132 * Note that a defaulted address locator can never match 133 * the value of ca->ca_paddr set by the obio_attach loop. 134 * Without this diagnostic, any device with a defaulted 135 * address locator would always be silently unmatched. 136 * Therefore, just disallow default addresses on OBIO. 137 */ 138 #ifdef DIAGNOSTIC 139 if (cf->cf_paddr == -1) 140 panic("obio_submatch: invalid address for: %s%d\n", 141 cf->cf_driver->cd_name, cf->cf_unit); 142 #endif 143 144 /* 145 * Note that obio_attach calls config_found_sm() with 146 * this function as the "submatch" and ca->ca_paddr 147 * set to each of the possible OBIO locations, so we 148 * want to reject any unmatched address here. 149 */ 150 if (cf->cf_paddr != ca->ca_paddr) 151 return 0; 152 153 /* 154 * Note that the Sun3 does not really support vectored 155 * interrupts on OBIO, but the locator is permitted for 156 * consistency with the Sun3X. Verify its absence... 157 */ 158 #ifdef DIAGNOSTIC 159 if (cf->cf_intvec != -1) 160 panic("obio_submatch: %s%d can not have a vector\n", 161 cf->cf_driver->cd_name, cf->cf_unit); 162 #endif 163 164 /* 165 * Copy the locators into our confargs for the child. 166 * Note: ca->ca_bustype was set by our parent driver 167 * (mainbus) and ca->ca_paddr was set by obio_attach. 168 */ 169 ca->ca_intpri = cf->cf_intpri; 170 ca->ca_intvec = -1; 171 172 /* Now call the match function of the potential child. */ 173 submatch = cf->cf_attach->ca_match; 174 if (submatch == NULL) 175 panic("obio_submatch: no match function for: %s\n", 176 cf->cf_driver->cd_name); 177 178 return ((*submatch)(parent, cf, aux)); 179 } 180 181 182 /*****************************************************************/ 183 184 /* 185 * Spacing of "interesting" OBIO mappings. We will 186 * record only those with an OBIO address that is a 187 * multiple of SAVE_INCR and below SAVE_LAST. 188 * The saved mappings are just one page each, which 189 * is good enough for all the devices that use this. 190 */ 191 #define SAVE_SHIFT 17 192 #define SAVE_INCR (1<<SAVE_SHIFT) 193 #define SAVE_MASK (SAVE_INCR-1) 194 #define SAVE_SLOTS 16 195 #define SAVE_LAST (SAVE_SLOTS * SAVE_INCR) 196 197 /* 198 * This is our record of "interesting" OBIO mappings that 199 * the PROM has left in the virtual space reserved for it. 200 * Each non-null array element holds the virtual address 201 * of an OBIO mapping where the OBIO address mapped is: 202 * (array_index * SAVE_INCR) 203 * and the length of the mapping is one page. 204 */ 205 static caddr_t prom_mappings[SAVE_SLOTS]; 206 207 /* 208 * Find a virtual address for a device at physical address 'pa'. 209 * If one is found among the mappings already made by the PROM 210 * at power-up time, use it. Otherwise return 0 as a sign that 211 * a mapping will have to be created. 212 */ 213 caddr_t 214 obio_find_mapping(paddr_t pa, psize_t sz) 215 { 216 vsize_t off; 217 vaddr_t va; 218 219 off = pa & PGOFSET; 220 pa -= off; 221 sz += off; 222 223 /* The saved mappings are all one page long. */ 224 if (sz > NBPG) 225 return (caddr_t)0; 226 227 /* Within our table? */ 228 if (pa >= SAVE_LAST) 229 return (caddr_t)0; 230 231 /* Do we have this one? */ 232 va = (vaddr_t)prom_mappings[pa >> SAVE_SHIFT]; 233 if (va == 0) 234 return (caddr_t)0; 235 236 /* Found it! */ 237 return ((caddr_t)(va + off)); 238 } 239 240 /* 241 * This defines the permission bits to put in our PTEs. 242 * Device space is never cached, and the PROM appears to 243 * leave off the "no-cache" bit, so we can do the same. 244 */ 245 #define PGBITS (PG_VALID|PG_WRITE|PG_SYSTEM) 246 247 static void 248 save_prom_mappings __P((void)) 249 { 250 paddr_t pa; 251 vaddr_t segva, pgva; 252 int pte, sme, i; 253 254 segva = (vaddr_t)SUN3_MONSTART; 255 while (segva < (vaddr_t)SUN3_MONEND) { 256 sme = get_segmap(segva); 257 if (sme == SEGINV) { 258 segva += NBSG; 259 continue; /* next segment */ 260 } 261 /* 262 * We have a valid segmap entry, so examine the 263 * PTEs for all the pages in this segment. 264 */ 265 pgva = segva; /* starting page */ 266 segva += NBSG; /* ending page (next seg) */ 267 while (pgva < segva) { 268 pte = get_pte(pgva); 269 if ((pte & (PG_VALID | PG_TYPE)) == 270 (PG_VALID | PGT_OBIO)) 271 { 272 /* Have a valid OBIO mapping. */ 273 pa = PG_PA(pte); 274 /* Is it one we want to record? */ 275 if ((pa < SAVE_LAST) && 276 ((pa & SAVE_MASK) == 0)) 277 { 278 i = pa >> SAVE_SHIFT; 279 if (prom_mappings[i] == NULL) { 280 prom_mappings[i] = (caddr_t)pgva; 281 } 282 } 283 /* Make sure it has the right permissions. */ 284 if ((pte & PGBITS) != PGBITS) { 285 pte |= PGBITS; 286 set_pte(pgva, pte); 287 } 288 } 289 pgva += NBPG; /* next page */ 290 } 291 } 292 } 293 294 /* 295 * These are all the OBIO address that are required early in 296 * the life of the kernel. All are less than one page long. 297 */ 298 static paddr_t required_mappings[] = { 299 /* Basically the first six OBIO devices. */ 300 OBIO_ZS_KBD_MS, 301 OBIO_ZS_TTY_AB, 302 OBIO_EEPROM, 303 OBIO_CLOCK, 304 OBIO_MEMERR, 305 OBIO_INTERREG, 306 (paddr_t)-1, /* end marker */ 307 }; 308 309 static void 310 make_required_mappings __P((void)) 311 { 312 paddr_t *rmp; 313 314 rmp = required_mappings; 315 while (*rmp != (paddr_t)-1) { 316 if (!obio_find_mapping(*rmp, NBPG)) { 317 /* 318 * XXX - Ack! Need to create one! 319 * I don't think this can happen, but if 320 * it does, we can allocate a PMEG in the 321 * "high segment" and add it there. -gwr 322 */ 323 mon_printf("obio: no mapping for 0x%x\n", *rmp); 324 sunmon_abort(); 325 } 326 rmp++; 327 } 328 } 329 330 331 /* 332 * Find mappings for devices that are needed before autoconfiguration. 333 * We first look for and record any useful PROM mappings, then call 334 * the "init" functions for drivers that we need to use before the 335 * normal autoconfiguration calls configure(). Warning: this is 336 * called before pmap_bootstrap, so no allocation allowed! 337 */ 338 void 339 obio_init() 340 { 341 save_prom_mappings(); 342 make_required_mappings(); 343 344 /* 345 * Find the interrupt reg mapping and turn off the 346 * interrupts, otherwise the PROM clock interrupt 347 * would poll the zs and toggle some LEDs... 348 */ 349 intreg_init(); 350 } 351