#ifndef _E5_IMC_VAR_H_
#define _E5_IMC_VAR_H_
#define E5_IMC_CHAN_VER2 2
#define E5_IMC_CHAN_VER3 3
struct e5_imc_chan {
uint16_t did;
int slot;
int func;
const char *desc;
int chan_ext;
int chan;
int ver;
int ubox_slot;
int ubox_func;
uint16_t ubox_did;
int cpgc_slot;
int cpgc_func;
uint16_t cpgc_did;
uint32_t cpgc_chandis;
int ctad_slot;
int ctad_func;
uint16_t ctad_did;
};
#define E5_IMC_CHAN_END \
{ 0, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
#define E5_IMC_CHAN_FIELDS(v, imc, c, c_ext) \
.chan_ext = c_ext, \
.chan = c, \
.ver = E5_IMC_CHAN_VER##v, \
\
.ubox_slot = PCISLOT_E5V##v##_UBOX0, \
.ubox_func = PCIFUNC_E5V##v##_UBOX0, \
.ubox_did = PCI_E5V##v##_UBOX0_DID_ID, \
\
.cpgc_slot = PCISLOT_E5V##v##_IMC##imc##_CPGC, \
.cpgc_func = PCIFUNC_E5V##v##_IMC##imc##_CPGC, \
.cpgc_did = PCI_E5V##v##_IMC##imc##_CPGC_DID_ID, \
.cpgc_chandis = PCI_E5V##v##_IMC_CPGC_MCMTR_CHN_DISABLE(c), \
\
.ctad_slot = PCISLOT_E5V##v##_IMC##imc##_CTAD, \
.ctad_func = PCIFUNC_E5V##v##_IMC##imc##_CTAD(c), \
.ctad_did = PCI_E5V##v##_IMC##imc##_CTAD_DID_ID(c) \
#define UBOX_READ(dev, c, ofs, w) \
pcib_read_config((dev), pci_get_bus((dev)), \
(c)->ubox_slot, (c)->ubox_func, (ofs), (w))
#define UBOX_READ_2(dev, c, ofs) UBOX_READ((dev), (c), (ofs), 2)
#define UBOX_READ_4(dev, c, ofs) UBOX_READ((dev), (c), (ofs), 4)
#define IMC_CPGC_READ(dev, c, ofs, w) \
pcib_read_config((dev), pci_get_bus((dev)), \
(c)->cpgc_slot, (c)->cpgc_func, (ofs), (w))
#define IMC_CPGC_READ_2(dev, c, ofs) IMC_CPGC_READ((dev), (c), (ofs), 2)
#define IMC_CPGC_READ_4(dev, c, ofs) IMC_CPGC_READ((dev), (c), (ofs), 4)
#define IMC_CTAD_READ(dev, c, ofs, w) \
pcib_read_config((dev), pci_get_bus((dev)), \
(c)->ctad_slot, (c)->ctad_func, (ofs), (w))
#define IMC_CTAD_READ_2(dev, c, ofs) IMC_CTAD_READ((dev), (c), (ofs), 2)
#define IMC_CTAD_READ_4(dev, c, ofs) IMC_CTAD_READ((dev), (c), (ofs), 4)
static __inline int
e5_imc_node_probe(device_t dev, const struct e5_imc_chan *c)
{
int node, dimm;
uint32_t val;
if (IMC_CPGC_READ_2(dev, c, PCIR_VENDOR) != PCI_E5_IMC_VID_ID ||
IMC_CPGC_READ_2(dev, c, PCIR_DEVICE) != c->cpgc_did)
return -1;
val = IMC_CPGC_READ_4(dev, c, PCI_E5_IMC_CPGC_MCMTR);
if (val & c->cpgc_chandis)
return -1;
if (IMC_CTAD_READ_2(dev, c, PCIR_VENDOR) != PCI_E5_IMC_VID_ID ||
IMC_CTAD_READ_2(dev, c, PCIR_DEVICE) != c->ctad_did)
return -1;
for (dimm = 0; dimm < PCI_E5_IMC_CHN_DIMM_MAX; ++dimm) {
val = IMC_CTAD_READ_4(dev, c, PCI_E5_IMC_CTAD_DIMMMTR(dimm));
if (val & PCI_E5_IMC_CTAD_DIMMMTR_DIMM_POP)
break;
}
if (dimm == PCI_E5_IMC_CHN_DIMM_MAX)
return -1;
if (UBOX_READ_2(dev, c, PCIR_VENDOR) != PCI_E5_IMC_VID_ID ||
UBOX_READ_2(dev, c, PCIR_DEVICE) != c->ubox_did)
return -1;
val = UBOX_READ_4(dev, c, PCI_E5_UBOX0_CPUNODEID);
node = __SHIFTOUT(val, PCI_E5_UBOX0_CPUNODEID_LCLNODEID);
return node;
}
#endif