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
|