Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / devices / pcie_bridge / pcie_bridge.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: pcie_bridge.cc
4// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
6//
7// The above named program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public
9// License version 2 as published by the Free Software Foundation.
10//
11// The above named program is distributed in the hope that it will be
12// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// General Public License for more details.
15//
16// You should have received a copy of the GNU General Public
17// License along with this work; if not, write to the Free Software
18// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19//
20// ========== Copyright Header End ============================================
21#include "pcie_bridge.h"
22
23static const char * pcieToPcieBridge_help = "\n\
24SAM functional model for PCIE-PCIE bridge component of PLX 8532\n\
25The switch is composed by sysconf'ing individual pcie bridges\n\
26connected by an internal pcie bus (also sysconf'ed)\n\
27The following illustrates a sample configuration with the buses\n\
28numbered in DFS order.\n\
29 |--------------PCIE Bridge----------------|\n\
30 bus [0] _____|_____ \n\
31 _____________________________|______________________\n\
32| | |\n\
33| port0 (upstream) |\n\
34| internal bus [1]____________|_________________ |PCIE switch\n\
35| | | | |\n\
36| downstream port1 port2 (downstream) ... |\n\
37|________________|____________|______________________|\n\
38 | |\n\
39 bus [2] ___|___ ___|___ bus [5]\n\
40 |\n\
41 PCIE-PCI[E] bridge/PCIE device\n\
42\n\
43Sysconf format for individual pcie bridge is: \n\
44sysconf pcie_bridge <instance name> bus=<upstream bus> secbus=<downstream bus>\n\
45 dev=<device number> [upstream]\n\
46where,\n\
47 \'bus\' is the upstream bus for this bridge instance\n\
48 \'secbus\' is the secondary bus of this bridge instance\n\
49 \'dev\' is the device number on the upstream bus\n\
50 \'upstream\' is boolean parameter that designates the bridge as a switch\n\
51 upstream port. If absent the bridge is a downstream port\n\
52\n\
53Example switch config - port 0 as upstream and 1 2 8 9 as downstream\n\
54{NOTE: port is same as dev here. Can also add ports 3 10 11 as well}\n\
55#upstream port - pcie_a is primary bus of upstream bridge\n\
56sysconf pcie_bridge b0 bus=pcie_a dev=0 fun=0 secbus=pcie_int upstream\n\
57#internal virtual pcie bus\n\
58sysconf pcie_bus pcie_int bridge=b0\n\
59#downstream ports connected at upstream to pcie_int\n\
60sysconf pcie_bridge b1 bus=pcie_int dev=1 secbus=pcie_b\n\
61sysconf pcie_bridge b2 bus=pcie_int dev=2 secbus=pcie_c\n\
62sysconf pcie_bridge b3 bus=pcie_int dev=8 secbus=pcie_d\n\
63sysconf pcie_bridge b4 bus=pcie_int dev=9 secbus=pcie_e\n\
64#downstream pcie buses\n\
65sysconf pcie_bus pcie_b bridge=b1\n\
66sysconf pcie_bus pcie_c bridge=b2\n\
67sysconf pcie_bus pcie_d bridge=b3\n\
68sysconf pcie_bus pcie_e bridge=b4\n\
69\n\
70For UI help type <instance name>\n\
71For module specific info type \'modinfo <instance name>\'\n";
72
73const char *
74Module::get_help_string(){
75 return pcieToPcieBridge_help;
76}
77
78Module *
79Module::create(const char *_modname, const char *_instance_name){
80 return new PcieBridge(_modname, _instance_name);
81}
82
83
84pcieToPcieBridge_ui_cmd (void * obj, int argc, char * argv[]){
85 PcieBridge * i = dynamic_cast<PcieBridge*>((Module *)obj);
86 i->handle_ui(argc, argv);
87 return 0;
88}
89
90
91PcieBridge::PcieBridge(const char* modname, const char * instance_name)
92 : Module(modname, instance_name){
93 debug_info("PCIE-PCIE bridge: creating instance %s\n", instance_name);
94 mem32_base = mem32_limit = 0;
95 mem64_base = mem64_limit = 0;
96 io_base = io_limit = 0;
97 upstream_port = false;
98 secBusName = 0;
99 bCR = 0;
100 mmi_register_instance_cmd(getInstance(),pcieToPcieBridge_help,pcieToPcieBridge_ui_cmd);
101 pendingIntr[0] = pendingIntr[1] = pendingIntr[2] = pendingIntr[3] = false;
102 assert(pthread_mutex_init(&intMutex,0) == 0);
103
104 dump_version1_0 = strdup("v1.0"); // never change
105 current_dump_version = dump_version1_0; // change if when dump format changes,
106 // i.e. point current to new version
107 // string
108
109}
110
111PcieBridge::~PcieBridge(){
112 debug_info("%s: destructor\n", HERE);
113}
114
115const char *
116PcieBridge::get_help(){
117 return Module::get_help_string();
118}
119
120
121bool
122PcieBridge::dump(FILE * fp) {
123
124 char *dumpDir = DR_get_dir();
125 assert(dumpDir);
126 bool ret = genericPcieDev::dump (dumpDir, getName());
127
128 const int bufsize = 64 * 1024;
129 char buf[bufsize];
130 char tbuf[bufsize];
131 // intx interrupts
132 // dump the port/device numbers of downstream ports/devices
133 fprintf(fp,"%s\n",current_dump_version);
134 fprintf(fp,"downstream ports/devices with pending interrupts\n");
135 for(int i = 0; i < 4; i++){
136 sprintf(buf,"Int%c ",'A' + i);
137 list<int>::iterator listIt;
138 tbuf[0] = 0;
139 for(listIt = intLine[i].begin(); listIt != intLine[i].end(); listIt++){
140 sprintf(tbuf,"0x%x ",*listIt);
141 strcat(buf,tbuf);
142 }
143 fwrite(buf,strlen(buf),1,fp);
144 fwrite("\n",strlen("\n"),1,fp);
145 }
146
147 // now dump the intx pending status
148 fprintf(fp,"Pending interrupts to upstream bridge\n");
149 for(char i = 0; i < 4; i++)
150 fprintf(fp,"int%c-%s\n", i+'A', pendingIntr[i]? "Asserted":"Deasserted");
151 fclose(fp);
152 return ret;
153}
154
155bool
156PcieBridge::restore(FILE * fp) {
157 char *dumpDir = DR_get_dir();
158 assert(dumpDir);
159 bool ret = genericPcieDev::restore (dumpDir, getName());
160
161 const int bufsize = 64 * 1024;
162 char buf[bufsize];
163
164
165 // read the version string.
166 fgets(buf,bufsize,fp);
167 if(!strcmp(current_dump_version,buf)){
168 printf("%s: dump version unknown\n",getName());
169 assert(0);
170 }
171
172 // throw away the comment line
173 fgets(buf,bufsize,fp);
174
175 for(int i = 0; i < 4; i++){
176 fgets(buf,bufsize,fp);
177 strtok(buf," "); // intr line number, ignore
178 const char * port_val;
179 while( port_val = strtok(0," ") ){
180 if(port_val[0] == '\n')
181 break;
182 uint64_t val = strtoull(port_val,0,0);
183 intLine[i].push_back(val);
184 intLine[i].sort();
185 intLine[i].unique();
186 pendingIntr[i] = true;
187 }
188 }
189
190 // ignore the other dump data as it can be derived from data above
191
192 return ret;
193}
194
195void
196PcieBridge::initPci(){
197 char reg_descr[100];
198
199 snprintf(reg_descr, 100, "%s-%s Vender ID", devif_getName(),busName);
200 confSpace->addConfReg(new pciConfReg(reg_descr, 2,0x10b5,0x0,0x0),PCI_CONF_VENID);
201
202 snprintf(reg_descr, 100, "%s-%s Device ID", devif_getName(),busName);
203 confSpace->addConfReg(new pciConfReg(reg_descr, 2,0x8532,0x0,0x0),PCI_CONF_DEVID);
204
205 snprintf(reg_descr, 100, "%s-%s command register", devif_getName(),busName);
206 confSpace->addConfReg(new bridgeCommandReg(reg_descr,(genericPcieDev*)this,0x547,0x0),PCI_CONF_COMM);// write mask = 0x547
207
208 snprintf(reg_descr,100,"%s-%s Primary device status reg", devif_getName(),busName);
209 confSpace->addConfReg(new pcieStatusReg(reg_descr,(genericPcieDev*)this,0x0010,0xc900),PCI_CONF_STAT);//write mask = 0xc900
210// this reg has some rw1c bit fields. over-ride the pciStatusReg class r/w functions in case OS ever complains.
211
212 snprintf(reg_descr,100,"%s-%s revision id", devif_getName(),busName);
213 confSpace->addConfReg(new pciConfReg(reg_descr,1,0xbb,0x0),PCI_CONF_REVID);// rev id = 0xBB, the latest silicon revision, ro
214
215 snprintf(reg_descr,100,"%s-%s prog interface",devif_getName(),busName);
216 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x0,0x0),PCI_CONF_PROGCLASS);//0x00, ro
217
218 snprintf(reg_descr,100,"%s-%s sub class",devif_getName(),busName);
219 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x4,0x0),PCI_CONF_SUBCLASS);//0x04, ro
220
221 snprintf(reg_descr,100,"%s-%s base class",devif_getName(),busName);
222 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x06,0x0),PCI_CONF_BASCLASS);//0x06, ro
223
224 snprintf(reg_descr,100,"%s-%s cache line size",devif_getName(),busName);
225 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x0,0xff),PCI_CONF_CACHE_LINESZ);//0x00,
226
227 snprintf(reg_descr,100,"%s-%s latency timer",devif_getName(),busName);
228 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x0,0x0),PCI_CONF_LATENCY_TIMER);//0x00,
229
230 snprintf(reg_descr,100,"%s-%s Header type",devif_getName(),busName);
231 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x01,0x00),PCI_CONF_HEADER);
232
233 snprintf(reg_descr,100,"%s-%s Base Address 0",devif_getName(),busName);
234 if (upstream_port)
235 confSpace->addConfReg(new pciConfReg(reg_descr,4,0x0,0xfffe0000),PCI_CONF_BASE0); // Base Address writable
236 else
237 confSpace->addConfReg(new pciConfReg(reg_descr,4,0x0,0x0),PCI_CONF_BASE0); // Base Address read only
238
239 snprintf(reg_descr,100,"%s-%s Base Address 1",devif_getName(),busName);
240 if (upstream_port)
241 confSpace->addConfReg(new pciConfReg(reg_descr,4,0x0,0xffffffff),PCI_CONF_BASE1); // Base Address writable
242 else
243 confSpace->addConfReg(new pciConfReg(reg_descr,4,0x0,0x0),PCI_CONF_BASE1); // Base Address read only
244
245 snprintf(reg_descr,100,"%s-%s Primary Bus No",devif_getName(),busName);
246 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x00,0xff),PCI_BCNF_PRIBUS);//0x00, rw
247
248 snprintf(reg_descr,100,"%s-%s Secondary Bus No",devif_getName(),busName);
249 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x00,0xff),PCI_BCNF_SECBUS);//0x00, rw
250
251 snprintf(reg_descr,100,"%s-%s Subordinate Bus No",devif_getName(),busName);
252 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x00,0xff),PCI_BCNF_SUBBUS);//0x00, rw
253
254 snprintf(reg_descr,100,"%s-%s Secondary Latency Timer",devif_getName(),busName);
255 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x0,0x0),PCI_BCNF_LATENCY_TIMER);//0x0, RO
256
257 snprintf(reg_descr,100,"%s-%s I/O Base",devif_getName(),busName);
258 confSpace->addConfReg(new pciConfReg(reg_descr,1,0xf1,0xf0),PCI_BCNF_IO_BASE_LOW);//0xf1, rw
259
260 snprintf(reg_descr,100,"%s-%s I/O Limit",devif_getName(),busName);
261 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x01,0xf0),PCI_BCNF_IO_LIMIT_LOW);//0x01, rw
262
263 snprintf(reg_descr,100,"%s-%s Secondary Status",devif_getName(),busName);
264 confSpace->addConfReg(new pciSecondaryStatusReg(0,0xc100,0,reg_descr),PCI_BCNF_SEC_STATUS);//0x0, rw
265
266 snprintf(reg_descr,100,"%s-%s Memory Base",devif_getName(),busName);
267 confSpace->addConfReg(new pciConfReg(reg_descr,2,0xfff0,0xfff0),PCI_BCNF_MEM_BASE);//0xfff0, rw
268
269 snprintf(reg_descr,100,"%s-%s Memory Limit",devif_getName(),busName);
270 confSpace->addConfReg(new pciConfReg(reg_descr,2,0x00,0xfff0),PCI_BCNF_MEM_LIMIT);//0x00, rw
271
272 snprintf(reg_descr,100,"%s-%s Prefetchable Memory Base",devif_getName(),busName);
273 confSpace->addConfReg(new pciConfReg(reg_descr,2,0xfff1,0xfff0),PCI_BCNF_PF_BASE_LOW);//0xfff1, rw
274
275 snprintf(reg_descr,100,"%s-%s Prefetchable Memory Limit",devif_getName(),busName);
276 confSpace->addConfReg(new pciConfReg(reg_descr,2,0x01,0xfff0),PCI_BCNF_PF_LIMIT_LOW);//0x01, rw
277
278 snprintf(reg_descr,100,"%s-%s Prefetchable Memory Base Upper Portion",devif_getName(),busName);
279 confSpace->addConfReg(new pciConfReg(reg_descr,4,0x0,0xffffffff),PCI_BCNF_PF_BASE_HIGH);//0x0, rw
280
281 snprintf(reg_descr,100,"%s-%s Prefetchable Memory Limit Upper Portion",devif_getName(),busName);
282 confSpace->addConfReg(new pciConfReg(reg_descr,4,0x0,0xffffffff),PCI_BCNF_PF_LIMIT_HIGH);//0x0, rw
283
284 snprintf(reg_descr,100,"%s-%s I/O Base High",devif_getName(),busName);
285 confSpace->addConfReg(new pciConfReg(reg_descr,2,0xffff,0xffff),PCI_BCNF_IO_BASE_HI); //0xffff, rw
286
287 snprintf(reg_descr,100,"%s-%s I/O Limit High",devif_getName(),busName);
288 confSpace->addConfReg(new pciConfReg(reg_descr,2,0x0,0xffff),PCI_BCNF_IO_LIMIT_HI); //0x0, rw
289
290 snprintf(reg_descr,100,"%s-%s Capabilities List Pointer",devif_getName(),busName);
291 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x40,0x0),PCI_BCNF_CAP_PTR); //0x40, RO
292
293 snprintf(reg_descr,100,"%s-%s Interrupt Line",devif_getName(),busName);
294 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x0,0xff),PCI_BCNF_ILINE); //0x0, RW
295
296 snprintf(reg_descr,100,"%s-%s Interrupt Pin",devif_getName(),busName);
297 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x1,0x0),PCI_BCNF_IPIN); //0x1, RO
298
299 snprintf(reg_descr,100,"%s-%s Bridge control",devif_getName(),busName);
300 confSpace->addConfReg(new pciBridgeControlReg(0x0,0x5f,0,reg_descr),PCI_BCNF_BCNTRL); //0x0, RW
301
302 snprintf(reg_descr,100,"%s-%s Power Management Capability ID",devif_getName(),busName);
303 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x01,0x00),BRIDGE_POWER_CAP_ADDR); //0x01, RO
304
305 snprintf(reg_descr,100,"%s-%s Next Capability Pointer",devif_getName(),busName);
306 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x48,0x00),BRIDGE_POWER_CAP_ADDR+1); //0x48, RO
307
308 snprintf(reg_descr,100,"%s-%s ower Management Version",devif_getName(),busName);
309 confSpace->addConfReg(new pciConfReg(reg_descr,2,0xc802,0x00),BRIDGE_POWER_CAP_ADDR+2); //0xc802, RO
310
311
312 addMsiCap(BRIDGE_PCIE_CAP_ADDR, BRIDGE_MSI_CAP_ADDR, 0x80);
313
314
315 snprintf(reg_descr,100,"%s PCI Express Capability Identifier",getName());
316 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x10,0x00),BRIDGE_PCIE_CAP_ADDR + PCI_EXP_CAP_ID_OFFSET);
317
318 snprintf(reg_descr,100,"%s Next Item Pointer",getName());
319 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x0,0x0),BRIDGE_PCIE_CAP_ADDR + PCI_EXP_NXT_CAP_PTR_OFFSET);
320
321 snprintf(reg_descr,100,"%s PCI Express Capability",getName());
322 if (upstream_port)
323 confSpace->addConfReg(new pciExpCapReg(0x51,0x0,0,reg_descr),BRIDGE_PCIE_CAP_ADDR + PCI_EXP_CAP_REG_OFFSET);
324 else
325 confSpace->addConfReg(new pciExpCapReg(0x161,0x0,0,reg_descr),BRIDGE_PCIE_CAP_ADDR + PCI_EXP_CAP_REG_OFFSET);
326
327 snprintf(reg_descr,100,"%s PCI Express Device Capabilities Register",getName());
328 if (upstream_port)
329 confSpace->addConfReg(new pciExpDevCapReg(0x7001,0x0,0,reg_descr),BRIDGE_PCIE_CAP_ADDR + PCI_EXP_DEV_CAP_OFFSET);
330 else
331 confSpace->addConfReg(new pciExpDevCapReg(0x1,0x0,0,reg_descr),BRIDGE_PCIE_CAP_ADDR + PCI_EXP_DEV_CAP_OFFSET);
332
333 snprintf(reg_descr,100,"%s PCI Express Device Control Register",getName());
334 confSpace->addConfReg(new pciExpDevCntrlReg(0x0,0xef,0,reg_descr),BRIDGE_PCIE_CAP_ADDR + PCI_EXP_DEV_CTRL_OFFSET);
335
336 snprintf(reg_descr,100,"%s PCI Express Device Status Register",getName());
337 confSpace->addConfReg(new pciExpDevStatReg(0x0,0xf,0,reg_descr),BRIDGE_PCIE_CAP_ADDR + PCI_EXP_DEV_STAT_OFFSET);
338
339 snprintf(reg_descr,100,"%s PCI Express Link Capabilities Register",getName());
340 confSpace->addConfReg(new pciExpLnkCapReg(device << 24 | 0x2dc41,0x0,0x0,reg_descr),BRIDGE_PCIE_CAP_ADDR + PCI_EXP_LINK_CAP_OFFSET);
341
342 snprintf(reg_descr,100,"%s PCI Express Link Control Register",getName());
343 if (upstream_port)
344 confSpace->addConfReg(new pciExpLnkCntrlReg(0x0,0xc3,0x0,reg_descr),BRIDGE_PCIE_CAP_ADDR + PCI_EXP_LINK_CONT_OFFSET);
345 else
346 confSpace->addConfReg(new pciExpLnkCntrlReg(0x0,0xf3,0x0,reg_descr),BRIDGE_PCIE_CAP_ADDR + PCI_EXP_LINK_CONT_OFFSET);
347
348 snprintf(reg_descr,100,"%s PCI Express Link Status Register",getName());
349 confSpace->addConfReg(new pciExpLnkStatReg(0x11,0x0,0x0,reg_descr),BRIDGE_PCIE_CAP_ADDR + PCI_EXP_LINK_STAT_OFFSET);
350
351 snprintf(reg_descr,100,"%s PCI Express Slot Capabilities Register",getName());
352 if (upstream_port)
353 confSpace->addConfReg(new pciExpSlotCapReg(0x0,0x0,0x0,reg_descr),BRIDGE_PCIE_CAP_ADDR + PCI_EXP_SLOT_CAP_OFFSET);
354 else
355 confSpace->addConfReg(new pciExpSlotCapReg(0xcdf,0x0,0x0,reg_descr),BRIDGE_PCIE_CAP_ADDR + PCI_EXP_SLOT_CAP_OFFSET);
356
357 snprintf(reg_descr,100,"%s PCI Express Slot Control Register",getName());
358 if (upstream_port)
359 confSpace->addConfReg(new pciExpSlotCntrlReg(0x0,0x0,0x0,reg_descr),BRIDGE_PCIE_CAP_ADDR + PCI_EXP_SLOT_CTRL_OFFSET);
360 else
361 confSpace->addConfReg(new pciExpSlotCntrlReg(0x7c0,0x7ff,0x0,reg_descr),BRIDGE_PCIE_CAP_ADDR + PCI_EXP_SLOT_CTRL_OFFSET);
362
363 snprintf(reg_descr,100,"%s PCI Express Slot Status Register",getName());
364 if (upstream_port)
365 confSpace->addConfReg(new pciExpSlotStatReg(0x0,0x0,0x0,reg_descr),BRIDGE_PCIE_CAP_ADDR + PCI_EXP_SLOT_STAT_OFFSET);
366 else
367 confSpace->addConfReg(new pciExpSlotStatReg(0x0,0x1f,0x0,reg_descr),BRIDGE_PCIE_CAP_ADDR + PCI_EXP_SLOT_STAT_OFFSET);
368
369
370 snprintf(reg_descr,100,"%s Device Serial Number Extended Capability ID",getName());
371 confSpace->addConfReg(new pciConfReg(reg_descr,2,0x3,0x0),BRIDGE_DEV_SERNUM_XCAP_ADDR);
372
373 snprintf(reg_descr,100,"%s Device Serial Number Capability Version & Next Pointer",getName());
374 confSpace->addConfReg(new pciConfReg(reg_descr,2,0xfb41,0x0),BRIDGE_DEV_SERNUM_XCAP_ADDR + SERNUM_VER_NXTPTR_OFFSET);
375
376 snprintf(reg_descr,100,"%s Device Serial Number Low",getName());
377 confSpace->addConfReg(new pciConfReg(reg_descr,4,0xedf,0x0),BRIDGE_DEV_SERNUM_XCAP_ADDR + SERNUM_SN_LOW_OFFSET);
378
379 snprintf(reg_descr,100,"%s Device Serial Number High",getName());
380 confSpace->addConfReg(new pciConfReg(reg_descr,4,0x1,0x0),BRIDGE_DEV_SERNUM_XCAP_ADDR + SERNUM_SN_HIGH_OFFSET);
381
382
383 addAERCap(BRIDGE_ADV_ERR_CAP_ADDR, BRIDGE_PWRBGT_HDR_ADDR);
384
385
386 snprintf(reg_descr,100,"%s Power Budgeting Enhanced Capability Header",getName());
387 confSpace->addConfReg(new pciConfReg(reg_descr,4,0x14810004,0x0),BRIDGE_PWRBGT_HDR_ADDR);
388
389 snprintf(reg_descr,100,"%s Power Budgeting Data Select Register",getName());
390 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x0,0xff),BRIDGE_PWRBGT_HDR_ADDR + PWRBGT_DSEL_OFFSET);
391
392 snprintf(reg_descr,100,"%s Power Budgeting Data Register",getName());
393 confSpace->addConfReg(new pciConfReg(reg_descr,4,0x0,0x0),BRIDGE_PWRBGT_HDR_ADDR + PWRBGT_DATA_OFFSET);
394
395 snprintf(reg_descr,100,"%s Power Budget Capability",getName());
396 confSpace->addConfReg(new pciConfReg(reg_descr,4,0x1,0x0),BRIDGE_PWRBGT_HDR_ADDR + PWRBGT_DATA_CAP_OFFSET);
397
398}
399
400void
401PcieBridge::init_done(){
402 initPci();
403 dev_init_done(debug_level);
404 mem32_base = GET_MEM_BASE(confSpace);
405 mem32_limit = GET_MEM_LIMIT(confSpace);
406 io_base = GET_IO_BASE(confSpace);
407 io_limit = GET_IO_LIMIT(confSpace);
408 mem64_base = GET_PF_MEM_BASE(confSpace);
409 mem64_limit = GET_PF_MEM_LIMIT(confSpace);
410 bCR = (bridgeCommandReg*)confSpace->getConfReg(PCI_CONF_COMM);
411}
412
413void
414PcieBridge::module_added(mmi_instance_t target, const char *target_name){
415 if (secBusName && !strcmp(target_name,secBusName)){
416 secBusIf = (pcieBusIf*)mmi_get_interface(target, PCIE_BUS_INTERFACE);
417 secBusIf->setBridgeIf((genericPcieDevIf*)this);
418 }
419 if(busName && !strcmp(target_name, busName)){
420 busIf = (pcieBusIf*)mmi_get_interface(target, PCIE_BUS_INTERFACE);
421 }
422 dev_module_added(target_name);
423}
424
425void
426PcieBridge::module_deleted(mmi_instance_t target, const char *target_name){
427 dev_module_deleted(target_name);
428}
429
430void
431PcieBridge::modinfo(){
432 printf("%s: pcie-pcie virtual bridge device component of PLX 8532\n",getName());
433 printf("device id <0x%lx>, vendor id <0x%lx>\n",confSpace->readConf(PCI_CONF_VENID),\
434 confSpace->readConf(PCI_CONF_DEVID));
435 printf("The port type is %s\n",upstream_port?"Upstream":"Downstream");
436 printf("Upstream pcie bus is <%s>, secondary pcie bus is <%s>\n",busName,secBusName);
437 printf("To display pcie config regs, type \'%s dump\'\n",getName());
438}
439
440bool
441PcieBridge::parse_arg(const char *arg){
442
443 if (argval("secbus",arg,&secBusName)) {
444 debug_more("%s:secondary bus = %s\n",getName(),secBusName);
445 return true;
446 }else if (!strcmp(arg, "upstream")){
447 debug_more("%s: port type <Upstream>\n",getName());
448 upstream_port = true;
449 return true;
450 } else
451 return dev_parse_arg(arg);
452}
453
454bool
455PcieBridge::check_args(){
456 if(!secBusName){
457 debug_err("%s: ERROR: must specify a secondary PCIE bus\n", getName());
458 return false;
459 }else
460 return dev_check_args();
461}
462
463void*
464PcieBridge::get_interface(const char *name){
465 if (!strcmp(name, GENERIC_PCIE_DEV_INTERFACE))
466 return (genericPcieDevIf*)this;
467 else if(!strcmp(name, PCI_BRIDGE_INTERFACE))
468 return (pciBridgeIf*)this;
469 else return 0;
470}
471
472
473void
474PcieBridge::devif_confAccessCb(bool wr, uint64_t offset, uint8_t be){
475 if (!wr)
476 return;
477
478 switch (offset) {
479 case PCI_BCNF_PF_BASE_HIGH:
480 case PCI_BCNF_PF_BASE_LOW:
481 case PCI_BCNF_PF_LIMIT_HIGH:
482 case PCI_BCNF_PF_LIMIT_LOW:
483 if (!mem_mapped()){
484 mem64_base = GET_PF_MEM_BASE(confSpace);
485 mem64_limit = GET_PF_MEM_LIMIT(confSpace);
486 return;
487 }else{
488 if(mem64_base < mem64_limit){
489 debug_more("%s unmap MEM64[%llx %llx]\n",getName(), mem64_base, mem64_limit);
490 unmapSpace(PCIE_MEM, mem64_base);
491 }
492 mem64_base = GET_PF_MEM_BASE(confSpace);
493 mem64_limit = GET_PF_MEM_LIMIT(confSpace);
494 if (mem64_base < mem64_limit) {
495 debug_more("%s remap: MEM64 [%llx %llx]\n", getName(), mem64_base, mem64_limit);
496 mapSpace(PCIE_MEM, mem64_base, mem64_limit - mem64_base + 1);
497 }
498 }
499 break;
500 case PCI_BCNF_MEM_BASE:
501 case PCI_BCNF_MEM_LIMIT:
502 if (!mem_mapped()){
503 mem32_base = GET_MEM_BASE(confSpace);
504 mem32_limit = GET_MEM_LIMIT(confSpace);
505 return;
506 }else{
507 if(mem32_base < mem32_limit){
508 debug_more("%s unmap: MEM[%lx %lx]\n",getName(), mem32_base, mem32_limit);
509 unmapSpace(PCIE_MEM, mem32_base);
510 }
511 mem32_base = GET_MEM_BASE(confSpace);
512 mem32_limit = GET_MEM_LIMIT(confSpace);
513 if (mem32_base < mem32_limit) {
514 debug_more("%s remap: MEM[%lx %lx]\n",getName(), mem32_base, mem32_limit);
515 mapSpace(PCIE_MEM, mem32_base, mem32_limit - mem32_base);
516 }
517 }
518 break;
519 case PCI_BCNF_IO_BASE_LOW:
520 case PCI_BCNF_IO_LIMIT_LOW:
521 case PCI_BCNF_IO_BASE_HI:
522 case PCI_BCNF_IO_LIMIT_HI:
523 if (!io_mapped()){
524 io_base = GET_IO_BASE(confSpace);
525 io_limit = GET_IO_LIMIT(confSpace);
526 return;
527 }else{
528 if(io_base < io_limit){
529 debug_more("%s unmap: IO[%lx %lx]\n",getName(), io_base, io_limit);
530 unmapSpace(PCIE_IO, io_base);
531 }
532 io_base = GET_IO_BASE(confSpace);
533 io_limit = GET_IO_LIMIT(confSpace);
534 if (io_base < io_limit) {
535 debug_more("%s remap: IO[%lx %lx]\n",getName(), io_base, io_limit);
536 mapSpace(PCIE_IO, io_base, io_limit - io_base);
537 }
538 }
539 break;
540 default: return;
541 }
542 return;
543}
544
545pcieCompleter
546PcieBridge::devif_confAccess(bool wr, uint32_t addr, void * data, uint8_t be, uint16_t reqId, addrMd_xactnType tType, uint16_t length, tlp_X args, SAM_DeviceId *id) {
547
548 uint32_t l_buf;
549 int size = byteEnabletoSize(be); // length is the number of words
550
551 if (tType == conf_type1) {
552 pcieCompleter ret;
553 if(wr)
554 debug_more("%s:conf wr xactn type 1: addr <0x%x> size <%d> byte_en<0x%x> data<0x%llx>\n",
555 getName(), addr, size, be,*(uint64_t*)data);
556
557 // Change requester ID to bridge's ID for the handling in pcieBus::busif_access():
558 ret = secBusIf->busif_access(PCIE_CFG, wr, addr, (uint64_t *)data, length, be, getId(), tType, id, args);
559
560 if(!wr)
561 debug_more("%s:conf rd xactn type 1: addr <0x%x> size <%d> byte_en<0x%x> data<0x%llx>\n",
562 getName(), addr, size, be, *(uint64_t*)data);
563 if(debug_level >= 2) printf("\n");
564
565 return ret;
566
567 } else {
568 bool ret;
569 if(id)
570 *id = samId;
571
572 if (addr >= 0x1000) {
573 debug_err("Config address higher than 4K!\n");
574 return pcieCompleter(UR,getId());
575 }
576
577 if(wr){
578 *(uint64_t*)data &= 0xffffffff;
579 l_buf = *(uint64_t*)data;
580 if(size == 4){
581 *(uint64_t*)data = swap_word(l_buf);
582 }else if(size == 2){
583 *(uint64_t*)data = swap_hword(l_buf);
584 }else if (size == 1)
585 *(uint64_t*)data = l_buf;
586 debug_more("%s:conf xactn type 0: addr <0x%x> wr size <%d> byte_en<0x%x> data<0x%llx>\n",
587 getName(), addr,size, be,*(uint64_t*)data);
588 }
589 ret = confSpace->confAccessSize(addr, wr, (uint64_t *)data, size);
590 if(!wr){
591 l_buf = *(uint64_t*)data;
592 if(size == 4){
593 *(uint64_t*)data = swap_word(l_buf & 0xFFFFFFFF);
594 }else if(size == 2){
595 *(uint64_t*)data = swap_hword(l_buf & 0xFFFF);
596 }else if (size == 1)
597 *(uint64_t*)data = l_buf & 0xFF;
598
599 debug_more("%s:conf xactn type 0: addr <0x%x> rd size <%d> byte_en<0x%x> data<0x%llx>\n",
600 getName(), addr, size, be, *(uint64_t*)data);
601 if(debug_level >= 2) printf("\n");
602
603 }
604
605 devif_confAccessCb(wr,addr,be);
606 return (ret ? pcieCompleter(SC,getId()) : pcieCompleter(CA,getId()));
607 }
608}
609
610pcieCompleter
611PcieBridge::devif_memAccess(bool wr, uint64_t addr, addrMd_xactnType mode, void * data, uint16_t length, uint8_t be, uint16_t reqId, tlp_X args, SAM_DeviceId *id) {
612 direction_t direct = direction(busIf->busif_getBusno(), reqId);
613
614 debug_more("%s: %s %s %s access at <0x%llx> of length <%4d> byte_en <0x%x> \n",
615 getName(),
616 direct == downstream ? "downstream":"upstream ",
617 mode == mem_addr32 ? "mem32" : "mem64",
618 wr ? "wr":"rd",
619 addr,
620 length, be);
621
622 if ((direct == downstream) && (addr >= mem32_base && addr < mem32_limit || addr >= mem64_base && addr < mem64_limit)) {
623 return secBusIf->busif_access(PCIE_MEM, wr, addr, (uint64_t *)data, length, be, reqId, mode, id, args);
624 } else if ((direct == upstream) && ((addr < mem32_base || addr >= mem32_limit ) && (addr < mem64_base || addr >= mem64_limit))) {
625 return busIf->busif_access(PCIE_MEM, wr, addr, (uint64_t *)data, length, be, reqId, mode, id, args);
626 } else
627 return pcieCompleter(UR,getId());
628}
629
630pcieCompleter
631PcieBridge::devif_ioAccess(bool wr, uint64_t addr, void * data, uint8_t be, uint16_t reqId, uint16_t length, tlp_X args, SAM_DeviceId *id) {
632 direction_t direct = direction(busIf->busif_getBusno(), reqId);
633
634 debug_more("%s: %s %s %s access at <0x%llx> length <%d> be <0x%x> \n",
635 getName(), direct == downstream ? "downstream":"upstream ",
636 "IO", wr ? "wr":"rd", addr, length, be);
637
638 if ((direct == downstream) && addr >= io_base && addr < io_limit) {
639 return secBusIf->busif_access(PCIE_IO, wr, addr, (uint64_t *)data, length, be, reqId, mem_addr32, id, args);
640 } else if ((direct == upstream) && (addr < io_base || addr >= io_limit)) {
641 return busIf->busif_access(PCIE_IO, wr, addr, (uint64_t *)data, length, be, reqId, mem_addr32, id, args);
642 } else
643 return pcieCompleter(UR,getId());
644}
645
646pcieCompleter
647PcieBridge::devif_msgAccess(uint8_t messageCode, msgRouting route, uint64_t tarIdOrAddr, uint16_t reqId, void * data, uint16_t length, uint16_t vendorId, uint32_t vendor_data, tlp_X args, SAM_DeviceId *id){
648 switch(route){
649 case routed_to_RC:
650 case gathered_routed_to_RC:
651 return busIf->busif_msgAccess(messageCode,route,reqId,id,tarIdOrAddr,data,length,vendorId,
652 vendor_data, args);
653 break;
654 case local:
655 // intx message from downstream device or port.
656 if(messageCode >= MSG_Assert_INTA && messageCode <= MSG_Assert_INTD)
657 return assertIntx((pciExpMsgCode)messageCode, reqId, id);
658 else if(messageCode >= MSG_Deassert_INTA && messageCode <= MSG_Deassert_INTD)
659 return deassertIntx((pciExpMsgCode)messageCode, reqId, id);
660 else{
661 debug_err("%s: don;t know how to handle message 0x%x\n", getName(), messageCode);
662 return pcieCompleter(SIM_FAIL);
663 }
664 break;
665 case broadcast_from_RC:
666 return secBusIf->busif_msgAccess(messageCode,route,reqId,id, tarIdOrAddr,data,length,vendorId,vendor_data, args);
667 break;
668 case routed_by_addr:
669 debug_err("%s: address routing unsupported\n", getName());
670 break;
671 case routed_by_id:
672 debug_err("%s: ID routing unsupported\n", getName());
673 break;
674 default:
675 debug_err("%s: unknown message routing type %x\n",getName(),route);
676 return pcieCompleter(SIM_FAIL);
677 }
678 return pcieCompleter(SIM_OK);
679}
680
681
682void PcieBridge::handle_ui(int argc, char * argv[]){
683 if(argc == 1){
684 ui_cmd_usage();
685 return;
686 }else if(!strcmp(argv[1],"dump")){
687 char * dumpDir;
688 char buf[1024];
689 dumpDir = getcwd(buf,1024);
690 assert( errno != ERANGE);
691 genericPcieDev::dump (dumpDir, argv[2]);
692 }else if(!strcmp(argv[1],"restore")){
693 if(argv[2]){
694 char *dumpDir;
695 char buf[1024];
696 dumpDir = getcwd(buf,1024);
697 assert( errno != ERANGE);
698 genericPcieDev::restore (dumpDir, argv[2]);
699 }else
700 printf("%s restore: no restore filename specified\n",getName());
701 }else if(!strcmp(argv[1],"debug")){
702 if(argv[2]){
703 debug_level = atoi(argv[2]);
704 confSpace->set_debug_level(debug_level);
705 printf("%s: set debug level to %d\n",getName(),debug_level);
706 }else
707 printf("%s: current debug level %d\n",getName(),debug_level);
708
709 }else
710 debug_err("%s: unsupported UI command <%s>\n",getName(),argv[1]);
711
712 return;
713}
714