1 /* $NetBSD: machdep.c,v 1.42 2002/09/25 22:21:18 thorpej Exp $ */ 2 3 /* 4 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 5 * Copyright (C) 1995, 1996 TooLs GmbH. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by TooLs GmbH. 19 * 4. The name of TooLs GmbH may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "opt_compat_netbsd.h" 35 #include "opt_ddb.h" 36 37 #include <sys/param.h> 38 #include <sys/buf.h> 39 #include <sys/conf.h> 40 #include <sys/device.h> 41 #include <sys/exec.h> 42 #include <sys/kernel.h> 43 #include <sys/malloc.h> 44 #include <sys/mbuf.h> 45 #include <sys/mount.h> 46 #include <sys/msgbuf.h> 47 #include <sys/proc.h> 48 #include <sys/reboot.h> 49 #include <sys/syscallargs.h> 50 #include <sys/syslog.h> 51 #include <sys/systm.h> 52 #include <sys/user.h> 53 54 #include <uvm/uvm_extern.h> 55 56 #include <sys/sysctl.h> 57 58 #include <net/netisr.h> 59 60 #include <machine/autoconf.h> 61 #include <machine/bat.h> 62 #include <machine/bootinfo.h> 63 #include <machine/bus.h> 64 #include <machine/intr.h> 65 #include <machine/pmap.h> 66 #include <machine/platform.h> 67 #include <machine/powerpc.h> 68 #include <machine/residual.h> 69 #include <machine/trap.h> 70 71 #include <dev/cons.h> 72 73 #include "com.h" 74 #if (NCOM > 0) 75 #include <sys/termios.h> 76 #include <dev/ic/comreg.h> 77 #include <dev/ic/comvar.h> 78 void comsoft(void); 79 #endif 80 81 #ifdef DDB 82 #include <machine/db_machdep.h> 83 #include <ddb/db_extern.h> 84 #endif 85 86 void initppc __P((u_long, u_long, u_int, void *)); 87 void dumpsys __P((void)); 88 void strayintr __P((int)); 89 int lcsplx __P((int)); 90 91 char bootinfo[BOOTINFO_MAXSIZE]; 92 93 vaddr_t prep_intr_reg; /* PReP interrupt vector register */ 94 95 #define OFMEMREGIONS 32 96 struct mem_region physmemr[OFMEMREGIONS], availmemr[OFMEMREGIONS]; 97 98 paddr_t avail_end; /* XXX temporary */ 99 100 RESIDUAL *res; 101 RESIDUAL resdata; 102 103 #ifdef DDB 104 extern void *endsym, *startsym; 105 #endif 106 107 void 108 initppc(startkernel, endkernel, args, btinfo) 109 u_long startkernel, endkernel; 110 u_int args; 111 void *btinfo; 112 { 113 114 /* 115 * copy bootinfo 116 */ 117 memcpy(bootinfo, btinfo, sizeof(bootinfo)); 118 119 /* 120 * copy residual data 121 */ 122 { 123 struct btinfo_residual *resinfo; 124 125 resinfo = 126 (struct btinfo_residual *)lookup_bootinfo(BTINFO_RESIDUAL); 127 if (!resinfo) 128 panic("not found residual information in bootinfo"); 129 130 if (((RESIDUAL *)resinfo->addr != 0) && 131 ((RESIDUAL *)resinfo->addr)->ResidualLength != 0) { 132 memcpy(&resdata, resinfo->addr, sizeof(resdata)); 133 res = &resdata; 134 } else 135 panic("No residual data."); 136 } 137 138 /* 139 * Set memory region 140 */ 141 { 142 u_long memsize = res->TotalMemory; 143 144 physmemr[0].start = 0; 145 physmemr[0].size = memsize & ~PGOFSET; 146 availmemr[0].start = (endkernel + PGOFSET) & ~PGOFSET; 147 availmemr[0].size = memsize - availmemr[0].start; 148 } 149 avail_end = physmemr[0].start + physmemr[0].size; /* XXX temporary */ 150 151 /* 152 * Set CPU clock 153 */ 154 { 155 struct btinfo_clock *clockinfo; 156 extern u_long ticks_per_sec, ns_per_tick; 157 158 clockinfo = 159 (struct btinfo_clock *)lookup_bootinfo(BTINFO_CLOCK); 160 if (!clockinfo) 161 panic("not found clock information in bootinfo"); 162 163 ticks_per_sec = clockinfo->ticks_per_sec; 164 ns_per_tick = 1000000000 / ticks_per_sec; 165 } 166 167 /* Initialize the CPU type */ 168 ident_platform(); 169 170 /* 171 * boothowto 172 */ 173 boothowto = args; 174 175 /* 176 * Initialize bus_space. 177 */ 178 prep_bus_space_init(); 179 180 /* 181 * i386 port says, that this shouldn't be here, 182 * but I really think the console should be initialized 183 * as early as possible. 184 */ 185 consinit(); 186 187 /* 188 * Now setup fixed bat registers 189 */ 190 mpc6xx_batinit( 191 PREP_BUS_SPACE_MEM, BAT_BL_256M, 192 PREP_BUS_SPACE_IO, BAT_BL_256M, 193 0); 194 195 mpc6xx_init(NULL); 196 197 /* 198 * external interrupt handler install 199 */ 200 (*platform->init_intr)(); 201 202 /* 203 * Set the page size. 204 */ 205 uvm_setpagesize(); 206 207 /* 208 * Initialize pmap module. 209 */ 210 pmap_bootstrap(startkernel, endkernel, NULL); 211 212 #ifdef DDB 213 ddb_init((int)((u_long)endsym - (u_long)startsym), startsym, endsym); 214 215 if (boothowto & RB_KDB) 216 Debugger(); 217 #endif 218 } 219 220 void 221 mem_regions(mem, avail) 222 struct mem_region **mem, **avail; 223 { 224 225 *mem = physmemr; 226 *avail = availmemr; 227 } 228 229 /* 230 * Machine dependent startup code. 231 */ 232 void 233 cpu_startup() 234 { 235 /* 236 * Mapping PReP interrput vector register. 237 */ 238 prep_intr_reg = (vaddr_t) mapiodev(PREP_INTR_REG, NBPG); 239 if (!prep_intr_reg) 240 panic("startup: no room for interrupt register"); 241 242 /* 243 * Do common startup. 244 */ 245 mpc6xx_startup(res->VitalProductData.PrintableModel); 246 247 /* 248 * Now allow hardware interrupts. 249 */ 250 { 251 int msr; 252 253 splraise(-1); 254 __asm __volatile ("mfmsr %0; ori %0,%0,%1; mtmsr %0" 255 : "=r"(msr) : "K"(PSL_EE)); 256 } 257 258 /* 259 * Now safe for bus space allocation to use malloc. 260 */ 261 prep_bus_space_mallocok(); 262 } 263 264 /* 265 * lookup_bootinfo: 266 * Look up information in bootinfo of boot loader. 267 */ 268 void * 269 lookup_bootinfo(type) 270 int type; 271 { 272 struct btinfo_common *bt; 273 struct btinfo_common *help = (struct btinfo_common *)bootinfo; 274 275 do { 276 bt = help; 277 if (bt->type == type) 278 return (help); 279 help = (struct btinfo_common *)((char*)help + bt->next); 280 } while (bt->next && 281 (size_t)help < (size_t)bootinfo + sizeof (bootinfo)); 282 283 return (NULL); 284 } 285 286 /* 287 * Soft tty interrupts. 288 */ 289 void 290 softserial() 291 { 292 293 #if (NCOM > 0) 294 comsoft(); 295 #endif 296 } 297 298 /* 299 * Stray interrupts. 300 */ 301 void 302 strayintr(irq) 303 int irq; 304 { 305 306 log(LOG_ERR, "stray interrupt %d\n", irq); 307 } 308 309 /* 310 * Halt or reboot the machine after syncing/dumping according to howto. 311 */ 312 void 313 cpu_reboot(howto, what) 314 int howto; 315 char *what; 316 { 317 static int syncing; 318 319 if (cold) { 320 howto |= RB_HALT; 321 goto halt_sys; 322 } 323 324 boothowto = howto; 325 if ((howto & RB_NOSYNC) == 0 && syncing == 0) { 326 syncing = 1; 327 vfs_shutdown(); /* sync */ 328 resettodr(); /* set wall clock */ 329 } 330 331 /* Disable intr */ 332 splhigh(); 333 334 /* Do dump if requested */ 335 if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) 336 mpc6xx_dumpsys(); 337 338 halt_sys: 339 doshutdownhooks(); 340 341 if (howto & RB_HALT) { 342 printf("\n"); 343 printf("The operating system has halted.\n"); 344 printf("Please press any key to reboot.\n\n"); 345 cnpollc(1); /* for proper keyboard command handling */ 346 cngetc(); 347 cnpollc(0); 348 } 349 350 printf("rebooting...\n\n"); 351 352 (*platform->reset)(); 353 354 for (;;) 355 continue; 356 /* NOTREACHED */ 357 } 358 359 /* 360 * lcsplx() is called from locore; it is an open-coded version of 361 * splx() differing in that it returns the previous priority level. 362 */ 363 int 364 lcsplx(ipl) 365 int ipl; 366 { 367 int oldcpl; 368 369 __asm__ volatile("sync; eieio\n"); /* reorder protect */ 370 oldcpl = cpl; 371 cpl = ipl; 372 if (ipending & ~ipl) 373 do_pending_int(); 374 __asm__ volatile("sync; eieio\n"); /* reorder protect */ 375 376 return (oldcpl); 377 } 378