/* $NetBSD: autoconf.c,v 1.28 2015/09/30 14:18:54 phx Exp $ */ /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)autoconf.c 7.1 (Berkeley) 5/9/91 */ #include __KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.28 2015/09/30 14:18:54 phx Exp $"); #include #include #include #include #include #include #include #include #include #include static struct btinfo_rootdevice *bi_rdev; static struct btinfo_bootpath *bi_path; static struct btinfo_net *bi_net; static struct btinfo_prodfamily *bi_pfam; static struct btinfo_model *bi_model; struct i2c_dev { const char *name; unsigned addr; /* only attach when one of these bits in the model flags is set */ uint32_t model_mask; }; #define MAXI2CDEVS 4 struct model_i2c { const char *family; struct i2c_dev i2c_devs[MAXI2CDEVS]; }; static struct model_i2c model_i2c_list[] = { { "dlink", { { "strtc", 0x68, 0 } } }, { "iomega", { { "dsrtc", 0x68, 0 } } }, { "kurobox", { { "rs5c372rtc", 0x32, 0 } } }, { "kurot4", { { "rs5c372rtc", 0x32, 0 } } }, { "nhnas", { { "pcf8563rtc", 0x51, 0 } } }, { "qnap", { { "s390rtc", 0x30, 0 } } }, { "synology", { { "rs5c372rtc", 0x32, 0 }, { "lmtemp", 0x48, BI_MODEL_THERMAL } } }, }; static void add_i2c_child_devices(device_t, const char *); /* * Determine i/o configuration for a machine. */ void cpu_configure(void) { bi_rdev = lookup_bootinfo(BTINFO_ROOTDEVICE); bi_path = lookup_bootinfo(BTINFO_BOOTPATH); bi_net = lookup_bootinfo(BTINFO_NET); bi_pfam = lookup_bootinfo(BTINFO_PRODFAMILY); bi_model = lookup_bootinfo(BTINFO_MODEL); if (config_rootfound("mainbus", NULL) == NULL) panic("configure: mainbus not configured"); genppc_cpu_configure(); } void cpu_rootconf(void) { if (bi_path != NULL) booted_kernel = bi_path->bootpath; aprint_normal("boot device: %s\n", booted_device ? device_xname(booted_device) : ""); rootconf(); } void device_register(device_t dev, void *aux) { struct pci_attach_args *pa; static device_t boot_parent = NULL, net_parent = NULL; static pcitag_t boot_tag, net_tag; pcitag_t tag; if (device_is_a(dev, "skc")) { pa = aux; if (bi_rdev != NULL && bi_rdev->cookie == pa->pa_tag) { boot_parent = dev; boot_tag = pa->pa_tag; } if (bi_net != NULL && bi_net->cookie == pa->pa_tag) { net_parent = dev; net_tag = pa->pa_tag; } } else if (device_class(dev) == DV_IFNET) { if (device_is_a(device_parent(dev), "pci")) { pa = aux; tag = pa->pa_tag; } else if (device_parent(dev) == boot_parent) tag = boot_tag; else if (device_parent(dev) == net_parent) tag = net_tag; else tag = 0; if (bi_rdev != NULL && device_is_a(dev, bi_rdev->devname) && bi_rdev->cookie == tag) booted_device = dev; if (bi_net != NULL && device_is_a(dev, bi_net->devname) && bi_net->cookie == tag) { prop_data_t pd; pd = prop_data_create_data_nocopy(bi_net->mac_address, ETHER_ADDR_LEN); KASSERT(pd != NULL); if (prop_dictionary_set(device_properties(dev), "mac-address", pd) == false) printf("WARNING: unable to set mac-addr " "property for %s\n", device_xname(dev)); prop_object_release(pd); bi_net = NULL; /* do it just once */ } } else if (bi_rdev != NULL && device_class(dev) == DV_DISK && device_is_a(dev, bi_rdev->devname) && device_unit(dev) == (bi_rdev->cookie >> 8)) { booted_device = dev; booted_partition = bi_rdev->cookie & 0xff; } else if (device_is_a(dev, "ociic") && bi_pfam != NULL) { add_i2c_child_devices(dev, bi_pfam->name); } } static void add_i2c_child_devices(device_t self, const char *family) { struct i2c_dev *model_i2c_devs; prop_dictionary_t pd; prop_array_t pa; int i; for (i = 0; i < (int)(sizeof(model_i2c_list) / sizeof(model_i2c_list[0])); i++) { if (strcmp(family, model_i2c_list[i].family) == 0) { model_i2c_devs = model_i2c_list[i].i2c_devs; goto found; } } return; found: /* make an i2c-child-devices property list with for direct config. */ pa = prop_array_create(); for (i = 0; i < MAXI2CDEVS && model_i2c_devs[i].name != NULL; i++) { if (model_i2c_devs[i].model_mask != 0 && !(bi_model->flags & model_i2c_devs[i].model_mask)) continue; pd = prop_dictionary_create(); prop_dictionary_set_cstring_nocopy(pd, "name", model_i2c_devs[i].name); prop_dictionary_set_uint32(pd, "addr", model_i2c_devs[i].addr); prop_array_add(pa, pd); prop_object_release(pd); } prop_dictionary_set(device_properties(self), "i2c-child-devices", pa); prop_object_release(pa); }