static int ntb_setup_xeon(struct ntb_softc *ntb) { uint8_t val, connection_type; val = pci_read_config(ntb->device, NTB_PPD_OFFSET, 1); connection_type = val & XEON_PPD_CONN_TYPE; switch (connection_type) { case NTB_CONN_B2B: ntb->conn_type = NTB_CONN_B2B; break; case NTB_CONN_CLASSIC: case NTB_CONN_RP: default: device_printf(ntb->device, "Connection type %d not supported\n", connection_type); return (ENXIO); } if ((val & XEON_PPD_DEV_TYPE) != 0) ntb->dev_type = NTB_DEV_DSD; else ntb->dev_type = NTB_DEV_USD; ntb->reg_ofs.pdb = XEON_PDOORBELL_OFFSET; ntb->reg_ofs.pdb_mask = XEON_PDBMSK_OFFSET; ntb->reg_ofs.sbar2_xlat = XEON_SBAR2XLAT_OFFSET; ntb->reg_ofs.sbar4_xlat = XEON_SBAR4XLAT_OFFSET; ntb->reg_ofs.lnk_cntl = XEON_NTBCNTL_OFFSET; ntb->reg_ofs.lnk_stat = XEON_LINK_STATUS_OFFSET; ntb->reg_ofs.spad_local = XEON_SPAD_OFFSET; ntb->reg_ofs.spci_cmd = XEON_PCICMD_OFFSET; if (ntb->conn_type == NTB_CONN_B2B) { ntb->reg_ofs.sdb = XEON_B2B_DOORBELL_OFFSET; ntb->reg_ofs.spad_remote = XEON_B2B_SPAD_OFFSET; ntb->limits.max_spads = XEON_MAX_SPADS; } else { ntb->reg_ofs.sdb = XEON_SDOORBELL_OFFSET; ntb->reg_ofs.spad_remote = XEON_SPAD_OFFSET; ntb->limits.max_spads = XEON_MAX_COMPAT_SPADS; } ntb->limits.max_db_bits = XEON_MAX_DB_BITS; ntb->limits.msix_cnt = XEON_MSIX_CNT; ntb->bits_per_vector = XEON_DB_BITS_PER_VEC; configure_xeon_secondary_side_bars(ntb); /* Enable Bus Master and Memory Space on the secondary side */ ntb_reg_write(2, ntb->reg_ofs.spci_cmd, PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); /* Enable link training */ ntb_reg_write(4, ntb->reg_ofs.lnk_cntl, NTB_CNTL_BAR23_SNOOP | NTB_CNTL_BAR45_SNOOP); return (0); }
static int ntb_setup_xeon(struct ntb_softc *ntb) { ntb->reg_ofs.ldb = XEON_PDOORBELL_OFFSET; ntb->reg_ofs.ldb_mask = XEON_PDBMSK_OFFSET; ntb->reg_ofs.spad_local = XEON_SPAD_OFFSET; ntb->reg_ofs.bar2_xlat = XEON_SBAR2XLAT_OFFSET; ntb->reg_ofs.bar4_xlat = XEON_SBAR4XLAT_OFFSET; if (HAS_FEATURE(NTB_SPLIT_BAR)) ntb->reg_ofs.bar5_xlat = XEON_SBAR5XLAT_OFFSET; switch (ntb->conn_type) { case NTB_CONN_B2B: /* * reg_ofs.rdb and reg_ofs.spad_remote are effectively ignored * with the NTB_REGS_THRU_MW errata mode enabled. (See * ntb_ring_doorbell() and ntb_read/write_remote_spad().) */ ntb->reg_ofs.rdb = XEON_B2B_DOORBELL_OFFSET; ntb->reg_ofs.spad_remote = XEON_B2B_SPAD_OFFSET; ntb->limits.max_spads = XEON_MAX_SPADS; break; case NTB_CONN_RP: /* * Every Xeon today needs NTB_REGS_THRU_MW, so punt on RP for * now. */ KASSERT(HAS_FEATURE(NTB_REGS_THRU_MW), ("Xeon without MW errata unimplemented")); device_printf(ntb->device, "NTB-RP disabled to due hardware errata.\n"); return (ENXIO); case NTB_CONN_TRANSPARENT: default: device_printf(ntb->device, "Connection type %d not supported\n", ntb->conn_type); return (ENXIO); } /* * There is a Xeon hardware errata related to writes to SDOORBELL or * B2BDOORBELL in conjunction with inbound access to NTB MMIO space, * which may hang the system. To workaround this use the second memory * window to access the interrupt and scratch pad registers on the * remote system. * * There is another HW errata on the limit registers -- they can only * be written when the base register is (?)4GB aligned and < 32-bit. * This should already be the case based on the driver defaults, but * write the limit registers first just in case. */ if (HAS_FEATURE(NTB_REGS_THRU_MW)) { /* * Set the Limit register to 4k, the minimum size, to prevent * an illegal access. * * XXX: Should this be PBAR5LMT / get_mw_size(, max_mw - 1)? */ ntb_reg_write(8, XEON_PBAR4LMT_OFFSET, ntb_get_mw_size(ntb, 1) + 0x1000); /* Reserve the last MW for mapping remote spad */ ntb->limits.max_mw--; } else /* * Disable the limit register, just in case it is set to * something silly. A 64-bit write will also clear PBAR5LMT in * split-bar mode, and this is desired. */ ntb_reg_write(8, XEON_PBAR4LMT_OFFSET, 0); ntb->reg_ofs.lnk_cntl = XEON_NTBCNTL_OFFSET; ntb->reg_ofs.lnk_stat = XEON_LINK_STATUS_OFFSET; ntb->reg_ofs.spci_cmd = XEON_PCICMD_OFFSET; ntb->limits.max_db_bits = XEON_MAX_DB_BITS; ntb->limits.msix_cnt = XEON_MSIX_CNT; ntb->bits_per_vector = XEON_DB_BITS_PER_VEC; /* * HW Errata on bit 14 of b2bdoorbell register. Writes will not be * mirrored to the remote system. Shrink the number of bits by one, * since bit 14 is the last bit. * * On REGS_THRU_MW errata mode, we don't use the b2bdoorbell register * anyway. Nor for non-B2B connection types. */ if (HAS_FEATURE(NTB_B2BDOORBELL_BIT14) && !HAS_FEATURE(NTB_REGS_THRU_MW) && ntb->conn_type == NTB_CONN_B2B) ntb->limits.max_db_bits = XEON_MAX_DB_BITS - 1; configure_xeon_secondary_side_bars(ntb); /* Enable Bus Master and Memory Space on the secondary side */ if (ntb->conn_type == NTB_CONN_B2B) ntb_reg_write(2, ntb->reg_ofs.spci_cmd, PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); /* Enable link training */ ntb_hw_link_up(ntb); return (0); }