1 /*
2 * Copyright (c) 1992 OMRON Corporation.
3 * Copyright (c) 1992, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * OMRON Corporation.
8 *
9 * %sccs.include.redist.c%
10 *
11 * @(#)autoconf.c 8.1 (Berkeley) 06/10/93
12 */
13
14 /*
15 * autoconf.c -- Determine mass storage and memory configuration for a machine.
16 * by A.Fujita, NOV-30-1991
17 *
18 * Modified by A.Fujita, FEB-04-1992
19 */
20
21
22 #include <sys/param.h>
23 #include <sys/dkstat.h>
24 #include <luna68k/stand/device.h>
25
26 int dkn; /* number of iostat dk numbers assigned so far */
27 struct hp_hw sc_table[MAX_CTLR];
28
29 #ifdef DEBUG
30 int acdebug = 1;
31 #endif
32
33 /*
34 * Determine mass storage and memory configuration for a machine.
35 */
configure()36 configure()
37 {
38 register struct hp_hw *hw;
39 int found;
40
41 /*
42 * Look over each hardware device actually found and attempt
43 * to match it with an ioconf.c table entry.
44 */
45 for (hw = sc_table; hw->hw_type; hw++) {
46 if (hw->hw_type & CONTROLLER)
47 found = find_controller(hw);
48 else
49 found = find_device(hw);
50 #ifdef DEBUG
51 if (!found) {
52 printf("unconfigured %s ", hw->hw_name);
53 printf("at 0x%x\n", hw->hw_addr);
54 }
55 #endif
56 }
57
58 }
59
60 #define dr_type(d, s) \
61 (strcmp((d)->d_name, (s)) == 0)
62
63 #define same_hw_ctlr(hw, hc) \
64 ((hw)->hw_type == SCSI && dr_type((hc)->hp_driver, "sc"))
65
find_controller(hw)66 find_controller(hw)
67 register struct hp_hw *hw;
68 {
69 register struct hp_ctlr *hc;
70 struct hp_ctlr *match_c;
71 caddr_t oaddr;
72 int sc;
73
74 #ifdef DEBUG
75 if (acdebug)
76 printf("find_controller: hw: %s at sc%d (%x), type %x...",
77 hw->hw_name, hw->hw_sc, hw->hw_addr, hw->hw_type);
78 #endif
79 sc = hw->hw_sc;
80 match_c = NULL;
81 for (hc = hp_cinit; hc->hp_driver; hc++) {
82 if (hc->hp_alive)
83 continue;
84 /*
85 * Make sure we are looking at the right
86 * controller type.
87 */
88 if (!same_hw_ctlr(hw, hc))
89 continue;
90 /*
91 * Exact match; all done
92 */
93 if ((int)hc->hp_addr == sc) {
94 match_c = hc;
95 break;
96 }
97 /*
98 * Wildcard; possible match so remember first instance
99 * but continue looking for exact match.
100 */
101 if ((int)hc->hp_addr == WILD_CARD_CTLR && match_c == NULL)
102 match_c = hc;
103 }
104 #ifdef DEBUG
105 if (acdebug) {
106 if (match_c)
107 printf("found %s%d\n",
108 match_c->hp_driver->d_name,
109 match_c->hp_unit);
110 else
111 printf("not found\n");
112 }
113 #endif
114 /*
115 * Didn't find an ioconf entry for this piece of hardware,
116 * just ignore it.
117 */
118 if (match_c == NULL)
119 return(0);
120 /*
121 * Found a match, attempt to initialize and configure all attached
122 * slaves. Note, we can still fail if HW won't initialize.
123 */
124 hc = match_c;
125 oaddr = hc->hp_addr;
126 hc->hp_addr = hw->hw_addr;
127 if ((*hc->hp_driver->d_init)(hc)) {
128 hc->hp_alive = 1;
129 printf("%s%d", hc->hp_driver->d_name, hc->hp_unit);
130 printf(" at 0x%x,", hc->hp_addr);
131 printf(" ipl %d", hc->hp_ipl);
132 if (hc->hp_flags)
133 printf(" flags 0x%x", hc->hp_flags);
134 printf("\n");
135 find_slaves(hc);
136 } else
137 hc->hp_addr = oaddr;
138 return(1);
139 }
140
find_device(hw)141 find_device(hw)
142 register struct hp_hw *hw;
143 {
144 register struct hp_device *hd;
145 struct hp_device *match_d;
146 caddr_t oaddr;
147 int sc;
148
149 #ifdef DEBUG
150 if (acdebug)
151 printf("find_device: hw: %s at sc%d (%x), type %x...",
152 hw->hw_name, hw->hw_sc, hw->hw_addr, hw->hw_type);
153 #endif
154 match_d = NULL;
155 for (hd = hp_dinit; hd->hp_driver; hd++) {
156 if (hd->hp_alive)
157 continue;
158 /* Must not be a slave */
159 if (hd->hp_cdriver)
160 continue;
161 sc = (int) hd->hp_addr;
162 /*
163 * Exact match; all done.
164 */
165 if (sc > 0 && sc == hw->hw_sc) {
166 match_d = hd;
167 break;
168 }
169 /*
170 * Wildcard; possible match so remember first instance
171 * but continue looking for exact match.
172 */
173 if (sc == 0 && same_hw_device(hw, hd) && match_d == NULL)
174 match_d = hd;
175 }
176 #ifdef DEBUG
177 if (acdebug) {
178 if (match_d)
179 printf("found %s%d\n",
180 match_d->hp_driver->d_name,
181 match_d->hp_unit);
182 else
183 printf("not found\n");
184 }
185 #endif
186 /*
187 * Didn't find an ioconf entry for this piece
188 * of hardware, just ignore it.
189 */
190 if (match_d == NULL)
191 return(0);
192 /*
193 * Found a match, attempt to initialize.
194 * Note, we can still fail if HW won't initialize.
195 */
196 hd = match_d;
197 oaddr = hd->hp_addr;
198 hd->hp_addr = hw->hw_addr;
199 if ((*hd->hp_driver->d_init)(hd)) {
200 hd->hp_alive = 1;
201 printf("%s%d", hd->hp_driver->d_name, hd->hp_unit);
202 printf(" at 0x%x", hd->hp_addr);
203 if (hd->hp_ipl)
204 printf(", ipl %d", hd->hp_ipl);
205 if (hd->hp_flags)
206 printf(", flags 0x%x", hd->hp_flags);
207 printf("\n");
208 } else
209 hd->hp_addr = oaddr;
210 return(1);
211 }
212
213 /*
214 * Search each BUS controller found for slaves attached to it.
215 * The bad news is that we don't know how to uniquely identify all slaves
216 * (e.g. PPI devices on HP-IB). The good news is that we can at least
217 * differentiate those from slaves we can identify. At worst (a totally
218 * wildcarded entry) this will cause us to locate such a slave at the first
219 * unused position instead of where it really is. To save grief, non-
220 * identifing devices should always be fully qualified.
221 */
find_slaves(hc)222 find_slaves(hc)
223 register struct hp_ctlr *hc;
224 {
225 register int s;
226 register struct hp_device *hd;
227 struct hp_device *match_s;
228 int maxslaves = MAXSLAVES-1;
229 int new_s, new_c, old_s, old_c;
230 int rescan;
231
232 #ifdef DEBUG
233 if (acdebug)
234 printf("find_slaves: for %s%d\n",
235 hc->hp_driver->d_name, hc->hp_unit);
236 #endif
237 for (s = 0; s < maxslaves; s++) {
238 rescan = 1;
239 match_s = NULL;
240 for (hd = hp_dinit; hd->hp_driver; hd++) {
241 /*
242 * Rule out the easy ones:
243 * 1. slave already assigned or not a slave
244 * 2. not of the proper type
245 * 3. controller specified but not this one
246 * 4. slave specified but not this one
247 */
248 if (hd->hp_alive || hd->hp_cdriver == NULL)
249 continue;
250 if (!dr_type(hc->hp_driver, hd->hp_cdriver->d_name))
251 continue;
252 if (hd->hp_ctlr >= 0 && hd->hp_ctlr != hc->hp_unit)
253 continue;
254 if (hd->hp_slave >= 0 && hd->hp_slave != s)
255 continue;
256 /*
257 * Case 0: first possible match.
258 * Remember it and keep looking for better.
259 */
260 if (match_s == NULL) {
261 match_s = hd;
262 new_c = hc->hp_unit;
263 new_s = s;
264 continue;
265 }
266 /*
267 * Case 1: exact match.
268 * All done. Note that we do not attempt any other
269 * matches if this one fails. This allows us to
270 * "reserve" locations for dynamic addition of
271 * disk/tape drives by fully qualifing the location.
272 */
273 if (hd->hp_slave == s && hd->hp_ctlr == hc->hp_unit) {
274 match_s = hd;
275 rescan = 0;
276 break;
277 }
278 /*
279 * Case 2: right controller, wildcarded slave.
280 * Remember first and keep looking for an exact match.
281 */
282 if (hd->hp_ctlr == hc->hp_unit &&
283 match_s->hp_ctlr < 0) {
284 match_s = hd;
285 new_s = s;
286 continue;
287 }
288 /*
289 * Case 3: right slave, wildcarded controller.
290 * Remember and keep looking for a better match.
291 */
292 if (hd->hp_slave == s &&
293 match_s->hp_ctlr < 0 && match_s->hp_slave < 0) {
294 match_s = hd;
295 new_c = hc->hp_unit;
296 continue;
297 }
298 /*
299 * OW: we had a totally wildcarded spec.
300 * If we got this far, we have found a possible
301 * match already (match_s != NULL) so there is no
302 * reason to remember this one.
303 */
304 continue;
305 }
306 /*
307 * Found a match. We need to set hp_ctlr/hp_slave properly
308 * for the init routines but we also need to remember all
309 * the old values in case this doesn't pan out.
310 */
311 if (match_s) {
312 hd = match_s;
313 old_c = hd->hp_ctlr;
314 old_s = hd->hp_slave;
315 if (hd->hp_ctlr < 0)
316 hd->hp_ctlr = new_c;
317 if (hd->hp_slave < 0)
318 hd->hp_slave = new_s;
319 #ifdef DEBUG
320 if (acdebug)
321 printf("looking for %s%d at slave %d...",
322 hd->hp_driver->d_name,
323 hd->hp_unit, hd->hp_slave);
324 #endif
325
326 if ((*hd->hp_driver->d_init)(hd)) {
327 #ifdef DEBUG
328 if (acdebug)
329 printf("found\n");
330 #endif
331 printf("%s%d at %s%d, slave %d",
332 hd->hp_driver->d_name, hd->hp_unit,
333 hc->hp_driver->d_name, hd->hp_ctlr,
334 hd->hp_slave);
335 if (hd->hp_flags)
336 printf(" flags 0x%x", hd->hp_flags);
337 printf("\n");
338 hd->hp_alive = 1;
339 if (hd->hp_dk && dkn < DK_NDRIVE)
340 hd->hp_dk = dkn++;
341 else
342 hd->hp_dk = -1;
343 rescan = 1;
344 } else {
345 #ifdef DEBUG
346 if (acdebug)
347 printf("not found\n");
348 #endif
349 hd->hp_ctlr = old_c;
350 hd->hp_slave = old_s;
351 }
352 /*
353 * XXX: This should be handled better.
354 * Re-scan a slave. There are two reasons to do this.
355 * 1. It is possible to have both a tape and disk
356 * (e.g. 7946) or two disks (e.g. 9122) at the
357 * same slave address. Here we need to rescan
358 * looking only at entries with a different
359 * physical unit number (hp_flags).
360 * 2. It is possible that an init failed because the
361 * slave was there but of the wrong type. In this
362 * case it may still be possible to match the slave
363 * to another ioconf entry of a different type.
364 * Here we need to rescan looking only at entries
365 * of different types.
366 * In both cases we avoid looking at undesirable
367 * ioconf entries of the same type by setting their
368 * alive fields to -1.
369 */
370 if (rescan) {
371 for (hd = hp_dinit; hd->hp_driver; hd++) {
372 if (hd->hp_alive)
373 continue;
374 if (match_s->hp_alive == 1) { /* 1 */
375 if (hd->hp_flags == match_s->hp_flags)
376 hd->hp_alive = -1;
377 } else { /* 2 */
378 if (hd->hp_driver == match_s->hp_driver)
379 hd->hp_alive = -1;
380 }
381 }
382 s--;
383 continue;
384 }
385 }
386 /*
387 * Reset bogon alive fields prior to attempting next slave
388 */
389 for (hd = hp_dinit; hd->hp_driver; hd++)
390 if (hd->hp_alive == -1)
391 hd->hp_alive = 0;
392 }
393 }
394
395 same_hw_device(hw, hd)
396 struct hp_hw *hw;
397 struct hp_device *hd;
398 {
399 int found = 0;
400
401 switch (hw->hw_type) {
402 case NET:
403 found = dr_type(hd->hp_driver, "le");
404 break;
405 case SCSI:
406 found = dr_type(hd->hp_driver, "scsi");
407 break;
408 case VME:
409 case MISC:
410 break;
411 }
412 return(found);
413 }
414
415 #define setup_hw(hw, addr, sc, type, id, name) \
416 (hw)->hw_addr = addr; \
417 (hw)->hw_sc = sc; \
418 (hw)->hw_type = type; \
419 (hw)->hw_id = id; \
420 (hw)->hw_name = name
421
find_devs()422 find_devs()
423 {
424 register struct hp_hw *hw = sc_table;
425
426 setup_hw(hw, (char *) 0x51000000, 0x5, SIO, 0x5, "uPD7201A (SIO)");
427 hw->hw_id2 = 0; hw++;
428
429 setup_hw(hw, (char *) 0x51000004, 0x5, KEYBOARD, 0x5, "uPD7201A (KBD)");
430 hw->hw_id2 = 1; hw++;
431
432 setup_hw(hw, (char *) 0xe1000000, 0xe, SCSI, 0xe, "MB89352 (SPC)");
433 hw++;
434
435 if (!badaddr((caddr_t) 0xf1000000)) {
436 setup_hw(hw, (char *) 0xf1000000, 0xf, NET, 0xf, "Am7990 (LANCE)");
437 hw++;
438 }
439 }
440
strcmp(s1,s2)441 strcmp(s1, s2)
442 register char *s1, *s2;
443 {
444 while (*s1 == *s2)
445 if (*s1++=='\0' || *s2++ == '\0')
446 return (0);
447 return (*s1 - *s2);
448 }
449