summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/hallx3/alpha/idle.s
blob: 22dc3c2eef41fe49eaf5f0fe85479d8f6d2d9f43 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
//      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