obio.c revision 1.9
1/* $NetBSD: obio.c,v 1.9 1998/02/05 04:58:00 gwr 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/machdep.h> 48#include <sun3/sun3x/obio.h> 49 50static int obio_match __P((struct device *, struct cfdata *, void *)); 51static void obio_attach __P((struct device *, struct device *, void *)); 52static int obio_print __P((void *, const char *parentname)); 53static int obio_submatch __P((struct device *, struct cfdata *, void *)); 54 55struct cfattach obio_ca = { 56 sizeof(struct device), obio_match, obio_attach 57}; 58 59static int 60obio_match(parent, cf, aux) 61 struct device *parent; 62 struct cfdata *cf; 63 void *aux; 64{ 65 struct confargs *ca = aux; 66 67 if (ca->ca_bustype != BUS_OBIO) 68 return (0); 69 return(1); 70} 71 72/* 73 * We need some control over the order of attachment on OBIO, 74 * and all OBIO device addresses are known and fixed foerver. 75 * Therefore, this uses a list of addresses to attach. 76 * XXX - Any other way to control search/attach order? 77 * 78 * Warning: This whole list is very carefully ordered! 79 * In general, anything not already shown here should 80 * be added at or near the end. 81 */ 82static int obio_alist[] = { 83 84 /* Misc. registers - needed by many things */ 85 OBIO_ENABLEREG, 86 OBIO_BUSERRREG, 87 OBIO_DIAGREG, /* leds.c */ 88 OBIO_IDPROM1, /* idprom.c (3/470) */ 89 OBIO_MEMREG, /* memerr.c */ 90 OBIO_INTERREG, /* intreg.c */ 91 92 /* Zilog UARTs */ 93 OBIO_ZS_KBD_MS, 94 OBIO_ZS_TTY_AB, 95 96 /* eeprom.c */ 97 OBIO_EEPROM, 98 99 /* Note: This must come after OBIO_IDPROM1. */ 100 OBIO_IDPROM2, /* idprom.c (3/80) */ 101 102 /* Note: Must probe for the Intersil first! */ 103 OBIO_CLOCK1, /* clock.c (3/470) */ 104 OBIO_CLOCK2, /* clock.c (3/80) */ 105 106 /* This is used by the Ethernet and SCSI drivers. */ 107 OBIO_IOMMU, 108 109 OBIO_INTEL_ETHER, 110 OBIO_LANCE_ETHER, 111 112 OBIO_EMULEX_SCSI, /* 3/80 only */ 113 114 /* ...todo... */ 115 OBIO_FDC, 116 OBIO_PRINTER_PORT, 117}; 118#define OBIO_ALIST_LEN (sizeof(obio_alist) / \ 119 sizeof(obio_alist[0])) 120 121static void 122obio_attach(parent, self, aux) 123 struct device *parent; 124 struct device *self; 125 void *aux; 126{ 127 struct confargs *ca = aux; 128 int i; 129 130 printf("\n"); 131 132 /* Configure these in the order listed above. */ 133 for (i = 0; i < OBIO_ALIST_LEN; i++) { 134 /* Our parent set ca->ca_bustype already. */ 135 ca->ca_paddr = obio_alist[i]; 136 /* These are filled-in by obio_submatch. */ 137 ca->ca_intpri = -1; 138 ca->ca_intvec = -1; 139 (void) config_found_sm(self, ca, obio_print, obio_submatch); 140 } 141} 142 143/* 144 * Print out the confargs. The (parent) name is non-NULL 145 * when there was no match found by config_found(). 146 */ 147static int 148obio_print(args, name) 149 void *args; 150 const char *name; 151{ 152 153 /* Be quiet about empty OBIO locations. */ 154 if (name) 155 return(QUIET); 156 157 /* Otherwise do the usual. */ 158 return(bus_print(args, name)); 159} 160 161int 162obio_submatch(parent, cf, aux) 163 struct device *parent; 164 struct cfdata *cf; 165 void *aux; 166{ 167 struct confargs *ca = aux; 168 cfmatch_t submatch; 169 170 /* 171 * Note that a defaulted address locator can never match 172 * the value of ca->ca_paddr set by the obio_attach loop. 173 * Without this diagnostic, any device with a defaulted 174 * address locator would always be silently unmatched. 175 * Therefore, just disallow default addresses on OBIO. 176 */ 177#ifdef DIAGNOSTIC 178 if (cf->cf_paddr == -1) 179 panic("obio_submatch: invalid address for: %s%d\n", 180 cf->cf_driver->cd_name, cf->cf_unit); 181#endif 182 183 /* 184 * Note that obio_attach calls config_found_sm() with 185 * this function as the "submatch" and ca->ca_paddr 186 * set to each of the possible OBIO locations, so we 187 * want to reject any unmatched address here. 188 */ 189 if (cf->cf_paddr != ca->ca_paddr) 190 return 0; 191 192 /* 193 * Copy the locators into our confargs for the child. 194 * Note: ca->ca_bustype was set by our parent driver 195 * (mainbus) and ca->ca_paddr was set by obio_attach. 196 */ 197 ca->ca_intpri = cf->cf_intpri; 198 ca->ca_intvec = cf->cf_intvec; 199 200 /* Now call the match function of the potential child. */ 201 submatch = cf->cf_attach->ca_match; 202 if (submatch == NULL) 203 panic("obio_submatch: no match function for: %s\n", 204 cf->cf_driver->cd_name); 205 206 return ((*submatch)(parent, cf, aux)); 207} 208 209 210/*****************************************************************/ 211 212/* 213 * This is our record of "interesting" OBIO mappings that 214 * the PROM has left in the virtual space reserved for it. 215 * Each non-null array element holds the virtual address 216 * of an OBIO mapping where the OBIO address mapped is: 217 * (array_index * SAVE_INCR) 218 * and the length of the mapping is one page. 219 */ 220static struct prom_map { 221 vm_offset_t pa, va; 222} prom_mappings[] = { 223 { OBIO_ENABLEREG, 0 }, /* regs: Sys ENA, Bus ERR, etc. */ 224 { OBIO_ZS_KBD_MS, 0 }, /* Keyboard and Mouse */ 225 { OBIO_ZS_TTY_AB, 0 }, /* Serial Ports */ 226 { OBIO_EEPROM, 0 }, /* EEPROM/IDPROM/clock */ 227}; 228#define PROM_MAP_CNT (sizeof(prom_mappings) / \ 229 sizeof(prom_mappings[0])) 230 231/* 232 * Find a virtual address for a device at physical address 'pa'. 233 * If one is found among the mappings already made by the PROM 234 * at power-up time, use it. Otherwise return 0 as a sign that 235 * a mapping will have to be created. 236 */ 237caddr_t 238obio_find_mapping(int pa, int size) 239{ 240 int i, off; 241 242 if (size >= NBPG) 243 return (caddr_t)0; 244 245 off = pa & PGOFSET; 246 pa -= off; 247 248 for (i = 0; i < PROM_MAP_CNT; i++) { 249 if (pa == prom_mappings[i].pa) { 250 return ((caddr_t)(prom_mappings[i].va + off)); 251 } 252 } 253 return (caddr_t)0; 254} 255 256/* 257 * Search the PROM page tables for OBIO mappings that 258 * we would like to borrow. 259 */ 260static void 261save_prom_mappings __P((void)) 262{ 263 int *mon_pte; 264 vm_offset_t va, 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 += NBPG, 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 */ 298static void 299make_required_mappings __P((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 */ 325void 326obio_init() 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