root / hw / pci / slotid_cap.c @ 062db740
History | View | Annotate | Download (1.4 kB)
1 |
#include "hw/pci/slotid_cap.h" |
---|---|
2 |
#include "hw/pci/pci.h" |
3 |
#include "qemu/error-report.h" |
4 |
|
5 |
#define SLOTID_CAP_LENGTH 4 |
6 |
#define SLOTID_NSLOTS_SHIFT (ffs(PCI_SID_ESR_NSLOTS) - 1) |
7 |
|
8 |
int slotid_cap_init(PCIDevice *d, int nslots, |
9 |
uint8_t chassis, |
10 |
unsigned offset)
|
11 |
{ |
12 |
int cap;
|
13 |
if (!chassis) {
|
14 |
error_report("Bridge chassis not specified. Each bridge is required "
|
15 |
"to be assigned a unique chassis id > 0.");
|
16 |
return -EINVAL;
|
17 |
} |
18 |
if (nslots < 0 || nslots > (PCI_SID_ESR_NSLOTS >> SLOTID_NSLOTS_SHIFT)) { |
19 |
/* TODO: error report? */
|
20 |
return -EINVAL;
|
21 |
} |
22 |
|
23 |
cap = pci_add_capability(d, PCI_CAP_ID_SLOTID, offset, SLOTID_CAP_LENGTH); |
24 |
if (cap < 0) { |
25 |
return cap;
|
26 |
} |
27 |
/* We make each chassis unique, this way each bridge is First in Chassis */
|
28 |
d->config[cap + PCI_SID_ESR] = PCI_SID_ESR_FIC | |
29 |
(nslots << SLOTID_NSLOTS_SHIFT); |
30 |
d->cmask[cap + PCI_SID_ESR] = 0xff;
|
31 |
d->config[cap + PCI_SID_CHASSIS_NR] = chassis; |
32 |
/* Note: Chassis number register is non-volatile,
|
33 |
so we don't reset it. */
|
34 |
/* TODO: store in eeprom? */
|
35 |
d->wmask[cap + PCI_SID_CHASSIS_NR] = 0xff;
|
36 |
|
37 |
d->cap_present |= QEMU_PCI_CAP_SLOTID; |
38 |
return 0; |
39 |
} |
40 |
|
41 |
void slotid_cap_cleanup(PCIDevice *d)
|
42 |
{ |
43 |
/* TODO: cleanup config space? */
|
44 |
d->cap_present &= ~QEMU_PCI_CAP_SLOTID; |
45 |
} |