Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: niu_txcintr_utils.vr | |
4 | // Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved | |
5 | // 4150 Network Circle, Santa Clara, California 95054, U.S.A. | |
6 | // | |
7 | // * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
8 | // | |
9 | // This program is free software; you can redistribute it and/or modify | |
10 | // it under the terms of the GNU General Public License as published by | |
11 | // the Free Software Foundation; version 2 of the License. | |
12 | // | |
13 | // This program is distributed in the hope that it will be useful, | |
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | // GNU General Public License for more details. | |
17 | // | |
18 | // You should have received a copy of the GNU General Public License | |
19 | // along with this program; if not, write to the Free Software | |
20 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 | // | |
22 | // For the avoidance of doubt, and except that if any non-GPL license | |
23 | // choice is available it will apply instead, Sun elects to use only | |
24 | // the General Public License version 2 (GPLv2) at this time for any | |
25 | // software where a choice of GPL license versions is made | |
26 | // available with the language indicating that GPLv2 or any later version | |
27 | // may be used, or where a choice of which version of the GPL is applied is | |
28 | // otherwise unspecified. | |
29 | // | |
30 | // Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
31 | // CA 95054 USA or visit www.sun.com if you need additional information or | |
32 | // have any questions. | |
33 | // | |
34 | // ========== Copyright Header End ============================================ | |
35 | #include <vera_defines.vrh> | |
36 | ||
37 | #include "niu_tx_descp.vrh" | |
38 | ||
39 | #include "niu_int_dev.vrh" | |
40 | #include "niu_int_mgr.vrh" | |
41 | extern niu_gen_pio gen_pio_drv; | |
42 | #include "txc_memory_map.vri" | |
43 | ||
44 | #include "cMesg.vrh" | |
45 | ||
46 | extern Mesg be_msg; | |
47 | #include "tx_test_class_defines.vri" | |
48 | ||
49 | ||
50 | ||
51 | ||
52 | class CNiuIntrDevTxc extends CNiuIntrDev { | |
53 | ||
54 | bit [63:0] rd_data; | |
55 | // bit [63:0] wr_data; | |
56 | bit [3:0] ports_active; | |
57 | integer error_injection_type[4]; | |
58 | integer clear_pending_flag[4]; | |
59 | integer done=0; | |
60 | integer sem_id = -1; | |
61 | integer expect_error_interrupt[4]; | |
62 | ||
63 | task new(bit[3:0] p, integer dev_id) { | |
64 | integer i; | |
65 | super.new(dev_id); | |
66 | SetErrId(7);// bit 7 in sys error stat | |
67 | ports_active = p; | |
68 | for(i=0;i<4;i++) clear_pending_flag[i] = 0; | |
69 | for(i=0;i<4;i++) expect_error_interrupt[i] = 0; | |
70 | sem_id = alloc(SEMAPHORE, 0, 1, 1); | |
71 | } | |
72 | function integer isr( ( bit[1:0] ldf_flags = 0) ); | |
73 | task unmask_intrs(bit [3:0] p); | |
74 | task setPortIntMask(integer port_id); | |
75 | task ReEnablePortInt(integer port_id); | |
76 | task ClearPortInt(integer port_id); | |
77 | function bit CheckPortIntStat(integer port_id); | |
78 | task InjectTxcFifoError(bit[3:0] p); | |
79 | task decode_txc_err_events(bit[5:0] data ,integer port_id) ; | |
80 | task checkPendingStatus() ; | |
81 | ||
82 | ||
83 | } | |
84 | ||
85 | task CNiuIntrDevTxc::InjectTxcFifoError( bit[3:0] p) { | |
86 | ||
87 | shadow integer pid; | |
88 | for(pid = 0;pid<2;pid++) { | |
89 | if(p[pid]) { | |
90 | fork { | |
91 | while(!done) { | |
92 | // Inject Error here | |
93 | ReEnablePortInt(pid); | |
94 | clear_pending_flag[pid] = 1; | |
95 | // Wait for clear from interrupt | |
96 | while(clear_pending_flag[pid]) repeat(500)@(posedge CLOCK); | |
97 | } // end while | |
98 | } join none // endfork | |
99 | }// endif | |
100 | }// endfor | |
101 | } | |
102 | task CNiuIntrDevTxc::unmask_intrs(bit [3:0] p) { | |
103 | integer i; | |
104 | for(i=0;i<4;i++) { | |
105 | if(p[i]){ | |
106 | setPortIntMask(i); | |
107 | } | |
108 | } | |
109 | } | |
110 | task CNiuIntrDevTxc::setPortIntMask(integer port_id) { | |
111 | ||
112 | bit [63:0] address; | |
113 | bit [63:0] data; | |
114 | bit [63:0] wdata; | |
115 | address = TXC_FZC_BASE + TXC_INT_MASK; | |
116 | ||
117 | gen_pio_drv.pio_rd(address, data); | |
118 | wdata = (6'h3f) <<(8*port_id); | |
119 | wdata = wdata ^32'hffffffff; | |
120 | /* read Modify bits based upon port id*/ | |
121 | data = data & wdata; | |
122 | gen_pio_drv.pio_wr(address, data); | |
123 | } | |
124 | ||
125 | function bit CNiuIntrDevTxc::CheckPortIntStat(integer port_id) { | |
126 | // read status of the port | |
127 | // return 1 is any of the bits are set | |
128 | bit [63:0] address; | |
129 | bit [63:0] r_data; | |
130 | integer interrupts_set; | |
131 | ||
132 | address = TXC_FZC_BASE + TXC_INT_STAT; | |
133 | gen_pio_drv.pio_rd(address,r_data); | |
134 | if((r_data >> (port_id*8)) & 6'h3f ) { | |
135 | interrupts_set = 1; | |
136 | decode_txc_err_events( ( (r_data >> (port_id*8)) & 6'h3f ) ,port_id); | |
137 | } else interrupts_set = 0; | |
138 | // check for only bits related to - port_id | |
139 | // check bits against error_interrupt_type; | |
140 | if(interrupts_set) { | |
141 | CheckPortIntStat = 1; | |
142 | } else CheckPortIntStat = 0; | |
143 | ||
144 | } | |
145 | task CNiuIntrDevTxc::ClearPortInt(integer port_id) { | |
146 | // clear interrupts for this port | |
147 | bit [63:0] address; | |
148 | bit [63:0] data; | |
149 | bit [63:0] wdata; | |
150 | ||
151 | semaphore_get(WAIT, sem_id, 1); | |
152 | ||
153 | address = TXC_FZC_BASE + TXC_INT_STAT; | |
154 | gen_pio_drv.pio_rd(address, data); | |
155 | ||
156 | wdata = (6'h3f) << (8*port_id); | |
157 | wdata = data | wdata; | |
158 | gen_pio_drv.pio_wr(address, wdata); | |
159 | ||
160 | clear_pending_flag[port_id] = 0; | |
161 | semaphore_put(sem_id, 1); | |
162 | ||
163 | ||
164 | } | |
165 | task CNiuIntrDevTxc::ReEnablePortInt(integer port_id) { | |
166 | // set interrupts for this port | |
167 | ||
168 | integer error_type; | |
169 | bit [63:0] address; | |
170 | bit [63:0] data; | |
171 | ||
172 | ||
173 | ||
174 | error_type = error_injection_type[port_id]; | |
175 | ||
176 | // get the error code | |
177 | data = error_type & 64'h3ffff; // {dblbit,snglbit,rsvd,all,alt,one,rsvd,last,second,first} | |
178 | ||
179 | ||
180 | // based upon error type set the appropriate bits | |
181 | if(error_type & TxFIFO_SF_ERROR) { | |
182 | address = TXC_FZC_BASE + TXC_SFECC_CTL +256 * port_id; | |
183 | gen_pio_drv.pio_wr(address, data); | |
184 | } | |
185 | ||
186 | if(error_type & TxFIFO_RO_ERROR) { | |
187 | address = TXC_FZC_BASE + TXC_ROECC_CTL+256 * port_id; | |
188 | gen_pio_drv.pio_wr(address, data); | |
189 | } | |
190 | expect_error_interrupt[port_id] = error_type; | |
191 | ||
192 | ||
193 | ||
194 | ||
195 | } | |
196 | function integer CNiuIntrDevTxc::isr( ( bit[1:0] ldf_flags = 0) ) { | |
197 | shadow integer i; | |
198 | printf("Start In ISR id - %d LDF Flags - %x \n",super.dev_id,ldf_flags); | |
199 | if(ldf_flags!==2'h2) { | |
200 | printf("ERROR dev id - %d LDF Flags Incorrect - %x \n",super.dev_id,ldf_flags); | |
201 | } | |
202 | ||
203 | isr_done = 0; | |
204 | SetPendingFlag(); | |
205 | for(i=0;i<4;i++) { | |
206 | fork{ | |
207 | if(ports_active[i]) { | |
208 | if(CheckPortIntStat(i)) | |
209 | ClearPortInt(i); | |
210 | } | |
211 | } join none | |
212 | } | |
213 | wait_child(); | |
214 | ClrPendingFlag(); | |
215 | isr_done = 1; | |
216 | printf("End In ISR id - %d LDF Flags - %x \n",super.dev_id,ldf_flags); | |
217 | } | |
218 | ||
219 | ||
220 | task CNiuIntrDevTxc::decode_txc_err_events(bit[5:0] data ,integer port_id) { | |
221 | ||
222 | bit [63:0] rd_data; | |
223 | bit [63:0] wr_data; | |
224 | bit [63:0] addr; | |
225 | bit [11:0] port_offset; | |
226 | integer error_type; | |
227 | bit pktassydead,reordererror,ro_unco,ro_correct,sf_unco,sf_correct; | |
228 | bit [5:0] expected_status; | |
229 | ||
230 | port_offset = 256*port_id; | |
231 | ||
232 | ||
233 | // This function can now check this integer to see what has been injected | |
234 | error_type = expect_error_interrupt[port_id] ; | |
235 | if(error_type ==0) { | |
236 | printf("CNiuIntrDevTxC Port %d Not expected to generate interrupts!!ERROR: ErrorType Set to %x \n",port_id,error_type); | |
237 | return; | |
238 | } else { | |
239 | // expected_status = {pktassydead,reordererror,ro_unco,ro_correct,sf_uncorrect,sf_correct}; | |
240 | pktassydead = 0; // Not injected in this case | |
241 | reordererror = 0; // Not injected in this case | |
242 | ro_unco = (error_type & TxFIFO_RO_ERROR) && ( error_type & TxFIFO_UnCorrectError) ; | |
243 | sf_unco = (error_type & TxFIFO_SF_ERROR) && ( error_type & TxFIFO_UnCorrectError) ; | |
244 | ro_correct = (error_type & TxFIFO_RO_ERROR) && ( error_type & TxFIFO_CorrectError) ; | |
245 | sf_correct = (error_type & TxFIFO_SF_ERROR) && ( error_type & TxFIFO_CorrectError) ; | |
246 | expected_status = {pktassydead,reordererror,ro_unco,ro_correct,sf_unco,sf_correct}; | |
247 | if(expected_status!==data) { | |
248 | printf("CNiuIntrDevTxC Port %d ERROR Unexpected interrupts status expected %x received - %x\n",port_id,expected_status,data); | |
249 | } | |
250 | } | |
251 | ||
252 | printf("CNiuIntrDevTxC Port %d has interrupted\n",port_id); | |
253 | // check for store and forward fifo registers | |
254 | if(data[0]) { | |
255 | printf("CNiuIntrDevTxC Port %d SF_Correct_error status set\n",port_id); | |
256 | addr = TXC_FZC_BASE + (TXC_SFECC_ST + port_offset); | |
257 | gen_pio_drv.pio_rd(addr,rd_data); | |
258 | if(rd_data[17] != 1'b1) | |
259 | printf("ERROR SF_Correctable error bit not set for Port %d\n",port_id); | |
260 | else | |
261 | printf("INFO SF_Correctable error bit set for Port %d\n", port_id); | |
262 | } | |
263 | ||
264 | if(data[1]) { | |
265 | printf("CNiuIntrDevTxC Port %d SF_UnCorrect_error status set\n",port_id); | |
266 | addr = TXC_FZC_BASE + (TXC_SFECC_ST + port_offset); | |
267 | gen_pio_drv.pio_rd(addr,rd_data); | |
268 | if(rd_data[16] != 1'b1) | |
269 | printf("ERROR SF_UnCorrectable error bit not set for Port %d\n",port_id); | |
270 | else | |
271 | printf("INFO SF_UnCorrectable error bit set for Port %d\n", port_id); | |
272 | } | |
273 | ||
274 | // check for RO fifo registers and functionality | |
275 | if(data[2]) { | |
276 | printf("CNiuIntrDevTxC Port %d RO_Correct_error status set\n",port_id); | |
277 | addr = TXC_FZC_BASE + (TXC_ROECC_ST + port_offset); | |
278 | gen_pio_drv.pio_rd(addr,rd_data); | |
279 | if(rd_data[17] != 1'b1) | |
280 | printf("ERROR RO_Correctable error bit not set for Port %d\n",port_id); | |
281 | else | |
282 | printf("INFO RO_Correctable error bit set for Port %d\n", port_id); | |
283 | } | |
284 | ||
285 | if(data[3]) { | |
286 | printf("CNiuIntrDevTxC Port %d RO_UnCorrect_error status set\n",port_id); | |
287 | addr = TXC_FZC_BASE + (TXC_ROECC_ST + port_offset); | |
288 | gen_pio_drv.pio_rd(addr,rd_data); | |
289 | if(rd_data[16] != 1'b1) | |
290 | printf("ERROR RO_UnCorrectable error bit not set for Port %d\n",port_id); | |
291 | else | |
292 | printf("INFO RO_UnCorrectable error bit set for Port %d\n", port_id); | |
293 | } | |
294 | ||
295 | ||
296 | if(data[0] || data[1]) { | |
297 | addr = TXC_FZC_BASE + (TXC_SFECC_ST + port_offset); | |
298 | gen_pio_drv.pio_rd(addr,rd_data); | |
299 | wr_data = 64'h8000_0000 | rd_data; | |
300 | gen_pio_drv.pio_wr(addr,wr_data); | |
301 | ||
302 | // read the sf_data & sf_ecc_st to check | |
303 | ||
304 | gen_pio_drv.pio_rd(addr,rd_data); | |
305 | if(rd_data != 64'h0) | |
306 | printf("ERROR TXC_SFECC_ST not clrd for Port %d value %h\n",port_id,rd_data); | |
307 | else | |
308 | printf("INFO TXC_SFECC_ST clrd for Port %d value %h\n",port_id,rd_data); | |
309 | } | |
310 | ||
311 | if(data[2] || data[3]) { | |
312 | addr = TXC_FZC_BASE + (TXC_ROECC_ST + port_offset); | |
313 | gen_pio_drv.pio_rd(addr,rd_data); | |
314 | wr_data = 64'h8000_0000 | rd_data; | |
315 | gen_pio_drv.pio_wr(addr,wr_data); | |
316 | ||
317 | // read the ro_data & ro_ecc_st to check | |
318 | ||
319 | gen_pio_drv.pio_rd(addr,rd_data); | |
320 | if(rd_data != 64'h0) | |
321 | printf("ERROR TXC_ROECC_ST not clrd for Port %d value %h\n",port_id,rd_data); | |
322 | else | |
323 | printf("INFO TXC_ROECC_ST clrd for Port %d value %h\n",port_id,rd_data); | |
324 | } | |
325 | ||
326 | ||
327 | } | |
328 | ||
329 | task CNiuIntrDevTxc::checkPendingStatus() { | |
330 | // final exit status check for TXC | |
331 | ||
332 | bit [63:0] rd_data; | |
333 | bit [63:0] wr_data; | |
334 | bit [63:0] addr; | |
335 | bit [11:0] port_offset; | |
336 | integer port_id; | |
337 | ||
338 | ||
339 | printf("CNiuIntrDevTxc::checkPendingStatus!!\n"); | |
340 | for(port_id=0;port_id<4;port_id++) { | |
341 | if(ports_active[port_id]) { | |
342 | ||
343 | port_offset = 256*port_id; | |
344 | ||
345 | ||
346 | // clear sf_data | |
347 | ||
348 | addr = TXC_FZC_BASE + (TXC_SF_DATA0 + port_offset); | |
349 | gen_pio_drv.pio_rd(addr,rd_data); | |
350 | if(rd_data != 64'h0) | |
351 | printf("ERROR TXC_SF_ECC_DATA0 not clrd for Port %d value %h\n",port_id,rd_data); | |
352 | ||
353 | addr = TXC_FZC_BASE + (TXC_SF_DATA1 + port_offset); | |
354 | gen_pio_drv.pio_rd(addr,rd_data); | |
355 | if(rd_data != 64'h0) | |
356 | printf("ERROR TXC_SF_ECC_DATA1 not clrd for Port %d value %h\n",port_id,rd_data); | |
357 | ||
358 | addr = TXC_FZC_BASE + (TXC_SF_DATA2 + port_offset); | |
359 | gen_pio_drv.pio_rd(addr,rd_data); | |
360 | if(rd_data != 64'h0) | |
361 | printf("ERROR TXC_SF_ECC_DATA2 not clrd for Port %d value %h\n",port_id,rd_data); | |
362 | ||
363 | addr = TXC_FZC_BASE + (TXC_SF_DATA3 + port_offset); | |
364 | gen_pio_drv.pio_rd(addr,rd_data); | |
365 | if(rd_data != 64'h0) | |
366 | printf("ERROR TXC_SF_ECC_DATA3 not clrd for Port %d value %h\n",port_id,rd_data); | |
367 | ||
368 | addr = TXC_FZC_BASE + (TXC_SF_DATA4 + port_offset); | |
369 | gen_pio_drv.pio_rd(addr,rd_data); | |
370 | if(rd_data != 64'h0) | |
371 | printf("ERROR TXC_SF_ECC_DATA4 not clrd for Port %d value %h\n",port_id,rd_data); | |
372 | ||
373 | ||
374 | // clear RO_data | |
375 | ||
376 | addr = TXC_FZC_BASE + (TXC_RO_DATA0 + port_offset); | |
377 | gen_pio_drv.pio_rd(addr,rd_data); | |
378 | if(rd_data != 64'h0) | |
379 | printf("ERROR TXC_RO_ECC_DATA0 not clrd for Port %d value %h\n",port_id,rd_data); | |
380 | ||
381 | addr = TXC_FZC_BASE + (TXC_RO_DATA1 + port_offset); | |
382 | gen_pio_drv.pio_rd(addr,rd_data); | |
383 | if(rd_data != 64'h0) | |
384 | printf("ERROR TXC_RO_ECC_DATA1 not clrd for Port %d value %h\n",port_id,rd_data); | |
385 | ||
386 | addr = TXC_FZC_BASE + (TXC_RO_DATA2 + port_offset); | |
387 | gen_pio_drv.pio_rd(addr,rd_data); | |
388 | if(rd_data != 64'h0) | |
389 | printf("ERROR TXC_RO_ECC_DATA2 not clrd for Port %d value %h\n",port_id,rd_data); | |
390 | ||
391 | addr = TXC_FZC_BASE + (TXC_RO_DATA3 + port_offset); | |
392 | gen_pio_drv.pio_rd(addr,rd_data); | |
393 | if(rd_data != 64'h0) | |
394 | printf("ERROR TXC_RO_ECC_DATA3 not clrd for Port %d value %h\n",port_id,rd_data); | |
395 | ||
396 | addr = TXC_FZC_BASE + (TXC_RO_DATA4 + port_offset); | |
397 | gen_pio_drv.pio_rd(addr,rd_data); | |
398 | if(rd_data != 64'h0) | |
399 | printf("ERROR TXC_RO_ECC_DATA4 not clrd for Port %d value %h\n",port_id,rd_data); | |
400 | ||
401 | }// else if ports_valid | |
402 | }// end for | |
403 | } |