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