Home | History | Annotate | Line # | Download | only in sun68k
      1 /*	$NetBSD: autoconf.c,v 1.32 2021/08/07 16:19:06 thorpej 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, Gordon W. Ross, and Matthew Fredette.
      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  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 /*
     33  * Setup the system to run on the current machine.
     34  *
     35  * Configure() is called at boot time.  Available devices are
     36  * determined (from possibilities mentioned in ioconf.c), and
     37  * the drivers are initialized.
     38  */
     39 
     40 #include <sys/cdefs.h>
     41 __KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.32 2021/08/07 16:19:06 thorpej Exp $");
     42 
     43 #include "opt_kgdb.h"
     44 
     45 #include <sys/param.h>
     46 #include <sys/systm.h>
     47 #include <sys/conf.h>
     48 #include <sys/device.h>
     49 #include <sys/reboot.h>
     50 
     51 #include "locators.h"
     52 
     53 #include "scsibus.h"
     54 
     55 #if NSCSIBUS > 0
     56 #include <dev/scsipi/scsi_all.h>
     57 #include <dev/scsipi/scsipi_all.h>
     58 #include <dev/scsipi/scsiconf.h>
     59 #endif /* NSCSIBUS > 0 */
     60 
     61 #include <machine/autoconf.h>
     62 #include <machine/intr.h>
     63 #include <machine/promlib.h>
     64 
     65 #ifdef	KGDB
     66 #include <sys/kgdb.h>
     67 #endif
     68 
     69 /*
     70  * Do general device autoconfiguration,
     71  * then choose root device (etc.)
     72  * Called by sys/kern/subr_autoconf.c: configure()
     73  */
     74 void
     75 cpu_configure(void)
     76 {
     77 
     78 	/*
     79 	 * Consider stopping for a debugger before
     80 	 * autoconfiguration.
     81 	 */
     82 	if (boothowto & RB_KDB) {
     83 #ifdef KGDB
     84 		/* XXX - Ask on console for kgdb_dev? */
     85 		/* Note: this will just return if kgdb_dev==NODEV */
     86 		kgdb_connect(1);
     87 #else	/* KGDB */
     88 		/* Either DDB or no debugger (just PROM). */
     89 		Debugger();
     90 #endif	/* KGDB */
     91 	}
     92 
     93 	/* General device autoconfiguration. */
     94 	if (config_rootfound("mainbus", NULL) == NULL)
     95 		panic("%s: mainbus not found", __func__);
     96 
     97 	/*
     98 	 * Now that device autoconfiguration is finished,
     99 	 * we can safely enable interrupts.
    100 	 */
    101 	printf("enabling interrupts\n");
    102 	(void)spl0();
    103 }
    104 
    105 static int 	mainbus_match(device_t, cfdata_t, void *);
    106 static void	mainbus_attach(device_t, device_t, void *);
    107 
    108 CFATTACH_DECL_NEW(mainbus, 0,
    109     mainbus_match, mainbus_attach, NULL, NULL);
    110 
    111 /*
    112  * Probe for the mainbus; always succeeds.
    113  */
    114 static int
    115 mainbus_match(device_t parent, cfdata_t cf, void *aux)
    116 {
    117 
    118 	return 1;
    119 }
    120 
    121 /*
    122  * Do "direct" configuration for the bus types on mainbus.
    123  * This controls the order of autoconfig for important things
    124  * used early.  For example, idprom is used by Ether drivers.
    125  */
    126 static void
    127 mainbus_attach(device_t parent, device_t self, void *args)
    128 {
    129 	struct mainbus_attach_args ma;
    130 	const char *const *cpp;
    131 	static const char *const special[] = {
    132 		/* find these first */
    133 		"obio",
    134 		"obmem",
    135 		NULL
    136 	};
    137 
    138 	aprint_normal("\n");
    139 
    140 	ma.ma_bustag = &mainbus_space_tag;
    141 	ma.ma_dmatag = &mainbus_dma_tag;
    142 	ma.ma_paddr = LOCATOR_FORBIDDEN;
    143 	ma.ma_pri = LOCATOR_FORBIDDEN;
    144 
    145 	/* Find all `early' mainbus buses */
    146 	for (cpp = special; *cpp != NULL; cpp++) {
    147 		ma.ma_name = *cpp;
    148 		(void)config_found(self, &ma, NULL, CFARGS_NONE);
    149 	}
    150 
    151 	/* Find the remaining buses */
    152 	ma.ma_name = NULL;
    153 	(void)config_found(self, &ma, NULL, CFARGS_NONE);
    154 
    155 	/* Lastly, find the PROM console */
    156 	ma.ma_name = "pcons";
    157 	(void)config_found(self, &ma, NULL, CFARGS_NONE);
    158 }
    159 
    160 /*
    161  * sun68k_bus_search:
    162  * This function is passed to config_search_ia() by the attach function
    163  * for each of the "bus" drivers (obio, obmem, mbmem, vme, ...).
    164  * The purpose of this function is to copy the "locators" into our
    165  * _attach_args structure, so child drivers may use the _attach_args both
    166  * as match parameters and as temporary storage for the defaulted
    167  * locator values determined in the child_match and preserved for
    168  * the child_attach function.  If the bus attach functions just
    169  * used config_found, then we would not have an opportunity to
    170  * setup the _attach_args for each child match and attach call.
    171  */
    172 int
    173 sun68k_bus_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
    174 {
    175 	struct mainbus_attach_args *map = aux;
    176 	struct mainbus_attach_args ma;
    177 
    178 	/* Check whether we're looking for a specifically named device */
    179 	if (map->ma_name != NULL && strcmp(map->ma_name, cf->cf_name) != 0)
    180 		return 0;
    181 
    182 #ifdef	DIAGNOSTIC
    183 	if (cf->cf_fstate == FSTATE_STAR)
    184 		panic("%s: FSTATE_STAR", __func__);
    185 #endif
    186 
    187 	/*
    188 	 * Prepare to copy the locators into our _attach_args.
    189 	 */
    190 	ma = *map;
    191 	ma.ma_name = NULL;
    192 
    193 	/*
    194 	 * Avoid entries which are missing attach information that
    195 	 * they need, or that have attach information that they
    196 	 * cannot have.  The individual bus attach functions tell
    197 	 * us this by initializing the locator fields in the attach
    198 	 * args they provide us.
    199 	 *
    200 	 * At the same time we copy these values into the _attach_args
    201 	 * will pass to the device's match and attach functions.
    202 	 */
    203 #ifdef	DIAGNOSTIC
    204 #define BAD_LOCATOR(ma_loc, what) \
    205 	panic("%s: %s %s for: %s%d", __func__, \
    206 	    map->ma_loc == LOCATOR_REQUIRED ? "missing" : "unexpected", \
    207 	    what, cf->cf_name, cf->cf_unit)
    208 #else
    209 #define BAD_LOCATOR(ma_loc, what) return 0
    210 #endif
    211 
    212 #define CHECK_LOCATOR(ma_loc, cf_loc, what) \
    213 	if ((map->ma_loc == LOCATOR_FORBIDDEN && cf->cf_loc != -1) || \
    214 	    (map->ma_loc == LOCATOR_REQUIRED && cf->cf_loc == -1)) \
    215 		BAD_LOCATOR(ma_loc, what); \
    216 	else \
    217 		ma.ma_loc = cf->cf_loc
    218 
    219 	CHECK_LOCATOR(ma_paddr, cf_loc[MBIOCF_ADDR], "address");
    220 	CHECK_LOCATOR(ma_pri, cf_loc[MBIOCF_IPL], "ipl");
    221 
    222 	/*
    223 	 * Note that this allows the probe function to save
    224 	 * defaulted locators in the _attach_args that will be
    225 	 * preserved for the related attach call.
    226 	 * XXX - This is a hack...
    227 	 */
    228 	if (config_probe(parent, cf, &ma)) {
    229 		config_attach(parent, cf, &ma, sun68k_bus_print, CFARGS_NONE);
    230 	}
    231 	return 0;
    232 }
    233 
    234 /*
    235  * sun68k_bus_print:
    236  * Just print out the final (non-default) locators.
    237  * The parent name is non-NULL when there was no match
    238  * found by config_found().
    239  */
    240 int
    241 sun68k_bus_print(void *args, const char *name)
    242 {
    243 	struct mainbus_attach_args *ma = args;
    244 
    245 	if (name)
    246 		aprint_normal("%s:", name);
    247 
    248 	if (ma->ma_paddr != -1)
    249 		aprint_normal(" addr 0x%x", (unsigned int) ma->ma_paddr);
    250 	if (ma->ma_pri != -1)
    251 		aprint_normal(" ipl %d", ma->ma_pri);
    252 
    253 	return UNCONF;
    254 }
    255 
    256 /****************************************************************/
    257 
    258 /* This takes the args: name, ctlr, unit */
    259 typedef device_t (*findfunc_t)(char *, int, int);
    260 
    261 static device_t net_find(char *, int, int);
    262 #if NSCSIBUS > 0
    263 static device_t scsi_find(char *, int, int);
    264 #endif /* NSCSIBUS > 0 */
    265 static device_t xx_find(char *, int, int);
    266 
    267 struct prom_n2f {
    268 	const char name[4];
    269 	findfunc_t func;
    270 };
    271 static struct prom_n2f prom_dev_table[] = {
    272 	{ "ie",		net_find },
    273 	{ "ec",		net_find },
    274 	{ "le",		net_find },
    275 #if NSCSIBUS > 0
    276 	{ "sd",		scsi_find },
    277 #endif /* NSCSIBUS > 0 */
    278 	{ "xy",		xx_find },
    279 	{ "xd",		xx_find },
    280 	{ "",		0 },
    281 };
    282 
    283 /*
    284  * This converts one hex number to an integer, and returns
    285  * an updated string pointer.
    286  */
    287 static const char *str2hex(const char *, int *);
    288 static const char *
    289 str2hex(const char *p, int *_val)
    290 {
    291 	int val;
    292 	int c;
    293 
    294 	for (val = 0;; val = (val << 4) + c, p++) {
    295 		c = *((const unsigned char *)p);
    296 		if (c >= 'a')
    297 			c-= ('a' + 10);
    298 		else if (c >= 'A')
    299 			c -= ('A' + 10);
    300 		else if (c >= '0')
    301 			c -= '0';
    302 		if (c < 0 || c > 15)
    303 			break;
    304 	}
    305 	*_val = val;
    306 	return p;
    307 }
    308 
    309 /*
    310  * Choose root and swap devices.
    311  */
    312 void
    313 cpu_rootconf(void)
    314 {
    315 	struct prom_n2f *nf;
    316 	const char *devname;
    317 	findfunc_t find;
    318 	char promname[4];
    319 	char partname[4];
    320 	const char *prompath;
    321 	int prom_ctlr, prom_unit, prom_part;
    322 
    323 	/* Get the PROM boot path and take it apart. */
    324 	prompath = prom_getbootpath();
    325 	if (prompath == NULL)
    326 		prompath = "zz(0,0,0)";
    327 	promname[0] = *(prompath++);
    328 	promname[1] = *(prompath++);
    329 	promname[2] = '\0';
    330 	prom_ctlr = prom_unit = prom_part = 0;
    331 	if (*prompath == '(' &&
    332 	    *(prompath = str2hex(++prompath, &prom_ctlr)) == ',' &&
    333 	    *(prompath = str2hex(++prompath, &prom_unit)) == ',')
    334 		(void)str2hex(++prompath, &prom_part);
    335 
    336 	/* Default to "unknown" */
    337 	booted_device = NULL;
    338 	booted_partition = 0;
    339 	devname = "<unknown>";
    340 	partname[0] = '\0';
    341 	find = NULL;
    342 
    343 	/* Do we know anything about the PROM boot device? */
    344 	for (nf = prom_dev_table; nf->func; nf++)
    345 		if (!strcmp(nf->name, promname)) {
    346 			find = nf->func;
    347 			break;
    348 		}
    349 	if (find)
    350 		booted_device = (*find)(promname, prom_ctlr, prom_unit);
    351 	if (booted_device) {
    352 		devname = device_xname(booted_device);
    353 		if (device_class(booted_device) == DV_DISK) {
    354 			booted_partition = prom_part & 7;
    355 			partname[0] = 'a' + booted_partition;
    356 			partname[1] = '\0';
    357 		}
    358 	}
    359 
    360 	printf("boot device: %s%s\n", devname, partname);
    361 	rootconf();
    362 }
    363 
    364 /*
    365  * Functions to find devices using PROM boot parameters.
    366  */
    367 
    368 /*
    369  * Network device:  Just use controller number.
    370  */
    371 static device_t
    372 net_find(char *name, int ctlr, int unit)
    373 {
    374 
    375 	return device_find_by_driver_unit(name, ctlr);
    376 }
    377 
    378 #if NSCSIBUS > 0
    379 /*
    380  * SCSI device:  The controller number corresponds to the
    381  * scsibus number, and the unit number is (targ*8 + LUN).
    382  */
    383 static device_t
    384 scsi_find(char *name, int ctlr, int unit)
    385 {
    386 	device_t scsibus;
    387 	struct scsibus_softc *sbsc;
    388 	struct scsipi_periph *periph;
    389 	int target, lun;
    390 
    391 	if ((scsibus = device_find_by_driver_unit("scsibus", ctlr)) == NULL)
    392 		return NULL;
    393 
    394 	/* Compute SCSI target/LUN from PROM unit. */
    395 	target = prom_sd_target((unit >> 3) & 7);
    396 	lun = unit & 7;
    397 
    398 	/* Find the device at this target/LUN */
    399 	sbsc = device_private(scsibus);
    400 	periph = scsipi_lookup_periph(sbsc->sc_channel, target, lun);
    401 	if (periph == NULL)
    402 		return NULL;
    403 
    404 	return periph->periph_dev;
    405 }
    406 #endif /* NSCSIBUS > 0 */
    407 
    408 /*
    409  * Xylogics SMD disk: (xy, xd)
    410  * Assume wired-in unit numbers for now...
    411  */
    412 static device_t
    413 xx_find(char *name, int ctlr, int unit)
    414 {
    415 
    416 	return device_find_by_driver_unit(name, ctlr * 2 + unit);
    417 }
    418