Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * OpenSPARC T2 Processor File: interrupt_pci_INTx_all_threads.s | |
5 | * Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved | |
6 | * 4150 Network Circle, Santa Clara, California 95054, U.S.A. | |
7 | * | |
8 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
9 | * | |
10 | * This program is free software; you can redistribute it and/or modify | |
11 | * it under the terms of the GNU General Public License as published by | |
12 | * the Free Software Foundation; version 2 of the License. | |
13 | * | |
14 | * This program is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | * GNU General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU General Public License | |
20 | * along with this program; if not, write to the Free Software | |
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
22 | * | |
23 | * For the avoidance of doubt, and except that if any non-GPL license | |
24 | * choice is available it will apply instead, Sun elects to use only | |
25 | * the General Public License version 2 (GPLv2) at this time for any | |
26 | * software where a choice of GPL license versions is made | |
27 | * available with the language indicating that GPLv2 or any later version | |
28 | * may be used, or where a choice of which version of the GPL is applied is | |
29 | * otherwise unspecified. | |
30 | * | |
31 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
32 | * CA 95054 USA or visit www.sun.com if you need additional information or | |
33 | * have any questions. | |
34 | * | |
35 | * | |
36 | * ========== Copyright Header End ============================================ | |
37 | */ | |
38 | #define MAIN_PAGE_HV_ALSO | |
39 | #define ENABLE_PCIE_LINK_TRAINING | |
40 | ||
41 | #define H_HT0_Interrupt_0x60 | |
42 | #define My_HT0_Interrupt_0x60 \ | |
43 | call my_trap_code; \ | |
44 | nop; \ | |
45 | retry; \ | |
46 | nop; | |
47 | ||
48 | #include "hboot.s" | |
49 | #include "peu_defines.h" | |
50 | #include "ncu_defines.h" | |
51 | #include "cmp_macros.h" | |
52 | ||
53 | ||
54 | /************************************************************************ | |
55 | Test case code start | |
56 | ************************************************************************/ | |
57 | .text | |
58 | .global main | |
59 | ||
60 | main: | |
61 | ta T_CHANGE_HPRIV | |
62 | nop | |
63 | ||
64 | ! Initialize the global registers. | |
65 | mov %g0, %g1 | |
66 | mov %g0, %g2 | |
67 | mov %g0, %g3 | |
68 | mov %g0, %g4 | |
69 | mov %g0, %g5 | |
70 | mov %g0, %g6 | |
71 | mov %g0, %g7 | |
72 | ||
73 | ta T_RD_THID | |
74 | mov %o1, %g6 ! %o1, %g6 = thread ID | |
75 | set 8, %l7 | |
76 | umul %g6, %l7, %l7 | |
77 | setx user_data_start, %g1, %g3 | |
78 | add %l7, %g3, %g7 ! %g7 = pointer to thread's data area | |
79 | ||
80 | cmp %g6, 0x0 | |
81 | be main_t0 ! branch if tread 0 | |
82 | nop | |
83 | ba main_t1_to_t63 ! branch if not thread 0 | |
84 | nop | |
85 | ||
86 | ||
87 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
88 | ! | |
89 | ! Thread 0 Start Here | |
90 | ! | |
91 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
92 | ||
93 | main_t0: | |
94 | stx %g0, [%g7] ! Clear this thread's interrupt count | |
95 | membar #Sync | |
96 | ||
97 | /* Initialize the NCU for the interrupt. */ | |
98 | ||
99 | ! Disable interrupts | |
100 | ||
101 | no_intr: | |
102 | rdpr %pstate, %g7 | |
103 | xor %g7, 0x2, %g7 ! Reset interrupt enable | |
104 | wrpr %g7, %pstate | |
105 | ||
106 | ! Initially set all the Interrupt Management Registers | |
107 | ! Not used in this diag, so set vector number to 0, thread to 0. | |
108 | ncu_init: | |
109 | setx INT_MAN, %g1, %g2 ! %g2 = INT_MAN reg. addr. | |
110 | setx INT_MAN_COUNT, %g1, %g4 ! %g4 = INT_MAN reg. count value | |
111 | ||
112 | ncu_init_loop_top: | |
113 | stx %g0, [%g2] | |
114 | add %g2, INT_MAN_STEP, %g2 | |
115 | cmp %g4, 1 | |
116 | bne ncu_init_loop_top | |
117 | add %g4, -1, %g4 | |
118 | ||
119 | ! Initialize Mondo Interrupt Vector Register | |
120 | ! VECTOR = 63 | |
121 | ||
122 | ncu_mondo_int_vec: | |
123 | set 63, %g1 | |
124 | setx MONDO_INT_VEC, %g2, %g3 | |
125 | stx %g1, [%g3] | |
126 | ||
127 | ! Clear Mondo Interrupt Busy registers. | |
128 | ||
129 | ncu_mondo_int_busy: | |
130 | setx MONDO_INT_BUSY, %g1, %g2 | |
131 | setx MONDO_INT_BUSY_STEP, %g1, %g3 | |
132 | setx MONDO_INT_BUSY_COUNT, %g1, %g4 | |
133 | ||
134 | ncu_mondo_int_busy_loop_top: | |
135 | stx %g0, [%g2] | |
136 | add %g2, %g3, %g2 | |
137 | cmp %g4, 1 | |
138 | bne ncu_mondo_int_busy_loop_top | |
139 | dec %g4 | |
140 | ||
141 | ! Initialize for INTA interrupt in DMU/PEU | |
142 | ! First clear INTA in case one pending. | |
143 | ||
144 | peu_inta_clear: | |
145 | setx PCI_E_INT_A_CLEAR_ADDR, %g1, %g2 | |
146 | set 1, %g3 | |
147 | stx %g3, [%g2] | |
148 | ||
149 | ! Also clear in Interrupt Clear reg. | |
150 | ||
151 | peu_intr_clear: | |
152 | setx PCI_E_INT_CLEAR_ADDR, %g1, %g2 | |
153 | stx %g0, [%g2] | |
154 | ||
155 | ! Now enable INTA in DMU/PEU and set destination thread | |
156 | ||
157 | peu_inta_enable: | |
158 | setx PCI_E_INT_MAP_ADDR, %g1, %g7 | |
159 | setx 0x80000040, %g1, %g6 ! valid = 1, thread id = 0 | |
160 | #ifdef PORTABLE_CORE | |
161 | ldxa [%g0]ASI_INTR_ID, %o2 ! get full thread ID | |
162 | and %o2, 0x38, %o3 ! get thread 0 of this core | |
163 | sllx %o3, 25, %o3 | |
164 | or %g6, %o3, %g6 | |
165 | #endif | |
166 | stx %g6, [%g7] ! interrupt controller = 1 | |
167 | ||
168 | ! Enable interrupts | |
169 | ||
170 | yes_intr: | |
171 | rdpr %pstate, %g7 | |
172 | or %g7, 0x2, %g7 ! Set interrupt enable | |
173 | wrpr %g7, %pstate | |
174 | ||
175 | ||
176 | /* Sync up all the treads. */ | |
177 | ||
178 | #ifndef PORTABLE_CORE | |
179 | sync_t0: | |
180 | SYNC_THREAD_MAIN( local_test_failed, %g1, %g2, %g3 ) | |
181 | #else | |
182 | cmp_sync_threads | |
183 | #endif | |
184 | ||
185 | ||
186 | ! Kick off first interrupt, trap handler kicks off rest | |
187 | ||
188 | first_inta_intr: | |
189 | ! user event to generate ASSERT_INTA msg. | |
190 | nop ! $EV trig_pc_d(1, @VA(.MAIN.first_inta_intr)) -> EnablePCIeIgCmd ("INTA", 0, 0, "ASSERT", 64'd1, *, * ) | |
191 | ||
192 | /* Wait for interrupt to occur. */ | |
193 | ||
194 | intr_wait: | |
195 | #ifdef DTM_ENABLED | |
196 | setx 0x2000, %g1, %g2 ! DTM timeout count | |
197 | #else | |
198 | setx 0x800, %g1, %g2 ! timeout count | |
199 | #endif | |
200 | ta T_RD_THID ! %o1 = thread id | |
201 | set 8, %g7 | |
202 | umul %o1, %g7, %g7 | |
203 | setx user_data_start, %g1, %g3 | |
204 | add %g7, %g3, %g7 ! %g7 = pointer to thread's data area | |
205 | ||
206 | intr_wait_loop_top: | |
207 | ldx [%g7], %g5 | |
208 | cmp %g5, 1 | |
209 | be t0_new_intr | |
210 | dec %g2 | |
211 | ||
212 | cmp %g2, 0 | |
213 | bne intr_wait_loop_top | |
214 | nop | |
215 | ba local_test_failed | |
216 | nop | |
217 | ||
218 | ! Kick off next INTA interrupt | |
219 | ||
220 | t0_new_intr: | |
221 | ! user event for ASSERT_INTA msg. | |
222 | nop ! $EV trig_pc_d(1, @VA(.MAIN.t0_new_intr)) -> EnablePCIeIgCmd ("INTA", 0, 0, "ASSERT", 64'd1, *, * ) | |
223 | ||
224 | ba test_passed | |
225 | nop | |
226 | ||
227 | ||
228 | ||
229 | ||
230 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
231 | ! | |
232 | ! All Threads Except 0 Start Here | |
233 | ! | |
234 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
235 | ||
236 | ||
237 | main_t1_to_t63: | |
238 | stx %g0, [%g7] ! Clear this thread's interrupt count | |
239 | membar #Sync | |
240 | ||
241 | #ifndef PORTABLE_CORE | |
242 | SYNC_THREAD_OTHER( %g6,%g1,%g2 ) | |
243 | #else | |
244 | cmp_sync_threads | |
245 | #endif | |
246 | ||
247 | /* Wait for interrupt to occur. */ | |
248 | ||
249 | t1_t63_intr_wait: | |
250 | #ifdef DTM_ENABLED | |
251 | setx 0x10000, %g1, %g2 ! DTM timeout count | |
252 | #else | |
253 | setx 0x4000, %g1, %g2 ! timeout count | |
254 | #endif | |
255 | ta T_RD_THID ! %o1 = thread id | |
256 | set 8, %g7 | |
257 | umul %o1, %g7, %g7 | |
258 | setx user_data_start, %g1, %g3 | |
259 | add %g7, %g3, %g7 ! %g7 = pointer to thread's data area | |
260 | ||
261 | t1_t63_intr_wait_loop_top: | |
262 | ldx [%g7], %g5 | |
263 | cmp %g5, 1 | |
264 | be t1_t63_last | |
265 | dec %g2 | |
266 | ||
267 | cmp %g2, 0 | |
268 | bne t1_t63_intr_wait_loop_top | |
269 | nop | |
270 | ba local_test_failed | |
271 | nop | |
272 | ||
273 | ! Kick off next INTA interrupt, if not in last thread | |
274 | ||
275 | t1_t63_last: | |
276 | ta T_RD_THID | |
277 | #ifndef PORTABLE_CORE | |
278 | cmp %o1, 63 | |
279 | #else | |
280 | ldxa [%g0]ASI_INTR_ID, %o2 ! get full thread ID | |
281 | and %o2, 0x7, %o3 | |
282 | cmp %o3, 7 | |
283 | #endif | |
284 | be test_passed | |
285 | nop | |
286 | ||
287 | t1_t63_new_intr: | |
288 | ! user event for ASSERT_INTA msg. | |
289 | nop ! $EV trig_pc_d(1, @VA(.MAIN.t1_t63_new_intr)) -> EnablePCIeIgCmd ("INTA", 0, 0, "ASSERT", 64'd1, *, * ) | |
290 | ||
291 | ba test_passed | |
292 | nop | |
293 | ||
294 | ||
295 | test_passed: | |
296 | EXIT_GOOD | |
297 | ||
298 | local_test_failed: | |
299 | EXIT_BAD | |
300 | ||
301 | ||
302 | /********************************************************************** | |
303 | Interrupt trap handler. | |
304 | **********************************************************************/ | |
305 | ||
306 | .global my_trap_code | |
307 | ||
308 | my_trap_code: | |
309 | ||
310 | ! Get the thread id. | |
311 | ta T_RD_THID ! %o1 = thread id | |
312 | ldxa [%g0]ASI_INTR_ID, %o2 ! get full thread ID | |
313 | set 8, %l7 | |
314 | umul %o1, %l7, %l7 | |
315 | setx user_data_start, %l1, %l3 | |
316 | add %l7, %l3, %l7 ! %l7 = pointer to thread's data area | |
317 | ||
318 | ! Has interrupt to this thread already occured? | |
319 | ||
320 | trap_mult_intr: | |
321 | ldx [%l7], %l1 | |
322 | cmp %l1, 0 | |
323 | bne local_test_failed | |
324 | nop | |
325 | ||
326 | ! Record interrupt occured for this thread. | |
327 | ||
328 | trap_intr_flag: | |
329 | set 1, %l1 | |
330 | stx %l1, [%l7] | |
331 | ||
332 | ! Check Mondo Interrupt Busy reg. for this thread | |
333 | ||
334 | trap_mondo_busy: | |
335 | setx MONDO_INT_BUSY, %l1, %l2 | |
336 | setx MONDO_INT_BUSY_STEP, %l1, %l3 | |
337 | mulx %l3, %o2, %l3 | |
338 | add %l3, %l2, %l2 | |
339 | ldx [%l2], %l4 | |
340 | and %l4, 0x40, %l5 ! Is busy bit set? | |
341 | cmp %l5, 0 | |
342 | be local_test_failed | |
343 | nop | |
344 | ||
345 | ! Check Mondo Interrupt Alias Busy reg. | |
346 | ||
347 | trap_mondo_abusy: | |
348 | setx MONDO_INT_ABUSY, %l1, %l2 | |
349 | ldx [%l2], %l3 | |
350 | cmp %l3, %l4 ! ABUSY = BUSY ? | |
351 | bne local_test_failed | |
352 | nop | |
353 | ||
354 | ! Check Mondo Interrupt Data 0/1 against Mondo Interrupt Alias Data 0/1 | |
355 | ||
356 | trap_mondo_data0: | |
357 | setx MONDO_INT_DATA0, %l1, %l2 | |
358 | setx MONDO_INT_DATA0_STEP, %l1, %l3 | |
359 | mulx %l3, %o2, %l3 | |
360 | add %l3, %l2, %l2 | |
361 | ldx [%l2], %l0 ! %l0 = mondo_int_busy0 | |
362 | ||
363 | trap_mondo_adata0: | |
364 | setx MONDO_INT_ADATA0, %l1, %l4 ! %l5 = mondo_int_abusy0 | |
365 | ldx [%l4], %l5 | |
366 | cmp %l5, %l0 | |
367 | bne local_test_failed | |
368 | nop | |
369 | ||
370 | trap_mondo_data1: | |
371 | setx MONDO_INT_DATA1, %l1, %l2 | |
372 | setx MONDO_INT_DATA1_STEP, %l1, %l3 | |
373 | mulx %l3, %o2, %l3 | |
374 | add %l3, %l2, %l2 | |
375 | ldx [%l2], %l0 ! %l0 = mondo_int_busy1 | |
376 | ||
377 | trap_mondo_adata1: | |
378 | setx MONDO_INT_ADATA1, %l1, %l4 ! %l5 = mondo_int_abusy1 | |
379 | ldx [%l4], %l5 | |
380 | cmp %l5, %l0 | |
381 | bne local_test_failed | |
382 | nop | |
383 | ||
384 | ! Check INTA status in DMU/PEU | |
385 | ||
386 | ! Interrupt Clear reg. | |
387 | ||
388 | trap_peu_intr_clear: | |
389 | setx PCI_E_INT_CLEAR_ADDR, %l1, %l2 | |
390 | ldx [%l2], %l0 | |
391 | cmp %l0, 3 ! Should be in pending state | |
392 | bne local_test_failed | |
393 | nop | |
394 | ||
395 | trap_peu_inta_status: | |
396 | setx PCI_E_INTX_STATUS_ADDR, %l1, %l2 | |
397 | ldx [%l2], %l0 | |
398 | cmp %l0, 8 ! INTA should be only one active | |
399 | bne local_test_failed | |
400 | nop | |
401 | ||
402 | trap_peu_inta_clear: | |
403 | setx PCI_E_INT_A_CLEAR_ADDR, %l1, %l2 | |
404 | ldx [%l2], %l0 | |
405 | cmp %l0, 1 ! INTA should be active | |
406 | bne local_test_failed | |
407 | nop | |
408 | ||
409 | ! Clear the INTA interrupt in the DMU/PEU | |
410 | ||
411 | trap_inta_clear: | |
412 | ! user event for INTA deassert msg. | |
413 | nop ! $EV trig_pc_d(1, @VA(.MAIN.trap_inta_clear)) -> EnablePCIeIgCmd ("INTA", 0, 0, "DEASSERT", 64'd1, *, * ) | |
414 | ||
415 | ! Check the INTA status in INTA Clear reg. | |
416 | ||
417 | #ifdef DTM_ENABLED | |
418 | setx 0x400, %l0, %l1 ! DTM Timeout count | |
419 | #else | |
420 | setx 0x100, %l0, %l1 ! Timeout count | |
421 | #endif | |
422 | setx PCI_E_INT_A_CLEAR_ADDR, %l0, %l2 | |
423 | ||
424 | trap_inta_clear_loop_top: | |
425 | ldx [%l2], %l0 | |
426 | cmp %l0, 0 ! Waiting for idle state | |
427 | be trap_inta_clear_done | |
428 | nop | |
429 | cmp %l1, 1 | |
430 | be local_test_failed ! Timeout check | |
431 | dec %l1 | |
432 | ba trap_inta_clear_loop_top | |
433 | nop | |
434 | ||
435 | ! Check other DMU/PEU INTA registers | |
436 | ||
437 | trap_inta_clear_done: | |
438 | setx PCI_E_INTX_STATUS_ADDR, %l1, %l2 | |
439 | ldx [%l2], %l0 | |
440 | cmp %l0, 0 ! All should be inactive | |
441 | bne local_test_failed | |
442 | nop | |
443 | ||
444 | ! Interrupt Clear reg. | |
445 | ||
446 | trap_intr_clear: | |
447 | setx PCI_E_INT_CLEAR_ADDR, %g1, %g2 | |
448 | stx %g0, [%g2] | |
449 | ||
450 | ! Clear the mondo interrupt in the NCU | |
451 | ||
452 | trap_mondo_intr_clear: | |
453 | setx MONDO_INT_ABUSY, %l0, %l1 | |
454 | stx %g0, [%l1] | |
455 | membar #Sync | |
456 | ||
457 | ldx [%l1], %l2 | |
458 | and %l2, 0x40, %l2 | |
459 | cmp %l2, 0 ! Busy should be cleared | |
460 | bne local_test_failed | |
461 | nop | |
462 | ||
463 | ! Clear the interrupt in the core | |
464 | ||
465 | trap_asi_intr_r_clear: | |
466 | ldxa [%g0]ASI_SWVR_INTR_R, %l5 | |
467 | cmp %l5, 63 ! check for correct vector number | |
468 | bne local_test_failed | |
469 | nop | |
470 | ||
471 | ! Increment the thread to send next interrupt to. | |
472 | ||
473 | trap_inc_thread: | |
474 | setx PCI_E_INT_MAP_ADDR, %l0, %l7 | |
475 | setx 0x2000000, %l0, %l5 | |
476 | ldx [%l7], %l6 | |
477 | addx %l6, %l5, %l6 | |
478 | stx %l6, [%l7] | |
479 | membar #Sync | |
480 | ||
481 | ! Done. | |
482 | ||
483 | trap_done: | |
484 | jmpl %o7+0x8, %g0 | |
485 | nop | |
486 | ||
487 | ||
488 | ||
489 | /************************************************************************ | |
490 | Test case data start | |
491 | ************************************************************************/ | |
492 | ||
493 | .align 1024 | |
494 | .data | |
495 | user_data_start: | |
496 | .word 0xffffffff | |
497 | .word 0xffffffff | |
498 | .word 0xffffffff | |
499 | .word 0xffffffff | |
500 | user_data_end: | |
501 | .end | |
502 | ||
503 | /************************************************************************/ |