1 /* $NetBSD: bus_subr.c,v 1.5 1997/04/25 18:02:47 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 /* 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 /* This is defined in _startup.c */ 136 extern vm_offset_t tmp_vpages[]; 137 138 static const int bustype_to_patype[4] = { 139 0, /* OBMEM */ 140 0, /* OBIO */ 141 PMAP_VME16, /* VMED16 */ 142 PMAP_VME32, /* VMED32 */ 143 }; 144 145 /* 146 * Read addr with size len (1,2,4) into val. 147 * If this generates a bus error, return -1 148 * 149 * Create a temporary mapping, 150 * Try the access using peek_* 151 * Clean up temp. mapping 152 */ 153 int bus_peek(bustype, paddr, sz) 154 int bustype, paddr, sz; 155 { 156 int offset, rtn; 157 vm_offset_t va_page; 158 caddr_t va; 159 160 /* XXX - Must fix for VME support... */ 161 if (bustype != OBIO && bustype != OBMEM) 162 return -1; 163 164 offset = paddr & ~(MMU_PAGE_MASK); 165 paddr = _trunc_page(paddr); 166 paddr |= bustype_to_patype[bustype]; 167 paddr |= PMAP_NC; 168 169 va_page = tmp_vpages[0]; 170 va = (caddr_t) va_page + offset; 171 172 pmap_enter(pmap_kernel(), va_page, paddr, (VM_PROT_READ|VM_PROT_WRITE), 173 TRUE); 174 175 switch (sz) { 176 case 1: 177 rtn = peek_byte(va); 178 break; 179 case 2: 180 rtn = peek_word(va); 181 break; 182 case 4: 183 rtn = peek_long(va); 184 break; 185 default: 186 printf(" bus_peek: invalid size=%d\n", sz); 187 rtn = -1; 188 } 189 190 pmap_remove(pmap_kernel(), va_page, va_page + NBPG); 191 192 193 return rtn; 194 } 195 196 197 void * 198 bus_mapin(bustype, paddr, sz) 199 int bustype, paddr, sz; 200 { 201 int off, pa, pmt; 202 vm_offset_t va, retval; 203 204 if (bustype & ~3) 205 return (NULL); 206 207 off = paddr & PGOFSET; 208 pa = paddr - off; 209 sz += off; 210 sz = round_page(sz); 211 212 pmt = PMAP_NC; /* non-cached */ 213 214 /* Get some kernel virtual address space. */ 215 va = kmem_alloc_wait(kernel_map, sz); 216 if (va == 0) 217 panic("bus_mapin"); 218 retval = va + off; 219 220 /* Map it to the specified bus. */ 221 #if 0 /* XXX */ 222 /* This has a problem with wrap-around... */ 223 pmap_map((int)va, pa | pmt, pa + sz, VM_PROT_ALL); 224 #else 225 do { 226 pmap_enter(pmap_kernel(), va, pa | pmt, VM_PROT_ALL, FALSE); 227 va += NBPG; 228 pa += NBPG; 229 } while ((sz -= NBPG) > 0); 230 #endif 231 232 return ((void*)retval); 233 } 234 235 /* from hp300: badbaddr() */ 236 int 237 peek_byte(addr) 238 register caddr_t addr; 239 { 240 label_t faultbuf; 241 register int x; 242 243 nofault = &faultbuf; 244 if (setjmp(&faultbuf)) { 245 nofault = NULL; 246 return(-1); 247 } 248 x = *(volatile u_char *)addr; 249 nofault = NULL; 250 return(x); 251 } 252 253 int 254 peek_word(addr) 255 register caddr_t addr; 256 { 257 label_t faultbuf; 258 register int x; 259 260 nofault = &faultbuf; 261 if (setjmp(&faultbuf)) { 262 nofault = NULL; 263 return(-1); 264 } 265 x = *(volatile u_short *)addr; 266 nofault = NULL; 267 return(x); 268 } 269 270 int 271 peek_long(addr) 272 register caddr_t addr; 273 { 274 label_t faultbuf; 275 register int x; 276 277 nofault = &faultbuf; 278 if (setjmp(&faultbuf)) { 279 nofault = NULL; 280 return(-1); 281 } 282 x = *(volatile int *)addr; 283 nofault = NULL; 284 return(x); 285 } 286