@@ -414,3 +414,88 @@ void margin_free_results(struct margin_results *results, uint8_t results_n)
}
free(results);
}
+
+bool margin_read_params_standalone(struct pci_access *pacc, struct pci_dev *dev,
+ int8_t recvn, struct margin_recv *caps)
+{
+ struct pci_cap *cap = pci_find_cap(dev, PCI_CAP_ID_EXP, PCI_CAP_NORMAL);
+ uint8_t dev_dir = (pci_read_word(dev, cap->addr + PCI_EXP_FLAGS) & PCI_EXP_FLAGS_TYPE) >> 4;
+
+ bool dev_down;
+ if (dev_dir == 4 || dev_dir == 6)
+ dev_down = true;
+ else
+ dev_down = false;
+
+ if (recvn == -1)
+ {
+ if (dev_down)
+ recvn = 1;
+ else
+ recvn = 6;
+ }
+
+ if (recvn < 1 || recvn > 6)
+ return false;
+ if (dev_down && recvn == 6)
+ return false;
+ if (!dev_down && recvn != 6)
+ return false;
+
+ caps->recvn = recvn;
+
+ struct pci_dev *down = NULL;
+ struct pci_dev *up = NULL;
+ struct margin_dev down_w;
+ struct margin_dev up_w;
+
+ for (struct pci_dev *p = pacc->devices; p; p = p->next)
+ {
+ if (dev_down && pci_read_byte(dev, PCI_SECONDARY_BUS) == p->bus && dev->domain == p->domain && p->func == 0)
+ {
+ down = dev;
+ up = p;
+ break;
+ }
+ else if (!dev_down && pci_read_byte(p, PCI_SECONDARY_BUS) == dev->bus && dev->domain == p->domain)
+ {
+ down = p;
+ up = dev;
+ break;
+ }
+ }
+
+ if (!down)
+ return false;
+ if (!margin_verify_link(down, up))
+ return false;
+
+ down_w = margin_fill_wrapper(down);
+ up_w = margin_fill_wrapper(up);
+
+ caps->dev = (dev_down ? &down_w : &up_w);
+ if (!margin_check_ready_bit(caps->dev->dev))
+ return false;
+
+ if (!margin_prep_dev(&down_w))
+ return false;
+ if (!margin_prep_dev(&up_w))
+ {
+ margin_restore_dev(&down_w);
+ return false;
+ }
+
+ bool status;
+ caps->lane_reversal = false;
+ status = margin_read_params(caps);
+ if (!status)
+ {
+ caps->lane_reversal = true;
+ status = margin_read_params(caps);
+ }
+
+ margin_restore_dev(&down_w);
+ margin_restore_dev(&up_w);
+
+ return status;
+}
@@ -172,6 +172,10 @@ union margin_cmd margin_make_cmd(uint8_t payload, uint8_t type, uint8_t recvn);
dev, recvn and lane_reversal fields must be initialized*/
bool margin_read_params(struct margin_recv *recv);
+/*Fill margin_recv without calling other functions*/
+bool margin_read_params_standalone(struct pci_access *pacc, struct pci_dev* dev,
+ int8_t recvn, struct margin_recv* caps);
+
bool margin_report_cmd(struct margin_dev *dev, uint8_t lane,
union margin_cmd cmd, union margin_payload *result);