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