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