1 /* $NetBSD: autoconf.c,v 1.24 1995/04/10 05:44:08 mycroft Exp $ */ 2 3 /* 4 * Copyright (c) 1994 Gordon W. Ross 5 * Copyright (c) 1993 Adam Glass 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Adam Glass. 19 * 4. The name of the authors may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * Setup the system to run on the current machine. 36 * 37 * Configure() is called at boot time. Available 38 * devices are determined (from possibilities mentioned in ioconf.c), 39 * and the drivers are initialized. 40 */ 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/device.h> 45 #include <sys/map.h> 46 #include <sys/buf.h> 47 #include <sys/dkstat.h> 48 #include <sys/conf.h> 49 #include <sys/dmap.h> 50 #include <sys/reboot.h> 51 52 #include <vm/vm.h> 53 #include <vm/vm_kern.h> 54 #include <vm/vm_map.h> 55 56 #include <machine/autoconf.h> 57 #include <machine/cpu.h> 58 #include <machine/isr.h> 59 #include <machine/pte.h> 60 #include <machine/pmap.h> 61 62 extern int soft1intr(); 63 64 void mainbusattach __P((struct device *, struct device *, void *)); 65 void swapgeneric(); 66 void swapconf(), dumpconf(); 67 68 69 struct mainbus_softc { 70 struct device mainbus_dev; 71 }; 72 73 struct cfdriver mainbuscd = 74 { NULL, "mainbus", always_match, mainbusattach, DV_DULL, 75 sizeof(struct mainbus_softc), 0}; 76 77 void mainbusattach(parent, self, args) 78 struct device *parent; 79 struct device *self; 80 void *args; 81 { 82 struct cfdata *new_match; 83 84 printf("\n"); 85 while (1) { 86 new_match = config_search(NULL, self, NULL); 87 if (!new_match) break; 88 config_attach(self, new_match, NULL, NULL); 89 } 90 } 91 92 int nmi_intr(arg) 93 int arg; 94 { 95 printf("nmi interrupt received\n"); 96 return 1; 97 } 98 99 void configure() 100 { 101 int root_found; 102 103 /* General device autoconfiguration. */ 104 root_found = config_rootfound("mainbus", NULL); 105 if (!root_found) 106 panic("configure: mainbus not found"); 107 108 /* Install non-device interrupt handlers. */ 109 isr_add_autovect(nmi_intr, 0, 7); 110 isr_add_autovect(soft1intr, 0, 1); 111 112 #ifdef GENERIC 113 /* Choose root and swap devices. */ 114 swapgeneric(); 115 #endif 116 swapconf(); 117 dumpconf(); 118 } 119 120 /* 121 * Configure swap space and related parameters. 122 */ 123 void 124 swapconf() 125 { 126 struct swdevt *swp; 127 u_int maj; 128 int nblks; 129 130 for (swp = swdevt; swp->sw_dev != NODEV; swp++) { 131 maj = major(swp->sw_dev); 132 133 if (maj > nblkdev) /* paranoid? */ 134 break; 135 136 if (bdevsw[maj].d_psize) { 137 nblks = (*bdevsw[maj].d_psize)(swp->sw_dev); 138 if (nblks > 0 && 139 (swp->sw_nblks == 0 || swp->sw_nblks > nblks)) 140 swp->sw_nblks = nblks; 141 swp->sw_nblks = ctod(dtoc(swp->sw_nblks)); 142 } 143 } 144 } 145 146 int always_match(parent, cf, args) 147 struct device *parent; 148 void *cf; 149 void *args; 150 { 151 return 1; 152 } 153 154 /* 155 * Generic "bus" support functions. 156 */ 157 void bus_scan(parent, child, bustype) 158 struct device *parent; 159 void *child; 160 int bustype; 161 { 162 struct cfdata *cf = child; 163 struct confargs ca; 164 cfmatch_t match; 165 166 #ifdef DIAGNOSTIC 167 if (parent->dv_cfdata->cf_driver->cd_indirect) 168 panic("bus_scan: indirect?"); 169 if (cf->cf_fstate == FSTATE_STAR) 170 panic("bus_scan: FSTATE_STAR"); 171 #endif 172 173 ca.ca_bustype = bustype; 174 ca.ca_paddr = cf->cf_loc[0]; 175 ca.ca_intpri = cf->cf_loc[1]; 176 177 if ((bustype == BUS_VME16) || (bustype == BUS_VME32)) { 178 ca.ca_intvec = cf->cf_loc[2]; 179 } else { 180 ca.ca_intvec = -1; 181 } 182 183 match = cf->cf_driver->cd_match; 184 if ((*match)(parent, cf, &ca) > 0) { 185 config_attach(parent, cf, &ca, bus_print); 186 } 187 } 188 189 int 190 bus_print(args, name) 191 void *args; 192 char *name; 193 { 194 struct confargs *ca = args; 195 196 if (ca->ca_paddr != -1) 197 printf(" addr 0x%x", ca->ca_paddr); 198 if (ca->ca_intpri != -1) 199 printf(" level %d", ca->ca_intpri); 200 if (ca->ca_intvec != -1) 201 printf(" vector 0x%x", ca->ca_intvec); 202 /* XXXX print flags? */ 203 return(QUIET); 204 } 205 206 extern vm_offset_t tmp_vpages[]; 207 static const int bustype_to_ptetype[4] = { 208 PGT_OBMEM, 209 PGT_OBIO, 210 PGT_VME_D16, 211 PGT_VME_D32, 212 }; 213 214 /* 215 * Read addr with size len (1,2,4) into val. 216 * If this generates a bus error, return -1 217 * 218 * Create a temporary mapping, 219 * Try the access using peek_* 220 * Clean up temp. mapping 221 */ 222 int bus_peek(bustype, paddr, sz) 223 int bustype, paddr, sz; 224 { 225 int off, pte, rv; 226 vm_offset_t pgva; 227 caddr_t va; 228 229 if (bustype & ~3) 230 return -1; 231 232 off = paddr & PGOFSET; 233 paddr -= off; 234 pte = PA_PGNUM(paddr); 235 pte |= bustype_to_ptetype[bustype]; 236 pte |= (PG_VALID | PG_WRITE | PG_SYSTEM | PG_NC); 237 238 pgva = tmp_vpages[0]; 239 va = (caddr_t)pgva + off; 240 241 set_pte(pgva, pte); 242 243 /* 244 * OK, try the access using one of the assembly routines 245 * that will set pcb_onfault and catch any bus errors. 246 */ 247 switch (sz) { 248 case 1: 249 rv = peek_byte(va); 250 break; 251 case 2: 252 rv = peek_word(va); 253 break; 254 default: 255 printf(" bus_peek: invalid size=%d\n", sz); 256 rv = -1; 257 } 258 259 set_pte(pgva, PG_INVAL); 260 261 return rv; 262 } 263 264 static const int bustype_to_pmaptype[4] = { 265 0, 266 PMAP_OBIO, 267 PMAP_VME16, 268 PMAP_VME32, 269 }; 270 271 extern caddr_t dvma_vm_alloc(); 272 273 char * 274 bus_mapin(bustype, paddr, sz) 275 int bustype, paddr, sz; 276 { 277 int off, pa, pgs, pmt; 278 caddr_t va; 279 280 if (bustype & ~3) 281 return (NULL); 282 283 off = paddr & PGOFSET; 284 pa = paddr - off; 285 sz += off; 286 sz = sun3_round_page(sz); 287 288 pmt = bustype_to_pmaptype[bustype]; 289 pmt |= PMAP_NC; /* non-cached */ 290 291 /* Get some DVMA space. */ 292 va = dvma_vm_alloc(sz); 293 if (va == NULL) 294 panic("bus_mapin"); 295 296 /* Map it to the specified bus. */ 297 pmap_map((int)va, pa | pmt, pa + sz, VM_PROT_ALL); 298 299 return (va + off); 300 } 301