misc: Rename misc.(hh|cc) to logging.(hh|cc)
[gem5.git] / src / dev / pci / device.cc
1 /*
2 * Copyright (c) 2013, 2015 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2004-2005 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Ali Saidi
41 * Andrew Schultz
42 * Miguel Serrano
43 */
44
45 /* @file
46 * A single PCI device configuration space entry.
47 */
48
49 #include "dev/pci/device.hh"
50
51 #include <list>
52 #include <string>
53 #include <vector>
54
55 #include "base/inifile.hh"
56 #include "base/intmath.hh"
57 #include "base/logging.hh"
58 #include "base/str.hh"
59 #include "base/trace.hh"
60 #include "debug/PciDevice.hh"
61 #include "mem/packet.hh"
62 #include "mem/packet_access.hh"
63 #include "sim/byteswap.hh"
64 #include "sim/core.hh"
65
66 PciDevice::PciDevice(const PciDeviceParams *p)
67 : DmaDevice(p),
68 _busAddr(p->pci_bus, p->pci_dev, p->pci_func),
69 PMCAP_BASE(p->PMCAPBaseOffset),
70 PMCAP_ID_OFFSET(p->PMCAPBaseOffset+PMCAP_ID),
71 PMCAP_PC_OFFSET(p->PMCAPBaseOffset+PMCAP_PC),
72 PMCAP_PMCS_OFFSET(p->PMCAPBaseOffset+PMCAP_PMCS),
73 MSICAP_BASE(p->MSICAPBaseOffset),
74 MSIXCAP_BASE(p->MSIXCAPBaseOffset),
75 MSIXCAP_ID_OFFSET(p->MSIXCAPBaseOffset+MSIXCAP_ID),
76 MSIXCAP_MXC_OFFSET(p->MSIXCAPBaseOffset+MSIXCAP_MXC),
77 MSIXCAP_MTAB_OFFSET(p->MSIXCAPBaseOffset+MSIXCAP_MTAB),
78 MSIXCAP_MPBA_OFFSET(p->MSIXCAPBaseOffset+MSIXCAP_MPBA),
79 PXCAP_BASE(p->PXCAPBaseOffset),
80
81 hostInterface(p->host->registerDevice(this, _busAddr,
82 (PciIntPin)p->InterruptPin)),
83 pioDelay(p->pio_latency),
84 configDelay(p->config_latency)
85 {
86 fatal_if(p->InterruptPin >= 5,
87 "Invalid PCI interrupt '%i' specified.", p->InterruptPin);
88
89 config.vendor = htole(p->VendorID);
90 config.device = htole(p->DeviceID);
91 config.command = htole(p->Command);
92 config.status = htole(p->Status);
93 config.revision = htole(p->Revision);
94 config.progIF = htole(p->ProgIF);
95 config.subClassCode = htole(p->SubClassCode);
96 config.classCode = htole(p->ClassCode);
97 config.cacheLineSize = htole(p->CacheLineSize);
98 config.latencyTimer = htole(p->LatencyTimer);
99 config.headerType = htole(p->HeaderType);
100 config.bist = htole(p->BIST);
101
102 config.baseAddr[0] = htole(p->BAR0);
103 config.baseAddr[1] = htole(p->BAR1);
104 config.baseAddr[2] = htole(p->BAR2);
105 config.baseAddr[3] = htole(p->BAR3);
106 config.baseAddr[4] = htole(p->BAR4);
107 config.baseAddr[5] = htole(p->BAR5);
108 config.cardbusCIS = htole(p->CardbusCIS);
109 config.subsystemVendorID = htole(p->SubsystemVendorID);
110 config.subsystemID = htole(p->SubsystemID);
111 config.expansionROM = htole(p->ExpansionROM);
112 config.capabilityPtr = htole(p->CapabilityPtr);
113 // Zero out the 7 bytes of reserved space in the PCI Config space register.
114 bzero(config.reserved, 7*sizeof(uint8_t));
115 config.interruptLine = htole(p->InterruptLine);
116 config.interruptPin = htole(p->InterruptPin);
117 config.minimumGrant = htole(p->MinimumGrant);
118 config.maximumLatency = htole(p->MaximumLatency);
119
120 // Initialize the capability lists
121 // These structs are bitunions, meaning the data is stored in host
122 // endianess and must be converted to Little Endian when accessed
123 // by the guest
124 // PMCAP
125 pmcap.pid = (uint16_t)p->PMCAPCapId; // pid.cid
126 pmcap.pid |= (uint16_t)p->PMCAPNextCapability << 8; //pid.next
127 pmcap.pc = p->PMCAPCapabilities;
128 pmcap.pmcs = p->PMCAPCtrlStatus;
129
130 // MSICAP
131 msicap.mid = (uint16_t)p->MSICAPCapId; //mid.cid
132 msicap.mid |= (uint16_t)p->MSICAPNextCapability << 8; //mid.next
133 msicap.mc = p->MSICAPMsgCtrl;
134 msicap.ma = p->MSICAPMsgAddr;
135 msicap.mua = p->MSICAPMsgUpperAddr;
136 msicap.md = p->MSICAPMsgData;
137 msicap.mmask = p->MSICAPMaskBits;
138 msicap.mpend = p->MSICAPPendingBits;
139
140 // MSIXCAP
141 msixcap.mxid = (uint16_t)p->MSIXCAPCapId; //mxid.cid
142 msixcap.mxid |= (uint16_t)p->MSIXCAPNextCapability << 8; //mxid.next
143 msixcap.mxc = p->MSIXMsgCtrl;
144 msixcap.mtab = p->MSIXTableOffset;
145 msixcap.mpba = p->MSIXPbaOffset;
146
147 // allocate MSIX structures if MSIXCAP_BASE
148 // indicates the MSIXCAP is being used by having a
149 // non-zero base address.
150 // The MSIX tables are stored by the guest in
151 // little endian byte-order as according the
152 // PCIe specification. Make sure to take the proper
153 // actions when manipulating these tables on the host
154 uint16_t msixcap_mxc_ts = msixcap.mxc & 0x07ff;
155 if (MSIXCAP_BASE != 0x0) {
156 int msix_vecs = msixcap_mxc_ts + 1;
157 MSIXTable tmp1 = {{0UL,0UL,0UL,0UL}};
158 msix_table.resize(msix_vecs, tmp1);
159
160 MSIXPbaEntry tmp2 = {0};
161 int pba_size = msix_vecs / MSIXVECS_PER_PBA;
162 if ((msix_vecs % MSIXVECS_PER_PBA) > 0) {
163 pba_size++;
164 }
165 msix_pba.resize(pba_size, tmp2);
166 }
167 MSIX_TABLE_OFFSET = msixcap.mtab & 0xfffffffc;
168 MSIX_TABLE_END = MSIX_TABLE_OFFSET +
169 (msixcap_mxc_ts + 1) * sizeof(MSIXTable);
170 MSIX_PBA_OFFSET = msixcap.mpba & 0xfffffffc;
171 MSIX_PBA_END = MSIX_PBA_OFFSET +
172 ((msixcap_mxc_ts + 1) / MSIXVECS_PER_PBA)
173 * sizeof(MSIXPbaEntry);
174 if (((msixcap_mxc_ts + 1) % MSIXVECS_PER_PBA) > 0) {
175 MSIX_PBA_END += sizeof(MSIXPbaEntry);
176 }
177
178 // PXCAP
179 pxcap.pxid = (uint16_t)p->PXCAPCapId; //pxid.cid
180 pxcap.pxid |= (uint16_t)p->PXCAPNextCapability << 8; //pxid.next
181 pxcap.pxcap = p->PXCAPCapabilities;
182 pxcap.pxdcap = p->PXCAPDevCapabilities;
183 pxcap.pxdc = p->PXCAPDevCtrl;
184 pxcap.pxds = p->PXCAPDevStatus;
185 pxcap.pxlcap = p->PXCAPLinkCap;
186 pxcap.pxlc = p->PXCAPLinkCtrl;
187 pxcap.pxls = p->PXCAPLinkStatus;
188 pxcap.pxdcap2 = p->PXCAPDevCap2;
189 pxcap.pxdc2 = p->PXCAPDevCtrl2;
190
191 BARSize[0] = p->BAR0Size;
192 BARSize[1] = p->BAR1Size;
193 BARSize[2] = p->BAR2Size;
194 BARSize[3] = p->BAR3Size;
195 BARSize[4] = p->BAR4Size;
196 BARSize[5] = p->BAR5Size;
197
198 legacyIO[0] = p->BAR0LegacyIO;
199 legacyIO[1] = p->BAR1LegacyIO;
200 legacyIO[2] = p->BAR2LegacyIO;
201 legacyIO[3] = p->BAR3LegacyIO;
202 legacyIO[4] = p->BAR4LegacyIO;
203 legacyIO[5] = p->BAR5LegacyIO;
204
205 for (int i = 0; i < 6; ++i) {
206 if (legacyIO[i]) {
207 BARAddrs[i] = p->LegacyIOBase + letoh(config.baseAddr[i]);
208 config.baseAddr[i] = 0;
209 } else {
210 BARAddrs[i] = 0;
211 uint32_t barsize = BARSize[i];
212 if (barsize != 0 && !isPowerOf2(barsize)) {
213 fatal("BAR %d size %d is not a power of 2\n", i, BARSize[i]);
214 }
215 }
216 }
217 }
218
219 Tick
220 PciDevice::readConfig(PacketPtr pkt)
221 {
222 int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
223
224 /* Return 0 for accesses to unimplemented PCI configspace areas */
225 if (offset >= PCI_DEVICE_SPECIFIC &&
226 offset < PCI_CONFIG_SIZE) {
227 warn_once("Device specific PCI config space "
228 "not implemented for %s!\n", this->name());
229 switch (pkt->getSize()) {
230 case sizeof(uint8_t):
231 pkt->set<uint8_t>(0);
232 break;
233 case sizeof(uint16_t):
234 pkt->set<uint16_t>(0);
235 break;
236 case sizeof(uint32_t):
237 pkt->set<uint32_t>(0);
238 break;
239 default:
240 panic("invalid access size(?) for PCI configspace!\n");
241 }
242 } else if (offset > PCI_CONFIG_SIZE) {
243 panic("Out-of-range access to PCI config space!\n");
244 }
245
246 switch (pkt->getSize()) {
247 case sizeof(uint8_t):
248 pkt->set<uint8_t>(config.data[offset]);
249 DPRINTF(PciDevice,
250 "readConfig: dev %#x func %#x reg %#x 1 bytes: data = %#x\n",
251 _busAddr.dev, _busAddr.func, offset,
252 (uint32_t)pkt->get<uint8_t>());
253 break;
254 case sizeof(uint16_t):
255 pkt->set<uint16_t>(*(uint16_t*)&config.data[offset]);
256 DPRINTF(PciDevice,
257 "readConfig: dev %#x func %#x reg %#x 2 bytes: data = %#x\n",
258 _busAddr.dev, _busAddr.func, offset,
259 (uint32_t)pkt->get<uint16_t>());
260 break;
261 case sizeof(uint32_t):
262 pkt->set<uint32_t>(*(uint32_t*)&config.data[offset]);
263 DPRINTF(PciDevice,
264 "readConfig: dev %#x func %#x reg %#x 4 bytes: data = %#x\n",
265 _busAddr.dev, _busAddr.func, offset,
266 (uint32_t)pkt->get<uint32_t>());
267 break;
268 default:
269 panic("invalid access size(?) for PCI configspace!\n");
270 }
271 pkt->makeAtomicResponse();
272 return configDelay;
273
274 }
275
276 AddrRangeList
277 PciDevice::getAddrRanges() const
278 {
279 AddrRangeList ranges;
280 int x = 0;
281 for (x = 0; x < 6; x++)
282 if (BARAddrs[x] != 0)
283 ranges.push_back(RangeSize(BARAddrs[x],BARSize[x]));
284 return ranges;
285 }
286
287 Tick
288 PciDevice::writeConfig(PacketPtr pkt)
289 {
290 int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
291
292 /* No effect if we write to config space that is not implemented*/
293 if (offset >= PCI_DEVICE_SPECIFIC &&
294 offset < PCI_CONFIG_SIZE) {
295 warn_once("Device specific PCI config space "
296 "not implemented for %s!\n", this->name());
297 switch (pkt->getSize()) {
298 case sizeof(uint8_t):
299 case sizeof(uint16_t):
300 case sizeof(uint32_t):
301 break;
302 default:
303 panic("invalid access size(?) for PCI configspace!\n");
304 }
305 } else if (offset > PCI_CONFIG_SIZE) {
306 panic("Out-of-range access to PCI config space!\n");
307 }
308
309 switch (pkt->getSize()) {
310 case sizeof(uint8_t):
311 switch (offset) {
312 case PCI0_INTERRUPT_LINE:
313 config.interruptLine = pkt->get<uint8_t>();
314 break;
315 case PCI_CACHE_LINE_SIZE:
316 config.cacheLineSize = pkt->get<uint8_t>();
317 break;
318 case PCI_LATENCY_TIMER:
319 config.latencyTimer = pkt->get<uint8_t>();
320 break;
321 /* Do nothing for these read-only registers */
322 case PCI0_INTERRUPT_PIN:
323 case PCI0_MINIMUM_GRANT:
324 case PCI0_MAXIMUM_LATENCY:
325 case PCI_CLASS_CODE:
326 case PCI_REVISION_ID:
327 break;
328 default:
329 panic("writing to a read only register");
330 }
331 DPRINTF(PciDevice,
332 "writeConfig: dev %#x func %#x reg %#x 1 bytes: data = %#x\n",
333 _busAddr.dev, _busAddr.func, offset,
334 (uint32_t)pkt->get<uint8_t>());
335 break;
336 case sizeof(uint16_t):
337 switch (offset) {
338 case PCI_COMMAND:
339 config.command = pkt->get<uint8_t>();
340 break;
341 case PCI_STATUS:
342 config.status = pkt->get<uint8_t>();
343 break;
344 case PCI_CACHE_LINE_SIZE:
345 config.cacheLineSize = pkt->get<uint8_t>();
346 break;
347 default:
348 panic("writing to a read only register");
349 }
350 DPRINTF(PciDevice,
351 "writeConfig: dev %#x func %#x reg %#x 2 bytes: data = %#x\n",
352 _busAddr.dev, _busAddr.func, offset,
353 (uint32_t)pkt->get<uint16_t>());
354 break;
355 case sizeof(uint32_t):
356 switch (offset) {
357 case PCI0_BASE_ADDR0:
358 case PCI0_BASE_ADDR1:
359 case PCI0_BASE_ADDR2:
360 case PCI0_BASE_ADDR3:
361 case PCI0_BASE_ADDR4:
362 case PCI0_BASE_ADDR5:
363 {
364 int barnum = BAR_NUMBER(offset);
365
366 if (!legacyIO[barnum]) {
367 // convert BAR values to host endianness
368 uint32_t he_old_bar = letoh(config.baseAddr[barnum]);
369 uint32_t he_new_bar = letoh(pkt->get<uint32_t>());
370
371 uint32_t bar_mask =
372 BAR_IO_SPACE(he_old_bar) ? BAR_IO_MASK : BAR_MEM_MASK;
373
374 // Writing 0xffffffff to a BAR tells the card to set the
375 // value of the bar to a bitmask indicating the size of
376 // memory it needs
377 if (he_new_bar == 0xffffffff) {
378 he_new_bar = ~(BARSize[barnum] - 1);
379 } else {
380 // does it mean something special to write 0 to a BAR?
381 he_new_bar &= ~bar_mask;
382 if (he_new_bar) {
383 BARAddrs[barnum] = BAR_IO_SPACE(he_old_bar) ?
384 hostInterface.pioAddr(he_new_bar) :
385 hostInterface.memAddr(he_new_bar);
386 pioPort.sendRangeChange();
387 }
388 }
389 config.baseAddr[barnum] = htole((he_new_bar & ~bar_mask) |
390 (he_old_bar & bar_mask));
391 }
392 }
393 break;
394
395 case PCI0_ROM_BASE_ADDR:
396 if (letoh(pkt->get<uint32_t>()) == 0xfffffffe)
397 config.expansionROM = htole((uint32_t)0xffffffff);
398 else
399 config.expansionROM = pkt->get<uint32_t>();
400 break;
401
402 case PCI_COMMAND:
403 // This could also clear some of the error bits in the Status
404 // register. However they should never get set, so lets ignore
405 // it for now
406 config.command = pkt->get<uint32_t>();
407 break;
408
409 default:
410 DPRINTF(PciDevice, "Writing to a read only register");
411 }
412 DPRINTF(PciDevice,
413 "writeConfig: dev %#x func %#x reg %#x 4 bytes: data = %#x\n",
414 _busAddr.dev, _busAddr.func, offset,
415 (uint32_t)pkt->get<uint32_t>());
416 break;
417 default:
418 panic("invalid access size(?) for PCI configspace!\n");
419 }
420 pkt->makeAtomicResponse();
421 return configDelay;
422 }
423
424 void
425 PciDevice::serialize(CheckpointOut &cp) const
426 {
427 SERIALIZE_ARRAY(BARSize, sizeof(BARSize) / sizeof(BARSize[0]));
428 SERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0]));
429 SERIALIZE_ARRAY(config.data, sizeof(config.data) / sizeof(config.data[0]));
430
431 // serialize the capability list registers
432 paramOut(cp, csprintf("pmcap.pid"), uint16_t(pmcap.pid));
433 paramOut(cp, csprintf("pmcap.pc"), uint16_t(pmcap.pc));
434 paramOut(cp, csprintf("pmcap.pmcs"), uint16_t(pmcap.pmcs));
435
436 paramOut(cp, csprintf("msicap.mid"), uint16_t(msicap.mid));
437 paramOut(cp, csprintf("msicap.mc"), uint16_t(msicap.mc));
438 paramOut(cp, csprintf("msicap.ma"), uint32_t(msicap.ma));
439 SERIALIZE_SCALAR(msicap.mua);
440 paramOut(cp, csprintf("msicap.md"), uint16_t(msicap.md));
441 SERIALIZE_SCALAR(msicap.mmask);
442 SERIALIZE_SCALAR(msicap.mpend);
443
444 paramOut(cp, csprintf("msixcap.mxid"), uint16_t(msixcap.mxid));
445 paramOut(cp, csprintf("msixcap.mxc"), uint16_t(msixcap.mxc));
446 paramOut(cp, csprintf("msixcap.mtab"), uint32_t(msixcap.mtab));
447 paramOut(cp, csprintf("msixcap.mpba"), uint32_t(msixcap.mpba));
448
449 // Only serialize if we have a non-zero base address
450 if (MSIXCAP_BASE != 0x0) {
451 uint16_t msixcap_mxc_ts = msixcap.mxc & 0x07ff;
452 int msix_array_size = msixcap_mxc_ts + 1;
453 int pba_array_size = msix_array_size/MSIXVECS_PER_PBA;
454 if ((msix_array_size % MSIXVECS_PER_PBA) > 0) {
455 pba_array_size++;
456 }
457
458 SERIALIZE_SCALAR(msix_array_size);
459 SERIALIZE_SCALAR(pba_array_size);
460
461 for (int i = 0; i < msix_array_size; i++) {
462 paramOut(cp, csprintf("msix_table[%d].addr_lo", i),
463 msix_table[i].fields.addr_lo);
464 paramOut(cp, csprintf("msix_table[%d].addr_hi", i),
465 msix_table[i].fields.addr_hi);
466 paramOut(cp, csprintf("msix_table[%d].msg_data", i),
467 msix_table[i].fields.msg_data);
468 paramOut(cp, csprintf("msix_table[%d].vec_ctrl", i),
469 msix_table[i].fields.vec_ctrl);
470 }
471 for (int i = 0; i < pba_array_size; i++) {
472 paramOut(cp, csprintf("msix_pba[%d].bits", i),
473 msix_pba[i].bits);
474 }
475 }
476
477 paramOut(cp, csprintf("pxcap.pxid"), uint16_t(pxcap.pxid));
478 paramOut(cp, csprintf("pxcap.pxcap"), uint16_t(pxcap.pxcap));
479 paramOut(cp, csprintf("pxcap.pxdcap"), uint32_t(pxcap.pxdcap));
480 paramOut(cp, csprintf("pxcap.pxdc"), uint16_t(pxcap.pxdc));
481 paramOut(cp, csprintf("pxcap.pxds"), uint16_t(pxcap.pxds));
482 paramOut(cp, csprintf("pxcap.pxlcap"), uint32_t(pxcap.pxlcap));
483 paramOut(cp, csprintf("pxcap.pxlc"), uint16_t(pxcap.pxlc));
484 paramOut(cp, csprintf("pxcap.pxls"), uint16_t(pxcap.pxls));
485 paramOut(cp, csprintf("pxcap.pxdcap2"), uint32_t(pxcap.pxdcap2));
486 paramOut(cp, csprintf("pxcap.pxdc2"), uint32_t(pxcap.pxdc2));
487 }
488
489 void
490 PciDevice::unserialize(CheckpointIn &cp)
491 {
492 UNSERIALIZE_ARRAY(BARSize, sizeof(BARSize) / sizeof(BARSize[0]));
493 UNSERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0]));
494 UNSERIALIZE_ARRAY(config.data,
495 sizeof(config.data) / sizeof(config.data[0]));
496
497 // unserialize the capability list registers
498 uint16_t tmp16;
499 uint32_t tmp32;
500 paramIn(cp, csprintf("pmcap.pid"), tmp16);
501 pmcap.pid = tmp16;
502 paramIn(cp, csprintf("pmcap.pc"), tmp16);
503 pmcap.pc = tmp16;
504 paramIn(cp, csprintf("pmcap.pmcs"), tmp16);
505 pmcap.pmcs = tmp16;
506
507 paramIn(cp, csprintf("msicap.mid"), tmp16);
508 msicap.mid = tmp16;
509 paramIn(cp, csprintf("msicap.mc"), tmp16);
510 msicap.mc = tmp16;
511 paramIn(cp, csprintf("msicap.ma"), tmp32);
512 msicap.ma = tmp32;
513 UNSERIALIZE_SCALAR(msicap.mua);
514 paramIn(cp, csprintf("msicap.md"), tmp16);;
515 msicap.md = tmp16;
516 UNSERIALIZE_SCALAR(msicap.mmask);
517 UNSERIALIZE_SCALAR(msicap.mpend);
518
519 paramIn(cp, csprintf("msixcap.mxid"), tmp16);
520 msixcap.mxid = tmp16;
521 paramIn(cp, csprintf("msixcap.mxc"), tmp16);
522 msixcap.mxc = tmp16;
523 paramIn(cp, csprintf("msixcap.mtab"), tmp32);
524 msixcap.mtab = tmp32;
525 paramIn(cp, csprintf("msixcap.mpba"), tmp32);
526 msixcap.mpba = tmp32;
527
528 // Only allocate if MSIXCAP_BASE is not 0x0
529 if (MSIXCAP_BASE != 0x0) {
530 int msix_array_size;
531 int pba_array_size;
532
533 UNSERIALIZE_SCALAR(msix_array_size);
534 UNSERIALIZE_SCALAR(pba_array_size);
535
536 MSIXTable tmp1 = {{0UL, 0UL, 0UL, 0UL}};
537 msix_table.resize(msix_array_size, tmp1);
538
539 MSIXPbaEntry tmp2 = {0};
540 msix_pba.resize(pba_array_size, tmp2);
541
542 for (int i = 0; i < msix_array_size; i++) {
543 paramIn(cp, csprintf("msix_table[%d].addr_lo", i),
544 msix_table[i].fields.addr_lo);
545 paramIn(cp, csprintf("msix_table[%d].addr_hi", i),
546 msix_table[i].fields.addr_hi);
547 paramIn(cp, csprintf("msix_table[%d].msg_data", i),
548 msix_table[i].fields.msg_data);
549 paramIn(cp, csprintf("msix_table[%d].vec_ctrl", i),
550 msix_table[i].fields.vec_ctrl);
551 }
552 for (int i = 0; i < pba_array_size; i++) {
553 paramIn(cp, csprintf("msix_pba[%d].bits", i),
554 msix_pba[i].bits);
555 }
556 }
557
558 paramIn(cp, csprintf("pxcap.pxid"), tmp16);
559 pxcap.pxid = tmp16;
560 paramIn(cp, csprintf("pxcap.pxcap"), tmp16);
561 pxcap.pxcap = tmp16;
562 paramIn(cp, csprintf("pxcap.pxdcap"), tmp32);
563 pxcap.pxdcap = tmp32;
564 paramIn(cp, csprintf("pxcap.pxdc"), tmp16);
565 pxcap.pxdc = tmp16;
566 paramIn(cp, csprintf("pxcap.pxds"), tmp16);
567 pxcap.pxds = tmp16;
568 paramIn(cp, csprintf("pxcap.pxlcap"), tmp32);
569 pxcap.pxlcap = tmp32;
570 paramIn(cp, csprintf("pxcap.pxlc"), tmp16);
571 pxcap.pxlc = tmp16;
572 paramIn(cp, csprintf("pxcap.pxls"), tmp16);
573 pxcap.pxls = tmp16;
574 paramIn(cp, csprintf("pxcap.pxdcap2"), tmp32);
575 pxcap.pxdcap2 = tmp32;
576 paramIn(cp, csprintf("pxcap.pxdc2"), tmp32);
577 pxcap.pxdc2 = tmp32;
578 pioPort.sendRangeChange();
579 }
580