1 /* Copyright (c) 1999 The NetBSD Foundation, Inc. 2 * All rights reserved. 3 * 4 * Copyright (c) 2008 Microsoft. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by the NetBSD 17 * Foundation, Inc. and its contributors. 18 * 4. Neither the name of The NetBSD Foundation nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 * POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 #include <lib/libsa/stand.h> 37 #include <lib/libsa/loadfile.h> 38 #include <lib/libkern/libkern.h> 39 40 #include <sys/param.h> 41 #include <sys/exec.h> 42 #include <sys/exec_elf.h> 43 #include <sys/reboot.h> 44 45 #include <machine/emipsreg.h> 46 47 #include "common.h" 48 #include "bootinfo.h" 49 #include "start.h" 50 #include "prom_iface.h" 51 52 #if _DEBUG 53 #define TRACE(x) printf x 54 #else 55 #define TRACE(x) 56 #endif 57 58 void epmc_halt(void); 59 void save_locore(void); 60 void restore_locore(void); 61 62 static void *nope(void) {return NULL;} 63 int getchar(void){return GetChar();} 64 65 static void 66 real_halt(void *arg) 67 { 68 int howto = (int)arg; 69 u_int ps = GetPsr(); 70 71 /* Turn off interrupts and the TLB */ 72 #define EMIPS_SR_RP 0x08000000 /* reduced power */ 73 #define EMIPS_SR_TS 0x00200000 /* TLB shutdown */ 74 #define EMIPS_SR_RST 0x00000080 /* Soft-reset */ 75 #define EMIPS_SR_INT 0x0000ff00 /* Interrupt enable mask */ 76 #define EMIPS_SR_IEc 0x00000001 /* Interrupt enable current */ 77 78 ps &= ~(EMIPS_SR_INT | EMIPS_SR_IEc); 79 ps |= EMIPS_SR_TS; 80 SetPsr(ps); 81 82 /* Reset entry must be restored for reboot 83 */ 84 restore_locore(); 85 86 /* Tell the power manager to halt? */ 87 for (;howto & RB_HALT;) { 88 epmc_halt(); 89 90 /* We should not be here!! */ 91 ps |= EMIPS_SR_RP | EMIPS_SR_INT; /* but not current */ 92 SetPsr(ps); 93 } 94 95 /* For a reboot, all we can really do is a reset actually */ 96 for (;;) { 97 ps |= EMIPS_SR_RST; 98 SetPsr(ps); 99 } 100 } 101 102 static void 103 halt(int *unused, int howto) 104 { 105 /* We must switch to a safe stack! TLB will go down 106 */ 107 switch_stack_and_call((void *)howto,real_halt); 108 /* no return, stack lost */ 109 } 110 111 struct callback cb = { 112 nope, 113 nope, 114 nope, 115 nope, 116 nope, 117 nope, 118 nope, 119 nope, 120 nope, 121 getchar, 122 nope, 123 nope, 124 printf, 125 nope, 126 nope, 127 nope, 128 nope, 129 nope, 130 nope, 131 nope, 132 nope, 133 nope, 134 nope, 135 nope, 136 nope, 137 nope, 138 nope, 139 nope, 140 nope, 141 nope, 142 nope, 143 nope, 144 getsysid, 145 nope, 146 nope, 147 nope, 148 nope, 149 nope, 150 nope, 151 halt 152 }; 153 154 typedef char *string_t; 155 156 void epmc_halt(void) 157 { 158 struct _Pmc *pm = (struct _Pmc *)0xfff00000; 159 160 pm->SystemPowerDisable = PMCSC_CPU; 161 } 162 163 164 int init_usart(void) 165 { 166 struct _Usart *us = (struct _Usart *)0xfff90000; 167 168 us->Baud = 0x29; 169 us->Control = (USC_RXEN|USC_TXEN|USC_BPC_8|USC_NONE|USC_1STOP|USC_CLKDIV_4); 170 return 1; 171 } 172 173 /* Need to scan the PMT for all memory controllers 174 * Actually.. just enough to make the kernel fit but we dont know how big it is 175 */ 176 177 /* Common format for SRAM, DDRAM, and FLASH controllers. 178 * Use SRAM decl. and careful about DDRAM that is twice as big. 179 */ 180 typedef struct _Sram *ram_controller_t; 181 # define RAMBT_TAG SRAMBT_TAG 182 # define RAMBT_BASE SRAMBT_BASE 183 # define RAMST_SIZE SRAMST_SIZE 184 185 int init_memory(void) 186 { 187 struct _Pmt *Pmt; 188 ram_controller_t Ram, Ours, First; 189 uint32_t base, addr, moi = (uint32_t)(&init_memory) & 0x3ffff000; 190 size_t size; 191 uint16_t tag; 192 int nsr, ndr, nfl; 193 194 /* Make three passes. 195 * First find which controller we are running under, cuz we cant touch it. 196 * Then remap every RAM segment around it. 197 * Then make sure FLASH segments do not overlap RAM. 198 */ 199 200 nsr = ndr = nfl = 0; 201 First = Ours = NULL; 202 base = ~0; 203 for (Pmt = ThePmt;;Pmt--) { 204 tag = Pmt->Tag; 205 //printf("PMT @%x tag=%x\n",Pmt,tag); 206 switch (tag) { 207 case PMTTAG_END_OF_TABLE: 208 goto DoneFirst; 209 case PMTTAG_SRAM: 210 case PMTTAG_DDRAM: 211 case PMTTAG_FLASH: 212 Ram = (ram_controller_t)(Pmt->TopOfPhysicalAddress << 16); 213 /* Scan the whole segment */ 214 for (;;) { 215 //printf("RAM @%x tag=%x ctl=%x\n", Ram, Ram->BaseAddressAndTag,Ram->Control); 216 if (tag != (Ram->BaseAddressAndTag & RAMBT_TAG)) 217 break; 218 addr = Ram->BaseAddressAndTag & RAMBT_BASE; 219 if ((tag != PMTTAG_FLASH) && (addr < base)) { 220 base = addr; 221 First = Ram; 222 } 223 size = Ram->Control & RAMST_SIZE; 224 if ((moi >= addr) && (moi < (addr + size))) { 225 Ours = Ram; 226 } 227 /* Next one.. and count them */ 228 Ram++; 229 switch (tag) { 230 case PMTTAG_SRAM: 231 nsr++; 232 break; 233 case PMTTAG_FLASH: 234 nfl++; 235 break; 236 case PMTTAG_DDRAM: 237 Ram++; /* yeach */ 238 ndr++; 239 break; 240 } 241 } 242 break; 243 default: 244 break; 245 } 246 } 247 248 /* Make sure we know */ 249 DoneFirst: 250 if ((First == NULL) || (Ours == NULL)) { 251 printf("Bad memory layout (%p, %p), wont work.\n", First, Ours); 252 return 0; 253 } 254 255 /* Second pass now */ 256 base += First->BaseAddressAndTag & RAMBT_BASE; 257 for (Pmt = ThePmt;;Pmt--) { 258 tag = Pmt->Tag; 259 //printf("PMT @%x tag=%x\n",Pmt,tag); 260 switch (tag) { 261 case PMTTAG_END_OF_TABLE: 262 goto DoneSecond; 263 case PMTTAG_SRAM: 264 case PMTTAG_DDRAM: 265 case PMTTAG_FLASH: 266 Ram = (ram_controller_t)(Pmt->TopOfPhysicalAddress << 16); 267 /* Scan the whole segment */ 268 for (;;) { 269 //printf("RAM @%x tag=%x ctl=%x\n", Ram, Ram->BaseAddressAndTag,Ram->Control); 270 if (tag != (Ram->BaseAddressAndTag & RAMBT_TAG)) 271 break; 272 /* Leave us alone */ 273 if (Ram == Ours) 274 goto Next; 275 /* Leave the first alone too */ 276 if (Ram == First) 277 goto Next; 278 /* We do FLASH next round */ 279 if (tag == PMTTAG_FLASH) 280 goto Next; 281 282 addr = Ram->BaseAddressAndTag & RAMBT_BASE; 283 size = Ram->Control & RAMST_SIZE; 284 285 /* Dont make it overlap with us */ 286 if ((moi >= base) && (moi < (base + size))) 287 base += Ours->Control & RAMST_SIZE; 288 289 if (addr != base) { 290 printf("remapping %x+%x to %x\n", addr, size, base); 291 Ram->BaseAddressAndTag = base; 292 } 293 base += size; 294 295 Next: 296 Ram++; 297 if (tag == PMTTAG_DDRAM) Ram++; /* yeach */ 298 } 299 break; 300 default: 301 break; 302 } 303 } 304 DoneSecond: 305 306 /* Third pass now: FLASH */ 307 for (Pmt = ThePmt;;Pmt--) { 308 tag = Pmt->Tag; 309 //printf("PMT @%x tag=%x\n",Pmt,tag); 310 switch (tag) { 311 case PMTTAG_END_OF_TABLE: 312 goto DoneThird; 313 case PMTTAG_FLASH: 314 Ram = (ram_controller_t)(Pmt->TopOfPhysicalAddress << 16); 315 /* Scan the whole segment */ 316 for (;;Ram++) { 317 //printf("RAM @%x tag=%x ctl=%x\n", Ram, Ram->BaseAddressAndTag,Ram->Control); 318 if (tag != (Ram->BaseAddressAndTag & RAMBT_TAG)) 319 break; 320 /* Leave us alone */ 321 if (Ram == Ours) 322 continue; 323 324 addr = Ram->BaseAddressAndTag & RAMBT_BASE; 325 size = Ram->Control & RAMST_SIZE; 326 327 /* No need to move if it does not overlap RAM */ 328 if (addr >= base) 329 continue; 330 331 /* Ahi */ 332 printf("remapping FLASH %x+%x to %x\n", addr, size, base); 333 Ram->BaseAddressAndTag = base; 334 base += size; 335 } 336 break; 337 default: 338 break; 339 } 340 } 341 DoneThird: 342 return (nfl<<16) | (nsr << 8) | (ndr << 0); 343 } 344 345 u_int startjump[2]; 346 u_int exceptioncode[(0x200-0x080)/4]; /* Change if ExceptionHandlerEnd changes */ 347 348 void save_locore(void) 349 { 350 memcpy(startjump,start,sizeof startjump); 351 memcpy(exceptioncode,ExceptionHandler,sizeof exceptioncode); 352 } 353 354 void restore_locore(void) 355 { 356 memcpy(start,startjump,sizeof startjump); 357 memcpy(ExceptionHandler,exceptioncode,sizeof exceptioncode); 358 /* BUGBUG flush icache */ 359 } 360 361 void call_kernel(uint32_t addr, char *kname, char *kargs, u_int bim, char *bip) 362 { 363 int argc = 0; 364 string_t argv[3]; 365 int code = PROM_MAGIC; 366 struct callback * cv = &cb; 367 368 /* Safeguard ourselves */ 369 save_locore(); 370 371 if (kargs == NULL) kargs = ""; 372 argv[0] = kname; 373 argv[1] = kargs; 374 argv[2] = NULL; 375 argc = 2; 376 377 TRACE(("Geronimo(%x,%s %s)!\n",addr,kname,kargs)); 378 ((void(*)(int,char**,int,struct callback *,u_int,char*))addr) 379 (argc,argv,code,cv,bim,bip); 380 } 381 382