Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / devices / common / include / pcie.h
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* OpenSPARC T2 Processor File: pcie.h
5* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
6* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
7*
8* The above named program is free software; you can redistribute it and/or
9* modify it under the terms of the GNU General Public
10* License version 2 as published by the Free Software Foundation.
11*
12* The above named program is distributed in the hope that it will be
13* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15* General Public License for more details.
16*
17* You should have received a copy of the GNU General Public
18* License along with this work; if not, write to the Free Software
19* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20*
21* ========== Copyright Header End ============================================
22*/
23#ifndef _PCIE_NEW_
24#define _PCIE_NEW_
25
26#include "module.h"
27#include "pci_common.h"
28#include <stdlib.h>
29#include <assert.h>
30
31// fw declaration
32class genericPcieDev;
33class genericPcieDevIf;
34
35// Helper PCIE function:
36// convert "count" bytes to byte enables.
37// assume that count <= 8 and the bytes are
38// contiguous
39inline uint8_t pcie_countToBe(int count){
40 uint8_t be = 0;
41 if(count > 8)
42 assert(0);
43
44 for(int i = 0; i < count; i++)
45 be |= 1 << i;
46 return be;
47}
48
49
50enum pcie_space {PCIE_CFG = 0, PCIE_IO, PCIE_MEM, PCIE_MSG, PCIE_NSPACES = 4};
51
52static const char *pcie_space_names[] = {"PCIE_CFG", "PCIE_IO", "PCIE_MEM", "PCIE_MSG", "PCIE_UNKN"};
53
54#define pcie_space2name(space) ((int)space < PCIE_NSPACES ? (pcie_space_names[(int)space]) : "PCIE_UNKN")
55
56static const int busShift = 20;
57static const int devShift = 15;
58static const int funShift = 12;
59
60
61enum tlp_orderingAttr { \
62 defaultOrdering, /* strongly ordered model*/ \
63 relaxedOrdering /* relaxed ordering model*/
64};
65
66enum tlp_snoopAttr { \
67 snoop, /* hw enforced cache coherency, default */ \
68 noSnoop /* hw enforced cache cohrencey not expected*/
69};
70
71struct tlp_Attr{
72 tlp_orderingAttr oA;
73 tlp_snoopAttr sA;
74};
75
76enum tlp_trafficClass {
77 TC0, /* best effort service class, default TC */
78 TC1, /* differntiated service classes */
79 TC2,
80 TC3,
81 TC4,
82 TC5,
83 TC6,
84 TC7
85};
86
87// these attributes are not needed from functional sim viewpoint.
88// hence create a struct to bundle them and pass around in functions
89// in case anyone ever cares for more.
90struct tlp_X{
91 tlp_Attr ta;
92 tlp_trafficClass tc;
93 uint8_t tag; /* unique id used to match request with completion*/
94 bool TD; /* includes TLP digest ? true:false*/
95 bool EP; /* is TLP poisoned ? true:false*/
96};
97
98static const tlp_X dont_care_attrs = {{defaultOrdering,snoop},TC0,0, false, false};
99
100
101enum pcieComplStatus { \
102 // values same as those in completion status of completer TLP
103 SC = 0x0 /* successful completion */,
104 UR = 0x1 /* unsupported request */,
105 CRS =0x2 /* configuration retry request status */,
106 CA = 0x4 /* completer abort */,
107
108 // these values though not returned in Completion packet, can be
109 // returned by sim models
110 CMPL_TO, /* completion timeout */
111 // the bus or endpoint needs to tell the requester
112 // in this model since no timing is present
113
114 CMPL_POISONED, // a completer returns a completion TLP that is poisoned
115
116 SIM_OK, /* for posted xactns that do not return completion*/
117 SIM_FAIL /* status, use these reserved values for internal use */
118};
119
120// while handling a TLP, some actions depends upon
121// whether the TLP is originated by the device,
122// or it has reached the final destination device,
123// or is passing through a bridge/switch in the fabric.
124// a trasnmitter can be a requester as well, however
125// an intermediate bridge cannot be. the same distinction holds
126// for completer/receiver
127
128enum pciExpTLPHandler{
129 requester,
130 completer,
131 transmitter,
132 receiver
133};
134
135struct pcieCompleter{
136 pcieComplStatus status;
137 uint16_t completerId;
138 pcieCompleter(pcieComplStatus st, uint16_t cI ){
139 status=st;
140 completerId = cI;
141 }
142 pcieCompleter(int st, int cI){
143 status = (pcieComplStatus)st;
144 completerId = (uint16_t)cI;
145 }
146 pcieCompleter(pcieComplStatus st){
147 status = st;
148 completerId = 0;
149 }
150 pcieCompleter(){
151 status = SIM_OK;
152 completerId = 0;
153 }
154};
155
156
157// addressing mode (either 32 or 64 bit) for memory space access,
158// configuration type (either 0 or 1) for configuration accesses
159// the space identifier tells which of the fields is valid,
160// mem* and conf* are mutually exclusive
161enum addrMd_xactnType{
162 mem_addr32,
163 mem_addr64,
164 conf_type0,
165 conf_type1
166};
167
168
169// message routing methods
170enum msgRouting {
171 routed_to_RC = 0x0, /* RC = root complex */
172 routed_by_addr = 0x1,
173 routed_by_id = 0x2,
174 broadcast_from_RC = 0x3,
175 local = 0x4, /* terminate at receiver */
176 gathered_routed_to_RC = 0x5,
177 invalid_routing
178};
179
180
181
182#define PCIE_COMPLETER_ID(BUS,DEV,FUN) ((BUS & 0xff) << 8 | (DEV & 0x1f) << 3 | (FUN & 0x7))
183#define PCIE_REQUESTER_ID(BUS,DEV,FUN) PCIE_COMPLETER_ID(BUS,DEV,FUN)
184
185//////////// pci express messages //////////////////
186
187// spec defined messages
188
189enum pciExpMsgCode{
190
191 /* INTx Mechanism Messages */
192 MSG_Assert_INTA = 0x20,
193 MSG_Assert_INTB = 0x21,
194 MSG_Assert_INTC = 0x22,
195 MSG_Assert_INTD = 0x23,
196 MSG_Deassert_INTA = 0x24,
197 MSG_Deassert_INTB = 0x25,
198 MSG_Deassert_INTC = 0x26,
199 MSG_Deassert_INTD = 0x27,
200
201 /* Power Management Messages */
202 MSG_PM_Active_State_Nak = 0x14,
203 MSG_PM_PME = 0x18,
204 MSG_PME_Turn_Off = 0x19,
205 MSG_PME_TO_Ack = 0x1b,
206
207 /* error signalling messages*/
208 MSG_ERR_COR = 0x30,
209 MSG_ERR_NONFATAL = 0x31,
210 MSG_ERR_FATAL = 0x32,
211
212 /* Locked Transactions Support */
213 MSG_Unlock = 0x00,
214
215 /* Set_Slot_Power_Limit Message */
216 MSG_Set_Slot_Power_Limit = 0x50,
217
218 /* Hot-Plug Signaling Messages */
219 MSG_Attention_Indicator_On = 0x41,
220 MSG_Attention_Indicator_Blink = 0x43,
221 MSG_Attention_Indicator_Off = 0x40,
222 MSG_Power_Indicator_On = 0x45,
223 MSG_Power_Indicator_Blink = 0x47,
224 MSG_Power_Indicator_Off = 0x44,
225 MSG_Attention_Button_Pressed = 0x48
226};
227
228
229
230struct pciExpMsgUtility{
231private:
232 struct pciExpMsg{
233 char * name;
234 pciExpMsgCode code;
235 msgRouting routing;
236
237 pciExpMsg(const char * n,pciExpMsgCode c,msgRouting r){
238 name = strdup(n);
239 code = c;
240 routing = r;
241 }
242 ~pciExpMsg(){
243 if(name)
244 free(name);
245 }
246
247 };
248
249 static const int numMsgs = 24;
250 pciExpMsg *pciExpMsgDb[numMsgs];
251
252public:
253 pciExpMsgUtility(){
254 pciExpMsgDb[0] = new pciExpMsg("Unlock", MSG_Unlock, broadcast_from_RC);
255 pciExpMsgDb[1] = new pciExpMsg("ERR_COR", MSG_ERR_COR, routed_to_RC);
256 pciExpMsgDb[2] = new pciExpMsg("ERR_NONFATAL", MSG_ERR_NONFATAL, routed_to_RC);
257 pciExpMsgDb[3] = new pciExpMsg("ERR_FATAL", MSG_ERR_FATAL, routed_to_RC);
258 pciExpMsgDb[4] = new pciExpMsg("Assert_INTA", MSG_Assert_INTA, local);
259 pciExpMsgDb[5] = new pciExpMsg("Assert_INTB", MSG_Assert_INTB, local);
260 pciExpMsgDb[6] = new pciExpMsg("Assert_INTC", MSG_Assert_INTC, local);
261 pciExpMsgDb[7] = new pciExpMsg("Assert_INTD", MSG_Assert_INTD, local);
262 pciExpMsgDb[8] = new pciExpMsg("Deassert_INTA", MSG_Deassert_INTA, local);
263 pciExpMsgDb[9] = new pciExpMsg("Deassert_INTB", MSG_Deassert_INTB, local);
264 pciExpMsgDb[10] = new pciExpMsg("Deassert_INTC", MSG_Deassert_INTC, local);
265 pciExpMsgDb[11] = new pciExpMsg("Deassert_INTD", MSG_Deassert_INTD, local);
266 pciExpMsgDb[12] = new pciExpMsg("PM_Active_State_Nak", MSG_PM_Active_State_Nak,local);
267 pciExpMsgDb[13] = new pciExpMsg("PM_PME", MSG_PM_PME, routed_to_RC);
268 pciExpMsgDb[14] = new pciExpMsg("PME_Turn_Off", MSG_PME_Turn_Off, broadcast_from_RC);
269 pciExpMsgDb[15] = new pciExpMsg("PME_TO_Ack", MSG_PME_TO_Ack, gathered_routed_to_RC);
270 pciExpMsgDb[16] = new pciExpMsg("Set_Slot_Power_Limit",MSG_Set_Slot_Power_Limit, local);
271 pciExpMsgDb[17] = new pciExpMsg("Attention_Indicator_On", MSG_Attention_Indicator_On, local);
272 pciExpMsgDb[18] = new pciExpMsg("Attention_Indicator_Blink", MSG_Attention_Indicator_Blink, local);
273 pciExpMsgDb[19] = new pciExpMsg("Attention_Indicator_Off", MSG_Attention_Indicator_Off, local);
274 pciExpMsgDb[20] = new pciExpMsg("Power_Indicator_On", MSG_Power_Indicator_On, local);
275 pciExpMsgDb[21] = new pciExpMsg("Power_Indicator_Blink", MSG_Power_Indicator_Blink, local);
276 pciExpMsgDb[22] = new pciExpMsg("Power_Indicator_Off", MSG_Power_Indicator_Off, local);
277 pciExpMsgDb[23] = new pciExpMsg("Attention_Button_Pressed", MSG_Attention_Button_Pressed, local);
278 }
279 const char * msgCode2name(pciExpMsgCode code){
280 for(int i = 0; i < numMsgs; i++)
281 if(code == pciExpMsgDb[i]->code)
282 return pciExpMsgDb[i]->name;
283 // programming error ??
284 //printf("ERROR msgCode2name: no msg code 0x%x registered \n",code);
285 //assert(0);
286 return 0;
287 }
288 msgRouting msgCode2Routing(pciExpMsgCode code){
289 for(int i = 0; i < numMsgs; i++)
290 if(code == pciExpMsgDb[i]->code)
291 return pciExpMsgDb[i]->routing;
292 // programming error ??
293 // printf("ERROR msgCode2Routing: no msg code 0x%x registered \n",code);
294 // assert(0);
295 return invalid_routing;
296 }
297};
298
299/////////////// AER //////////////////////////////////////////
300
301
302enum pciExpAERRegOffset {
303 UNCORR_ERR_STAT_OFFSET = 4,
304 UNCORR_ERR_MASK_OFFSET = 8,
305 UNCORR_ERR_SEVERITY_OFFSET = 0xc,
306 CORR_ERR_STAT_OFFSET = 0x10,
307 CORR_ERR_MASK_OFFSET = 0x14,
308 ADVANCED_ERR_CAPCNTRL_OFFSET = 0x18,
309 HDR_LOG_OFFSET = 0x1c,
310 ROOT_ERR_CMD_OFFSET = 0x2c,
311 ROOT_ERR_STAT_OFFSET = 0x30,
312 CORR_ERR_SRC_ID_OFFSET = 0x34,
313 ERR_SRC_ID_OFFSET = 0x36
314};
315
316static const int aerUncorrErrBitMask = 0x1ff011;
317static const int aerCorrErrBitMask = 0x11c1;
318
319// bit positions of spec defined uncorrectable errors
320// relevent to uncorrectable error status/mask/severity registers
321enum pciExpAER_ErrBitPos {
322 uncorr_trng_err_bp = 0,
323 uncorr_data_lnk_protocol_err_bp = 4,
324 uncorr_poisoned_tld_bp = 12,
325 uncorr_flow_cntrl_protocol_err_bp = 13,
326 uncorr_completion_timeout_bp = 14,
327 uncorr_completer_abort_bp = 15,
328 uncorr_unexpexted_completion_bp = 16,
329 uncorr_receiver_overflow_bp = 17,
330 uncorr_malformed_tlp_bp = 18,
331 uncorr_ecrc_err_bp = 19,
332 uncorr_unsupported_req_bp = 20,
333// bit positions of spec defined correctable errors
334// relevent to correctable error mask/status register
335 corr_receiver_err_bp = 0,
336 corr_bad_tlp_bp = 6,
337 corr_bad_dllp_bp = 7,
338 corr_replay_num_rollover_bp = 8,
339 corr_replay_timer_timeout_bp = 12
340};
341
342// errors that can be reported by pci express advanced error reporting.
343// include both correctable and non correctable errors.
344enum pciExp_Error{
345// un-correctable errors // detecting agent
346 trainingErr, // device
347 dataLinkProtocolErr, // device
348 poisonedTLP, // receiver
349 poisonedDMA, // receiver
350 flowCntrlProtocolErr, // receiver
351 completionTimeout, // requester
352 completerAbort, // completer, sets error bits at both xmiter & receiver
353 unexpectedCompletion, // receiver. a completion that was not expected.
354 // reason is problems with routing.
355 receiverOverflow, // receiver
356 malformedTLP, // receiver
357 ecrcErr, // receiver
358 ecrcDMAErr, // receiver
359 unsupportedRequest, // sets error bits at both xmiter & receiver
360// correctable errors
361 receiverErr, // detected at receiver
362 badTLP, // receiver
363 badDLLP, // receiver
364 replayNumRollover, // transmitter
365 replayTimerTimeout // transmitter
366};
367
368// pci Express error classification.
369// fatal and nonfatal are sub classifications of uncorrectable errors.
370enum pciExpErrorType{
371 errCorrectable,
372 errUnCorrectable_fatal,
373 errUnCorrectable_nonfatal
374};
375
376class pciExpErrUtility{
377private:
378 struct pciExpErr{
379 pciExp_Error error;
380 char * name;
381 pciExpErrorType dfltErrType;
382 pciExpMsgCode errMessage;
383 pciExpAER_ErrBitPos bitpos; // bit position of error in status/mask/severity regs
384 pciExpErr(pciExp_Error e,const char * n, pciExpErrorType et,pciExpMsgCode em, pciExpAER_ErrBitPos bp ){
385 error = e;
386 name = strdup(n);
387 dfltErrType = et;
388 errMessage = em;
389 bitpos = bp;
390 }
391 ~pciExpErr(){
392 if(name)
393 free(name);
394 }
395 };
396 static const int numErr = 16;
397
398 pciExpErr * pciExpErrDb[numErr];
399
400public:
401 pciExpErrUtility(){
402 pciExpErrDb[0] = new pciExpErr(trainingErr,"traning error",errUnCorrectable_fatal,MSG_ERR_FATAL,uncorr_trng_err_bp);
403 pciExpErrDb[1] = new pciExpErr(receiverErr,"receiver error",errCorrectable,MSG_ERR_COR,corr_receiver_err_bp);
404 pciExpErrDb[2] = new pciExpErr(badTLP,"Bad TLP",errCorrectable,MSG_ERR_COR,corr_bad_tlp_bp);
405 pciExpErrDb[3] = new pciExpErr(badDLLP,"Bad DLLP",errCorrectable,MSG_ERR_COR,corr_bad_dllp_bp);
406 pciExpErrDb[4] = new pciExpErr(replayTimerTimeout,"Replay Timeout",errCorrectable,MSG_ERR_COR,corr_replay_timer_timeout_bp);
407 pciExpErrDb[5] = new pciExpErr(replayNumRollover,"Replay NUM rollover",errCorrectable,MSG_ERR_COR,corr_replay_num_rollover_bp);
408 pciExpErrDb[6] = new pciExpErr(dataLinkProtocolErr,"Data link layer protocol error",errUnCorrectable_fatal,MSG_ERR_FATAL,uncorr_data_lnk_protocol_err_bp);
409 pciExpErrDb[7] = new pciExpErr(poisonedTLP,"Poisoned TLP received",errUnCorrectable_nonfatal,MSG_ERR_NONFATAL,uncorr_poisoned_tld_bp);
410 pciExpErrDb[8] = new pciExpErr(ecrcErr,"ECRC check fail",errUnCorrectable_nonfatal,MSG_ERR_NONFATAL,uncorr_ecrc_err_bp);
411 pciExpErrDb[9] = new pciExpErr(unsupportedRequest,"unsupported request",errUnCorrectable_nonfatal,MSG_ERR_NONFATAL,uncorr_unsupported_req_bp);
412 pciExpErrDb[10] = new pciExpErr(completionTimeout,"Completion timeout",errUnCorrectable_nonfatal,MSG_ERR_NONFATAL,uncorr_completion_timeout_bp);
413 pciExpErrDb[11] = new pciExpErr(completerAbort,"Completer abort",errUnCorrectable_nonfatal,MSG_ERR_NONFATAL,uncorr_completer_abort_bp);
414 pciExpErrDb[12] = new pciExpErr(unexpectedCompletion,"Unexpected completion",errUnCorrectable_nonfatal,MSG_ERR_NONFATAL,uncorr_unexpexted_completion_bp);
415 pciExpErrDb[13] = new pciExpErr(receiverOverflow,"Receiver overflow",errUnCorrectable_fatal,MSG_ERR_FATAL,uncorr_receiver_overflow_bp);
416 pciExpErrDb[14] = new pciExpErr(malformedTLP,"malformed TLP",errUnCorrectable_fatal,MSG_ERR_FATAL,uncorr_malformed_tlp_bp);
417 pciExpErrDb[15] = new pciExpErr(flowCntrlProtocolErr,"Flow control protocol error",errUnCorrectable_fatal,MSG_ERR_FATAL,uncorr_flow_cntrl_protocol_err_bp);
418 }
419
420 const char * error2Name(pciExp_Error e){
421 for(int i = 0; i < numErr; i++)
422 if(e == pciExpErrDb[i]->error)
423 return pciExpErrDb[i]->name;
424 // programming error ??
425 // printf("ERROR error2Name: no error code 0x%x registered \n",e);
426 // assert(0);
427 return 0;
428 }
429 pciExpErrorType error2DfltErrType(pciExp_Error e){
430 for(int i = 0; i < numErr; i++)
431 if(e == pciExpErrDb[i]->error)
432 return pciExpErrDb[i]->dfltErrType;
433 // programming error ??
434 // printf("ERROR error2DfltErrType: no error code 0x%x registered \n",e);
435 // assert(0);
436 return (pciExpErrorType)-1;
437 }
438
439 pciExpMsgCode error2DfltErrMsg(pciExp_Error e){
440 for(int i = 0; i < numErr; i++)
441 if(e == pciExpErrDb[i]->error)
442 return pciExpErrDb[i]->errMessage;
443 // programming error ??
444 // printf("ERROR error2DfltErrMsg: no error code 0x%x registered \n",e);
445 // assert(0);
446 return (pciExpMsgCode)-1;
447 }
448
449 pciExpAER_ErrBitPos error2RegBitPos(pciExp_Error e){
450 for(int i = 0; i < numErr; i++)
451 if(e == pciExpErrDb[i]->error)
452 return pciExpErrDb[i]->bitpos;
453 // programming error ??
454 // printf("ERROR error2RegBitPos: no error code 0x%x registered \n",e);
455 // assert(0);
456 return (pciExpAER_ErrBitPos)-1;
457 }
458};
459
460class pciExpEnhncdCapHdr: public pciConfReg{
461public:
462 static const int pciExpExtCapId_lbp = 15;
463 static const int pciExpExtCapId_rbp = 0;
464 static const int pciExpExtCapId_size = 16;
465
466 static const int capVersion_lbp = 19;
467 static const int capVersion_rbp = 16;
468 static const int capVersion_size = 4;
469
470 static const int nxtCapOffset_lbp = 31;
471 static const int nxtCapOffset_rbp = 20;
472 static const int nxtCapOffset_size = 12;
473
474 static const int capVersion = 1;
475 pciExpEnhncdCapHdr(uint32_t por_val = capVersion << capVersion_rbp, uint32_t mask = 0x0, void *d = 0, const char * name = "pciExpEnhancedCapHeader") \
476 : pciConfReg(name,4,por_val, mask, d){}
477};
478
479
480
481class pciExpAER_UnCorrErrStatReg:public pciConfReg{
482public:
483 pciExpAER_UnCorrErrStatReg(uint32_t por_val = 0x0, uint32_t mask = 0x1ff011, void * d = 0, const char * name = "AdvErrRep-UnCorrErrStatReg") \
484 : pciConfReg(name, 4, por_val, mask, d){}
485
486 uint8_t write(uint32_t buf, uint8_t byte_offset, uint8_t bytes_to_write){
487 assert(bytes_to_write == 4);
488 assert(byte_offset == 0);
489 // rw1c register
490 uint32_t oldval = val;
491 buf &= mask; // 0 out the ro bits if any in buf
492 buf = ~buf; // flip the 0's to 1's and vice versa
493 val &= buf; // and with val so that bits set to 1 are turned off
494 // bits written to with 0 are unaffected.
495
496 if(debug_level >= 2)
497 printf("Name<%s>,size<0x%x>mask<0x%lx>value<0x%lx -> 0x%lx>\n",name,size,mask,oldval,val);
498
499 return 4;
500 }
501};
502
503class pciExpAER_CorrErrStatReg: public pciConfReg{
504public:
505 pciExpAER_CorrErrStatReg(uint32_t por_val = 0x0, uint32_t mask = 0x11c1, void * d = 0, const char * name = "AdvErrRep-CorrErrStatReg") \
506 : pciConfReg(name, 4, por_val, mask, d){}
507
508 uint8_t write(uint32_t buf, uint8_t byte_offset, uint8_t bytes_to_write){
509 assert(bytes_to_write == 4);
510 assert(byte_offset == 0);
511 // rw1c register
512 uint32_t oldval = val;
513
514 buf &= mask;
515 buf = ~buf;
516 val &= buf;
517
518 if(debug_level >= 2)
519 printf("Name<%s>,size<0x%x>mask<0x%lx>value<0x%lx -> 0x%lx>\n",name,size,mask,oldval,val);
520
521 return 4;
522 }
523};
524
525class pciExpAER_ErrCapCntrlReg: public pciConfReg{
526public:
527 static const int firstErrPointer_lbp = 4;
528 static const int firstErrPointer_rbp = 0;
529 static const int firstErrPointer_size = 5;
530
531 static const int ecrcGenCapable_bp = 5;
532 static const int ecrcGenEnable_bp = 6;
533 static const int ecrcCheckCapable_bp = 7;
534 static const int ecrcCheckEnable_bp = 8;
535
536 pciExpAER_ErrCapCntrlReg(uint32_t por_val = 0x0, uint32_t mask = 0x140, void * d = 0, const char * name = "AdvErrRep-ErrCapCntrlReg")
537 : pciConfReg(name, 4, por_val, mask, d){}
538
539};
540
541class pciExpAER_RootErrCmdReg:public pciConfReg{
542public:
543 static const int fatal_err_rprtng_enable_bp = 0;
544 static const int non_fatal_err_rprtng_enable_bp = 1;
545 static const int corr_err_rprtng_enable_bp = 2;
546
547 pciExpAER_RootErrCmdReg(uint32_t por_val = 0x0, uint32_t mask = 0x3, void * d = 0, const char * name = "AdvErrRep-RootErrCmdReg")
548 : pciConfReg(name, 4, por_val, mask, d){}
549};
550
551class pciExpAER_RootErrStatReg: public pciConfReg{
552public:
553 static const int err_cor_recvd_bp = 0;
554 static const int multi_err_cor_recvd_bp = 1;
555 static const int err_ftl_nonftl_recvd_bp = 2;
556 static const int multi_err_ftl_nonftl_recvd_bp = 3;
557 static const int first_uncorr_fatal_bp = 4;
558 static const int non_ftl_err_msg_recvd_bp = 5;
559 static const int ftl_err_msg_recvd_bp = 6;
560
561 static const int adv_err_intr_msg_lbp = 31;
562 static const int adv_err_intr_msg_rbp = 27;
563 static const int adv_err_intr_msg_size = 5;
564
565 pciExpAER_RootErrStatReg(uint32_t por_val = 0x0, uint32_t mask = 0xff, void * d = 0, const char * name = "AdvErrRep-RootErrStatusReg")
566 :pciConfReg(name, 4, por_val, mask, d){}
567
568 uint8_t write(uint32_t buf, uint8_t byte_offset, uint8_t bytes_to_write){
569 assert(bytes_to_write == 4);
570 assert(byte_offset == 0);
571 // rw1c register
572
573 uint32_t oldval = val;
574 buf &= mask; // 0 out the ro bits if any in buf
575 buf = ~buf; // flip the 0's to 1's and vice versa
576 val &= buf; // and with val so that bits set to 1 are turned off
577 // bits written to with 0 are unaffected.
578
579 if(debug_level >= 2)
580 printf("Name<%s>,size<0x%x>mask<0x%lx>value<0x%lx -> 0x%lx>\n",name,size,mask,oldval,val);
581
582 return 4;
583 }
584
585};
586
587
588
589///////////////////////////////////////////////////////////////
590
591
592// pciexpress specific configuration register definitions.
593
594// register offset in bytes for pci express capability
595enum pciExpCapRegOffsets{
596 PCI_EXP_CAP_ID_OFFSET = 0x0,
597 PCI_EXP_NXT_CAP_PTR_OFFSET = 0x1,
598 PCI_EXP_CAP_REG_OFFSET = 0x2,
599 PCI_EXP_DEV_CAP_OFFSET = 0x4,
600 PCI_EXP_DEV_CTRL_OFFSET = 0x8,
601 PCI_EXP_DEV_STAT_OFFSET = 0xa,
602 PCI_EXP_LINK_CAP_OFFSET = 0xc,
603 PCI_EXP_LINK_CONT_OFFSET = 0x10,
604 PCI_EXP_LINK_STAT_OFFSET = 0x12,
605 PCI_EXP_SLOT_CAP_OFFSET = 0x14,
606 PCI_EXP_SLOT_CTRL_OFFSET = 0x18,
607 PCI_EXP_SLOT_STAT_OFFSET = 0x1a,
608 PCI_EXP_ROOT_CTRL_OFFSET = 0x1c,
609 PCI_EXP_RSVDP_OFFSET = 0x1e,
610 PCI_EXP_ROOT_STAT = 0x20
611};
612
613
614static const int pciExpCapSize = 0x24; // in bytes
615// pciexpress capability registers.
616
617static const int pciExpressCapId = 0x10;
618
619class pciExpCapReg:public pciConfReg{
620public:
621 static const int capVersion_val = 1;
622 static const int capVersion_lbp = 3;
623 static const int capVersion_rbp = 0;
624 static const int capVersion_size = 4;
625
626 static const int devPortType_lbp = 7;
627 static const int devPortType_rbp = 4;
628 static const int devPortType_size = 4;
629
630 enum devPortType_val {
631 pci_exp_end_pnt = 0x0,
632 pci_exp_leg_end_pnt = 0x1,
633 pci_exp_root_port = 0x4,
634 pci_exp_swtch_upstrm_prt = 0x5,
635 pci_exp_swtch_dwnstrm_prt = 0x6,
636 pci_exp_to_pci_x_bridge = 0x7,
637 pci_x_to_pci_exp_bridge = 0x8
638 };
639
640 static const int slotImpl_bp = 8;
641 // if 1 then device is either
642 // a) root port of pcie root complex
643 // b) dwnstrm port of pcie swtch
644
645 static const int intrMsgNo_lbp = 13;
646 static const int intrMsgNo_rbp = 9;
647 static const int intrMsgNo_size = 4;
648
649 pciExpCapReg(uint16_t por_val = 0, uint16_t mask = 0x0, void * d = 0, const char * name = "pcieExpCapReg")\
650 :pciConfReg(name,2,por_val,mask,d){} // size = 2, RO.
651
652
653 // a read only register. models can use the base class getBit,setBit and
654 // get-setRange() with the const defintions above to r/w individual fields
655};
656
657class pciExpDevCapReg:public pciConfReg{
658public:
659 static const int maxPayload_lbp = 2;
660 static const int maxPayload_rbp = 0;
661 static const int maxPayload_size = 3;
662
663 enum maxPayload_val {
664 s128 = 0x0,
665 s256 = 0x1,
666 s512 = 0x2,
667 s1k = 0x3,
668 s2k = 0x4,
669 s4k = 0x5
670 };
671
672 static const int phantomFunc_lbp = 4;
673 static const int phantomFunc_rbp = 3;
674 static const int phantomFunc_size = 2;
675
676 enum phantomFunc_val {
677 Pf_0 = 0x0, // no phantom functions
678 Pf_4 = 0x1, // first msb of function # used for phantom functions, 4 available
679 Pf_6 = 0x2, // 2 msbs of function # used for phantom functions, 6 available,
680 Pf_8 = 0x3 // all (3) bits of function # used for phantom functions, 8 available
681 };
682
683 static const int extendedTag_bp = 5;
684 // 0 => 5 bit tag support
685 // 1 => 8 bit '' ''
686
687 static const int endPntL0sLat_lbp = 8;
688 static const int endPntL0sLat_rbp = 6;
689 static const int endPntL0sLat_size = 3;
690
691 enum endPntL0sLat_val {
692 l0_lat_64ns = 0x0, // < 64ns
693 l0_lat_64_128ns = 0x1, // 64 ns to < 128ns
694 l0_lat_128_256ns = 0x2, // 128ns to < 256ns
695 l3_lat_256_512ns = 0x3, // 256ns to < 512ns
696 l0_lat_512ns_1us = 0x4, // 512ns to < 1us
697 l0_lat_1us_2us = 0x5, // 1us to < 2us
698 l0_lat_2us_4us = 0x6, // 2us to 4us
699 l0_lat_4us = 0x7 // > 4us
700 };
701
702 static const int endPntL1Lat_lbp = 9;
703 static const int endPntL1Lat_rbp = 11;
704 static const int endPntL1Lat_size = 3;
705 enum endPntL1Lat_val {
706 l1_lat_1us = 0x0, // < 1us
707 l1_lat_1_2us = 0x1, // 1us to < 2us
708 l1_lat_2_4us = 0x2, // 2us to < 4us
709 l1_lat_4_8us = 0x3, // 4us to < 8us
710 l1_lat_8_16us = 0x4, // 8us to < 16us
711 l1_lat_16_32us = 0x5, // 16us to < 32us
712 l1_lat_32_64us = 0x6, // 32us to 64us
713 l1_lat_64us = 0x7 // > 64us
714 };
715
716 static const int attnBtnPrsnt_bp = 12;
717 // valid for the following devices only:
718 // pcie endpoint
719 // legacy pcie endpoint
720 // upstrm port of pcie swtch
721 // pcie to pci/pcix bridge
722
723 static const int attnIndPrsnt_bp = 13;
724 // valid for same devices as for attention button present bit
725
726 static const int pwrIndPrsnt_bp = 14;
727 // same devices as above
728
729 static const int capturedSltPwrLmtVal_lbp = 25;
730 static const int capturedSltPwrLmtVal_rbp = 18;
731 static const int capturedSltPwrLmtVal_size = 8;
732
733 static const int capturedSltPwrLmtSz_lbp = 27;
734 static const int capturedSltPwrLmtSz_rbp = 26;
735 static const int capturedSltPwrLmtSz_size = 2;
736
737
738 pciExpDevCapReg(uint32_t por_val, uint32_t mask = 0, void * d = 0, const char * name = "pcieDevCapReg")\
739 :pciConfReg(name,4,por_val,mask, d){} // size 4 bytes, RO reg
740
741};
742
743class pciExpDevCntrlReg:public pciConfReg{
744public:
745 static const int corrErrRepEn_bp = 0;
746 static const int nonFatalErrRepEn_bp = 1;
747 static const int fatalErrRepEn_bp = 2;
748 static const int unsprtdReqRepEn_bp = 3;
749 static const int rlxdOrdrEn_bp = 4;
750
751 static const int maxPaylodSz_lbp = 7;
752 static const int maxPaylodSz_rbp = 5;
753 static const int maxPaylodSz_size = 2;
754 enum maxPaylodSz_val {
755 Pls_128b = 0, // 128b
756 Pls_s256b = 1, // 256b
757 Pls_s512b = 2, // 512b
758 Pls_s1k = 3, // 1k
759 Pls_s2k = 4, // 2k
760 Pls_s4k = 5 // 4k
761 };
762
763 static const int extTagFldEn_bp = 8;
764 static const int phntmFuncEn_bp = 9;
765 static const int auxPwrPMEn_bp = 10;
766 static const int noSnpEn_bp = 11;
767
768 static const int maxRdReqSz_lbp = 14;
769 static const int maxRdReqSz_rbp = 12;
770 static const int maxRdReqSz_size = 3;
771 enum maxRdReqSz_val {
772 Rrs_128b = 0, // 128b
773 Rrs_256b = 1, // 256b
774 Rrs_512b = 2, // 512b
775 Rrs_1k = 3, // 1k
776 Rrs_2k = 4, // 2k
777 Rrs_4k = 5 // 4k
778 };
779 // default por val = 0b 0000 1000 1000 0000 = 0x0880
780 pciExpDevCntrlReg(uint16_t por_val = 0x0880, uint16_t mask = 0x7fff, void * d = 0, const char * name = "pcieDevCapReg")\
781 :pciConfReg(name, 2, por_val, mask, d){} // size = 2
782};
783
784
785class pciExpDevStatReg: public pciConfReg{
786public:
787 static const int corrErrDet_bp = 0; // rw1c
788 static const int nonFtlErrDet_bp = 1; // rw1c
789 static const int ftlErrDet_bp = 2; // rw1c
790 static const int unSprtdReqDet_bp = 3; // rw1c
791 static const int auxPwrSel_bp = 4; // ro
792 static const int xactnPndng_bp = 5; // ro
793
794 pciExpDevStatReg(uint16_t por_val = 0, uint16_t mask = 0x000f, void *d = 0, const char * name = "pcieDevStatReg")\
795 :pciConfReg(name, 2, por_val, mask, d){} // size = 2.
796
797
798 uint8_t write(uint32_t buf, uint8_t byte_offset, uint8_t bytes_to_write){
799 assert(bytes_to_write == 2); // if fails, write a more generic functions like in
800 // the base class
801
802 uint32_t oldval = val;
803
804 buf &= mask; // 0 out the ro bits if any in buf
805 buf = ~buf; // flip the 0's to 1's and vice versa
806 val &= buf; // and with val so that bits set to 1 are turned off
807 // bits written to with 0 are unaffected.
808
809 if(debug_level >= 2)
810 printf("Name<%s>,size<0x%x>mask<0x%lx>value<0x%lx -> 0x%lx>\n",name,size,mask,oldval,val);
811
812 return 2;
813 }
814
815 // NOTE models would use setBit etc to set the bits in this reg, not the write
816 // function. this function is for the s/w use
817};
818
819
820class pciExpLnkCapReg: public pciConfReg{
821public:
822 static const int maxLnkSpeed_lbp = 3;
823 static const int maxLnkSpeed_rbp = 0;
824 static const int maxLnkSpeed_size = 4;
825 static const int maxLnkSpeed_val = 1; // 2.5 Gb/s, all other values are reserved
826
827 static const int maxLnkWdth_lbp = 9;
828 static const int maxLnkWdth_rbp = 4;
829 static const int maxLnkWdth_size = 6;
830 enum maxLnkWdth_val {
831 x1 = 1,
832 x2 = 2,
833 x4 = 4,
834 x8 = 8,
835 x12 = 12,
836 x16 = 16,
837 x32 = 32
838 };
839
840 // ASPM support
841 static const int actvStatePwrMgmt_lbp = 11;
842 static const int actvStatePwrMgmt_rbp = 10;
843 static const int actvStatePwrMgmt_size = 2;
844 enum actvStatePwrMgmt_val {
845 L0s_supported = 1,
846 L0s_and_L01_supported = 3
847 };
848
849 static const int L0sExitLat_lbp = 14;
850 static const int L0sExitLat_rbp = 12;
851 static const int L0sExitLat_size = 3;
852 enum L0sExitLat_val {
853 L0el_64ns = 0,
854 L0el_64_128ns = 1,
855 L0el_128_256ns = 2,
856 L0el_256_512ns = 3,
857 L0el_512_1us = 4,
858 L0el_1_2us = 5,
859 L0el_2_4us = 6,
860 L0el_4us = 7 // > 4us
861 };
862
863 static const int L1ExitLat_lbp = 17;
864 static const int L1ExitLat_rbp = 15;
865 static const int L1ExitLat_size = 3;
866 enum L1ExitLat_val {
867 L1el_1us = 0,
868 L1el_1_2us = 1,
869 L1el_2_4us = 2,
870 L1el_4_8us = 3,
871 L1el_8_16us = 4,
872 L1el_16_32us = 5,
873 L1el_32_64us = 6,
874 L1el_64us = 7 // > 64us
875 };
876
877 // port number for this pcie port
878 static const int portNo_lbp = 31;
879 static const int portNo_rbp = 24;
880 static const int portNo_size = 8;
881
882 // default por_val = 0x00000411
883 // 2,5 Gb/s x1 link, l0s_exit_lat<64ns, ;1exitLat < 1us,
884 // port = 0, l0s supported
885 pciExpLnkCapReg(uint32_t por_val = 0x411, uint32_t mask = 0, void * d = 0, const char * name = "pcieLnkCapReg")\
886 :pciConfReg(name, 4, por_val, mask,d){} // ro 4 byte reg
887};
888
889class pciExpLnkCntrlReg: public pciConfReg{
890public:
891 static const int aspmCntrl_lbp = 1;
892 static const int aspmCntrl_rbp = 0;
893 static const int aspmCntrl_size = 2;
894 enum aspmCntrl_val {
895 aspm_disabled = 0,
896 l0s_enabled = 1,
897 l1_enabled = 2,
898 l0_l1_enabled = 3
899 };
900
901 static const int rcb_bp = 3;
902 // root_ports 0 = 64byte, 1 = 128 byte, RO
903 // endpoints 0 = 64byte, 1 = 128 byte, RW
904 // switch ports, RO, hardwire to 0
905
906 static const int lnkDisable_bp = 4;
907 // if 1, link is disabled.
908
909 static const int lnkRetrain_bp = 5;
910 // always reads 0., RW
911
912 static const int commonClkConf_bp = 6;
913
914 static const int extendedSynch_bp = 7;
915
916 pciExpLnkCntrlReg(uint16_t por_val, uint16_t mask = 0xff, void * d= 0, const char * name = "pcieLinkCntrlReg") \
917 :pciConfReg(name, 2, por_val, mask, d){} //mask = 0xff
918
919};
920
921class pciExpLnkStatReg: public pciConfReg{
922public:
923 static const int lnkSpeed_lbp = 3;
924 static const int lnkSpeed_rbp = 0;
925 static const int lnkSpeed_size = 4;
926 static const int lnkSpeed_val = 1; // 2.5 Gb/s, RO
927
928 static const int lnkWdth_lbp = 9;
929 static const int lnkWdth_rbp = 4;
930 static const int lnkWdth_size = 6;
931 enum lnkWdth_val {
932 x1 = 1,
933 x2 = 2,
934 x4 = 4,
935 x8 = 8,
936 x16 = 16,
937 x32 = 32
938 };
939
940 static const int trainingError_bp = 10; // 1 if an error occurred during link training
941 static const int lnkTraining_bp = 11; // if 1 means link traning is in progress, hw
942 // clears this bit on completion
943 static const int slot_ClkConf_bp = 12; // indicates if 1 that the component uses the
944 // same clock as platform
945
946
947 pciExpLnkStatReg(uint16_t por_val = 0x1011, uint16_t mask = 0, void * d = 0, const char * name = "pcieLinkStatReg") \
948 :pciConfReg(name,2,por_val,mask,d){} // size = 2, RO reg.
949 // por_val is for link speed = 2.5Gb/s, link wodth = X1
950 // no training error, no traning in progress, same reference clock as platform
951
952};
953
954class pciExpSlotCapReg: public pciConfReg{
955public:
956 static const int attnBtnPrsnt_bp = 0;
957 static const int attnCntrlPrsnt_bp = 1;
958 static const int mrlSensorPrsnt_bp = 2;
959 static const int attnIndPrsnt_bp = 3;
960 static const int pwrIndPrsnt_bp = 4;
961 static const int hotPlugSurprise_bp = 5;
962 static const int hotPlugCapable_bp = 6;
963
964 static const int slotPwrLmtVal_lbp = 7;
965 static const int slotPwrLmtVal_rbp = 14;
966 static const int slotPwrLmtVal_size = 8;
967
968 static const int slotPwrLmtScale_lbp = 16;
969 static const int slotPwrLmtScale_rbp = 15;
970 static const int slotPwrLmtScale_size = 2;
971
972 static const int physSlotNum_lbp = 31;
973 static const int physSlotNum_rbp = 19;
974 static const int physSlotNum_size = 13;
975
976 pciExpSlotCapReg(uint32_t por_val = 0x0, uint32_t mask = 0, void * d = 0, const char * name = "pcieSlotCapReg") \
977 :pciConfReg(name, 4, por_val, mask, d){}
978 // RO register. however writes to some fields cause messages to be sent.
979 // hence the write method needs to be overriden
980};
981
982class pciExpSlotCntrlReg: public pciConfReg{
983public:
984 static const int attnBtnPressEn_bp = 0;
985 static const int pwrFaultDetEn_bp = 1;
986 static const int mrlSensorChngEn_bp = 2;
987 static const int prescDetChngEn_bp = 3;
988 static const int commdCompIntEn_bp = 4;
989 static const int hotPlugIntEn_bp = 5;
990
991 static const int attnIndCntrl_lbp = 7;
992 static const int attnIndCntrl_rbp = 6;
993 static const int attnIndCntrl_size = 2;
994 enum attnIndCntrl_val {
995 attnInd_on = 1,
996 attnInd_blink = 2,
997 attnInd_off = 3
998 };
999
1000 static const int pwrIndCntrl_lbp = 9;
1001 static const int pwrIndCntrl_rbp = 8;
1002 static const int pwrIndCntrl_size = 2;
1003 enum pwrIndCntrl_val {
1004 pwrIndCntrl_on = 1,
1005 pwrIndCntrl_blink = 2,
1006 pwrIndCntrl_off = 3
1007 };
1008
1009 static const int pwrCntrlerCntrl_bp = 10;
1010 // 0 - power on, 1 power off
1011
1012 pciExpSlotCntrlReg(uint16_t por_val = 0x3c0, uint16_t mask = 0x0fff, void * d = 0, const char * name = "pcieSlotContrlReg") \
1013 :pciConfReg(name, 2, por_val, mask, d){}
1014 // por val has lights off, power on
1015 // some writes generate an interrupts.
1016 // hence the write method may need to be over-ridden
1017
1018};
1019
1020class pciExpSlotStatReg: public pciConfReg{
1021public:
1022 static const int attnBtnPrsd_bp = 0;
1023 static const int pwrFltDet_bp = 1;
1024 static const int mrlSnsrChngd_bp = 2;
1025 static const int prsnceDetChng_bp = 3;
1026 static const int cmdCmplt_bp = 4;
1027 static const int mrlSnsrState_bp = 5;
1028 static const int prsnceDetState_p = 6;
1029
1030 pciExpSlotStatReg(uint16_t por_val = 0x0, uint16_t mask = 0xf, void * d = 0, const char * name = "pcieSlotStatReg") \
1031 :pciConfReg(name, 2, por_val, mask, d){} // size 2, lowest nibble writable as w1c
1032
1033 uint8_t write(uint32_t buf, uint8_t byte_offset, uint8_t bytes_to_write){
1034 assert(bytes_to_write == 2); // if fails, write a more generic functions like in
1035 // the base class
1036
1037 uint32_t oldval = val;
1038
1039 buf &= mask; // 0 out the ro bits if any in buf
1040 buf = ~buf; // flip the 0's to 1's and vice versa
1041 val &= buf; // and with val so that bits set to 1 are turned off
1042 // bits written to with 0 are unaffected.
1043
1044 if(debug_level >= 2)
1045 printf("Name<%s>,size<0x%x>mask<0x%lx>value<0x%lx -> 0x%lx>\n",name,size,mask,oldval,val);
1046
1047 return 2;
1048 }
1049};
1050
1051
1052class pciExpRootCntrlReg: public pciConfReg{
1053public:
1054 static const int sysErrOnCorrErrEn_bp = 0;
1055 static const int sysErrOnNonFtlErrEn_bp = 1;
1056 static const int sysErrOnFtlErrEn_bp = 2;
1057 static const int pmeIntrEn_bp = 3;
1058
1059 pciExpRootCntrlReg(uint16_t por_val = 0x0, uint16_t mask = 0xf, void * d = 0, const char * name = "pcieRootCntrlReg") \
1060 : pciConfReg(name, 2, por_val, 0xf, d){} // mask=0xf rw bits
1061
1062};
1063
1064class pciExpRootStatReg: public pciConfReg{
1065public:
1066 static const int pmeReqId_lbp = 15;
1067 static const int pmeReqId_rbp = 0;
1068 static const int pmeReqId_size = 16;
1069
1070 static const int pmeStat_bp = 16;
1071 static const int pmePending_bp = 17;
1072
1073 pciExpRootStatReg(uint32_t por_val = 0, uint32_t mask = 0x10000, void * d = 0, const char * name = "pcieRootStatReg") \
1074 : pciConfReg(name, 4, por_val, mask, d){}
1075
1076 // bit 16 is rw1c. over-ride the write function
1077};
1078
1079//////////////////////////////////////
1080
1081// MSI 2.3 related regs.
1082
1083static const int msiCapId = 0x5;
1084
1085// relative offsets from start of capability structure
1086enum pciMsiCapRegOffsets{
1087 MSI_CAPID_OFFSET = 0,
1088 MSI_NEXTPTR_OFFSET = 1,
1089 MSI_MSGCNTRL_OFFSET = 2,
1090 MSI_MSGADDR0_OFFSET = 4,
1091 MSI_MSGADDR1_OFFSET = 8,
1092 MSI_MSGDATA32_OFFSET = 8,
1093 MSI_MSGDATA64_OFFSET = 0xc
1094};
1095
1096class msiCapMsgCntrl: public pciConfReg{
1097public:
1098 static const int is64bitAddrCapable_bp = 7;
1099
1100 static const int multiMsgEn_lbp = 6;
1101 static const int multiMsgEn_rbp = 4;
1102 static const int multiMsgEn_size = 3;
1103 enum multiMsgEn_val {
1104 msgEn1 = 0,
1105 msgEn2 = 1,
1106 msgEn4 = 2,
1107 msgEn8 = 3,
1108 msgEn16 = 4,
1109 msgEn32 = 5
1110 };
1111
1112
1113 static const int multiMsgCapable_lbp = 3;
1114 static const int multiMsgCapable_rbp = 1;
1115 static const int multiMsgCapable_size = 3;
1116 enum multiMsgCapable_val {
1117 msgCap1 = 0,
1118 msgCap2 = 1,
1119 msgCap4 = 2,
1120 msgCap8 = 3,
1121 msgCap16 = 4,
1122 msgCap32 = 5
1123 };
1124
1125 static const int msiEnable_bp = 0;
1126
1127 msiCapMsgCntrl(uint16_t por_val = 0, uint16_t mask = 0xf1, void* d = 0, const char * name = "pciMsiMsgCapCntrlReg") \
1128 : pciConfReg(name, 2, por_val, mask, d){}
1129
1130};
1131
1132
1133
1134
1135class pcieCommandReg:public pciConfReg{
1136 //command register reset value is 0. Device specific model should set
1137 //the write mask for this register, so that the probing software can determine
1138 //the capabilities of the device. in general if a device does not support
1139 //a particular feature/operation, the corresponding mask bit should be set
1140 //to 0 to disable writes.
1141 /*
1142 bit # Function
1143 0 Control I/O space response. Devices that do not support
1144 i/o access must h/w this bit to 0, ie bit 0 of write mask is 0
1145 1 Control memory space access.
1146 2 Control a devices ability to act as master. Devices that do
1147 not generate PCI accesses must hardwire this bit to 0
1148 6 Controls devices response to parity errors
1149 8 controls SERR#
1150 10 interrupt disable
1151 all other bits are either reserved or RDONLY hardwired to 0
1152 reference:pcie spec rev 10.2
1153 */
1154public:
1155
1156 enum commandRegBits {IO_SPACE = 0, MEM_SPACE = 1, BUS_MASTER = 2,
1157 PARITY_ERR_EN = 6, SERR_ENABLE = 8, INTR_DIS = 10};
1158
1159 pcieCommandReg(const char * name, genericPcieDev * d, uint16_t write_mask,uint16_t val=0):\
1160 pciConfReg(name,2,val,write_mask & 0x547, (void *)d){
1161
1162 if(d == 0){
1163 printf("pcie command reg constructor error: must provide genericPcieDev device pointer\n");
1164 return;
1165 }
1166 }
1167
1168 virtual uint8_t write(uint32_t buf, uint8_t byte_offset, uint8_t bytes_to_write);
1169
1170
1171private:
1172 //try to map/unmap all the base registers if they map pci space 'spc'
1173 void mapSpace(pcie_space spc);
1174 void unMapSpace(pcie_space spc);
1175};
1176
1177class pcieStatusReg:public pciConfReg{
1178 //status register provides additional information about a devices
1179 //capabilities. This register may not be 0 at reset. A device must
1180 //provide the initial value of this register at reset, as well as the mask
1181 //describing writable bits. this register is RW1C
1182 //devices set the writable bits to indicate abnormal conditions during xactns.
1183
1184public:
1185
1186 enum statusRegBits{ INTR_STAT = 0x3, MASTER_DATA_PARITY_ERROR = 0x8,\
1187 SIGNALED_TARGET_ABORT = 0xb, RECEIVED_TARGET_ABORT = 0xc, RECEIVED_MASTER_ABORT = 0xd, \
1188 SIGNALED_SYSTEM_ERROR = 0xe, DETECTED_PARITY_ERROR = 0xf};
1189
1190
1191 pcieStatusReg(const char * name, genericPcieDev * d, uint16_t init_val, uint16_t write_mask): \
1192 pciConfReg(name,2,init_val, write_mask & 0xf900 ,d){
1193
1194 if(d == 0){
1195 printf("pcie status reg constructor error: must provide genericPcieDev device pointer\n");
1196 return;
1197 }
1198 }
1199
1200 uint8_t write(uint32_t buf, uint8_t byte_offset, uint8_t bytes_to_write){
1201 assert(bytes_to_write == 2);
1202
1203 uint32_t oldval = val;
1204
1205 // if fails, write a more generic function in here.
1206 buf &= mask; // 0 out the ro bits if any in buf
1207 buf = ~buf; // flip the 0's to 1's and vice versa
1208 val &= buf; // and with val so that bits set to 1 are turned off
1209 // bits written to with 0 are unaffected.
1210
1211 if(debug_level >= 2)
1212 printf("Name<%s>,size<0x%x>mask<0x%lx>value<0x%lx -> 0x%lx>\n",name,size,mask,oldval,val);
1213
1214 return 2;
1215 }
1216
1217
1218};
1219
1220class pcieBaseAddrReg:public pciConfReg{
1221/*
1222 Format of BAR - - -
1223 I/O space bit 0 - hardwired to 1
1224 bit 1 - reserved, hardwired to 0
1225 memory space bit 0 - hardwired to 0
1226 bit [2,1] - 00 => locate anywhere in 32 bit address space
1227 - 01 => reserved
1228 - 10 => locate anywhere in 64 bit address space
1229 - 11 => reserved
1230 bit 3 - hardwired to 1 if device memory space has no side
1231 effects on reads and host bridge can merge writes
1232 into this range. (ie prefetchable)
1233*/
1234public:
1235 bool isPrefetchable; //if memory then prefetchable or not?
1236 uint32_t val_32To63; //upper 32 bits in case of 64 bit reg
1237 uint32_t mask_32To63; //mask " " " " " " etc
1238 uint64_t mapSize;
1239 bool isMapped;
1240 uint64_t oldVal;
1241 pcie_space space;
1242 int bartype;
1243
1244 static const int IO = 0x1; //0001
1245 static const int MEM32 = 0x0; //0000
1246 static const int MEM64 = 0x4; //0100
1247 static const int PREFETCH = 0x8; //1000
1248
1249public:
1250 //constructor: default is mem32, non-prefetchable mapping
1251 pcieBaseAddrReg(const char * name, genericPcieDev * d,uint64_t spaceSize,pcie_space space , bool ismem32 = true, bool isPrefetchable = false);
1252 virtual uint8_t write(uint32_t buf, uint8_t byte_offset, uint8_t bytes_to_write);
1253 uint8_t read(uint32_t *buf, uint8_t bytes_to_read, uint8_t byte_offset,uint8_t buf_offset){
1254 if(byte_offset <= 3)
1255 return pciConfReg::read(buf,bytes_to_read,byte_offset,buf_offset);
1256 // return the bytes in buf. 'bytes_to_read' bytes are filled in from (char*)buf + buf_offset
1257 // w/0 affecting the other bytes in *buf.
1258 byte_offset -= 4;
1259 uint8_t bytes_read = (4 - byte_offset) >= bytes_to_read ? bytes_to_read: 4 - byte_offset;
1260 uint64_t byte_mask = (~ ((uint64_t) -1 << bytes_read * 8));//eg for bytes_read=1, mask = 0xff
1261 *buf = (*buf & ~(byte_mask << buf_offset * 8)) | (val_32To63 >> byte_offset * 8 & byte_mask) << buf_offset * 8;
1262 return bytes_read;
1263 }
1264
1265 virtual void print(){
1266 printf("name <%s>, size<%x>", name,size);
1267 if(size == 8)
1268 printf("value <%lx %lx>, mask <%lx %lx>",val_32To63,val,mask_32To63, mask);
1269 else
1270 printf("value <%lx>, mask <%lx>",val,mask);
1271 printf(" Space<%s>Size<%llx>\n",pcie_space2name(space),mapSize);
1272 }
1273
1274 void reMap();
1275
1276 bool map();
1277 bool unmap();
1278
1279};
1280
1281
1282
1283// interface functions that need to be supported by a pcie bus.
1284class pcieBusIf{
1285public:
1286 // set the bridge interface for this bus
1287 virtual void setBridgeIf(genericPcieDevIf *) = 0;
1288
1289 virtual int busif_getBusno() = 0;
1290 // return bus number for this bus (query from the bridge). this is the secondary
1291 // bus number register in the upstream bridges conf space header.
1292
1293 virtual bool busif_map(const char * devName, pcie_space, uint64_t base, uint64_t size) = 0;
1294 // map a device into 32 bit IO or 64 bit memory space
1295 virtual bool busif_unmap(const char * devName, pcie_space, uint64_t base) = 0;
1296 // unmap a particular address space
1297 virtual bool busif_addDevice(const char * devName, int dev, int fun) = 0;
1298 // add device into internal data structures. add it to PCIE_CONF space as well.
1299 virtual bool busif_deleteDevice(const char * devName) = 0;
1300 // delete device from all the address maps.
1301
1302 virtual bool dump(const char * dir, const char* file) = 0;
1303 virtual bool restore(const char * dir, const char* file) = 0;
1304
1305 virtual mmi_instance_t getDevInstance(int dev,int fun) = 0;
1306 // NOTE1: no interrupt interface is present since only MSIs are used which are normal MEM writes
1307 // OR, INTx emulation is done using writes in MSG space.
1308
1309 // NOTE2: no dma function is present either. The dma would be done by routing normal MEM writes
1310 // from downstream devices to the bridge upstream.
1311
1312 // the following 2 functions can be used by devices to access other devices/functions
1313 // under the pcie bus
1314
1315 // access the mem, io, conf space addresses under this bus hierarchy.
1316 virtual pcieCompleter busif_access(pcie_space, bool wr, uint64_t addr, void * data, \
1317 uint16_t length, uint8_t be, uint16_t reqId, addrMd_xactnType addr64,SAM_DeviceId* samId = 0, tlp_X args = dont_care_attrs ) = 0;
1318 // addr is a 64 bit flat address into one of the mem/io/conf spaces.
1319 // the bus would call one of the devif functions based upon the space.
1320
1321 virtual pcieCompleter busif_msgAccess(uint8_t messageCode, msgRouting route, uint16_t reqId, SAM_DeviceId *samId = 0, \
1322 uint64_t tarIdOrAddr = 0x0, /*msg tlp*/ \
1323 void * data = 0, uint16_t length = 0, /* msgd tlp*/ \
1324 uint16_t vendor = 0x0, uint32_t vendor_data = 0x0, tlp_X args = dont_care_attrs ) = 0; /* vendor defined msg*/
1325 // msgs are posted xactns, hence return SIM_* values only
1326
1327 /* NOTES:
1328 1) the bus should forward all unmapped xactns to upstream bridge
1329 interface.
1330 2) the byte enables should never be non-contiguous in func sim model,
1331 because no write merging, etc is ever done.
1332 */
1333};
1334
1335
1336// interface functions that can be called by bus.
1337class genericPcieDevIf{
1338public:
1339 virtual const char *devif_getBusName()=0;
1340 virtual int devif_getDevice()=0;
1341 virtual int devif_getFunction() = 0;
1342 virtual mmi_instance_t devif_getInstance()=0;
1343 virtual const char *devif_getName()=0;
1344
1345
1346 virtual pcieCompleter devif_memAccess(bool wr, uint64_t addr, addrMd_xactnType mode, void * data,\
1347 uint16_t length, uint8_t be, uint16_t reqId, tlp_X args = dont_care_attrs, SAM_DeviceId* samId = 0) = 0;
1348
1349 // 'data' is a byte array where, the lowest addressed byte goes to
1350 // lowest addressed memory location ie (uint8_t*)data[0] <=> (uint8_t*)addr[0].
1351 // for all the accesses(mem, io, conf)
1352 // uint8_t* data corrsponds to byte-enable bit0
1353 // uint8_t* data + 1 corresponds to byte-enable bit1, and so on
1354 // since pcie is endian neutral, no byte swap will be done anywhere.
1355 // the length of the byte array will be length * 4
1356
1357 // 'length' is in number of doublewords(DW = 4 bytes).
1358 // 'be' is the byte enable mask for last and first DW.
1359 // in case of less than 4 byte r/w, the byte enable specify which
1360 // particular byte to read/write (not length).
1361
1362 virtual pcieCompleter devif_ioAccess(bool wr, uint32_t addr, void * data, uint8_t be, uint16_t reqId, \
1363 uint16_t length = 1, tlp_X args = dont_care_attrs, SAM_DeviceId * samId = 0) = 0;
1364 // only 32 bit addressing.
1365 // only 4 bytes of maximum data access,
1366 // length has to be 1, if not then error condition.
1367 // args have to be default args, if not, error condition.
1368 // 'be' should 0000xxxxb.
1369
1370 virtual pcieCompleter devif_msgAccess(uint8_t messageCode, msgRouting route, uint64_t tarIdOrAddr, uint16_t reqId, /*msg tlp*/ \
1371 void * data = 0, uint16_t length = 0, /* msgd tlp*/ \
1372 uint16_t vendorId = 0x0, uint32_t vendor_data = 0x0, tlp_X args = dont_care_attrs, SAM_DeviceId* samId = 0) = 0; /* vendor defined msg*/
1373 // address routing though supported is not used aywhere in pcie spec msg descr.
1374 // tarIdOrAddr field either encodes a 16 bit target id or a 64 bit address. route determines
1375 // which meaning is being used
1376 // posted xactns, hence return SIM_* values only
1377 // route and tarIdOrAddr is needed at device level because further routing may be done by the
1378 // intermediate bridge device in a hierarchy
1379
1380 virtual pcieCompleter devif_confAccess(bool wr, uint32_t offset, void * data, \
1381 uint8_t be, uint16_t reqId, addrMd_xactnType tType = conf_type0, uint16_t length = 1, tlp_X args = dont_care_attrs,\
1382 SAM_DeviceId *samId = 0) = 0;
1383 // 'regNo' is the 12 bit register number (offset into confSpace).
1384 // 'be' must be 0000xxxxb.
1385 // 'length' should be 1, if not, an error condition.
1386 // 'args' should be don't care defaults , else an error.
1387
1388 // NOTE: bridges should forward the conf access accordingly when a type1 conf request is received.
1389
1390 virtual void devif_confAccessCb(bool wr, uint64_t offset, uint8_t be=0xf) = 0;
1391
1392
1393 // non pure functions to be over-ridden only by bridges/root complexes
1394
1395 virtual bool devif_isBridge(){return false;}
1396 virtual bool devif_isRootCmplx(){return false;}
1397
1398 // this function should return the value of secondary bus number
1399 // from conf space header. this is the "bus number" of the bus
1400 // connected to the downstream side of this bridge.
1401 virtual int devif_getBusNo(){return -1;}
1402
1403 // return the primary bus number of the bridge device.
1404 virtual int devif_getPriBusNo(){return -1;}
1405
1406 // return subordinate bus # under the hierarchy originating from this bridge
1407 virtual int devif_getSubBusNo(){return -1;}
1408
1409
1410 // NOTE1: need these bus functions because the values are programmable by s/w
1411 // and can change anytime. Hence they should always be read from the config regs.
1412
1413 // NOTE2: there is no seperate bridge interface. A bridge exports
1414 // the interface defined by this class.
1415
1416 // NOTE3: A bridge shall map in the space of devices below its hierarchy into the
1417 // primary bus (map the range in membase/limit, iobase/limit registers etc).
1418 // The bus shall call the appropriate space access function.
1419 // the address can distinguish whether the access is to bridge internal space
1420 // or to downstream devices
1421};
1422
1423// forward declarations
1424
1425class genericPcieDev:public genericPcieDevIf, pciDebug{
1426public:
1427 const char * busName; /*upstream bus if any*/
1428 pcieBusIf * busIf; /*upstream busif*/
1429 int device;
1430 int function;
1431
1432 pciConfSpace * confSpace;
1433 bool mapSpace(pcie_space, uint64_t base, uint64_t size);
1434 bool unmapSpace(pcie_space, uint64_t base);
1435 /* (un)map address range for IO/MEM space */
1436 /* NOTE : CONF space gets mapped during busif_addDevice() */
1437
1438 //pci bus exported functions
1439 const char *devif_getBusName() { return busName;}
1440 int devif_getDevice() { return device;}
1441 int devif_getFunction() { return function;}
1442
1443
1444 //functions to be called by specific device implementation
1445 //to allow parsing of busName and attach to pcie bus, at right points of time.
1446 // these functions are implemented by this class
1447 bool dev_parse_arg(const char *arg); /*to be called from Module::parse_args()*/
1448 bool dev_check_args(); /*to be called from Module::check_arg()*/
1449 bool dev_module_added(const char *bus_name);/*to be called from Module::module_added()*/
1450 bool dev_module_deleted(const char *target_name);/*to be called from Module::module_deleted()*/
1451 void dev_init_done(int debug_level); /*to be called from Module::init_done()*/
1452 // should be called from Module::dump(restore)
1453 bool dump(const char * dump_dir,const char *dump_file);
1454 bool restore(const char * dump_dir, const char *dump_file);
1455
1456 pcieCompleter devif_memAccess(bool wr, uint64_t addr, addrMd_xactnType mode, void * data,\
1457 uint16_t length, uint8_t be, uint16_t reqId, tlp_X args, SAM_DeviceId* samId);
1458 pcieCompleter devif_ioAccess(bool wr, uint32_t addr, void * data, uint8_t be, uint16_t reqId,\
1459 uint16_t length, tlp_X args, SAM_DeviceId *samId);
1460 pcieCompleter devif_msgAccess(uint8_t messageCode, msgRouting route, uint64_t tarIdOrAddr, uint16_t reqId,/*msg tlp*/ \
1461 void * data, uint16_t length, /* msgd tlp*/ \
1462 uint16_t vendorId, uint32_t vendor_data, tlp_X args, SAM_DeviceId *samId); /* vendor defined msg*/
1463 pcieCompleter devif_confAccess(bool wr, uint32_t offset, void * data, \
1464 uint8_t be,uint16_t reqId, addrMd_xactnType tType, uint16_t length, tlp_X args,SAM_DeviceId * samId);
1465
1466 genericPcieDev(confHeaderType htype);
1467 genericPcieDev();
1468
1469 // print info about config space registers, etc.
1470 void pcieDevInfo();
1471
1472 // return the bus,dev,fun id for this module.
1473 // this could work as either completer id or requester id
1474 uint16_t getId(){ return PCIE_REQUESTER_ID(busIf->busif_getBusno(), device, function);}
1475
1476 pciExpMsgUtility *msgDB;
1477 pciExpErrUtility *errDB;
1478
1479 void initPciConfSpace(confHeaderType); // provide a default initialization
1480 // for some conf regs based upon header type
1481
1482 uint16_t pciExpCapOffset;
1483 uint16_t msiCapOffset;
1484 uint16_t aerCapOffset;
1485 bool aerCapable;
1486
1487 bool msiEnabled(){
1488 msiCapMsgCntrl * r;
1489 if(r = dynamic_cast<msiCapMsgCntrl*>(confSpace->getConfReg(msiCapOffset + MSI_MSGCNTRL_OFFSET)))
1490 return r->getBit(msiCapMsgCntrl::msiEnable_bp);
1491 else
1492 return false;
1493 }
1494
1495 void addMsiCap(uint8_t next_ptr, uint16_t offset, uint16_t msiCapMsgCntrl_reset_val = 0);
1496 // add pci2.3 Msi Capability registers to the configuration header
1497 // next_ptr - next capability offset
1498 // offset - byte offset where to add the regs,
1499 // reset_val is the the reset value of this register. tells whether it is 64 bit addr
1500 // capable and the number of messages requested
1501
1502
1503 // utility function. route a predefined pci express message.
1504 // does not include messages with TLP or vendor defined mesages.
1505 // also no messgags with id or address routing are accepted.
1506 // these messages should be sent using the busif_msgAccess directly
1507 pcieCompleter routeMsg(pciExpMsgCode code);
1508
1509 // add the advanced error capability at the specified offset.
1510 // NOTE: some extra regs for root ports are not added.
1511 void addAERCap(uint16_t capOffset, uint16_t nextCapPtr);
1512
1513 // handle an error condition from the perspective of a receiver/completer
1514 // of a TLP or as the detecting agent( eg trainingErr) of an
1515 // error condition.
1516 // process an error by setting relevent bits in status registers etc.
1517 // in case of advanced error reporting (AER) capability present,
1518 // update those registers as well.
1519 // header is a pointer to uint32_t[4] array which contains
1520 // the TLP packet header in case AER is supported and header
1521 // logging is enabled. default value is null
1522 pcieCompleter processErrorRcvrCmpltr(pciExp_Error error, uint32_t * header = 0);
1523
1524 // handle the completion of a request initiated by this device.
1525 // set the relevent bits for all the completion statu's defined
1526 // including CMPL_TO etc.
1527 // returns 0 on success (No simulation error), -1 otherwise
1528 int handleCompletion(pcieCompleter C);
1529
1530 bool isCorrErr(pciExp_Error error){
1531 switch(error){
1532 case receiverErr:
1533 case badTLP:
1534 case replayNumRollover:
1535 case replayTimerTimeout:
1536 return true;
1537 default:
1538 return false;
1539 }
1540 }
1541
1542 // "guess" the possible size of the request, given the byte enables.
1543 // NOTE: assumes upto 8 byte request.
1544 // for non contiguous byte-enables, the size is returned
1545 // as the next higher power of 2 ie for be = 0b0101 size = 4.
1546 // compliant devices should never need to use this function
1547 int byteEnabletoSize(uint8_t be){
1548 switch(be){
1549 case 0:
1550 case 1:
1551 return be;
1552 case 2:
1553 case 3:
1554 return 2;
1555 case 4:case 5:case 6:case 7:
1556 case 8:case 9:case 10:case 11:
1557 case 12:case 13:case 14:case 15:
1558 return 4;
1559 default:
1560 return 8;
1561 }
1562 }
1563
1564 /*NOTES:
1565 A) specific PCIE dev implementations should provide implementation for
1566 following virtual functions.
1567
1568 virtual mmi_instance_t devif_getInstance()=0;
1569 virtual const char *devif_getName()=0;
1570
1571 B) Specific device impl. should call
1572 pcieBusIf::busif_access() &
1573 pcieBusIf::busif_msgAccess() directly for,
1574 1) peer-to-peer IO/MEM/CONF space access or for DVMA through upstream bridge, &
1575 2) access into pcie msg space.
1576 Should not ever need to call other busIf functions. Their intended usage is for
1577 this genericPcie class impl.
1578
1579 C) The generic class provides default implementations for
1580 devif_memAccess(),devif_ioAccess() & devif_msgAccess().
1581 If these address spaces are defined by
1582 the device then these functions should be overridden.
1583 devif_confAccess() is implemented by this generic class.
1584 Normally it would not need to be overridden, except when there is some
1585 non standard behaviour, in which case it should be.
1586 Also devif_confAccessCb() is provided for specific implementations
1587 to do impl. dep. stuff on access to conf space regs. this function is
1588 called after each r/w to conf space registers from devif_confAccess().this function is
1589 left pure virtual, hence must be overridden.
1590 Other approach would be to
1591 override the default config space register impl.
1592 */
1593
1594};
1595
1596#define GENERIC_PCIE_DEV_INTERFACE "genericPcieDevIntf"
1597#define PCIE_BUS_INTERFACE "pcieBusIntf"
1598
1599#endif //_PCIE_NEW_