xref: /freebsd/sys/dev/ntb/ntb_hw/ntb_hw_plx.c (revision 3883c6fbf232452098ba6ea802ef1426d83d2d68)
1 /*-
2  * Copyright (c) 2017-2019 Alexander Motin <mav@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
13  *
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
24  * SUCH DAMAGE.
25  */
26 
27 /*
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.
30  *
31  * This module contains a driver for NTBs in PLX/Avago/Broadcom PCIe bridges.
32  */
33 
34 #include <sys/param.h>
35 #include <sys/kernel.h>
36 #include <sys/systm.h>
37 #include <sys/bus.h>
38 #include <sys/interrupt.h>
39 #include <sys/module.h>
40 #include <sys/rman.h>
41 #include <sys/sysctl.h>
42 #include <sys/taskqueue.h>
43 #include <sys/tree.h>
44 #include <vm/vm.h>
45 #include <vm/pmap.h>
46 #include <machine/bus.h>
47 #include <machine/intr_machdep.h>
48 #include <machine/resource.h>
49 #include <dev/pci/pcireg.h>
50 #include <dev/pci/pcivar.h>
51 #include <dev/iommu/iommu.h>
52 
53 #include "../ntb.h"
54 
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. */
59 #define PLX_MAX_SPLIT		128	/* Allow are at most 128 splits. */
60 
61 struct ntb_plx_mw_info {
62 	int			 mw_bar;
63 	int			 mw_64bit;
64 	int			 mw_rid;
65 	struct resource		*mw_res;
66 	vm_paddr_t		 mw_pbase;
67 	caddr_t			 mw_vbase;
68 	vm_size_t		 mw_size;
69 	struct {
70 		vm_memattr_t	 mw_map_mode;
71 		bus_addr_t	 mw_xlat_addr;
72 		bus_size_t	 mw_xlat_size;
73 	} splits[PLX_MAX_SPLIT];
74 };
75 
76 struct ntb_plx_softc {
77 	/* ntb.c context. Do not move! Must go first! */
78 	void			*ntb_store;
79 
80 	device_t		 dev;
81 	struct resource		*conf_res;
82 	int			 conf_rid;
83 	u_int			 ntx;		/* NTx number within chip. */
84 	u_int			 link;		/* Link v/s Virtual side. */
85 	u_int			 port;		/* Port number within chip. */
86 	u_int			 alut;		/* A-LUT is enabled for NTx */
87 	u_int			 split;		/* split BAR2 into 2^x parts */
88 
89 	int			 int_rid;
90 	struct resource		*int_res;
91 	void			*int_tag;
92 
93 	struct ntb_plx_mw_info	 mw_info[PLX_MAX_BARS];
94 	int			 mw_count;	/* Number of memory windows. */
95 
96 	int			 spad_count1;	/* Number of standard spads. */
97 	int			 spad_count2;	/* Number of extra spads. */
98 	uint32_t		 spad_off1;	/* Offset of our spads. */
99 	uint32_t		 spad_off2;	/* Offset of our extra spads. */
100 	uint32_t		 spad_offp1;	/* Offset of peer spads. */
101 	uint32_t		 spad_offp2;	/* Offset of peer extra spads. */
102 
103 	/* Parameters of window shared with peer config access in B2B mode. */
104 	int			 b2b_mw;	/* Shared window number. */
105 	uint64_t		 b2b_off;	/* Offset in shared window. */
106 };
107 
108 #define	PLX_NT0_BASE		0x3E000
109 #define	PLX_NT1_BASE		0x3C000
110 #define	PLX_NTX_BASE(sc)	((sc)->ntx ? PLX_NT1_BASE : PLX_NT0_BASE)
111 #define	PLX_NTX_LINK_OFFSET	0x01000
112 
113 /* Bases of NTx our/peer interface registers */
114 #define	PLX_NTX_OUR_BASE(sc)				\
115     (PLX_NTX_BASE(sc) + ((sc)->link ? PLX_NTX_LINK_OFFSET : 0))
116 #define	PLX_NTX_PEER_BASE(sc)				\
117     (PLX_NTX_BASE(sc) + ((sc)->link ? 0 : PLX_NTX_LINK_OFFSET))
118 
119 /* Read/write NTx our interface registers */
120 #define	NTX_READ(sc, reg)				\
121     bus_read_4((sc)->conf_res, PLX_NTX_OUR_BASE(sc) + (reg))
122 #define	NTX_WRITE(sc, reg, val)				\
123     bus_write_4((sc)->conf_res, PLX_NTX_OUR_BASE(sc) + (reg), (val))
124 
125 /* Read/write NTx peer interface registers */
126 #define	PNTX_READ(sc, reg)				\
127     bus_read_4((sc)->conf_res, PLX_NTX_PEER_BASE(sc) + (reg))
128 #define	PNTX_WRITE(sc, reg, val)			\
129     bus_write_4((sc)->conf_res, PLX_NTX_PEER_BASE(sc) + (reg), (val))
130 
131 /* Read/write B2B NTx registers */
132 #define	BNTX_READ(sc, reg)				\
133     bus_read_4((sc)->mw_info[(sc)->b2b_mw].mw_res,	\
134     PLX_NTX_BASE(sc) + (reg))
135 #define	BNTX_WRITE(sc, reg, val)			\
136     bus_write_4((sc)->mw_info[(sc)->b2b_mw].mw_res,	\
137     PLX_NTX_BASE(sc) + (reg), (val))
138 
139 #define	PLX_PORT_BASE(p)		((p) << 12)
140 #define	PLX_STATION_PORT_BASE(sc)	PLX_PORT_BASE((sc)->port & ~7)
141 
142 #define	PLX_PORT_CONTROL(sc)		(PLX_STATION_PORT_BASE(sc) + 0x208)
143 
144 static int ntb_plx_init(device_t dev);
145 static int ntb_plx_detach(device_t dev);
146 static int ntb_plx_mw_set_trans_internal(device_t dev, unsigned mw_idx);
147 
148 static int
ntb_plx_probe(device_t dev)149 ntb_plx_probe(device_t dev)
150 {
151 
152 	switch (pci_get_devid(dev)) {
153 	case 0x87a010b5:
154 		device_set_desc(dev, "PLX Non-Transparent Bridge NT0 Link");
155 		return (BUS_PROBE_DEFAULT);
156 	case 0x87a110b5:
157 		device_set_desc(dev, "PLX Non-Transparent Bridge NT1 Link");
158 		return (BUS_PROBE_DEFAULT);
159 	case 0x87b010b5:
160 		device_set_desc(dev, "PLX Non-Transparent Bridge NT0 Virtual");
161 		return (BUS_PROBE_DEFAULT);
162 	case 0x87b110b5:
163 		device_set_desc(dev, "PLX Non-Transparent Bridge NT1 Virtual");
164 		return (BUS_PROBE_DEFAULT);
165 	}
166 	return (ENXIO);
167 }
168 
169 static int
ntb_plx_init(device_t dev)170 ntb_plx_init(device_t dev)
171 {
172 	struct ntb_plx_softc *sc = device_get_softc(dev);
173 	struct ntb_plx_mw_info *mw;
174 	uint64_t val64;
175 	int i;
176 	uint32_t val;
177 
178 	if (sc->b2b_mw >= 0) {
179 		/* Set peer BAR0/1 size and address for B2B NTx access. */
180 		mw = &sc->mw_info[sc->b2b_mw];
181 		if (mw->mw_64bit) {
182 			PNTX_WRITE(sc, 0xe4, 0x3);	/* 64-bit */
183 			val64 = 0x2000000000000000 * mw->mw_bar | 0x4;
184 			PNTX_WRITE(sc, PCIR_BAR(0), val64);
185 			PNTX_WRITE(sc, PCIR_BAR(0) + 4, val64 >> 32);
186 		} else {
187 			PNTX_WRITE(sc, 0xe4, 0x2);	/* 32-bit */
188 			val = 0x20000000 * mw->mw_bar;
189 			PNTX_WRITE(sc, PCIR_BAR(0), val);
190 		}
191 
192 		/* Set Virtual to Link address translation for B2B. */
193 		for (i = 0; i < sc->mw_count; i++) {
194 			mw = &sc->mw_info[i];
195 			if (mw->mw_64bit) {
196 				val64 = 0x2000000000000000 * mw->mw_bar;
197 				NTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4, val64);
198 				NTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4 + 4, val64 >> 32);
199 			} else {
200 				val = 0x20000000 * mw->mw_bar;
201 				NTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4, val);
202 			}
203 		}
204 
205 		/* Make sure Virtual to Link A-LUT is disabled. */
206 		if (sc->alut)
207 			PNTX_WRITE(sc, 0xc94, 0);
208 
209 		/* Enable all Link Interface LUT entries for peer. */
210 		for (i = 0; i < 32; i += 2) {
211 			PNTX_WRITE(sc, 0xdb4 + i * 2,
212 			    0x00010001 | ((i + 1) << 19) | (i << 3));
213 		}
214 	}
215 
216 	/*
217 	 * Enable Virtual Interface LUT entry 0 for 0:0.*.
218 	 * entry 1 for our Requester ID reported by the chip,
219 	 * entries 2-5 for 0/64/128/192:4.* of I/OAT DMA engines.
220 	 * XXX: Its a hack, we can't know all DMA engines, but this covers all
221 	 * I/OAT of Xeon E5/E7 at least from Sandy Bridge till Skylake I saw.
222 	 */
223 	val = (NTX_READ(sc, 0xc90) << 16) | 0x00010001;
224 	NTX_WRITE(sc, sc->link ? 0xdb4 : 0xd94, val);
225 	NTX_WRITE(sc, sc->link ? 0xdb8 : 0xd98, 0x40210021);
226 	NTX_WRITE(sc, sc->link ? 0xdbc : 0xd9c, 0xc0218021);
227 
228 	/* Set Link to Virtual address translation. */
229 	for (i = 0; i < sc->mw_count; i++)
230 		ntb_plx_mw_set_trans_internal(dev, i);
231 
232 	pci_enable_busmaster(dev);
233 	if (sc->b2b_mw >= 0)
234 		PNTX_WRITE(sc, PCIR_COMMAND, PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
235 
236 	return (0);
237 }
238 
239 static void
ntb_plx_isr(void * arg)240 ntb_plx_isr(void *arg)
241 {
242 	device_t dev = arg;
243 	struct ntb_plx_softc *sc = device_get_softc(dev);
244 	uint32_t val;
245 
246 	ntb_db_event((device_t)arg, 0);
247 
248 	if (sc->link)	/* Link Interface has no Link Error registers. */
249 		return;
250 
251 	val = NTX_READ(sc, 0xfe0);
252 	if (val == 0)
253 		return;
254 	NTX_WRITE(sc, 0xfe0, val);
255 	if (val & 1)
256 		device_printf(dev, "Correctable Error\n");
257 	if (val & 2)
258 		device_printf(dev, "Uncorrectable Error\n");
259 	if (val & 4) {
260 		/* DL_Down resets link side registers, have to reinit. */
261 		ntb_plx_init(dev);
262 		ntb_link_event(dev);
263 	}
264 	if (val & 8)
265 		device_printf(dev, "Uncorrectable Error Message Drop\n");
266 }
267 
268 static int
ntb_plx_setup_intr(device_t dev)269 ntb_plx_setup_intr(device_t dev)
270 {
271 	struct ntb_plx_softc *sc = device_get_softc(dev);
272 	int error;
273 
274 	/*
275 	 * XXX: This hardware supports MSI, but I found it unusable.
276 	 * It generates new MSI only when doorbell register goes from
277 	 * zero, but does not generate it when another bit is set or on
278 	 * partial clear.  It makes operation very racy and unreliable.
279 	 * The data book mentions some mask juggling magic to workaround
280 	 * that, but I failed to make it work.
281 	 */
282 	sc->int_rid = 0;
283 	sc->int_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
284 	    &sc->int_rid, RF_SHAREABLE|RF_ACTIVE);
285 	if (sc->int_res == NULL) {
286 		device_printf(dev, "bus_alloc_resource failed\n");
287 		return (ENOMEM);
288 	}
289 	error = bus_setup_intr(dev, sc->int_res, INTR_MPSAFE | INTR_TYPE_MISC,
290 	    NULL, ntb_plx_isr, dev, &sc->int_tag);
291 	if (error != 0) {
292 		device_printf(dev, "bus_setup_intr failed: %d\n", error);
293 		return (error);
294 	}
295 
296 	if (!sc->link) { /* Link Interface has no Link Error registers. */
297 		NTX_WRITE(sc, 0xfe0, 0xf);	/* Clear link interrupts. */
298 		NTX_WRITE(sc, 0xfe4, 0x0);	/* Unmask link interrupts. */
299 	}
300 	return (0);
301 }
302 
303 static void
ntb_plx_teardown_intr(device_t dev)304 ntb_plx_teardown_intr(device_t dev)
305 {
306 	struct ntb_plx_softc *sc = device_get_softc(dev);
307 
308 	if (!sc->link)	/* Link Interface has no Link Error registers. */
309 		NTX_WRITE(sc, 0xfe4, 0xf);	/* Mask link interrupts. */
310 
311 	if (sc->int_res) {
312 		bus_teardown_intr(dev, sc->int_res, sc->int_tag);
313 		bus_release_resource(dev, SYS_RES_IRQ, sc->int_rid,
314 		    sc->int_res);
315 	}
316 }
317 
318 static int
ntb_plx_attach(device_t dev)319 ntb_plx_attach(device_t dev)
320 {
321 	struct ntb_plx_softc *sc = device_get_softc(dev);
322 	struct ntb_plx_mw_info *mw;
323 	int error = 0, i, j;
324 	uint32_t val;
325 	char buf[32];
326 
327 	/* Identify what we are (what side of what NTx). */
328 	sc->dev = dev;
329 	val = pci_read_config(dev, 0xc8c, 4);
330 	sc->ntx = (val & 1) != 0;
331 	sc->link = (val & 0x80000000) != 0;
332 
333 	/* Get access to whole 256KB of chip configuration space via BAR0/1. */
334 	sc->conf_rid = PCIR_BAR(0);
335 	sc->conf_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
336 	    &sc->conf_rid, RF_ACTIVE);
337 	if (sc->conf_res == NULL) {
338 		device_printf(dev, "Can't allocate configuration BAR.\n");
339 		return (ENXIO);
340 	}
341 
342 	/*
343 	 * The device occupies whole bus.  In translated TLP slot field
344 	 * keeps LUT index (original bus/slot), function is passed through.
345 	 */
346 	bus_dma_iommu_set_buswide(dev);
347 
348 	/* Identify chip port we are connected to. */
349 	val = bus_read_4(sc->conf_res, 0x360);
350 	sc->port = (val >> ((sc->ntx == 0) ? 8 : 16)) & 0x1f;
351 
352 	/* Detect A-LUT enable and size. */
353 	val >>= 30;
354 	sc->alut = (val == 0x3) ? 1 : ((val & (1 << sc->ntx)) ? 2 : 0);
355 	if (sc->alut)
356 		device_printf(dev, "%u A-LUT entries\n", 128 * sc->alut);
357 
358 	/* Find configured memory windows at BAR2-5. */
359 	sc->mw_count = 0;
360 	for (i = 2; i <= 5; i++) {
361 		mw = &sc->mw_info[sc->mw_count];
362 		mw->mw_bar = i;
363 		mw->mw_rid = PCIR_BAR(mw->mw_bar);
364 		mw->mw_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
365 		    &mw->mw_rid, RF_ACTIVE);
366 		if (mw->mw_res == NULL)
367 			continue;
368 		mw->mw_pbase = rman_get_start(mw->mw_res);
369 		mw->mw_size = rman_get_size(mw->mw_res);
370 		mw->mw_vbase = rman_get_virtual(mw->mw_res);
371 		for (j = 0; j < PLX_MAX_SPLIT; j++)
372 			mw->splits[j].mw_map_mode = VM_MEMATTR_UNCACHEABLE;
373 		sc->mw_count++;
374 
375 		/* Skip over adjacent BAR for 64-bit BARs. */
376 		val = pci_read_config(dev, PCIR_BAR(mw->mw_bar), 4);
377 		if ((val & PCIM_BAR_MEM_TYPE) == PCIM_BAR_MEM_64) {
378 			mw->mw_64bit = 1;
379 			i++;
380 		}
381 	}
382 
383 	/* Try to identify B2B mode. */
384 	i = 1;
385 	snprintf(buf, sizeof(buf), "hint.%s.%d.b2b", device_get_name(dev),
386 	    device_get_unit(dev));
387 	TUNABLE_INT_FETCH(buf, &i);
388 	if (sc->link) {
389 		device_printf(dev, "NTB-to-Root Port mode (Link Interface)\n");
390 		sc->b2b_mw = -1;
391 	} else if (i == 0) {
392 		device_printf(dev, "NTB-to-Root Port mode (Virtual Interface)\n");
393 		sc->b2b_mw = -1;
394 	} else {
395 		device_printf(dev, "NTB-to-NTB (back-to-back) mode\n");
396 
397 		/* We need at least one memory window for B2B peer access. */
398 		if (sc->mw_count == 0) {
399 			device_printf(dev, "No memory window BARs enabled.\n");
400 			error = ENXIO;
401 			goto out;
402 		}
403 		sc->b2b_mw = sc->mw_count - 1;
404 
405 		/* Use half of the window for B2B, but no less then 1MB. */
406 		mw = &sc->mw_info[sc->b2b_mw];
407 		if (mw->mw_size >= 2 * 1024 * 1024)
408 			sc->b2b_off = mw->mw_size / 2;
409 		else
410 			sc->b2b_off = 0;
411 	}
412 
413 	snprintf(buf, sizeof(buf), "hint.%s.%d.split", device_get_name(dev),
414 	    device_get_unit(dev));
415 	TUNABLE_INT_FETCH(buf, &sc->split);
416 	if (sc->split > 7) {
417 		device_printf(dev, "Split value is too high (%u)\n", sc->split);
418 		sc->split = 0;
419 	} else if (sc->split > 0 && sc->alut == 0) {
420 		device_printf(dev, "Can't split with disabled A-LUT\n");
421 		sc->split = 0;
422 	} else if (sc->split > 0 && (sc->mw_count == 0 || sc->mw_info[0].mw_bar != 2)) {
423 		device_printf(dev, "Can't split disabled BAR2\n");
424 		sc->split = 0;
425 	} else if (sc->split > 0 && (sc->b2b_mw == 0 && sc->b2b_off == 0)) {
426 		device_printf(dev, "Can't split BAR2 consumed by B2B\n");
427 		sc->split = 0;
428 	} else if (sc->split > 0) {
429 		device_printf(dev, "Splitting BAR2 into %d memory windows\n",
430 		    1 << sc->split);
431 	}
432 
433 	/*
434 	 * Use Physical Layer User Test Pattern as additional scratchpad.
435 	 * Make sure they are present and enabled by writing to them.
436 	 * XXX: Its a hack, but standard 8 registers are not enough.
437 	 */
438 	sc->spad_offp1 = sc->spad_off1 = PLX_NTX_OUR_BASE(sc) + 0xc6c;
439 	sc->spad_offp2 = sc->spad_off2 = PLX_PORT_BASE(sc->ntx * 8) + 0x20c;
440 	if (sc->b2b_mw >= 0) {
441 		/* In NTB-to-NTB mode each side has own scratchpads. */
442 		sc->spad_count1 = PLX_NUM_SPAD;
443 		bus_write_4(sc->conf_res, sc->spad_off2, 0x12345678);
444 		if (bus_read_4(sc->conf_res, sc->spad_off2) == 0x12345678)
445 			sc->spad_count2 = PLX_NUM_SPAD_PATT;
446 	} else {
447 		/* Otherwise we have share scratchpads with the peer. */
448 		if (sc->link) {
449 			sc->spad_off1 += PLX_NUM_SPAD / 2 * 4;
450 			sc->spad_off2 += PLX_NUM_SPAD_PATT / 2 * 4;
451 		} else {
452 			sc->spad_offp1 += PLX_NUM_SPAD / 2 * 4;
453 			sc->spad_offp2 += PLX_NUM_SPAD_PATT / 2 * 4;
454 		}
455 		sc->spad_count1 = PLX_NUM_SPAD / 2;
456 		bus_write_4(sc->conf_res, sc->spad_off2, 0x12345678);
457 		if (bus_read_4(sc->conf_res, sc->spad_off2) == 0x12345678)
458 			sc->spad_count2 = PLX_NUM_SPAD_PATT / 2;
459 	}
460 
461 	/* Apply static part of NTB configuration. */
462 	ntb_plx_init(dev);
463 
464 	/* Allocate and setup interrupts. */
465 	error = ntb_plx_setup_intr(dev);
466 	if (error)
467 		goto out;
468 
469 	/* Attach children to this controller */
470 	error = ntb_register_device(dev);
471 
472 out:
473 	if (error != 0)
474 		ntb_plx_detach(dev);
475 	return (error);
476 }
477 
478 static int
ntb_plx_detach(device_t dev)479 ntb_plx_detach(device_t dev)
480 {
481 	struct ntb_plx_softc *sc = device_get_softc(dev);
482 	struct ntb_plx_mw_info *mw;
483 	int i;
484 
485 	/* Detach & delete all children */
486 	ntb_unregister_device(dev);
487 
488 	/* Disable and free interrupts. */
489 	ntb_plx_teardown_intr(dev);
490 
491 	/* Free memory resources. */
492 	for (i = 0; i < sc->mw_count; i++) {
493 		mw = &sc->mw_info[i];
494 		bus_release_resource(dev, SYS_RES_MEMORY, mw->mw_rid,
495 		    mw->mw_res);
496 	}
497 	bus_release_resource(dev, SYS_RES_MEMORY, sc->conf_rid, sc->conf_res);
498 	return (0);
499 }
500 
501 static int
ntb_plx_port_number(device_t dev)502 ntb_plx_port_number(device_t dev)
503 {
504 	struct ntb_plx_softc *sc = device_get_softc(dev);
505 
506 	return (sc->link ? 1 : 0);
507 }
508 
509 static int
ntb_plx_peer_port_count(device_t dev)510 ntb_plx_peer_port_count(device_t dev)
511 {
512 
513 	return (1);
514 }
515 
516 static int
ntb_plx_peer_port_number(device_t dev,int pidx)517 ntb_plx_peer_port_number(device_t dev, int pidx)
518 {
519 	struct ntb_plx_softc *sc = device_get_softc(dev);
520 
521 	if (pidx != 0)
522 		return (-EINVAL);
523 
524 	return (sc->link ? 0 : 1);
525 }
526 
527 static int
ntb_plx_peer_port_idx(device_t dev,int port)528 ntb_plx_peer_port_idx(device_t dev, int port)
529 {
530 	int peer_port;
531 
532 	peer_port = ntb_plx_peer_port_number(dev, 0);
533 	if (peer_port == -EINVAL || port != peer_port)
534 		return (-EINVAL);
535 
536 	return (0);
537 }
538 
539 static bool
ntb_plx_link_is_up(device_t dev,enum ntb_speed * speed,enum ntb_width * width)540 ntb_plx_link_is_up(device_t dev, enum ntb_speed *speed, enum ntb_width *width)
541 {
542 	uint16_t link;
543 
544 	link = pcie_read_config(dev, PCIER_LINK_STA, 2);
545 	if (speed != NULL)
546 		*speed = (link & PCIEM_LINK_STA_SPEED);
547 	if (width != NULL)
548 		*width = (link & PCIEM_LINK_STA_WIDTH) >> 4;
549 	return ((link & PCIEM_LINK_STA_WIDTH) != 0);
550 }
551 
552 static int
ntb_plx_link_enable(device_t dev,enum ntb_speed speed __unused,enum ntb_width width __unused)553 ntb_plx_link_enable(device_t dev, enum ntb_speed speed __unused,
554     enum ntb_width width __unused)
555 {
556 	struct ntb_plx_softc *sc = device_get_softc(dev);
557 	uint32_t reg, val;
558 
559 	/* The fact that we see the Link Interface means link is enabled. */
560 	if (sc->link) {
561 		ntb_link_event(dev);
562 		return (0);
563 	}
564 
565 	reg = PLX_PORT_CONTROL(sc);
566 	val = bus_read_4(sc->conf_res, reg);
567 	if ((val & (1 << (sc->port & 7))) == 0) {
568 		/* If already enabled, generate fake link event and exit. */
569 		ntb_link_event(dev);
570 		return (0);
571 	}
572 	val &= ~(1 << (sc->port & 7));
573 	bus_write_4(sc->conf_res, reg, val);
574 	return (0);
575 }
576 
577 static int
ntb_plx_link_disable(device_t dev)578 ntb_plx_link_disable(device_t dev)
579 {
580 	struct ntb_plx_softc *sc = device_get_softc(dev);
581 	uint32_t reg, val;
582 
583 	/* Link disable for Link Interface would be suicidal. */
584 	if (sc->link)
585 		return (0);
586 
587 	reg = PLX_PORT_CONTROL(sc);
588 	val = bus_read_4(sc->conf_res, reg);
589 	val |= (1 << (sc->port & 7));
590 	bus_write_4(sc->conf_res, reg, val);
591 	return (0);
592 }
593 
594 static bool
ntb_plx_link_enabled(device_t dev)595 ntb_plx_link_enabled(device_t dev)
596 {
597 	struct ntb_plx_softc *sc = device_get_softc(dev);
598 	uint32_t reg, val;
599 
600 	/* The fact that we see the Link Interface means link is enabled. */
601 	if (sc->link)
602 		return (TRUE);
603 
604 	reg = PLX_PORT_CONTROL(sc);
605 	val = bus_read_4(sc->conf_res, reg);
606 	return ((val & (1 << (sc->port & 7))) == 0);
607 }
608 
609 static uint8_t
ntb_plx_mw_count(device_t dev)610 ntb_plx_mw_count(device_t dev)
611 {
612 	struct ntb_plx_softc *sc = device_get_softc(dev);
613 	uint8_t res;
614 
615 	res = sc->mw_count;
616 	res += (1 << sc->split) - 1;
617 	if (sc->b2b_mw >= 0 && sc->b2b_off == 0)
618 		res--; /* B2B consumed whole window. */
619 	return (res);
620 }
621 
622 static unsigned
ntb_plx_user_mw_to_idx(struct ntb_plx_softc * sc,unsigned uidx,unsigned * sp)623 ntb_plx_user_mw_to_idx(struct ntb_plx_softc *sc, unsigned uidx, unsigned *sp)
624 {
625 	unsigned t;
626 
627 	t = 1 << sc->split;
628 	if (uidx < t) {
629 		*sp = uidx;
630 		return (0);
631 	}
632 	*sp = 0;
633 	return (uidx - (t - 1));
634 }
635 
636 static int
ntb_plx_mw_get_range(device_t dev,unsigned mw_idx,vm_paddr_t * base,caddr_t * vbase,size_t * size,size_t * align,size_t * align_size,bus_addr_t * plimit)637 ntb_plx_mw_get_range(device_t dev, unsigned mw_idx, vm_paddr_t *base,
638     caddr_t *vbase, size_t *size, size_t *align, size_t *align_size,
639     bus_addr_t *plimit)
640 {
641 	struct ntb_plx_softc *sc = device_get_softc(dev);
642 	struct ntb_plx_mw_info *mw;
643 	size_t off, ss;
644 	unsigned sp, split;
645 
646 	mw_idx = ntb_plx_user_mw_to_idx(sc, mw_idx, &sp);
647 	if (mw_idx >= sc->mw_count)
648 		return (EINVAL);
649 	off = 0;
650 	if (mw_idx == sc->b2b_mw) {
651 		KASSERT(sc->b2b_off != 0,
652 		    ("user shouldn't get non-shared b2b mw"));
653 		off = sc->b2b_off;
654 	}
655 	mw = &sc->mw_info[mw_idx];
656 	split = (mw->mw_bar == 2) ? sc->split : 0;
657 	ss = (mw->mw_size - off) >> split;
658 
659 	/* Local to remote memory window parameters. */
660 	if (base != NULL)
661 		*base = mw->mw_pbase + off + ss * sp;
662 	if (vbase != NULL)
663 		*vbase = mw->mw_vbase + off + ss * sp;
664 	if (size != NULL)
665 		*size = ss;
666 
667 	/*
668 	 * Remote to local memory window translation address alignment.
669 	 * Translation address has to be aligned to the BAR size, but A-LUT
670 	 * entries re-map addresses can be aligned to 1/128 or 1/256 of it.
671 	 * XXX: In B2B mode we can change BAR size (and so alignmet) live,
672 	 * but there is no way to report it here, so report safe value.
673 	 */
674 	if (align != NULL) {
675 		if (sc->alut && mw->mw_bar == 2)
676 			*align = (mw->mw_size - off) / 128 / sc->alut;
677 		else
678 			*align = mw->mw_size - off;
679 	}
680 
681 	/*
682 	 * Remote to local memory window size alignment.
683 	 * The chip has no limit registers, but A-LUT, when available, allows
684 	 * access control with granularity of 1/128 or 1/256 of the BAR size.
685 	 * XXX: In B2B case we can change BAR size live, but there is no way
686 	 * to report it, so report half of the BAR size, that should be safe.
687 	 * In non-B2B case there is no control at all, so report the BAR size.
688 	 */
689 	if (align_size != NULL) {
690 		if (sc->alut && mw->mw_bar == 2)
691 			*align_size = (mw->mw_size - off) / 128 / sc->alut;
692 		else if (sc->b2b_mw >= 0)
693 			*align_size = (mw->mw_size - off) / 2;
694 		else
695 			*align_size = mw->mw_size - off;
696 	}
697 
698 	/* Remote to local memory window translation address upper limit. */
699 	if (plimit != NULL)
700 		*plimit = mw->mw_64bit ? BUS_SPACE_MAXADDR :
701 		    BUS_SPACE_MAXADDR_32BIT;
702 	return (0);
703 }
704 
705 static int
ntb_plx_mw_set_trans_internal(device_t dev,unsigned mw_idx)706 ntb_plx_mw_set_trans_internal(device_t dev, unsigned mw_idx)
707 {
708 	struct ntb_plx_softc *sc = device_get_softc(dev);
709 	struct ntb_plx_mw_info *mw;
710 	uint64_t addr, eaddr, off, size, bsize, esize, val64;
711 	uint32_t val;
712 	unsigned i, sp, split;
713 
714 	mw = &sc->mw_info[mw_idx];
715 	off = (mw_idx == sc->b2b_mw) ? sc->b2b_off : 0;
716 	split = (mw->mw_bar == 2) ? sc->split : 0;
717 
718 	/* Get BAR size.  In case of split or B2RP we can't change it. */
719 	if (split || sc->b2b_mw < 0) {
720 		bsize = mw->mw_size - off;
721 	} else {
722 		bsize = mw->splits[0].mw_xlat_size;
723 		if (!powerof2(bsize))
724 			bsize = 1LL << flsll(bsize);
725 		if (bsize > 0 && bsize < 1024 * 1024)
726 			bsize = 1024 * 1024;
727 	}
728 
729 	/*
730 	 * While for B2B we can set any BAR size on a link side, for shared
731 	 * window we can't go above preconfigured size due to BAR address
732 	 * alignment requirements.
733 	 */
734 	if ((off & (bsize - 1)) != 0)
735 		return (EINVAL);
736 
737 	/* In B2B mode set Link Interface BAR size/address. */
738 	if (sc->b2b_mw >= 0 && mw->mw_64bit) {
739 		val64 = 0;
740 		if (bsize > 0)
741 			val64 = (~(bsize - 1) & ~0xfffff);
742 		val64 |= 0xc;
743 		PNTX_WRITE(sc, 0xe8 + (mw->mw_bar - 2) * 4, val64);
744 		PNTX_WRITE(sc, 0xe8 + (mw->mw_bar - 2) * 4 + 4, val64 >> 32);
745 
746 		val64 = 0x2000000000000000 * mw->mw_bar + off;
747 		PNTX_WRITE(sc, PCIR_BAR(mw->mw_bar), val64);
748 		PNTX_WRITE(sc, PCIR_BAR(mw->mw_bar) + 4, val64 >> 32);
749 	} else if (sc->b2b_mw >= 0) {
750 		val = 0;
751 		if (bsize > 0)
752 			val = (~(bsize - 1) & ~0xfffff);
753 		PNTX_WRITE(sc, 0xe8 + (mw->mw_bar - 2) * 4, val);
754 
755 		val64 = 0x20000000 * mw->mw_bar + off;
756 		PNTX_WRITE(sc, PCIR_BAR(mw->mw_bar), val64);
757 	}
758 
759 	/* Set BARs address translation */
760 	addr = split ? UINT64_MAX : mw->splits[0].mw_xlat_addr;
761 	if (mw->mw_64bit) {
762 		PNTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4, addr);
763 		PNTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4 + 4, addr >> 32);
764 	} else {
765 		PNTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4, addr);
766 	}
767 
768 	/* Configure and enable A-LUT if we need it. */
769 	size = split ? 0 : mw->splits[0].mw_xlat_size;
770 	if (sc->alut && mw->mw_bar == 2 && (sc->split > 0 ||
771 	    ((addr & (bsize - 1)) != 0 || size != bsize))) {
772 		esize = bsize / (128 * sc->alut);
773 		for (i = sp = 0; i < 128 * sc->alut; i++) {
774 			if (i % (128 * sc->alut >> sc->split) == 0) {
775 				eaddr = addr = mw->splits[sp].mw_xlat_addr;
776 				size = mw->splits[sp++].mw_xlat_size;
777 			}
778 			val = sc->link ? 0 : 1;
779 			if (sc->alut == 1)
780 				val += 2 * sc->ntx;
781 			val *= 0x1000 * sc->alut;
782 			val += 0x38000 + i * 4 + (i >= 128 ? 0x0e00 : 0);
783 			bus_write_4(sc->conf_res, val, eaddr);
784 			bus_write_4(sc->conf_res, val + 0x400, eaddr >> 32);
785 			bus_write_4(sc->conf_res, val + 0x800,
786 			    (eaddr < addr + size) ? 0x3 : 0);
787 			eaddr += esize;
788 		}
789 		NTX_WRITE(sc, 0xc94, 0x10000000);
790 	} else if (sc->alut && mw->mw_bar == 2)
791 		NTX_WRITE(sc, 0xc94, 0);
792 
793 	return (0);
794 }
795 
796 static int
ntb_plx_mw_set_trans(device_t dev,unsigned mw_idx,bus_addr_t addr,size_t size)797 ntb_plx_mw_set_trans(device_t dev, unsigned mw_idx, bus_addr_t addr, size_t size)
798 {
799 	struct ntb_plx_softc *sc = device_get_softc(dev);
800 	struct ntb_plx_mw_info *mw;
801 	unsigned sp;
802 
803 	mw_idx = ntb_plx_user_mw_to_idx(sc, mw_idx, &sp);
804 	if (mw_idx >= sc->mw_count)
805 		return (EINVAL);
806 	mw = &sc->mw_info[mw_idx];
807 	if (!mw->mw_64bit &&
808 	    ((addr & UINT32_MAX) != addr ||
809 	     ((addr + size) & UINT32_MAX) != (addr + size)))
810 		return (ERANGE);
811 	mw->splits[sp].mw_xlat_addr = addr;
812 	mw->splits[sp].mw_xlat_size = size;
813 	return (ntb_plx_mw_set_trans_internal(dev, mw_idx));
814 }
815 
816 static int
ntb_plx_mw_clear_trans(device_t dev,unsigned mw_idx)817 ntb_plx_mw_clear_trans(device_t dev, unsigned mw_idx)
818 {
819 
820 	return (ntb_plx_mw_set_trans(dev, mw_idx, 0, 0));
821 }
822 
823 static int
ntb_plx_mw_get_wc(device_t dev,unsigned mw_idx,vm_memattr_t * mode)824 ntb_plx_mw_get_wc(device_t dev, unsigned mw_idx, vm_memattr_t *mode)
825 {
826 	struct ntb_plx_softc *sc = device_get_softc(dev);
827 	struct ntb_plx_mw_info *mw;
828 	unsigned sp;
829 
830 	mw_idx = ntb_plx_user_mw_to_idx(sc, mw_idx, &sp);
831 	if (mw_idx >= sc->mw_count)
832 		return (EINVAL);
833 	mw = &sc->mw_info[mw_idx];
834 	*mode = mw->splits[sp].mw_map_mode;
835 	return (0);
836 }
837 
838 static int
ntb_plx_mw_set_wc(device_t dev,unsigned mw_idx,vm_memattr_t mode)839 ntb_plx_mw_set_wc(device_t dev, unsigned mw_idx, vm_memattr_t mode)
840 {
841 	struct ntb_plx_softc *sc = device_get_softc(dev);
842 	struct ntb_plx_mw_info *mw;
843 	uint64_t off, ss;
844 	int rc;
845 	unsigned sp, split;
846 
847 	mw_idx = ntb_plx_user_mw_to_idx(sc, mw_idx, &sp);
848 	if (mw_idx >= sc->mw_count)
849 		return (EINVAL);
850 	mw = &sc->mw_info[mw_idx];
851 	if (mw->splits[sp].mw_map_mode == mode)
852 		return (0);
853 
854 	off = 0;
855 	if (mw_idx == sc->b2b_mw) {
856 		KASSERT(sc->b2b_off != 0,
857 		    ("user shouldn't get non-shared b2b mw"));
858 		off = sc->b2b_off;
859 	}
860 
861 	split = (mw->mw_bar == 2) ? sc->split : 0;
862 	ss = (mw->mw_size - off) >> split;
863 	rc = pmap_change_attr((vm_offset_t)mw->mw_vbase + off + ss * sp,
864 	    ss, mode);
865 	if (rc == 0)
866 		mw->splits[sp].mw_map_mode = mode;
867 	return (rc);
868 }
869 
870 static uint8_t
ntb_plx_spad_count(device_t dev)871 ntb_plx_spad_count(device_t dev)
872 {
873 	struct ntb_plx_softc *sc = device_get_softc(dev);
874 
875 	return (sc->spad_count1 + sc->spad_count2);
876 }
877 
878 static int
ntb_plx_spad_write(device_t dev,unsigned int idx,uint32_t val)879 ntb_plx_spad_write(device_t dev, unsigned int idx, uint32_t val)
880 {
881 	struct ntb_plx_softc *sc = device_get_softc(dev);
882 	u_int off, t;
883 
884 	if (idx >= sc->spad_count1 + sc->spad_count2)
885 		return (EINVAL);
886 
887 	if (idx < sc->spad_count1) {
888 		off = sc->spad_off1 + idx * 4;
889 		bus_write_4(sc->conf_res, off, val);
890 		return (0);
891 	} else {
892 		off = sc->spad_off2 + (idx - sc->spad_count1) * 4;
893 		/*
894 		 * For some reason when link goes down Test Pattern registers
895 		 * we use as additional scratchpad become read-only for about
896 		 * 100us.  I see no explanation in specs, so just wait a bit.
897 		 */
898 		for (t = 0; t <= 1000; t++) {
899 			bus_write_4(sc->conf_res, off, val);
900 			if (bus_read_4(sc->conf_res, off) == val)
901 				return (0);
902 			DELAY(1);
903 		}
904 		device_printf(dev,
905 		    "Can't write Physical Layer User Test Pattern (0x%x)\n",
906 		    off);
907 		return (EIO);
908 	}
909 }
910 
911 static void
ntb_plx_spad_clear(device_t dev)912 ntb_plx_spad_clear(device_t dev)
913 {
914 	struct ntb_plx_softc *sc = device_get_softc(dev);
915 	int i;
916 
917 	for (i = 0; i < sc->spad_count1 + sc->spad_count2; i++)
918 		ntb_plx_spad_write(dev, i, 0);
919 }
920 
921 static int
ntb_plx_spad_read(device_t dev,unsigned int idx,uint32_t * val)922 ntb_plx_spad_read(device_t dev, unsigned int idx, uint32_t *val)
923 {
924 	struct ntb_plx_softc *sc = device_get_softc(dev);
925 	u_int off;
926 
927 	if (idx >= sc->spad_count1 + sc->spad_count2)
928 		return (EINVAL);
929 
930 	if (idx < sc->spad_count1)
931 		off = sc->spad_off1 + idx * 4;
932 	else
933 		off = sc->spad_off2 + (idx - sc->spad_count1) * 4;
934 	*val = bus_read_4(sc->conf_res, off);
935 	return (0);
936 }
937 
938 static int
ntb_plx_peer_spad_write(device_t dev,unsigned int idx,uint32_t val)939 ntb_plx_peer_spad_write(device_t dev, unsigned int idx, uint32_t val)
940 {
941 	struct ntb_plx_softc *sc = device_get_softc(dev);
942 	u_int off;
943 
944 	if (idx >= sc->spad_count1 + sc->spad_count2)
945 		return (EINVAL);
946 
947 	if (idx < sc->spad_count1)
948 		off = sc->spad_offp1 + idx * 4;
949 	else
950 		off = sc->spad_offp2 + (idx - sc->spad_count1) * 4;
951 	if (sc->b2b_mw >= 0)
952 		bus_write_4(sc->mw_info[sc->b2b_mw].mw_res, off, val);
953 	else
954 		bus_write_4(sc->conf_res, off, val);
955 	return (0);
956 }
957 
958 static int
ntb_plx_peer_spad_read(device_t dev,unsigned int idx,uint32_t * val)959 ntb_plx_peer_spad_read(device_t dev, unsigned int idx, uint32_t *val)
960 {
961 	struct ntb_plx_softc *sc = device_get_softc(dev);
962 	u_int off;
963 
964 	if (idx >= sc->spad_count1 + sc->spad_count2)
965 		return (EINVAL);
966 
967 	if (idx < sc->spad_count1)
968 		off = sc->spad_offp1 + idx * 4;
969 	else
970 		off = sc->spad_offp2 + (idx - sc->spad_count1) * 4;
971 	if (sc->b2b_mw >= 0)
972 		*val = bus_read_4(sc->mw_info[sc->b2b_mw].mw_res, off);
973 	else
974 		*val = bus_read_4(sc->conf_res, off);
975 	return (0);
976 }
977 
978 static uint64_t
ntb_plx_db_valid_mask(device_t dev)979 ntb_plx_db_valid_mask(device_t dev)
980 {
981 
982 	return ((1LL << PLX_NUM_DB) - 1);
983 }
984 
985 static int
ntb_plx_db_vector_count(device_t dev)986 ntb_plx_db_vector_count(device_t dev)
987 {
988 
989 	return (1);
990 }
991 
992 static uint64_t
ntb_plx_db_vector_mask(device_t dev,uint32_t vector)993 ntb_plx_db_vector_mask(device_t dev, uint32_t vector)
994 {
995 
996 	if (vector > 0)
997 		return (0);
998 	return ((1LL << PLX_NUM_DB) - 1);
999 }
1000 
1001 static void
ntb_plx_db_clear(device_t dev,uint64_t bits)1002 ntb_plx_db_clear(device_t dev, uint64_t bits)
1003 {
1004 	struct ntb_plx_softc *sc = device_get_softc(dev);
1005 
1006 	NTX_WRITE(sc, sc->link ? 0xc60 : 0xc50, bits);
1007 }
1008 
1009 static void
ntb_plx_db_clear_mask(device_t dev,uint64_t bits)1010 ntb_plx_db_clear_mask(device_t dev, uint64_t bits)
1011 {
1012 	struct ntb_plx_softc *sc = device_get_softc(dev);
1013 
1014 	NTX_WRITE(sc, sc->link ? 0xc68 : 0xc58, bits);
1015 }
1016 
1017 static uint64_t
ntb_plx_db_read(device_t dev)1018 ntb_plx_db_read(device_t dev)
1019 {
1020 	struct ntb_plx_softc *sc = device_get_softc(dev);
1021 
1022 	return (NTX_READ(sc, sc->link ? 0xc5c : 0xc4c));
1023 }
1024 
1025 static void
ntb_plx_db_set_mask(device_t dev,uint64_t bits)1026 ntb_plx_db_set_mask(device_t dev, uint64_t bits)
1027 {
1028 	struct ntb_plx_softc *sc = device_get_softc(dev);
1029 
1030 	NTX_WRITE(sc, sc->link ? 0xc64 : 0xc54, bits);
1031 }
1032 
1033 static int
ntb_plx_peer_db_addr(device_t dev,bus_addr_t * db_addr,vm_size_t * db_size)1034 ntb_plx_peer_db_addr(device_t dev, bus_addr_t *db_addr, vm_size_t *db_size)
1035 {
1036 	struct ntb_plx_softc *sc = device_get_softc(dev);
1037 	struct ntb_plx_mw_info *mw;
1038 
1039 	KASSERT((db_addr != NULL && db_size != NULL), ("must be non-NULL"));
1040 
1041 	if (sc->b2b_mw >= 0) {
1042 		mw = &sc->mw_info[sc->b2b_mw];
1043 		*db_addr = (uint64_t)mw->mw_pbase + PLX_NTX_BASE(sc) + 0xc4c;
1044 	} else {
1045 		*db_addr = rman_get_start(sc->conf_res) + PLX_NTX_BASE(sc);
1046 		*db_addr += sc->link ? 0xc4c : 0xc5c;
1047 	}
1048 	*db_size = 4;
1049 	return (0);
1050 }
1051 
1052 static void
ntb_plx_peer_db_set(device_t dev,uint64_t bit)1053 ntb_plx_peer_db_set(device_t dev, uint64_t bit)
1054 {
1055 	struct ntb_plx_softc *sc = device_get_softc(dev);
1056 
1057 	if (sc->b2b_mw >= 0)
1058 		BNTX_WRITE(sc, 0xc4c, bit);
1059 	else
1060 		NTX_WRITE(sc, sc->link ? 0xc4c : 0xc5c, bit);
1061 }
1062 
1063 static device_method_t ntb_plx_methods[] = {
1064 	/* Device interface */
1065 	DEVMETHOD(device_probe,		ntb_plx_probe),
1066 	DEVMETHOD(device_attach,	ntb_plx_attach),
1067 	DEVMETHOD(device_detach,	ntb_plx_detach),
1068 	/* Bus interface */
1069 	DEVMETHOD(bus_child_location,	ntb_child_location),
1070 	DEVMETHOD(bus_print_child,	ntb_print_child),
1071 	DEVMETHOD(bus_get_dma_tag,	ntb_get_dma_tag),
1072 	/* NTB interface */
1073 	DEVMETHOD(ntb_port_number,	ntb_plx_port_number),
1074 	DEVMETHOD(ntb_peer_port_count,	ntb_plx_peer_port_count),
1075 	DEVMETHOD(ntb_peer_port_number,	ntb_plx_peer_port_number),
1076 	DEVMETHOD(ntb_peer_port_idx, 	ntb_plx_peer_port_idx),
1077 	DEVMETHOD(ntb_link_is_up,	ntb_plx_link_is_up),
1078 	DEVMETHOD(ntb_link_enable,	ntb_plx_link_enable),
1079 	DEVMETHOD(ntb_link_disable,	ntb_plx_link_disable),
1080 	DEVMETHOD(ntb_link_enabled,	ntb_plx_link_enabled),
1081 	DEVMETHOD(ntb_mw_count,		ntb_plx_mw_count),
1082 	DEVMETHOD(ntb_mw_get_range,	ntb_plx_mw_get_range),
1083 	DEVMETHOD(ntb_mw_set_trans,	ntb_plx_mw_set_trans),
1084 	DEVMETHOD(ntb_mw_clear_trans,	ntb_plx_mw_clear_trans),
1085 	DEVMETHOD(ntb_mw_get_wc,	ntb_plx_mw_get_wc),
1086 	DEVMETHOD(ntb_mw_set_wc,	ntb_plx_mw_set_wc),
1087 	DEVMETHOD(ntb_spad_count,	ntb_plx_spad_count),
1088 	DEVMETHOD(ntb_spad_clear,	ntb_plx_spad_clear),
1089 	DEVMETHOD(ntb_spad_write,	ntb_plx_spad_write),
1090 	DEVMETHOD(ntb_spad_read,	ntb_plx_spad_read),
1091 	DEVMETHOD(ntb_peer_spad_write,	ntb_plx_peer_spad_write),
1092 	DEVMETHOD(ntb_peer_spad_read,	ntb_plx_peer_spad_read),
1093 	DEVMETHOD(ntb_db_valid_mask,	ntb_plx_db_valid_mask),
1094 	DEVMETHOD(ntb_db_vector_count,	ntb_plx_db_vector_count),
1095 	DEVMETHOD(ntb_db_vector_mask,	ntb_plx_db_vector_mask),
1096 	DEVMETHOD(ntb_db_clear,		ntb_plx_db_clear),
1097 	DEVMETHOD(ntb_db_clear_mask,	ntb_plx_db_clear_mask),
1098 	DEVMETHOD(ntb_db_read,		ntb_plx_db_read),
1099 	DEVMETHOD(ntb_db_set_mask,	ntb_plx_db_set_mask),
1100 	DEVMETHOD(ntb_peer_db_addr,	ntb_plx_peer_db_addr),
1101 	DEVMETHOD(ntb_peer_db_set,	ntb_plx_peer_db_set),
1102 	DEVMETHOD_END
1103 };
1104 
1105 static DEFINE_CLASS_0(ntb_hw, ntb_plx_driver, ntb_plx_methods,
1106     sizeof(struct ntb_plx_softc));
1107 DRIVER_MODULE(ntb_hw_plx, pci, ntb_plx_driver, NULL, NULL);
1108 MODULE_DEPEND(ntb_hw_plx, ntb, 1, 1, 1);
1109 MODULE_VERSION(ntb_hw_plx, 1);
1110