autoconf.c revision 1.42
1/* $NetBSD: autoconf.c,v 1.42 1996/10/11 19:49:49 mhitch 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 /* 58 * this is the real thing baby (i.e. not console init) 59 */ 60 amiga_realconfig = 1; 61#ifdef DRACO 62 if (is_draco()) { 63 *draco_intena &= ~DRIRQ_GLOBAL; 64 } else 65#endif 66 custom.intena = INTF_INTEN; 67 68 if (config_rootfound("mainbus", "mainbus") == NULL) 69 panic("no mainbus found"); 70 71#ifdef DEBUG_KERNEL_START 72 kprintf("survived autoconf, going to enable interrupts\n"); 73#endif 74 75#ifdef DRACO 76 if (is_draco()) { 77 *draco_intena |= DRIRQ_GLOBAL; 78 /* softints always enabled */ 79 } else 80#endif 81 { 82 custom.intena = INTF_SETCLR | INTF_INTEN; 83 84 /* also enable hardware aided software interrupts */ 85 custom.intena = INTF_SETCLR | INTF_SOFTINT; 86 } 87#ifdef DEBUG_KERNEL_START 88 kprintf("survived interrupt enable\n"); 89#endif 90 91#ifdef GENERIC 92 if ((boothowto & RB_ASKNAME) == 0) { 93 setroot(); 94#ifdef DEBUG_KERNEL_START 95 kprintf("survived setroot()\n"); 96#endif 97 } 98 setconf(); 99#ifdef DEBUG_KERNEL_START 100 kprintf("survived setconf()\n"); 101#endif 102#else 103 setroot(); 104#ifdef DEBUG_KERNEL_START 105 kprintf("survived setroot()\n"); 106#endif 107#endif 108#ifdef DEBUG_KERNEL_START 109 kprintf("survived root device search\n"); 110#endif 111 swapconf(); 112#ifdef DEBUG_KERNEL_START 113 kprintf("survived swap device search\n"); 114#endif 115 cold = 0; 116} 117 118/*ARGSUSED*/ 119int 120simple_devprint(auxp, pnp) 121 void *auxp; 122 const char *pnp; 123{ 124 return(QUIET); 125} 126 127int 128matchname(fp, sp) 129 char *fp, *sp; 130{ 131 int len; 132 133 len = strlen(fp); 134 if (strlen(sp) != len) 135 return(0); 136 if (bcmp(fp, sp, len) == 0) 137 return(1); 138 return(0); 139} 140 141/* 142 * use config_search to find appropriate device, then call that device 143 * directly with NULL device variable storage. A device can then 144 * always tell the difference betwean the real and console init 145 * by checking for NULL. 146 */ 147int 148amiga_config_found(pcfp, pdp, auxp, pfn) 149 struct cfdata *pcfp; 150 struct device *pdp; 151 void *auxp; 152 cfprint_t pfn; 153{ 154 struct device temp; 155 struct cfdata *cf; 156 157 if (amiga_realconfig) 158 return(config_found(pdp, auxp, pfn) != NULL); 159 160 if (pdp == NULL) 161 pdp = &temp; 162 163 pdp->dv_cfdata = pcfp; 164 if ((cf = config_search((cfmatch_t)NULL, pdp, auxp)) != NULL) { 165 cf->cf_attach->ca_attach(pdp, NULL, auxp); 166 pdp->dv_cfdata = NULL; 167 return(1); 168 } 169 pdp->dv_cfdata = NULL; 170 return(0); 171} 172 173/* 174 * this function needs to get enough configured to do a console 175 * basically this means start attaching the grfxx's that support 176 * the console. Kinda hacky but it works. 177 */ 178void 179config_console() 180{ 181 struct cfdata *cf; 182 183 /* 184 * we need mainbus' cfdata. 185 */ 186 cf = config_rootsearch(NULL, "mainbus", "mainbus"); 187 if (cf == NULL) { 188 panic("no mainbus"); 189 } 190 /* 191 * internal grf. 192 */ 193#ifdef DRACO 194 if (!(is_draco())) 195#endif 196 amiga_config_found(cf, NULL, "grfcc", NULL); 197 /* 198 * zbus knows when its not for real and will 199 * only configure the appropriate hardware 200 */ 201 amiga_config_found(cf, NULL, "zbus", NULL); 202} 203 204/* 205 * mainbus driver 206 */ 207struct cfattach mainbus_ca = { 208 sizeof(struct device), mbmatch, mbattach 209}; 210 211struct cfdriver mainbus_cd = { 212 NULL, "mainbus", DV_DULL, NULL, 0 213}; 214 215int 216mbmatch(pdp, match, auxp) 217 struct device *pdp; 218 void *match, *auxp; 219{ 220 struct cfdata *cfp = match; 221 222 if (cfp->cf_unit > 0) 223 return(0); 224 /* 225 * We are always here 226 */ 227 return(1); 228} 229 230/* 231 * "find" all the things that should be there. 232 */ 233void 234mbattach(pdp, dp, auxp) 235 struct device *pdp, *dp; 236 void *auxp; 237{ 238 kprintf("\n"); 239 config_found(dp, "clock", simple_devprint); 240#ifdef DRACO 241 if (is_draco()) { 242 config_found(dp, "kbd", simple_devprint); 243 config_found(dp, "drsc", simple_devprint); 244 /* 245 * XXX -- missing here: 246 * SuperIO chip serial, parallel, floppy 247 * or maybe just make that into a pseudo 248 * ISA bus. 249 */ 250 } else 251#endif 252 { 253 config_found(dp, "ser", simple_devprint); 254 config_found(dp, "par", simple_devprint); 255 config_found(dp, "kbd", simple_devprint); 256 config_found(dp, "ms", simple_devprint); 257 config_found(dp, "ms", simple_devprint); 258 config_found(dp, "grfcc", simple_devprint); 259 config_found(dp, "fdc", simple_devprint); 260 } 261 if (is_a4000() || is_a1200()) 262 config_found(dp, "idesc", simple_devprint); 263 if (is_a4000()) /* Try to configure A4000T SCSI */ 264 config_found(dp, "afsc", simple_devprint); 265 config_found(dp, "zbus", simple_devprint); 266 if (is_a3000()) 267 config_found(dp, "ahsc", simple_devprint); 268} 269 270int 271mbprint(auxp, pnp) 272 void *auxp; 273 const char *pnp; 274{ 275 if (pnp) 276 kprintf("%s at %s", (char *)auxp, pnp); 277 return(UNCONF); 278} 279 280void 281swapconf() 282{ 283 struct swdevt *swp; 284 u_int maj; 285 int nb; 286 287 for (swp = swdevt; swp->sw_dev > 0; swp++) { 288 maj = major(swp->sw_dev); 289 290 if (maj > nblkdev) 291 break; 292 293 if (bdevsw[maj].d_psize) { 294 nb = bdevsw[maj].d_psize(swp->sw_dev); 295 if (nb > 0 && 296 (swp->sw_nblks == 0 || swp->sw_nblks > nb)) 297 swp->sw_nblks = nb; 298 else 299 swp->sw_nblks = 0; 300 } 301 swp->sw_nblks = ctod(dtoc(swp->sw_nblks)); 302 } 303 dumpconf(); 304 if (dumplo < 0) 305 dumplo = 0; 306 307} 308 309#define DOSWAP /* change swdevt and dumpdev */ 310u_long bootdev = 0; /* should be dev_t, but not until 32 bits */ 311 312static char devname[][2] = { 313 { 0 ,0 }, 314 { 0 ,0 }, 315 { 'f' ,'d' }, /* 2 = fd */ 316 { 0 ,0 }, 317 { 's' ,'d' } /* 4 = sd -- new SCSI system */ 318}; 319 320void 321setroot() 322{ 323 int majdev, mindev, unit, part, adaptor; 324 dev_t temp = 0; 325 dev_t orootdev; 326 struct swdevt *swp; 327 328 if (boothowto & RB_DFLTROOT || 329 (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) 330 return; 331 majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK; 332 if (majdev > sizeof(devname) / sizeof(devname[0])) 333 return; 334 adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK; 335 part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK; 336 unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK; 337 orootdev = rootdev; 338 rootdev = MAKEDISKDEV(majdev, unit, part); 339 /* 340 * If the original rootdev is the same as the one 341 * just calculated, don't need to adjust the swap configuration. 342 */ 343 if (rootdev == orootdev) 344 return; 345 kprintf("changing root device to %c%c%d%c\n", 346 devname[majdev][0], devname[majdev][1], 347 unit, part + 'a'); 348#ifdef DOSWAP 349 mindev = DISKUNIT(rootdev); 350 for (swp = swdevt; swp->sw_dev; swp++) { 351 if (majdev == major(swp->sw_dev) && 352 mindev == DISKUNIT(swp->sw_dev)) { 353 temp = swdevt[0].sw_dev; 354 swdevt[0].sw_dev = swp->sw_dev; 355 swp->sw_dev = temp; 356 break; 357 } 358 } 359 if (swp->sw_dev == 0) 360 return; 361 /* 362 * If dumpdev was the same as the old primary swap 363 * device, move it to the new primary swap device. 364 */ 365 if (temp == dumpdev) 366 dumpdev = swdevt[0].sw_dev; 367#endif 368} 369 370 371/* 372 * Try to determine, of this machine is an A3000, which has a builtin 373 * realtime clock and scsi controller, so that this hardware is only 374 * included as "configured" if this IS an A3000 375 */ 376 377int a3000_flag = 1; /* patchable */ 378#ifdef A4000 379int a4000_flag = 1; /* patchable - default to A4000 */ 380#else 381int a4000_flag = 0; /* patchable */ 382#endif 383 384int 385is_a3000() 386{ 387 /* this is a dirty kludge.. but how do you do this RIGHT ? :-) */ 388 extern long boot_fphystart; 389 short sc; 390 391 if ((machineid >> 16) == 3000) 392 return (1); /* It's an A3000 */ 393 if (machineid >> 16) 394 return (0); /* It's not an A3000 */ 395 /* Machine type is unknown, so try to guess it */ 396 /* where is fastram on the A4000 ?? */ 397 /* if fastram is below 0x07000000, assume it's not an A3000 */ 398 if (boot_fphystart < 0x07000000) 399 return(0); 400 /* 401 * OK, fastram starts at or above 0x07000000, check specific 402 * machines 403 */ 404 for (sc = 0; sc < ncfdev; sc++) { 405 switch (cfdev[sc].rom.manid) { 406 case 2026: /* Progressive Peripherals, Inc */ 407 switch (cfdev[sc].rom.prodid) { 408 case 0: /* PPI Mercury - A3000 */ 409 case 1: /* PP&S A3000 '040 */ 410 return(1); 411 case 150: /* PPI Zeus - it's an A2000 */ 412 case 105: /* PP&S A2000 '040 */ 413 case 187: /* PP&S A500 '040 */ 414 return(0); 415 } 416 break; 417 418 case 2112: /* IVS */ 419 switch (cfdev[sc].rom.prodid) { 420 case 242: 421 return(0); /* A2000 accelerator? */ 422 } 423 break; 424 } 425 } 426 return (a3000_flag); /* XXX let flag tell now */ 427} 428 429int 430is_a4000() 431{ 432 if ((machineid >> 16) == 4000) 433 return (1); /* It's an A4000 */ 434 if ((machineid >> 16) == 1200) 435 return (0); /* It's an A1200, so not A4000 */ 436#ifdef DRACO 437 if (is_draco()) 438 return (0); 439#endif 440 /* Do I need this any more? */ 441 if ((custom.deniseid & 0xff) == 0xf8) 442 return (1); 443#ifdef DEBUG 444 if (a4000_flag) 445 kprintf("Denise ID = %04x\n", (unsigned short)custom.deniseid); 446#endif 447 if (machineid >> 16) 448 return (0); /* It's not an A4000 */ 449 return (a4000_flag); /* Machine type not set */ 450} 451 452int 453is_a1200() 454{ 455 if ((machineid >> 16) == 1200) 456 return (1); /* It's an A1200 */ 457 return (0); /* Machine type not set */ 458} 459 460#ifdef DRACO 461int 462is_draco() 463{ 464 if ((machineid >> 24) == 0x7D) 465 return ((machineid >> 16) & 0xFF); 466 return (0); 467} 468#endif 469