static void ecc_e31200_callout(void *xsc) { struct ecc_e31200_softc *sc = xsc; ecc_e31200_status(sc); callout_reset(&sc->ecc_callout, hz, ecc_e31200_callout, sc); }
static int ecc_e31200_attach(device_t dev) { struct ecc_e31200_softc *sc = device_get_softc(dev); uint32_t capa, dmfc, mch_barlo, mch_barhi; uint64_t mch_bar; int bus, slot; dev = sc->ecc_device; /* XXX */ bus = pci_get_bus(dev); slot = pci_get_slot(dev); capa = pcib_read_config(dev, bus, slot, 0, PCI_E31200_CAPID0_A, 4); dmfc = __SHIFTOUT(capa, PCI_E31200_CAPID0_A_DMFC); if (dmfc == PCI_E31200_CAPID0_A_DMFC_1333) { ecc_printf(sc, "CAP DDR3 1333 "); } else if (dmfc == PCI_E31200_CAPID0_A_DMFC_1067) { ecc_printf(sc, "CAP DDR3 1067 "); } else if (dmfc == PCI_E31200_CAPID0_A_DMFC_ALL) { ecc_printf(sc, "no CAP "); } else { ecc_printf(sc, "unknown DMFC %#x\n", dmfc); return 0; } if (capa & PCI_E31200_CAPID0_A_ECCDIS) { kprintf("NON-ECC\n"); return 0; } else { kprintf("ECC\n"); } mch_barlo = pcib_read_config(dev, bus, slot, 0, PCI_E31200_MCHBAR_LO, 4); mch_barhi = pcib_read_config(dev, bus, slot, 0, PCI_E31200_MCHBAR_HI, 4); mch_bar = (uint64_t)mch_barlo | (((uint64_t)mch_barhi) << 32); if (bootverbose) ecc_printf(sc, "MCHBAR %jx\n", (uintmax_t)mch_bar); if (mch_bar & PCI_E31200_MCHBAR_LO_EN) { uint64_t map_addr = mch_bar & PCI_E31200_MCHBAR_ADDRMASK; uint32_t dimm_ch0, dimm_ch1; sc->ecc_addr = pmap_mapdev_uncacheable(map_addr, MCH_E31200_SIZE); if (bootverbose) { ecc_printf(sc, "LOG0_C0 %#x\n", CSR_READ_4(sc, MCH_E31200_ERRLOG0_C0)); ecc_printf(sc, "LOG0_C1 %#x\n", CSR_READ_4(sc, MCH_E31200_ERRLOG0_C1)); } dimm_ch0 = CSR_READ_4(sc, MCH_E31200_DIMM_CH0); dimm_ch1 = CSR_READ_4(sc, MCH_E31200_DIMM_CH1); if (bootverbose) { ecc_e31200_chaninfo(sc, dimm_ch0, "channel0"); ecc_e31200_chaninfo(sc, dimm_ch1, "channel1"); } if (((dimm_ch0 | dimm_ch1) & MCH_E31200_DIMM_ECC) == 0) { ecc_printf(sc, "No ECC active\n"); pmap_unmapdev((vm_offset_t)sc->ecc_addr, MCH_E31200_SIZE); return 0; } } ecc_e31200_status(sc); callout_init_mp(&sc->ecc_callout); callout_reset(&sc->ecc_callout, hz, ecc_e31200_callout, sc); return 0; }
static int ecc_e31200_attach(device_t dev) { struct ecc_e31200_softc *sc = device_get_softc(dev); uint32_t capa, dmfc, mch_barlo, mch_barhi; uint64_t mch_bar; int bus, slot, dmfc_parsed = 1; dev = sc->ecc_device; /* XXX */ bus = pci_get_bus(dev); slot = pci_get_slot(dev); capa = pcib_read_config(dev, bus, slot, 0, PCI_E31200_CAPID0_A, 4); if (sc->ecc_ver == ECC_E31200_VER_1) { dmfc = __SHIFTOUT(capa, PCI_E31200_CAPID0_A_DMFC); } else { /* V2/V3 */ uint32_t capb; capb = pcib_read_config(dev, bus, slot, 0, PCI_E31200_CAPID0_B, 4); dmfc = __SHIFTOUT(capb, PCI_E31200_CAPID0_B_DMFC); } if (dmfc == PCI_E31200_CAPID0_DMFC_1067) { ecc_printf(sc, "CAP DDR3 1067 "); } else if (dmfc == PCI_E31200_CAPID0_DMFC_1333) { ecc_printf(sc, "CAP DDR3 1333 "); } else { if (sc->ecc_ver == ECC_E31200_VER_1) { if (dmfc == PCI_E31200_CAPID0_DMFC_V1_ALL) ecc_printf(sc, "no CAP "); else dmfc_parsed = 0; } else { /* V2/V3 */ if (dmfc == PCI_E31200_CAPID0_DMFC_1600) ecc_printf(sc, "CAP DDR3 1600 "); else if (dmfc == PCI_E31200_CAPID0_DMFC_1867) ecc_printf(sc, "CAP DDR3 1867 "); else if (dmfc == PCI_E31200_CAPID0_DMFC_2133) ecc_printf(sc, "CAP DDR3 2133 "); else if (dmfc == PCI_E31200_CAPID0_DMFC_2400) ecc_printf(sc, "CAP DDR3 2400 "); else if (dmfc == PCI_E31200_CAPID0_DMFC_2667) ecc_printf(sc, "CAP DDR3 2667 "); else if (dmfc == PCI_E31200_CAPID0_DMFC_2933) ecc_printf(sc, "CAP DDR3 2933 "); else dmfc_parsed = 0; } } if (!dmfc_parsed) { ecc_printf(sc, "unknown DMFC %#x\n", dmfc); return 0; } if (capa & PCI_E31200_CAPID0_A_ECCDIS) { kprintf("NON-ECC\n"); return 0; } else { kprintf("ECC\n"); } mch_barlo = pcib_read_config(dev, bus, slot, 0, PCI_E31200_MCHBAR_LO, 4); mch_barhi = pcib_read_config(dev, bus, slot, 0, PCI_E31200_MCHBAR_HI, 4); mch_bar = (uint64_t)mch_barlo | (((uint64_t)mch_barhi) << 32); if (bootverbose) ecc_printf(sc, "MCHBAR %jx\n", (uintmax_t)mch_bar); if (mch_bar & PCI_E31200_MCHBAR_LO_EN) { uint64_t map_addr = mch_bar & PCI_E31200_MCHBAR_ADDRMASK; uint32_t dimm_ch0, dimm_ch1; int ecc_active; sc->ecc_addr = pmap_mapdev_uncacheable(map_addr, MCH_E31200_SIZE); if (bootverbose) { ecc_printf(sc, "LOG0_C0 %#x\n", CSR_READ_4(sc, MCH_E31200_ERRLOG0_C0)); ecc_printf(sc, "LOG0_C1 %#x\n", CSR_READ_4(sc, MCH_E31200_ERRLOG0_C1)); } dimm_ch0 = CSR_READ_4(sc, MCH_E31200_DIMM_CH0); dimm_ch1 = CSR_READ_4(sc, MCH_E31200_DIMM_CH1); if (bootverbose) { ecc_e31200_chaninfo(sc, dimm_ch0, "channel0"); ecc_e31200_chaninfo(sc, dimm_ch1, "channel1"); } ecc_active = 1; if (sc->ecc_ver == ECC_E31200_VER_1 || sc->ecc_ver == ECC_E31200_VER_2) { if (((dimm_ch0 | dimm_ch1) & MCH_E31200_DIMM_ECC) == MCH_E31200_DIMM_ECC_NONE) { ecc_active = 0; ecc_printf(sc, "No ECC active\n"); } } else { /* V3 */ uint32_t ecc_mode0, ecc_mode1; ecc_mode0 = __SHIFTOUT(dimm_ch0, MCH_E31200_DIMM_ECC); ecc_mode1 = __SHIFTOUT(dimm_ch1, MCH_E31200_DIMM_ECC); /* * Only active ALL/NONE is supported */ if (ecc_mode0 != MCH_E31200_DIMM_ECC_NONE && ecc_mode0 != MCH_E31200_DIMM_ECC_ALL) { ecc_active = 0; ecc_printf(sc, "channel0, invalid ECC " "active 0x%x\n", ecc_mode0); } if (ecc_mode1 != MCH_E31200_DIMM_ECC_NONE && ecc_mode1 != MCH_E31200_DIMM_ECC_ALL) { ecc_active = 0; ecc_printf(sc, "channel1, invalid ECC " "active 0x%x\n", ecc_mode1); } if (ecc_mode0 == MCH_E31200_DIMM_ECC_NONE && ecc_mode1 == MCH_E31200_DIMM_ECC_NONE) { ecc_active = 0; ecc_printf(sc, "No ECC active\n"); } } if (!ecc_active) { pmap_unmapdev((vm_offset_t)sc->ecc_addr, MCH_E31200_SIZE); return 0; } } else { ecc_printf(sc, "MCHBAR is not enabled\n"); } ecc_e31200_status(sc); callout_init_mp(&sc->ecc_callout); callout_reset(&sc->ecc_callout, hz, ecc_e31200_callout, sc); return 0; }