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