xref: /netbsd-src/sys/arch/luna68k/stand/boot/autoconf.c (revision 6a493d6bc668897c91594964a732d38505b70cbb)
1 /*	$NetBSD: autoconf.c,v 1.7 2013/01/22 15:48:40 tsutsui Exp $	*/
2 
3 /*
4  * Copyright (c) 1992 OMRON Corporation.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * OMRON Corporation.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *	This product includes software developed by the University of
20  *	California, Berkeley and its contributors.
21  * 4. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  *	@(#)autoconf.c	8.1 (Berkeley) 6/10/93
38  */
39 /*
40  * Copyright (c) 1992, 1993
41  *	The Regents of the University of California.  All rights reserved.
42  *
43  * This code is derived from software contributed to Berkeley by
44  * OMRON Corporation.
45  *
46  * Redistribution and use in source and binary forms, with or without
47  * modification, are permitted provided that the following conditions
48  * are met:
49  * 1. Redistributions of source code must retain the above copyright
50  *    notice, this list of conditions and the following disclaimer.
51  * 2. Redistributions in binary form must reproduce the above copyright
52  *    notice, this list of conditions and the following disclaimer in the
53  *    documentation and/or other materials provided with the distribution.
54  * 3. Neither the name of the University nor the names of its contributors
55  *    may be used to endorse or promote products derived from this software
56  *    without specific prior written permission.
57  *
58  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68  * SUCH DAMAGE.
69  *
70  *	@(#)autoconf.c	8.1 (Berkeley) 6/10/93
71  */
72 
73 /*
74  * autoconf.c -- Determine mass storage and memory configuration for a machine.
75  *          by A.Fujita, NOV-30-1991
76  *
77  * Modified by A.Fujita, FEB-04-1992
78  */
79 
80 
81 #include <sys/param.h>
82 #include <sys/dkstat.h>
83 #include <machine/cpu.h>
84 #include <lib/libkern/libkern.h>
85 #include <luna68k/stand/boot/samachdep.h>
86 #include <luna68k/stand/boot/device.h>
87 
88 int	dkn;		    /* number of iostat dk numbers assigned so far */
89 struct	hp_hw sc_table[MAX_CTLR];
90 
91 #ifdef DEBUG
92 int	acdebug = 1;
93 #endif
94 
95 static int find_controller(struct hp_hw *);
96 static int find_device(struct hp_hw *);
97 static void find_slaves(struct hp_ctlr *);
98 static int same_hw_device(struct hp_hw *, struct hp_device *);
99 
100 /*
101  * Determine mass storage and memory configuration for a machine.
102  */
103 void
104 configure(void)
105 {
106 	struct hp_hw *hw;
107 	int found;
108 
109 	/*
110 	 * Look over each hardware device actually found and attempt
111 	 * to match it with an ioconf.c table entry.
112 	 */
113 	for (hw = sc_table; hw->hw_type; hw++) {
114 		if (hw->hw_type & CONTROLLER)
115 			found = find_controller(hw);
116 		else
117 			found = find_device(hw);
118 #ifdef DEBUG
119 		if (!found) {
120 			printf("unconfigured %s ", hw->hw_name);
121 			printf("at 0x%x\n", (u_int)hw->hw_addr);
122 		}
123 #endif
124 	}
125 
126 }
127 
128 #define dr_type(d, s)	\
129 	(strcmp((d)->d_name, (s)) == 0)
130 
131 #define same_hw_ctlr(hw, hc) \
132 	((hw)->hw_type == SCSI && dr_type((hc)->hp_driver, "sc"))
133 
134 int
135 find_controller(struct hp_hw *hw)
136 {
137 	struct hp_ctlr *hc;
138 	struct hp_ctlr *match_c;
139 	uint8_t *addr, *oaddr;
140 
141 #ifdef DEBUG
142 	if (acdebug)
143 		printf("find_controller: hw: %s at sc%d (%x), type %x...",
144 		       hw->hw_name, hw->hw_sc, (u_int)hw->hw_addr, hw->hw_type);
145 #endif
146 	addr = hw->hw_addr;
147 	match_c = NULL;
148 	for (hc = hp_cinit; hc->hp_driver; hc++) {
149 		if (hc->hp_alive)
150 			continue;
151 		/*
152 		 * Make sure we are looking at the right
153 		 * controller type.
154 		 */
155 		if (!same_hw_ctlr(hw, hc))
156 			continue;
157 		/*
158 		 * Exact match; all done
159 		 */
160 		if (hc->hp_addr == addr) {
161 			match_c = hc;
162 			break;
163 		}
164 		/*
165 		 * Wildcard; possible match so remember first instance
166 		 * but continue looking for exact match.
167 		 */
168 		if ((int)hc->hp_addr == WILD_CARD_CTLR && match_c == NULL)
169 			match_c = hc;
170 	}
171 #ifdef DEBUG
172 	if (acdebug) {
173 		if (match_c)
174 			printf("found %s%d\n",
175 			       match_c->hp_driver->d_name,
176 			       match_c->hp_unit);
177 		else
178 			printf("not found\n");
179 	}
180 #endif
181 	/*
182 	 * Didn't find an ioconf entry for this piece of hardware,
183 	 * just ignore it.
184 	 */
185 	if (match_c == NULL)
186 		return(0);
187 	/*
188 	 * Found a match, attempt to initialize and configure all attached
189 	 * slaves.  Note, we can still fail if HW won't initialize.
190 	 */
191 	hc = match_c;
192 	oaddr = hc->hp_addr;
193 	hc->hp_addr = hw->hw_addr;
194 	if ((*hc->hp_driver->d_init)(hc)) {
195 		hc->hp_alive = 1;
196 		printf("%s%d", hc->hp_driver->d_name, hc->hp_unit);
197 		printf(" at %p,", hc->hp_addr);
198 		printf(" ipl %d", hc->hp_ipl);
199 		if (hc->hp_flags)
200 			printf(" flags 0x%x", hc->hp_flags);
201 		printf("\n");
202 		find_slaves(hc);
203 	} else
204 		hc->hp_addr = oaddr;
205 	return(1);
206 }
207 
208 int
209 find_device(struct hp_hw *hw)
210 {
211 	struct hp_device *hd;
212 	struct hp_device *match_d;
213 	uint8_t *addr, *oaddr;
214 
215 #ifdef DEBUG
216 	if (acdebug)
217 		printf("find_device: hw: %s at sc%d (%x), type %x...",
218 		       hw->hw_name, hw->hw_sc, (u_int)hw->hw_addr, hw->hw_type);
219 #endif
220 	match_d = NULL;
221 	for (hd = hp_dinit; hd->hp_driver; hd++) {
222 		if (hd->hp_alive)
223 			continue;
224 		/* Must not be a slave */
225 		if (hd->hp_cdriver)
226 			continue;
227 		addr = hd->hp_addr;
228 		/*
229 		 * Exact match; all done.
230 		 */
231 		if (addr != NULL && addr == hw->hw_addr) {
232 			match_d = hd;
233 			break;
234 		}
235 		/*
236 		 * Wildcard; possible match so remember first instance
237 		 * but continue looking for exact match.
238 		 */
239 		if (addr == NULL && same_hw_device(hw, hd) && match_d == NULL)
240 			match_d = hd;
241 	}
242 #ifdef DEBUG
243 	if (acdebug) {
244 		if (match_d)
245 			printf("found %s%d\n",
246 			       match_d->hp_driver->d_name,
247 			       match_d->hp_unit);
248 		else
249 			printf("not found\n");
250 	}
251 #endif
252 	/*
253 	 * Didn't find an ioconf entry for this piece
254 	 * of hardware, just ignore it.
255 	 */
256 	if (match_d == NULL)
257 		return(0);
258 	/*
259 	 * Found a match, attempt to initialize.
260 	 * Note, we can still fail if HW won't initialize.
261 	 */
262 	hd = match_d;
263 	oaddr = hd->hp_addr;
264 	hd->hp_addr = hw->hw_addr;
265 	if ((*hd->hp_driver->d_init)(hd)) {
266 		hd->hp_alive = 1;
267 		printf("%s%d", hd->hp_driver->d_name, hd->hp_unit);
268 		printf(" at %p", hd->hp_addr);
269 		if (hd->hp_ipl)
270 			printf(", ipl %d", hd->hp_ipl);
271 		if (hd->hp_flags)
272 			printf(", flags 0x%x", hd->hp_flags);
273 		printf("\n");
274 	} else
275 		hd->hp_addr = oaddr;
276 	return(1);
277 }
278 
279 /*
280  * Search each BUS controller found for slaves attached to it.
281  * The bad news is that we don't know how to uniquely identify all slaves
282  * (e.g. PPI devices on HP-IB).  The good news is that we can at least
283  * differentiate those from slaves we can identify.  At worst (a totally
284  * wildcarded entry) this will cause us to locate such a slave at the first
285  * unused position instead of where it really is.  To save grief, non-
286  * identifing devices should always be fully qualified.
287  */
288 void
289 find_slaves(struct hp_ctlr *hc)
290 {
291 	int s;
292 	struct hp_device *hd;
293 	struct hp_device *match_s;
294 	int maxslaves = MAXSLAVES-1;
295 	int new_s, new_c, old_s, old_c;
296 	int rescan;
297 
298 #ifdef DEBUG
299 	if (acdebug)
300 		printf("find_slaves: for %s%d\n",
301 		       hc->hp_driver->d_name, hc->hp_unit);
302 #endif
303 	for (s = 0; s < maxslaves; s++) {
304 		rescan = 1;
305 		match_s = NULL;
306 		for (hd = hp_dinit; hd->hp_driver; hd++) {
307 			/*
308 			 * Rule out the easy ones:
309 			 * 1. slave already assigned or not a slave
310 			 * 2. not of the proper type
311 			 * 3. controller specified but not this one
312 			 * 4. slave specified but not this one
313 			 */
314 			if (hd->hp_alive || hd->hp_cdriver == NULL)
315 				continue;
316 			if (!dr_type(hc->hp_driver, hd->hp_cdriver->d_name))
317 				continue;
318 			if (hd->hp_ctlr >= 0 && hd->hp_ctlr != hc->hp_unit)
319 				continue;
320 			if (hd->hp_slave >= 0 && hd->hp_slave != s)
321 				continue;
322 			/*
323 			 * Case 0: first possible match.
324 			 * Remember it and keep looking for better.
325 			 */
326 			if (match_s == NULL) {
327 				match_s = hd;
328 				new_c = hc->hp_unit;
329 				new_s = s;
330 				continue;
331 			}
332 			/*
333 			 * Case 1: exact match.
334 			 * All done.  Note that we do not attempt any other
335 			 * matches if this one fails.  This allows us to
336 			 * "reserve" locations for dynamic addition of
337 			 * disk/tape drives by fully qualifing the location.
338 			 */
339 			if (hd->hp_slave == s && hd->hp_ctlr == hc->hp_unit) {
340 				match_s = hd;
341 				rescan = 0;
342 				break;
343 			}
344 			/*
345 			 * Case 2: right controller, wildcarded slave.
346 			 * Remember first and keep looking for an exact match.
347 			 */
348 			if (hd->hp_ctlr == hc->hp_unit &&
349 			    match_s->hp_ctlr < 0) {
350 				match_s = hd;
351 				new_s = s;
352 				continue;
353 			}
354 			/*
355 			 * Case 3: right slave, wildcarded controller.
356 			 * Remember and keep looking for a better match.
357 			 */
358 			if (hd->hp_slave == s &&
359 			    match_s->hp_ctlr < 0 && match_s->hp_slave < 0) {
360 				match_s = hd;
361 				new_c = hc->hp_unit;
362 				continue;
363 			}
364 			/*
365 			 * OW: we had a totally wildcarded spec.
366 			 * If we got this far, we have found a possible
367 			 * match already (match_s != NULL) so there is no
368 			 * reason to remember this one.
369 			 */
370 			continue;
371 		}
372 		/*
373 		 * Found a match.  We need to set hp_ctlr/hp_slave properly
374 		 * for the init routines but we also need to remember all
375 		 * the old values in case this doesn't pan out.
376 		 */
377 		if (match_s) {
378 			hd = match_s;
379 			old_c = hd->hp_ctlr;
380 			old_s = hd->hp_slave;
381 			if (hd->hp_ctlr < 0)
382 				hd->hp_ctlr = new_c;
383 			if (hd->hp_slave < 0)
384 				hd->hp_slave = new_s;
385 #ifdef DEBUG
386 			if (acdebug)
387 				printf("looking for %s%d at slave %d...",
388 				       hd->hp_driver->d_name,
389 				       hd->hp_unit, hd->hp_slave);
390 #endif
391 
392 			if ((*hd->hp_driver->d_init)(hd)) {
393 #ifdef DEBUG
394 				if (acdebug)
395 					printf("found\n");
396 #endif
397 				printf("%s%d at %s%d, slave %d",
398 				       hd->hp_driver->d_name, hd->hp_unit,
399 				       hc->hp_driver->d_name, hd->hp_ctlr,
400 				       hd->hp_slave);
401 				if (hd->hp_flags)
402 					printf(" flags 0x%x", hd->hp_flags);
403 				printf("\n");
404 				hd->hp_alive = 1;
405 				if (hd->hp_dk && dkn < DK_NDRIVE)
406 					hd->hp_dk = dkn++;
407 				else
408 					hd->hp_dk = -1;
409 				rescan = 1;
410 			} else {
411 #ifdef DEBUG
412 				if (acdebug)
413 					printf("not found\n");
414 #endif
415 				hd->hp_ctlr = old_c;
416 				hd->hp_slave = old_s;
417 			}
418 			/*
419 			 * XXX: This should be handled better.
420 			 * Re-scan a slave.  There are two reasons to do this.
421 			 * 1. It is possible to have both a tape and disk
422 			 *    (e.g. 7946) or two disks (e.g. 9122) at the
423 			 *    same slave address.  Here we need to rescan
424 			 *    looking only at entries with a different
425 			 *    physical unit number (hp_flags).
426 			 * 2. It is possible that an init failed because the
427 			 *    slave was there but of the wrong type.  In this
428 			 *    case it may still be possible to match the slave
429 			 *    to another ioconf entry of a different type.
430 			 *    Here we need to rescan looking only at entries
431 			 *    of different types.
432 			 * In both cases we avoid looking at undesirable
433 			 * ioconf entries of the same type by setting their
434 			 * alive fields to -1.
435 			 */
436 			if (rescan) {
437 				for (hd = hp_dinit; hd->hp_driver; hd++) {
438 					if (hd->hp_alive)
439 						continue;
440 					if (match_s->hp_alive == 1) {	/* 1 */
441 						if (hd->hp_flags == match_s->hp_flags)
442 							hd->hp_alive = -1;
443 					} else {			/* 2 */
444 						if (hd->hp_driver == match_s->hp_driver)
445 							hd->hp_alive = -1;
446 					}
447 				}
448 				s--;
449 				continue;
450 			}
451 		}
452 		/*
453 		 * Reset bogon alive fields prior to attempting next slave
454 		 */
455 		for (hd = hp_dinit; hd->hp_driver; hd++)
456 			if (hd->hp_alive == -1)
457 				hd->hp_alive = 0;
458 	}
459 }
460 
461 int
462 same_hw_device(struct hp_hw *hw, struct hp_device *hd)
463 {
464 	int found = 0;
465 
466 	switch (hw->hw_type) {
467 	case NET:
468 		found = dr_type(hd->hp_driver, "le");
469 		break;
470 	case SCSI:
471 		found = dr_type(hd->hp_driver, "scsi");
472 		break;
473 	case VME:
474 	case MISC:
475 		break;
476 	}
477 	return(found);
478 }
479 
480 #define setup_hw(hw, addr, type, name) \
481 	(hw)->hw_addr = addr; \
482 	(hw)->hw_type = type; \
483 	(hw)->hw_name = name
484 
485 void
486 find_devs(void)
487 {
488 	struct hp_hw *hw = sc_table;
489 
490 	setup_hw(hw, (uint8_t *)0x51000000, SIO,      "uPD7201A (SIO)");
491 	hw++;
492 
493 	setup_hw(hw, (uint8_t *)0x51000004, KEYBOARD, "uPD7201A (KBD)");
494 	hw++;
495 
496 	setup_hw(hw, (uint8_t *)0xe1000000, SCSI,     "MB89352  (SPC)");
497 	hw++;
498 
499 	if (machtype == LUNA_II && !badaddr((void *) 0xe1000040)) {
500 		setup_hw(hw, (uint8_t *)0xe1000040, SCSI,     "MB89352  (SPC)");
501 		hw++;
502 	}
503 	if (!badaddr((void *) 0xf1000000)) {
504 		setup_hw(hw, (uint8_t *)0xf1000000, NET,      "Am7990 (LANCE)");
505 		hw++;
506 	}
507 }
508