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