Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: niu_dma_bind.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 | #include "pio_memory_map.vri" | |
37 | #include "niu_gen_pio.vrh" | |
38 | #include "niu_mem.vrh" | |
39 | #include "niu_cbclass.vrh" | |
40 | #include "mbox_class.vrh" | |
41 | #include "cMesg.vrh" | |
42 | ||
43 | extern niu_gen_pio gen_pio_drv; | |
44 | extern CSparseMem SparseMem; | |
45 | extern mbox_class mbox_id; | |
46 | extern Mesg be_msg; | |
47 | ||
48 | ||
49 | class CNiuDMABind { | |
50 | ||
51 | // Bind Shadows | |
52 | ||
53 | // group to DMA Shadow | |
54 | local bit [31:0] grp_tx_dma_bind[64]; | |
55 | local bit [31:0] grp_rx_dma_bind[64]; | |
56 | local bit[63:0] prog_grps; | |
57 | // DMA to group Shadow | |
58 | local integer tx_dma_grp_bind[64]; | |
59 | local integer rx_dma_grp_bind[64]; | |
60 | ||
61 | // functions numbers per DMA | |
62 | integer tx_dma_func_bind[32]; | |
63 | integer rx_dma_func_bind[32]; | |
64 | ||
65 | ||
66 | local task WriteDMABind(integer group_no, bit[63:0] data); | |
67 | function bit[63:0] ReadDMABind(integer group_no); | |
68 | task SetTxBind( integer dma_no, integer group_no); | |
69 | task SetRxBind( integer dma_no, integer group_no); | |
70 | task ResetTxBind( integer dma_no, integer group_no); | |
71 | task ResetRxBind( integer dma_no, integer group_no); | |
72 | task SetRxTxBind( integer tx_dma_no, integer rx_dma_no, integer group_no); | |
73 | function integer isDMABound(integer dma_no, integer tx_or_rx, integer group_no); | |
74 | function bit[63:0] getPIOAddress( integer dma_no, integer tx_or_rx, integer group_no, bit[63:0] address, (integer pass_through=1) ); | |
75 | function bit[63:0] getFuncNoBase( integer group_no) ; | |
76 | function integer getUnboundPIOAddress(var bit [63:0] address) ; | |
77 | task CheckFunctionBinds(bit [63:0] address,integer func); | |
78 | task InitUnBoundGroups() ; | |
79 | task spCheckFunctionBinds (); | |
80 | task SetDefFunc(integer func,integer type,integer id) ; | |
81 | ||
82 | ||
83 | task new() { | |
84 | integer i; | |
85 | integer func_chk_enable; | |
86 | prog_grps = 64'h0; | |
87 | for(i=0;i<64;i++) { | |
88 | grp_tx_dma_bind[i] = 32'h0; | |
89 | grp_rx_dma_bind[i] = 32'h0; | |
90 | } | |
91 | for(i=0;i<64;i++) { | |
92 | tx_dma_grp_bind[i] = -1; | |
93 | rx_dma_grp_bind[i] = -1; | |
94 | } | |
95 | for(i=0;i<32;i++) { | |
96 | rx_dma_func_bind[i] = -1; | |
97 | tx_dma_func_bind[i] = -1; | |
98 | } | |
99 | } | |
100 | } | |
101 | ||
102 | task CNiuDMABind::SetDefFunc(integer func,integer type,integer id) { | |
103 | if(type==1/*RX*/) { | |
104 | rx_dma_func_bind[id] = func; | |
105 | } else {/*TX*/ | |
106 | tx_dma_func_bind[id] = func; | |
107 | } | |
108 | } | |
109 | ||
110 | task CNiuDMABind::WriteDMABind(integer group_no, bit[63:0] data) { | |
111 | bit[63:0] address; | |
112 | address = DMA_BIND + 8*group_no; | |
113 | gen_pio_drv.pio_wr(address,data); | |
114 | } | |
115 | function bit[63:0] CNiuDMABind::ReadDMABind(integer group_no) { | |
116 | bit[63:0] address; | |
117 | address = DMA_BIND + 8*group_no; | |
118 | gen_pio_drv.pio_rd(address,ReadDMABind); | |
119 | } | |
120 | ||
121 | task CNiuDMABind::SetTxBind( integer dma_no, integer group_no) { | |
122 | // Check if this group is already bound. If so do a RMW | |
123 | bit [63:0] rdata; | |
124 | bit [4:0] d; | |
125 | d = dma_no; // vera issue | |
126 | //if((rx_dma_grp_bind[group_no]!= -1)|(tx_dma_grp_bind[group_no]!= -1)) { // } | |
127 | if((grp_tx_dma_bind[group_no]!= 0) | (grp_rx_dma_bind[group_no]!= 0)) { | |
128 | // group already bound | |
129 | rdata = ReadDMABind(group_no); | |
130 | } else { | |
131 | rdata = 64'h0; | |
132 | } | |
133 | rdata[12:8] = d; | |
134 | rdata[13] = 1; | |
135 | WriteDMABind(group_no,rdata); | |
136 | // update the Shadows | |
137 | tx_dma_grp_bind[dma_no] = group_no; | |
138 | tx_dma_func_bind[dma_no] = group_no/16; | |
139 | grp_tx_dma_bind[group_no] = grp_tx_dma_bind[group_no] | 1<<dma_no; | |
140 | prog_grps[group_no] = 1'b1; | |
141 | printf("CNiuDMABind::SetTxBind: TxDMA - %d Bound to Group - %d \n",dma_no,group_no); | |
142 | } | |
143 | task CNiuDMABind::SetRxBind( integer dma_no, integer group_no) { | |
144 | bit [63:0] rdata; | |
145 | bit [4:0] d; | |
146 | d = dma_no; // vera issue | |
147 | //if((rx_dma_grp_bind[group_no]!= -1)|(tx_dma_grp_bind[group_no]!= -1)) { // } | |
148 | if((grp_tx_dma_bind[group_no]!= 0) | (grp_rx_dma_bind[group_no]!= 0)) { | |
149 | // group already bound | |
150 | rdata = ReadDMABind(group_no); | |
151 | } else { | |
152 | rdata = 64'h0; | |
153 | } | |
154 | rdata[4:0] = d; | |
155 | rdata[5] = 1; | |
156 | WriteDMABind(group_no,rdata); | |
157 | rx_dma_grp_bind[dma_no] = group_no; | |
158 | rx_dma_func_bind[dma_no] = group_no/16; | |
159 | grp_rx_dma_bind[group_no] = grp_rx_dma_bind[group_no] | 1<<dma_no; | |
160 | prog_grps[group_no] = 1'b1; | |
161 | printf("CNiuDMABind::SetRxBind: RxDMA - %d Bound to Group - %d \n",dma_no,group_no); | |
162 | ||
163 | } | |
164 | task CNiuDMABind::ResetTxBind( integer dma_no, integer group_no) { | |
165 | // Check if this group is already bound. If so do a RMW | |
166 | bit [63:0] rdata; | |
167 | bit [4:0] d; | |
168 | d = dma_no; // vera issue | |
169 | rdata = ReadDMABind(group_no); | |
170 | rdata[12:8] = d; | |
171 | rdata[13] = 0; | |
172 | WriteDMABind(group_no,rdata); | |
173 | // update the Shadows | |
174 | tx_dma_grp_bind[dma_no] = -1; | |
175 | tx_dma_func_bind[dma_no] = group_no/16; | |
176 | grp_tx_dma_bind[group_no] = grp_tx_dma_bind[group_no] | 0<<dma_no; | |
177 | prog_grps[group_no] = 1'b0; | |
178 | printf("CNiuDMABind::ResetTxBind: TxDMA - %d Reset Bound to Group - %d \n",dma_no,group_no); | |
179 | } | |
180 | task CNiuDMABind::ResetRxBind( integer dma_no, integer group_no) { | |
181 | bit [63:0] rdata; | |
182 | bit [4:0] d; | |
183 | d = dma_no; // vera issue | |
184 | rdata = ReadDMABind(group_no); | |
185 | rdata[4:0] = d; | |
186 | rdata[5] = 0; | |
187 | WriteDMABind(group_no,rdata); | |
188 | rx_dma_grp_bind[dma_no] = -1; | |
189 | rx_dma_func_bind[dma_no] = group_no/16; | |
190 | grp_rx_dma_bind[group_no] = grp_rx_dma_bind[group_no] | 0<<dma_no; | |
191 | prog_grps[group_no] = 1'b0; | |
192 | printf("CNiuDMABind::ResetRxBind: RxDMA - %d Reset Bound to Group - %d \n",dma_no,group_no); | |
193 | ||
194 | } | |
195 | task CNiuDMABind::SetRxTxBind( integer tx_dma_no, integer rx_dma_no, integer group_no) { | |
196 | ||
197 | bit[63:0] rdata; | |
198 | bit [4:0] t_d, r_d; | |
199 | rdata = 64'h0; | |
200 | ||
201 | t_d = tx_dma_no; | |
202 | r_d = rx_dma_no; | |
203 | ||
204 | rdata[12:8] = t_d; | |
205 | rdata[13] = 1; | |
206 | rdata[4:0] = r_d; | |
207 | rdata[5] = 1; | |
208 | ||
209 | WriteDMABind(group_no,rdata); | |
210 | rx_dma_grp_bind[rx_dma_no] = group_no; | |
211 | rx_dma_func_bind[rx_dma_no] = group_no/16; | |
212 | grp_rx_dma_bind[group_no] = grp_rx_dma_bind[group_no] | 1<<rx_dma_no; | |
213 | ||
214 | tx_dma_grp_bind[tx_dma_no] = group_no; | |
215 | tx_dma_func_bind[tx_dma_no] = group_no/16; | |
216 | grp_tx_dma_bind[group_no] = grp_tx_dma_bind[group_no] | 1<<tx_dma_no; | |
217 | prog_grps[group_no] = 1'b1; | |
218 | ||
219 | ||
220 | } | |
221 | ||
222 | function bit[63:0] CNiuDMABind::getFuncNoBase( integer group_no) { | |
223 | if(group_no<=15) { | |
224 | getFuncNoBase = FUNC0_VIR; | |
225 | } else if(group_no<=31) { | |
226 | getFuncNoBase = FUNC1_VIR; | |
227 | } else if(group_no<=47) { | |
228 | getFuncNoBase = FUNC2_VIR; | |
229 | } else if(group_no<=63) { | |
230 | getFuncNoBase = FUNC3_VIR; | |
231 | } else { | |
232 | getFuncNoBase = 64'hx; | |
233 | } | |
234 | } | |
235 | ||
236 | function bit[63:0] CNiuDMABind::getPIOAddress( integer dma_no, integer tx_or_rx, integer group_no, bit[63:0] address, (integer pass_through=1) ) { | |
237 | integer func; | |
238 | bit[5:0] g; | |
239 | bit[63:0] orig_address; | |
240 | orig_address = address; | |
241 | g = group_no; | |
242 | getPIOAddress = orig_address; | |
243 | if((pass_through==1) | ( address[19]==1)) { | |
244 | getPIOAddress = orig_address; | |
245 | } else if(pass_through==-1) { | |
246 | // place holder for generating error address | |
247 | getPIOAddress = 0; | |
248 | } else if(isDMABound(dma_no,tx_or_rx,group_no)) { | |
249 | ||
250 | getPIOAddress = getFuncNoBase(group_no); | |
251 | getPIOAddress[8:0] = orig_address[8:0]; | |
252 | getPIOAddress[9] = (tx_or_rx==0)? 0: 1; // Check polarity | |
253 | getPIOAddress[14] = g[3]; | |
254 | getPIOAddress[12:10] = g[2:0]; | |
255 | ||
256 | ||
257 | } else { | |
258 | // Need to generate error address here | |
259 | getPIOAddress = 64'hx; | |
260 | printf("CNiuDMABind::getPIOAddress dma_no - %d Not Bound to GroupNo - %d \n",dma_no,group_no); | |
261 | } | |
262 | printf("CNiuDMABind::getPIOAddress dma_no - %d orig_address - %x New Address - %x \n",dma_no,address,getPIOAddress); | |
263 | } | |
264 | ||
265 | function integer CNiuDMABind::isDMABound(integer dma_no, integer tx_or_rx, integer group_no) { | |
266 | if(group_no==-1) { | |
267 | /* NEED TO GENERATE A VALID GROUP!!!*/ | |
268 | isDMABound =0; | |
269 | } else if(tx_or_rx==0/*TX*/) { | |
270 | if(tx_dma_grp_bind[dma_no]==group_no) isDMABound = 1; | |
271 | else isDMABound = 0; | |
272 | } else {/*RX*/ | |
273 | if(rx_dma_grp_bind[dma_no]==group_no) isDMABound = 1; | |
274 | else isDMABound = 0; | |
275 | } | |
276 | printf("CNiuDMABind::isDMABound dma_no - %d group - %d isDMABound - %d \n",dma_no,group_no,isDMABound); | |
277 | } | |
278 | task CNiuDMABind::InitUnBoundGroups() { | |
279 | // Fill up the group table with random values, but disable the valid bit | |
280 | integer i; | |
281 | bit[63:0] wdata; | |
282 | ||
283 | for(i=0;i<64;i++) { | |
284 | if(prog_grps[i]==1'b0) { | |
285 | wdata = {random(),random()}; | |
286 | wdata[13] = 1'b0; | |
287 | wdata[5] = 1'b0; | |
288 | WriteDMABind(i,wdata); | |
289 | } | |
290 | } | |
291 | } | |
292 | ||
293 | task CNiuDMABind::spCheckFunctionBinds () { | |
294 | CfuncCheck funcChk; | |
295 | bit [63:0] address;integer func; | |
296 | integer no; | |
297 | while(1) { | |
298 | no = mailbox_get(WAIT,mbox_id.funcChk, funcChk); | |
299 | address = funcChk.address; | |
300 | func = funcChk.func; | |
301 | CheckFunctionBinds(address,func); | |
302 | ||
303 | } | |
304 | } | |
305 | task CNiuDMABind::CheckFunctionBinds(bit [63:0] address,integer func) { | |
306 | /*Task to be called only in Neptune and with a plusargs*/ | |
307 | integer page_id; | |
308 | integer dma; | |
309 | integer rx_or_tx; | |
310 | integer group; | |
311 | integer funct_for_dma; | |
312 | ||
313 | page_id= SparseMem.check_page_id(address); | |
314 | if(page_id==-1) { | |
315 | printf("CNiuDMABind::CheckFunctionBinds: WARNING Address - %x Doesnt Match any of the defined Page!! \n",address); | |
316 | be_msg.print(e_mesg_error,"CNiuDMABind::CheckFunctionBinds:",""," Address - %x Doesnt Match any of the defined Page!! \n",address); | |
317 | ||
318 | return; | |
319 | } else { | |
320 | if(page_id <64) { | |
321 | rx_or_tx=0; | |
322 | dma = page_id/2; | |
323 | } else { | |
324 | rx_or_tx=1; | |
325 | dma = (page_id-64)/2; | |
326 | } | |
327 | } | |
328 | printf("CNiuDMABind::CheckFunctionBinds: PAGE - %d rx_or_tx -%d - DMA - %d Address - %x!!\n",page_id,rx_or_tx,dma,address); | |
329 | if(rx_or_tx) { | |
330 | funct_for_dma = rx_dma_func_bind[dma]; | |
331 | } else { | |
332 | funct_for_dma = tx_dma_func_bind[dma]; | |
333 | } | |
334 | ||
335 | if(funct_for_dma==-1) { | |
336 | printf("CNiuDMABind::CheckFunctionBinds: ERROR funct_for_dma for DMA - %d is unbound !!\n",dma); | |
337 | be_msg.print(e_mesg_error,"CNiuDMABind::CheckFunctionBinds:",""," funct_for_dma for DMA - %d is unbound \n",dma); | |
338 | } else { | |
339 | if(func!==funct_for_dma) { | |
340 | printf(" CNiuDMABind::CheckFunctionBinds: Incorrect FunctionNumber received for address - %x DMA - %d\n",address,dma); | |
341 | be_msg.print(e_mesg_error,"CNiuDMABind::CheckFunctionBinds:",""," Incorrect FunctionNumber received Expected Function No - %d Actual - %d \n",funct_for_dma,func); | |
342 | printf(" CNiuDMABind::CheckFunctionBinds: ERROR Incorrect FunctionNumber received Expected Function No - %d Actual - %d\n",funct_for_dma,func); | |
343 | } | |
344 | } | |
345 | } | |
346 | function integer CNiuDMABind::getUnboundPIOAddress(var bit [63:0] address) { | |
347 | ||
348 | bit[5:0] g; | |
349 | // pick up a random unbound group | |
350 | // | |
351 | if(prog_grps==64'hffffffffffffffff) { | |
352 | getUnboundPIOAddress = 0; | |
353 | } else { | |
354 | g=random()%64; | |
355 | while(prog_grps[g]==1'b1) { | |
356 | g=random()%64; | |
357 | } | |
358 | ||
359 | address = getFuncNoBase(g); | |
360 | address[9:0] = random(); | |
361 | address[14] = g[3]; | |
362 | address[12:10] = g[2:0]; | |
363 | ||
364 | getUnboundPIOAddress = 1; | |
365 | ||
366 | } | |
367 | ||
368 | } |