1 " ***********************************************************
2 " * *
3 " * Copyright, C Honeywell Bull Inc., 1987 *
4 " * *
5 " * Copyright, C Honeywell Information Systems Inc., 1982 *
6 " * *
7 " * Copyright c 1972 by Massachusetts Institute of *
8 " * Technology and Honeywell Information Systems, Inc. *
9 " * *
10 " ***********************************************************
11
12 " iom_interrupt: IOM interrupt handler
13 " Stolen from iom_manager and ii November 1980 by C. Hornig
14 " Added loop protocol for IOM switch checking, January 1985 by M. Pandolf
15 " see iom_connect$connect_and_identify for the other half of the protocol
16
17 name iom_interrupt
18
19 segdef interrupt_entry " interrupt vector transfers here
20 segdef iilink " ITS ptr to linkage section
21 segdef prds_prs " ITS ptr to space for spri
22 segdef prds_scu " ITS ptr to space for SCU
23
24 tempd hlr_arglist4 " argument list for interrupt handler
25 tempd time " time handler called
26 tempd imw_save " current IMW for scan
27 temp int_level " interrupt level for handler 1 3 5 7
28 temp index " index for this channel
29 temp chantab_base " offset in chantab for this IOM
30 temp device " offset in per_device for this channel
31 temp chx " channel index from chantab
32 temp int_count " handlers called this time around
33
34 " Index register conventions:
35
36 " X0 - internal subroutine calls.
37 " X1 - index into devtab.
38 " X2 - index into mailbox.
39 " X3 - Used to index iomd.per_iom.
40 " X4 - interrupt cell #.
41 " X5 - interrupt level #.
42 " X6 - index in status queue
43
44 " Pointer Register Conventions:
45
46 " AP -> machine conditions
47 " AB -> inetrnal calls
48 " BP -> <iom_data>|0
49 " BB -> mailbox for this IOM.
50 " LP -> linkage section
51 " LB -> status queue
52
53
54 " These are initialized by initialize_faults
55
56 even
57 iilink: its -1,1 " our LP
58 prds_prs: its -1,1 " where to store PRs
59 prds_scu: its -1,1 " and CU info
60
61 three_args_nd:
62 zero 6,4
63 zero: zero 0
64
65 push_value:
66 push
67
68 chanpos: " table of chantab offsets
69 zero 0,0*4*per_iom_size+32
70 zero 0,1*4*per_iom_size+32
71 zero 0,2*4*per_iom_size+32
72 zero 0,3*4*per_iom_size+32
73 zero 0,0*4*per_iom_size
74 zero 0,1*4*per_iom_size
75 zero 0,2*4*per_iom_size
76 zero 0,3*4*per_iom_size
77 " ^L
78 " This entry is transferred to by the interrupt vector.
79 " It is responsible for calling the interrupt handlers of various DIM's
80 " for which interrupts have been stored in the IMW array.
81 " It calls the interrupt routine as follows:
82 " call int_proc idx int_level data_word
83 " where int_level 1 3 5 7 corresponds to the level passed by the channel
84 " to the IOM and data_word in the system fault or special status word.
85
86 inhibit on <+><+><+><+><+><+><+><+><+><+><+><+><+>
87
88 interrupt_entry:
89 spri prds_prs-*,ic* " save pointer registers
90 eppbp prds_prs-*,ic* " ab -> machine conditions
91 sreg bp|mc.regs " save registers
92 lxl7 bp|mc.scu.indicators_word
93 canx7 scu.ir.mif,du " check for EIS
94 tze 2,ic " so we can save
95 spl bp|mc.eis_info " the pointers and lengths
96
97 epplp iilink-*,ic* " set up LP
98
99 tsx0 fim_util$v_time_init " meter virtual time
100
101 tsx0 fim_util$check_interrupt " make sure we're not not prds
102
103 tsx0 fim_util$check_mct " go save M.C.s and hregs
104 " if trace is on
105 nop " return ic +1
106
107 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
108 "
109 " Establish a stack frame and mask interrupts.
110 "
111 epbpsb prds$ " use prds
112 ldx7 push_value-*,ic " get size of stack frame
113 tsx0 fim_util$push_stack " push the frame
114
115 tsx0 fim_util$set_mask " mask to sys level
116
117 inhibit off <-><-><-><-><-><-><-><-><-><-><-><->
118
119 tsx0 fim_util$reset_mode_reg
120 " turn on hist regs and cache
121 ldq bp|mc.scu.fault_data_word
122 anq scu.fi_num_mask,dl " get the interrupt number
123 qrl scu.fi_num_shift
124 eax4 0,ql " interrupt cell in X4
125 " ^L
126 anq =7,dl " get base channel table position
127 lda chanpos,ql
128 sta chantab_base " save it for later
129
130 eaa 0,x4 " get interrupt cell
131 arl 18+2 " interrupt level in AL
132 ora =1,dl " always odd
133 sta int_level " save for handler
134
135 ldaq three_args_nd-*,ic " Build argument list for handler
136 staq hlr_arglist " call handler index int_level ""b
137 epplb index
138 sprilb hlr_arglist+2
139 epplb int_level
140 sprilb hlr_arglist+4
141 epplb zero-*,ic
142 sprilb hlr_arglist+6
143 "
144 " set up to search IMW area
145 "
146 eppbp iom_data$
147 stz int_count " no interrupts yet
148
149 "
150 " wait until any IOM switch checking is completed
151 "
152
153 imw_wait:
154 odd
155 ldac bp|iom_data.imw_lock
156 tze -1,ic " loop while lock in transition
157 tpl imw_read
158 sta bp|iom_data.imw_lock" restore -1 into lock
159 tra imw_wait " and continue looping
160
161 imw_read:
162 aos bp|iom_data.n_intr_procs " bump number of cpus handling interrupts
163 aos bp|iom_data.imw_lock " was 0 from ldac, now is 1
164
165 ldac iom_mailbox$+iom_mailbox_seg.imw_array_word,x4
166 tze null_int-*,ic " no IMW bit set
167
168 ldq 0,du " make a fake float number
169 lde 0,du
170 lrl 1
171 tra imw_begin-*,ic " start scanning
172
173 " Scan the IMW for any bits on and process these interrupts.
174
175 imw_retry:
176 dfld imw_save " get back remaining bits
177 tze interrupt_return " no bits left
178
179 imw_begin:
180 ldi 0,dl " clear hex and overflow bits
181 fno
182 era =o200000,du " clear the bit
183 dfst imw_save
184
185 lda imw_save " get channel number
186 ars 36-8 " in AL
187 neg 0
188 ada chantab_base " add chantab offset
189 sta index " store in case of error
190
191 mrl pral,pr,fill0 " Reference the channel table.
192 desc9a bp|iom_data.per_iom+per_iom.chantab_word,1
193 desc9a chx,4 " Word will be leading zero padded.
194
195 eppap hlr_arglist
196
197 ldq chx " chx in QL
198 tze invalid_int-*,ic " Ignore interrupt if channel not assigned.
199 mpy per_device_size,dl
200 eax1 -per_device_size,ql " index into per_device
201
202 lda bp|iom_data.per_device+per_device.flags,x1
203 " is there a handler?
204 cana per_device.in_use,du
205 tze invalid_int-*,ic " Return if no handler assigned.
206
207 lda bp|iom_data.per_device+per_device.index,x1
208 sta index " save the handler's index
209 stx1 device " save per_device index for ext. call
210
211 rccl sys_info$clock_,* " Get int_time now.
212 staq time " And save it.
213
214 short_call bp|iom_data.per_device+per_device.handler,x1*
215 " Call handler.
216
217 rccl sys_info$clock_,* " Get int_time again.
218 sbaq time " Compute delta.
219
220 eppbp iom_data$ " re-establish addressability
221 ldx1 device " restore per_device offset
222 adaq bp|iom_data.per_device+per_device.interrupt_time,x1
223 staq bp|iom_data.per_device+per_device.interrupt_time,x1
224 ldaq bp|iom_data.per_device+per_device.interrupts,x1
225 adl =1,dl " update meters
226 staq bp|iom_data.per_device+per_device.interrupts,x1
227 aos int_count " count interrupts
228
229 tra imw_retry-*,ic " find more interrupts
230
231
232 invalid_int:
233 aos bp|iom_data.invalid_interrupts
234 " meter unexpected interrupts
235 short_call iom_error$invalid_interrupt
236 " and tell the world
237 eppbp iom_data$ " re-establish addressability
238 tra imw_retry-*,ic " find more channels
239 " ^L
240 null_int: " meter interrupts with null IMW
241 aos bp|iom_data.null_interrupts
242
243 interrupt_return:
244 lda int_count " meter multiple interrupts
245 cmpa =1,dl
246 tmoz 2,ic
247 aos bp|iom_data.multiple_interrupts
248
249 ldaq tc_data$interrupt_count
250 adl 1,dl " count interrupts
251 staq tc_data$interrupt_count
252
253 odd
254 ldac bp|iom_data.imw_lock
255 tze -1,ic " loop while lock in transition
256
257 lcq 1,dl " decrement count of cpus in interrupt handler
258 asq bp|iom_data.n_intr_procs
259
260 sta bp|iom_data.imw_lock
261
262 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
263 "
264 " Relinquish stack frame and open interrupt mask.
265 "
266 eppbp prds_prs-*,ic* " restore MC ptr
267
268 tsx0 fim_util$restore_mask
269 inhibit on <+><+><+><+><+><+><+><+><+><+><+><+>
270
271 epbpsb sp|0 get ptr to base of stack
272 sprisp sb|stack_header.stack_end_ptr pop our stack frame
273
274 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
275 "
276 " Perform interrupt metering and exit.
277 "
278 ldaq bp|mc.fault_time " get fault time
279 ana =o777777,dl " clear CPU type
280 staq prds$iitemp " save for now
281 rccl sys_info$clock_,* " read the clock
282 sbaq prds$iitemp " compute real time spent
283 adaq tc_data$interrupt_time " add in to total
284 staq tc_data$interrupt_time " ..
285
286 odd
287 tsx0 fim_util$v_time_calc " compute virtual time
288
289 lxl1 bp|mc.scu.indicators_word
290 canx1 scu.ir.mif,du " check for EIS if not don't reload pl
291 tze 2,ic
292 lpl bp|mc.eis_info restore pointers and lengths
293 lreg bp|mc.regs and registers
294 lpri prds_prs-*,ic* restore prs
295 rcu prds_scu-*,ic* and dismiss the interrupt
296 " ^L
297 include iom_data
298 include mc
299 include stack_header
300
301 end