obio.c revision 1.1
1/* $NetBSD: obio.c,v 1.1 1997/01/14 20:57:03 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/pte.h> 45#include <machine/mon.h> 46#include <machine/obio.h> 47 48short *enable_reg; 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 59struct cfdriver obio_cd = { 60 NULL, "obio", DV_DULL 61}; 62 63static int 64obio_match(parent, cf, aux) 65 struct device *parent; 66 struct cfdata *cf; 67 void *aux; 68{ 69 struct confargs *ca = aux; 70 71 if (ca->ca_bustype != BUS_OBIO) 72 return (0); 73 return(1); 74} 75 76/* 77 * We need some control over the order of attachment on OBIO, 78 * and all OBIO device addresses are known and fixed foerver. 79 * Therefore, this uses a list of addresses to attach. 80 * XXX - Any other way to control search/attach order? 81 */ 82static int obio_alist[] = { 83 OBIO_ZS_KBD_MS, 84 OBIO_ZS_TTY_AB, 85 86 OBIO_EEPROM, /* the next two are part of the eeprom */ 87 OBIO_IDPROM2, /* 3/80 only */ 88 OBIO_CLOCK2, /* 3/80 only */ 89 90 OBIO_CLOCK1, /* 3/470 only */ 91 92 /* These are all in the same page - could be just one driver... */ 93 OBIO_ENABLEREG, 94 OBIO_BUSERRREG, 95 OBIO_DIAGREG, 96 OBIO_IDPROM1, 97 OBIO_MEMREG, 98 OBIO_INTERREG, 99 100 OBIO_P4_REG, 101 OBIO_IOMMU, 102 103 OBIO_INTEL_ETHER, 104 OBIO_LANCE_ETHER, 105 106 /* ...todo... */ 107 OBIO_FDC, 108 OBIO_PRINTER_PORT, 109}; 110#define OBIO_ALIST_LEN (sizeof(obio_alist) / \ 111 sizeof(obio_alist[0])) 112 113static void 114obio_attach(parent, self, aux) 115 struct device *parent; 116 struct device *self; 117 void *aux; 118{ 119 struct confargs *ca = aux; 120 int i; 121 122 printf("\n"); 123 124 /* Configure these in order of address. */ 125 for (i = 0; i < OBIO_ALIST_LEN; i++) { 126 /* We know ca_bustype == BUS_OBIO */ 127 ca->ca_paddr = obio_alist[i]; 128 ca->ca_intpri = -1; 129 ca->ca_intvec = -1; 130 (void) config_found_sm(self, ca, obio_print, obio_submatch); 131 } 132} 133 134/* 135 * Print out the confargs. The (parent) name is non-NULL 136 * when there was no match found by config_found(). 137 */ 138static int 139obio_print(args, name) 140 void *args; 141 const char *name; 142{ 143 struct confargs *ca = args; 144 145 /* Be quiet about empty OBIO locations. */ 146 if (name) 147 return(QUIET); 148 149 if (ca->ca_paddr != -1) 150 printf(" addr 0x%x", ca->ca_paddr); 151 if (ca->ca_intpri != -1) 152 printf(" level %d", ca->ca_intpri); 153 154 return(UNCONF); 155} 156 157int 158obio_submatch(parent, cf, aux) 159 struct device *parent; 160 struct cfdata *cf; 161 void *aux; 162{ 163 struct confargs *ca = aux; 164 cfmatch_t submatch; 165 166 /* 167 * Default addresses are mostly useless for OBIO. 168 * The address assignments are fixed for all time, 169 * so our config files might as well reflect that. 170 */ 171#ifdef DIAGNOSTIC 172 if (cf->cf_paddr == -1) 173 panic("obio_submatch: invalid address for: %s%d\n", 174 cf->cf_driver->cd_name, cf->cf_unit); 175#endif 176 177 /* This enforces exact address match. */ 178 if (cf->cf_paddr != ca->ca_paddr) 179 return 0; 180 181 /* Now call the match function of the potential child. */ 182 submatch = cf->cf_attach->ca_match; 183 if (submatch == NULL) 184 panic("obio_submatch: no match function for: %s\n", 185 cf->cf_driver->cd_name); 186 187 return ((*submatch)(parent, cf, aux)); 188} 189 190 191/*****************************************************************/ 192 193/* 194 * This is our record of "interesting" OBIO mappings that 195 * the PROM has left in the virtual space reserved for it. 196 * Each non-null array element holds the virtual address 197 * of an OBIO mapping where the OBIO address mapped is: 198 * (array_index * SAVE_INCR) 199 * and the length of the mapping is one page. 200 */ 201static struct prom_map { 202 vm_offset_t pa, va; 203} prom_mappings[] = { 204 { OBIO_ZS_KBD_MS, 0 }, /* Keyboard and Mouse */ 205 { OBIO_ZS_TTY_AB, 0 }, /* Serial Ports */ 206 { OBIO_EEPROM, 0 }, /* EEPROM/IDPROM/clock */ 207 { OBIO_ENABLEREG, 0 }, /* regs: Sys ENA, Bus ERR, etc. */ 208}; 209#define PROM_MAP_CNT (sizeof(prom_mappings) / \ 210 sizeof(prom_mappings[0])) 211 212/* 213 * Find a virtual address for a device at physical address 'pa'. 214 * If one is found among the mappings already made by the PROM 215 * at power-up time, use it. Otherwise return 0 as a sign that 216 * a mapping will have to be created. 217 */ 218caddr_t 219obio_find_mapping(int pa, int size) 220{ 221 int i, off; 222 223 if (size >= NBPG) 224 return (caddr_t)0; 225 226 off = pa & PGOFSET; 227 pa -= off; 228 229 for (i = 0; i < PROM_MAP_CNT; i++) { 230 if (pa == prom_mappings[i].pa) { 231 return ((caddr_t)(prom_mappings[i].va + off)); 232 } 233 } 234 return (caddr_t)0; 235} 236 237/* 238 * Search the PROM page tables for OBIO mappings that 239 * we would like to borrow. 240 */ 241static void 242save_prom_mappings __P((void)) 243{ 244 int *mon_pte; 245 vm_offset_t va, pa; 246 int i; 247 248 /* Note: mon_ctbl[0] maps MON_KDB_START */ 249 mon_pte = *romVectorPtr->monptaddr; 250 251 for (va = MON_KDB_START; va < MONEND; 252 va += NBPG, mon_pte++) 253 { 254 /* Is this a valid mapping to OBIO? */ 255 /* XXX - Some macros would be nice... */ 256 if ((*mon_pte & 0xF0000003) != 0x60000001) 257 continue; 258 259 /* Yes it is. Is this a mapping we want? */ 260 pa = *mon_pte & MMU_SHORT_PTE_BASEADDR; 261 for (i = 0; i < PROM_MAP_CNT; i++) { 262 if (pa != prom_mappings[i].pa) 263 continue; 264 /* Yes, we want it. Save the va? */ 265 if (prom_mappings[i].va == 0) { 266 prom_mappings[i].va = va; 267 } 268 } 269 } 270 271} 272 273/* 274 * These are all the OBIO address that are required early in 275 * the life of the kernel. All are less than one page long. 276 * This function should make any required mappings that we 277 * were not able to find among the PROM monitor's mappings. 278 */ 279static void 280make_required_mappings __P((void)) 281{ 282 int i; 283 284 for (i = 0; i < PROM_MAP_CNT; i++) { 285 if (prom_mappings[i].va == 0) { 286 /* 287 * Actually, the PROM always has all the 288 * "required" mappings we need, (smile) 289 * but this makes sure that is true. 290 */ 291 mon_printf("obio: no mapping for 0x%x\n", 292 prom_mappings[i].pa); 293 mon_panic("obio: Ancient PROM?\n"); 294 } 295 } 296} 297 298 299/* 300 * Find mappings for devices that are needed before autoconfiguration. 301 * We first look for and record any useful PROM mappings, then call 302 * the "init" functions for drivers that we need to use before the 303 * normal autoconfiguration calls configure(). Warning: this is 304 * called before pmap_bootstrap, so no allocation allowed! 305 */ 306void 307obio_init() 308{ 309 save_prom_mappings(); 310 make_required_mappings(); 311 312 /* Init drivers that use the required OBIO mappings. */ 313 idprom_init(); 314 eeprom_init(); 315 zs_init(); 316 317 enable_reg = (short*) obio_find_mapping(OBIO_ENABLEREG, 2); 318 intreg_init(); 319 clock_init(); 320} 321 322caddr_t 323obio_alloc(obio_addr, obio_size) 324 int obio_addr, obio_size; 325{ 326 caddr_t cp; 327 328 cp = obio_find_mapping((vm_offset_t)obio_addr, obio_size); 329 if (cp) return (cp); 330 331 cp = bus_mapin(BUS_OBIO, obio_addr, obio_size); 332 return (cp); 333} 334