autoconf.c revision 1.8 1 /* $NetBSD: autoconf.c,v 1.8 2002/07/11 16:03:14 christos Exp $ */
2
3 /*
4 * Copyright (c) 1988 University of Utah.
5 * Copyright (c) 1982, 1986, 1990, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * the Systems Programming Group of the University of Utah Computer
10 * Science Department.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the University of
23 * California, Berkeley and its contributors.
24 * 4. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 *
40 * from: Utah $Hdr: autoconf.c 1.36 92/12/20$
41 *
42 * @(#)autoconf.c 8.2 (Berkeley) 1/12/94
43 */
44
45 /*
46 * Setup the system to run on the current machine.
47 *
48 * Configure() is called at boot time. Available
49 * devices are determined (from possibilities mentioned in ioconf.c),
50 * and the drivers are initialized.
51 */
52
53 #include <sys/param.h>
54 #include <sys/systm.h>
55 #include <sys/map.h>
56 #include <sys/buf.h>
57 #include <sys/dkstat.h>
58 #include <sys/conf.h>
59 #include <sys/reboot.h>
60 #include <sys/device.h>
61
62 #include <machine/vmparam.h>
63 #include <machine/autoconf.h>
64 #include <machine/disklabel.h>
65 #include <machine/cpu.h>
66 #include <machine/pte.h>
67
68 #include <next68k/next68k/isr.h>
69 #include <next68k/next68k/nextrom.h>
70
71 struct device *booted_device; /* boot device */
72
73 void mainbus_attach __P((struct device *, struct device *, void *));
74 int mainbus_match __P((struct device *, struct cfdata *, void *));
75 int mainbus_print __P((void *, const char *));
76
77 static struct device *getdevunit __P((char *, int));
78 static int devidentparse __P((const char *, int *, int *, int *));
79 static int atoi __P((const char *));
80
81 struct mainbus_softc {
82 struct device sc_dev;
83 };
84
85 struct cfattach mainbus_ca = {
86 sizeof(struct mainbus_softc), mainbus_match, mainbus_attach
87 };
88
89 #if 0
90 struct cfdriver mainbus_cd = {
91 NULL, "mainbus", DV_DULL, 0
92 };
93 #endif
94
95 static char *mainbusdevs[] = {
96 "intio",
97 "nextdisplay",
98 NULL
99 };
100
101 struct device_equiv {
102 char *alias;
103 char *real;
104 };
105 static struct device_equiv device_equiv[] = {
106 { "en", "xe" },
107 { "tp", "xe" },
108 };
109 static int ndevice_equivs = (sizeof(device_equiv)/sizeof(device_equiv[0]));
110
111 int
112 mainbus_match(parent, cf, args)
113 struct device *parent;
114 struct cfdata *cf;
115 void *args;
116 {
117 static int mainbus_matched;
118
119 if (mainbus_matched)
120 return (0);
121
122 return ((mainbus_matched = 1));
123 }
124
125 void
126 mainbus_attach(parent, self, args)
127 struct device *parent, *self;
128 void *args;
129 {
130 char **devices;
131 int i;
132
133 printf("\n");
134
135 /*
136 * Attach children.
137 */
138 devices = mainbusdevs;
139
140 for (i = 0; devices[i] != NULL; ++i)
141 (void)config_found(self, devices[i], mainbus_print);
142 }
143
144 int
145 mainbus_print(aux, cp)
146 void *aux;
147 const char *cp;
148 {
149 char *devname = aux;
150
151 if (cp)
152 printf("%s at %s\n", devname, cp);
153
154 return (UNCONF);
155 }
156
157 /*
158 * Determine mass storage and memory configuration for a machine.
159 */
160 void
161 cpu_configure()
162 {
163
164 booted_device = NULL; /* set by device drivers (if found) */
165
166 INTR_SETMASK(0);
167
168 init_sir();
169
170 if (config_rootfound("mainbus", NULL) == NULL)
171 panic("autoconfig failed, no root");
172
173 /* Turn on interrupts */
174 spl0();
175 }
176
177 void
178 cpu_rootconf()
179 {
180 int count, lun, part;
181
182 count = lun = part = 0;
183
184 devidentparse (rom_boot_info, &count, &lun, &part);
185 booted_device = getdevunit (rom_boot_dev, count);
186
187 printf("boot device: %s\n",
188 (booted_device) ? booted_device->dv_xname : "<unknown>");
189
190 setroot(booted_device, part);
191 }
192
193 /*
194 * find a device matching "name" and unit number
195 */
196 static struct device *
197 getdevunit(name, unit)
198 char *name;
199 int unit;
200 {
201 struct device *dev = alldevs.tqh_first;
202 char num[10], fullname[16];
203 int lunit;
204 int i;
205
206 for (i = 0; i < ndevice_equivs; i++)
207 if (device_equiv->alias && strcmp (name, device_equiv->alias) == 0)
208 name = device_equiv->real;
209
210 /* compute length of name and decimal expansion of unit number */
211 sprintf(num, "%d", unit);
212 lunit = strlen(num);
213 if (strlen(name) + lunit >= sizeof(fullname) - 1)
214 panic("config_attach: device name too long");
215
216 strcpy(fullname, name);
217 strcat(fullname, num);
218
219 while (strcmp(dev->dv_xname, fullname) != 0) {
220 if ((dev = dev->dv_list.tqe_next) == NULL)
221 return NULL;
222 }
223 return dev;
224 }
225
226 /*
227 * Parse a device ident.
228 *
229 * Format:
230 * (count, lun, part)
231 */
232 static int
233 devidentparse(spec, count, lun, part)
234 const char *spec;
235 int *count;
236 int *lun;
237 int *part;
238 {
239 int i;
240 const char *args[3];
241
242 if (*spec == '(') {
243 /* tokenize device ident */
244 args[0] = ++spec;
245 for (i = 1; *spec && *spec != ')' && i<3; spec++) {
246 if (*spec == ',')
247 args[i++] = ++spec;
248 }
249 if (*spec != ')')
250 goto baddev;
251
252 switch(i) {
253 case 3:
254 *count = atoi(args[0]);
255 *lun = atoi(args[1]);
256 *part = atoi(args[2]);
257 break;
258 case 2:
259 *lun = atoi(args[0]);
260 *part = atoi(args[1]);
261 break;
262 case 1:
263 *part = atoi(args[0]);
264 break;
265 case 0:
266 break;
267 }
268 }
269 else
270 goto baddev;
271
272 return 0;
273
274 baddev:
275 return ENXIO;
276 }
277
278 static int
279 atoi(s)
280 const char *s;
281 {
282 int val = 0;
283
284 while(isdigit(*s))
285 val = val * 10 + (*s++ - '0');
286 return val;
287 }
288