2 * Copyright (c) 2017 Alexander Motin <mav@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * The Non-Transparent Bridge (NTB) is a device that allows you to connect
29 * two or more systems using a PCI-e links, providing remote memory access.
31 * This module contains a driver for NTBs in PLX/Avago/Broadcom PCIe bridges.
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
37 #include <sys/param.h>
38 #include <sys/kernel.h>
39 #include <sys/systm.h>
41 #include <sys/interrupt.h>
42 #include <sys/module.h>
44 #include <sys/sysctl.h>
47 #include <machine/bus.h>
48 #include <machine/intr_machdep.h>
49 #include <machine/resource.h>
50 #include <dev/pci/pcireg.h>
51 #include <dev/pci/pcivar.h>
55 #define PLX_MAX_BARS 4 /* There are at most 4 data BARs. */
56 #define PLX_NUM_SPAD 8 /* There are 8 scratchpads. */
57 #define PLX_NUM_SPAD_PATT 4 /* Use test pattern as 4 more. */
58 #define PLX_NUM_DB 16 /* There are 16 doorbells. */
60 struct ntb_plx_mw_info {
64 struct resource *mw_res;
68 vm_memattr_t mw_map_mode;
69 bus_addr_t mw_xlat_addr;
73 struct ntb_plx_softc {
74 /* ntb.c context. Do not move! Must go first! */
78 struct resource *conf_res;
80 u_int ntx; /* NTx number within chip. */
81 u_int link; /* Link v/s Virtual side. */
82 u_int port; /* Port number within chip. */
83 u_int alut; /* A-LUT is enabled for NTx */
86 struct resource *int_res;
89 struct ntb_plx_mw_info mw_info[PLX_MAX_BARS];
90 int mw_count; /* Number of memory windows. */
92 int spad_count1; /* Number of standard spads. */
93 int spad_count2; /* Number of extra spads. */
94 uint32_t spad_off1; /* Offset of our spads. */
95 uint32_t spad_off2; /* Offset of our extra spads. */
96 uint32_t spad_offp1; /* Offset of peer spads. */
97 uint32_t spad_offp2; /* Offset of peer extra spads. */
99 /* Parameters of window shared with peer config access in B2B mode. */
100 int b2b_mw; /* Shared window number. */
101 uint64_t b2b_off; /* Offset in shared window. */
104 #define PLX_NT0_BASE 0x3E000
105 #define PLX_NT1_BASE 0x3C000
106 #define PLX_NTX_BASE(sc) ((sc)->ntx ? PLX_NT1_BASE : PLX_NT0_BASE)
107 #define PLX_NTX_LINK_OFFSET 0x01000
109 /* Bases of NTx our/peer interface registers */
110 #define PLX_NTX_OUR_BASE(sc) \
111 (PLX_NTX_BASE(sc) + ((sc)->link ? PLX_NTX_LINK_OFFSET : 0))
112 #define PLX_NTX_PEER_BASE(sc) \
113 (PLX_NTX_BASE(sc) + ((sc)->link ? 0 : PLX_NTX_LINK_OFFSET))
115 /* Read/write NTx our interface registers */
116 #define NTX_READ(sc, reg) \
117 bus_read_4((sc)->conf_res, PLX_NTX_OUR_BASE(sc) + (reg))
118 #define NTX_WRITE(sc, reg, val) \
119 bus_write_4((sc)->conf_res, PLX_NTX_OUR_BASE(sc) + (reg), (val))
121 /* Read/write NTx peer interface registers */
122 #define PNTX_READ(sc, reg) \
123 bus_read_4((sc)->conf_res, PLX_NTX_PEER_BASE(sc) + (reg))
124 #define PNTX_WRITE(sc, reg, val) \
125 bus_write_4((sc)->conf_res, PLX_NTX_PEER_BASE(sc) + (reg), (val))
127 /* Read/write B2B NTx registers */
128 #define BNTX_READ(sc, reg) \
129 bus_read_4((sc)->mw_info[(sc)->b2b_mw].mw_res, \
130 PLX_NTX_BASE(sc) + (reg))
131 #define BNTX_WRITE(sc, reg, val) \
132 bus_write_4((sc)->mw_info[(sc)->b2b_mw].mw_res, \
133 PLX_NTX_BASE(sc) + (reg), (val))
135 #define PLX_PORT_BASE(p) ((p) << 12)
136 #define PLX_STATION_PORT_BASE(sc) PLX_PORT_BASE((sc)->port & ~7)
138 #define PLX_PORT_CONTROL(sc) (PLX_STATION_PORT_BASE(sc) + 0x208)
140 static int ntb_plx_init(device_t dev);
141 static int ntb_plx_detach(device_t dev);
142 static int ntb_plx_mw_set_trans_internal(device_t dev, unsigned mw_idx);
145 ntb_plx_probe(device_t dev)
148 switch (pci_get_devid(dev)) {
150 device_set_desc(dev, "PLX Non-Transparent Bridge NT0 Link");
151 return (BUS_PROBE_DEFAULT);
153 device_set_desc(dev, "PLX Non-Transparent Bridge NT1 Link");
154 return (BUS_PROBE_DEFAULT);
156 device_set_desc(dev, "PLX Non-Transparent Bridge NT0 Virtual");
157 return (BUS_PROBE_DEFAULT);
159 device_set_desc(dev, "PLX Non-Transparent Bridge NT1 Virtual");
160 return (BUS_PROBE_DEFAULT);
166 ntb_plx_init(device_t dev)
168 struct ntb_plx_softc *sc = device_get_softc(dev);
169 struct ntb_plx_mw_info *mw;
174 if (sc->b2b_mw >= 0) {
175 /* Set peer BAR0/1 size and address for B2B NTx access. */
176 mw = &sc->mw_info[sc->b2b_mw];
178 PNTX_WRITE(sc, 0xe4, 0x3); /* 64-bit */
179 val64 = 0x2000000000000000 * mw->mw_bar | 0x4;
180 PNTX_WRITE(sc, PCIR_BAR(0), val64);
181 PNTX_WRITE(sc, PCIR_BAR(0) + 4, val64 >> 32);
183 PNTX_WRITE(sc, 0xe4, 0x2); /* 32-bit */
184 val = 0x20000000 * mw->mw_bar;
185 PNTX_WRITE(sc, PCIR_BAR(0), val);
188 /* Set Virtual to Link address translation for B2B. */
189 for (i = 0; i < sc->mw_count; i++) {
190 mw = &sc->mw_info[i];
192 val64 = 0x2000000000000000 * mw->mw_bar;
193 NTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4, val64);
194 NTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4 + 4, val64 >> 32);
196 val = 0x20000000 * mw->mw_bar;
197 NTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4, val);
201 /* Make sure Virtual to Link A-LUT is disabled. */
203 PNTX_WRITE(sc, 0xc94, 0);
205 /* Enable Link Interface LUT entries 0/1 for peer 0/1. */
206 PNTX_WRITE(sc, 0xdb4, 0x00090001);
210 * Enable Virtual Interface LUT entry 0 for 0:0.0 and
211 * entry 1 for our Requester ID reported by chip.
213 val = (NTX_READ(sc, 0xc90) << 16) | 0x00010001;
214 NTX_WRITE(sc, sc->link ? 0xdb4 : 0xd94, val);
216 /* Set Link to Virtual address translation. */
217 for (i = 0; i < sc->mw_count; i++) {
218 mw = &sc->mw_info[i];
219 if (mw->mw_xlat_size != 0)
220 ntb_plx_mw_set_trans_internal(dev, i);
223 pci_enable_busmaster(dev);
225 PNTX_WRITE(sc, PCIR_COMMAND, PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
231 ntb_plx_isr(void *arg)
234 struct ntb_plx_softc *sc = device_get_softc(dev);
237 ntb_db_event((device_t)arg, 0);
239 if (sc->link) /* Link Interface has no Link Error registers. */
242 val = NTX_READ(sc, 0xfe0);
245 NTX_WRITE(sc, 0xfe0, val);
247 device_printf(dev, "Correctable Error\n");
249 device_printf(dev, "Uncorrectable Error\n");
251 /* DL_Down resets link side registers, have to reinit. */
256 device_printf(dev, "Uncorrectable Error Message Drop\n");
260 ntb_plx_setup_intr(device_t dev)
262 struct ntb_plx_softc *sc = device_get_softc(dev);
266 * XXX: This hardware supports MSI, but I found it unusable.
267 * It generates new MSI only when doorbell register goes from
268 * zero, but does not generate it when another bit is set or on
269 * partial clear. It makes operation very racy and unreliable.
270 * The data book mentions some mask juggling magic to workaround
271 * that, but I failed to make it work.
274 sc->int_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
275 &sc->int_rid, RF_SHAREABLE|RF_ACTIVE);
276 if (sc->int_res == NULL) {
277 device_printf(dev, "bus_alloc_resource failed\n");
280 error = bus_setup_intr(dev, sc->int_res, INTR_MPSAFE | INTR_TYPE_MISC,
281 NULL, ntb_plx_isr, dev, &sc->int_tag);
283 device_printf(dev, "bus_setup_intr failed: %d\n", error);
287 if (!sc->link) { /* Link Interface has no Link Error registers. */
288 NTX_WRITE(sc, 0xfe0, 0xf); /* Clear link interrupts. */
289 NTX_WRITE(sc, 0xfe4, 0x0); /* Unmask link interrupts. */
295 ntb_plx_teardown_intr(device_t dev)
297 struct ntb_plx_softc *sc = device_get_softc(dev);
299 if (!sc->link) /* Link Interface has no Link Error registers. */
300 NTX_WRITE(sc, 0xfe4, 0xf); /* Mask link interrupts. */
303 bus_teardown_intr(dev, sc->int_res, sc->int_tag);
304 bus_release_resource(dev, SYS_RES_IRQ, sc->int_rid,
310 ntb_plx_attach(device_t dev)
312 struct ntb_plx_softc *sc = device_get_softc(dev);
313 struct ntb_plx_mw_info *mw;
318 /* Identify what we are (what side of what NTx). */
320 val = pci_read_config(dev, 0xc8c, 4);
321 sc->ntx = (val & 1) != 0;
322 sc->link = (val & 0x80000000) != 0;
324 /* Get access to whole 256KB of chip configuration space via BAR0/1. */
325 sc->conf_rid = PCIR_BAR(0);
326 sc->conf_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
327 &sc->conf_rid, RF_ACTIVE);
328 if (sc->conf_res == NULL) {
329 device_printf(dev, "Can't allocate configuration BAR.\n");
333 /* Identify chip port we are connected to. */
334 val = bus_read_4(sc->conf_res, 0x360);
335 sc->port = (val >> ((sc->ntx == 0) ? 8 : 16)) & 0x1f;
337 /* Detect A-LUT enable and size. */
339 sc->alut = (val == 0x3) ? 1 : ((val & (1 << sc->ntx)) ? 2 : 0);
341 device_printf(dev, "%u A-LUT entries\n", 128 * sc->alut);
343 /* Find configured memory windows at BAR2-5. */
345 for (i = 2; i <= 5; i++) {
346 mw = &sc->mw_info[sc->mw_count];
348 mw->mw_rid = PCIR_BAR(mw->mw_bar);
349 mw->mw_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
350 &mw->mw_rid, RF_ACTIVE);
351 if (mw->mw_res == NULL)
353 mw->mw_pbase = rman_get_start(mw->mw_res);
354 mw->mw_size = rman_get_size(mw->mw_res);
355 mw->mw_vbase = rman_get_virtual(mw->mw_res);
356 mw->mw_map_mode = VM_MEMATTR_UNCACHEABLE;
359 /* Skip over adjacent BAR for 64-bit BARs. */
360 val = pci_read_config(dev, PCIR_BAR(mw->mw_bar), 4);
361 if ((val & PCIM_BAR_MEM_TYPE) == PCIM_BAR_MEM_64) {
367 /* Try to identify B2B mode. */
369 snprintf(buf, sizeof(buf), "hint.%s.%d.b2b", device_get_name(dev),
370 device_get_unit(dev));
371 TUNABLE_INT_FETCH(buf, &i);
373 device_printf(dev, "NTB-to-Root Port mode (Link Interface)\n");
376 device_printf(dev, "NTB-to-Root Port mode (Virtual Interface)\n");
379 device_printf(dev, "NTB-to-NTB (back-to-back) mode\n");
381 /* We need at least one memory window for B2B peer access. */
382 if (sc->mw_count == 0) {
383 device_printf(dev, "No memory window BARs enabled.\n");
387 sc->b2b_mw = sc->mw_count - 1;
389 /* Use half of the window for B2B, but no less then 1MB. */
390 mw = &sc->mw_info[sc->b2b_mw];
391 if (mw->mw_size >= 2 * 1024 * 1024)
392 sc->b2b_off = mw->mw_size / 2;
398 * Use Physical Layer User Test Pattern as additional scratchpad.
399 * Make sure they are present and enabled by writing to them.
400 * XXX: Its a hack, but standard 8 registers are not enough.
402 sc->spad_offp1 = sc->spad_off1 = PLX_NTX_OUR_BASE(sc) + 0xc6c;
403 sc->spad_offp2 = sc->spad_off2 = PLX_PORT_BASE(sc->ntx * 8) + 0x20c;
404 if (sc->b2b_mw >= 0) {
405 /* In NTB-to-NTB mode each side has own scratchpads. */
406 sc->spad_count1 = PLX_NUM_SPAD;
407 bus_write_4(sc->conf_res, sc->spad_off2, 0x12345678);
408 if (bus_read_4(sc->conf_res, sc->spad_off2) == 0x12345678)
409 sc->spad_count2 = PLX_NUM_SPAD_PATT;
411 /* Otherwise we have share scratchpads with the peer. */
413 sc->spad_off1 += PLX_NUM_SPAD / 2 * 4;
414 sc->spad_off2 += PLX_NUM_SPAD_PATT / 2 * 4;
416 sc->spad_offp1 += PLX_NUM_SPAD / 2 * 4;
417 sc->spad_offp2 += PLX_NUM_SPAD_PATT / 2 * 4;
419 sc->spad_count1 = PLX_NUM_SPAD / 2;
420 bus_write_4(sc->conf_res, sc->spad_off2, 0x12345678);
421 if (bus_read_4(sc->conf_res, sc->spad_off2) == 0x12345678)
422 sc->spad_count2 = PLX_NUM_SPAD_PATT / 2;
425 /* Apply static part of NTB configuration. */
428 /* Allocate and setup interrupts. */
429 error = ntb_plx_setup_intr(dev);
433 /* Attach children to this controller */
434 error = ntb_register_device(dev);
443 ntb_plx_detach(device_t dev)
445 struct ntb_plx_softc *sc = device_get_softc(dev);
446 struct ntb_plx_mw_info *mw;
449 /* Detach & delete all children */
450 ntb_unregister_device(dev);
452 /* Disable and free interrupts. */
453 ntb_plx_teardown_intr(dev);
455 /* Free memory resources. */
456 for (i = 0; i < sc->mw_count; i++) {
457 mw = &sc->mw_info[i];
458 bus_release_resource(dev, SYS_RES_MEMORY, mw->mw_rid,
461 bus_release_resource(dev, SYS_RES_MEMORY, sc->conf_rid, sc->conf_res);
467 ntb_plx_link_is_up(device_t dev, enum ntb_speed *speed, enum ntb_width *width)
471 link = pcie_read_config(dev, PCIER_LINK_STA, 2);
473 *speed = (link & PCIEM_LINK_STA_SPEED);
475 *width = (link & PCIEM_LINK_STA_WIDTH) >> 4;
476 return ((link & PCIEM_LINK_STA_WIDTH) != 0);
480 ntb_plx_link_enable(device_t dev, enum ntb_speed speed __unused,
481 enum ntb_width width __unused)
483 struct ntb_plx_softc *sc = device_get_softc(dev);
486 /* The fact that we see the Link Interface means link is enabled. */
492 reg = PLX_PORT_CONTROL(sc);
493 val = bus_read_4(sc->conf_res, reg);
494 if ((val & (1 << (sc->port & 7))) == 0) {
495 /* If already enabled, generate fake link event and exit. */
499 val &= ~(1 << (sc->port & 7));
500 bus_write_4(sc->conf_res, reg, val);
505 ntb_plx_link_disable(device_t dev)
507 struct ntb_plx_softc *sc = device_get_softc(dev);
510 /* Link disable for Link Interface would be suicidal. */
514 reg = PLX_PORT_CONTROL(sc);
515 val = bus_read_4(sc->conf_res, reg);
516 val |= (1 << (sc->port & 7));
517 bus_write_4(sc->conf_res, reg, val);
522 ntb_plx_link_enabled(device_t dev)
524 struct ntb_plx_softc *sc = device_get_softc(dev);
527 /* The fact that we see the Link Interface means link is enabled. */
531 reg = PLX_PORT_CONTROL(sc);
532 val = bus_read_4(sc->conf_res, reg);
533 return ((val & (1 << (sc->port & 7))) == 0);
537 ntb_plx_mw_count(device_t dev)
539 struct ntb_plx_softc *sc = device_get_softc(dev);
541 if (sc->b2b_mw >= 0 && sc->b2b_off == 0)
542 return (sc->mw_count - 1); /* B2B consumed whole window. */
543 return (sc->mw_count);
547 ntb_plx_mw_get_range(device_t dev, unsigned mw_idx, vm_paddr_t *base,
548 caddr_t *vbase, size_t *size, size_t *align, size_t *align_size,
551 struct ntb_plx_softc *sc = device_get_softc(dev);
552 struct ntb_plx_mw_info *mw;
555 if (mw_idx >= sc->mw_count)
558 if (mw_idx == sc->b2b_mw) {
559 KASSERT(sc->b2b_off != 0,
560 ("user shouldn't get non-shared b2b mw"));
563 mw = &sc->mw_info[mw_idx];
565 /* Local to remote memory window parameters. */
567 *base = mw->mw_pbase + off;
569 *vbase = mw->mw_vbase + off;
571 *size = mw->mw_size - off;
574 * Remote to local memory window translation address alignment.
575 * Translation address has to be aligned to the BAR size, but A-LUT
576 * entries re-map addresses can be aligned to 1/128 or 1/256 of it.
577 * XXX: In B2B mode we can change BAR size (and so alignmet) live,
578 * but there is no way to report it here, so report safe value.
581 if (sc->alut && mw->mw_bar == 2)
582 *align = (mw->mw_size - off) / 128 / sc->alut;
584 *align = mw->mw_size - off;
588 * Remote to local memory window size alignment.
589 * The chip has no limit registers, but A-LUT, when available, allows
590 * access control with granularity of 1/128 or 1/256 of the BAR size.
591 * XXX: In B2B case we can change BAR size live, but there is no way
592 * to report it, so report half of the BAR size, that should be safe.
593 * In non-B2B case there is no control at all, so report the BAR size.
595 if (align_size != NULL) {
596 if (sc->alut && mw->mw_bar == 2)
597 *align_size = (mw->mw_size - off) / 128 / sc->alut;
598 else if (sc->b2b_mw >= 0)
599 *align_size = (mw->mw_size - off) / 2;
601 *align_size = mw->mw_size - off;
604 /* Remote to local memory window translation address upper limit. */
606 *plimit = mw->mw_64bit ? BUS_SPACE_MAXADDR :
607 BUS_SPACE_MAXADDR_32BIT;
612 ntb_plx_mw_set_trans_internal(device_t dev, unsigned mw_idx)
614 struct ntb_plx_softc *sc = device_get_softc(dev);
615 struct ntb_plx_mw_info *mw;
616 uint64_t addr, eaddr, off, size, bsize, esize, val64;
620 mw = &sc->mw_info[mw_idx];
621 addr = mw->mw_xlat_addr;
622 size = mw->mw_xlat_size;
624 if (mw_idx == sc->b2b_mw) {
626 KASSERT(off != 0, ("user shouldn't get non-shared b2b mw"));
629 * While generally we can set any BAR size on link side,
630 * for B2B shared window we can't go above preconfigured
631 * size due to BAR address alignment requirements.
633 if (size > mw->mw_size - off)
638 /* Round BAR size to next power of 2 or at least 1MB. */
640 if (!powerof2(bsize))
641 bsize = 1LL << flsll(bsize);
642 if (bsize < 1024 * 1024)
645 /* A-LUT has 128 or 256 times better granularity. */
647 if (sc->alut && mw->mw_bar == 2)
648 esize /= 128 * sc->alut;
650 /* addr should be aligned to BAR or A-LUT element size. */
651 if ((addr & (esize - 1)) != 0)
657 if (sc->b2b_mw >= 0) {
658 /* Set Link Interface BAR size and enable/disable it. */
661 val64 = (~(bsize - 1) & ~0xfffff);
663 PNTX_WRITE(sc, 0xe8 + (mw->mw_bar - 2) * 4, val64);
664 PNTX_WRITE(sc, 0xe8 + (mw->mw_bar - 2) * 4 + 4, val64 >> 32);
666 /* Set Link Interface BAR address. */
667 val64 = 0x2000000000000000 * mw->mw_bar + off;
668 PNTX_WRITE(sc, PCIR_BAR(mw->mw_bar), val64);
669 PNTX_WRITE(sc, PCIR_BAR(mw->mw_bar) + 4, val64 >> 32);
672 /* Set Virtual Interface BARs address translation */
673 PNTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4, addr);
674 PNTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4 + 4, addr >> 32);
676 /* Make sure we fit into 32-bit address space. */
677 if ((addr & UINT32_MAX) != addr)
679 if (((addr + bsize) & UINT32_MAX) != (addr + bsize))
682 if (sc->b2b_mw >= 0) {
683 /* Set Link Interface BAR size and enable/disable it. */
686 val = (~(bsize - 1) & ~0xfffff);
687 PNTX_WRITE(sc, 0xe8 + (mw->mw_bar - 2) * 4, val);
689 /* Set Link Interface BAR address. */
690 val64 = 0x20000000 * mw->mw_bar + off;
691 PNTX_WRITE(sc, PCIR_BAR(mw->mw_bar), val64);
694 /* Set Virtual Interface BARs address translation */
695 PNTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4, addr);
698 /* Configure and enable Link to Virtual A-LUT if we need it. */
699 if (sc->alut && mw->mw_bar == 2 &&
700 ((addr & (bsize - 1)) != 0 || size != bsize)) {
702 for (i = 0; i < 128 * sc->alut; i++) {
703 val = sc->link ? 0 : 1;
706 val *= 0x1000 * sc->alut;
707 val += 0x38000 + i * 4 + (i >= 128 ? 0x0e00 : 0);
708 bus_write_4(sc->conf_res, val, eaddr);
709 bus_write_4(sc->conf_res, val + 0x400, eaddr >> 32);
710 bus_write_4(sc->conf_res, val + 0x800,
711 (eaddr < addr + size) ? 0x3 : 0);
714 NTX_WRITE(sc, 0xc94, 0x10000000);
715 } else if (sc->alut && mw->mw_bar == 2)
716 NTX_WRITE(sc, 0xc94, 0);
722 ntb_plx_mw_set_trans(device_t dev, unsigned mw_idx, bus_addr_t addr, size_t size)
724 struct ntb_plx_softc *sc = device_get_softc(dev);
725 struct ntb_plx_mw_info *mw;
727 if (mw_idx >= sc->mw_count)
729 mw = &sc->mw_info[mw_idx];
730 mw->mw_xlat_addr = addr;
731 mw->mw_xlat_size = size;
732 return (ntb_plx_mw_set_trans_internal(dev, mw_idx));
736 ntb_plx_mw_clear_trans(device_t dev, unsigned mw_idx)
739 return (ntb_plx_mw_set_trans(dev, mw_idx, 0, 0));
743 ntb_plx_mw_get_wc(device_t dev, unsigned idx, vm_memattr_t *mode)
745 struct ntb_plx_softc *sc = device_get_softc(dev);
746 struct ntb_plx_mw_info *mw;
748 if (idx >= sc->mw_count)
750 mw = &sc->mw_info[idx];
751 *mode = mw->mw_map_mode;
756 ntb_plx_mw_set_wc(device_t dev, unsigned idx, vm_memattr_t mode)
758 struct ntb_plx_softc *sc = device_get_softc(dev);
759 struct ntb_plx_mw_info *mw;
763 if (idx >= sc->mw_count)
765 mw = &sc->mw_info[idx];
766 if (mw->mw_map_mode == mode)
770 if (idx == sc->b2b_mw) {
771 KASSERT(sc->b2b_off != 0,
772 ("user shouldn't get non-shared b2b mw"));
776 rc = pmap_change_attr((vm_offset_t)mw->mw_vbase + off,
777 mw->mw_size - off, mode);
779 mw->mw_map_mode = mode;
784 ntb_plx_spad_count(device_t dev)
786 struct ntb_plx_softc *sc = device_get_softc(dev);
788 return (sc->spad_count1 + sc->spad_count2);
792 ntb_plx_spad_write(device_t dev, unsigned int idx, uint32_t val)
794 struct ntb_plx_softc *sc = device_get_softc(dev);
797 if (idx >= sc->spad_count1 + sc->spad_count2)
800 if (idx < sc->spad_count1)
801 off = sc->spad_off1 + idx * 4;
803 off = sc->spad_off2 + (idx - sc->spad_count1) * 4;
804 bus_write_4(sc->conf_res, off, val);
809 ntb_plx_spad_clear(device_t dev)
811 struct ntb_plx_softc *sc = device_get_softc(dev);
814 for (i = 0; i < sc->spad_count1 + sc->spad_count2; i++)
815 ntb_plx_spad_write(dev, i, 0);
819 ntb_plx_spad_read(device_t dev, unsigned int idx, uint32_t *val)
821 struct ntb_plx_softc *sc = device_get_softc(dev);
824 if (idx >= sc->spad_count1 + sc->spad_count2)
827 if (idx < sc->spad_count1)
828 off = sc->spad_off1 + idx * 4;
830 off = sc->spad_off2 + (idx - sc->spad_count1) * 4;
831 *val = bus_read_4(sc->conf_res, off);
836 ntb_plx_peer_spad_write(device_t dev, unsigned int idx, uint32_t val)
838 struct ntb_plx_softc *sc = device_get_softc(dev);
841 if (idx >= sc->spad_count1 + sc->spad_count2)
844 if (idx < sc->spad_count1)
845 off = sc->spad_offp1 + idx * 4;
847 off = sc->spad_offp2 + (idx - sc->spad_count1) * 4;
849 bus_write_4(sc->mw_info[sc->b2b_mw].mw_res, off, val);
851 bus_write_4(sc->conf_res, off, val);
856 ntb_plx_peer_spad_read(device_t dev, unsigned int idx, uint32_t *val)
858 struct ntb_plx_softc *sc = device_get_softc(dev);
861 if (idx >= sc->spad_count1 + sc->spad_count2)
864 if (idx < sc->spad_count1)
865 off = sc->spad_offp1 + idx * 4;
867 off = sc->spad_offp2 + (idx - sc->spad_count1) * 4;
869 *val = bus_read_4(sc->mw_info[sc->b2b_mw].mw_res, off);
871 *val = bus_read_4(sc->conf_res, off);
876 ntb_plx_db_valid_mask(device_t dev)
879 return ((1LL << PLX_NUM_DB) - 1);
883 ntb_plx_db_vector_count(device_t dev)
890 ntb_plx_db_vector_mask(device_t dev, uint32_t vector)
895 return ((1LL << PLX_NUM_DB) - 1);
899 ntb_plx_db_clear(device_t dev, uint64_t bits)
901 struct ntb_plx_softc *sc = device_get_softc(dev);
903 NTX_WRITE(sc, sc->link ? 0xc60 : 0xc50, bits);
907 ntb_plx_db_clear_mask(device_t dev, uint64_t bits)
909 struct ntb_plx_softc *sc = device_get_softc(dev);
911 NTX_WRITE(sc, sc->link ? 0xc68 : 0xc58, bits);
915 ntb_plx_db_read(device_t dev)
917 struct ntb_plx_softc *sc = device_get_softc(dev);
919 return (NTX_READ(sc, sc->link ? 0xc5c : 0xc4c));
923 ntb_plx_db_set_mask(device_t dev, uint64_t bits)
925 struct ntb_plx_softc *sc = device_get_softc(dev);
927 NTX_WRITE(sc, sc->link ? 0xc64 : 0xc54, bits);
931 ntb_plx_peer_db_addr(device_t dev, bus_addr_t *db_addr, vm_size_t *db_size)
933 struct ntb_plx_softc *sc = device_get_softc(dev);
934 struct ntb_plx_mw_info *mw;
936 KASSERT((db_addr != NULL && db_size != NULL), ("must be non-NULL"));
938 if (sc->b2b_mw >= 0) {
939 mw = &sc->mw_info[sc->b2b_mw];
940 *db_addr = (uint64_t)mw->mw_pbase + PLX_NTX_BASE(sc) + 0xc4c;
942 *db_addr = rman_get_start(sc->conf_res) + PLX_NTX_BASE(sc);
943 *db_addr += sc->link ? 0xc4c : 0xc5c;
950 ntb_plx_peer_db_set(device_t dev, uint64_t bit)
952 struct ntb_plx_softc *sc = device_get_softc(dev);
955 BNTX_WRITE(sc, 0xc4c, bit);
957 NTX_WRITE(sc, sc->link ? 0xc4c : 0xc5c, bit);
960 static device_method_t ntb_plx_methods[] = {
961 /* Device interface */
962 DEVMETHOD(device_probe, ntb_plx_probe),
963 DEVMETHOD(device_attach, ntb_plx_attach),
964 DEVMETHOD(device_detach, ntb_plx_detach),
966 DEVMETHOD(bus_child_location_str, ntb_child_location_str),
967 DEVMETHOD(bus_print_child, ntb_print_child),
969 DEVMETHOD(ntb_link_is_up, ntb_plx_link_is_up),
970 DEVMETHOD(ntb_link_enable, ntb_plx_link_enable),
971 DEVMETHOD(ntb_link_disable, ntb_plx_link_disable),
972 DEVMETHOD(ntb_link_enabled, ntb_plx_link_enabled),
973 DEVMETHOD(ntb_mw_count, ntb_plx_mw_count),
974 DEVMETHOD(ntb_mw_get_range, ntb_plx_mw_get_range),
975 DEVMETHOD(ntb_mw_set_trans, ntb_plx_mw_set_trans),
976 DEVMETHOD(ntb_mw_clear_trans, ntb_plx_mw_clear_trans),
977 DEVMETHOD(ntb_mw_get_wc, ntb_plx_mw_get_wc),
978 DEVMETHOD(ntb_mw_set_wc, ntb_plx_mw_set_wc),
979 DEVMETHOD(ntb_spad_count, ntb_plx_spad_count),
980 DEVMETHOD(ntb_spad_clear, ntb_plx_spad_clear),
981 DEVMETHOD(ntb_spad_write, ntb_plx_spad_write),
982 DEVMETHOD(ntb_spad_read, ntb_plx_spad_read),
983 DEVMETHOD(ntb_peer_spad_write, ntb_plx_peer_spad_write),
984 DEVMETHOD(ntb_peer_spad_read, ntb_plx_peer_spad_read),
985 DEVMETHOD(ntb_db_valid_mask, ntb_plx_db_valid_mask),
986 DEVMETHOD(ntb_db_vector_count, ntb_plx_db_vector_count),
987 DEVMETHOD(ntb_db_vector_mask, ntb_plx_db_vector_mask),
988 DEVMETHOD(ntb_db_clear, ntb_plx_db_clear),
989 DEVMETHOD(ntb_db_clear_mask, ntb_plx_db_clear_mask),
990 DEVMETHOD(ntb_db_read, ntb_plx_db_read),
991 DEVMETHOD(ntb_db_set_mask, ntb_plx_db_set_mask),
992 DEVMETHOD(ntb_peer_db_addr, ntb_plx_peer_db_addr),
993 DEVMETHOD(ntb_peer_db_set, ntb_plx_peer_db_set),
997 static DEFINE_CLASS_0(ntb_hw, ntb_plx_driver, ntb_plx_methods,
998 sizeof(struct ntb_plx_softc));
999 DRIVER_MODULE(ntb_hw_plx, pci, ntb_plx_driver, ntb_hw_devclass, NULL, NULL);
1000 MODULE_DEPEND(ntb_hw_plx, ntb, 1, 1, 1);
1001 MODULE_VERSION(ntb_hw_plx, 1);