1 /* $NetBSD: autoconf.c,v 1.42 2009/03/18 10:22:35 cegger 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.42 2009/03/18 10:22:35 cegger 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 struct device *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 int s; 68 69 s = splhigh(); 70 if (config_rootfound("mainbus", NULL) == NULL) 71 panic("no mainbus found"); 72 73 /* 74 * Clear latched bus error registers which may have been 75 * caused by probes for non-existent devices. 76 */ 77 (*platform.bus_reset)(); 78 79 /* 80 * Hardware interrupts will be enabled in cpu_initclocks(9) 81 * to avoid hardclock(9) by CPU INT5 before softclockintr is 82 * initialized in initclocks(). 83 */ 84 } 85 86 /* 87 * Look at the string 'cp' and decode the boot device. Boot names 88 * can be something like 'bootp(0)netbsd' or 89 * 'scsi(0)disk(1)rdisk(0)partition(0)netbsd' or 90 * 'dksc(0,1,0)netbsd' 91 */ 92 void 93 makebootdev(const char *cp) 94 { 95 if (booted_protocol != NULL) 96 return; 97 98 booted_slot = booted_unit = booted_partition = 0; 99 100 if (strncmp(cp, "pci(", 4) == 0) { 101 cp += 4; 102 103 while (*cp && *cp != ')') 104 cp++; 105 106 if (*cp != ')') 107 return; 108 109 cp++; 110 } 111 112 if (strncmp(cp, "scsi(", 5) == 0) { 113 cp += 5; 114 if (*cp >= '0' && *cp <= '9') 115 booted_slot = *cp++ - '0'; 116 if (strncmp(cp, ")disk(", 6) == 0) { 117 cp += 6; 118 if (*cp >= '0' && *cp <= '9') 119 booted_unit = *cp++ - '0'; 120 } 121 /* XXX can rdisk() ever be other than 0? */ 122 if (strncmp(cp, ")rdisk(0)partition(", 19) == 0) { 123 cp += 19; 124 while (*cp >= '0' && *cp <= '9') 125 booted_partition = 126 booted_partition * 10 + *cp++ - '0'; 127 } 128 if (*cp != ')') 129 return; /* XXX ? */ 130 booted_protocol = "SCSI"; 131 return; 132 } 133 if (strncmp(cp, "dksc(", 5) == 0) { 134 cp += 5; 135 if (*cp >= '0' && *cp <= '9') 136 booted_slot = *cp++ - '0'; 137 if (*cp == ',') { 138 ++cp; 139 if (*cp >= '0' || *cp <= '9') 140 booted_unit = *cp++ - '0'; 141 if (*cp == ',') { 142 ++cp; 143 if (*cp >= '0' && *cp <= '9') 144 booted_partition = *cp++ - '0'; 145 } 146 } 147 if (*cp != ')') 148 return; /* XXX ??? */ 149 booted_protocol = "SCSI"; 150 return; 151 } 152 if (strncmp(cp, "bootp(", 6) == 0) { 153 /* XXX controller number? Needed to 154 handle > 1 network controller */ 155 booted_protocol = "BOOTP"; 156 return; 157 } 158 } 159 160 void 161 cpu_rootconf(void) 162 { 163 printf("boot device: %s\n", 164 booted_device ? booted_device->dv_xname : "<unknown>"); 165 166 setroot(booted_device, booted_partition); 167 } 168 169 /* 170 * Try to determine the boot device and set up some device properties 171 * to handle machine dependent quirks. 172 */ 173 174 #define BUILTIN_AHC_P(pa) \ 175 (((pa)->pa_bus == 0 && (pa)->pa_device == 1 && (pa)->pa_function == 0) || \ 176 ((pa)->pa_bus == 0 && (pa)->pa_device == 2 && (pa)->pa_function == 0)) 177 178 void 179 device_register(struct device *dev, void *aux) 180 { 181 static int found, initted, scsiboot, netboot; 182 struct device *parent = device_parent(dev); 183 184 if (mach_type == MACH_SGI_IP32 && 185 parent != NULL && device_is_a(parent, "pci")) { 186 struct pci_attach_args *pa = aux; 187 188 if (BUILTIN_AHC_P(pa)) { 189 if (prop_dictionary_set_bool(device_properties(dev), 190 "aic7xxx-use-target-defaults", true) == false) { 191 printf("WARNING: unable to set " 192 "aic7xxx-use-target-defaults property " 193 "for %s\n", dev->dv_xname); 194 } 195 196 if (prop_dictionary_set_bool(device_properties(dev), 197 "aic7xxx-override-ultra", true) == false) { 198 printf("WARNING: unable to set " 199 "aic7xxx-override-ultra property for %s\n", 200 dev->dv_xname); 201 } 202 } 203 } 204 205 /* 206 * The Set Engineering GIO Fast Ethernet controller has restrictions 207 * on DMA boundaries. 208 */ 209 if (device_is_a(dev, "tl")) { 210 struct device *grandparent; 211 prop_number_t gfe_boundary; 212 213 grandparent = device_parent(parent); 214 if (grandparent != NULL && device_is_a(grandparent, "giopci")) { 215 gfe_boundary = prop_number_create_integer(PAGE_SIZE); 216 KASSERT(gfe_boundary != NULL); 217 218 if (prop_dictionary_set(device_properties(dev), 219 "tl-dma-page-boundary", gfe_boundary) == false) { 220 printf("WARNING: unable to set " 221 "tl-dma-page-boundary property " 222 "for %s\n", dev->dv_xname); 223 } 224 prop_object_release(gfe_boundary); 225 return; 226 } 227 } 228 229 if (found) 230 return; 231 232 if (!initted && booted_protocol) { 233 scsiboot = strcmp(booted_protocol, "SCSI") == 0; 234 netboot = (strcmp(booted_protocol, "BOOTP") == 0); 235 initted = 1; 236 } 237 238 /* 239 * Handle SCSI boot device definitions 240 * wdsc -- IP12/22/24 241 * ahc -- IP32 242 */ 243 if ( (scsiboot && device_is_a(dev, "wdsc")) || 244 (scsiboot && device_is_a(dev, "ahc")) ) { 245 /* XXX device_unit() abuse */ 246 if (device_unit(dev) == booted_slot) 247 booted_controller = dev; 248 return; 249 } 250 251 /* 252 * If we found the boot controller, if check disk/tape/cdrom device 253 * on that controller matches. 254 */ 255 if (booted_controller && 256 (device_is_a(dev, "sd") || 257 device_is_a(dev, "st") || 258 device_is_a(dev, "cd"))) { 259 struct scsipibus_attach_args *sa = aux; 260 261 if (device_parent(parent) != booted_controller) 262 return; 263 if (booted_unit != sa->sa_periph->periph_target) 264 return; 265 booted_device = dev; 266 found = 1; 267 return; 268 } 269 270 /* 271 * Check if netboot device. 272 */ 273 if (netboot && 274 (device_is_a(dev, "sq") || 275 device_is_a(dev, "mec"))) { 276 /* XXX Check unit number? (Which we don't parse yet) */ 277 booted_device = dev; 278 found = 1; 279 return; 280 } 281 } 282