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