in mac/misc.c [452:531]
void mac_reset(void)
{
if (macintosh_config->adb_type == MAC_ADB_II &&
macintosh_config->ident != MAC_MODEL_SE30) {
/* need ROMBASE in booter */
/* indeed, plus need to MAP THE ROM !! */
if (mac_bi_data.rombase == 0)
mac_bi_data.rombase = 0x40800000;
/* works on some */
rom_reset = (void *) (mac_bi_data.rombase + 0xa);
local_irq_disable();
rom_reset();
#ifdef CONFIG_ADB_CUDA
} else if (macintosh_config->adb_type == MAC_ADB_EGRET ||
macintosh_config->adb_type == MAC_ADB_CUDA) {
cuda_restart();
#endif
#ifdef CONFIG_ADB_PMU
} else if (macintosh_config->adb_type == MAC_ADB_PB2) {
pmu_restart();
#endif
} else if (CPU_IS_030) {
/* 030-specific reset routine. The idea is general, but the
* specific registers to reset are '030-specific. Until I
* have a non-030 machine, I can't test anything else.
* -- C. Scott Ananian <cananian@alumni.princeton.edu>
*/
unsigned long rombase = 0x40000000;
/* make a 1-to-1 mapping, using the transparent tran. reg. */
unsigned long virt = (unsigned long) mac_reset;
unsigned long phys = virt_to_phys(mac_reset);
unsigned long addr = (phys&0xFF000000)|0x8777;
unsigned long offset = phys-virt;
local_irq_disable(); /* lets not screw this up, ok? */
__asm__ __volatile__(".chip 68030\n\t"
"pmove %0,%/tt0\n\t"
".chip 68k"
: : "m" (addr));
/* Now jump to physical address so we can disable MMU */
__asm__ __volatile__(
".chip 68030\n\t"
"lea %/pc@(1f),%/a0\n\t"
"addl %0,%/a0\n\t"/* fixup target address and stack ptr */
"addl %0,%/sp\n\t"
"pflusha\n\t"
"jmp %/a0@\n\t" /* jump into physical memory */
"0:.long 0\n\t" /* a constant zero. */
/* OK. Now reset everything and jump to reset vector. */
"1:\n\t"
"lea %/pc@(0b),%/a0\n\t"
"pmove %/a0@, %/tc\n\t" /* disable mmu */
"pmove %/a0@, %/tt0\n\t" /* disable tt0 */
"pmove %/a0@, %/tt1\n\t" /* disable tt1 */
"movel #0, %/a0\n\t"
"movec %/a0, %/vbr\n\t" /* clear vector base register */
"movec %/a0, %/cacr\n\t" /* disable caches */
"movel #0x0808,%/a0\n\t"
"movec %/a0, %/cacr\n\t" /* flush i&d caches */
"movew #0x2700,%/sr\n\t" /* set up status register */
"movel %1@(0x0),%/a0\n\t"/* load interrupt stack pointer */
"movec %/a0, %/isp\n\t"
"movel %1@(0x4),%/a0\n\t" /* load reset vector */
"reset\n\t" /* reset external devices */
"jmp %/a0@\n\t" /* jump to the reset vector */
".chip 68k"
: : "r" (offset), "a" (rombase) : "a0");
}
/* should never get here */
pr_crit("Restart failed. Please restart manually.\n");
local_irq_disable();
while(1);
}