xref: /original-bsd/sys/luna68k/stand/autoconf.c (revision 3705696b)
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  */
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 
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 
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  */
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 
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 
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