Commit | Line | Data |
---|---|---|
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 | ||
257 | 1: | |
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] | |
265 | 3: | |
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 | |
276 | 1: | |
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 | |
302 | 4: | |
303 | #endif | |
304 | add %g3, 16, %g3 | |
305 | stx %g2, [%g4 + %g6] | |
306 | ba 1b | |
307 | stx %g2, [%g5 + %g6] | |
308 | 2: | |
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] | |
414 | 3: | |
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 | |
438 | 1: | |
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 | |
469 | 1: | |
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 | |
485 | 1: | |
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 | |
516 | 1: | |
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 | |
687 | 0: | |
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 | |
737 | 0: PLX_TRAINING_ERROR_nz(2) ! port 2 | |
738 | bnz,a,pt %xcc, 0f | |
739 | bset PLX_HACK_STATUS_PORT2, %o0 | |
740 | 0: PLX_TRAINING_ERROR_nz(8) ! port 8 | |
741 | bnz,a,pt %xcc, 0f | |
742 | bset PLX_HACK_STATUS_PORT8, %o0 | |
743 | 0: PLX_TRAINING_ERROR_nz(9) ! port 9 | |
744 | bnz,a,pt %xcc, 0f | |
745 | bset PLX_HACK_STATUS_PORT9, %o0 | |
746 | 0: | |
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 | |
1280 | 0: | |
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 | ||
1403 | 1: | |
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] | |
1475 | 1: | |
1476 | #ifdef FIRE_ERRATUM_20_18 | |
1477 | ldx [%g1 + FIRE_COOKIE_EXTRACFGRDADDRPA], %g6 | |
1478 | brz,pt %g6, 2f | |
1479 | nop | |
1480 | lduw [%g6], %g0 | |
1481 | 2: | |
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 | |
1536 | 1: | |
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 | |
1624 | 1: | |
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 | |
1631 | 2: | |
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 | |
1692 | 1: | |
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 | |
1780 | 1: | |
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 | |
1787 | 2: | |
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 | ||
1882 | 1: 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] | |
1955 | 1: | |
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 | ||
2062 | 1: 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 | |
2106 | 1: 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 | |
2221 | 1: | |
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 | ||
2327 | 0: 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 | |
2428 | 1: 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 | |
2464 | 1: 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 | |
2500 | 1: 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 | |
2536 | 1: | |
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 | ||
2595 | 1: | |
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 | ||
2638 | 2: ! 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 | |
2662 | 3: | |
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 | |
2671 | 9: | |
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] ;\ | |
2940 | 0: ;\ | |
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] ;\ | |
2961 | 0: ;\ | |
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] ;\ | |
2989 | 0: ;\ | |
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 | |
3071 | 1: 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 | |
3111 | 1: 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 | |
3121 | 1: 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 | |
3180 | herr_nocpu: HCALL_RET(ENOCPU) | |
3181 | herr_nomap: HCALL_RET(ENOMAP) | |
3182 | herr_inval: HCALL_RET(EINVAL) | |
3183 | herr_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 | |
3269 | 1: | |
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 */ |