#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.31 2025/10/04 04:46:56 thorpej Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/disklabel.h>
#include <sys/conf.h>
#include <sys/reboot.h>
#include <sys/device.h>
#include <sys/queue.h>
#include <machine/pte.h>
#include <machine/intr.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>
#include <dev/scsipi/scsi_all.h>
#include <dev/scsipi/scsipi_all.h>
#include <dev/scsipi/scsiconf.h>
#include <dev/ata/atavar.h>
#include <dev/ic/wdcvar.h>
#include <machine/isa_machdep.h>
#include <dev/isa/isareg.h>
#include <prep/pnpbus/pnpbusvar.h>
#include "opt_nvram.h"
u_long bootdev = 0;
extern char bootpath[256];
static void findroot(void);
void
cpu_configure(void)
{
if (config_rootfound("mainbus", NULL) == NULL)
panic("configure: mainbus not configured");
genppc_cpu_configure();
}
void
cpu_rootconf(void)
{
findroot();
aprint_normal("boot device: %s\n",
booted_device ? device_xname(booted_device) : "<unknown>");
rootconf();
}
void
device_register(device_t dev, void *aux)
{
device_t parent;
char devpath[256];
int n;
if (device_is_a(dev, "com") || device_is_a(dev, "attimer") ||
device_is_a(dev, "pcppi") || device_is_a(dev, "mcclock") ||
device_is_a(dev, "mkclock") || device_is_a(dev, "lpt") ||
device_is_a(dev, "pckbc") || device_is_a(dev, "pckbd") ||
device_is_a(dev, "vga") || device_is_a(dev, "wsdisplay") ||
device_is_a(dev, "wskbd") || device_is_a(dev, "wsmouse") ||
device_is_a(dev, "pms") || device_is_a(dev, "cpu"))
return;
if (device_is_a(dev, "pchb")) {
struct pci_attach_args *pa = aux;
if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_MOT &&
PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_MOT_RAVEN) {
device_setprop_bool(dev, "prep-raven-pchb", true);
}
}
if (device_is_a(dev, "mainbus")) {
device_setprop_string(dev, "prep-fw-path-component", "/");
return;
}
parent = device_parent(dev);
n = 0;
if (device_is_a(dev, "pci")) {
if (device_is_a(parent, "ppb"))
n = snprintf(devpath, sizeof(devpath), "");
else
n = snprintf(devpath, sizeof(devpath), "pci@%x",
prep_io_space_tag.pbs_offset);
}
if (device_is_a(parent, "pci")) {
struct pci_attach_args *pa = aux;
n = snprintf(devpath, sizeof(devpath), "pci%x,%x@%x,%x",
PCI_VENDOR(pa->pa_id), PCI_PRODUCT(pa->pa_id),
pa->pa_device, pa->pa_function);
}
if (device_is_a(parent, "pnpbus")) {
struct pnpbus_dev_attach_args *pna = aux;
struct pnpbus_io *io;
n = snprintf(devpath, sizeof(devpath), "%s@",
pna->pna_devid);
io = SIMPLEQ_FIRST(&pna->pna_res.io);
if (n > sizeof(devpath))
n = sizeof(devpath);
if (io != NULL)
n += snprintf(devpath + n, sizeof(devpath) - n, "%x",
io->minbase);
}
if (n > sizeof(devpath))
n = sizeof(devpath);
if (device_class(dev) == DV_IFNET)
n += snprintf(devpath + n, sizeof(devpath) - n, ":");
else if (device_is_a(dev, "cd"))
n = snprintf(devpath, sizeof(devpath), "cdrom@");
else if (device_class(dev) == DV_DISK)
n = snprintf(devpath, sizeof(devpath), "harddisk@");
else if (device_class(dev) == DV_TAPE)
n = snprintf(devpath, sizeof(devpath), "tape@");
else if (device_is_a(dev, "fd"))
n = snprintf(devpath, sizeof(devpath), "floppy@");
if (device_is_a(parent, "scsibus") || device_is_a(parent, "atapibus")) {
struct scsipibus_attach_args *sa = aux;
if (n > sizeof(devpath))
n = sizeof(devpath);
n += snprintf(devpath + n, sizeof(devpath) - n, "%d",
sa->sa_periph->periph_target);
if (n > sizeof(devpath))
n = sizeof(devpath);
if (device_is_a(parent, "scsibus"))
n += snprintf(devpath + n, sizeof(devpath) - n, ",%d",
sa->sa_periph->periph_lun);
} else if (device_is_a(parent, "atabus") ||
device_is_a(parent, "pciide")) {
struct ata_device *adev = aux;
if (n > sizeof(devpath))
n = sizeof(devpath);
n += snprintf(devpath + n, sizeof(devpath) - n, "%d",
adev->adev_drv_data->drive);
} else if (device_is_a(dev, "fd")) {
if (n > sizeof(devpath))
n = sizeof(devpath);
n += snprintf(devpath + n, sizeof(devpath) - n, "%d",
device_unit(dev));
}
device_setprop_string(dev, "prep-fw-path-component", devpath);
}
static void
gen_fwpath(device_t dev)
{
device_t parent;
prop_string_t str1, str2, str3;
parent = device_parent(dev);
str1 = prop_dictionary_get(device_properties(dev),
"prep-fw-path-component");
if (str1 == NULL)
return;
if (parent == NULL) {
prop_dictionary_set(device_properties(dev), "prep-fw-path",
str1);
return;
}
str2 = prop_dictionary_get(device_properties(parent), "prep-fw-path");
if (str2 == NULL) {
prop_dictionary_set(device_properties(dev), "prep-fw-path",
str1);
return;
}
str3 = prop_string_copy(str2);
KASSERT(str3 != NULL);
if (!(prop_string_equals_cstring(str3, "/") ||
prop_string_equals_cstring(str1, "")))
prop_string_append_cstring(str3, "/");
if (!prop_string_equals_cstring(str1, "/"))
prop_string_append(str3, str1);
#if defined(NVRAM_DUMP)
printf("%s devpath: %s+%s == %s\n", device_xname(dev),
prop_string_cstring_nocopy(str2),
prop_string_cstring_nocopy(str1),
prop_string_cstring_nocopy(str3));
#endif
(void)prop_dictionary_set(device_properties(dev),
"prep-fw-path", str3);
prop_object_release(str3);
}
static void
build_fwpath(void)
{
device_t dev, d;
deviter_t di, inner_di;
prop_string_t str1;
for (dev = deviter_first(&di, DEVITER_F_ROOT_FIRST); dev != NULL;
dev = deviter_next(&di)) {
if (device_is_a(dev, "pci") || device_is_a(dev, "mainbus") ||
device_is_a(dev, "pcib") || device_is_a(dev, "pceb") ||
device_is_a(dev, "ppb"))
gen_fwpath(dev);
}
deviter_release(&di);
for (dev = deviter_first(&di, DEVITER_F_ROOT_FIRST); dev != NULL;
dev = deviter_next(&di)) {
if (device_is_a(dev, "isa"))
gen_fwpath(dev);
}
deviter_release(&di);
for (dev = deviter_first(&di, DEVITER_F_ROOT_FIRST); dev != NULL;
dev = deviter_next(&di)) {
if (device_is_a(dev, "pci") || device_is_a(dev, "pcib") ||
device_is_a(dev, "pceb") || device_is_a(dev, "isa") ||
device_is_a(dev, "ppb"))
continue;
if (device_is_a(dev, "pnpbus")) {
for (d = deviter_first(&inner_di, DEVITER_F_ROOT_FIRST);
d != NULL;
d = deviter_next(&inner_di)) {
if (!device_is_a(d, "isa"))
continue;
str1 = prop_dictionary_get(device_properties(d),
"prep-fw-path");
if (str1 == NULL)
continue;
prop_dictionary_set(device_properties(dev),
"prep-fw-path", str1);
}
deviter_release(&inner_di);
} else
gen_fwpath(dev);
}
deviter_release(&di);
}
void
findroot(void)
{
device_t d;
deviter_t di;
char *cp;
prop_string_t str;
size_t len;
build_fwpath();
cp = strchr(bootpath, ':');
if (cp != NULL) {
cp++;
*cp = '\0';
}
len = strlen(bootpath);
#if defined(NVRAM_DUMP)
printf("Modified bootpath: %s\n", bootpath);
#endif
for (d = deviter_first(&di, DEVITER_F_ROOT_FIRST);
d != NULL;
d = deviter_next(&di)) {
str = prop_dictionary_get(device_properties(d), "prep-fw-path");
if (str == NULL)
continue;
#if defined(NVRAM_DUMP)
printf("dev %s: fw-path: %s\n", device_xname(d),
prop_string_cstring_nocopy(str));
#endif
if (strncmp(prop_string_cstring_nocopy(str), bootpath,
len) == 0)
break;
}
deviter_release(&di);
if (d != NULL) {
booted_device = d;
booted_partition = 0;
}
}