1 /* $NetBSD: autoconf.c,v 1.45 2013/12/16 15:45:29 mrg Exp $ */ 2 3 /* 4 * Copyright (c) 2000 Soren S. Jorvang 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed for the 18 * NetBSD Project. See http://www.NetBSD.org/ for 19 * information about NetBSD. 20 * 4. The name of the author may not be used to endorse or promote products 21 * derived from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include <sys/cdefs.h> 36 __KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.45 2013/12/16 15:45:29 mrg Exp $"); 37 38 #include "opt_ddb.h" 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/buf.h> 43 #include <sys/conf.h> 44 #include <sys/device.h> 45 46 #include <machine/cpu.h> 47 #include <machine/sysconf.h> 48 #include <machine/machtype.h> 49 #include <machine/autoconf.h> 50 #include <machine/vmparam.h> /* for PAGE_SIZE */ 51 52 #include <dev/pci/pcivar.h> 53 54 #include <dev/scsipi/scsi_all.h> 55 #include <dev/scsipi/scsipi_all.h> 56 #include <dev/scsipi/scsiconf.h> 57 58 static device_t booted_controller = NULL; 59 static int booted_slot, booted_unit; 60 static const char *booted_protocol = NULL; 61 62 extern struct platform platform; 63 64 void 65 cpu_configure(void) 66 { 67 68 (void)splhigh(); 69 if (config_rootfound("mainbus", NULL) == NULL) 70 panic("no mainbus found"); 71 72 /* 73 * Clear latched bus error registers which may have been 74 * caused by probes for non-existent devices. 75 */ 76 (*platform.bus_reset)(); 77 78 /* 79 * Hardware interrupts will be enabled in cpu_initclocks(9) 80 * to avoid hardclock(9) by CPU INT5 before softclockintr is 81 * initialized in initclocks(). 82 */ 83 } 84 85 /* 86 * Look at the string 'cp' and decode the boot device. Boot names 87 * can be something like 'bootp(0)netbsd' or 88 * 'scsi(0)disk(1)rdisk(0)partition(0)netbsd' or 89 * 'dksc(0,1,0)netbsd' 90 */ 91 void 92 makebootdev(const char *cp) 93 { 94 if (booted_protocol != NULL) 95 return; 96 97 booted_slot = booted_unit = booted_partition = 0; 98 99 if (strncmp(cp, "pci(", 4) == 0) { 100 cp += 4; 101 102 while (*cp && *cp != ')') 103 cp++; 104 105 if (*cp != ')') 106 return; 107 108 cp++; 109 } 110 111 if (strncmp(cp, "scsi(", 5) == 0) { 112 cp += 5; 113 if (*cp >= '0' && *cp <= '9') 114 booted_slot = *cp++ - '0'; 115 if (strncmp(cp, ")disk(", 6) == 0) { 116 cp += 6; 117 if (*cp >= '0' && *cp <= '9') 118 booted_unit = *cp++ - '0'; 119 } 120 /* XXX can rdisk() ever be other than 0? */ 121 if (strncmp(cp, ")rdisk(0)partition(", 19) == 0) { 122 cp += 19; 123 while (*cp >= '0' && *cp <= '9') 124 booted_partition = 125 booted_partition * 10 + *cp++ - '0'; 126 } 127 if (*cp != ')') 128 return; /* XXX ? */ 129 booted_protocol = "SCSI"; 130 return; 131 } 132 if (strncmp(cp, "dksc(", 5) == 0) { 133 cp += 5; 134 if (*cp >= '0' && *cp <= '9') 135 booted_slot = *cp++ - '0'; 136 if (*cp == ',') { 137 ++cp; 138 if (*cp >= '0' || *cp <= '9') 139 booted_unit = *cp++ - '0'; 140 if (*cp == ',') { 141 ++cp; 142 if (*cp >= '0' && *cp <= '9') 143 booted_partition = *cp++ - '0'; 144 } 145 } 146 if (*cp != ')') 147 return; /* XXX ??? */ 148 booted_protocol = "SCSI"; 149 return; 150 } 151 if (strncmp(cp, "bootp(", 6) == 0) { 152 /* XXX controller number? Needed to 153 handle > 1 network controller */ 154 booted_protocol = "BOOTP"; 155 return; 156 } 157 } 158 159 void 160 cpu_rootconf(void) 161 { 162 printf("boot device: %s\n", 163 booted_device ? device_xname(booted_device) : "<unknown>"); 164 165 rootconf(); 166 } 167 168 /* 169 * Try to determine the boot device and set up some device properties 170 * to handle machine dependent quirks. 171 */ 172 173 #define BUILTIN_AHC_P(pa) \ 174 (((pa)->pa_bus == 0 && (pa)->pa_device == 1 && (pa)->pa_function == 0) || \ 175 ((pa)->pa_bus == 0 && (pa)->pa_device == 2 && (pa)->pa_function == 0)) 176 177 void 178 device_register(device_t dev, void *aux) 179 { 180 static int found, initted, scsiboot, netboot; 181 device_t parent = device_parent(dev); 182 183 if (mach_type == MACH_SGI_IP32 && 184 parent != NULL && device_is_a(parent, "pci")) { 185 struct pci_attach_args *pa = aux; 186 187 if (BUILTIN_AHC_P(pa)) { 188 if (prop_dictionary_set_bool(device_properties(dev), 189 "aic7xxx-use-target-defaults", true) == false) { 190 printf("WARNING: unable to set " 191 "aic7xxx-use-target-defaults property " 192 "for %s\n", device_xname(dev)); 193 } 194 195 if (prop_dictionary_set_bool(device_properties(dev), 196 "aic7xxx-override-ultra", true) == false) { 197 printf("WARNING: unable to set " 198 "aic7xxx-override-ultra property for %s\n", 199 device_xname(dev)); 200 } 201 } 202 } 203 204 /* 205 * The Set Engineering GIO Fast Ethernet controller has restrictions 206 * on DMA boundaries. 207 */ 208 if (device_is_a(dev, "tl")) { 209 device_t grandparent; 210 prop_number_t gfe_boundary; 211 212 grandparent = device_parent(parent); 213 if (grandparent != NULL && device_is_a(grandparent, "giopci")) { 214 gfe_boundary = prop_number_create_integer(PAGE_SIZE); 215 KASSERT(gfe_boundary != NULL); 216 217 if (prop_dictionary_set(device_properties(dev), 218 "tl-dma-page-boundary", gfe_boundary) == false) { 219 printf("WARNING: unable to set " 220 "tl-dma-page-boundary property " 221 "for %s\n", device_xname(dev)); 222 } 223 prop_object_release(gfe_boundary); 224 return; 225 } 226 } 227 228 if (found) 229 return; 230 231 if (!initted && booted_protocol) { 232 scsiboot = strcmp(booted_protocol, "SCSI") == 0; 233 netboot = (strcmp(booted_protocol, "BOOTP") == 0); 234 initted = 1; 235 } 236 237 /* 238 * Handle SCSI boot device definitions 239 * wdsc -- IP12/22/24 240 * ahc -- IP32 241 */ 242 if ( (scsiboot && device_is_a(dev, "wdsc")) || 243 (scsiboot && device_is_a(dev, "ahc")) ) { 244 /* XXX device_unit() abuse */ 245 if (device_unit(dev) == booted_slot) 246 booted_controller = dev; 247 return; 248 } 249 250 /* 251 * If we found the boot controller, if check disk/tape/cdrom device 252 * on that controller matches. 253 */ 254 if (booted_controller && 255 (device_is_a(dev, "sd") || 256 device_is_a(dev, "st") || 257 device_is_a(dev, "cd"))) { 258 struct scsipibus_attach_args *sa = aux; 259 260 if (device_parent(parent) != booted_controller) 261 return; 262 if (booted_unit != sa->sa_periph->periph_target) 263 return; 264 booted_device = dev; 265 found = 1; 266 return; 267 } 268 269 /* 270 * Check if netboot device. 271 */ 272 if (netboot && 273 (device_is_a(dev, "sq") || 274 device_is_a(dev, "mec"))) { 275 /* XXX Check unit number? (Which we don't parse yet) */ 276 booted_device = dev; 277 found = 1; 278 return; 279 } 280 } 281