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