1 /* $NetBSD: bus_subr.c,v 1.8 1997/06/10 19:36:53 veego 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 /* 40 * bus_xxx support functions 41 */ 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/device.h> 46 47 #include <vm/vm.h> 48 #include <vm/vm_kern.h> 49 #include <vm/vm_map.h> 50 51 #include <machine/autoconf.h> 52 #include <machine/cpu.h> 53 #include <machine/pte.h> 54 #include <machine/pmap.h> 55 #include <machine/machdep.h> 56 #include <machine/mon.h> 57 58 /* 59 * bus_scan: 60 * This function is passed to config_search() by the attach function 61 * for each of the "bus" drivers (obctl, obio, obmem, vmes, vmel). 62 * The purpose of this function is to copy the "locators" into our 63 * confargs structure, so child drivers may use the confargs both 64 * as match parameters and as temporary storage for the defaulted 65 * locator values determined in the child_match and preserved for 66 * the child_attach function. If the bus attach functions just 67 * used config_found, then we would not have an opportunity to 68 * setup the confargs for each child match and attach call. 69 */ 70 int bus_scan(parent, cf, aux) 71 struct device *parent; 72 struct cfdata *cf; 73 void *aux; 74 { 75 struct confargs *ca = aux; 76 cfmatch_t mf; 77 78 #ifdef DIAGNOSTIC 79 if (cf->cf_fstate == FSTATE_STAR) 80 panic("bus_scan: FSTATE_STAR"); 81 #endif 82 83 /* 84 * Copy the locators into our confargs. 85 * Our parent set ca->ca_bustype already. 86 */ 87 ca->ca_paddr = cf->cf_paddr; 88 ca->ca_intpri = cf->cf_intpri; 89 ca->ca_intvec = cf->cf_intvec; 90 91 /* 92 * Note that this allows the match function to save 93 * defaulted locators in the confargs that will be 94 * preserved for the related attach call. 95 * XXX - This is a hack... 96 */ 97 mf = cf->cf_attach->ca_match; 98 if ((*mf)(parent, cf, ca) > 0) { 99 config_attach(parent, cf, ca, bus_print); 100 } 101 return (0); 102 } 103 104 /* 105 * bus_print: 106 * Just print out the final (non-default) locators. 107 * The parent name is non-NULL when there was no match 108 * found by config_found(). 109 */ 110 int 111 bus_print(args, name) 112 void *args; 113 const char *name; 114 { 115 struct confargs *ca = args; 116 117 if (name) 118 printf("%s:", name); 119 120 if (ca->ca_paddr != -1) 121 printf(" addr 0x%x", ca->ca_paddr); 122 if (ca->ca_intpri != -1) 123 printf(" ipl %d", ca->ca_intpri); 124 if (ca->ca_intvec != -1) 125 printf(" vect 0x%x", ca->ca_intvec); 126 127 return(UNCONF); 128 } 129 130 /****************************************************************/ 131 /* support functions */ 132 133 label_t *nofault; 134 135 /* These are defined in pmap.c */ 136 extern vm_offset_t tmp_vpages[]; 137 extern int tmp_vpages_inuse; 138 139 static const int bustype_to_patype[4] = { 140 0, /* OBMEM */ 141 0, /* OBIO */ 142 PMAP_VME16, /* VMED16 */ 143 PMAP_VME32, /* VMED32 */ 144 }; 145 146 /* 147 * Read addr with size len (1,2,4) into val. 148 * If this generates a bus error, return -1 149 * 150 * Create a temporary mapping, 151 * Try the access using peek_* 152 * Clean up temp. mapping 153 */ 154 int 155 bus_peek(bustype, paddr, sz) 156 int bustype, paddr, sz; 157 { 158 int offset, rtn, s; 159 vm_offset_t va_page; 160 caddr_t va; 161 162 /* XXX - Must fix for VME support... */ 163 if (bustype != OBIO && bustype != OBMEM) 164 return -1; 165 166 offset = paddr & ~(MMU_PAGE_MASK); 167 paddr = m68k_trunc_page(paddr); 168 paddr |= bustype_to_patype[bustype]; 169 paddr |= PMAP_NC; 170 171 s = splimp(); 172 if (tmp_vpages_inuse) 173 panic("bus_peek: temporary vpages are in use."); 174 tmp_vpages_inuse++; 175 176 va_page = tmp_vpages[1]; 177 va = (caddr_t) va_page + offset; 178 179 pmap_enter(pmap_kernel(), va_page, paddr, (VM_PROT_READ|VM_PROT_WRITE), 180 TRUE); 181 182 switch (sz) { 183 case 1: 184 rtn = peek_byte(va); 185 break; 186 case 2: 187 rtn = peek_word(va); 188 break; 189 case 4: 190 rtn = peek_long(va); 191 break; 192 default: 193 printf(" bus_peek: invalid size=%d\n", sz); 194 rtn = -1; 195 } 196 197 pmap_remove(pmap_kernel(), va_page, va_page + NBPG); 198 --tmp_vpages_inuse; 199 splx(s); 200 201 return (rtn); 202 } 203 204 205 void * 206 bus_mapin(bustype, paddr, sz) 207 int bustype, paddr, sz; 208 { 209 int off, pa, pmt; 210 vm_offset_t va, retval; 211 212 if (bustype & ~3) 213 return (NULL); 214 215 off = paddr & PGOFSET; 216 pa = paddr - off; 217 sz += off; 218 sz = round_page(sz); 219 220 pmt = PMAP_NC; /* non-cached */ 221 222 /* Get some kernel virtual address space. */ 223 va = kmem_alloc_wait(kernel_map, sz); 224 if (va == 0) 225 panic("bus_mapin"); 226 retval = va + off; 227 228 /* Map it to the specified bus. */ 229 #if 0 230 /* This has a problem with wrap-around... (on the sun3x? -j) */ 231 pmap_map((int)va, pa | pmt, pa + sz, VM_PROT_ALL); 232 #else 233 do { 234 pmap_enter(pmap_kernel(), va, pa | pmt, VM_PROT_ALL, FALSE); 235 va += NBPG; 236 pa += NBPG; 237 } while ((sz -= NBPG) > 0); 238 #endif 239 240 return ((void*)retval); 241 } 242 243 /* from hp300: badbaddr() */ 244 int 245 peek_byte(addr) 246 register caddr_t addr; 247 { 248 label_t faultbuf; 249 register int x; 250 251 nofault = &faultbuf; 252 if (setjmp(&faultbuf)) { 253 nofault = NULL; 254 return(-1); 255 } 256 x = *(volatile u_char *)addr; 257 nofault = NULL; 258 return(x); 259 } 260 261 int 262 peek_word(addr) 263 register caddr_t addr; 264 { 265 label_t faultbuf; 266 register int x; 267 268 nofault = &faultbuf; 269 if (setjmp(&faultbuf)) { 270 nofault = NULL; 271 return(-1); 272 } 273 x = *(volatile u_short *)addr; 274 nofault = NULL; 275 return(x); 276 } 277 278 int 279 peek_long(addr) 280 register caddr_t addr; 281 { 282 label_t faultbuf; 283 register int x; 284 285 nofault = &faultbuf; 286 if (setjmp(&faultbuf)) { 287 nofault = NULL; 288 return(-1); 289 } 290 x = *(volatile int *)addr; 291 nofault = NULL; 292 return(x); 293 } 294