autoconf.c revision 1.44
1/* $NetBSD: autoconf.c,v 1.44 1996/12/17 11:43:12 is Exp $ */ 2 3/* 4 * Copyright (c) 1994 Christian E. Hopps 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Christian E. Hopps. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/reboot.h> 35#include <sys/conf.h> 36#include <sys/device.h> 37#include <sys/disklabel.h> 38#include <machine/cpu.h> 39#include <amiga/amiga/cfdev.h> 40#include <amiga/amiga/device.h> 41#include <amiga/amiga/custom.h> 42 43void setroot __P((void)); 44void swapconf __P((void)); 45void mbattach __P((struct device *, struct device *, void *)); 46int mbprint __P((void *, const char *)); 47int mbmatch __P((struct device *, void *, void *)); 48 49int cold; /* 1 if still booting */ 50#include <sys/kernel.h> 51/* 52 * called at boot time, configure all devices on system 53 */ 54void 55configure() 56{ 57 int s; 58 /* 59 * this is the real thing baby (i.e. not console init) 60 */ 61 amiga_realconfig = 1; 62#ifdef DRACO 63 if (is_draco()) { 64 *draco_intena &= ~DRIRQ_GLOBAL; 65 } else 66#endif 67 custom.intena = INTF_INTEN; 68 s = splhigh(); 69 70 if (config_rootfound("mainbus", "mainbus") == NULL) 71 panic("no mainbus found"); 72 73#ifdef DEBUG_KERNEL_START 74 printf("survived autoconf, going to enable interrupts\n"); 75#endif 76 77#ifdef DRACO 78 if (is_draco()) { 79 *draco_intena |= DRIRQ_GLOBAL; 80 /* softints always enabled */ 81 } else 82#endif 83 { 84 custom.intena = INTF_SETCLR | INTF_INTEN; 85 86 /* also enable hardware aided software interrupts */ 87 custom.intena = INTF_SETCLR | INTF_SOFTINT; 88 } 89 splx(s); 90#ifdef DEBUG_KERNEL_START 91 printf("survived interrupt enable\n"); 92#endif 93 94#ifdef GENERIC 95 if ((boothowto & RB_ASKNAME) == 0) { 96 setroot(); 97#ifdef DEBUG_KERNEL_START 98 printf("survived setroot()\n"); 99#endif 100 } 101 setconf(); 102#ifdef DEBUG_KERNEL_START 103 printf("survived setconf()\n"); 104#endif 105#else 106 setroot(); 107#ifdef DEBUG_KERNEL_START 108 printf("survived setroot()\n"); 109#endif 110#endif 111#ifdef DEBUG_KERNEL_START 112 printf("survived root device search\n"); 113#endif 114 swapconf(); 115#ifdef DEBUG_KERNEL_START 116 printf("survived swap device search\n"); 117#endif 118 cold = 0; 119} 120 121/*ARGSUSED*/ 122int 123simple_devprint(auxp, pnp) 124 void *auxp; 125 const char *pnp; 126{ 127 return(QUIET); 128} 129 130int 131matchname(fp, sp) 132 char *fp, *sp; 133{ 134 int len; 135 136 len = strlen(fp); 137 if (strlen(sp) != len) 138 return(0); 139 if (bcmp(fp, sp, len) == 0) 140 return(1); 141 return(0); 142} 143 144/* 145 * use config_search to find appropriate device, then call that device 146 * directly with NULL device variable storage. A device can then 147 * always tell the difference betwean the real and console init 148 * by checking for NULL. 149 */ 150int 151amiga_config_found(pcfp, pdp, auxp, pfn) 152 struct cfdata *pcfp; 153 struct device *pdp; 154 void *auxp; 155 cfprint_t pfn; 156{ 157 struct device temp; 158 struct cfdata *cf; 159 160 if (amiga_realconfig) 161 return(config_found(pdp, auxp, pfn) != NULL); 162 163 if (pdp == NULL) 164 pdp = &temp; 165 166 pdp->dv_cfdata = pcfp; 167 if ((cf = config_search((cfmatch_t)NULL, pdp, auxp)) != NULL) { 168 cf->cf_attach->ca_attach(pdp, NULL, auxp); 169 pdp->dv_cfdata = NULL; 170 return(1); 171 } 172 pdp->dv_cfdata = NULL; 173 return(0); 174} 175 176/* 177 * this function needs to get enough configured to do a console 178 * basically this means start attaching the grfxx's that support 179 * the console. Kinda hacky but it works. 180 */ 181void 182config_console() 183{ 184 struct cfdata *cf; 185 186 /* 187 * we need mainbus' cfdata. 188 */ 189 cf = config_rootsearch(NULL, "mainbus", "mainbus"); 190 if (cf == NULL) { 191 panic("no mainbus"); 192 } 193 /* 194 * delay clock calibration. 195 */ 196 amiga_config_found(cf, NULL, "clock", NULL); 197 198 /* 199 * internal grf. 200 */ 201#ifdef DRACO 202 if (!(is_draco())) 203#endif 204 amiga_config_found(cf, NULL, "grfcc", NULL); 205 /* 206 * zbus knows when its not for real and will 207 * only configure the appropriate hardware 208 */ 209 amiga_config_found(cf, NULL, "zbus", NULL); 210} 211 212/* 213 * mainbus driver 214 */ 215struct cfattach mainbus_ca = { 216 sizeof(struct device), mbmatch, mbattach 217}; 218 219struct cfdriver mainbus_cd = { 220 NULL, "mainbus", DV_DULL, NULL, 0 221}; 222 223int 224mbmatch(pdp, match, auxp) 225 struct device *pdp; 226 void *match, *auxp; 227{ 228 struct cfdata *cfp = match; 229 230 if (cfp->cf_unit > 0) 231 return(0); 232 /* 233 * We are always here 234 */ 235 return(1); 236} 237 238/* 239 * "find" all the things that should be there. 240 */ 241void 242mbattach(pdp, dp, auxp) 243 struct device *pdp, *dp; 244 void *auxp; 245{ 246 printf("\n"); 247 config_found(dp, "clock", simple_devprint); 248#ifdef DRACO 249 if (is_draco()) { 250 config_found(dp, "kbd", simple_devprint); 251 config_found(dp, "drsc", simple_devprint); 252 config_found(dp, "drcom", simple_devprint); 253 config_found(dp, "drcom", simple_devprint); 254 /* 255 * XXX -- missing here: 256 * SuperIO chip serial, parallel, floppy 257 * or maybe just make that into a pseudo 258 * ISA bus. 259 */ 260 } else 261#endif 262 { 263 config_found(dp, "ser", simple_devprint); 264 config_found(dp, "par", simple_devprint); 265 config_found(dp, "kbd", simple_devprint); 266 config_found(dp, "ms", simple_devprint); 267 config_found(dp, "ms", simple_devprint); 268 config_found(dp, "grfcc", simple_devprint); 269 config_found(dp, "fdc", simple_devprint); 270 } 271 if (is_a4000() || is_a1200()) 272 config_found(dp, "idesc", simple_devprint); 273 if (is_a4000()) /* Try to configure A4000T SCSI */ 274 config_found(dp, "afsc", simple_devprint); 275 config_found(dp, "zbus", simple_devprint); 276 if (is_a3000()) 277 config_found(dp, "ahsc", simple_devprint); 278} 279 280int 281mbprint(auxp, pnp) 282 void *auxp; 283 const char *pnp; 284{ 285 if (pnp) 286 printf("%s at %s", (char *)auxp, pnp); 287 return(UNCONF); 288} 289 290void 291swapconf() 292{ 293 struct swdevt *swp; 294 u_int maj; 295 int nb; 296 297 for (swp = swdevt; swp->sw_dev > 0; swp++) { 298 maj = major(swp->sw_dev); 299 300 if (maj > nblkdev) 301 break; 302 303 if (bdevsw[maj].d_psize) { 304 nb = bdevsw[maj].d_psize(swp->sw_dev); 305 if (nb > 0 && 306 (swp->sw_nblks == 0 || swp->sw_nblks > nb)) 307 swp->sw_nblks = nb; 308 else 309 swp->sw_nblks = 0; 310 } 311 swp->sw_nblks = ctod(dtoc(swp->sw_nblks)); 312 } 313 dumpconf(); 314 if (dumplo < 0) 315 dumplo = 0; 316 317} 318 319#define DOSWAP /* change swdevt and dumpdev */ 320u_long bootdev = 0; /* should be dev_t, but not until 32 bits */ 321 322static char devname[][2] = { 323 { 0 ,0 }, 324 { 0 ,0 }, 325 { 'f' ,'d' }, /* 2 = fd */ 326 { 0 ,0 }, 327 { 's' ,'d' } /* 4 = sd -- new SCSI system */ 328}; 329 330void 331setroot() 332{ 333 int majdev, mindev, unit, part, adaptor; 334 dev_t temp = 0; 335 dev_t orootdev; 336 struct swdevt *swp; 337 338 if (boothowto & RB_DFLTROOT || 339 (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) 340 return; 341 majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK; 342 if (majdev > sizeof(devname) / sizeof(devname[0])) 343 return; 344 adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK; 345 part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK; 346 unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK; 347 orootdev = rootdev; 348 rootdev = MAKEDISKDEV(majdev, unit, part); 349 /* 350 * If the original rootdev is the same as the one 351 * just calculated, don't need to adjust the swap configuration. 352 */ 353 if (rootdev == orootdev) 354 return; 355 printf("changing root device to %c%c%d%c\n", 356 devname[majdev][0], devname[majdev][1], 357 unit, part + 'a'); 358#ifdef DOSWAP 359 mindev = DISKUNIT(rootdev); 360 for (swp = swdevt; swp->sw_dev; swp++) { 361 if (majdev == major(swp->sw_dev) && 362 mindev == DISKUNIT(swp->sw_dev)) { 363 temp = swdevt[0].sw_dev; 364 swdevt[0].sw_dev = swp->sw_dev; 365 swp->sw_dev = temp; 366 break; 367 } 368 } 369 if (swp->sw_dev == 0) 370 return; 371 /* 372 * If dumpdev was the same as the old primary swap 373 * device, move it to the new primary swap device. 374 */ 375 if (temp == dumpdev) 376 dumpdev = swdevt[0].sw_dev; 377#endif 378} 379 380 381/* 382 * Try to determine, of this machine is an A3000, which has a builtin 383 * realtime clock and scsi controller, so that this hardware is only 384 * included as "configured" if this IS an A3000 385 */ 386 387int a3000_flag = 1; /* patchable */ 388#ifdef A4000 389int a4000_flag = 1; /* patchable - default to A4000 */ 390#else 391int a4000_flag = 0; /* patchable */ 392#endif 393 394int 395is_a3000() 396{ 397 /* this is a dirty kludge.. but how do you do this RIGHT ? :-) */ 398 extern long boot_fphystart; 399 short sc; 400 401 if ((machineid >> 16) == 3000) 402 return (1); /* It's an A3000 */ 403 if (machineid >> 16) 404 return (0); /* It's not an A3000 */ 405 /* Machine type is unknown, so try to guess it */ 406 /* where is fastram on the A4000 ?? */ 407 /* if fastram is below 0x07000000, assume it's not an A3000 */ 408 if (boot_fphystart < 0x07000000) 409 return(0); 410 /* 411 * OK, fastram starts at or above 0x07000000, check specific 412 * machines 413 */ 414 for (sc = 0; sc < ncfdev; sc++) { 415 switch (cfdev[sc].rom.manid) { 416 case 2026: /* Progressive Peripherals, Inc */ 417 switch (cfdev[sc].rom.prodid) { 418 case 0: /* PPI Mercury - A3000 */ 419 case 1: /* PP&S A3000 '040 */ 420 return(1); 421 case 150: /* PPI Zeus - it's an A2000 */ 422 case 105: /* PP&S A2000 '040 */ 423 case 187: /* PP&S A500 '040 */ 424 return(0); 425 } 426 break; 427 428 case 2112: /* IVS */ 429 switch (cfdev[sc].rom.prodid) { 430 case 242: 431 return(0); /* A2000 accelerator? */ 432 } 433 break; 434 } 435 } 436 return (a3000_flag); /* XXX let flag tell now */ 437} 438 439int 440is_a4000() 441{ 442 if ((machineid >> 16) == 4000) 443 return (1); /* It's an A4000 */ 444 if ((machineid >> 16) == 1200) 445 return (0); /* It's an A1200, so not A4000 */ 446#ifdef DRACO 447 if (is_draco()) 448 return (0); 449#endif 450 /* Do I need this any more? */ 451 if ((custom.deniseid & 0xff) == 0xf8) 452 return (1); 453#ifdef DEBUG 454 if (a4000_flag) 455 printf("Denise ID = %04x\n", (unsigned short)custom.deniseid); 456#endif 457 if (machineid >> 16) 458 return (0); /* It's not an A4000 */ 459 return (a4000_flag); /* Machine type not set */ 460} 461 462int 463is_a1200() 464{ 465 if ((machineid >> 16) == 1200) 466 return (1); /* It's an A1200 */ 467 return (0); /* Machine type not set */ 468} 469 470#ifdef DRACO 471int 472is_draco() 473{ 474 if ((machineid >> 24) == 0x7D) 475 return ((machineid >> 16) & 0xFF); 476 return (0); 477} 478#endif 479