1 /* $NetBSD: obio.c,v 1.36 1998/12/13 19:08:43 kleink 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(int pa, int sz) 215 { 216 vaddr_t off, va; 217 218 off = pa & PGOFSET; 219 pa -= off; 220 sz += off; 221 222 /* The saved mappings are all one page long. */ 223 if (sz > NBPG) 224 return (caddr_t)0; 225 226 /* Within our table? */ 227 if (pa >= SAVE_LAST) 228 return (caddr_t)0; 229 230 /* Do we have this one? */ 231 va = (vaddr_t)prom_mappings[pa >> SAVE_SHIFT]; 232 if (va == 0) 233 return (caddr_t)0; 234 235 /* Found it! */ 236 return ((caddr_t)(va + off)); 237 } 238 239 /* 240 * This defines the permission bits to put in our PTEs. 241 * Device space is never cached, and the PROM appears to 242 * leave off the "no-cache" bit, so we can do the same. 243 */ 244 #define PGBITS (PG_VALID|PG_WRITE|PG_SYSTEM) 245 246 static void 247 save_prom_mappings __P((void)) 248 { 249 vm_offset_t pa, segva, pgva; 250 int pte, sme, i; 251 252 segva = (vm_offset_t)SUN3_MONSTART; 253 while (segva < (vm_offset_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 += NBPG; /* 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 vm_offset_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 (vm_offset_t)-1, /* end marker */ 305 }; 306 307 static void 308 make_required_mappings __P((void)) 309 { 310 vm_offset_t *rmp; 311 312 rmp = required_mappings; 313 while (*rmp != (vm_offset_t)-1) { 314 if (!obio_find_mapping(*rmp, NBPG)) { 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