Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / devices / bridge / bridge.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: 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 "bridge.h"
22#include <unistd.h>
23#include <assert.h>
24#include <errno.h>
25
26static const char * pcieToPciBridge_help = "\n\
27SAM model for Intel 41210 Serial to Parallel PCIE-PCI bridge\n\
28Sysconf format is:\n\
29sysconf bridge <instance name> bus=<primary bus> dev=<device> fun=<function> secbus=<secondary bus>\n\
30 <instance name> is any user specified name for the module\n\
31 <primary bus> is the instance name of the upstream pcie bus module\n\
32 <device> is the device number of bridge on upstream pcie bus\n\
33 <function> is the function number of bridge on upstream pcie bus\n\
34 <secondary bus> is the instance name of the downstream pci bus module\n\
35For UI help type <instance name>\n\
36For module specific info type \'modinfo <instance name>\'";
37
38pcieToPciBridge_ui_cmd (void * obj, int argc, char * argv[]){
39 pcieToPciBridge * i = dynamic_cast<pcieToPciBridge*>((Module *)obj);
40 i->handle_ui(argc, argv);
41 return 0;
42}
43
44
45#define BRIDGE_CAP_STRUCT_ADDR 0x44
46#define BRIDGE_MSI_CAP_ADDR 0x5c
47#define BRIDGE_POWER_CAP_ADDR 0x6c
48#define BRIDGE_PCIX_CAP_ADDR 0xd8
49#define BRIDGE_AER_CAP_OFFSET 0x100
50#define BRIDGE_POWER_BUDGET_CAP_OFFSET 0x300
51
52
53const char *
54Module::get_help_string(){
55 return pcieToPciBridge_help;
56}
57
58Module *
59Module::create(const char *_modname, const char *_instance_name){
60 return new pcieToPciBridge(_modname, _instance_name);
61}
62
63
64
65pcieToPciBridge::pcieToPciBridge(const char* modname, const char * instance_name)
66 : Module(modname, instance_name){
67 debug_info("Pcie bridge: creating instance %s\n", instance_name);
68 mem32_base = mem32_limit = 0;
69 mem64_base = mem64_limit = 0;
70 io_base = io_limit = 0;
71 bCR = 0;
72 mmi_register_instance_cmd(getInstance(),pcieToPciBridge_help,pcieToPciBridge_ui_cmd);
73 pendingIntr[0] = pendingIntr[1] = pendingIntr[2] = pendingIntr[3] = false;
74 assert(pthread_mutex_init(&intMutex,0) == 0);
75 dump_version1_0 = strdup("v1.0"); // never change
76 current_dump_version = dump_version1_0; // change if when dump format changes,
77 // i.e. point current to new version
78 // string
79}
80
81pcieToPciBridge::~pcieToPciBridge(){
82 debug_info("%s: destructor\n", HERE);
83}
84
85const char *
86pcieToPciBridge::get_help(){
87 return Module::get_help_string();
88}
89
90
91void
92pcieToPciBridge::initPci(){
93 char reg_descr[100];
94
95 snprintf(reg_descr, 100, "%s-%s Vender ID", devif_getName(),busName);
96 confSpace->addConfReg(new pciConfReg(reg_descr, 2,0x8086,0x0,0x0),PCI_CONF_VENID);
97
98 snprintf(reg_descr, 100, "%s-%s Device ID", devif_getName(),busName);
99 confSpace->addConfReg(new pciConfReg(reg_descr, 2,function?0x0341:0x0340,0x0,0x0),PCI_CONF_DEVID);
100
101 snprintf(reg_descr, 100, "%s-%s command register", devif_getName(),busName);
102 confSpace->addConfReg(new bridgeCommandReg(reg_descr,(genericPcieDev*)this,0x547,0x0),PCI_CONF_COMM);// write mask = 0x547
103
104 snprintf(reg_descr,100,"%s-%s Primary device status reg", devif_getName(),busName);
105 confSpace->addConfReg(new pcieStatusReg(reg_descr,(genericPcieDev*)this,0x10,0xf900),PCI_CONF_STAT);//write mask = 0xf900
106 // this reg has some rw1c bit fields. over-ride the pciStatusReg class r/w functions in case OS ever complains.
107
108 snprintf(reg_descr,100,"%s-%s revision id", devif_getName(),busName);
109 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x0,0x0,0x0),PCI_CONF_REVID);// rev id = 0x00, ro
110
111 snprintf(reg_descr,100,"%s-%s prog interface",devif_getName(),busName);
112 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x0,0x0),PCI_CONF_PROGCLASS);//0x00, ro
113
114 snprintf(reg_descr,100,"%s-%s sub class",devif_getName(),busName);
115 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x4,0x0),PCI_CONF_SUBCLASS);//0x04, ro
116
117 snprintf(reg_descr,100,"%s-%s base class",devif_getName(),busName);
118 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x06,0x0),PCI_CONF_BASCLASS);//0x06, ro
119
120 snprintf(reg_descr,100,"%s-%s cache line size",devif_getName(),busName);
121 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x0,0xff),PCI_CONF_CACHE_LINESZ);//0x00,
122
123 snprintf(reg_descr,100,"%s-%s latency timer",devif_getName(),busName);
124 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x0,0x0),PCI_CONF_LATENCY_TIMER);//0x00,
125
126 snprintf(reg_descr,100,"%s-%s Header type",devif_getName(),busName);
127 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x81,0x00),PCI_CONF_HEADER);
128
129 snprintf(reg_descr,100,"%s-%s Primary Bus No",devif_getName(),busName);
130 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x00,0xff),PCI_BCNF_PRIBUS);//0x00, rw
131
132 snprintf(reg_descr,100,"%s-%s Secondary Bus No",devif_getName(),busName);
133 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x00,0xff),PCI_BCNF_SECBUS);//0x00, rw
134
135 snprintf(reg_descr,100,"%s-%s Subordinate Bus No",devif_getName(),busName);
136 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x00,0xff),PCI_BCNF_SUBBUS);//0x00, rw
137
138 snprintf(reg_descr,100,"%s-%s Secondary Master Latency Timer",devif_getName(),busName);
139 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x40,0xf8),PCI_BCNF_LATENCY_TIMER);//0x40, rw
140
141 snprintf(reg_descr,100,"%s-%s I/O Base",devif_getName(),busName);
142 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x00,0xf0),PCI_BCNF_IO_BASE_LOW);//0x00, rw
143
144 snprintf(reg_descr,100,"%s-%s I/O Limit",devif_getName(),busName);
145 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x00,0xf0),PCI_BCNF_IO_LIMIT_LOW);//0x00, rw
146
147 snprintf(reg_descr,100,"%s-%s Secondary Status",devif_getName(),busName);
148 confSpace->addConfReg(new pciSecondaryStatusReg(0x2a,0xf900,0,reg_descr),PCI_BCNF_SEC_STATUS);//0x2a, rw
149
150 snprintf(reg_descr,100,"%s-%s Memory Base",devif_getName(),busName);
151 confSpace->addConfReg(new pciConfReg(reg_descr,2,0x00,0xfff0),PCI_BCNF_MEM_BASE);//0x00, rw
152
153 snprintf(reg_descr,100,"%s-%s Memory Limit",devif_getName(),busName);
154 confSpace->addConfReg(new pciConfReg(reg_descr,2,0x00,0xfff0),PCI_BCNF_MEM_LIMIT);//0x00, rw
155
156 snprintf(reg_descr,100,"%s-%s Prefetchable Memory Base",devif_getName(),busName);
157 confSpace->addConfReg(new pciConfReg(reg_descr,2,0x01,0xfff0),PCI_BCNF_PF_BASE_LOW);//0x01, rw
158
159 snprintf(reg_descr,100,"%s-%s Prefetchable Memory Limit",devif_getName(),busName);
160 confSpace->addConfReg(new pciConfReg(reg_descr,2,0x01,0xfff0),PCI_BCNF_PF_LIMIT_LOW);//0x01, rw
161
162 snprintf(reg_descr,100,"%s-%s Prefetchable Memory Base Upper Portion",devif_getName(),busName);
163 confSpace->addConfReg(new pciConfReg(reg_descr,4,0x0,0xffffffff),PCI_BCNF_PF_BASE_HIGH);//0x0, rw
164
165 snprintf(reg_descr,100,"%s-%s Prefetchable Memory Limit Upper Portion",devif_getName(),busName);
166 confSpace->addConfReg(new pciConfReg(reg_descr,4,0x0,0xffffffff),PCI_BCNF_PF_LIMIT_HIGH);//0x0, rw
167
168 snprintf(reg_descr,100,"%s-%s I/O Base High",devif_getName(),busName);
169 confSpace->addConfReg(new pciConfReg(reg_descr,2,0x0,0x0),PCI_BCNF_IO_BASE_HI); //0x0, RO
170
171 snprintf(reg_descr,100,"%s-%s I/O Limit High",devif_getName(),busName);
172 confSpace->addConfReg(new pciConfReg(reg_descr,2,0x0,0x0),PCI_BCNF_IO_LIMIT_HI); //0x0, RO
173
174 snprintf(reg_descr,100,"%s-%s Capabilities List Pointer",devif_getName(),busName);
175 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x44,0x0),PCI_BCNF_CAP_PTR); //0x44, RO
176
177 snprintf(reg_descr,100,"%s-%s Interrupt Line",devif_getName(),busName);
178 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x0,0xff),PCI_BCNF_ILINE); //0x0, RW
179
180 snprintf(reg_descr,100,"%s-%s Interrupt Pin",devif_getName(),busName);
181 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x0,0x0),PCI_BCNF_IPIN); //0x0, RO
182
183 snprintf(reg_descr,100,"%s-%s Bridge control",devif_getName(),busName);
184 confSpace->addConfReg(new pciBridgeControlReg(0x0,0xf7f,0x0,reg_descr),PCI_BCNF_BCNTRL); //0x0, RW
185
186 snprintf(reg_descr,100,"%s-%s Bridge configuration",devif_getName(),busName);
187 confSpace->addConfReg(new pciConfReg(reg_descr,2,0x2880,0x4683),PCI_BCNF_BCNF); //0x2880, RW
188
189 snprintf(reg_descr,100,"%s-%s Multi-Transaction Timer",devif_getName(),busName);
190 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x0,0xf8),PCI_BCNF_MTT); //0x0, RW
191
192 snprintf(reg_descr,100,"%s-%s PCI Clock Control",devif_getName(),busName);
193 confSpace->addConfReg(new pciConfReg(reg_descr,1,0xdf,0x7f),PCI_BCNF_PCLKC); //0xdf, RW
194
195 snprintf(reg_descr,100,"%s PCI Express Capability Identifier",getName());
196 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x10,0x00),BRIDGE_CAP_STRUCT_ADDR + PCI_EXP_CAP_ID_OFFSET);//ro
197
198 snprintf(reg_descr,100,"%s Next Item Pointer",getName());
199 confSpace->addConfReg(new pciConfReg(reg_descr,1,BRIDGE_MSI_CAP_ADDR,0x0),BRIDGE_CAP_STRUCT_ADDR + PCI_EXP_NXT_CAP_PTR_OFFSET);//, ro
200
201 snprintf(reg_descr,100,"%s PCI Express Capability",getName());
202 confSpace->addConfReg(new pciExpCapReg(0x71,0x0,0,reg_descr),BRIDGE_CAP_STRUCT_ADDR + PCI_EXP_CAP_REG_OFFSET);//0x1
203
204 snprintf(reg_descr,100,"%s PCI Express Device Capabilities Register",getName());
205 confSpace->addConfReg(new pciExpDevCapReg(0x1,0x0,0,reg_descr),BRIDGE_CAP_STRUCT_ADDR + PCI_EXP_DEV_CAP_OFFSET);//
206
207 snprintf(reg_descr,100,"%s PCI Express Device Control Register",getName());
208 confSpace->addConfReg(new pciExpDevCntrlReg(0x2000,0xf0ef,0,reg_descr),BRIDGE_CAP_STRUCT_ADDR + PCI_EXP_DEV_CTRL_OFFSET);//
209
210 snprintf(reg_descr,100,"%s PCI Express Device Status Register",getName());
211 confSpace->addConfReg(new pciExpDevStatReg(0x0,0xf,0,reg_descr),BRIDGE_CAP_STRUCT_ADDR + PCI_EXP_DEV_STAT_OFFSET);//
212
213 snprintf(reg_descr,100,"%s PCI Express Link Capabilities Register",getName());
214 confSpace->addConfReg(new pciExpLnkCapReg(0x3e481,0x0,0x0,reg_descr),BRIDGE_CAP_STRUCT_ADDR + PCI_EXP_LINK_CAP_OFFSET);//
215
216 snprintf(reg_descr,100,"%s PCI Express Link Control Register",getName());
217 confSpace->addConfReg(new pciExpLnkCntrlReg(0x0,0xc3,0x0,reg_descr),BRIDGE_CAP_STRUCT_ADDR + PCI_EXP_LINK_CONT_OFFSET);//
218
219 snprintf(reg_descr,100,"%s PCI Express Link Status Register",getName());
220 confSpace->addConfReg(new pciExpLnkStatReg(0x1081,0x0,0x0,reg_descr),BRIDGE_CAP_STRUCT_ADDR + PCI_EXP_LINK_STAT_OFFSET);//
221
222 addMsiCap(BRIDGE_POWER_CAP_ADDR, BRIDGE_MSI_CAP_ADDR, 0x80);
223 addAERCap(BRIDGE_AER_CAP_OFFSET,BRIDGE_POWER_BUDGET_CAP_OFFSET);
224
225 // pcix power management registers
226 snprintf(reg_descr,100,"%s PM_CAPID",getName());
227 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x1,0x0),0x6c);
228 snprintf(reg_descr,100,"%s PM_NXTP",getName());
229 confSpace->addConfReg(new pciConfReg(reg_descr,1,0xd8,0x0),0x6d);
230 snprintf(reg_descr,100,"%s PM_PMC",getName());
231 confSpace->addConfReg(new pciConfReg(reg_descr,2,0xc802,0x0),0x6e);
232 snprintf(reg_descr,100,"%s PM_PMCSR",getName());
233 confSpace->addConfReg(new pciConfReg(reg_descr,2,0x0,0x3),0x70);
234 snprintf(reg_descr,100,"%s PM_BSE",getName());
235 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x0,0x0),0x72);
236 snprintf(reg_descr,100,"%s PM_DATA",getName());
237 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x0,0x0),0x73);
238
239 // pcix capability id
240 snprintf(reg_descr,100,"%s PM_CAPID",getName());
241 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x7,0x0),0xd8);
242 snprintf(reg_descr,100,"%s PM_NXTP",getName());
243 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x0,0x0),0xd9);
244
245
246 // pcix registers
247 snprintf(reg_descr,100,"%s PX_SSTS",getName());
248 confSpace->addConfReg(new pciConfReg(reg_descr,2,0x3,0x0),0xda);
249 snprintf(reg_descr,100,"%s PX_BSTS",getName());
250 confSpace->addConfReg(new pciConfReg(reg_descr,4,0x0,0x0),0xdc);
251 snprintf(reg_descr,100,"%s PX_USTC",getName());
252 confSpace->addConfReg(new pciConfReg(reg_descr,4,0xffffffff,0xffff0000),0xe0);
253 snprintf(reg_descr,100,"%s PX_DSTC",getName());
254 confSpace->addConfReg(new pciConfReg(reg_descr,4,0xffffffff,0xffff0000),0xe4);
255 snprintf(reg_descr,100,"%s BINIT",getName());
256 confSpace->addConfReg(new pciConfReg(reg_descr,4,0x3,0x1f),0xfc);
257
258
259 // pcix error registers
260 snprintf(reg_descr,100,"%s PCIXERRUNC_PTR",getName());
261 confSpace->addConfReg(new pciConfReg(reg_descr,2,0x0,0x0),0x138);
262 snprintf(reg_descr,100,"%s PCIEXERRUNC_SEV",getName());
263 confSpace->addConfReg(new pciConfReg(reg_descr,2,0x0,0xffff),0x134);
264 snprintf(reg_descr,100,"%s PCIEXRRUNC_MSK",getName());
265 confSpace->addConfReg(new pciConfReg(reg_descr,2,0x20,0xffff),0x130);
266 snprintf(reg_descr,100,"%s PCIXERRUNC_STS",getName());
267 confSpace->addConfReg(new pciConfReg(reg_descr,2,0x0,0xffff),0x12c);
268
269 snprintf(reg_descr,100,"%s PCIXHDR_LOG0",getName());
270 confSpace->addConfReg(new pciConfReg(reg_descr,4,0x0,0x0),0x13c);
271 snprintf(reg_descr,100,"%s PCIXHDR_LOG1",getName());
272 confSpace->addConfReg(new pciConfReg(reg_descr,4,0x0,0x0),0x140);
273 snprintf(reg_descr,100,"%s PCIXHDR_LOG2",getName());
274 confSpace->addConfReg(new pciConfReg(reg_descr,4,0x0,0x0),0x144);
275 snprintf(reg_descr,100,"%s PCIXHDR_LOG3",getName());
276 confSpace->addConfReg(new pciConfReg(reg_descr,4,0x0,0x0),0x148);
277
278 snprintf(reg_descr,100,"%s ARB_CNTRL",getName());
279 confSpace->addConfReg(new pciConfReg(reg_descr,2,0xff,0xffff),0x16a);
280 snprintf(reg_descr,100,"%s SSR",getName());
281 confSpace->addConfReg(new pciConfReg(reg_descr,2,0x0,0x0),0x170);
282 snprintf(reg_descr,100,"%s PREFCTRL-Lower",getName());
283 confSpace->addConfReg(new pciConfReg(reg_descr,4,0x5060,0x3f0770),0x178);
284 snprintf(reg_descr,100,"%s PREFCTRL-Upper",getName());
285 confSpace->addConfReg(new pciConfReg(reg_descr,4,0x4000,0xc00),0x17c);
286
287 // power budgeting registers.
288 snprintf(reg_descr,100,"%s power budgeting enhanced cap hdr",getName());
289 confSpace->addConfReg(new pciConfReg(reg_descr,4,0x10004,0x0),0x300);
290 snprintf(reg_descr,100,"%s power budgeting data select",getName());
291 confSpace->addConfReg(new pciConfReg(reg_descr,1,0x0,0xff),0x304);
292 snprintf(reg_descr,100,"%s power budgeting data register",getName());
293 confSpace->addConfReg(new pciConfReg(reg_descr,4,0x0,0x0),0x308);
294}
295
296void
297pcieToPciBridge::init_done(){
298 initPci();
299 dev_init_done(debug_level);
300 mem32_base = GET_MEM_BASE(confSpace);
301 mem32_limit = GET_MEM_LIMIT(confSpace);
302 io_base = GET_IO_BASE(confSpace);
303 io_limit = GET_IO_LIMIT(confSpace);
304 mem64_base = GET_PF_MEM_BASE(confSpace);
305 mem64_limit = GET_PF_MEM_LIMIT(confSpace);
306 bCR = (bridgeCommandReg*)confSpace->getConfReg(PCI_CONF_COMM);
307}
308
309void
310pcieToPciBridge::module_added(mmi_instance_t target, const char *target_name){
311 if (secBusName && !strcmp(target_name,secBusName)){
312 secBusIf = (pciBusIf*)mmi_get_interface(target, PCI_BUS_INTERFACE);
313 }
314 if(busName && !strcmp(target_name, busName)){
315 busIf = (pcieBusIf*)mmi_get_interface(target, PCIE_BUS_INTERFACE);
316 }
317 dev_module_added(target_name);
318}
319
320void
321pcieToPciBridge::module_deleted(mmi_instance_t target, const char *target_name){
322 dev_module_deleted(target_name);
323}
324
325void
326pcieToPciBridge::modinfo(){
327 printf("%s is a Intel pcie-pci bridge device\n",getName());
328 printf("device id <0x%lx>, vendor id <0x%lx>\n",confSpace->readConf(PCI_CONF_VENID),\
329 confSpace->readConf(PCI_CONF_DEVID));
330 printf("it's primary pcie bus is <%s>, secondary pci bus is <%s>\n",busName,secBusName);
331 printf("to display pcie config regs, type \'%s dump\'\n",getName());
332}
333
334bool
335pcieToPciBridge::parse_arg(const char *arg){
336 if(argval("secbus",arg,&secBusName)){
337 debug_more("%s:secondary bus = %s\n",getName(),secBusName);
338 return true;
339 }else
340 return dev_parse_arg(arg);
341}
342
343bool
344pcieToPciBridge::check_args(){
345 if(!secBusName){
346 debug_err("%s: ERROR: must specify a secondary PCI bus\n", getName());
347 return false;
348 }else
349 return dev_check_args();
350}
351
352void*
353pcieToPciBridge::get_interface(const char *name){
354 if (!strcmp(name, GENERIC_PCIE_DEV_INTERFACE))
355 return (genericPcieDevIf*)this;
356 else if(!strcmp(name, PCI_BRIDGE_INTERFACE))
357 return (pciBridgeIf*)this;
358 else return 0;
359}
360
361
362pciExpMsgCode
363pcieToPciBridge::map_pin_vpin(int device, int line, bool ast) {
364 int vpin = (device % 4 + line) % 4;
365
366 if (ast)
367 switch (vpin) {
368 case 0: return MSG_Assert_INTA;
369 case 1: return MSG_Assert_INTB;
370 case 2: return MSG_Assert_INTC;
371 case 3: return MSG_Assert_INTD;
372 default: assert(0);
373 }
374 else
375 switch (vpin) {
376 case 0: return MSG_Deassert_INTA;
377 case 1: return MSG_Deassert_INTB;
378 case 2: return MSG_Deassert_INTC;
379 case 3: return MSG_Deassert_INTD;
380 default: assert(0);
381 }
382}
383
384int
385pcieToPciBridge::busif_interrupt_in(bool set, mmi_instance_t busMod, int device, int line, SAM_DeviceId *id) {
386
387 pciExpMsgCode vpin = map_pin_vpin(device, line, set);
388
389 int ret;
390
391 if(set)
392 ret = handleCompletion(assertIntx(vpin,device,id));
393 else
394 ret = handleCompletion(deassertIntx(vpin, device,id));
395
396 if (!ret)
397 return 0;
398 else {
399 debug_err("ERROR: PCI/X device %d, pin %d INT assertion failed!\n", device, line);
400 return -1;
401 }
402}
403
404int
405pcieToPciBridge::busif_free_interrupt(mmi_instance_t busMod, int dev_number) {
406 debug_more("%s: free interrupt\n",getName());
407 return 0;
408}
409
410int
411pcieToPciBridge::busif_dma_out(uint64_t vaddr, void *data, long count, mmi_instance_t caller,uint16_t requesterId,SAM_DeviceId *id) {
412 int length = (count - 1)/4 + 1;
413 uint8_t be;
414 // assume contiguous byte access.
415
416 if(count <= 4){
417 be = pcie_countToBe(count);
418 }else if(count <= 8){
419 be = pcie_countToBe(count);
420 }else{
421 if((count % 4) == 0 ) be = 0xff;
422 else{
423 be = pcie_countToBe(count % 4) << 4;
424 be |= 0xf;
425 }
426 }
427
428 debug_more("%s: busif_dma_out:byte count 0x%llx,pcie tlp length 0x%lx,pcie tlp be 0x%x\n",getName(),count,length,be);
429 busIf->busif_access(PCIE_MEM, true, vaddr, data, length, be, PCIE_REQUESTER_ID(busIf->busif_getBusno(),0,0), mem_addr32,id);
430
431 return 0;
432}
433
434int
435pcieToPciBridge::busif_dma_in(uint64_t vaddr, void *data, long count, mmi_instance_t caller,uint16_t requesterId, SAM_DeviceId *id) {
436 int length = (count - 1)/4 + 1;
437 uint8_t be;
438 // assume contiguous byte access.
439
440 if(count <= 4){
441 be = pcie_countToBe(count);
442 }else if(count <= 8){
443 be = pcie_countToBe(count);
444 }else{
445 if((count % 4) == 0 ) be = 0xff;
446 else{
447 be = pcie_countToBe(count % 4) << 4;
448 be |= 0xf;
449 }
450 }
451 debug_more("%s: busif_dma_in:bytecount 0x%llx,pcie tlp length 0x%lx,pcie tlp be 0x%x\n",getName(),count,length,be);
452 busIf->busif_access(PCIE_MEM, false, vaddr, data, length, be, PCIE_REQUESTER_ID(busIf->busif_getBusno(),0,0) , mem_addr32,id);
453
454 return 0;
455}
456
457int
458pcieToPciBridge::busif_add_interrupt(mmi_instance_t busMod,int device,int dev_type, int slot_irl[],bool isMulti = false) {
459 debug_more("%s:ADD INT\n",getName());
460 return 0;
461}
462
463/* PCI Express Enhanced Configuration address to conventional PCI
464 Configuration address translation (type 1 to type 0) */
465uint32_t
466pcieToPciBridge::pcie_eh1_pci0_translation(uint32_t addr) {
467 uint16_t dev_fun, reg; uint32_t bus, ret;
468
469 bus = addr >> busShift & 0xff;
470 dev_fun = addr >> funShift & 0xff;
471 reg = addr & 0xff;
472 ret = bus << 16 | dev_fun << 8 | reg;
473
474 return ret;
475}
476
477void
478pcieToPciBridge::devif_confAccessCb(bool wr, uint64_t offset, uint8_t be){
479 if (!wr)
480 return;
481
482 switch (offset) {
483 case PCI_BCNF_PF_BASE_HIGH:
484 case PCI_BCNF_PF_BASE_LOW:
485 case PCI_BCNF_PF_LIMIT_HIGH:
486 case PCI_BCNF_PF_LIMIT_LOW:
487 if (!mem_mapped()){
488 mem64_base = GET_PF_MEM_BASE(confSpace);
489 mem64_limit = GET_PF_MEM_LIMIT(confSpace);
490 return;
491 }else{
492 if(mem64_base < mem64_limit){
493 debug_more("%s unmap MEM64[%llx %llx]\n",getName(), mem64_base, mem64_limit);
494 unmapSpace(PCIE_MEM, mem64_base);
495 }
496 mem64_base = GET_PF_MEM_BASE(confSpace);
497 mem64_limit = GET_PF_MEM_LIMIT(confSpace);
498 if (mem64_base < mem64_limit) {
499 debug_more("%s remap: MEM64 [%llx %llx]\n",
500 getName(), mem64_base, mem64_limit);
501 mapSpace(PCIE_MEM, mem64_base, mem64_limit - mem64_base + 1);
502 }
503 }
504 break;
505 case PCI_BCNF_MEM_BASE:
506 case PCI_BCNF_MEM_LIMIT:
507 if (!mem_mapped()){
508 mem32_base = GET_MEM_BASE(confSpace);
509 mem32_limit = GET_MEM_LIMIT(confSpace);
510 return;
511 }else{
512 if(mem32_base < mem32_limit){
513 debug_more("%s unmap MEM[%lx %lx]\n",getName(), mem32_base, mem32_limit);
514 unmapSpace(PCIE_MEM, mem32_base);
515 }
516 mem32_base = GET_MEM_BASE(confSpace);
517 mem32_limit = GET_MEM_LIMIT(confSpace);
518 if (mem32_base < mem32_limit) {
519 debug_more("%s remap: MEM [%lx %lx]\n",
520 getName(), mem32_base, mem32_limit);
521 mapSpace(PCIE_MEM, mem32_base, mem32_limit - mem32_base + 1);
522 }
523 }
524 break;
525 case PCI_BCNF_IO_BASE_LOW:
526 case PCI_BCNF_IO_LIMIT_LOW:
527 if (!io_mapped()){
528 io_base = GET_IO_BASE(confSpace);
529 io_limit = GET_IO_LIMIT(confSpace);
530 return;
531 }else{
532 if(io_base < io_limit){
533 debug_more("%s unmap IO[%lx %lx]\n", getName(), io_base, io_limit);
534 unmapSpace(PCIE_IO, io_base);
535 }
536 io_base = GET_IO_BASE(confSpace);
537 io_limit = GET_IO_LIMIT(confSpace);
538 if (io_base < io_limit) {
539 debug_more("Bridge remap: IO [%lx %lx]\n", io_base, io_limit);
540 mapSpace(PCIE_IO, io_base, io_limit - io_base + 1);
541 }
542 }
543 break;
544 default:
545 return;
546 }
547 return;
548}
549
550pcieCompleter
551pcieToPciBridge::devif_confAccess(bool wr, uint32_t addr, void * data, uint8_t be, uint16_t reqId,
552 addrMd_xactnType tType, uint16_t length, tlp_X args, SAM_DeviceId *id) {
553
554 int size = byteEnabletoSize(be); // length is the number of words
555
556 if (tType == conf_type1) {
557 pciXactnStatus status;
558 addr = pcie_eh1_pci0_translation(addr);
559
560 if(wr){
561 *(uint64_t*)data &= 0xffffffff;
562 uint32_t l_buf = *(uint64_t*)data;
563 if(size == 4){
564 *(uint64_t*)data = swap_word(l_buf);
565 }else if(size == 2){
566 *(uint64_t*)data = swap_hword(l_buf);
567 }else if (size == 1)
568 *(uint64_t*)data = l_buf;
569 debug_more("%s conf wr xactn type 1: addr <0x%x> size<%d> be<0x%x> data<0x%llx>\n",
570 getName(), addr, size, be,*(uint64_t*)data);
571 }
572
573 status = secBusIf->busif_access_w_size(PCI_CFG, addr, addr, wr, (uint64_t *)data, size,id);
574
575 if(!wr){
576 uint32_t l_buf = *(uint64_t*)data;
577 if(size == 4){
578 *(uint64_t*)data = swap_word(l_buf & 0xFFFFFFFF);
579 }else if(size == 2){
580 *(uint64_t*)data = swap_hword(l_buf & 0xFFFF);
581 }else if (size == 1)
582 *(uint64_t*)data = l_buf & 0xFF;
583 debug_more("%s conf rd xactn type 1: addr <0x%x> size<%d> be<0x%x> data<0x%llx>\n",
584 getName(), addr, size, be, *(uint64_t*)data);
585 if(debug_level >= 2) printf("\n");
586 }
587
588 if ( status == SUCCESS )
589 return pcieCompleter(SC,getId());
590 else if( status == MASTER_ABORT)
591 return pcieCompleter(CA,getId());
592 else
593 return pcieCompleter(UR,getId());
594 } else {
595 bool ret;
596 if(id)
597 *id = samId;
598 if(wr){
599 *(uint64_t*)data &= 0xffffffff;
600 uint32_t l_buf = *(uint64_t*)data;
601 if(size == 4){
602 *(uint64_t*)data = swap_word(l_buf);
603 }else if(size == 2){
604 *(uint64_t*)data = swap_hword(l_buf);
605 }else if (size == 1)
606 *(uint64_t*)data = l_buf;
607 debug_more("%s conf xactn type 0: addr <0x%x> wr size<%d> be<0x%x> data<0x%llx>\n",
608 getName(), addr, size, be,*(uint64_t*)data);
609 }
610
611 ret = confSpace->confAccessSize(addr, wr, (uint64_t *)data, size);
612 if(wr && debug_level >= 2) printf("\n");
613 if(!wr){
614 uint32_t l_buf = *(uint64_t*)data;
615 if(size == 4){
616 *(uint64_t*)data = swap_word(l_buf & 0xFFFFFFFF);
617 }else if(size == 2){
618 *(uint64_t*)data = swap_hword(l_buf & 0xFFFF);
619 }else if (size == 1)
620 *(uint64_t*)data = l_buf & 0xFF;
621
622 debug_more("%s conf xactn type 0: addr <0x%x> rd size<%d> be<0x%x> data<0x%llx>\n",
623 getName(), addr, size, be, *(uint64_t*)data);
624 if(debug_level >= 2) printf("\n");
625 }
626
627 devif_confAccessCb(wr,addr,be);
628 return (ret ? pcieCompleter(SC,getId()) : pcieCompleter(CA,getId()));
629 }
630}
631
632pcieCompleter
633pcieToPciBridge::devif_memAccess(bool wr, uint64_t addr, addrMd_xactnType mode, void * data,\
634 uint16_t length, uint8_t be, uint16_t reqId, tlp_X args,SAM_DeviceId * id) {
635
636 int size = byteEnabletoSize(be);
637 if (addr >= mem32_base && addr < mem32_limit || addr >= mem64_base && addr < mem64_limit) {
638 if(wr)
639 debug_more("%s downstream wr mem access: addr <0x%x> size<%d> be<0x%x> data<0x%llx>\n",
640 getName(), addr, size, be, *(uint64_t*)data);
641 secBusIf->busif_access_w_size(mode == mem_addr64 ? PCI_MEM64 : PCI_MEM32, addr, addr, wr, (uint64_t *)data, size,id);
642 if(!wr)
643 debug_more("%s downstream rd mem access: addr <0x%x> size<%d> be<0x%x> data<0x%llx>\n",
644 getName(), addr, size, be, *(uint64_t*)data);
645 return pcieCompleter(SC, getId());
646 } else{
647 if(id) *id = samId;
648 return pcieCompleter(UR, getId());
649 }
650}
651
652pcieCompleter
653pcieToPciBridge::devif_ioAccess(bool wr, uint64_t addr, void * data, uint8_t be, uint16_t reqId, \
654 uint16_t length, tlp_X args, SAM_DeviceId *id) {
655 if(id)
656 *id = samId;
657 return pcieCompleter(UR, getId());
658}
659
660pcieCompleter
661pcieToPciBridge::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){
662 if(id)
663 *id = samId;
664 return pcieCompleter(UR,getId());
665}
666
667bool pcieToPciBridge::dump (FILE * fp){
668 const int bufsize = 64 * 1024;
669 char buf[bufsize];
670 char tbuf[bufsize];
671
672 char *dumpDir = DR_get_dir();
673 assert(dumpDir);
674 bool ret = genericPcieDev::dump (dumpDir, getName());
675
676
677 // intx interrupts
678 // dump the device numbers of downstream devices
679 fprintf(fp,"%s\n",current_dump_version);
680 fprintf(fp,"downstream devices with pending interrupts\n");
681 for(int i = 0; i < 4; i++){
682 sprintf(buf,"Int%c ",'A' + i);
683 list<int>::iterator listIt;
684 tbuf[0] = 0;
685 for(listIt = intLine[i].begin(); listIt != intLine[i].end(); listIt++){
686 sprintf(tbuf,"0x%x ",*listIt);
687 strcat(buf,tbuf);
688 }
689 fwrite(buf,strlen(buf),1,fp);
690 fwrite("\n",strlen("\n"),1,fp);
691 }
692
693 // now dump the intx pending status
694 fprintf(fp,"Pending interrupts to upstream bridge\n");
695 for(char i = 0; i < 4; i++)
696 fprintf(fp,"int%c-%s\n", i+'A', pendingIntr[i]? "Asserted":"Deasserted");
697 fclose(fp);
698 return ret;
699
700}
701
702bool pcieToPciBridge::restore (FILE * fp){
703 const int bufsize = 64 * 1024;
704 char buf[bufsize];
705
706 char *dumpDir = DR_get_dir();
707 assert(dumpDir);
708 bool ret = genericPcieDev::restore (dumpDir, getName());
709
710
711 // read the version string.
712 fgets(buf,bufsize,fp);
713 if(!strcmp(current_dump_version,buf)){
714 printf("%s: dump version unknown\n",getName());
715 assert(0);
716 }
717
718
719 // throw away the comment line
720 fgets(buf,bufsize,fp);
721
722 for(int i = 0; i < 4; i++){
723 fgets(buf,bufsize,fp);
724 strtok(buf," "); // intr line number, ignore
725 const char * port_val;
726 while( port_val = strtok(0," ") ){
727 if(port_val[0] == '\n')
728 break;
729 uint64_t val = strtoull(port_val,0,0);
730 intLine[i].push_back(val);
731 intLine[i].sort();
732 intLine[i].unique();
733 pendingIntr[i] = true;
734 }
735 }
736
737 // ignore the other dump data as it can be derived from data above
738
739 return ret;
740
741
742}
743
744void pcieToPciBridge::handle_ui(int argc, char * argv[]){
745 if(argc == 1){
746 ui_cmd_usage();
747 return;
748 }else if(!strcmp(argv[1],"dump")){
749 char * dumpDir;
750 char buf[1024];
751 dumpDir = getcwd(buf,1024);
752 assert( errno != ERANGE);
753 genericPcieDev::dump (dumpDir, argv[2]);
754 }else if(!strcmp(argv[1],"restore")){
755 if(argv[2]){
756 char *dumpDir;
757 char buf[1024];
758 dumpDir = getcwd(buf,1024);
759 assert( errno != ERANGE);
760 genericPcieDev::restore (dumpDir, argv[2]);
761 }else
762 printf("%s restore: no restore filename specified\n",getName());
763 }else if(!strcmp(argv[1],"debug")){
764 if(argv[2]){
765 debug_level = atoi(argv[2]);
766 confSpace->set_debug_level(debug_level);
767 printf("%s: set debug level to %d\n",getName(),debug_level);
768 }else
769 printf("%s: current debug level %d\n",getName(),debug_level);
770
771 }else
772 debug_err("%s: unsupported UI command <%s>\n",getName(),argv[1]);
773
774 return;
775}
776
777
778
779