// TITLE("Processor Idle Support") //++ // // Copyright (c) 1992 Digital Equipment Corporation // Copyright (c) 1993 Digital Equipment Corporation // // Module Name: // // idle.s // // Abstract: // // This module implements the HalProcessorIdle interface // // Author: // // John Vert (jvert) 11-May-1994 // // Environment: // // Revision History: // // Wim Colgate, 11-Nov-1995 // // Modified stub routine to idle the processor on LX3. // //-- #include "halalpha.h" #include "lx3.h" SBTTL("Processor Idle") //++ // // VOID // HalProcessorIdle( // VOID // ) // // Routine Description: // // This function is called when the current processor is idle with // interrupts disabled. There is no thread active and there are no // DPCs to process. Therefore, power can be switched to a standby // mode until the the next interrupt occurs on the current processor. // // N.B. This routine is entered with interrupts disabled. This routine // must do any power management enabling necessary, enable interrupts, // then either return or wait for an interrupt. // // Arguments: // // None. // // Return Value: // // None. // // Note: // // On LX3, the sequence of events should are: // // Write "idle" to processor // Flush Dcache // Enable Interrupts // // All of the above MUST be loaded into the Icache of the processor // once we write "idle" to the processor // // Once the processor is idle, we cannot get to the backup cache, // nor main memory. Once an interrupt occurs, the CPU reattaches via // hardware magic. // //-- LEAF_ENTRY(HalProcessorIdle) // // Enable, then disable interrups to force the PALcode // enable_interrupt routine into the Icache -- by executing it, // then back to interrupts disabled. // ENABLE_INTERRUPTS #ifdef IDLE_PROCESSOR // // set up temps here - instead of in critical Icache area // temps are a0-a5, t0-t7 // lda a0, HalpInterruptReceived bis zero, 1, t3 stl t3, 0(a0) // // set up t5 for superpage mode base address // ldiq t5, -0x4000 // 0xffff ffff ffff c000 sll t5, 28, t5 // 0xffff fc00 0000 0000 // // set t7 for interrupt register to poll on // ldah t7, 0x1b(zero) // 0x0000 0000 1b00 0000 sll t7, 4, t7 // 0x0000 0001 b000 0000 bis t5, t7, t7 // 0xffff fc01 b000 0000 // // set t6 for a 32K constant for Dcache flushing // ldil t6, 0x8000 // 0x0000 0000 0000 8000 // // set a1 to be the 'bouncing' bit // bis zero, 1, a1 mb DISABLE_INTERRUPTS // // Flush Dcache -- start at superpage address 0 and read 32K worth of // data // flush: ldl t1, 0(t5) // read data addl t5, 0x20, t5 // increment location by 8 longwords and t5, t6, t4 // check for 32K limit bne t4, setspin // loop finished br zero, flush // branch back bne a1, touch1 // bounce ahead to touch1 continue: // // clear a1 (aka the bouncing bit) so that we actually execite code // now. bis zero, zero, a1 // // Power down the processor to 'idle speed', which is not // completelty off. Duh. // ldil t0, CONFIG_REGISTER_SMALL // 0x0000 0000 0000 1001 sll t0, 20, t0 // 0x0000 0001 0010 0000 bis t0, t5, t0 // 0xffff fc01 0010 0000 ldil t2, CONFIG_SELECT_IDLE // load idle setting stl t2, 0(t0) // set processor to idle // // Past this point, all instructions MUST be in the Icache // // // Enable Interrupts // setspin: ENABLE_INTERRUPTS // // spin on the interrupt bit -- cleared by any interrupt routine // spin: ldl t0, 0(a0) // load bit bne t0, spin // spin on bit touch1: bne a1, continue // go all the way back #endif done: ret zero, (ra) .end HalProcessorIdle