1 /* $NetBSD: obio.c,v 1.26 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.26 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/machdep.h> 53 #include <sun3/sun3x/obio.h> 54 55 static int obio_match(struct device *, struct cfdata *, void *); 56 static void obio_attach(struct device *, struct device *, void *); 57 static int obio_print(void *, const char *); 58 static int obio_submatch(struct device *, struct cfdata *, 59 const int *, void *); 60 61 CFATTACH_DECL(obio, sizeof(struct device), 62 obio_match, obio_attach, NULL, NULL); 63 64 static int 65 obio_match(struct device *parent, struct cfdata *cf, 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 * from the list below. OBIO addresses are fixed forever. 78 * 79 * Warning: This whole list is very carefully ordered! 80 * In general, anything not already shown here should 81 * be added at or near the end. 82 */ 83 static int obio_alist[] = { 84 85 /* This is used by the Ethernet and SCSI drivers. */ 86 OBIO_IOMMU, 87 88 /* Misc. registers - needed by many things */ 89 OBIO_ENABLEREG, 90 OBIO_BUSERRREG, 91 OBIO_DIAGREG, /* leds.c */ 92 OBIO_IDPROM1, /* idprom.c (3/470) */ 93 OBIO_MEMREG, /* memerr.c */ 94 OBIO_INTERREG, /* intreg.c */ 95 96 /* Zilog UARTs */ 97 OBIO_ZS_KBD_MS, 98 OBIO_ZS_TTY_AB, 99 100 /* eeprom.c */ 101 OBIO_EEPROM, 102 103 /* Note: This must come after OBIO_IDPROM1. */ 104 OBIO_IDPROM2, /* idprom.c (3/80) */ 105 106 /* Note: Must probe for the Intersil first! */ 107 OBIO_CLOCK1, /* clock.c (3/470) */ 108 OBIO_CLOCK2, /* clock.c (3/80) */ 109 110 OBIO_INTEL_ETHER, 111 OBIO_LANCE_ETHER, 112 113 /* Need esp DMA before SCSI. */ 114 OBIO_EMULEX_DMA, /* 3/80 only */ 115 OBIO_EMULEX_SCSI, /* 3/80 only */ 116 117 /* Memory subsystem */ 118 OBIO_PCACHE_TAGS, 119 OBIO_ECCPARREG, 120 OBIO_IOC_TAGS, 121 OBIO_IOC_FLUSH, 122 123 OBIO_FDC, /* floppy disk (3/80) */ 124 OBIO_PRINTER_PORT, /* printer port (3/80) */ 125 }; 126 #define OBIO_ALIST_LEN (sizeof(obio_alist) / \ 127 sizeof(obio_alist[0])) 128 129 static void 130 obio_attach(struct device *parent, struct device *self, void *aux) 131 { 132 struct confargs *ca = aux; 133 int i; 134 135 printf("\n"); 136 137 /* Configure these in the order listed above. */ 138 for (i = 0; i < OBIO_ALIST_LEN; i++) { 139 /* Our parent set ca->ca_bustype already. */ 140 ca->ca_paddr = obio_alist[i]; 141 /* These are filled-in by obio_submatch. */ 142 ca->ca_intpri = -1; 143 ca->ca_intvec = -1; 144 (void) config_found_sm_loc(self, "obio", NULL, ca, obio_print, 145 obio_submatch); 146 } 147 } 148 149 /* 150 * Print out the confargs. The (parent) name is non-NULL 151 * when there was no match found by config_found(). 152 */ 153 static int 154 obio_print(void *args, const char *name) 155 { 156 157 /* Be quiet about empty OBIO locations. */ 158 if (name) 159 return(QUIET); 160 161 /* Otherwise do the usual. */ 162 return(bus_print(args, name)); 163 } 164 165 int 166 obio_submatch(struct device *parent, struct cfdata *cf, 167 const int *ldesc, void *aux) 168 { 169 struct confargs *ca = aux; 170 171 /* 172 * Note that a defaulted address locator can never match 173 * the value of ca->ca_paddr set by the obio_attach loop. 174 * Without this diagnostic, any device with a defaulted 175 * address locator would always be silently unmatched. 176 * Therefore, just disallow default addresses on OBIO. 177 */ 178 #ifdef DIAGNOSTIC 179 if (cf->cf_paddr == -1) 180 panic("obio_submatch: invalid address for: %s%d", 181 cf->cf_name, cf->cf_unit); 182 #endif 183 184 /* 185 * Note that obio_attach calls config_found_sm() with 186 * this function as the "submatch" and ca->ca_paddr 187 * set to each of the possible OBIO locations, so we 188 * want to reject any unmatched address here. 189 */ 190 if (cf->cf_paddr != ca->ca_paddr) 191 return 0; 192 193 /* 194 * Copy the locators into our confargs for the child. 195 * Note: ca->ca_bustype was set by our parent driver 196 * (mainbus) and ca->ca_paddr was set by obio_attach. 197 */ 198 ca->ca_intpri = cf->cf_intpri; 199 ca->ca_intvec = cf->cf_intvec; 200 201 /* Now call the match function of the potential child. */ 202 return (config_match(parent, cf, aux)); 203 } 204 205 206 /*****************************************************************/ 207 208 /* 209 * This is our record of "interesting" OBIO mappings that 210 * the PROM has left in the virtual space reserved for it. 211 * Each row of the array holds a virtual address and the 212 * physical address it maps to (if found). 213 */ 214 static struct prom_map { 215 paddr_t pa; 216 vaddr_t va; 217 } prom_mappings[] = { 218 { OBIO_ENABLEREG, 0 }, /* regs: Sys ENA, Bus ERR, etc. */ 219 { OBIO_ZS_KBD_MS, 0 }, /* Keyboard and Mouse */ 220 { OBIO_ZS_TTY_AB, 0 }, /* Serial Ports */ 221 { OBIO_EEPROM, 0 }, /* EEPROM/IDPROM/clock */ 222 }; 223 #define PROM_MAP_CNT (sizeof(prom_mappings) / \ 224 sizeof(prom_mappings[0])) 225 226 /* 227 * Find a virtual address for a device at physical address 'pa'. 228 * If one is found among the mappings already made by the PROM 229 * at power-up time, use it. Otherwise return 0 as a sign that 230 * a mapping will have to be created. 231 */ 232 caddr_t 233 obio_find_mapping(paddr_t pa, psize_t sz) 234 { 235 int i; 236 vsize_t off; 237 238 off = pa & PGOFSET; 239 pa -= off; 240 sz += off; 241 242 /* The saved mappings are all one page long. */ 243 if (sz > PAGE_SIZE) 244 return (caddr_t)0; 245 246 /* Linear search for it. The list is short. */ 247 for (i = 0; i < PROM_MAP_CNT; i++) { 248 if (pa == prom_mappings[i].pa) { 249 return ((caddr_t)(prom_mappings[i].va + off)); 250 } 251 } 252 return (caddr_t)0; 253 } 254 255 /* 256 * Search the PROM page tables for OBIO mappings that 257 * we would like to borrow. 258 */ 259 static void 260 save_prom_mappings(void) 261 { 262 int *mon_pte; 263 vaddr_t va; 264 paddr_t pa; 265 int i; 266 267 /* Note: mon_ctbl[0] maps SUN3X_MON_KDB_BASE */ 268 mon_pte = *romVectorPtr->monptaddr; 269 270 for (va = SUN3X_MON_KDB_BASE; va < SUN3X_MONEND; 271 va += PAGE_SIZE, mon_pte++) 272 { 273 /* Is this a valid mapping to OBIO? */ 274 /* XXX - Some macros would be nice... */ 275 if ((*mon_pte & 0xF0000003) != 0x60000001) 276 continue; 277 278 /* Yes it is. Is this a mapping we want? */ 279 pa = *mon_pte & MMU_SHORT_PTE_BASEADDR; 280 for (i = 0; i < PROM_MAP_CNT; i++) { 281 if (pa != prom_mappings[i].pa) 282 continue; 283 /* Yes, we want it. Save the va? */ 284 if (prom_mappings[i].va == 0) { 285 prom_mappings[i].va = va; 286 } 287 } 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 * This function should make any required mappings that we 296 * were not able to find among the PROM monitor's mappings. 297 */ 298 static void 299 make_required_mappings(void) 300 { 301 int i; 302 303 for (i = 0; i < PROM_MAP_CNT; i++) { 304 if (prom_mappings[i].va == 0) { 305 /* 306 * Actually, the PROM always has all the 307 * "required" mappings we need, (smile) 308 * but this makes sure that is true. 309 */ 310 mon_printf("obio: no mapping for pa=0x%x\n", 311 prom_mappings[i].pa); 312 sunmon_abort(); /* Ancient PROM? */ 313 } 314 } 315 } 316 317 318 /* 319 * Find mappings for devices that are needed before autoconfiguration. 320 * We first look for and record any useful PROM mappings, then call 321 * the "init" functions for drivers that we need to use before the 322 * normal autoconfiguration calls configure(). Warning: this is 323 * called before pmap_bootstrap, so no allocation allowed! 324 */ 325 void 326 obio_init(void) 327 { 328 save_prom_mappings(); 329 make_required_mappings(); 330 331 enable_init(); 332 333 /* 334 * Find the interrupt reg mapping and turn off the 335 * interrupts, otherwise the PROM clock interrupt 336 * would poll the zs and toggle some LEDs... 337 */ 338 intreg_init(); 339 } 340