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