1 /* $NetBSD: autoconf.c,v 1.29 2020/07/09 05:12:09 nisimura Exp $ */
2
3 /*-
4 * Copyright (c) 1990 The Regents of the University of California.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * William Jolitz.
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 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * @(#)autoconf.c 7.1 (Berkeley) 5/9/91
35 */
36
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.29 2020/07/09 05:12:09 nisimura Exp $");
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/conf.h>
43 #include <sys/device.h>
44
45 #include <dev/cons.h>
46 #include <dev/pci/pcivar.h>
47
48 #include <net/if.h>
49 #include <net/if_ether.h>
50
51 #include <machine/bootinfo.h>
52 #include <machine/pio.h>
53
54 static struct btinfo_rootdevice *bi_rdev;
55 static struct btinfo_bootpath *bi_path;
56 static struct btinfo_net *bi_net;
57 static struct btinfo_prodfamily *bi_pfam;
58 static struct btinfo_model *bi_model;
59
60 struct i2c_dev {
61 const char *name;
62 unsigned addr;
63 /* only attach when one of these bits in the model flags is set */
64 uint32_t model_mask;
65 };
66
67 #define MAXI2CDEVS 4
68 struct model_i2c {
69 const char *family;
70 struct i2c_dev i2c_devs[MAXI2CDEVS];
71 };
72
73 static struct model_i2c model_i2c_list[] = {
74 { "dlink", { { "strtc", 0x68, 0 } } },
75 { "iomega", { { "dsrtc", 0x68, 0 } } },
76 { "kurobox", { { "rs5c372rtc", 0x32, 0 } } },
77 { "kurot4", { { "rs5c372rtc", 0x32, 0 } } },
78 { "nhnas", { { "pcf8563rtc", 0x51, 0 } } },
79 { "qnap", { { "s390rtc", 0x30, 0 } } },
80 { "synology", { { "rs5c372rtc", 0x32, 0 },
81 { "lmtemp", 0x48, BI_MODEL_THERMAL } } },
82 };
83
84 static void add_i2c_child_devices(device_t, const char *);
85
86 /*
87 * Determine i/o configuration for a machine.
88 */
89 void
cpu_configure(void)90 cpu_configure(void)
91 {
92
93 bi_rdev = lookup_bootinfo(BTINFO_ROOTDEVICE);
94 bi_path = lookup_bootinfo(BTINFO_BOOTPATH);
95 bi_net = lookup_bootinfo(BTINFO_NET);
96 bi_pfam = lookup_bootinfo(BTINFO_PRODFAMILY);
97 bi_model = lookup_bootinfo(BTINFO_MODEL);
98
99 if (config_rootfound("mainbus", NULL) == NULL)
100 panic("configure: mainbus not configured");
101
102 genppc_cpu_configure();
103 }
104
105 void
cpu_rootconf(void)106 cpu_rootconf(void)
107 {
108
109 if (bi_path != NULL)
110 booted_kernel = bi_path->bootpath;
111
112 aprint_normal("boot device: %s\n",
113 booted_device ? device_xname(booted_device) : "<unknown>");
114 rootconf();
115 }
116
117 void
device_register(device_t dev,void * aux)118 device_register(device_t dev, void *aux)
119 {
120 struct pci_attach_args *pa;
121 static device_t boot_parent = NULL, net_parent = NULL;
122 static pcitag_t boot_tag, net_tag;
123 pcitag_t tag;
124
125 if (device_is_a(dev, "skc")) {
126 pa = aux;
127 if (bi_rdev != NULL && bi_rdev->cookie == pa->pa_tag) {
128 boot_parent = dev;
129 boot_tag = pa->pa_tag;
130 }
131 if (bi_net != NULL && bi_net->cookie == pa->pa_tag) {
132 net_parent = dev;
133 net_tag = pa->pa_tag;
134 }
135 }
136 else if (device_class(dev) == DV_IFNET) {
137 if (device_is_a(device_parent(dev), "pci")) {
138 pa = aux;
139 tag = pa->pa_tag;
140 } else if (device_parent(dev) == boot_parent)
141 tag = boot_tag;
142 else if (device_parent(dev) == net_parent)
143 tag = net_tag;
144 else
145 tag = 0;
146
147 if (bi_rdev != NULL && device_is_a(dev, bi_rdev->devname)
148 && bi_rdev->cookie == tag)
149 booted_device = dev;
150
151 if (bi_net != NULL && device_is_a(dev, bi_net->devname)
152 && bi_net->cookie == tag) {
153 prop_data_t pd;
154
155 pd = prop_data_create_nocopy(bi_net->mac_address,
156 ETHER_ADDR_LEN);
157 KASSERT(pd != NULL);
158 if (prop_dictionary_set(device_properties(dev),
159 "mac-address", pd) == false)
160 printf("WARNING: unable to set mac-addr "
161 "property for %s\n", device_xname(dev));
162 prop_object_release(pd);
163 bi_net = NULL; /* do it just once */
164 }
165 }
166 else if (bi_rdev != NULL && device_class(dev) == DV_DISK
167 && device_is_a(dev, bi_rdev->devname)
168 && device_unit(dev) == (bi_rdev->cookie >> 8)) {
169 booted_device = dev;
170 booted_partition = bi_rdev->cookie & 0xff;
171 }
172 else if (device_is_a(dev, "ociic") && bi_pfam != NULL) {
173 add_i2c_child_devices(dev, bi_pfam->name);
174 }
175 }
176
177 static void
add_i2c_child_devices(device_t self,const char * family)178 add_i2c_child_devices(device_t self, const char *family)
179 {
180 struct i2c_dev *model_i2c_devs;
181 prop_dictionary_t pd;
182 prop_array_t pa;
183 int i;
184
185 for (i = 0;
186 i < (int)(sizeof(model_i2c_list) / sizeof(model_i2c_list[0]));
187 i++) {
188 if (strcmp(family, model_i2c_list[i].family) == 0) {
189 model_i2c_devs = model_i2c_list[i].i2c_devs;
190 goto found;
191 }
192 }
193 return;
194
195 found:
196 /* make an i2c-child-devices property list with for direct config. */
197 pa = prop_array_create();
198
199 for (i = 0; i < MAXI2CDEVS && model_i2c_devs[i].name != NULL; i++) {
200 if (model_i2c_devs[i].model_mask != 0 &&
201 !(bi_model->flags & model_i2c_devs[i].model_mask))
202 continue;
203 pd = prop_dictionary_create();
204 prop_dictionary_set_string_nocopy(pd, "name",
205 model_i2c_devs[i].name);
206 prop_dictionary_set_uint32(pd, "addr",
207 model_i2c_devs[i].addr);
208 prop_array_add(pa, pd);
209 prop_object_release(pd);
210 }
211
212 prop_dictionary_set(device_properties(self), "i2c-child-devices", pa);
213 prop_object_release(pa);
214 }
215