obio.c revision 1.28
1/* $NetBSD: obio.c,v 1.28 2006/10/03 13:02:32 tsutsui 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.28 2006/10/03 13:02:32 tsutsui 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/bus.h> 50#include <machine/mon.h> 51#include <machine/pte.h> 52 53#include <sun3/sun3/machdep.h> 54#include <sun3/sun3x/obio.h> 55 56static int obio_match(struct device *, struct cfdata *, void *); 57static void obio_attach(struct device *, struct device *, void *); 58static int obio_print(void *, const char *); 59static int obio_submatch(struct device *, struct cfdata *, 60 const int *, void *); 61 62struct obio_softc { 63 struct device sc_dev; 64 bus_space_tag_t sc_bustag; 65 bus_dma_tag_t sc_dmatag; 66}; 67CFATTACH_DECL(obio, sizeof(struct obio_softc), 68 obio_match, obio_attach, NULL, NULL); 69 70static int obio_attached; 71 72static int obio_bus_map(bus_space_tag_t, bus_type_t, bus_addr_t, bus_size_t, 73 int, vaddr_t, bus_space_handle_t *); 74static paddr_t obio_bus_mmap(bus_space_tag_t, bus_type_t, bus_addr_t, 75 off_t, int, int); 76 77static struct sun68k_bus_space_tag obio_space_tag = { 78 NULL, /* cookie */ 79 NULL, /* parent bus space tag */ 80 obio_bus_map, /* bus_space_map */ 81 NULL, /* bus_space_unmap */ 82 NULL, /* bus_space_subregion */ 83 NULL, /* bus_space_barrier */ 84 obio_bus_mmap, /* bus_space_mmap */ 85 NULL, /* bus_intr_establish */ 86 NULL, /* bus_space_peek_N */ 87 NULL /* bus_space_poke_N */ 88}; 89 90static int 91obio_match(struct device *parent, struct cfdata *cf, void *aux) 92{ 93 struct confargs *ca = aux; 94 95 if (obio_attached) 96 return 0; 97 98 if (ca->ca_bustype != BUS_OBIO) 99 return 0; 100 101 if (ca->ca_name != NULL && strcmp(cf->cf_name, ca->ca_name) != 0) 102 return 0; 103 104 return 1; 105} 106 107/* 108 * We need control over the order of attachment on OBIO, 109 * so do "direct" style autoconfiguration with addresses 110 * from the list below. OBIO addresses are fixed forever. 111 * 112 * Warning: This whole list is very carefully ordered! 113 * In general, anything not already shown here should 114 * be added at or near the end. 115 */ 116static paddr_t obio_alist[] = { 117 118 /* This is used by the Ethernet and SCSI drivers. */ 119 OBIO_IOMMU, 120 121 /* Misc. registers - needed by many things */ 122 OBIO_ENABLEREG, 123 OBIO_BUSERRREG, 124 OBIO_DIAGREG, /* leds.c */ 125 OBIO_IDPROM1, /* idprom.c (3/470) */ 126 OBIO_MEMREG, /* memerr.c */ 127 OBIO_INTERREG, /* intreg.c */ 128 129 /* Zilog UARTs */ 130 OBIO_ZS_KBD_MS, 131 OBIO_ZS_TTY_AB, 132 133 /* eeprom.c */ 134 OBIO_EEPROM, 135 136 /* Note: This must come after OBIO_IDPROM1. */ 137 OBIO_IDPROM2, /* idprom.c (3/80) */ 138 139 /* Note: Must probe for the Intersil first! */ 140 OBIO_CLOCK1, /* clock.c (3/470) */ 141 OBIO_CLOCK2, /* clock.c (3/80) */ 142 143 OBIO_INTEL_ETHER, 144 OBIO_LANCE_ETHER, 145 146 /* Need esp DMA before SCSI. */ 147 OBIO_EMULEX_DMA, /* 3/80 only */ 148 OBIO_EMULEX_SCSI, /* 3/80 only */ 149 150 /* Memory subsystem */ 151 OBIO_PCACHE_TAGS, 152 OBIO_ECCPARREG, 153 OBIO_IOC_TAGS, 154 OBIO_IOC_FLUSH, 155 156 OBIO_FDC, /* floppy disk (3/80) */ 157 OBIO_PRINTER_PORT, /* printer port (3/80) */ 158}; 159#define OBIO_ALIST_LEN (sizeof(obio_alist) / \ 160 sizeof(obio_alist[0])) 161 162static void 163obio_attach(struct device *parent, struct device *self, void *aux) 164{ 165 struct confargs *ca = aux; 166 struct obio_softc *sc = (void *)self; 167 struct confargs oba; 168 int i; 169 170 obio_attached = 1; 171 172 printf("\n"); 173 174 sc->sc_bustag = ca->ca_bustag; 175 sc->sc_dmatag = ca->ca_dmatag; 176 177 obio_space_tag.cookie = sc; 178 obio_space_tag.parent = sc->sc_bustag; 179 180 oba = *ca; 181 oba.ca_bustag = &obio_space_tag; 182 183 /* Configure these in the order listed above. */ 184 for (i = 0; i < OBIO_ALIST_LEN; i++) { 185 /* Our parent set ca->ca_bustype already. */ 186 oba.ca_paddr = obio_alist[i]; 187 /* These are filled-in by obio_submatch. */ 188 oba.ca_intpri = -1; 189 oba.ca_intvec = -1; 190 (void)config_found_sm_loc(self, "obio", NULL, &oba, obio_print, 191 obio_submatch); 192 } 193} 194 195/* 196 * Print out the confargs. The (parent) name is non-NULL 197 * when there was no match found by config_found(). 198 */ 199static int 200obio_print(void *args, const char *name) 201{ 202 203 /* Be quiet about empty OBIO locations. */ 204 if (name) 205 return(QUIET); 206 207 /* Otherwise do the usual. */ 208 return(bus_print(args, name)); 209} 210 211int 212obio_submatch(struct device *parent, struct cfdata *cf, 213 const int *ldesc, void *aux) 214{ 215 struct confargs *ca = aux; 216 217 /* 218 * Note that a defaulted address locator can never match 219 * the value of ca->ca_paddr set by the obio_attach loop. 220 * Without this diagnostic, any device with a defaulted 221 * address locator would always be silently unmatched. 222 * Therefore, just disallow default addresses on OBIO. 223 */ 224#ifdef DIAGNOSTIC 225 if (cf->cf_paddr == -1) 226 panic("obio_submatch: invalid address for: %s%d", 227 cf->cf_name, cf->cf_unit); 228#endif 229 230 /* 231 * Note that obio_attach calls config_found_sm() with 232 * this function as the "submatch" and ca->ca_paddr 233 * set to each of the possible OBIO locations, so we 234 * want to reject any unmatched address here. 235 */ 236 if (cf->cf_paddr != ca->ca_paddr) 237 return 0; 238 239 /* 240 * Copy the locators into our confargs for the child. 241 * Note: ca->ca_bustype was set by our parent driver 242 * (mainbus) and ca->ca_paddr was set by obio_attach. 243 */ 244 ca->ca_intpri = cf->cf_intpri; 245 ca->ca_intvec = cf->cf_intvec; 246 247 /* Now call the match function of the potential child. */ 248 return (config_match(parent, cf, aux)); 249} 250 251 252/*****************************************************************/ 253 254/* 255 * This is our record of "interesting" OBIO mappings that 256 * the PROM has left in the virtual space reserved for it. 257 * Each row of the array holds a virtual address and the 258 * physical address it maps to (if found). 259 */ 260static struct prom_map { 261 paddr_t pa; 262 vaddr_t va; 263} prom_mappings[] = { 264 { OBIO_ENABLEREG, 0 }, /* regs: Sys ENA, Bus ERR, etc. */ 265 { OBIO_ZS_KBD_MS, 0 }, /* Keyboard and Mouse */ 266 { OBIO_ZS_TTY_AB, 0 }, /* Serial Ports */ 267 { OBIO_EEPROM, 0 }, /* EEPROM/IDPROM/clock */ 268}; 269#define PROM_MAP_CNT (sizeof(prom_mappings) / \ 270 sizeof(prom_mappings[0])) 271 272/* 273 * Find a virtual address for a device at physical address 'pa'. 274 * If one is found among the mappings already made by the PROM 275 * at power-up time, use it and return 0. Otherwise return errno 276 * as a sign that a mapping will have to be created. 277 */ 278int 279find_prom_map(paddr_t pa, bus_type_t iospace, int sz, vaddr_t *vap) 280{ 281 int i; 282 vsize_t off; 283 284 off = pa & PGOFSET; 285 pa -= off; 286 sz += off; 287 288 /* The saved mappings are all one page long. */ 289 if (sz > PAGE_SIZE) 290 return EINVAL; 291 292 /* Linear search for it. The list is short. */ 293 for (i = 0; i < PROM_MAP_CNT; i++) { 294 if (pa == prom_mappings[i].pa) { 295 *vap = prom_mappings[i].va + off; 296 return 0; 297 } 298 } 299 return ENOENT; 300} 301 302/* 303 * Search the PROM page tables for OBIO mappings that 304 * we would like to borrow. 305 */ 306static void 307save_prom_mappings(void) 308{ 309 int *mon_pte; 310 vaddr_t va; 311 paddr_t pa; 312 int i; 313 314 /* Note: mon_ctbl[0] maps SUN3X_MON_KDB_BASE */ 315 mon_pte = *romVectorPtr->monptaddr; 316 317 for (va = SUN3X_MON_KDB_BASE; va < SUN3X_MONEND; 318 va += PAGE_SIZE, mon_pte++) 319 { 320 /* Is this a valid mapping to OBIO? */ 321 /* XXX - Some macros would be nice... */ 322 if ((*mon_pte & 0xF0000003) != 0x60000001) 323 continue; 324 325 /* Yes it is. Is this a mapping we want? */ 326 pa = *mon_pte & MMU_SHORT_PTE_BASEADDR; 327 for (i = 0; i < PROM_MAP_CNT; i++) { 328 if (pa != prom_mappings[i].pa) 329 continue; 330 /* Yes, we want it. Save the va? */ 331 if (prom_mappings[i].va == 0) { 332 prom_mappings[i].va = va; 333 } 334 } 335 } 336 337} 338 339/* 340 * These are all the OBIO address that are required early in 341 * the life of the kernel. All are less than one page long. 342 * This function should make any required mappings that we 343 * were not able to find among the PROM monitor's mappings. 344 */ 345static void 346make_required_mappings(void) 347{ 348 int i; 349 350 for (i = 0; i < PROM_MAP_CNT; i++) { 351 if (prom_mappings[i].va == 0) { 352 /* 353 * Actually, the PROM always has all the 354 * "required" mappings we need, (smile) 355 * but this makes sure that is true. 356 */ 357 mon_printf("obio: no mapping for pa=0x%x\n", 358 prom_mappings[i].pa); 359 sunmon_abort(); /* Ancient PROM? */ 360 } 361 } 362} 363 364 365/* 366 * Find mappings for devices that are needed before autoconfiguration. 367 * We first look for and record any useful PROM mappings, then call 368 * the "init" functions for drivers that we need to use before the 369 * normal autoconfiguration calls configure(). Warning: this is 370 * called before pmap_bootstrap, so no allocation allowed! 371 */ 372void 373obio_init(void) 374{ 375 save_prom_mappings(); 376 make_required_mappings(); 377 378 enable_init(); 379 380 /* 381 * Find the interrupt reg mapping and turn off the 382 * interrupts, otherwise the PROM clock interrupt 383 * would poll the zs and toggle some LEDs... 384 */ 385 intreg_init(); 386} 387 388int 389obio_bus_map(bus_space_tag_t t, bus_type_t btype, bus_addr_t paddr, 390 bus_size_t size, int flags, vaddr_t vaddr, bus_space_handle_t *hp) 391{ 392 struct obio_softc *sc = t->cookie; 393 394 return bus_space_map2(sc->sc_bustag, PMAP_OBIO, paddr, size, 395 flags | _SUN68K_BUS_MAP_USE_PROM, vaddr, hp); 396} 397 398paddr_t 399obio_bus_mmap(bus_space_tag_t t, bus_type_t btype, bus_addr_t paddr, off_t off, 400 int prot, int flags) 401{ 402 struct obio_softc *sc = t->cookie; 403 404 return bus_space_mmap2(sc->sc_bustag, PMAP_OBIO, paddr, off, prot, 405 flags); 406} 407