Home | History | Annotate | Line # | Download | only in sgimips
      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