Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / hypervisor / src / greatlakes / ontario / src / vpci_fire.s
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* Hypervisor Software File: vpci_fire.s
5*
6* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
7*
8* - Do no alter or remove copyright notices
9*
10* - Redistribution and use of this software in source and binary forms, with
11* or without modification, are permitted provided that the following
12* conditions are met:
13*
14* - Redistribution of source code must retain the above copyright notice,
15* this list of conditions and the following disclaimer.
16*
17* - Redistribution in binary form must reproduce the above copyright notice,
18* this list of conditions and the following disclaimer in the
19* documentation and/or other materials provided with the distribution.
20*
21* Neither the name of Sun Microsystems, Inc. or the names of contributors
22* may be used to endorse or promote products derived from this software
23* without specific prior written permission.
24*
25* This software is provided "AS IS," without a warranty of any kind.
26* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
27* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
28* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
29* MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
30* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
31* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
32* OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
33* FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
34* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
35* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
36* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
37*
38* You acknowledge that this software is not designed, licensed or
39* intended for use in the design, construction, operation or maintenance of
40* any nuclear facility.
41*
42* ========== Copyright Header End ============================================
43*/
44/*
45 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
46 * Use is subject to license terms.
47 */
48
49 .ident "@(#)vpci_fire.s 1.51 07/07/17 SMI"
50
51#include <sys/asm_linkage.h>
52#include <sys/htypes.h>
53#include <hypervisor.h>
54#include <sparcv9/asi.h>
55#include <sun4v/asi.h>
56#include <asi.h>
57#include <mmu.h>
58
59#include <guest.h>
60#include <strand.h>
61#include <offsets.h>
62#include <debug.h>
63#include <util.h>
64#include <abort.h>
65#include <fire.h>
66#include <vdev_intr.h>
67#include <vpci_errs.h>
68#include <ldc.h>
69
70#if defined(CONFIG_FIRE)
71
72#define REGNO2OFFSET(no, off) sllx no, 3, off
73#define PCIDEV2FIREDEV(pci, fire) sllx pci, 4, fire
74
75/*
76 * CHK_FIRE_LINK_STATUS - Check status of Fire link. Returns status
77 * of 0 if the link is down.
78 *
79 * Delay Slot: not safe in a delay slot
80 */
81#define CHK_FIRE_LINK_STATUS(firecookie, status, scr1) \
82 ldx [firecookie + FIRE_COOKIE_PCIE], status ;\
83 set FIRE_PLC_TLU_CTB_TLR_TLU_STS, scr1 ;\
84 ldx [status + scr1], scr1 ;\
85 and scr1, FIRE_TLU_STS_STATUS_MASK, scr1 ;\
86 cmp scr1, FIRE_TLU_STS_STATUS_DATA_LINK_ACTIVE ;\
87 movne %xcc, 0, status
88
89#if FIRE_MSIEQ_SIZE != 0x28
90#error "FIRE_MSIEQ_SIZE changed, breaks the shifts below"
91#endif
92#define MSIEQNUM2MSIEQ(firecookie, num, msieq, scr1, scr2) \
93 ldx [firecookie + FIRE_COOKIE_MSICOOKIE], msieq ;\
94 sllx num, 5, scr1 ;\
95 sllx num, 3, scr2 ;\
96 add scr1, scr2, scr1 ;\
97 inc FIRE_MSI_COOKIE_EQ, scr1 ;\
98 add msieq, scr1, msieq
99
100
101 ! Ordered to minimize wasted space
102 BSS_GLOBAL(fire_a_equeue, (FIRE_NEQS * FIRE_EQSIZE), 512 KB)
103 BSS_GLOBAL(fire_a_iotsb, IOTSB_SIZE, 8 KB)
104 BSS_GLOBAL(fire_b_equeue, (FIRE_NEQS * FIRE_EQSIZE), 512 KB)
105 BSS_GLOBAL(fire_b_iotsb, IOTSB_SIZE, 8 KB)
106 BSS_GLOBAL(fire_virtual_intmap, 0x10, 0x10)
107
108 DATA_GLOBAL(fire_jbus_init_table)
109#ifdef CONFIG_FIRE_EBUS
110 .xword FIRE_SIZE(EBUS_SIZE), FIRE_EBUS_OFFSET_MASK
111 .xword FIRE_BAR_V(EBUS), FIRE_EBUS_OFFSET_BASE
112#else
113 .xword FIRE_BAR(EBUS), FIRE_EBUS_OFFSET_BASE
114#endif
115 .xword FIRE_BAR(CFGIO(A)), FIRE_PCIE_A_IOCON_OFFSET_BASE
116 .xword FIRE_BAR(MEM32(A)), FIRE_PCIE_A_MEM32_OFFSET_BASE
117 .xword FIRE_BAR(MEM64(A)), FIRE_PCIE_A_MEM64_OFFSET_BASE
118 .xword FIRE_BAR(MEM32(B)), FIRE_PCIE_B_MEM32_OFFSET_BASE
119 .xword FIRE_BAR(CFGIO(B)), FIRE_PCIE_B_IOCON_OFFSET_BASE
120 .xword FIRE_BAR(MEM64(B)), FIRE_PCIE_B_MEM64_OFFSET_BASE
121
122 .xword FIRE_SIZE(MEM32_SIZE), FIRE_PCIE_A_MEM32_OFFSET_MASK
123 .xword FIRE_BAR_V(MEM32(A)), FIRE_PCIE_A_MEM32_OFFSET_BASE
124
125 .xword FIRE_SIZE(CFGIO_SIZE), FIRE_PCIE_A_IOCON_OFFSET_MASK
126 .xword FIRE_BAR_V(CFGIO(A)), FIRE_PCIE_A_IOCON_OFFSET_BASE
127
128 .xword FIRE_SIZE(MEM64_SIZE), FIRE_PCIE_A_MEM64_OFFSET_MASK
129 .xword FIRE_BAR_V(MEM64(A)), FIRE_PCIE_A_MEM64_OFFSET_BASE
130
131 .xword FIRE_SIZE(MEM32_SIZE), FIRE_PCIE_B_MEM32_OFFSET_MASK
132 .xword FIRE_BAR_V(MEM32(B)), FIRE_PCIE_B_MEM32_OFFSET_BASE
133
134 .xword FIRE_SIZE(CFGIO_SIZE), FIRE_PCIE_B_IOCON_OFFSET_MASK
135 .xword FIRE_BAR_V(CFGIO(B)), FIRE_PCIE_B_IOCON_OFFSET_BASE
136
137 .xword FIRE_SIZE(MEM64_SIZE), FIRE_PCIE_B_MEM64_OFFSET_MASK
138 .xword FIRE_BAR_V(MEM64(B)), FIRE_PCIE_B_MEM64_OFFSET_BASE
139
140 /* From Solaris Driver */
141 .xword 0x8000000000000000, FIRE_JBUS_PAR_CTL
142 .xword 0x000000000600c047, FIRE_JBC_FATAL_RESET_ENABLE_REG
143 .xword 0xffffffffffffffff, FIRE_JBC_LOGGED_ERROR_STATUS_REG_RW1C_ALIAS
144 .xword 0xffffffffffffffff, FIRE_JBC_INTERRUPT_MASK_REG
145 .xword 0xffffffffffffffff, FIRE_JBC_ERROR_LOG_EN_REG
146 .xword 0xffffffffffffffff, FIRE_JBC_ERROR_INT_EN_REG
147 ! XXX
148 .xword 0xfffc000000000000, FIRE_DLC_IMU_ICS_MEM_64_PCIE_OFFSET_REG
149 .xword 0x000007f513cb7000, FIRE_FIRE_CONTROL_STATUS
150 .xword -1,-1 /* End of Table */
151 SET_SIZE(fire_jbus_init_table)
152
153 DATA_GLOBAL(fire_leaf_init_table)
154 .xword 0xffffffffffffffff, FIRE_DLC_IMU_ICS_IMU_ERROR_LOG_EN_REG
155 .xword 0xffffffffffffffff, FIRE_DLC_IMU_ICS_IMU_INT_EN_REG
156 .xword 0xffffffffffffffff, FIRE_DLC_IMU_ICS_IMU_LOGGED_ERROR_STATUS_REG_RW1C_ALIAS
157 .xword 0x0000000000000010, FIRE_DLC_ILU_CIB_ILU_LOG_EN
158 .xword 0x0000001000000010, FIRE_DLC_ILU_CIB_ILU_INT_EN
159 /*
160 * Changes to the CTO field of FIRE_PLC_TLU_CTB_TLR_TLU_CTL
161 * need to be reflected in the Niagara JBI_TRANS_TIMEOUT
162 * register. See the setup_jbi routine in setup.s.
163 */
164#ifdef FIRE_ERRATUM_20_18
165 /*
166 * Also, see below where NPRW_EN is masked off for Fire 2.0 but
167 * is set here for Fire 2.1 and later.
168 */
169#endif
170 .xword 0x00000000da130001, FIRE_PLC_TLU_CTB_TLR_TLU_CTL
171 .xword 0xffffffffffffffff, FIRE_PLC_TLU_CTB_TLR_OE_LOG
172 .xword 0xffffffffffffffff, FIRE_PLC_TLU_CTB_TLR_OE_ERR_RW1C_ALIAS
173 .xword 0xffffffffffffffff, FIRE_PLC_TLU_CTB_TLR_OE_INT_EN
174 .xword 0x0000000000000000, FIRE_PLC_TLU_CTB_TLR_DEV_CTL
175 .xword 0x0000000000000040, FIRE_PLC_TLU_CTB_TLR_LNK_CTL
176 .xword 0xffffffffffffffff, FIRE_PLC_TLU_CTB_TLR_UE_LOG
177 .xword 0xffffffffffffffff, FIRE_PLC_TLU_CTB_TLR_UE_INT_EN
178 .xword 0xffffffffffffffff, FIRE_PLC_TLU_CTB_TLR_CE_LOG
179 .xword 0xffffffffffffffff, FIRE_PLC_TLU_CTB_TLR_CE_INT_EN
180 .xword 0x0000000000000000, FIRE_PLC_TLU_CTB_LPR_PCIE_LPU_RST
181 .xword 0x0000000000000000, FIRE_PLC_TLU_CTB_LPR_PCIE_LPU_DBG_CONFIG
182 .xword 0x00000000800000ff, FIRE_PLC_TLU_CTB_LPR_PCIE_LPU_INTERRUPT_MASK
183 .xword 0x0000000000000100, FIRE_PLC_TLU_CTB_LPR_PCIE_LPU_LL_CONFIG
184 .xword 0x0000000000000003, FIRE_PLC_TLU_CTB_LPR_PCIE_LPU_FC_UP_CNTL
185 .xword 0x0000000000000070, FIRE_PLC_TLU_CTB_LPR_PCIE_LPU_ACKNAK_LATENCY
186 .xword 0x00000000000001bf, FIRE_PLC_TLU_CTB_LPR_PCIE_LPU_RPLAY_TMR_THHOLD
187 .xword 0x00000000ffff0000, FIRE_PLC_TLU_CTB_LPR_PCIE_LPU_RTRY_FIFO_PTR
188 .xword 0x0000000000000000, FIRE_PLC_TLU_CTB_LPR_PCIE_LPU_PHY_ERR_MSK
189 .xword 0x0000000000000000, FIRE_PLC_TLU_CTB_LPR_PCIE_LPU_RX_PHY_MSK
190 .xword 0x0000000000000050, FIRE_PLC_TLU_CTB_LPR_PCIE_LPU_TX_PHY_MSK
191 .xword 0x00000000002dc6c0, FIRE_PLC_TLU_CTB_LPR_PCIE_LPU_LTSSM_CONFIG2
192 .xword 0x000000000007a120, FIRE_PLC_TLU_CTB_LPR_PCIE_LPU_LTSSM_CONFIG3
193 .xword 0x0000000000029c00, FIRE_PLC_TLU_CTB_LPR_PCIE_LPU_LTSSM_CONFIG4
194 .xword 0x0000000000000800, FIRE_PLC_TLU_CTB_LPR_PCIE_LPU_LTSSM_CONFIG5
195 .xword 0x0000000000000000, FIRE_PLC_TLU_CTB_LPR_PCIE_LPU_LTSSM_MSK
196 .xword 0x0000000000000000, FIRE_PLC_TLU_CTB_LPR_PCIE_LPU_GB_GL_MSK
197 .xword 0xffffffffffffffff, FIRE_DLC_IMU_ICS_DMC_INTERRUPT_MASK_REG
198 .xword 0x0000000000000000, FIRE_DLC_CRU_DMC_DBG_SEL_A_REG
199 .xword 0x0000000000000000, FIRE_DLC_CRU_DMC_DBG_SEL_B_REG
200 .xword 0xffffffffffffffff, FIRE_DLC_ILU_CIB_PEC_INT_EN
201 .xword 0xffffffffffffffff, FIRE_DLC_MMU_INV
202 .xword 0x0000000000000000, FIRE_DLC_MMU_TSB
203 .xword 0x0000000000000703, FIRE_DLC_MMU_CTL
204 .xword 0xffffffffffffffff, FIRE_DLC_MMU_INT_EN
205
206 /* From OBP */
207 .xword 0x00000000da130001, FIRE_PLC_TLU_CTB_TLR_TLU_CTL
208 .xword 0x00000000a06bf035, FIRE_PLC_TLU_CTB_LPR_PCIE_LPU_GB_GL_CONFIG2
209 .xword 0x0000000000000070, FIRE_PLC_TLU_CTB_LPR_PCIE_LPU_ACKNAK_LATENCY
210 .xword 0x00000000000000f6, FIRE_PLC_TLU_CTB_LPR_PCIE_LPU_RPLAY_TMR_THHOLD
211 .xword 0x0000000002000000, FIRE_DLC_CRU_DMC_PCIE_CFG
212
213 /* MSI ranges */
214
215 .xword 0x000000007fff0000, FIRE_DLC_IMU_ICS_MSI_32_ADDR_REG
216 .xword 0x00000003ffff0000, FIRE_DLC_IMU_ICS_MSI_64_ADDR_REG
217 .xword -1, -1 /* End of Table */
218 SET_SIZE(fire_leaf_init_table)
219
220/*
221 * fire_init
222 *
223 * in:
224 * %i0 - global config pointer
225 * %i1 - base of guests
226 * %i2 - base of cpus
227 * %g7 - return address
228 */
229 ENTRY_NP(fire_init)
230 setx fire_jbus_init_table, %g5, %g3
231 setx fire_dev, %g5, %g1
232 ldx [%i0 + CONFIG_RELOC], %o0
233 sub %g3, %o0, %g3
234 sub %g1, %o0, %g1
235 !! %g1 = firep
236 !! %g3 = fire_jbus_init_table base
237 !! %g7 = return PC
238 ldx [%g1 + FIRE_COOKIE_JBUS], %g4
239 brz,pn %g4, 3f
240 nop
241
242 !! %g1 = firep
243 !! %g3 = fire_init_table base
244 !! %g4 = Fire Base JBus PA
245 !! %g7 = return PC
246 ldx [%g4], %g2
247 and %g2, FIRE_JBUS_ID_MR_MASK, %g2
248 cmp %g2, FIRE_REV_2_0
249 bgeu,pn %xcc, 1f
250 nop
251#ifdef DEBUG
252 PRINT("HV:Unsupported Fire Version\r\n")
253#endif
254 ba hvabort
255 rd %pc, %g1
256
2571:
258 ldx [%g3 + 8], %g5 ! Offset
259 add %g5, 1, %g6
260 brz,pn %g6, 3f
261 ldx [%g3 + 0], %g6 ! Data
262 add %g3, 16, %g3
263 ba 1b
264 stx %g6, [%g4 + %g5]
2653:
266 setx fire_leaf_init_table, %g5, %g3
267 ldx [%i0 + CONFIG_RELOC], %o0
268 sub %g3, %o0, %g3
269
270 ldx [%g1 + FIRE_COOKIE_PCIE], %g4
271 ldx [%g1 + FIRE_COOKIE_PCIE+FIRE_COOKIE_SIZE], %g5
272 !! %g4 leaf A base address
273 !! %g5 leaf B base address
274 brz,pn %g4, 3f
275 nop
2761:
277 ldx [%g3 + 8], %g6 ! Offset
278 add %g6, 1, %g2
279 brz,pn %g2, 2f ! End of table?
280 ldx [%g3 + 0], %g2 ! Data
281
282#ifdef FIRE_ERRATUM_20_18
283 /*
284 * Don't set the NPWR_EN bit in TLU CTL for Fire 2.0
285 */
286 set FIRE_PLC_TLU_CTB_TLR_TLU_CTL, %l0
287 cmp %g6, %l0
288 bne,pt %xcc, 4f
289 nop
290
291 /* Check Fire version */
292 ldx [%g1 + FIRE_COOKIE_JBUS], %l0
293 brz,pn %l0, 4f ! shouldn't happen at this point
294 nop
295 ldx [%l0], %l0
296 and %l0, FIRE_JBUS_ID_MR_MASK, %l0
297 cmp %l0, FIRE_REV_2_0
298 bne,pt %xcc, 4f
299 nop
300 set FIRE_TLU_CTL_NPWR_EN, %l0
301 andn %g2, %l0, %g2
3024:
303#endif
304 add %g3, 16, %g3
305 stx %g2, [%g4 + %g6]
306 ba 1b
307 stx %g2, [%g5 + %g6]
3082:
309 ! Setup Interrupt Mondo Data 0 register
310 set FIRE_DLC_IMU_RDS_MSI_INT_MONDO_DATA_0_REG, %g6
311 stx %g0, [%g4 + %g6] ! Leaf A
312 stx %g0, [%g5 + %g6] ! Leaf B
313
314 ! Setup Interrupt Mondo Data 1 register
315 set FIRE_DLC_IMU_RDS_MSI_INT_MONDO_DATA_1_REG, %g6
316 set FIRE_A_AID, %g2
317 sllx %g2, FIRE_DEVINO_SHIFT, %g2
318 stx %g2, [%g4 + %g6] ! Leaf A
319 set FIRE_B_AID, %g2
320 sllx %g2, FIRE_DEVINO_SHIFT, %g2
321 stx %g2, [%g5 + %g6] ! Leaf B
322
323 ! Setup interrupt mappings
324 ! mondo 62 leafs A and B
325 ! mondo 63 only leaf A
326 STRAND_STRUCT(%g4) /* FIXME: what does it want the PID for?*/
327 ldub [%g4 + STRAND_ID], %g2
328
329 mov %g0, %g5
330 ! Add CPU number
331 sllx %g2, JPID_SHIFT, %g6
332 or %g5, %g6, %g5
333
334 ! Select a Fire Interrupt Controller
335 and %g2, (NFIREINTRCONTROLLERS - 1), %g2
336 add %g2, FIRE_INTR_CNTLR_SHIFT, %g2
337 mov 1, %g6
338 sllx %g6, %g2, %g2
339 or %g5, %g2, %g5
340
341 ! Set MDO MODE bit
342 mov 1, %g6
343 sllx %g6, FIRE_INTMR_MDO_MODE_SHIFT, %g6
344 or %g5, %g6, %g5
345
346 ! Set Valid bit
347 mov 1, %g6
348 sllx %g6, FIRE_INTMR_V_SHIFT, %g6
349 or %g5, %g6, %g5
350
351 mov PCIE_ERR_INO, %g4
352 REGNO2OFFSET(%g4, %g4)
353 ldx [%g1 + FIRE_COOKIE_INTMAP], %g3
354 stx %g5, [%g3 + %g4] ! leaf A, modno 62
355 ldx [%g1 + FIRE_COOKIE_INTCLR], %g2
356 stx %g0, [%g2 + %g4]
357 ldx [%g2 + %g4], %g6
358 ldx [%g1 + FIRE_COOKIE_INTMAP+FIRE_COOKIE_SIZE], %g3
359 stx %g5, [%g3 + %g4] ! leaf B, mondo 62
360 ldx [%g1 + FIRE_COOKIE_INTCLR+FIRE_COOKIE_SIZE], %g2
361 stx %g0, [%g2 + %g4]
362 ldx [%g2 + %g4], %g6
363
364 mov JBC_ERR_INO, %g4
365 REGNO2OFFSET(%g4, %g4)
366 ldx [%g1 + FIRE_COOKIE_INTMAP], %g3
367 stx %g5, [%g3 + %g4] ! leaf A, mondo 63
368 ldx [%g1 + FIRE_COOKIE_INTCLR], %g2
369 stx %g0, [%g2 + %g4]
370
371 ! Clear Valid bit
372 mov 1, %g6
373 sllx %g6, FIRE_INTMR_V_SHIFT, %g6
374 bclr %g6, %g5
375 ldx [%g1 + FIRE_COOKIE_INTMAP+FIRE_COOKIE_SIZE], %g3
376 stx %g5, [%g3 + %g4] ! leaf B, mondo 63
377 ldx [%g1 + FIRE_COOKIE_INTCLR+FIRE_COOKIE_SIZE], %g2
378 stx %g0, [%g2 + %g4]
379
380 set FIRE_DLC_MMU_CTL, %g5
381 set FIRE_DLC_MMU_TSB, %g6
382 ! Fire Leaf A PCIE reg base
383 ldx [%g1 + FIRE_COOKIE_PCIE], %g3
384 ! Fire Leaf B PCIE reg base
385 ldx [%g1 + FIRE_COOKIE_PCIE+FIRE_COOKIE_SIZE], %g4
386 set FIRE_MMU_CSR_VALUE, %g2
387 ! Leaf A MMU_CTRL reg
388 stx %g2, [%g3 + %g5]
389 ! Leaf B MMU_CTRL reg
390 stx %g2, [%g4 + %g5]
391
392 ldx [%g1 + FIRE_COOKIE_IOTSB], %g2
393 ldx [%g1 + FIRE_COOKIE_IOTSB+FIRE_COOKIE_SIZE], %g5
394 or %g2, FIRE_TSB_SIZE, %g2
395 or %g5, FIRE_TSB_SIZE, %g5
396 ! Leaf A MMU_TSB_CTRL reg
397 stx %g2, [%g3 + %g6]
398 ! Leaf B MMU_TSB_CTRL reg
399 stx %g5, [%g4 + %g6]
400
401 !! %g1 = FIRE COOKIE
402 !! %g3 = FIRE_A PCIE Base
403 !! %g4 = FIRE_B PCIE Base
404 ldx [%g1 + FIRE_COOKIE_MSIEQBASE], %g2
405 ldx [%g1 + FIRE_COOKIE_MSIEQBASE+FIRE_COOKIE_SIZE], %g5
406 setx MSI_EQ_BASE_BYPASS_ADDR, %g7, %g6
407 or %g2, %g6, %g2
408 or %g5, %g6, %g5
409 set FIRE_DLC_IMU_EQS_EQ_BASE_ADDRESS, %g6
410 ! Leaf A EQ Base Address
411 stx %g2, [%g3 + %g6]
412 ! Leaf B EQ Base Address
413 stx %g5, [%g4 + %g6]
4143:
415
416#ifdef FIRE_ERRATUM_20_18
417
418#define BDF2DEV(b, d, f) ((((b) << 8) | ((d) << 5) | (f)) << 8)
419#define DV(v, d) (((d) << 16) | (v)) /* for 32-bit ASI_L */
420#define VENDOR_PLX 0x10b5
421#define DEVICE32_PLX8532 DV(VENDOR_PLX, 0x8532)
422#define DEVICE32_PLX8516 DV(VENDOR_PLX, 0x8516)
423
424 /* Check Fire version for 2.0 */
425 ldx [%g1 + FIRE_COOKIE_JBUS], %l0
426 brz,pn %l0, .skip_plx_workaround ! shouldn't happen
427 nop
428 ldx [%l0], %l0
429 and %l0, FIRE_JBUS_ID_MR_MASK, %l0
430 cmp %l0, FIRE_REV_2_0
431 bne,pt %xcc, .skip_plx_workaround
432 nop
433
434.check_plx_leafa:
435 /* Check if link is up, it should be for the PLX leaf on Ontario */
436 !! %g3 leaf A pcie base address
437 clr %l4
4381:
439 cmp %l4, 20 ! 20 * 50msec = 1 sec max delay
440 bge,pn %xcc, .skip_plx_leafa
441 .empty
442 CPU_MSEC_DELAY(50, %l5, %l6, %l7)
443 set FIRE_PLC_TLU_CTB_TLR_TLU_STS, %l0
444 ldx [%g3 + %l0], %l0
445 and %l0, FIRE_TLU_STS_STATUS_MASK, %l0
446 cmp %l0, FIRE_TLU_STS_STATUS_DATA_LINK_ACTIVE
447 bne,pt %xcc, 1b
448 inc %l4
449
450 /* calculate PA of config address for BDF 2.0.0, offset 0 */
451 set BDF2DEV(2, 0, 0), %l0
452 PCIDEV2FIREDEV(%l0, %l1)
453 ldx [%g1 + FIRE_COOKIE_CFG], %l2
454 add %l2, %l1, %l1
455 !! %l1 PA of config address of BDF 2.0.0
456
457 /* fire link up, but downlink needs a little more time */
458 CPU_MSEC_DELAY(200, %l5, %l6, %l7)
459 /* Check for PLX 8532/8516 */
460 lduwa [%l1]ASI_P_LE, %l2
461 set DEVICE32_PLX8532, %l3
462 cmp %l2, %l3
463 be,pt %xcc, 1f
464 nop
465 set DEVICE32_PLX8516, %l3
466 cmp %l2, %l3
467 bne,pn %xcc, .skip_plx_leafa
468 nop
4691:
470 stx %l1, [%g1 + FIRE_COOKIE_EXTRACFGRDADDRPA]
471#ifdef PLX_ERRATUM_LINK_HACK
472 mov %g7, %l7
473 mov %g3, %l2
474 !! %l1 = plx config base addr
475 !! %l2 = fire leaf base addr
476 HVCALL(fire_plx_reset_hack)
477 mov %l7, %g7
478#endif /* PLX_ERRATUM_LINK_HACK */
479.skip_plx_leafa:
480
481.check_plx_leafb:
482 /* Check if link is up, it should be for the PLX leaf on Ontario */
483 !! %g4 leaf B pcie base address
484 clr %l4
4851:
486 cmp %l4, 20 ! 20 * 50msec = 1 sec delay max
487 bge,pn %xcc, .skip_plx_leafb
488 .empty
489 CPU_MSEC_DELAY(50, %l5, %l6, %l7)
490 set FIRE_PLC_TLU_CTB_TLR_TLU_STS, %l0
491 ldx [%g4 + %l0], %l0
492 and %l0, FIRE_TLU_STS_STATUS_MASK, %l0
493 cmp %l0, FIRE_TLU_STS_STATUS_DATA_LINK_ACTIVE
494 bne,pt %xcc, 1b
495 inc %l4
496
497 /* calculate PA of config address for BDF 2.0.0, offset 0 */
498 set BDF2DEV(2, 0, 0), %l0
499 PCIDEV2FIREDEV(%l0, %l1)
500 ldx [%g1 + FIRE_COOKIE_SIZE + FIRE_COOKIE_CFG], %l2
501 add %l2, %l1, %l1
502 !! %l1 PA of config address of BDF 2.0.0
503
504 /* fire link up, but downlink needs a little more time */
505 CPU_MSEC_DELAY(200, %l5, %l6, %l7)
506 /* Check for PLX 8532/8516 */
507 lduwa [%l1]ASI_P_LE, %l2
508 set DEVICE32_PLX8532, %l3
509 cmp %l2, %l3
510 be,pt %xcc, 1f
511 nop
512 set DEVICE32_PLX8516, %l3
513 cmp %l2, %l3
514 bne,pn %xcc, .skip_plx_leafb
515 nop
5161:
517 stx %l1, [%g1 + FIRE_COOKIE_SIZE + FIRE_COOKIE_EXTRACFGRDADDRPA]
518#ifdef PLX_ERRATUM_LINK_HACK
519 mov %g7, %l7
520 mov %g4, %l2
521 !! %l1 = plx config base addr
522 !! %l2 = fire leaf base addr
523 !! %g3 = fire leaf A base
524 !! %g4 = fire leaf B base
525 HVCALL(fire_plx_reset_hack)
526 mov %l7, %g7
527#endif /* PLX_ERRATUM_LINK_HACK */
528.skip_plx_leafb:
529
530.skip_plx_workaround:
531#endif
532 HVRET
533 SET_SIZE(fire_init)
534
535
536/*
537 * void fire_config_bypass(fire_dev_t *firep, bool_t enable);
538 *
539 * Configures the bypass mode of a given fire PCI-E root complex.
540 *
541 * %o0 = fire_dev_t *
542 * %o1 = enable (true) / disable (false) bypass mode
543 */
544
545 ENTRY(fire_config_bypass)
546
547 ldx [%o0 + FIRE_COOKIE_PCIE], %o2
548 mov FIRE_MMU_CSR_BE, %o3
549 movrnz %o1, %o3, %o1
550
551 ! Leaf MMU_CTRL reg
552 set FIRE_DLC_MMU_CTL, %o4
553 ldx [%o2 + %o4], %o5
554 andn %o5, %o3, %o5
555 or %o5, %o1, %o5
556 stx %o5, [%o2 + %o4]
557
558 retl
559 nop
560 SET_SIZE(fire_config_bypass)
561
562
563
564#ifdef PLX_ERRATUM_LINK_HACK
565/*
566 * Workaround for PLX link training problem
567 */
568
569#define PLX_HACK_STATUS_LEAFB_SHIFT 4
570#define PLX_HACK_STATUS_PORT1 0x1
571#define PLX_HACK_STATUS_PORT2 0x2
572#define PLX_HACK_STATUS_PORT8 0x4
573#define PLX_HACK_STATUS_PORT9 0x8
574
575#define PLX_PORT_OFFSET 0x1000
576#define PLX_UE_STATUS_REG_OFFSET 0xfb8
577#define PLX_UESR_TRAINING_ERROR 0x1
578#define PLX_VC0_RSRC_STATUS_HI 0x162
579#define PLX_VC0_RSRC_NEGPEND_SHIFT 0x1
580
581#define PLX_PCIE_CAPABILITY_HI 0x6a
582#define PLX_PCIE_PORTTYPE_MASK 0xf0
583#define PLX_PCIE_PORTTYPE_UPSTREAM 0x50
584#define PLX_CONFIG_CMD 0x4
585#define PLX_CONFIG_CMD_MEMENABLE 0x2
586#define PLX_CONFIG_BAR0 0x10
587
588
589/*
590 * Register usage:
591 * %l1 - config base physical address
592 * %l3 - mem32 base physical address
593 */
594
595/* Uses %l4/%l5 as scratch */
596#define PLX_MEM_STOREB(value, offset) \
597 set value, %l4 ;\
598 set offset, %l5 ;\
599 stub %l4, [%l3 + %l5]
600
601/* Uses %l4/%l5 as scratch */
602#define PLX_MEM_STOREW(value, offset) \
603 set value, %l4 ;\
604 set offset, %l5 ;\
605 stuha %l4, [%l3 + %l5]ASI_P_LE
606
607/* Uses %l4/%l5 as scratch */
608#define PLX_MEM_STOREL(value, offset) \
609 set value, %l4 ;\
610 set offset, %l5 ;\
611 stuwa %l4, [%l3 + %l5]ASI_P_LE
612
613/* Uses %l5 as scratch */
614#define PLX_MEM_FETCHW(offset, dest) \
615 set offset, %l5 ;\
616 lduha [%l3 + %l5]ASI_P_LE, dest
617
618/* Uses %l5 as scratch */
619#define PLX_MEM_FETCHL(offset, dest) \
620 set offset, %l5 ;\
621 lduwa [%l3 + %l5]ASI_P_LE, dest
622
623/* Uses %l4/%l5 as scratch */
624#define PLX_CFG_STOREW(value, offset) \
625 set value, %l4 ;\
626 set offset, %l5 ;\
627 stuha %l4, [%l1 + %l5]ASI_P_LE
628
629#define PLX_CFG_STOREREGW(reg, offset) \
630 set offset, %l5 ;\
631 stuha reg, [%l1 + %l5]ASI_P_LE
632
633/* Uses %l4/%l5 as scratch */
634#define PLX_CFG_STOREL(value, offset) \
635 set value, %l4 ;\
636 set offset, %l5 ;\
637 stuwa %l4, [%l1 + %l5]ASI_P_LE
638
639#define PLX_CFG_STOREREGL(reg, offset) \
640 set offset, %l5 ;\
641 stuwa reg, [%l1 + %l5]ASI_P_LE
642
643/* Uses %l5 as scratch */
644#define PLX_CFG_FETCHB(offset, dest) \
645 set offset, %l5 ;\
646 ldub [%l1 + %l5], dest
647
648/* Uses %l5 as scratch */
649#define PLX_CFG_FETCHW(offset, dest) \
650 set offset, %l5 ;\
651 lduha [%l1 + %l5]ASI_P_LE, dest
652
653/* Uses %l5 as scratch */
654#define PLX_CFG_FETCHL(offset, dest) \
655 set offset, %l5 ;\
656 lduwa [%l1 + %l5]ASI_P_LE, dest
657
658/* Uses %g5/%g6 as scratch, invokes PLX_FETCH */
659#define PLX_TRAINING_ERROR_nz(port) \
660 PLX_MEM_FETCHW(((port * PLX_PORT_OFFSET) + \
661 PLX_VC0_RSRC_STATUS_HI), %g5) ;\
662 srlx %g5, PLX_VC0_RSRC_NEGPEND_SHIFT, %g5 ;\
663 PLX_MEM_FETCHL(((port * PLX_PORT_OFFSET) + \
664 PLX_UE_STATUS_REG_OFFSET), %g6) ;\
665 and %g5, %g6, %g5 ;\
666 btst PLX_UESR_TRAINING_ERROR, %g5
667
668
669/*
670 * fire_plx_reset_hack - work around PLX link training problem
671 *
672 * %l1 PLX config space address
673 * %l2 Fire leaf base
674 * %g1 base of Fire state structures ("cookies")
675 * %g3 fire leaf A base
676 * %g4 fire leaf B base
677 * %l3-%l6,%g5,%g6 available
678 */
679 ENTRY_NP(fire_plx_reset_hack)
680 /*
681 * See if this hack has been disabled by the SP
682 */
683 ldx [%i0 + CONFIG_IGNORE_PLX_LINK_HACK], %l6
684 brz,pt %l6, 0f
685 nop
686 HVRET
6870:
688
689 /*
690 * Check for rev AA and upstream port
691 */
692 PLX_CFG_FETCHB(0x8, %l6)
693 cmp %l6, 0xaa
694 bne,pt %xcc, .fire_plx_reset_hack_done
695 nop
696
697 PLX_CFG_FETCHW(PLX_PCIE_CAPABILITY_HI, %l6)
698 and %l6, PLX_PCIE_PORTTYPE_MASK, %l6
699 cmp %l6, PLX_PCIE_PORTTYPE_UPSTREAM
700 bne,pt %xcc, .fire_plx_reset_hack_done
701 nop
702
703 /*
704 * Get MEM32 base address for the appropriate leaf
705 */
706 setx FIRE_BAR(MEM32(A)), %l6, %l3
707 setx FIRE_BAR(MEM32(B)), %l6, %l4
708 cmp %l2, %g3 ! compare current leaf to leaf A addr
709 movne %xcc, %l4, %l3
710 !! %l3 = plx mem32 base addr
711
712 /* It's probably not enabled to respond in cmd register */
713 PLX_CFG_FETCHW(PLX_CONFIG_CMD, %g5)
714 or %g5, PLX_CONFIG_CMD_MEMENABLE, %g5
715 PLX_CFG_STOREREGW(%g5, PLX_CONFIG_CMD)
716
717 /* Map in PLX mem space BAR */
718 PLX_CFG_STOREREGL(%g0, PLX_CONFIG_BAR0)
719 mov PLX_CONFIG_BAR0, %l5 ! BAR0
720 lduwa [%l1 + %l5]ASI_P_LE, %g0 ! force completion of stores
721
722 /*
723 * If the link is not up, and a training error was logged
724 * then try to retrain
725 */
726 !! %l3 = plx mem32 base addr
727 !! %l2 = fire pcie leaf base addr
728 !! %l1 = plx cfg base addr
729
730 /*
731 * Check for link training errors
732 */
733 mov 0, %o0 ! failure flag
734 PLX_TRAINING_ERROR_nz(1) ! port 1
735 bnz,a,pt %xcc, 0f
736 bset PLX_HACK_STATUS_PORT1, %o0
7370: PLX_TRAINING_ERROR_nz(2) ! port 2
738 bnz,a,pt %xcc, 0f
739 bset PLX_HACK_STATUS_PORT2, %o0
7400: PLX_TRAINING_ERROR_nz(8) ! port 8
741 bnz,a,pt %xcc, 0f
742 bset PLX_HACK_STATUS_PORT8, %o0
7430: PLX_TRAINING_ERROR_nz(9) ! port 9
744 bnz,a,pt %xcc, 0f
745 bset PLX_HACK_STATUS_PORT9, %o0
7460:
747 brz,pt %o0, .fire_plx_reset_hack_done
748 nop
749
750 /*
751 * PLX encountered a link training problem, tell vbsc to reset
752 * the system.
753 * %o0 contains a bitmask of ports on the plx that failed
754 * |9|8|2|1|
755 * For leaf B we shift the bitmask up by 4 bits:
756 * |B9|B8|B2|B1|A9|A8|A2|A1|
757 */
758 mov 0, %g1
759 cmp %l2, %g3
760 movne %xcc, PLX_HACK_STATUS_LEAFB_SHIFT, %g1
761 sllx %o0, %g1, %g1
762 HVCALL(vbsc_hv_plxreset)
763 /* spin until vbsc resets the system */
764 ba .
765 nop
766
767.fire_plx_reset_hack_done:
768 PLX_CFG_STOREREGW(%g0, PLX_CONFIG_CMD)
769
770 HVRET
771 SET_SIZE(fire_plx_reset_hack)
772
773#endif /* PLX_ERRATUM_LINK_HACK */
774
775
776/*
777 * fire_devino2vino
778 *
779 * %g1 Fire Cookie Pointer
780 * arg0 dev config pa (%o0)
781 * arg1 dev ino (%o1)
782 * --
783 * ret0 status (%o0)
784 * ret1 virtual INO (%o1)
785 */
786 ENTRY_NP(fire_devino2vino)
787 !! %g1 pointer to FIRE_COOKIE
788 ldx [%g1 + FIRE_COOKIE_HANDLE], %g2
789 cmp %o0, %g2
790 bne herr_inval
791 lduh [%g1 + FIRE_COOKIE_INOMAX], %g3
792 cmp %o1, %g3
793 bgu,pn %xcc, herr_inval
794 lduh [%g1 + FIRE_COOKIE_VINO], %g4
795 or %o1, %g4, %o1
796 HCALL_RET(EOK)
797 SET_SIZE(fire_devino2vino)
798
799/*
800 * fire_intr_getvalid
801 *
802 * %g1 Fire Cookie Pointer
803 * arg0 Virtual INO (%o0)
804 * --
805 * ret0 status (%o0)
806 * ret1 intr valid state (%o1)
807 */
808 ENTRY_NP(fire_intr_getvalid)
809 !! %g1 pointer to FIRE_COOKIE
810 ldx [%g1 + FIRE_COOKIE_INTMAP], %g2
811 and %o0, FIRE_DEVINO_MASK, %g4
812 REGNO2OFFSET(%g4, %g4)
813 ldx [%g2 + %g4], %g5
814 sra %g5, 0, %g5
815 mov INTR_DISABLED, %o1
816 movrlz %g5, INTR_ENABLED, %o1
817 HCALL_RET(EOK)
818 SET_SIZE(fire_intr_getvalid)
819
820/*
821 * _fire_intr_setvalid
822 *
823 * %g1 Fire Cookie Pointer
824 * %g2 INO
825 * %g3 intr valid state
826 * --
827 *
828 * ret0 Fire Cookie (%g1)
829 * ret1 INO (%g2)
830 */
831 ENTRY_NP(_fire_intr_setvalid)
832 !! %g1 = pointer to FIRE_COOKIE
833 ldx [%g1 + FIRE_COOKIE_INTMAP], %g6
834 and %g2, FIRE_DEVINO_MASK, %g4
835 REGNO2OFFSET(%g4, %g4)
836 add %g4, %g6, %g4
837 ldx [%g4], %g5
838 mov 1, %g6
839 sllx %g6, FIRE_INTMR_V_SHIFT, %g6
840 andn %g5, %g6, %g5
841 sllx %g3, FIRE_INTMR_V_SHIFT, %g6
842 or %g5, %g6, %g5
843 stx %g5, [%g4]
844
845 HVRET
846 SET_SIZE(_fire_intr_setvalid)
847
848/*
849 * fire_intr_setvalid
850 *
851 * %g1 Fire Cookie Pointer
852 * arg0 Virtual INO (%o0)
853 * arg1 intr valid state (%o1) 1: Valid 0: Invalid
854 * --
855 * ret0 status (%o0)
856 */
857 ENTRY_NP(fire_intr_setvalid)
858 !! %g1 = pointer to FIRE_COOKIE
859 mov %o0, %g2
860 mov %o1, %g3
861 HVCALL(_fire_intr_setvalid)
862
863 HCALL_RET(EOK)
864 SET_SIZE(fire_intr_setvalid)
865
866/*
867 * fire_intr_getstate
868 *
869 * %g1 Fire Cookie Pointer
870 * arg0 Virtual INO (%o0)
871 * --
872 * ret0 status (%o0)
873 * ret1 (%o1) 1: Pending / 0: Idle
874 */
875 ENTRY_NP(fire_intr_getstate)
876 !! %g1 pointer to FIRE_COOKIE
877 ldx [%g1 + FIRE_COOKIE_INTCLR], %g2
878 and %o0, FIRE_DEVINO_MASK, %g4
879 REGNO2OFFSET(%g4, %g4)
880 ldx [%g2 + %g4], %g3
881 sub %g3, FIRE_INTR_RECEIVED, %g4
882 movrz %g4, INTR_DELIVERED, %o1
883 movrnz %g4, INTR_RECEIVED, %o1
884 movrz %g3, INTR_IDLE, %o1
885 HCALL_RET(EOK)
886 SET_SIZE(fire_intr_getstate)
887
888/*
889 * fire_intr_setstate
890 *
891 * %g1 Fire Cookie Pointer
892 * arg0 Virtual INO (%o0)
893 * arg1 (%o1) 1: Pending / 0: Idle XXX
894 * --
895 * ret0 status (%o0)
896 */
897 ENTRY_NP(fire_intr_setstate)
898 !! %g1 pointer to FIRE_COOKIE
899 cmp %o1, INTR_DELIVERED
900 bgu,pn %xcc, herr_inval
901 mov %o0, %g2
902 mov %o1, %g3
903 HVCALL(_fire_intr_setstate)
904
905 HCALL_RET(EOK)
906 SET_SIZE(fire_intr_setstate)
907
908/*
909 * %g1 = Fire Cookie
910 * %g2 = device ino
911 * %g3 = Pending/Idle
912 * --
913 * %g1 = Fire Cookie
914 * %g2 = device ino
915 */
916 ENTRY_NP(_fire_intr_setstate)
917 ldx [%g1 + FIRE_COOKIE_INTCLR], %g5
918 and %g2, FIRE_DEVINO_MASK, %g4
919 REGNO2OFFSET(%g4, %g4)
920 movrz %g3, FIRE_INTR_IDLE, %g3
921 movrnz %g3, FIRE_INTR_RECEIVED, %g3
922 stx %g3, [%g5 + %g4]
923
924 HVRET
925 SET_SIZE(_fire_intr_setstate)
926
927/*
928 * fire_intr_gettarget
929 *
930 * %g1 Fire Cookie Pointer
931 * arg0 Virtual INO (%o0)
932 * --
933 * ret0 status (%o0)
934 * ret1 cpuid (%o1)
935 */
936 ENTRY_NP(fire_intr_gettarget)
937 !! %g1 pointer to FIRE_COOKIE
938
939 mov %o0, %g2
940 HVCALL(_fire_intr_gettarget)
941
942 ! get the virtual cpuid
943 PID2VCPUP(%g3, %g4, %g5, %g6)
944 ldub [%g4 + CPU_VID], %o1
945
946 HCALL_RET(EOK)
947 SET_SIZE(fire_intr_gettarget)
948
949/*
950 * %g1 = Fire cookie
951 * %g2 = device ino
952 * --
953 * %g1 = Fire cookie
954 * %g2 = device ino
955 * %g3 = phys cpuid
956 */
957 ENTRY_NP(_fire_intr_gettarget)
958 ldx [%g1 + FIRE_COOKIE_INTMAP], %g3
959 and %g2, FIRE_DEVINO_MASK, %g4
960 REGNO2OFFSET(%g4, %g4)
961 ldx [%g3 + %g4], %g3
962 srlx %g3, JPID_SHIFT, %g3
963 and %g3, JPID_MASK, %g4
964
965 /* FIXME: What is this trying to do ?! */
966 ROOT_STRUCT(%g3)
967 ldx [%g3 + CONFIG_VCPUS], %g3
968 set VCPU_SIZE, %g5
969 mulx %g4, %g5, %g5
970 add %g3, %g5, %g3
971 VCPU2STRAND_STRUCT(%g3, %g3)
972 ldub [%g3 + STRAND_ID], %g3
973
974 HVRET
975 SET_SIZE(_fire_intr_gettarget)
976
977/*
978 * fire_intr_settarget
979 *
980 * %g1 Fire Cookie Pointer
981 * arg0 Virtual INO (%o0)
982 * arg1 cpuid (%o1)
983 * --
984 * ret0 status (%o0)
985 */
986 ENTRY_NP(fire_intr_settarget)
987 !! %g1 pointer to FIRE_COOKIE
988 GUEST_STRUCT(%g3)
989 VCPUID2CPUP(%g3, %o1, %g4, herr_nocpu, %g5)
990
991 IS_CPU_IN_ERROR(%g4, %g5)
992 be,pn %xcc, herr_cpuerror
993 nop
994
995 VCPU2STRAND_STRUCT(%g4, %g3)
996 ldub [%g3 + STRAND_ID], %g3
997 and %o0, FIRE_DEVINO_MASK, %g2
998
999 HVCALL(_fire_intr_settarget)
1000
1001 HCALL_RET(EOK)
1002 SET_SIZE(fire_intr_settarget)
1003
1004/*
1005 * %g1 = fire cookie
1006 * %g2 = device ino
1007 * %g3 = Physical CPU number
1008 * --
1009 * %g1 = fire cookie
1010 * %g2 = device ino
1011 */
1012 ENTRY_NP(_fire_intr_settarget)
1013 ldx [%g1 + FIRE_COOKIE_INTMAP], %g4
1014 REGNO2OFFSET(%g2, %g6)
1015 add %g4, %g6, %g4
1016 ldx [%g4], %g5
1017
1018 !! %g2 INO offset
1019 !! %g3 Physical CPU number
1020 !! %g4 INTMAP base
1021 !! %g5 INTMAP reg value
1022
1023 ! Add CPU number
1024 mov JPID_MASK, %g6
1025 sllx %g6, JPID_SHIFT, %g6
1026 andn %g5, %g6, %g5
1027 sllx %g3, JPID_SHIFT, %g6
1028 or %g5, %g6, %g5
1029
1030 ! Clear Interrupt Controller bits
1031 andn %g5, (FIRE_INTR_CNTLR_MASK << FIRE_INTR_CNTLR_SHIFT), %g5
1032
1033 ! Select a Fire Interrupt Controller
1034 and %g3, (NFIREINTRCONTROLLERS - 1), %g3
1035 add %g3, FIRE_INTR_CNTLR_SHIFT, %g3
1036 mov 1, %g6
1037 sllx %g6, %g3, %g3
1038 or %g5, %g3, %g5
1039
1040 ! Set MDO MODE bit
1041 mov 1, %g6
1042 sllx %g6, FIRE_INTMR_MDO_MODE_SHIFT, %g6
1043 or %g5, %g6, %g5
1044
1045 stx %g5, [%g4]
1046
1047 HVRET
1048 SET_SIZE(_fire_intr_settarget)
1049
1050/*
1051 * fire_iommu_map
1052 *
1053 * %g1 Fire Cookie Pointer
1054 * arg0 dev config pa (%o0)
1055 * arg1 tsbid (%o1)
1056 * arg2 #ttes (%o2)
1057 * arg3 tte attributes (%o3)
1058 * arg4 io_page_list_p (%o4)
1059 * --
1060 * ret0 status (%o0)
1061 * ret1 #ttes mapped (%o1)
1062 */
1063 ENTRY_NP(fire_iommu_map)
1064 !! %g1 pointer to FIRE_COOKIE
1065 and %o3, HVIO_TTE_ATTR_MASK, %g7
1066 cmp %o3, %g7
1067 bne,pn %xcc, herr_inval
1068 ! Check io_page_list_p alignment
1069 ! and make sure it is 8 byte aligned
1070 btst SZ_LONG - 1, %o4
1071 bnz,pn %xcc, herr_badalign
1072 ldx [%g1 + FIRE_COOKIE_IOTSB], %g5
1073 set IOTSB_INDEX_MAX, %g3
1074 cmp %o1, %g3
1075 bgu,pn %xcc, herr_inval
1076 brlez,pn %o2, herr_inval
1077 cmp %o2, IOMMU_MAP_MAX
1078 movgu %xcc, IOMMU_MAP_MAX, %o2
1079
1080 ! Check to ensure the end of the mapping is still within
1081 ! range.
1082
1083 !! %o2 #ttes
1084 !! %o1 tte index
1085 !! %g3 IOTSB_INDEX_MAX
1086
1087 add %o1, %o2, %g2
1088 inc %g3 ! make sure last mapping succeeds.
1089 cmp %g2, %g3
1090 bgu,pn %xcc, herr_inval
1091 nop
1092
1093 GUEST_STRUCT(%g2)
1094
1095 sllx %o2, IOTTE_SHIFT, %g6
1096 RA2PA_RANGE_CONV_UNK_SIZE(%g2, %o4, %g6, herr_noraddr, %g7, %g3)
1097 mov %g3, %g6
1098 !! %g6 PA
1099
1100 ldx [%g1 + FIRE_COOKIE_MMU], %g1
1101 mov 1, %g7
1102 sllx %g7, FIRE_IOTTE_V_SHIFT, %g7
1103 or %g7, %o3, %o3
1104
1105 set IOMMU_PAGESIZE, %g4
1106
1107 !! %g1 = Fire MMU Reg Block Base
1108 !! %g2 = Guest Struct
1109 !! %g4 = IOTSB pagesize
1110 !! %g5 = IOTSB base
1111 !! %g6 = PA of pagelist
1112 !! %o1 = TTE index
1113 !! %o2 = #ttes to map
1114 !! %o3 = TTE Attributes + Valid Bit
1115
1116 sllx %o1, IOTTE_SHIFT, %o1
1117 add %g5, %o1, %g5
1118 mov 0, %o1
1119
1120 !! %g1 = Fire MMU Reg Block Base
1121 !! %g2 = Guest
1122 !! %g4 = IOTSB pagesize
1123 !! %g5 = IOTSB base
1124 !! %g6 = PA of pagelist
1125 !! %o1 = TTE index
1126 !! %o2 = #ttes to map
1127 !! %o3 = TTE Attributes + Valid Bit
1128
1129.fire_iommu_map_loop:
1130 ldx [%g6], %g3
1131 srlx %g3, FIRE_PAGESIZE_8K_SHIFT, %o0
1132 sllx %o0, FIRE_PAGESIZE_8K_SHIFT, %o0
1133
1134 cmp %g3, %o0
1135 bne,pn %xcc, .fire_badalign
1136 nop
1137
1138 RA2PA_RANGE_CONV(%g2, %o0, %g4, .fire_check_ldc_ra, %g7, %g3)
1139 ba .fire_valid_ra
1140 mov %g3, %o0
1141
1142.fire_check_ldc_ra:
1143 LDC_IOMMU_GET_PA(%g2, %o0, %g3, %g7, .fire_noraddr, .fire_noaccess)
1144 mov %g3, %o0
1145
1146.fire_valid_ra:
1147 !! %g1 = Fire MMU Reg Block Base
1148 !! %g2 = Guest Struct
1149 !! %g4 = IOTSB pagesize
1150 !! %g5 = IOTSB base
1151 !! %g6 = PA of pagelist
1152 !! %o0 = PA of map addr
1153 !! %o1 = TTE index
1154 !! %o2 = #ttes to map
1155 !! %o3 = TTE Attributes + Valid Bit
1156 or %o0, %o3, %o0
1157 stx %o0, [%g5]
1158 and %g5, (1 << 6) - 1, %o0
1159
1160 stx %g5, [%g1+0x100] ! IOMMU Flush
1161
1162 add %g5, IOTTE_SIZE, %g5 ! *IOTSB++
1163 add %g6, IOTTE_SIZE, %g6 ! *PAGELIST++
1164 sub %o2, 1, %o2
1165 brgz,pt %o2, .fire_iommu_map_loop
1166 add %o1, 1, %o1
1167
1168.fire_noaccess:
1169 brz,pn %o1, herr_noaccess
1170 mov 0, %o2
1171 HCALL_RET(EOK)
1172
1173.fire_noraddr:
1174 brz,pn %o1, herr_noraddr
1175 mov 0, %o2
1176 HCALL_RET(EOK)
1177
1178.fire_badalign:
1179 brz,pn %o1, herr_badalign
1180 mov 0, %o2
1181 HCALL_RET(EOK)
1182 SET_SIZE(fire_iommu_map)
1183
1184/*
1185 * fire_iommu_map_v2
1186 *
1187 * %g1 Fire Cookie Pointer
1188 * arg0 dev config pa (%o0)
1189 * arg1 tsbid (%o1)
1190 * arg2 #ttes (%o2)
1191 * arg3 tte attributes (%o3)
1192 * arg4 io_page_list_p (%o4)
1193 * --
1194 * ret0 status (%o0)
1195 * ret1 #ttes mapped (%o1)
1196 */
1197 ENTRY_NP(fire_iommu_map_v2)
1198 set HVIO_TTE_ATTR_MASK_V2, %g7
1199 and %o3, %g7, %g7
1200 cmp %o3, %g7
1201 bne,pn %xcc, herr_inval
1202 and %o3, HVIO_TTE_ATTR_MASK, %o3
1203 ba,a fire_iommu_map
1204 .empty
1205 SET_SIZE(fire_iommu_map_v2)
1206
1207/*
1208 * fire_iommu_getmap
1209 * fire_iommu_getmap_v2
1210 *
1211 * %g1 = Fire Cookie Pointer
1212 * arg0 dev config pa (%o0)
1213 * arg1 tsbid (%o1)
1214 * --
1215 * ret0 status (%o0)
1216 * ret1 attributes (%o1)
1217 * ret2 ra (%o2)
1218 */
1219 ENTRY_NP(fire_iommu_getmap)
1220 ALTENTRY(fire_iommu_getmap_v2)
1221 !! %g1 pointer to FIRE_COOKIE
1222 ldx [%g1 + FIRE_COOKIE_IOTSB], %g5
1223 set IOTSB_INDEX_MAX, %g3
1224 cmp %o1, %g3
1225 bgu,pn %xcc, herr_inval
1226 sllx %o1, IOTTE_SHIFT, %g2
1227 ldx [%g5 + %g2], %g5
1228 brgez,pt %g5, herr_nomap
1229 GUEST_STRUCT(%g2)
1230
1231 !! %g1 = Fire Cookie Pointer
1232 !! %g2 = Guest pointer
1233 !! %g5 = IOTTE
1234 sllx %g5, (64-JBUS_PA_SHIFT), %g3
1235 srlx %g3, (64-JBUS_PA_SHIFT+FIRE_PAGESIZE_8K_SHIFT), %g3
1236 sllx %g3, FIRE_PAGESIZE_8K_SHIFT, %g3
1237 PA2RA_CONV(%g2, %g3, %o2, %g7, %g4) ! PA -> RA (%o2)
1238 brnz %g4, herr_nomap /* invalid translation */
1239 nop
1240
1241 and %g5, HVIO_TTE_ATTR_MASK, %o1
1242 movrgez %g5, 0, %o1 ! Clear the attributes if V=0
1243 HCALL_RET(EOK)
1244 SET_SIZE(fire_iommu_getmap)
1245
1246/*
1247 *
1248 *
1249 * %g1 Fire Cookie Pointer
1250 * arg0 dev config pa (%o0)
1251 * arg1 tsbid (%o1)
1252 * arg2 #ttes (%o2)
1253 * --
1254 * ret0 status (%o0)
1255 * ret1 #ttes demapped (%o1)
1256 */
1257 ENTRY_NP(fire_iommu_unmap)
1258 !! %g1 pointer to FIRE_COOKIE
1259 ldx [%g1 + FIRE_COOKIE_IOTSB], %g5
1260 set IOTSB_INDEX_MAX, %g3
1261 cmp %o1, %g3
1262 bgu,pn %xcc, herr_inval
1263 brlez,pn %o2, herr_inval
1264 cmp %o2, IOMMU_MAP_MAX
1265 movgu %xcc, IOMMU_MAP_MAX, %o2
1266 brz,pn %o2, herr_inval
1267 add %o1, %o2, %g2
1268 inc %g3 ! make sure last mapping succeeds.
1269 cmp %g2, %g3
1270 bgu,pn %xcc, herr_inval
1271 sllx %o1, IOTTE_SHIFT, %g2
1272 add %g5, %g2, %g2
1273 mov 0, %o1
1274
1275 !! %g1 = Fire Cookie Pointer
1276 !! %g2 = IOTSB offset
1277 !! %o1 = #ttes unmapped so far
1278 !! %o2 = #ttes to unmap
1279 ldx [%g1 + FIRE_COOKIE_MMU], %g1
12800:
1281 ldx [%g2], %g5
1282 ! Clear V bit
1283 sllx %g5, 1, %g4
1284 srlx %g4, 1, %g4
1285 ! Clear Attributes
1286 srlx %g4, FIRE_PAGESIZE_8K_SHIFT, %g4
1287 sllx %g4, FIRE_PAGESIZE_8K_SHIFT, %g4
1288 stx %g4, [%g2]
1289 ! IOMMU Flush
1290 stx %g2, [%g1+0x100]
1291 add %g2, IOTTE_SIZE, %g2
1292 sub %o2, 1, %o2
1293 brgz,pt %o2, 0b
1294 add %o1, 1, %o1
1295
1296 ! Flush Fire TSB here XXXX
1297 HCALL_RET(EOK)
1298 SET_SIZE(fire_iommu_unmap)
1299
1300/*
1301 * fire_iommu_getbypass
1302 *
1303 * arg0 dev config pa
1304 * arg1 ra
1305 * arg2 io attributes
1306 * --
1307 * ret0 status (%o0)
1308 * ret1 bypass addr (%o1)
1309 */
1310 ENTRY_NP(fire_iommu_getbypass)
1311 !! %g1 pointer to FIRE_COOKIE
1312
1313 ! Check to see if bypass is allowed
1314 ! (We could check the pcie structure, but what better way
1315 ! than to check and see what Fire itself has enabled after config)
1316 !
1317 ! FIXME: Note S10U3 has a bug in the px driver that will assume
1318 ! bypass is available if anything other than ENOTSUPP is returned
1319 ! .. so if the other tests also fail and return EINVAL or EBADRADDR
1320 ! *before* the bypass enable test then Solaris assumes bypass *is*
1321 ! supported. For this reason, the not supported test must be first.
1322 ! - ug !
1323
1324 ldx [%g1 + FIRE_COOKIE_PCIE], %g4
1325 set FIRE_DLC_MMU_CTL, %g5
1326 ldx [%g4 + %g5], %g5
1327 andcc %g5, FIRE_MMU_CSR_BE, %g0
1328 be,pn %xcc, herr_notsupported
1329 nop
1330
1331 andncc %o2, HVIO_IO_ATTR_MASK, %g0
1332 bnz,pn %xcc, herr_inval
1333 .empty
1334
1335 GUEST_STRUCT(%g2)
1336
1337 RA2PA_RANGE_CONV(%g2, %o1, 1, herr_noraddr, %g4, %g3)
1338 !! %g3 pa of bypass ra
1339
1340 setx FIRE_IOMMU_BYPASS_BASE, %g5, %g4
1341 or %g3, %g4, %o1
1342 HCALL_RET(EOK)
1343 SET_SIZE(fire_iommu_getbypass)
1344
1345/*
1346 * fire_config_get
1347 *
1348 * arg0 dev config pa (%o0)
1349 * arg1 PCI device (%o1)
1350 * arg2 offset (%o2)
1351 * arg3 size (%o3)
1352 * --
1353 * ret0 status (%o0)
1354 * ret1 error_flag (%o1)
1355 * ret2 value (%o2)
1356 */
1357
1358 ENTRY_NP(fire_config_get)
1359 !! %g1 pointer to FIRE_COOKIE
1360
1361 ! If leaf is blacklisted fail access
1362 lduw [%g1 + FIRE_COOKIE_BLACKLIST], %g3
1363 brnz,a,pn %g3, .skip_config_get
1364 mov 1, %o1
1365
1366 ldx [%g1 + FIRE_COOKIE_CFG], %g3
1367
1368 PCIDEV2FIREDEV(%o1, %g2)
1369 or %g2, %o2, %g2
1370 sub %g0, 1, %o2
1371
1372 !! %g1 = Fire cookie
1373 !! %g2 = PCIE config space offset
1374 !! %g3 = CFG base address
1375 !! %o2 = Error return value
1376
1377 CHK_FIRE_LINK_STATUS(%g1, %g5, %g6)
1378 brz,pn %g5, .skip_config_get
1379 mov 1, %o1 ! Error flag
1380
1381 mov 1, %g5
1382 STRAND_STRUCT(%g4)
1383 set STRAND_IO_PROT, %g6
1384
1385 ! strand.io_prot = 1
1386 stx %g5, [%g4 + %g6]
1387
1388 !! %g1 = Fire cookie
1389 !! %g2 = PCIE config space offset
1390 !! %g3 = CFG base address
1391 !! %g4 = STRAND struct
1392
1393 DISABLE_PCIE_RWUC_ERRORS(%g1, %g5, %g6, %g7)
1394
1395 cmp %o3, SZ_WORD
1396 beq,a,pn %xcc,1f
1397 lduwa [%g3 + %g2]ASI_P_LE, %o2
1398 cmp %o3, SZ_HWORD
1399 beq,a,pn %xcc,1f
1400 lduha [%g3 + %g2]ASI_P_LE, %o2
1401 ldub [%g3 + %g2], %o2
1402
14031:
1404 set STRAND_IO_PROT, %g6
1405 ! strand.io_prot = 0
1406 stx %g0, [%g4 + %g6]
1407 set STRAND_IO_ERROR, %g6
1408 ! strand.io_error
1409 ldx [%g4 + %g6], %o1
1410 ! strand.io_error = 0
1411 stx %g0, [%g4 + %g6]
1412
1413 !! %g1 = Fire cookie
1414
1415 ENABLE_PCIE_RWUC_ERRORS(%g1, %g5, %g6, %g7)
1416
1417.skip_config_get:
1418 HCALL_RET(EOK)
1419 SET_SIZE(fire_config_get)
1420
1421/*
1422 * fire_config_put
1423 *
1424 * arg0 dev config pa (%o0)
1425 * arg1 PCI device (%o1)
1426 * arg2 offset (%o2)
1427 * arg3 size (%o3)
1428 * arg4 data (%o4)
1429 * --
1430 * ret0 status (%o0)
1431 * ret1 error_flag (%o1)
1432 */
1433 ENTRY_NP(fire_config_put)
1434 !! %g1 pointer to FIRE_COOKIE
1435
1436 ! If leaf is blacklisted fail access
1437 lduw [%g1 + FIRE_COOKIE_BLACKLIST], %g3
1438 brnz,a,pn %g3, .skip_config_put
1439 mov 1, %o1
1440
1441 ldx [%g1 + FIRE_COOKIE_CFG], %g3
1442
1443 PCIDEV2FIREDEV(%o1, %g2)
1444 or %g2, %o2, %g2
1445
1446 !! %g1 = Fire cookie
1447 !! %g2 = PCIE config space offset
1448 !! %g3 = CFG base address
1449
1450 CHK_FIRE_LINK_STATUS(%g1, %g5, %g6)
1451 brz,pn %g5, .skip_config_put
1452 mov 1, %o1 ! Error flag
1453
1454 mov 1, %g5
1455 STRAND_STRUCT(%g4)
1456 set STRAND_IO_PROT, %g6
1457
1458 ! strand.io_prot = 1
1459 stx %g5, [%g4 + %g6]
1460
1461 !! %g1 = Fire cookie
1462 !! %g2 = PCIE config space offset
1463 !! %g3 = CFG base address
1464 !! %g4 = STRAND struct
1465
1466 DISABLE_PCIE_RWUC_ERRORS(%g1, %g5, %g6, %g7)
1467
1468 cmp %o3, SZ_WORD
1469 beq,a,pn %xcc,1f
1470 stwa %o4, [%g3 + %g2]ASI_P_LE
1471 cmp %o3, SZ_HWORD
1472 beq,a,pn %xcc,1f
1473 stha %o4, [%g3 + %g2]ASI_P_LE
1474 stb %o4, [%g3 + %g2]
14751:
1476#ifdef FIRE_ERRATUM_20_18
1477 ldx [%g1 + FIRE_COOKIE_EXTRACFGRDADDRPA], %g6
1478 brz,pt %g6, 2f
1479 nop
1480 lduw [%g6], %g0
14812:
1482#endif
1483 andn %g2, PCI_CFG_OFFSET_MASK, %g2
1484 ldub [%g3 + %g2], %g0
1485 set STRAND_IO_PROT, %g6
1486 ! strand.io_prot = 0
1487 stx %g0, [%g4 + %g6]
1488 set STRAND_IO_ERROR, %g6
1489 ! strand.io_error
1490 ldx [%g4 + %g6], %o1
1491 ! strand.io_error = 0
1492 stx %g0, [%g4 + %g6]
1493
1494 !! %g1 = Fire cookie
1495
1496 ENABLE_PCIE_RWUC_ERRORS(%g1, %g5, %g6, %g7)
1497.skip_config_put:
1498 HCALL_RET(EOK)
1499 SET_SIZE(fire_config_put)
1500
1501/*
1502 * arg0 (%g1) = Fire Cookie
1503 * arg2 (%g2) = Offset
1504 * arg3 (%g3) = size (1, 2, 4)
1505 * --------------------
1506 * ret0 = status (1 fail, 0 pass)
1507 * ret1 = data
1508 */
1509
1510 ENTRY_NP(hv_config_get)
1511
1512 !! %g1 = fire cookie (pointer)
1513 !! %g2 = offset
1514 !! %g3 = size (1 byte, 2 bytes, 4 bytes)
1515
1516 mov 1, %g5
1517 STRAND_STRUCT(%g4)
1518 set STRAND_IO_PROT, %g6
1519
1520 !! %g4 = Strand struct
1521
1522 ! strand.io_prot = 1
1523 stx %g5, [%g4 + %g6]
1524
1525 DISABLE_PCIE_RWUC_ERRORS(%g1, %g4, %g5, %g6)
1526
1527
1528 ldx [%g1 + FIRE_COOKIE_CFG], %g4
1529 cmp %g3, 1
1530 beq,a,pn %xcc,1f
1531 ldub [%g4 + %g2], %g3
1532 cmp %g3, 2
1533 beq,a,pn %xcc,1f
1534 lduha [%g4 + %g2]ASI_P_LE, %g3
1535 lduwa [%g4 + %g2]ASI_P_LE, %g3
15361:
1537 STRAND_STRUCT(%g4)
1538 set STRAND_IO_PROT, %g6
1539 ! strand.io_prot = 0
1540 stx %g0, [%g4 + %g6]
1541 set STRAND_IO_ERROR, %g6
1542 ! strand.io_error
1543 ldx [%g4 + %g6], %g5
1544 ! strand.io_error = 0
1545 stx %g0, [%g4 + %g6]
1546
1547 ENABLE_PCIE_RWUC_ERRORS(%g1, %g4, %g2, %g6)
1548 HVRET
1549 SET_SIZE(hv_config_get)
1550
1551/*
1552 * bool_t pci_config_get(uint64_t firep, uint64_t offset, int size,
1553 * uint64_t *data)
1554 */
1555 ENTRY(pci_config_get)
1556
1557 STRAND_PUSH(%g2, %g6, %g7)
1558 STRAND_PUSH(%g3, %g6, %g7)
1559 STRAND_PUSH(%g4, %g6, %g7)
1560
1561 mov %o0, %g1
1562 mov %o1, %g2
1563 mov %o2, %g3
1564
1565 ! %g1 - firep
1566 ! %g2 - Address
1567 ! %g3 - size ( 1, 2, 4)
1568
1569 HVCALL(hv_config_get)
1570
1571 stx %g3, [%o3]
1572 movrnz %g5, 0, %o0
1573 movrz %g5, 1, %o0
1574
1575 STRAND_POP(%g4, %g6)
1576 STRAND_POP(%g3, %g6)
1577 STRAND_POP(%g2, %g6)
1578
1579 retl
1580 nop
1581 SET_SIZE(pci_config_get)
1582
1583
1584
1585/*
1586 * arg0 (%o0) = Fire Cookie
1587 * arg2 (%o1) = Offset
1588 * arg3 (%o2) = size (1, 2, 4)
1589 * arg4 (%o3) = data
1590 * --------------------
1591 * ret0 (%o0)= status (1 fail, 0 pass)
1592 * %g1, %g5, %g6, %g7 Clobbered.
1593 *
1594 * bool_t pci_config_put(uint64_t firep, uint64_t offset, int size,
1595 * uint64_t data)
1596 */
1597
1598 ENTRY_NP(pci_config_put)
1599 !! %o0 = fire cookie (pointer)
1600 !! %o1 = offset
1601 !! %o2 = size (1 byte, 2 bytes, 4 bytes)
1602 !! %o3 = Data
1603 ldx [%o0 + FIRE_COOKIE_CFG], %o4
1604 add %o1, %o4, %o1
1605
1606 mov 1, %g5
1607 STRAND_STRUCT(%g6)
1608 set STRAND_IO_PROT, %g7
1609
1610 !! %g6 = Strand struct
1611
1612 ! strand.io_prot = 1
1613 stx %g5, [%g6 + %g7]
1614
1615 DISABLE_PCIE_RWUC_ERRORS(%o0, %g5, %g7, %g1)
1616
1617 cmp %o2, 1
1618 beq,a,pn %xcc,1f
1619 stb %o3, [%o1]
1620 cmp %o2, 2
1621 beq,a,pn %xcc,1f
1622 stha %o3, [%o1]ASI_P_LE
1623 stwa %o3, [%o1]ASI_P_LE
16241:
1625
1626#ifdef FIRE_ERRATUM_20_18
1627 ldx [%o0 + FIRE_COOKIE_EXTRACFGRDADDRPA], %g5
1628 brz,pt %g5, 2f
1629 nop
1630 lduw [%g5], %g0
16312:
1632#endif
1633 !! %g6 = Strand struct
1634 andn %o1, PCI_CFG_OFFSET_MASK, %g1
1635 ldub [%g1], %g0
1636
1637 set STRAND_IO_PROT, %g7
1638 ! strand.io_prot = 0
1639 stx %g0, [%g6 + %g7]
1640 set STRAND_IO_ERROR, %g7
1641 ! strand.io_error
1642 ldx [%g6 + %g7], %o1
1643 ! strand.io_error = 0
1644 stx %g0, [%g6 + %g7]
1645
1646 ENABLE_PCIE_RWUC_ERRORS(%o0, %g5, %g7, %g1)
1647
1648 movrnz %o1, 0, %o0
1649 movrz %o1, 1, %o0
1650
1651 retl
1652 nop
1653 SET_SIZE(pci_config_put)
1654
1655
1656
1657/*
1658 * arg0 (%g1) = Fire Cookie
1659 * arg2 (%g2) = Offset
1660 * arg3 (%g3) = size (1, 2, 4)
1661 * --------------------
1662 * ret0 = status (1 fail, 0 pass)
1663 * ret1 = data
1664 */
1665
1666 ENTRY_NP(hv_io_peek)
1667
1668 !! %g1 = fire cookie (pointer)
1669 !! %g2 = address
1670 !! %g3 = size (1 byte, 2 bytes, 4 bytes)
1671
1672 mov 1, %g5
1673 STRAND_STRUCT(%g4)
1674 set STRAND_IO_PROT, %g6
1675
1676 !! %g4 = Strand struct
1677
1678 ! strand.io_prot = 1
1679 stx %g5, [%g4 + %g6]
1680
1681 DISABLE_PCIE_RWUC_ERRORS(%g1, %g4, %g5, %g6)
1682
1683
1684 ldx [%g1 + FIRE_COOKIE_CFG], %g4
1685 cmp %g3, 1
1686 beq,a,pn %xcc,1f
1687 ldub [%g2], %g3
1688 cmp %g3, 2
1689 beq,a,pn %xcc,1f
1690 lduha [%g2]ASI_P_LE, %g3
1691 lduwa [%g2]ASI_P_LE, %g3
16921:
1693 STRAND_STRUCT(%g4)
1694 set STRAND_IO_PROT, %g6
1695 ! strand.io_prot = 0
1696 stx %g0, [%g4 + %g6]
1697 set STRAND_IO_ERROR, %g6
1698 ! strand.io_error
1699 ldx [%g4 + %g6], %g5
1700 ! strand.io_error = 0
1701 stx %g0, [%g4 + %g6]
1702
1703 ENABLE_PCIE_RWUC_ERRORS(%g1, %g4, %g2, %g6)
1704 HVRET
1705 SET_SIZE(hv_io_peek)
1706
1707/*
1708 * bool_t pci_io_peek(uint64_t firep, uint64_t address, int size,
1709 * uint64_t *data)
1710 */
1711 ENTRY(pci_io_peek)
1712
1713 STRAND_PUSH(%g2, %g6, %g7)
1714 STRAND_PUSH(%g3, %g6, %g7)
1715 STRAND_PUSH(%g4, %g6, %g7)
1716
1717 mov %o0, %g1
1718 mov %o1, %g2
1719 mov %o2, %g3
1720
1721 ! %g1 - firep
1722 ! %g2 - Address
1723 ! %g3 - size ( 1, 2, 4)
1724
1725 HVCALL(hv_io_peek)
1726
1727 stx %g3, [%o3]
1728 movrnz %g5, 0, %o0
1729 movrz %g5, 1, %o0
1730
1731 STRAND_POP(%g4, %g6)
1732 STRAND_POP(%g3, %g6)
1733 STRAND_POP(%g2, %g6)
1734
1735 retl
1736 nop
1737 SET_SIZE(pci_io_peek)
1738
1739
1740
1741/*
1742 * arg0 (%o0) = Fire Cookie
1743 * arg1 (%o1) = Offset
1744 * arg2 (%o2) = size (1, 2, 4)
1745 * arg3 (%o3) = data
1746 * arg4 (%o4) = PCI device
1747 * --------------------
1748 * ret0 (%o0)= status (1 fail, 0 pass)
1749 * %g1, %g5, %g6, %g7 Clobbered.
1750 *
1751 * bool_t pci_io_put(uint64_t firep, uint64_t address, int size,
1752 * uint64_t data)
1753 */
1754
1755 ENTRY_NP(pci_io_poke)
1756 !! %o0 = fire cookie (pointer)
1757 !! %o1 = Address
1758 !! %o2 = size (1 byte, 2 bytes, 4 bytes)
1759 !! %o3 = Data
1760 !! %o4 = Config space offset for device
1761
1762 STRAND_STRUCT(%g6)
1763
1764 !! %g6 = Strand struct
1765
1766 ! strand.io_prot = 1
1767 mov 1, %g5
1768 set STRAND_IO_PROT, %g7
1769 stx %g5, [%g6 + %g7]
1770
1771 DISABLE_PCIE_RWUC_ERRORS(%o0, %g5, %g7, %g1)
1772
1773 cmp %o2, 1
1774 beq,a,pn %xcc,1f
1775 stb %o3, [%o1]
1776 cmp %o2, 2
1777 beq,a,pn %xcc,1f
1778 stha %o3, [%o1]ASI_P_LE
1779 stwa %o3, [%o1]ASI_P_LE
17801:
1781
1782#ifdef FIRE_ERRATUM_20_18
1783 ldx [%o0 + FIRE_COOKIE_EXTRACFGRDADDRPA], %g5
1784 brz,pt %g5, 2f
1785 nop
1786 lduw [%g5], %g0
17872:
1788#endif
1789 ! Read from PCI config space as error barrier
1790 ldx [%o0 + FIRE_COOKIE_CFG], %g5
1791 ldub [%g5 + %o4], %g0
1792
1793 !! %g6 = Strand struct
1794
1795 set STRAND_IO_PROT, %g7
1796 ! strand.io_prot = 0
1797 stx %g0, [%g6 + %g7]
1798 set STRAND_IO_ERROR, %g7
1799 ! strand.io_error
1800 ldx [%g6 + %g7], %o1
1801 ! strand.io_error = 0
1802 stx %g0, [%g6 + %g7]
1803
1804 ENABLE_PCIE_RWUC_ERRORS(%o0, %g5, %g7, %g1)
1805
1806 movrnz %o1, 0, %o0
1807 movrz %o1, 1, %o0
1808
1809 retl
1810 nop
1811 SET_SIZE(pci_io_poke)
1812
1813/*
1814 * fire_dma_sync
1815 *
1816 * %g1 = Fire Cookie Pointer
1817 * arg0 devhandle (%o0)
1818 * arg1 r_addr (%o1)
1819 * arg2 size (%o2)
1820 * arg3 direction (%o3) (one or both of 1: for device 2: for cpu)
1821 * --
1822 * ret0 status (%o0)
1823 * ret1 #bytes synced (%o1)
1824 */
1825 ENTRY_NP(fire_dma_sync)
1826 GUEST_STRUCT(%g2)
1827 RA2PA_RANGE_CONV_UNK_SIZE(%g2, %o1, %o2, herr_noraddr, %g4, %g3)
1828 mov %o2, %o1
1829 HCALL_RET(EOK);
1830 SET_SIZE(fire_dma_sync)
1831
1832/*
1833 * fire_io_peek
1834 *
1835 * %g1 = Fire Cookie Pointer
1836 * arg0 devhandle (%o0)
1837 * arg1 r_addr (%o1)
1838 * arg2 size (%o2)
1839 * --
1840 * ret0 status (%o0)
1841 * ret1 error? (%o1)
1842 * ret2 data (%o2)
1843 */
1844 ENTRY_NP(fire_io_peek)
1845 !! %g1 = Fire Cookie
1846 GUEST_STRUCT(%g2)
1847
1848 !! %g2 = Guestp
1849 !! %o1 = ra
1850 !! %o2 = size
1851 !! %g4, %g5 = scratch
1852 RANGE_CHECK_IO(%g2, %o1, %o2, .fire_io_peek_found, herr_noraddr,
1853 %g4, %g6)
1854.fire_io_peek_found:
1855
1856 CHK_FIRE_LINK_STATUS(%g1, %g5, %g6)
1857 brz,a,pn %g5, .skip_io_peek
1858 mov 1, %o1 ! Error flag
1859
1860 mov 1, %g5
1861 STRAND_STRUCT(%g4)
1862 set STRAND_IO_PROT, %g6
1863 ! strand.io_prot = 1
1864 stx %g5, [%g4 + %g6]
1865
1866 !! %g1 = Fire cookie
1867 !! %g4 = STRAND struct
1868
1869 DISABLE_PCIE_RWUC_ERRORS(%g1, %g5, %g6, %g7)
1870
1871 cmp %o2, SZ_LONG
1872 beq,a,pn %xcc,1f
1873 ldxa [%o1]ASI_P_LE, %o2
1874 cmp %o2, SZ_WORD
1875 beq,a,pn %xcc,1f
1876 lduwa [%o1]ASI_P_LE, %o2
1877 cmp %o2, SZ_HWORD
1878 beq,a,pn %xcc,1f
1879 lduha [%o1]ASI_P_LE, %o2
1880 ldub [%o1], %o2
1881
18821: set STRAND_IO_PROT, %g6
1883 ! strand.io_prot = 0
1884 stx %g0, [%g4 + %g6]
1885 set STRAND_IO_ERROR, %g6
1886 ! strand.io_error
1887 ldx [%g4 + %g6], %o1
1888 ! strand.io_error = 0
1889 stx %g0, [%g4 + %g6]
1890
1891 !! %g1 = Fire cookie
1892
1893 ENABLE_PCIE_RWUC_ERRORS(%g1, %g5, %g6, %g7)
1894
1895.skip_io_peek:
1896 HCALL_RET(EOK)
1897 SET_SIZE(fire_io_peek)
1898
1899/*
1900 * fire_io_poke
1901 *
1902 * %g1 = Fire Cookie Pointer
1903 * arg0 devhandle (%o0)
1904 * arg1 r_addr (%o1)
1905 * arg2 size (%o2)
1906 * arg3 data (%o3)
1907 * arg4 PCI device (%o4)
1908 * --
1909 * ret0 status (%o0)
1910 * ret1 error? (%o1)
1911 */
1912 ENTRY_NP(fire_io_poke)
1913 !! %g1 = Fire Cookie
1914 ldx [%g1 + FIRE_COOKIE_CFG], %g3
1915 GUEST_STRUCT(%g2)
1916
1917 !! %g1 = Fire Cookie
1918 !! %g2 = Guestp
1919 !! %o1 = ra
1920 !! %o2 = size
1921 !! %g4, %g5 = scratch
1922 RANGE_CHECK_IO(%g2, %o1, %o2, .fire_io_poke_found, herr_noraddr,
1923 %g4, %g6)
1924.fire_io_poke_found:
1925
1926 CHK_FIRE_LINK_STATUS(%g1, %g5, %g6)
1927 brz,a,pn %g5, .skip_io_poke
1928 mov 1, %o1 ! Error flag
1929
1930 PCIDEV2FIREDEV(%o4, %g2)
1931 mov 1, %g5
1932 STRAND_STRUCT(%g4)
1933 set STRAND_IO_PROT, %g6
1934
1935 ! strand.io_prot = 1
1936 stx %g5, [%g4 + %g6]
1937
1938 !! %g1 = Fire cookie
1939 !! %g2 = PCI device BDF
1940 !! %g3 = CFG base address
1941 !! %g4 = CPU struct
1942
1943 DISABLE_PCIE_RWUC_ERRORS(%g1, %g5, %g6, %g7)
1944
1945 cmp %o2, SZ_LONG
1946 beq,a,pn %xcc,1f
1947 stxa %o3, [%o1]ASI_P_LE
1948 cmp %o2, SZ_WORD
1949 beq,a,pn %xcc,1f
1950 stwa %o3, [%o1]ASI_P_LE
1951 cmp %o2, SZ_HWORD
1952 beq,a,pn %xcc,1f
1953 stha %o3, [%o1]ASI_P_LE
1954 stb %o3, [%o1]
19551:
1956 ! Read from PCI config space
1957 ldub [%g3 + %g2], %g0
1958
1959 set STRAND_IO_PROT, %g6
1960 ! strand.io_prot = 0
1961 stx %g0, [%g4 + %g6]
1962 set STRAND_IO_ERROR, %g6
1963 ! strand.io_error
1964 ldx [%g4 + %g6], %o1
1965 ! strand.io_error = 0
1966 stx %g0, [%g4 + %g6]
1967
1968 !! %g1 = Fire cookie
1969
1970 ENABLE_PCIE_RWUC_ERRORS(%g1, %g5, %g6, %g7)
1971
1972.skip_io_poke:
1973 HCALL_RET(EOK)
1974 SET_SIZE(fire_io_poke)
1975
1976/*
1977 * fire_mondo_receive
1978 *
1979 * %g1 = Fire Cookie
1980 * %g2 = Mondo DATA0
1981 * %g3 = Mondo DATA1
1982 */
1983 ENTRY_NP(fire_mondo_receive)
1984 ba insert_device_mondo_r
1985 rd %pc, %g7
1986 retry
1987 SET_SIZE(fire_mondo_receive)
1988
1989/*
1990 * fire_msiq_conf
1991 *
1992 * %g1 = Fire Cookie Pointer
1993 * arg0 dev config pa (%o0)
1994 * arg1 MSI EQ id (%o1)
1995 * arg2 EQ base RA (%o2)
1996 * arg3 #entries (%o3)
1997 * --
1998 * ret0 status (%o0)
1999 */
2000 ENTRY_NP(fire_msiq_conf)
2001 cmp %o1, FIRE_NEQS
2002 bgeu,pn %xcc, herr_inval
2003 sethi %hi(FIRE_EQSIZE-1), %g2
2004 or %g2, %lo(FIRE_EQSIZE-1), %g2
2005 and %o2, %g2, %g2
2006 brnz %g2, herr_badalign
2007 cmp %o3, FIRE_NEQRECORDS
2008 bne herr_inval
2009
2010 /*
2011 * Verify RA range/alignment
2012 */
2013 GUEST_STRUCT(%g2)
2014 andcc %o2, 3, %g0
2015 bnz %xcc, herr_badalign
2016 .empty
2017 RA2PA_RANGE_CONV(%g2, %o2, %g0, herr_noraddr, %g7, %g6)
2018 !! %g6 paddr
2019
2020 MSIEQNUM2MSIEQ(%g1, %o1, %g4, %g3, %g2)
2021 ldx [%g1 + FIRE_COOKIE_EQSTATE], %g2
2022 REGNO2OFFSET(%o1, %g5)
2023 ldx [%g2 + %g5], %g3
2024 and %g3, 3, %g3
2025 sub %g3, 1, %g3
2026 brnz %g3, herr_inval
2027 ldx [%g1 + FIRE_COOKIE_EQHEAD], %g2
2028 ldx [%g1 + FIRE_COOKIE_EQTAIL], %g3
2029
2030 stx %g0, [%g2 + %g5]
2031 stx %g0, [%g3 + %g5]
2032 stx %g6, [%g4 + FIRE_MSIEQ_GUEST]
2033
2034 HCALL_RET(EOK)
2035 SET_SIZE(fire_msiq_conf)
2036
2037/*
2038 * fire_msiq_info
2039 *
2040 * %g1 = Fire Cookie Pointer
2041 * arg0 dev config pa (%o0)
2042 * arg1 MSI EQ id (%o1)
2043 * --
2044 * ret0 status (%o0)
2045 * ret1 ra (%o1)
2046 * ret2 #entries (%o2)
2047 */
2048 ENTRY_NP(fire_msiq_info)
2049 cmp %o1, FIRE_NEQS
2050 bgeu,pn %xcc, herr_inval
2051 .empty
2052 MSIEQNUM2MSIEQ(%g1, %o1, %g4, %g3, %g5)
2053 ldx [%g4 + FIRE_MSIEQ_GUEST], %g5
2054 set FIRE_NEQRECORDS, %o2
2055 movrz %g5, %g0, %o2
2056 brz,pn %g5, 1f
2057 GUEST_STRUCT(%g2)
2058 PA2RA_CONV(%g2, %g5, %o1, %g6, %g3) ! PA -> RA (%o1)
2059 brnz %g3, herr_inval
2060 nop
2061
20621: HCALL_RET(EOK)
2063 SET_SIZE(fire_msiq_info)
2064
2065/*
2066 * fire_msiq_getvalid
2067 *
2068 * %g1 = Fire Cookie Pointer
2069 * arg0 dev config pa (%o0)
2070 * arg1 MSI EQ id (%o1)
2071 * --
2072 * ret0 status (%o0)
2073 * ret1 EQ valid (%o1) (0: Invalid 1: Valid)
2074 */
2075 ENTRY_NP(fire_msiq_getvalid)
2076 cmp %o1, FIRE_NEQS
2077 bgeu,pn %xcc, herr_inval
2078 ldx [%g1 + FIRE_COOKIE_EQSTATE], %g2
2079 REGNO2OFFSET(%o1, %g7)
2080 ldx [%g2 + %g7], %g4
2081 and %g4, 3, %g4
2082 sub %g4, 1, %o1
2083 HCALL_RET(EOK)
2084 SET_SIZE(fire_msiq_getvalid)
2085
2086/*
2087 * fire_msiq_setvalid
2088 *
2089 * %g1 = Fire Cookie Pointer
2090 * arg0 dev config pa (%o0)
2091 * arg1 MSI EQ id (%o1)
2092 * arg2 EQ valid (%o2) (0: Invalid 1: Valid)
2093 * --
2094 * ret0 status
2095 */
2096 ENTRY_NP(fire_msiq_setvalid)
2097 cmp %o1, FIRE_NEQS
2098 bgeu,pn %xcc, herr_inval
2099 .empty
2100 MSIEQNUM2MSIEQ(%g1, %o1, %g3, %g2, %g4)
2101
2102 ldx [%g3 + FIRE_MSIEQ_GUEST], %g2 ! Guest Q base
2103 brnz %g2, 1f
2104 movrz %o2, FIRE_COOKIE_EQCTLCLR, %g3
2105 brnz %o2, herr_inval
21061: movrnz %o2, FIRE_COOKIE_EQCTLSET, %g3
2107 ldx [%g1 + %g3], %g3
2108 setx (1<<44), %g5, %g4
2109 REGNO2OFFSET(%o1, %g7)
2110 stx %g4, [%g3 + %g7]
2111 HCALL_RET(EOK)
2112 SET_SIZE(fire_msiq_setvalid)
2113
2114/*
2115 * fire_msiq_getstate
2116 *
2117 * %g1 = Fire Cookie Pointer
2118 * arg0 dev config pa (%o0)
2119 * arg1 MSI EQ id (%o1)
2120 * --
2121 * ret0 status (%o0)
2122 * ret1 EQ state (%o1) (0: Idle 1: Error)
2123 */
2124 ENTRY_NP(fire_msiq_getstate)
2125 cmp %o1, FIRE_NEQS
2126 bgeu,pn %xcc, herr_inval
2127 REGNO2OFFSET(%o1, %g4)
2128 ldx [%g1 + FIRE_COOKIE_EQSTATE], %g2
2129 ldx [%g2 + %g4], %g3
2130 and %g3, 4, %o1
2131 movrnz %o1, HVIO_MSIQSTATE_ERROR, %o1
2132 HCALL_RET(EOK)
2133 SET_SIZE(fire_msiq_getstate)
2134
2135/*
2136 * fire_msiq_setstate
2137 *
2138 * %g1 = Fire Cookie Pointer
2139 * arg0 dev config pa (%o0)
2140 * arg1 MSI EQ id (%o1)
2141 * arg2 EQ state (%o2) (0: Idle 1: Error)
2142 * --
2143 * ret0 status (%o0)
2144 */
2145 ENTRY_NP(fire_msiq_setstate)
2146 REGNO2OFFSET(%o1, %g4)
2147 cmp %o1, FIRE_NEQS
2148 bgeu,pn %xcc, herr_inval
2149 .empty
2150 /*
2151 * To change state from error to idle, we set bits 57 and 47 in the
2152 * Event Queue Control Clear Register (CCR)
2153 *
2154 * To change state from idle to error, we set bits 44 and 57 in the
2155 * Event Queue Control Set Register (CSR)
2156 */
2157 mov FIRE_COOKIE_EQCTLCLR, %g6 ! EQ CCR
2158 movrnz %o2, FIRE_COOKIE_EQCTLSET, %g6 ! EQ CSR
2159 ldx [%g1 + %g6], %g2
2160 setx (1 << FIRE_EQCCR_COVERR)|(1 << FIRE_EQCCR_E2I_SHIFT), %g5, %g3 ! set idle
2161 setx (1 << FIRE_EQCSR_ENOVERR)|(1 << FIRE_EQCSR_EN_SHIFT), %g5, %g6 ! set error
2162 movrnz %o2, %g6, %g3
2163 stx %g3, [%g2 + %g4]
2164
2165 HCALL_RET(EOK)
2166 SET_SIZE(fire_msiq_setstate)
2167
2168/*
2169 * fire_msiq_gethead
2170 *
2171 * %g1 = Fire Cookie Pointer
2172 * arg0 dev config pa (%o0)
2173 * arg1 MSI EQ id (%o1)
2174 * --
2175 * ret0 status
2176 * ret1 head index
2177 */
2178 ENTRY_NP(fire_msiq_gethead)
2179 cmp %o1, FIRE_NEQS
2180 bgeu,pn %xcc, herr_inval
2181 REGNO2OFFSET(%o1, %g4)
2182 ldx [%g1 + FIRE_COOKIE_EQHEAD], %g2
2183 ldx [%g2 + %g4], %o1
2184 sllx %o1, FIRE_EQREC_SHIFT, %o1
2185 HCALL_RET(EOK)
2186 SET_SIZE(fire_msiq_gethead)
2187
2188/*
2189 * fire_msiq_sethead
2190 *
2191 * %g1 = Fire Cookie Pointer
2192 * arg0 dev config pa (%o0)
2193 * arg1 MSI EQ id (%o1)
2194 * arg2 head offset (%o2)
2195 * --
2196 * ret0 status (%o0)
2197 */
2198 ENTRY_NP(fire_msiq_sethead)
2199 cmp %o1, FIRE_NEQS
2200 bgeu,pn %xcc, herr_inval
2201 set FIRE_EQSIZE, %g2
2202 cmp %o2, %g2
2203 bgeu,pn %xcc, herr_inval
2204 REGNO2OFFSET(%o1, %g6)
2205 ldx [%g1 + FIRE_COOKIE_EQHEAD], %g2
2206 ldx [%g2 + %g6], %g3
2207 mov %o2, %g6
2208 sllx %g3, FIRE_EQREC_SHIFT, %g3
2209 !! %g1 = FIRE COOKIE
2210 !! %g2 = EQ HEAD reg
2211 !! %g3 = Prev Head offset
2212 !! %g6 = New Head offset
2213 MSIEQNUM2MSIEQ(%g1, %o1, %g4, %g5, %g7)
2214 !! %g1 = FIRE COOKIE
2215 !! %g2 = EQ HEAD reg
2216 !! %g3 = Prev Head offset
2217 !! %g4 = struct *fire_msieq
2218 !! %g6 = New Head offset
2219 ldx [%g4 + FIRE_MSIEQ_BASE], %g5 /* HW Q base */
2220 add %g5, %g3, %g7
22211:
2222 stx %g0, [%g7 + 0x00]
2223 stx %g0, [%g7 + 0x08]
2224 stx %g0, [%g7 + 0x10]
2225 stx %g0, [%g7 + 0x18]
2226 stx %g0, [%g7 + 0x20]
2227 stx %g0, [%g7 + 0x28]
2228 stx %g0, [%g7 + 0x30]
2229 stx %g0, [%g7 + 0x38]
2230 add %g3, 0x40, %g3
2231 ldx [%g4 + FIRE_MSIEQ_EQMASK], %g7
2232 and %g3, %g7, %g3
2233 cmp %g6, %g3
2234 bne 1b
2235 add %g5, %g3, %g7
2236 REGNO2OFFSET(%o1, %g6)
2237 srlx %o2, FIRE_EQREC_SHIFT, %g3
2238 stx %g3, [%g2 + %g6]
2239 HCALL_RET(EOK)
2240 SET_SIZE(fire_msiq_sethead)
2241
2242/*
2243 * fire_msiq_gettail
2244 *
2245 * %g1 = Fire Cookie Pointer
2246 * arg0 dev config pa (%o0)
2247 * arg1 MSI EQ id (%o1)
2248 * --
2249 * ret0 status (%o0)
2250 * ret1 tail index (%o1)
2251 */
2252 ENTRY_NP(fire_msiq_gettail)
2253 cmp %o1, FIRE_NEQS
2254 bgeu,pn %xcc, herr_inval
2255 REGNO2OFFSET(%o1, %g4)
2256 ldx [%g1 + FIRE_COOKIE_EQTAIL], %g2
2257 ldx [%g2 + %g4], %o1
2258 sllx %o1, FIRE_EQREC_SHIFT, %o1
2259 HCALL_RET(EOK)
2260 SET_SIZE(fire_msiq_gettail)
2261
2262/*
2263 * fire_msi_getvalid
2264 *
2265 * %g1 = Fire Cookie Pointer
2266 * arg0 dev config pa (%o0)
2267 * arg1 MSI number (%o1)
2268 * --
2269 * ret0 status (%o0)
2270 * ret1 MSI status (%o1) (0: Invalid 1: Valid)
2271 */
2272 ENTRY_NP(fire_msi_getvalid)
2273 cmp %o1, FIRE_MSI_MASK
2274 bgu,pn %xcc, herr_inval
2275 REGNO2OFFSET(%o1, %g4)
2276 ldx [%g1 + FIRE_COOKIE_MSIMAP], %g2
2277 ldx [%g2 + %g4], %g5
2278 mov HVIO_MSI_INVALID, %o1
2279 movrlz %g5, HVIO_MSI_VALID, %o1
2280 HCALL_RET(EOK)
2281 SET_SIZE(fire_msi_getvalid)
2282
2283/*
2284 * fire_msi_setvalid
2285 *
2286 * %g1 = Fire Cookie Pointer
2287 * arg0 dev config pa (%o0)
2288 * arg1 MSI number (%o1)
2289 * arg2 MSI status (%o2) (0: Invalid 1: Valid)
2290 * --
2291 * ret0 status (%o0)
2292 */
2293 ENTRY_NP(fire_msi_setvalid)
2294 cmp %o1, FIRE_MSI_MASK
2295 bgu,pn %xcc, herr_inval
2296 REGNO2OFFSET(%o1, %g4)
2297 ldx [%g1 + FIRE_COOKIE_MSIMAP], %g2
2298 ldx [%g2 + %g4], %g5
2299 sllx %g5, 1, %g5
2300 srlx %g5, 1, %g5
2301 sllx %o2, FIRE_MSIMR_V_SHIFT, %g3
2302 or %g5, %g3, %g5
2303 stx %g5, [%g2 + %g4]
2304 HCALL_RET(EOK)
2305 SET_SIZE(fire_msi_setvalid)
2306
2307/*
2308 * fire_msi_getstate
2309 *
2310 * %g1 = Fire Cookie Pointer
2311 * arg0 dev config pa (%o0)
2312 * arg1 MSI number (%o1)
2313 * --
2314 * ret0 status (%o0)
2315 * ret1 MSI state (%o1) (0: Idle 1: Delivered)
2316 */
2317 ENTRY_NP(fire_msi_getstate)
2318 cmp %o1, FIRE_MSI_MASK
2319 bgu,pn %xcc, herr_inval
2320 REGNO2OFFSET(%o1, %g4)
2321 ldx [%g1 + FIRE_COOKIE_MSIMAP], %g2
2322 ldx [%g2 + %g4], %g5
2323 brlz,pn %g5, 0f
2324 mov HVIO_MSI_INVALID, %o1
2325 HCALL_RET(EOK)
2326
23270: srlx %g5, FIRE_MSIMR_EQWR_N_SHIFT, %o1
2328 and %o1, HVIO_MSI_VALID, %o1
2329 HCALL_RET(EOK)
2330 SET_SIZE(fire_msi_getstate)
2331
2332/*
2333 * fire_msi_setstate
2334 *
2335 * %g1 = Fire Cookie Pointer
2336 * arg0 dev config pa (%o0)
2337 * arg1 MSI number (%o1)
2338 * arg2 MSI state (%o2) (0: Idle)
2339 * --
2340 * ret0 status (%o0)
2341 */
2342 ENTRY_NP(fire_msi_setstate)
2343 cmp %o1, FIRE_MSI_MASK
2344 bgu,pn %xcc, herr_inval
2345 REGNO2OFFSET(%o1, %g4)
2346 brnz,pn %o2, herr_inval
2347 mov 1, %g5
2348 sllx %g5, FIRE_MSIMR_EQWR_N_SHIFT, %g5
2349 ldx [%g1 + FIRE_COOKIE_MSICLR], %g2
2350 stx %g5, [%g2 + %g4]
2351 HCALL_RET(EOK)
2352 SET_SIZE(fire_msi_setstate)
2353
2354/*
2355 * fire_msi_getmsiq
2356 *
2357 * %g1 = Fire Cookie Pointer
2358 * arg0 dev config pa (%o0)
2359 * arg1 MSI number (%o1)
2360 * --
2361 * ret0 status (%o0)
2362 * ret1 MSI EQ id (%o1)
2363 */
2364 ENTRY_NP(fire_msi_getmsiq)
2365 cmp %o1, FIRE_MSI_MASK
2366 bgu,pn %xcc, herr_inval
2367 REGNO2OFFSET(%o1, %g7)
2368 ldx [%g1 + FIRE_COOKIE_MSIMAP], %g2
2369 ldx [%g2 + %g7], %o1
2370 and %o1, FIRE_MSIEQNUM_MASK, %o1
2371 HCALL_RET(EOK)
2372 SET_SIZE(fire_msi_getmsiq)
2373
2374/*
2375 * fire_msi_setmsiq
2376 *
2377 * %g1 = Fire Cookie Pointer
2378 * arg0 dev config pa (%o0)
2379 * arg1 MSI number (%o1)
2380 * arg2 MSI EQ id (%o2)
2381 * arg3 MSI type (%o3) (MSI32=0 MSI64=1)
2382 * --
2383 * ret0 status (%o0)
2384 */
2385 ENTRY_NP(fire_msi_setmsiq)
2386 cmp %o1, FIRE_MSI_MASK
2387 bgu,pn %xcc, herr_inval
2388 cmp %o2, FIRE_NEQS
2389 bgeu,pn %xcc, herr_inval
2390 ldx [%g1 + FIRE_COOKIE_MSIMAP], %g2
2391 REGNO2OFFSET(%o1, %g7)
2392 ldx [%g2 + %g7], %g5
2393 andn %g5, FIRE_MSIEQNUM_MASK, %g5
2394 or %g5, %o2, %g5
2395 stx %g5, [%g2 + %g7]
2396 HCALL_RET(EOK)
2397 SET_SIZE(fire_msi_setmsiq)
2398
2399/*
2400 * fire_msi_msg_getmsiq
2401 *
2402 * %g1 = Fire Cookie Pointer
2403 * arg0 dev config pa (%o0)
2404 * arg1 MSI msg type (%o1)
2405 * --
2406 * ret0 status (%o0)
2407 * ret1 MSI EQ id (%o1)
2408 */
2409 ENTRY_NP(fire_msi_msg_getmsiq)
2410 ldx [%g1 + FIRE_COOKIE_MSGMAP], %g2
2411 cmp %o1, PCIE_CORR_MSG
2412 be,a,pn %xcc, 1f
2413 mov FIRE_CORR_OFF, %g3
2414 cmp %o1, PCIE_NONFATAL_MSG
2415 be,a,pn %xcc, 1f
2416 mov FIRE_NONFATAL_OFF, %g3
2417 cmp %o1, PCIE_FATAL_MSG
2418 be,a,pn %xcc, 1f
2419 mov FIRE_FATAL_OFF, %g3
2420 cmp %o1, PCIE_PME_MSG
2421 be,a,pn %xcc, 1f
2422 mov FIRE_PME_OFF, %g3
2423 cmp %o1, PCIE_PME_ACK_MSG
2424 be,a,pn %xcc, 1f
2425 mov FIRE_PME_ACK_OFF, %g3
2426 ba herr_inval
2427 nop
24281: ldx [%g2 + %g3], %o1
2429 and %o1, FIRE_MSIEQNUM_MASK, %o1
2430 HCALL_RET(EOK)
2431 SET_SIZE(fire_msi_msg_getmsiq)
2432
2433/*
2434 * fire_msi_msg_setmsiq
2435 *
2436 * %g1 = Fire Cookie Pointer
2437 * arg0 dev config pa (%o0)
2438 * arg1 MSI msg type (%o1)
2439 * arg2 MSI EQ id (%o2)
2440 * --
2441 * ret0 status (%o0)
2442 */
2443 ENTRY_NP(fire_msi_msg_setmsiq)
2444 cmp %o2, FIRE_NEQS
2445 bgeu,pn %xcc, herr_inval
2446 ldx [%g1 + FIRE_COOKIE_MSGMAP], %g2
2447 cmp %o1, PCIE_CORR_MSG
2448 be,a,pn %xcc, 1f
2449 mov FIRE_CORR_OFF, %g3
2450 cmp %o1, PCIE_NONFATAL_MSG
2451 be,a,pn %xcc, 1f
2452 mov FIRE_NONFATAL_OFF, %g3
2453 cmp %o1, PCIE_FATAL_MSG
2454 be,a,pn %xcc, 1f
2455 mov FIRE_FATAL_OFF, %g3
2456 cmp %o1, PCIE_PME_MSG
2457 be,a,pn %xcc, 1f
2458 mov FIRE_PME_OFF, %g3
2459 cmp %o1, PCIE_PME_ACK_MSG
2460 be,a,pn %xcc, 1f
2461 mov FIRE_PME_ACK_OFF, %g3
2462 ba herr_inval
2463 nop
24641: ldx [%g2 + %g3], %g4
2465 andn %g4, FIRE_MSIEQNUM_MASK, %g4
2466 or %g4, %o2, %g4
2467 stx %g4, [%g2 + %g3]
2468 HCALL_RET(EOK)
2469 SET_SIZE(fire_msi_msg_setmsiq)
2470
2471/*
2472 * fire_msi_msg_getvalid
2473 *
2474 * %g1 = Fire Cookie Pointer
2475 * arg0 dev config pa (%o0)
2476 * arg1 MSI msg type (%o1)
2477 * --
2478 * ret0 status (%o0)
2479 * ret1 MSI msg valid state (%o1)
2480 */
2481 ENTRY_NP(fire_msi_msg_getvalid)
2482 ldx [%g1 + FIRE_COOKIE_MSGMAP], %g2
2483 cmp %o1, PCIE_CORR_MSG
2484 be,a,pn %xcc, 1f
2485 ldx [%g2 + FIRE_CORR_OFF], %g3
2486 cmp %o1, PCIE_NONFATAL_MSG
2487 be,a,pn %xcc, 1f
2488 ldx [%g2 + FIRE_NONFATAL_OFF], %g3
2489 cmp %o1, PCIE_FATAL_MSG
2490 be,a,pn %xcc, 1f
2491 ldx [%g2 + FIRE_FATAL_OFF], %g3
2492 cmp %o1, PCIE_PME_MSG
2493 be,a,pn %xcc, 1f
2494 ldx [%g2 + FIRE_PME_OFF], %g3
2495 cmp %o1, PCIE_PME_ACK_MSG
2496 be,a,pn %xcc, 1f
2497 ldx [%g2 + FIRE_PME_ACK_OFF], %g3
2498 ba,pt %xcc, herr_inval
2499 nop
25001: movrlz %g3, HVIO_PCIE_MSG_VALID, %o1
2501 movrgez %g3, HVIO_PCIE_MSG_INVALID, %o1
2502 HCALL_RET(EOK)
2503 SET_SIZE(fire_msi_msg_getvalid)
2504
2505/*
2506 * fire_msi_msg_setvalid
2507 *
2508 * %g1 = Fire Cookie Pointer
2509 * arg0 dev config pa (%o0)
2510 * arg1 MSI msg type (%o1)
2511 * arg2 MSI msg valid state (%o2)
2512 * --
2513 * ret0 status (%o0)
2514 */
2515 ENTRY_NP(fire_msi_msg_setvalid)
2516 cmp %o2, 1
2517 bgu,pn %xcc, herr_inval
2518 ldx [%g1 + FIRE_COOKIE_MSGMAP], %g2
2519 cmp %o1, PCIE_CORR_MSG
2520 be,a,pn %xcc, 1f
2521 mov FIRE_CORR_OFF, %g3
2522 cmp %o1, PCIE_NONFATAL_MSG
2523 be,a,pn %xcc, 1f
2524 mov FIRE_NONFATAL_OFF, %g3
2525 cmp %o1, PCIE_FATAL_MSG
2526 be,a,pn %xcc, 1f
2527 mov FIRE_FATAL_OFF, %g3
2528 cmp %o1, PCIE_PME_MSG
2529 be,a,pn %xcc, 1f
2530 mov FIRE_PME_OFF, %g3
2531 cmp %o1, PCIE_PME_ACK_MSG
2532 be,a,pn %xcc, 1f
2533 mov FIRE_PME_ACK_OFF, %g3
2534 ba herr_inval
2535 nop
25361:
2537 sllx %o2, FIRE_MSGMR_V_SHIFT, %g5
2538 ldx [%g2 + %g3], %g4
2539 sllx %g4, 1, %g4
2540 srlx %g4, 1, %g4
2541 or %g4, %g5, %g4
2542 stx %g4, [%g2 + %g3]
2543 HCALL_RET(EOK)
2544 SET_SIZE(fire_msi_msg_setvalid)
2545
2546/*
2547 * fire_msi_mondo_receive
2548 *
2549 * %g1 = Fire Cookie
2550 * %g2 = Mondo DATA0
2551 * %g3 = Mondo DATA1
2552 */
2553 ENTRY_NP(fire_msi_mondo_receive)
2554 STRAND_PUSH(%g1, %g3, %g4)
2555 STRAND_PUSH(%g2, %g3, %g4)
2556 ba insert_device_mondo_r
2557 rd %pc, %g7
2558 STRAND_POP(%g2, %g3)
2559 STRAND_POP(%g1, %g3)
2560
2561 and %g2, FIRE_DEVINO_MASK, %g2
2562 sub %g2, FIRE_EQ2INO(0), %g2
2563 MSIEQNUM2MSIEQ(%g1, %g2, %g3, %g4, %g5)
2564 !! %g1 = Fire Cookie
2565 !! %g2 = MSI EQ Number
2566 !! %g3 = struct *fire_msieq
2567 REGNO2OFFSET(%g2, %g2)
2568 ldx [%g1 + FIRE_COOKIE_EQTAIL], %g5
2569 ldx [%g5 + %g2], %g7
2570 ldx [%g1 + FIRE_COOKIE_EQHEAD], %g5
2571 ldx [%g5 + %g2], %g6
2572
2573 !! %g1 = Fire COOKIE
2574 !! %g2 = MSI EQ OFFSET
2575 !! %g3 = struct fire_msieq *
2576 !! %g6 = Head
2577 !! %g7 = New Tail
2578 cmp %g6, %g7
2579 be 9f
2580 sllx %g6, FIRE_EQREC_SHIFT, %g6 /* New tail offset */
2581 sllx %g7, FIRE_EQREC_SHIFT, %g7 /* Old Tail offset */
2582
2583 ldx [%g3 + FIRE_MSIEQ_GUEST], %g2 /* Guest Q base */
2584 brz,pn %g2, 9f
2585 ldx [%g3 + FIRE_MSIEQ_BASE], %g5 /* HW Q base */
2586
2587 !! %g2 = Guest Q base
2588 !! %g3 = struct fire_msieq *
2589 !! %g5 = HW Q base
2590 !! %g6 = Old Tail
2591 !! %g7 = New Tail
2592 !! %g1 = scratch
2593 !! %g4 = scratch
2594
25951:
2596 ! Word 0 is TTTT EQW0[63:61]
2597 ldx [%g5 + %g6], %g1 ! Read Word 0 From HW
2598 stx %g1, [%g3 + FIRE_MSIEQ_WORD0]
2599
2600 srlx %g1, FIRE_EQREC_TYPE_SHIFT+5, %g4
2601 stx %g4, [%g2 + %g6] ! Store Word 0
2602 add %g6, 8, %g6
2603
2604 ldx [%g5 + %g6], %g4 ! Read Word 1 from HW
2605 stx %g4, [%g3 + FIRE_MSIEQ_WORD1]
2606
2607 stx %g0, [%g2 + %g6] ! Store Word 1 = 0
2608 add %g6, 8, %g6
2609
2610 stx %g0, [%g2 + %g6] ! Store Word 2 = 0
2611 add %g6, 8, %g6
2612
2613 stx %g0, [%g2 + %g6] ! Store Word 3 = 0
2614 add %g6, 8, %g6
2615
2616 ! Word 4 is RRRR.RRRR EQW0[31:16]
2617 sllx %g1, 64-(MSIEQ_RID_SHIFT+MSIEQ_RID_SIZE_BITS), %g4
2618 srlx %g4, 64-MSIEQ_RID_SHIFT, %g4
2619
2620 stx %g4, [%g2 + %g6] ! Store Word 4
2621 add %g6, 8, %g6
2622
2623 ! Word 5 is MSI address EQW1[63:0]
2624 ldx [%g3 + FIRE_MSIEQ_WORD1], %g4
2625 stx %g4, [%g2 + %g6] ! Store Word 5
2626 add %g6, 8, %g6
2627
2628 ! Word 6 is MSI Data EQW0[15:0]
2629 sllx %g1, 1, %g4
2630 brgz,pt %g4, 2f
2631 sllx %g1, 64-MSIEQ_DATA_SIZE_BITS, %g4
2632 ! MSI
2633 srlx %g4, 64-MSIEQ_DATA_SIZE_BITS, %g4
2634 stx %g4, [%g2 + %g6] ! Store Word 6
2635 ba 3f
2636 add %g6, 8, %g6
2637
26382: ! MSG
2639 !! %g1 = HW Word 0
2640
2641 ! Extract GGGG.GGGG EQW0[31:16] -> W6[47:32]
2642 srlx %g1, MSIEQ_TID_SHIFT, %g4
2643 sllx %g4, 64-MSIEQ_TID_SIZE_BITS, %g4
2644 srlx %g4, 64-(MSIEQ_TID_SIZE_BITS+VPCI_MSIEQ_TID_SHIFT), %g4
2645
2646 ldx [%g3 + FIRE_MSIEQ_WORD0], %g1
2647
2648 ! Extract CCC field EQW0[58:56] -> W6[18:16]
2649 sllx %g1, 64-(MSIEQ_MSG_RT_CODE_SHIFT+MSIEQ_MSG_RT_CODE_SIZE_BITS), %g1
2650 srlx %g1, 64-MSIEQ_MSG_RT_CODE_SIZE_BITS, %g1
2651 sllx %g1, VPCI_MSIEQ_MSG_RT_CODE_SHIFT, %g1
2652 or %g1, %g4, %g4
2653
2654 ldx [%g3 + FIRE_MSIEQ_WORD0], %g1
2655
2656 ! Extract MMMM.MMMM field EQW0[7:0] -> W6[7:0]
2657 sllx %g1, 64-MSIEQ_MSG_CODE_SIZE_BITS, %g1
2658 srlx %g1, 64-MSIEQ_MSG_CODE_SIZE_BITS, %g1
2659 or %g1, %g4, %g4
2660 stx %g4, [%g2 + %g6] ! Store Word 6
2661 add %g6, 8, %g6
26623:
2663 stx %g0, [%g2 + %g6] ! Store Word 7
2664 add %g6, 8, %g6
2665
2666 ldx [%g3 + FIRE_MSIEQ_EQMASK], %g4
2667 and %g6, %g4, %g6
2668 cmp %g6, %g7
2669 bne 1b
2670 nop
26719:
2672 retry
2673 SET_SIZE(fire_msi_mondo_receive)
2674
2675 DATA_GLOBAL(fire_perf_regs_table)
2676 ! Registers 0 - 2
2677 .xword FIRE_JBC_PERF_CNTRL, 0x000000000000ffff ! Read Offset & Mask
2678 .xword FIRE_JBC_PERF_CNTRL, 0x000000000000ffff ! Write Offset & Mask
2679 .xword FIRE_JBC_PERF_CNT0, 0xffffffffffffffff
2680 .xword FIRE_JBC_PERF_CNT0, 0xffffffffffffffff
2681 .xword FIRE_JBC_PERF_CNT1, 0xffffffffffffffff
2682 .xword FIRE_JBC_PERF_CNT1, 0xffffffffffffffff
2683 ! Registers 3 - 5
2684 .xword FIRE_DLC_IMU_ICS_IMU_PERF_CNTRL, 0x000000000000ffff
2685 .xword FIRE_DLC_IMU_ICS_IMU_PERF_CNTRL, 0x000000000000ffff
2686 .xword FIRE_DLC_IMU_ICS_IMU_PERF_CNT0, 0xffffffffffffffff
2687 .xword FIRE_DLC_IMU_ICS_IMU_PERF_CNT0, 0xffffffffffffffff
2688 .xword FIRE_DLC_IMU_ICS_IMU_PERF_CNT1, 0xffffffffffffffff
2689 .xword FIRE_DLC_IMU_ICS_IMU_PERF_CNT1, 0xffffffffffffffff
2690 ! Registers 6 - 8
2691 .xword FIRE_DLC_MMU_PRFC, 0x000000000000ffff
2692 .xword FIRE_DLC_MMU_PRFC, 0x000000000000ffff
2693 .xword FIRE_DLC_MMU_PRF0, 0xffffffffffffffff
2694 .xword FIRE_DLC_MMU_PRF0, 0xffffffffffffffff
2695 .xword FIRE_DLC_MMU_PRF1, 0xffffffffffffffff
2696 .xword FIRE_DLC_MMU_PRF1, 0xffffffffffffffff
2697 ! Registers 9 - 12
2698 .xword FIRE_PLC_TLU_CTB_TLR_TLU_PRFC, 0x000000000003ffff
2699 .xword FIRE_PLC_TLU_CTB_TLR_TLU_PRFC, 0x000000000003ffff
2700 .xword FIRE_PLC_TLU_CTB_TLR_TLU_PRF0, 0xffffffffffffffff
2701 .xword FIRE_PLC_TLU_CTB_TLR_TLU_PRF0, 0xffffffffffffffff
2702 .xword FIRE_PLC_TLU_CTB_TLR_TLU_PRF1, 0xffffffffffffffff
2703 .xword FIRE_PLC_TLU_CTB_TLR_TLU_PRF1, 0xffffffffffffffff
2704 .xword FIRE_PLC_TLU_CTB_TLR_TLU_PRF2, 0x00000000ffffffff
2705 .xword FIRE_PLC_TLU_CTB_TLR_TLU_PRF2, 0x00000000ffffffff
2706 ! Registers 13 - 15
2707 .xword FIRE_PLC_TLU_CTB_LPR_PCIE_LPU_LINK_PERF_CNTR1_SEL, 0xffffffff
2708 .xword FIRE_PLC_TLU_CTB_LPR_PCIE_LPU_LINK_PERF_CNTR1_SEL, 0xffffffff
2709 .xword FIRE_PLC_TLU_CTB_LPR_PCIE_LPU_LINK_PERF_CNTR1, 0xffffffff
2710 .xword FIRE_PLC_TLU_CTB_LPR_PCIE_LPU_LINK_PERF_CNTR1_TEST, 0xffffffff
2711 .xword FIRE_PLC_TLU_CTB_LPR_PCIE_LPU_LINK_PERF_CNTR2, 0xffffffff
2712 .xword FIRE_PLC_TLU_CTB_LPR_PCIE_LPU_LINK_PERF_CNTR2_TEST, 0xffffffff
2713 SET_SIZE(fire_perf_regs_table)
2714
2715/*
2716 * Each register entry is 0x20 bytes
2717 */
2718#define FIRE_REGID2OFFSET(id, offset) sllx id, 5, offset
2719#define FIRE_PERF_READ_ADR 0
2720#define FIRE_PERF_READ_MASK 8
2721#define FIRE_PERF_WRITE_ADR 0x10
2722#define FIRE_PERF_WRITE_MASK 0x18
2723
2724/*
2725 * fire_get_perf_reg
2726 *
2727 * %g1 = Fire Cookie Pointer
2728 * arg0 dev config pa (%o0)
2729 * arg1 perf reg ID (%o1)
2730 * --
2731 * ret0 status (%o0)
2732 * ret1 value (%o1)
2733 */
2734 ENTRY_NP(fire_get_perf_reg)
2735 cmp %o1, FIRE_NPERFREGS
2736 bgeu,pn %xcc, herr_inval
2737 mov 1, %g3
2738 sllx %g3, %o1, %g3
2739 ldx [%g1 + FIRE_COOKIE_PERFREGS], %g2
2740 and %g2, %g3, %g3
2741 brz,pn %g3, herr_inval
2742 mov FIRE_COOKIE_JBUS, %g2
2743 cmp %g3, FIRE_DLC_IMU_ICS_IMU_PERF_CNTRL_MASK
2744 movgeu %xcc, FIRE_COOKIE_PCIE, %g2
2745 ldx [%g1 + %g2], %g2
2746
2747 !! %g1 = Fire cookie pointer
2748 !! %g2 = Fire base PA
2749 ROOT_STRUCT(%g5)
2750 setx fire_perf_regs_table, %g3, %g4
2751 ldx [%g5 + CONFIG_RELOC], %g3
2752 sub %g4, %g3, %g4
2753
2754 !! %g1 = Fire cookie pointer
2755 !! %g2 = Fire base PA
2756 !! %g4 = Performance regs table
2757 FIRE_REGID2OFFSET(%o1, %g3)
2758 add %g3, %g4, %g4
2759 ldx [%g4 + FIRE_PERF_READ_ADR], %g3
2760 ldx [%g4 + FIRE_PERF_READ_MASK], %g4
2761
2762 !! %g1 = Fire cookie pointer
2763 !! %g2 = Fire base PA
2764 !! %g3 = Perf reg offset
2765 !! %g4 = Perf reg mask
2766 ldx [%g2 + %g3], %o1
2767 and %o1, %g4, %o1
2768 HCALL_RET(EOK)
2769 SET_SIZE(fire_get_perf_reg)
2770
2771/*
2772 * fire_set_perf_reg
2773 *
2774 * %g1 = Fire Cookie Pointer
2775 * arg0 dev config pa (%o0)
2776 * arg1 perf reg ID (%o1)
2777 * arg2 value (%o2)
2778 * --
2779 * ret0 status (%o0)
2780 */
2781 ENTRY_NP(fire_set_perf_reg)
2782 cmp %o1, FIRE_NPERFREGS
2783 bgeu,pn %xcc, herr_inval
2784 mov 1, %g3
2785 sllx %g3, %o1, %g3
2786 ldx [%g1 + FIRE_COOKIE_PERFREGS], %g2
2787 and %g2, %g3, %g3
2788 brz,pn %g3, herr_inval
2789 mov FIRE_COOKIE_JBUS, %g2
2790 cmp %g3, FIRE_DLC_IMU_ICS_IMU_PERF_CNTRL_MASK
2791 movgeu %xcc, FIRE_COOKIE_PCIE, %g2
2792 ldx [%g1 + %g2], %g2
2793
2794 !! %g1 = Fire cookie pointer
2795 !! %g2 = Fire base PA
2796 ROOT_STRUCT(%g5)
2797 setx fire_perf_regs_table, %g3, %g4
2798 ldx [%g5 + CONFIG_RELOC], %g3
2799 sub %g4, %g3, %g4
2800
2801 !! %g1 = Fire cookie pointer
2802 !! %g2 = Fire base PA
2803 !! %g4 = Performance regs table
2804 FIRE_REGID2OFFSET(%o1, %g3)
2805 add %g3, %g4, %g4
2806 ldx [%g4 + FIRE_PERF_WRITE_ADR], %g3
2807 ldx [%g4 + FIRE_PERF_WRITE_MASK], %g4
2808
2809 !! %g1 = Fire cookie pointer
2810 !! %g2 = Fire base PA
2811 !! %g3 = Perf reg offset
2812 !! %g4 = Perf reg mask
2813 and %o2, %g4, %g5
2814 stx %g5, [%g2 + %g3]
2815 HCALL_RET(EOK)
2816 SET_SIZE(fire_set_perf_reg)
2817
2818/*
2819 * fire_intr_redistribution
2820 *
2821 * %g1 - this cpu id
2822 * %g2 - tgt cpu id
2823 *
2824 * Need to invalidate all of the virtual intrs that are
2825 * mapped to the cpu passed in %g1
2826 *
2827 * Need to retarget the 3 HW intrs hv controls that are
2828 * mapped to the cpu passed in %g1 to cpu in %g2
2829 */
2830 ENTRY_NP(fire_intr_redistribution)
2831 CPU_PUSH(%g7, %g3, %g4, %g5)
2832
2833 mov %g1, %g3 ! save cpuid
2834 GUEST_STRUCT(%g4)
2835 mov FIRE_A_AID, %g1
2836 DEVINST2INDEX(%g4, %g1, %g1, %g5, .fire_intr_redis_fail)
2837 DEVINST2COOKIE(%g4, %g1, %g1, %g5, .fire_intr_redis_fail)
2838
2839 ! %g1 - fire cookie
2840 ! %g3 - this cpu
2841 HVCALL(_fire_intr_redistribution)
2842
2843 mov FIRE_B_AID, %g1
2844 GUEST_STRUCT(%g4)
2845 DEVINST2INDEX(%g4, %g1, %g1, %g5, .fire_intr_redis_fail)
2846 DEVINST2COOKIE(%g4, %g1, %g1, %g5, .fire_intr_redis_fail)
2847
2848 ! %g1 - fire cookie
2849 ! %g3 - this cpu
2850 HVCALL(_fire_intr_redistribution)
2851
2852.fire_intr_redis_fail:
2853 mov %g3, %g1 ! restore cpuid
2854 CPU_POP(%g7, %g3, %g4, %g5)
2855 HVRET
2856 SET_SIZE(fire_intr_redistribution)
2857
2858
2859
2860
2861/*
2862 * _fire_intr_redistribution
2863 *
2864 * %g1 - Fire cookie
2865 * %g3 - this cpu
2866 */
2867 ENTRY_NP(_fire_intr_redistribution)
2868 CPU_PUSH(%g7, %g4, %g5, %g6)
2869
2870 ! %g1 - fire cookie ptr
2871 lduh [%g1 + FIRE_COOKIE_INOMAX], %g2 ! loop counter
2872 dec %g2 ! INOMAX - 1
2873
2874._fire_intr_redis_loop:
2875 cmp %g2, PCIE_ERR_INO
2876 be %xcc, .fire_intr_redis_continue ! fire errors handle separate
2877 nop
2878
2879 cmp %g2, JBC_ERR_INO
2880 be %xcc, .fire_intr_redis_continue ! fire errors handle separate
2881 nop
2882
2883 ldx [%g1 + FIRE_COOKIE_INTMAP], %g5
2884 REGNO2OFFSET(%g2, %g4)
2885 ldx [%g5 + %g4], %g4
2886
2887 ! Extract cpuid
2888 srlx %g4, JPID_SHIFT, %g7
2889 and %g7, JPID_MASK, %g7
2890
2891 ! %g7 - jpid
2892 ! compare with this cpu, if match, set to idle
2893 cmp %g3, %g7
2894 bne,pt %xcc, .fire_intr_redis_continue
2895 nop
2896
2897 ! save cpuid since call clobbers it
2898 CPU_PUSH(%g3, %g4, %g5, %g6)
2899 CPU_PUSH(%g2, %g4, %g5, %g6)
2900 mov INTR_DISABLED, %g3 ! Invalid
2901
2902 ! %g1 = Fire Cookie
2903 ! %g2 = device ino
2904 ! %g3 = Idle
2905 HVCALL(_fire_intr_setvalid)
2906
2907 CPU_POP(%g2, %g4, %g5, %g6)
2908 CPU_POP(%g3, %g4, %g5, %g6)
2909
2910.fire_intr_redis_continue:
2911 deccc %g2
2912 bgeu,pt %xcc, ._fire_intr_redis_loop
2913 nop
2914
2915.fire_redis_done:
2916
2917 CPU_POP(%g7, %g4, %g5, %g6)
2918 HVRET
2919 SET_SIZE(_fire_intr_redistribution)
2920
2921
2922/*
2923 * FIRE_MSIQ_UNCONFIGURE
2924 *
2925 * fire - (preserved) Fire Cookie Pointer
2926 * msieq_id - (preserved) MSI EQ id
2927 *
2928 */
2929#define FIRE_MSIQ_UNCONFIGURE(fire, msieq_id, scr1, scr2, scr3, scr4) \
2930 .pushlocals ;\
2931 cmp msieq_id, FIRE_NEQS ;\
2932 bgeu,pn %xcc, 0f ;\
2933 MSIEQNUM2MSIEQ(fire, msieq_id, scr3, scr2, scr1) ;\
2934 REGNO2OFFSET(msieq_id, scr4) ;\
2935 ldx [fire + FIRE_COOKIE_EQHEAD], scr1 ;\
2936 ldx [fire + FIRE_COOKIE_EQTAIL], scr2 ;\
2937 stx %g0, [scr1 + scr4] ;\
2938 stx %g0, [scr2 + scr4] ;\
2939 stx %g0, [scr3 + FIRE_MSIEQ_GUEST] ;\
29400: ;\
2941 .poplocals
2942
2943
2944/*
2945 * FIRE_MSIQ_INVALIDATE
2946 *
2947 * fire - (preserved) Fire Cookie Pointer
2948 * msieq_id - (preserved) MSI EQ id
2949 *
2950 */
2951#define FIRE_MSIQ_INVALIDATE(fire, msieq_id, scr1, scr2, scr3, scr4) \
2952 .pushlocals ;\
2953 cmp msieq_id, FIRE_NEQS ;\
2954 bgeu,pn %xcc, 0f ;\
2955 nop ;\
2956 ldx [fire + FIRE_COOKIE_EQCTLCLR], scr1 ;\
2957 /* 44=disable, 47=e2i 57=coverr */ ;\
2958 setx (1<<44)|(1<<47)|(1<<57), scr3, scr2 ;\
2959 REGNO2OFFSET(msieq_id, scr4) ;\
2960 stx scr2, [scr1 + scr4] ;\
29610: ;\
2962 .poplocals
2963
2964
2965/*
2966 * FIRE_MSI_INVALIDATE - Invalidate the MSI mappings and then clear
2967 * the MSI status (mark as "idle")
2968 *
2969 * fire - (preserved) Fire Cookie Pointer
2970 * msi_num - (preserved) MSI number (%o1)
2971 *
2972 */
2973#define FIRE_MSI_INVALIDATE(fire, msi_num, scr1, scr2, scr3) \
2974 .pushlocals ;\
2975 cmp msi_num, FIRE_MSI_MASK ;\
2976 bgu,pn %xcc, 0f ;\
2977 REGNO2OFFSET(msi_num, scr2) ;\
2978 ldx [fire + FIRE_COOKIE_MSIMAP], scr1 ;\
2979 ldx [scr1 + scr2], scr3 ;\
2980 /* clear both bits 62 and 63 in the map reg */ ;\
2981 /* valid and ok to write (pending MSI) bit */ ;\
2982 sllx scr3, 2, scr3 ;\
2983 srlx scr3, 2, scr3 ;\
2984 stx scr3, [scr1 + scr2] ;\
2985 mov 1, scr3 /* now mark status as "idle" */ ;\
2986 sllx scr3, FIRE_MSIMR_EQWR_N_SHIFT, scr3 ;\
2987 ldx [fire + FIRE_COOKIE_MSICLR], scr1 ;\
2988 stx scr3, [scr1 + scr2] ;\
29890: ;\
2990 .poplocals
2991
2992
2993/*
2994 * FIRE_MSI_MSG_INVALIDATE
2995 *
2996 * fire - (preserved) Fire Cookie Pointer
2997 * msg_offset - (preserved) message offset such as FIRE_CORR_OFF,
2998 * FIRE_NONFATAL_OFF, etc. (reg or contant)
2999 *
3000 */
3001#define FIRE_MSI_MSG_INVALIDATE(fire, msg_offset, scr1, scr2) \
3002 ldx [fire + FIRE_COOKIE_MSGMAP], scr1 ;\
3003 ldx [scr1 + msg_offset], scr2 ;\
3004 sllx scr2, 1, scr2 ;\
3005 srlx scr2, 1, scr2 ;\
3006 stx scr2, [scr1 + msg_offset]
3007
3008
3009#define FIRE_INVALIDATE_INTX(fire, intx_off, scr1, scr2) \
3010 ldx [fire + FIRE_COOKIE_PCIE], scr1 ;\
3011 set intx_off, scr2 ;\
3012 add scr1, scr2, scr1 ;\
3013 set 1, scr2 ;\
3014 stx scr2, [scr1]
3015
3016
3017
3018/*
3019 * fire_leaf_soft_reset
3020 *
3021 * %g1 - Fire cookie (preserved)
3022 * %g2 - root complex (0=A, 1=B)
3023 * %g7 - return address
3024 *
3025 * clobbers %g2-%g6
3026 */
3027 ENTRY_NP(fire_leaf_soft_reset)
3028
3029 !
3030 ! Put STRAND in protected mode
3031 !
3032 STRAND_STRUCT(%g4)
3033 mov 1, %g5
3034 set STRAND_IO_PROT, %g6
3035 stx %g5, [%g4 + %g6]
3036 membar #Sync
3037
3038 !
3039 ! Disable errors
3040 !
3041 DISABLE_PCIE_RWUC_ERRORS(%g1, %g4, %g5, %g6)
3042 membar #Sync
3043
3044 !! %g1 fire struct
3045 !! %g2 PCI bus (0=A, 1=B)
3046
3047 !
3048 ! Destroy the iommu mappings
3049 !
3050 FIRE_IOMMU_FLUSH(%g1, %g2, %g4, %g5, %g6)
3051 membar #Sync
3052
3053 !
3054 ! Invalidate any pending legacy (level) interrupts
3055 ! that were previously signalled from switches we just reset
3056 !
3057
3058 FIRE_INVALIDATE_INTX(%g1, FIRE_DLC_IMU_RDS_INTX_INT_A_INT_CLR_REG,
3059 %g2, %g4)
3060 FIRE_INVALIDATE_INTX(%g1, FIRE_DLC_IMU_RDS_INTX_INT_B_INT_CLR_REG,
3061 %g2, %g4)
3062 FIRE_INVALIDATE_INTX(%g1, FIRE_DLC_IMU_RDS_INTX_INT_C_INT_CLR_REG,
3063 %g2, %g4)
3064 FIRE_INVALIDATE_INTX(%g1, FIRE_DLC_IMU_RDS_INTX_INT_D_INT_CLR_REG,
3065 %g2, %g4)
3066
3067 !
3068 ! invalidate all MSIs
3069 !
3070 set FIRE_MAX_MSIS - 1, %g2
30711: FIRE_MSI_INVALIDATE(%g1, %g2, %g6, %g4, %g5)
3072 brgz,pt %g2, 1b
3073 dec %g2
3074 membar #Sync
3075
3076 !
3077 ! invalidate all MSI Messages
3078 !
3079 FIRE_MSI_MSG_INVALIDATE(%g1, FIRE_CORR_OFF, %g5, %g4)
3080 FIRE_MSI_MSG_INVALIDATE(%g1, FIRE_NONFATAL_OFF, %g5, %g4)
3081 FIRE_MSI_MSG_INVALIDATE(%g1, FIRE_FATAL_OFF, %g5, %g4)
3082 FIRE_MSI_MSG_INVALIDATE(%g1, FIRE_PME_OFF, %g5, %g4)
3083 FIRE_MSI_MSG_INVALIDATE(%g1, FIRE_PME_ACK_OFF, %g5, %g4)
3084
3085 !
3086 ! invalidate all interrupts
3087 !
3088
3089 ! invalidate inos 63 and 62, special case ones not set with
3090 ! _fire_intr_setvalid
3091 ldx [%g1 + FIRE_COOKIE_VIRTUAL_INTMAP], %g2
3092 add %g2, PCIE_ERR_MONDO_OFFSET, %g2
3093 mov 0, %g3 ! devid 0
3094 add %g3, %g2, %g2
3095 stb %g0, [%g1 + %g2]
3096
3097 ldx [%g1 + FIRE_COOKIE_VIRTUAL_INTMAP], %g2
3098 add %g2, PCIE_ERR_MONDO_OFFSET, %g2
3099 mov 1, %g3 ! devid 1
3100 add %g3, %g2, %g2
3101 stb %g0, [%g1 + %g2]
3102
3103 ldx [%g1 + FIRE_COOKIE_VIRTUAL_INTMAP], %g2
3104 add %g2, JBC_ERR_MONDO_OFFSET, %g2
3105 sth %g0, [%g1 + %g2]
3106
3107 CPU_PUSH(%g7, %g4, %g5, %g6) ! _fire_intr_setvalid clobbers all regs
3108 ! Don't invalidate inos 62 & 63 in this loop, 62 and 63 are done above
3109 set NFIREDEVINO - 3, %g2
3110 clr %g3
31111: HVCALL(_fire_intr_setvalid) ! clobbers %g4-%g6
3112 brgz,pt %g2, 1b
3113 dec %g2
3114 membar #Sync
3115 CPU_POP(%g7, %g4, %g5, %g6) ! restore clobbered value
3116
3117 !
3118 ! invalidate and unconfigure all MSI EQs
3119 !
3120 set FIRE_NEQS - 1, %g2
31211: FIRE_MSIQ_INVALIDATE(%g1, %g2, %g3, %g4, %g5, %g6)
3122 FIRE_MSIQ_UNCONFIGURE(%g1, %g2, %g3, %g4, %g5, %g6)
3123 brgz,pt %g2, 1b
3124 dec %g2
3125 membar #Sync
3126
3127 !
3128 ! re-enable errors
3129 !
3130 ENABLE_PCIE_RWUC_ERRORS(%g1, %g2, %g4, %g5)
3131 membar #Sync
3132
3133 !
3134 ! Bring STRAND out of protected mode
3135 !
3136 STRAND_STRUCT(%g4)
3137 set STRAND_IO_PROT, %g2
3138 stx %g0, [%g4 + %g2]
3139 set STRAND_IO_ERROR, %g2
3140 stx %g0, [%g4 + %g2]
3141
3142 HVRET
3143 SET_SIZE(fire_leaf_soft_reset)
3144
3145
3146 /*
3147 * Wrapper around fire_leaf_soft_reset so it can be called from C
3148 * SPARC ABI requries only that g2,g3,g4 are preserved across
3149 * function calls.
3150 * %o0 = fire cookie
3151 * %o1 = root complex (0=A, 1=B), bus number
3152 *
3153 * void c_fire_leaf_soft_reset(struct fire_cookie *, uint64 root)
3154 */
3155
3156 ENTRY(c_fire_leaf_soft_reset)
3157
3158 STRAND_PUSH(%g2, %g6, %g7)
3159 STRAND_PUSH(%g3, %g6, %g7)
3160 STRAND_PUSH(%g4, %g6, %g7)
3161
3162 mov %o0, %g1
3163 mov %o1, %g2
3164
3165 !! %g1 - fire cookie
3166 !! %g2 - root complex (0=A, 1=B)
3167 HVCALL(fire_leaf_soft_reset)
3168
3169 STRAND_POP(%g4, %g6)
3170 STRAND_POP(%g3, %g6)
3171 STRAND_POP(%g2, %g6)
3172
3173 retl
3174 nop
3175 SET_SIZE(c_fire_leaf_soft_reset)
3176
3177#ifdef DEBUG
3178! When DEBUG is defined hcall.s versions
3179! of these are labels are too far away
3180herr_nocpu: HCALL_RET(ENOCPU)
3181herr_nomap: HCALL_RET(ENOMAP)
3182herr_inval: HCALL_RET(EINVAL)
3183herr_badalign: HCALL_RET(EBADALIGN)
3184#endif
3185
3186
3187 /*
3188 * This macro brings a given fire leaf's link up
3189 *
3190 * Inputs:
3191 *
3192 * fire - (preserved) pointer to FIRE_COOKIE
3193 *
3194 * Bring up a fire link. Returns false on failure.
3195 */
3196 ENTRY(fire_link_up)
3197 /* get the base addr of RC control regs */
3198 ldx [ %o0 + FIRE_COOKIE_PCIE ], %o1
3199
3200 /* Clear Other Event Status Register LinkDown bit */
3201 setx FIRE_PLC_TLU_CTB_TLR_OE_ERR_RW1C_ALIAS, %o3, %o2
3202 ldx [ %o1 + %o2 ], %o3
3203 stx %o3, [ %o1 + %o2]
3204
3205 /* The drain bit is cleared via W1C */
3206 setx FIRE_PLC_TLU_CTB_TLR_TLU_STS, %o3, %o2
3207 ldx [ %o1 + %o2 ], %o3
3208 stx %o3, [ %o1 + %o2]
3209
3210 /* bit 8 of the TLU Control Register is */
3211 /* cleared to initiate link training */
3212 setx FIRE_PLC_TLU_CTB_TLR_TLU_CTL, %o3, %o2
3213 ldx [ %o1 + %o2 ], %o3
3214 andn %o3, 1<<8, %o3
3215 stx %o3, [ %o1 + %o2]
3216
3217 CPU_MSEC_DELAY(200, %o1, %o2, %o3)
3218
3219 ldx [ %o0 + FIRE_COOKIE_CFG ], %o1
3220 setx UPST_CFG_BASE, %o3, %o2
3221 lduwa [%o1 + %o2]ASI_P_LE, %o3 /* 16 reads are */
3222 lduwa [%o1 + %o2]ASI_P_LE, %o3 /* needed to flush */
3223 lduwa [%o1 + %o2]ASI_P_LE, %o3 /* the fifo after */
3224 lduwa [%o1 + %o2]ASI_P_LE, %o3 /* toggling the */
3225 lduwa [%o1 + %o2]ASI_P_LE, %o3 /* link. */
3226 lduwa [%o1 + %o2]ASI_P_LE, %o3
3227 lduwa [%o1 + %o2]ASI_P_LE, %o3
3228 lduwa [%o1 + %o2]ASI_P_LE, %o3
3229 lduwa [%o1 + %o2]ASI_P_LE, %o3
3230 lduwa [%o1 + %o2]ASI_P_LE, %o3
3231 lduwa [%o1 + %o2]ASI_P_LE, %o3
3232 lduwa [%o1 + %o2]ASI_P_LE, %o3
3233 lduwa [%o1 + %o2]ASI_P_LE, %o3
3234 lduwa [%o1 + %o2]ASI_P_LE, %o3
3235 lduwa [%o1 + %o2]ASI_P_LE, %o3
3236 lduwa [%o1 + %o2]ASI_P_LE, %o3
3237
3238 retl
3239 mov 1, %o0
3240 SET_SIZE(fire_link_up)
3241
3242
3243
3244
3245 /*
3246 * This function brings a given fire leaf's link down
3247 * Inputs:
3248 *
3249 * fire - (preserved) pointer to FIRE_COOKIE
3250 * Returns:
3251 * false (0) on failure.
3252 */
3253 ENTRY(fire_link_down)
3254 /* get the base addr of RC control regs */
3255 ldx [ %o0 + FIRE_COOKIE_PCIE ], %o1
3256 /* And now the actual reset code... */
3257 /* Remain in detect quiesce */
3258 setx FIRE_PLC_TLU_CTB_TLR_TLU_CTL, %o4, %o2
3259 ldx [ %o1 + %o2 ], %o3
3260 or %o3, 1<<8, %o3
3261 stx %o3, [ %o1 + %o2]
3262 /* Disable link */
3263 setx FIRE_PLC_TLU_CTB_LPR_PCIE_LPU_LTSSM_CNTL, %o4, %o2
3264 setx 0x80000401, %o4, %o3
3265 stx %o3, [ %o1 + %o2]
3266
3267 /* Wait for link to go down */
3268 setx FIRE_PLC_TLU_CTB_TLR_TLU_STS, %o4, %o2
32691:
3270 ldx [ %o1 + %o2 ], %o3
3271 andcc %o3, 0x7, %o3
3272 cmp %o3, 0x1
3273 bne,pt %xcc, 1b
3274 nop
3275
3276 retl
3277 mov 1, %o0
3278 SET_SIZE(fire_link_down)
3279
3280
3281
3282
3283 /*
3284 * Check and see if a fire link is up. Returns true on
3285 * success, false on failure.
3286 */
3287 ENTRY(is_fire_port_link_up)
3288 ldx [ %o0 + FIRE_COOKIE_PCIE ], %o1
3289 setx FIRE_PLC_TLU_CTB_TLR_TLU_STS, %o3, %o2
3290 ldx [ %o1 + %o2 ], %o3
3291 and %o3, 0x7, %o3
3292 cmp %o3, 0x4
3293 mov %g0, %o0
3294 move %xcc, 1, %o0
3295 retl
3296 nop
3297 SET_SIZE(is_fire_port_link_up)
3298
3299#endif /* CONFIG_FIRE */