ntb_hw_intel.c revision 255276
1/*-
2 * Copyright (C) 2013 Intel Corporation
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#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/dev/ntb/ntb_hw/ntb_hw.c 255276 2013-09-05 23:04:36Z carl $");
29
30#include <sys/param.h>
31#include <sys/kernel.h>
32#include <sys/systm.h>
33#include <sys/bus.h>
34#include <sys/malloc.h>
35#include <sys/module.h>
36#include <sys/queue.h>
37#include <sys/rman.h>
38#include <vm/vm.h>
39#include <vm/pmap.h>
40#include <machine/bus.h>
41#include <machine/pmap.h>
42#include <machine/resource.h>
43#include <dev/pci/pcireg.h>
44#include <dev/pci/pcivar.h>
45
46#include "ntb_regs.h"
47#include "ntb_hw.h"
48
49/*
50 * The Non-Transparent Bridge (NTB) is a device on some Intel processors that
51 * allows you to connect two systems using a PCI-e link.
52 *
53 * This module contains the hardware abstraction layer for the NTB. It allows
54 * you to send and recieve interrupts, map the memory windows and send and
55 * receive messages in the scratch-pad registers.
56 *
57 * NOTE: Much of the code in this module is shared with Linux. Any patches may
58 * be picked up and redistributed in Linux with a dual GPL/BSD license.
59 */
60
61#define NTB_CONFIG_BAR	0
62#define NTB_B2B_BAR_1	1
63#define NTB_B2B_BAR_2	2
64#define NTB_MAX_BARS	3
65#define NTB_MW_TO_BAR(mw) ((mw) + 1)
66
67#define MAX_MSIX_INTERRUPTS MAX(XEON_MAX_DB_BITS, SOC_MAX_DB_BITS)
68
69#define NTB_HB_TIMEOUT	1 /* second */
70#define SOC_LINK_RECOVERY_TIME	500
71
72#define DEVICE2SOFTC(dev) ((struct ntb_softc *) device_get_softc(dev))
73
74enum ntb_device_type {
75	NTB_XEON,
76	NTB_SOC
77};
78
79/* Device features and workarounds */
80#define HAS_FEATURE(feature)	\
81	((ntb->features & (feature)) != 0)
82
83#define NTB_BAR_SIZE_4K		(1 << 0)
84#define NTB_REGS_THRU_MW	(1 << 1)
85
86struct ntb_hw_info {
87	uint32_t		device_id;
88	const char		*desc;
89	enum ntb_device_type	type;
90	uint64_t		features;
91};
92
93struct ntb_pci_bar_info {
94	bus_space_tag_t		pci_bus_tag;
95	bus_space_handle_t	pci_bus_handle;
96	int			pci_resource_id;
97	struct resource		*pci_resource;
98	vm_paddr_t		pbase;
99	void			*vbase;
100	u_long			size;
101};
102
103struct ntb_int_info {
104	struct resource	*res;
105	int		rid;
106	void		*tag;
107};
108
109struct ntb_db_cb {
110	ntb_db_callback		callback;
111	unsigned int		db_num;
112	void			*data;
113	struct ntb_softc	*ntb;
114};
115
116struct ntb_softc {
117	device_t		device;
118	enum ntb_device_type	type;
119	uint64_t		features;
120
121	struct ntb_pci_bar_info	bar_info[NTB_MAX_BARS];
122	struct ntb_int_info	int_info[MAX_MSIX_INTERRUPTS];
123	uint32_t		allocated_interrupts;
124
125	struct callout		heartbeat_timer;
126	struct callout		lr_timer;
127
128	void			*ntb_transport;
129	ntb_event_callback	event_cb;
130	struct ntb_db_cb 	*db_cb;
131
132	struct {
133		uint32_t max_spads;
134		uint32_t max_db_bits;
135		uint32_t msix_cnt;
136	} limits;
137	struct {
138		uint32_t pdb;
139		uint32_t pdb_mask;
140		uint32_t sdb;
141		uint32_t sbar2_xlat;
142		uint32_t sbar4_xlat;
143		uint32_t spad_remote;
144		uint32_t spad_local;
145		uint32_t lnk_cntl;
146		uint32_t lnk_stat;
147		uint32_t spci_cmd;
148	} reg_ofs;
149	uint8_t conn_type;
150	uint8_t dev_type;
151	uint8_t bits_per_vector;
152	uint8_t link_status;
153	uint8_t link_width;
154	uint8_t link_speed;
155};
156
157#define ntb_reg_read(SIZE, offset) \
158	bus_space_read_ ## SIZE (ntb->bar_info[NTB_CONFIG_BAR].pci_bus_tag, \
159	    ntb->bar_info[NTB_CONFIG_BAR].pci_bus_handle, (offset))
160#define ntb_reg_write(SIZE, offset, val) \
161	bus_space_write_ ## SIZE (ntb->bar_info[NTB_CONFIG_BAR].pci_bus_tag, \
162	    ntb->bar_info[NTB_CONFIG_BAR].pci_bus_handle, (offset), (val))
163
164#define ntb_read_1(offset) ntb_reg_read(1, (offset))
165#define ntb_read_2(offset) ntb_reg_read(2, (offset))
166#define ntb_read_4(offset) ntb_reg_read(4, (offset))
167#define ntb_read_8(offset) ntb_reg_read(8, (offset))
168#define ntb_write_1(offset, val) ntb_reg_write(1, (offset), (val))
169#define ntb_write_2(offset, val) ntb_reg_write(2, (offset), (val))
170#define ntb_write_4(offset, val) ntb_reg_write(4, (offset), (val))
171#define ntb_write_8(offset, val) ntb_reg_write(8, (offset), (val))
172
173typedef int (*bar_map_strategy)(struct ntb_softc *ntb,
174    struct ntb_pci_bar_info *bar);
175
176static int ntb_probe(device_t device);
177static int ntb_attach(device_t device);
178static int ntb_detach(device_t device);
179static int ntb_map_pci_bars(struct ntb_softc *ntb);
180static int map_pci_bar(struct ntb_softc *ntb, bar_map_strategy strategy,
181    struct ntb_pci_bar_info *bar);
182static int map_mmr_bar(struct ntb_softc *ntb, struct ntb_pci_bar_info *bar);
183static int map_memory_window_bar(struct ntb_softc *ntb,
184    struct ntb_pci_bar_info *bar);
185static void ntb_unmap_pci_bar(struct ntb_softc *ntb);
186static int ntb_setup_interrupts(struct ntb_softc *ntb);
187static void ntb_teardown_interrupts(struct ntb_softc *ntb);
188static void handle_soc_irq(void *arg);
189static void handle_xeon_irq(void *arg);
190static void handle_xeon_event_irq(void *arg);
191static void ntb_handle_legacy_interrupt(void *arg);
192static int ntb_create_callbacks(struct ntb_softc *ntb, int num_vectors);
193static void ntb_free_callbacks(struct ntb_softc *ntb);
194static struct ntb_hw_info *ntb_get_device_info(uint32_t device_id);
195static int ntb_initialize_hw(struct ntb_softc *ntb);
196static int ntb_setup_xeon(struct ntb_softc *ntb);
197static int ntb_setup_soc(struct ntb_softc *ntb);
198static void ntb_handle_heartbeat(void *arg);
199static void ntb_handle_link_event(struct ntb_softc *ntb, int link_state);
200static void recover_soc_link(void *arg);
201static int ntb_check_link_status(struct ntb_softc *ntb);
202static void save_bar_parameters(struct ntb_pci_bar_info *bar);
203
204static struct ntb_hw_info pci_ids[] = {
205	{ 0x3C0D8086, "Xeon E5/Core i7 Non-Transparent Bridge B2B", NTB_XEON,
206	    NTB_REGS_THRU_MW },
207	{ 0x0C4E8086, "Atom Processor S1200 NTB Primary B2B", NTB_SOC, 0 },
208	{ 0x0E0D8086, "Xeon E5 V2 Non-Transparent Bridge B2B", NTB_XEON,
209	    NTB_REGS_THRU_MW | NTB_BAR_SIZE_4K },
210	{ 0x00000000, NULL, NTB_SOC, 0 }
211};
212
213/*
214 * OS <-> Driver interface structures
215 */
216MALLOC_DEFINE(M_NTB, "ntb_hw", "ntb_hw driver memory allocations");
217
218static device_method_t ntb_pci_methods[] = {
219	/* Device interface */
220	DEVMETHOD(device_probe,     ntb_probe),
221	DEVMETHOD(device_attach,    ntb_attach),
222	DEVMETHOD(device_detach,    ntb_detach),
223	DEVMETHOD_END
224};
225
226static driver_t ntb_pci_driver = {
227	"ntb_hw",
228	ntb_pci_methods,
229	sizeof(struct ntb_softc),
230};
231
232static devclass_t ntb_devclass;
233DRIVER_MODULE(ntb_hw, pci, ntb_pci_driver, ntb_devclass, NULL, NULL);
234MODULE_VERSION(ntb_hw, 1);
235
236/*
237 * OS <-> Driver linkage functions
238 */
239static int
240ntb_probe(device_t device)
241{
242	struct ntb_hw_info *p = ntb_get_device_info(pci_get_devid(device));
243
244	if (p != NULL) {
245		device_set_desc(device, p->desc);
246		return (0);
247	} else
248		return (ENXIO);
249}
250
251#define DETACH_ON_ERROR(func)           \
252	error = func;		        \
253	if (error < 0) {		\
254		ntb_detach(device);	\
255		return (error);		\
256	}
257
258static int
259ntb_attach(device_t device)
260{
261	struct ntb_softc *ntb = DEVICE2SOFTC(device);
262	struct ntb_hw_info *p = ntb_get_device_info(pci_get_devid(device));
263	int error;
264
265	ntb->device = device;
266	ntb->type = p->type;
267	ntb->features = p->features;
268
269	/* Heartbeat timer for NTB_SOC since there is no link interrupt */
270	callout_init(&ntb->heartbeat_timer, CALLOUT_MPSAFE);
271	callout_init(&ntb->lr_timer, CALLOUT_MPSAFE);
272
273	DETACH_ON_ERROR(ntb_map_pci_bars(ntb));
274	DETACH_ON_ERROR(ntb_initialize_hw(ntb));
275	DETACH_ON_ERROR(ntb_setup_interrupts(ntb));
276
277	pci_enable_busmaster(ntb->device);
278
279	return (error);
280}
281
282static int
283ntb_detach(device_t device)
284{
285	struct ntb_softc *ntb = DEVICE2SOFTC(device);
286
287	callout_drain(&ntb->heartbeat_timer);
288	callout_drain(&ntb->lr_timer);
289	ntb_teardown_interrupts(ntb);
290	ntb_unmap_pci_bar(ntb);
291
292	return (0);
293}
294
295static int
296ntb_map_pci_bars(struct ntb_softc *ntb)
297{
298	int rc;
299
300	ntb->bar_info[NTB_CONFIG_BAR].pci_resource_id = PCIR_BAR(0);
301	rc = map_pci_bar(ntb, map_mmr_bar, &ntb->bar_info[NTB_CONFIG_BAR]);
302	if (rc != 0)
303		return rc;
304
305	ntb->bar_info[NTB_B2B_BAR_1].pci_resource_id  = PCIR_BAR(2);
306	rc = map_pci_bar(ntb, map_memory_window_bar,
307	    &ntb->bar_info[NTB_B2B_BAR_1]);
308	if (rc != 0)
309		return rc;
310
311	ntb->bar_info[NTB_B2B_BAR_2].pci_resource_id  = PCIR_BAR(4);
312	rc = map_pci_bar(ntb, map_memory_window_bar,
313	    &ntb->bar_info[NTB_B2B_BAR_2]);
314	if (rc != 0)
315		return rc;
316
317	return (0);
318}
319
320static int
321map_pci_bar(struct ntb_softc *ntb, bar_map_strategy strategy,
322    struct ntb_pci_bar_info *bar)
323{
324	int rc;
325
326	rc = strategy(ntb, bar);
327	if (rc != 0) {
328		device_printf(ntb->device,
329		    "unable to allocate pci resource\n");
330	} else {
331		device_printf(ntb->device,
332		    "Bar size = %lx, v %p, p %p\n",
333		    bar->size, bar->vbase,
334		    (void *)(bar->pbase));
335	}
336	return (rc);
337}
338
339static int
340map_mmr_bar(struct ntb_softc *ntb, struct ntb_pci_bar_info *bar)
341{
342
343	bar->pci_resource = bus_alloc_resource_any(ntb->device, SYS_RES_MEMORY,
344		&bar->pci_resource_id, RF_ACTIVE);
345
346	if (bar->pci_resource == NULL)
347		return (ENXIO);
348	else {
349		save_bar_parameters(bar);
350		return (0);
351	}
352}
353
354static int
355map_memory_window_bar(struct ntb_softc *ntb, struct ntb_pci_bar_info *bar)
356{
357	int rc;
358	uint8_t bar_size_bits = 0;
359
360	bar->pci_resource = bus_alloc_resource_any(ntb->device,
361	    SYS_RES_MEMORY, &bar->pci_resource_id, RF_ACTIVE);
362
363	if (bar->pci_resource == NULL)
364		return (ENXIO);
365	else {
366		save_bar_parameters(bar);
367		/*
368		 * Ivytown NTB BAR sizes are misreported by the hardware due to
369		 * a hardware issue. To work around this, query the size it
370		 * should be configured to by the device and modify the resource
371		 * to correspond to this new size. The BIOS on systems with this
372		 * problem is required to provide enough address space to allow
373		 * the driver to make this change safely.
374		 *
375		 * Ideally I could have just specified the size when I allocated
376		 * the resource like:
377		 *  bus_alloc_resource(ntb->device,
378		 *	SYS_RES_MEMORY, &bar->pci_resource_id, 0ul, ~0ul,
379		 *	1ul << bar_size_bits, RF_ACTIVE);
380		 * but the PCI driver does not honor the size in this call, so
381		 * we have to modify it after the fact.
382		 */
383		if (HAS_FEATURE(BAR_SIZE_4K)) {
384			if (bar->pci_resource_id == PCIR_BAR(2))
385				bar_size_bits = pci_read_config(ntb->device,
386				    XEON_PBAR23SZ_OFFSET, 1);
387			else
388				bar_size_bits = pci_read_config(ntb->device,
389				    XEON_PBAR45SZ_OFFSET, 1);
390			rc = bus_adjust_resource(ntb->device, SYS_RES_MEMORY,
391			    bar->pci_resource, bar->pbase,
392			    bar->pbase + (1ul << bar_size_bits) - 1);
393			if (rc != 0 ) {
394				device_printf(ntb->device,
395				    "unable to resize bar\n");
396				return (rc);
397			} else
398				save_bar_parameters(bar);
399		}
400
401		/* Mark bar region as write combining to improve performance. */
402		rc = pmap_change_attr((vm_offset_t)bar->vbase, bar->size,
403		    VM_MEMATTR_WRITE_COMBINING);
404		if (rc != 0) {
405			device_printf(ntb->device, "unable to mark bar as"
406			    " WRITE_COMBINING\n");
407			return (rc);
408		}
409	}
410	return (0);
411}
412
413static void
414ntb_unmap_pci_bar(struct ntb_softc *ntb)
415{
416	struct ntb_pci_bar_info *current_bar;
417	int i;
418
419	for (i = 0; i< NTB_MAX_BARS; i++) {
420		current_bar = &ntb->bar_info[i];
421		if (current_bar->pci_resource != NULL)
422			bus_release_resource(ntb->device, SYS_RES_MEMORY,
423			    current_bar->pci_resource_id,
424			    current_bar->pci_resource);
425	}
426}
427
428static int
429ntb_setup_interrupts(struct ntb_softc *ntb)
430{
431	void (*interrupt_handler)(void *);
432	void *int_arg;
433	bool use_msix = 0;
434	uint32_t num_vectors;
435	int i;
436
437	ntb->allocated_interrupts = 0;
438	/*
439	 * On SOC, disable all interrupts.  On XEON, disable all but Link
440	 * Interrupt.  The rest will be unmasked as callbacks are registered.
441	 */
442	if (ntb->type == NTB_SOC)
443		ntb_write_8(ntb->reg_ofs.pdb_mask, ~0);
444	else
445		ntb_write_2(ntb->reg_ofs.pdb_mask,
446		    ~(1 << ntb->limits.max_db_bits));
447
448	num_vectors = MIN(pci_msix_count(ntb->device),
449	    ntb->limits.max_db_bits);
450	if (num_vectors >= 1) {
451		pci_alloc_msix(ntb->device, &num_vectors);
452		if (num_vectors >= 4)
453			use_msix = TRUE;
454	}
455
456	ntb_create_callbacks(ntb, num_vectors);
457	if (use_msix == TRUE) {
458		for (i = 0; i < num_vectors; i++) {
459			ntb->int_info[i].rid = i + 1;
460			ntb->int_info[i].res = bus_alloc_resource_any(
461			    ntb->device, SYS_RES_IRQ, &ntb->int_info[i].rid,
462			    RF_ACTIVE);
463			if (ntb->int_info[i].res == NULL) {
464				device_printf(ntb->device,
465				    "bus_alloc_resource failed\n");
466				return (-1);
467			}
468			ntb->int_info[i].tag = NULL;
469			ntb->allocated_interrupts++;
470			if (ntb->type == NTB_SOC) {
471				interrupt_handler = handle_soc_irq;
472				int_arg = &ntb->db_cb[i];
473			} else {
474				if (i == num_vectors - 1) {
475					interrupt_handler = handle_xeon_event_irq;
476					int_arg = ntb;
477				} else {
478					interrupt_handler =
479					    handle_xeon_irq;
480					int_arg = &ntb->db_cb[i];
481				}
482			}
483			if (bus_setup_intr(ntb->device, ntb->int_info[i].res,
484			    INTR_MPSAFE | INTR_TYPE_MISC, NULL,
485			    interrupt_handler, int_arg,
486			    &ntb->int_info[i].tag) != 0) {
487				device_printf(ntb->device,
488				    "bus_setup_intr failed\n");
489				return (ENXIO);
490			}
491		}
492	}
493	else {
494		ntb->int_info[0].rid = 0;
495		ntb->int_info[0].res = bus_alloc_resource_any(ntb->device, SYS_RES_IRQ,
496		    &ntb->int_info[0].rid, RF_SHAREABLE|RF_ACTIVE);
497		interrupt_handler = ntb_handle_legacy_interrupt;
498		if (ntb->int_info[0].res == NULL) {
499			device_printf(ntb->device,
500			    "bus_alloc_resource failed\n");
501			return (-1);
502		}
503		ntb->int_info[0].tag = NULL;
504		ntb->allocated_interrupts = 1;
505
506		if (bus_setup_intr(ntb->device, ntb->int_info[0].res,
507			INTR_MPSAFE | INTR_TYPE_MISC, NULL,
508			interrupt_handler, ntb, &ntb->int_info[0].tag) != 0) {
509
510			device_printf(ntb->device, "bus_setup_intr failed\n");
511			return (ENXIO);
512		}
513	}
514
515	return (0);
516}
517
518static void
519ntb_teardown_interrupts(struct ntb_softc *ntb)
520{
521	struct ntb_int_info *current_int;
522	int i;
523
524	for (i=0; i<ntb->allocated_interrupts; i++) {
525		current_int = &ntb->int_info[i];
526		if (current_int->tag != NULL)
527			bus_teardown_intr(ntb->device, current_int->res,
528			    current_int->tag);
529
530		if (current_int->res != NULL)
531			bus_release_resource(ntb->device, SYS_RES_IRQ,
532			    rman_get_rid(current_int->res), current_int->res);
533	}
534
535	ntb_free_callbacks(ntb);
536	pci_release_msi(ntb->device);
537}
538
539static void
540handle_soc_irq(void *arg)
541{
542	struct ntb_db_cb *db_cb = arg;
543	struct ntb_softc *ntb = db_cb->ntb;
544
545	ntb_write_8(ntb->reg_ofs.pdb, (uint64_t) 1 << db_cb->db_num);
546
547	if (db_cb->callback != NULL)
548		db_cb->callback(db_cb->data, db_cb->db_num);
549}
550
551static void
552handle_xeon_irq(void *arg)
553{
554	struct ntb_db_cb *db_cb = arg;
555	struct ntb_softc *ntb = db_cb->ntb;
556
557	/*
558	 * On Xeon, there are 16 bits in the interrupt register
559	 * but only 4 vectors.  So, 5 bits are assigned to the first 3
560	 * vectors, with the 4th having a single bit for link
561	 * interrupts.
562	 */
563	ntb_write_2(ntb->reg_ofs.pdb,
564	    ((1 << ntb->bits_per_vector) - 1) <<
565	    (db_cb->db_num * ntb->bits_per_vector));
566
567	if (db_cb->callback != NULL)
568		db_cb->callback(db_cb->data, db_cb->db_num);
569}
570
571/* Since we do not have a HW doorbell in SOC, this is only used in JF/JT */
572static void
573handle_xeon_event_irq(void *arg)
574{
575	struct ntb_softc *ntb = arg;
576	int rc;
577
578	rc = ntb_check_link_status(ntb);
579	if (rc != 0)
580		device_printf(ntb->device, "Error determining link status\n");
581
582	/* bit 15 is always the link bit */
583	ntb_write_2(ntb->reg_ofs.pdb, 1 << ntb->limits.max_db_bits);
584}
585
586static void
587ntb_handle_legacy_interrupt(void *arg)
588{
589	struct ntb_softc *ntb = arg;
590	unsigned int i = 0;
591	uint64_t pdb64;
592	uint16_t pdb16;
593
594	if (ntb->type == NTB_SOC) {
595		pdb64 = ntb_read_8(ntb->reg_ofs.pdb);
596
597		while (pdb64) {
598			i = ffs(pdb64);
599			pdb64 &= pdb64 - 1;
600			handle_soc_irq(&ntb->db_cb[i]);
601		}
602	} else {
603		pdb16 = ntb_read_2(ntb->reg_ofs.pdb);
604
605		if ((pdb16 & XEON_DB_HW_LINK) != 0) {
606			handle_xeon_event_irq(ntb);
607			pdb16 &= ~XEON_DB_HW_LINK;
608		}
609
610		while (pdb16 != 0) {
611			i = ffs(pdb16);
612			pdb16 &= pdb16 - 1;
613			handle_xeon_irq(&ntb->db_cb[i]);
614		}
615	}
616
617}
618
619static int
620ntb_create_callbacks(struct ntb_softc *ntb, int num_vectors)
621{
622	int i;
623
624	ntb->db_cb = malloc(num_vectors * sizeof(struct ntb_db_cb), M_NTB,
625	    M_ZERO | M_WAITOK);
626	for (i = 0; i < num_vectors; i++) {
627		ntb->db_cb[i].db_num = i;
628		ntb->db_cb[i].ntb = ntb;
629	}
630
631	return (0);
632}
633
634static void
635ntb_free_callbacks(struct ntb_softc *ntb)
636{
637	int i;
638
639	for (i = 0; i < ntb->limits.max_db_bits; i++)
640		ntb_unregister_db_callback(ntb, i);
641
642	free(ntb->db_cb, M_NTB);
643}
644
645static struct ntb_hw_info *
646ntb_get_device_info(uint32_t device_id)
647{
648	struct ntb_hw_info *ep = pci_ids;
649
650	while (ep->device_id) {
651		if (ep->device_id == device_id)
652			return (ep);
653		++ep;
654	}
655	return (NULL);
656}
657
658static int
659ntb_initialize_hw(struct ntb_softc *ntb)
660{
661
662	if (ntb->type == NTB_SOC)
663		return (ntb_setup_soc(ntb));
664	else
665		return (ntb_setup_xeon(ntb));
666}
667
668static int
669ntb_setup_xeon(struct ntb_softc *ntb)
670{
671	uint8_t val, connection_type;
672
673	val = pci_read_config(ntb->device, NTB_PPD_OFFSET, 1);
674
675	connection_type = val & XEON_PPD_CONN_TYPE;
676	switch (connection_type) {
677	case NTB_CONN_B2B:
678		ntb->conn_type = NTB_CONN_B2B;
679		break;
680	case NTB_CONN_CLASSIC:
681	case NTB_CONN_RP:
682	default:
683		device_printf(ntb->device, "Connection type %d not supported\n",
684		    connection_type);
685		return (ENXIO);
686	}
687
688	if ((val & XEON_PPD_DEV_TYPE) != 0)
689		ntb->dev_type = NTB_DEV_DSD;
690	else
691		ntb->dev_type = NTB_DEV_USD;
692
693	ntb->reg_ofs.pdb	= XEON_PDOORBELL_OFFSET;
694	ntb->reg_ofs.pdb_mask	= XEON_PDBMSK_OFFSET;
695	ntb->reg_ofs.sbar2_xlat = XEON_SBAR2XLAT_OFFSET;
696	ntb->reg_ofs.sbar4_xlat = XEON_SBAR4XLAT_OFFSET;
697	ntb->reg_ofs.lnk_cntl	= XEON_NTBCNTL_OFFSET;
698	ntb->reg_ofs.lnk_stat	= XEON_LINK_STATUS_OFFSET;
699	ntb->reg_ofs.spad_local	= XEON_SPAD_OFFSET;
700	ntb->reg_ofs.spci_cmd	= XEON_PCICMD_OFFSET;
701
702	if (ntb->conn_type == NTB_CONN_B2B) {
703		ntb->reg_ofs.sdb	 = XEON_B2B_DOORBELL_OFFSET;
704		ntb->reg_ofs.spad_remote = XEON_B2B_SPAD_OFFSET;
705		ntb->limits.max_spads	 = XEON_MAX_SPADS;
706	} else {
707		ntb->reg_ofs.sdb	 = XEON_SDOORBELL_OFFSET;
708		ntb->reg_ofs.spad_remote = XEON_SPAD_OFFSET;
709		ntb->limits.max_spads	 = XEON_MAX_COMPAT_SPADS;
710	}
711
712	ntb->limits.max_db_bits  = XEON_MAX_DB_BITS;
713	ntb->limits.msix_cnt	 = XEON_MSIX_CNT;
714	ntb->bits_per_vector	 = XEON_DB_BITS_PER_VEC;
715
716	/* Enable Bus Master and Memory Space on the secondary side */
717	ntb_write_2(ntb->reg_ofs.spci_cmd,
718	    PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
719
720	/* Enable link training */
721	ntb_write_4(ntb->reg_ofs.lnk_cntl,
722	    NTB_CNTL_BAR23_SNOOP | NTB_CNTL_BAR45_SNOOP);
723
724	return (0);
725}
726
727static int
728ntb_setup_soc(struct ntb_softc *ntb)
729{
730	uint32_t val, connection_type;
731
732	val = pci_read_config(ntb->device, NTB_PPD_OFFSET, 4);
733
734	connection_type = (val & SOC_PPD_CONN_TYPE) >> 8;
735	switch (connection_type) {
736	case NTB_CONN_B2B:
737		ntb->conn_type = NTB_CONN_B2B;
738		break;
739	case NTB_CONN_RP:
740	default:
741		device_printf(ntb->device, "Connection type %d not supported\n",
742		    connection_type);
743		return (ENXIO);
744	}
745
746	if ((val & SOC_PPD_DEV_TYPE) != 0)
747		ntb->dev_type = NTB_DEV_DSD;
748	else
749		ntb->dev_type = NTB_DEV_USD;
750
751	/* Initiate PCI-E link training */
752	pci_write_config(ntb->device, NTB_PPD_OFFSET, val | SOC_PPD_INIT_LINK,
753	    4);
754
755	ntb->reg_ofs.pdb	 = SOC_PDOORBELL_OFFSET;
756	ntb->reg_ofs.pdb_mask	 = SOC_PDBMSK_OFFSET;
757	ntb->reg_ofs.sbar2_xlat  = SOC_SBAR2XLAT_OFFSET;
758	ntb->reg_ofs.sbar4_xlat  = SOC_SBAR4XLAT_OFFSET;
759	ntb->reg_ofs.lnk_cntl	 = SOC_NTBCNTL_OFFSET;
760	ntb->reg_ofs.lnk_stat	 = SOC_LINK_STATUS_OFFSET;
761	ntb->reg_ofs.spad_local	 = SOC_SPAD_OFFSET;
762	ntb->reg_ofs.spci_cmd	 = SOC_PCICMD_OFFSET;
763
764	if (ntb->conn_type == NTB_CONN_B2B) {
765		ntb->reg_ofs.sdb	 = SOC_B2B_DOORBELL_OFFSET;
766		ntb->reg_ofs.spad_remote = SOC_B2B_SPAD_OFFSET;
767		ntb->limits.max_spads	 = SOC_MAX_SPADS;
768	} else {
769		ntb->reg_ofs.sdb	 = SOC_PDOORBELL_OFFSET;
770		ntb->reg_ofs.spad_remote = SOC_SPAD_OFFSET;
771		ntb->limits.max_spads	 = SOC_MAX_COMPAT_SPADS;
772	}
773
774	ntb->limits.max_db_bits  = SOC_MAX_DB_BITS;
775	ntb->limits.msix_cnt	 = SOC_MSIX_CNT;
776	ntb->bits_per_vector	 = SOC_DB_BITS_PER_VEC;
777
778	/*
779	 * FIXME - MSI-X bug on early SOC HW, remove once internal issue is
780	 * resolved.  Mask transaction layer internal parity errors.
781	 */
782	pci_write_config(ntb->device, 0xFC, 0x4, 4);
783
784	/*
785	 * Some BIOSes aren't filling out the XLAT offsets.
786	 * Check and correct the issue.
787	 */
788	if (ntb->dev_type == NTB_DEV_USD) {
789		if (ntb_read_8(SOC_PBAR2XLAT_OFFSET) == 0)
790			ntb_write_8(SOC_PBAR2XLAT_OFFSET,
791			    SOC_PBAR2XLAT_USD_ADDR);
792
793		if (ntb_read_8(SOC_PBAR4XLAT_OFFSET) == 0)
794			ntb_write_8(SOC_PBAR4XLAT_OFFSET,
795			    SOC_PBAR4XLAT_USD_ADDR);
796
797		if (ntb_read_8(SOC_MBAR23_OFFSET) == 0xC)
798			ntb_write_8(SOC_MBAR23_OFFSET, SOC_MBAR23_USD_ADDR);
799
800		if (ntb_read_8(SOC_MBAR45_OFFSET) == 0xC)
801			ntb_write_8(SOC_MBAR45_OFFSET, SOC_MBAR45_USD_ADDR);
802	} else {
803		if (ntb_read_8(SOC_PBAR2XLAT_OFFSET) == 0)
804			ntb_write_8(SOC_PBAR2XLAT_OFFSET,
805			    SOC_PBAR2XLAT_DSD_ADDR);
806
807		if (ntb_read_8(SOC_PBAR4XLAT_OFFSET) == 0)
808			ntb_write_8(SOC_PBAR4XLAT_OFFSET,
809			    SOC_PBAR4XLAT_DSD_ADDR);
810
811		if (ntb_read_8(SOC_MBAR23_OFFSET) == 0xC)
812			ntb_write_8(SOC_MBAR23_OFFSET, SOC_MBAR23_DSD_ADDR);
813
814		if (ntb_read_8(SOC_MBAR45_OFFSET) == 0xC)
815			ntb_write_8(SOC_MBAR45_OFFSET, SOC_MBAR45_DSD_ADDR);
816	}
817
818	/* Enable Bus Master and Memory Space on the secondary side */
819	ntb_write_2(ntb->reg_ofs.spci_cmd,
820	    PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
821	callout_reset(&ntb->heartbeat_timer, 0, ntb_handle_heartbeat, ntb);
822
823	return (0);
824}
825
826/* SOC doesn't have link status interrupt, poll on that platform */
827static void
828ntb_handle_heartbeat(void *arg)
829{
830	struct ntb_softc *ntb = arg;
831	uint32_t status32;
832	int rc = ntb_check_link_status(ntb);
833
834	if (rc != 0)
835		device_printf(ntb->device,
836		    "Error determining link status\n");
837	/* Check to see if a link error is the cause of the link down */
838	if (ntb->link_status == NTB_LINK_DOWN) {
839		status32 = ntb_read_4(SOC_LTSSMSTATEJMP_OFFSET);
840		if ((status32 & SOC_LTSSMSTATEJMP_FORCEDETECT) != 0) {
841			callout_reset(&ntb->lr_timer, 0, recover_soc_link,
842			    ntb);
843			return;
844		}
845	}
846
847	callout_reset(&ntb->heartbeat_timer, NTB_HB_TIMEOUT * hz,
848	    ntb_handle_heartbeat, ntb);
849}
850
851static void
852soc_perform_link_restart(struct ntb_softc *ntb)
853{
854	uint32_t status;
855
856	/* Driver resets the NTB ModPhy lanes - magic! */
857	ntb_write_1(SOC_MODPHY_PCSREG6, 0xe0);
858	ntb_write_1(SOC_MODPHY_PCSREG4, 0x40);
859	ntb_write_1(SOC_MODPHY_PCSREG4, 0x60);
860	ntb_write_1(SOC_MODPHY_PCSREG6, 0x60);
861
862	/* Driver waits 100ms to allow the NTB ModPhy to settle */
863	pause("ModPhy", hz / 10);
864
865	/* Clear AER Errors, write to clear */
866	status = ntb_read_4(SOC_ERRCORSTS_OFFSET);
867	status &= PCIM_AER_COR_REPLAY_ROLLOVER;
868	ntb_write_4(SOC_ERRCORSTS_OFFSET, status);
869
870	/* Clear unexpected electrical idle event in LTSSM, write to clear */
871	status = ntb_read_4(SOC_LTSSMERRSTS0_OFFSET);
872	status |= SOC_LTSSMERRSTS0_UNEXPECTEDEI;
873	ntb_write_4(SOC_LTSSMERRSTS0_OFFSET, status);
874
875	/* Clear DeSkew Buffer error, write to clear */
876	status = ntb_read_4(SOC_DESKEWSTS_OFFSET);
877	status |= SOC_DESKEWSTS_DBERR;
878	ntb_write_4(SOC_DESKEWSTS_OFFSET, status);
879
880	status = ntb_read_4(SOC_IBSTERRRCRVSTS0_OFFSET);
881	status &= SOC_IBIST_ERR_OFLOW;
882	ntb_write_4(SOC_IBSTERRRCRVSTS0_OFFSET, status);
883
884	/* Releases the NTB state machine to allow the link to retrain */
885	status = ntb_read_4(SOC_LTSSMSTATEJMP_OFFSET);
886	status &= ~SOC_LTSSMSTATEJMP_FORCEDETECT;
887	ntb_write_4(SOC_LTSSMSTATEJMP_OFFSET, status);
888}
889
890static void
891ntb_handle_link_event(struct ntb_softc *ntb, int link_state)
892{
893	enum ntb_hw_event event;
894	uint16_t status;
895
896	if (ntb->link_status == link_state)
897		return;
898
899	if (link_state == NTB_LINK_UP) {
900		device_printf(ntb->device, "Link Up\n");
901		ntb->link_status = NTB_LINK_UP;
902		event = NTB_EVENT_HW_LINK_UP;
903
904		if (ntb->type == NTB_SOC)
905			status = ntb_read_2(ntb->reg_ofs.lnk_stat);
906		else
907			status = pci_read_config(ntb->device,
908			    XEON_LINK_STATUS_OFFSET, 2);
909		ntb->link_width = (status & NTB_LINK_WIDTH_MASK) >> 4;
910		ntb->link_speed = (status & NTB_LINK_SPEED_MASK);
911		device_printf(ntb->device, "Link Width %d, Link Speed %d\n",
912		    ntb->link_width, ntb->link_speed);
913		callout_reset(&ntb->heartbeat_timer, NTB_HB_TIMEOUT * hz,
914		    ntb_handle_heartbeat, ntb);
915	} else {
916		device_printf(ntb->device, "Link Down\n");
917		ntb->link_status = NTB_LINK_DOWN;
918		event = NTB_EVENT_HW_LINK_DOWN;
919		/* Don't modify link width/speed, we need it in link recovery */
920	}
921
922	/* notify the upper layer if we have an event change */
923	if (ntb->event_cb != NULL)
924		ntb->event_cb(ntb->ntb_transport, event);
925}
926
927static void
928recover_soc_link(void *arg)
929{
930	struct ntb_softc *ntb = arg;
931	uint8_t speed, width;
932	uint32_t status32;
933	uint16_t status16;
934
935	soc_perform_link_restart(ntb);
936	pause("Link", SOC_LINK_RECOVERY_TIME * hz / 1000);
937
938	status32 = ntb_read_4(SOC_LTSSMSTATEJMP_OFFSET);
939	if ((status32 & SOC_LTSSMSTATEJMP_FORCEDETECT) != 0)
940		goto retry;
941
942	status32 = ntb_read_4(SOC_IBSTERRRCRVSTS0_OFFSET);
943	if ((status32 & SOC_IBIST_ERR_OFLOW) != 0)
944		goto retry;
945
946	status16 = ntb_read_2(ntb->reg_ofs.lnk_stat);
947	width = (status16 & NTB_LINK_WIDTH_MASK) >> 4;
948	speed = (status16 & NTB_LINK_SPEED_MASK);
949	if (ntb->link_width != width || ntb->link_speed != speed)
950		goto retry;
951
952	callout_reset(&ntb->heartbeat_timer, NTB_HB_TIMEOUT * hz,
953	    ntb_handle_heartbeat, ntb);
954	return;
955
956retry:
957	callout_reset(&ntb->lr_timer, NTB_HB_TIMEOUT * hz, recover_soc_link,
958	    ntb);
959}
960
961static int
962ntb_check_link_status(struct ntb_softc *ntb)
963{
964	int link_state;
965	uint32_t ntb_cntl;
966	uint16_t status;
967
968	if (ntb->type == NTB_SOC) {
969		ntb_cntl = ntb_read_4(ntb->reg_ofs.lnk_cntl);
970		if ((ntb_cntl & SOC_CNTL_LINK_DOWN) != 0)
971			link_state = NTB_LINK_DOWN;
972		else
973			link_state = NTB_LINK_UP;
974	} else {
975		status = pci_read_config(ntb->device, XEON_LINK_STATUS_OFFSET,
976		    2);
977
978		if ((status & NTB_LINK_STATUS_ACTIVE) != 0)
979			link_state = NTB_LINK_UP;
980		else
981			link_state = NTB_LINK_DOWN;
982	}
983
984	ntb_handle_link_event(ntb, link_state);
985
986	return (0);
987}
988
989/**
990 * ntb_register_event_callback() - register event callback
991 * @ntb: pointer to ntb_softc instance
992 * @func: callback function to register
993 *
994 * This function registers a callback for any HW driver events such as link
995 * up/down, power management notices and etc.
996 *
997 * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
998 */
999int
1000ntb_register_event_callback(struct ntb_softc *ntb, ntb_event_callback func)
1001{
1002
1003	if (ntb->event_cb != NULL)
1004		return (EINVAL);
1005
1006	ntb->event_cb = func;
1007
1008	return (0);
1009}
1010
1011/**
1012 * ntb_unregister_event_callback() - unregisters the event callback
1013 * @ntb: pointer to ntb_softc instance
1014 *
1015 * This function unregisters the existing callback from transport
1016 */
1017void
1018ntb_unregister_event_callback(struct ntb_softc *ntb)
1019{
1020
1021	ntb->event_cb = NULL;
1022}
1023
1024/**
1025 * ntb_register_db_callback() - register a callback for doorbell interrupt
1026 * @ntb: pointer to ntb_softc instance
1027 * @idx: doorbell index to register callback, zero based
1028 * @func: callback function to register
1029 *
1030 * This function registers a callback function for the doorbell interrupt
1031 * on the primary side. The function will unmask the doorbell as well to
1032 * allow interrupt.
1033 *
1034 * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
1035 */
1036int
1037ntb_register_db_callback(struct ntb_softc *ntb, unsigned int idx, void *data,
1038    ntb_db_callback func)
1039{
1040	uint16_t mask;
1041
1042	if (idx >= ntb->allocated_interrupts || ntb->db_cb[idx].callback) {
1043		device_printf(ntb->device, "Invalid Index.\n");
1044		return (EINVAL);
1045	}
1046
1047	ntb->db_cb[idx].callback = func;
1048	ntb->db_cb[idx].data = data;
1049
1050	/* unmask interrupt */
1051	mask = ntb_read_2(ntb->reg_ofs.pdb_mask);
1052	mask &= ~(1 << (idx * ntb->bits_per_vector));
1053	ntb_write_2(ntb->reg_ofs.pdb_mask, mask);
1054
1055	return (0);
1056}
1057
1058/**
1059 * ntb_unregister_db_callback() - unregister a callback for doorbell interrupt
1060 * @ntb: pointer to ntb_softc instance
1061 * @idx: doorbell index to register callback, zero based
1062 *
1063 * This function unregisters a callback function for the doorbell interrupt
1064 * on the primary side. The function will also mask the said doorbell.
1065 */
1066void
1067ntb_unregister_db_callback(struct ntb_softc *ntb, unsigned int idx)
1068{
1069	unsigned long mask;
1070
1071	if (idx >= ntb->allocated_interrupts || !ntb->db_cb[idx].callback)
1072		return;
1073
1074	mask = ntb_read_2(ntb->reg_ofs.pdb_mask);
1075	mask |= 1 << (idx * ntb->bits_per_vector);
1076	ntb_write_2(ntb->reg_ofs.pdb_mask, mask);
1077
1078	ntb->db_cb[idx].callback = NULL;
1079}
1080
1081/**
1082 * ntb_find_transport() - find the transport pointer
1083 * @transport: pointer to pci device
1084 *
1085 * Given the pci device pointer, return the transport pointer passed in when
1086 * the transport attached when it was inited.
1087 *
1088 * RETURNS: pointer to transport.
1089 */
1090void *
1091ntb_find_transport(struct ntb_softc *ntb)
1092{
1093
1094	return (ntb->ntb_transport);
1095}
1096
1097/**
1098 * ntb_register_transport() - Register NTB transport with NTB HW driver
1099 * @transport: transport identifier
1100 *
1101 * This function allows a transport to reserve the hardware driver for
1102 * NTB usage.
1103 *
1104 * RETURNS: pointer to ntb_softc, NULL on error.
1105 */
1106struct ntb_softc *
1107ntb_register_transport(struct ntb_softc *ntb, void *transport)
1108{
1109
1110	/*
1111	 * TODO: when we have more than one transport, we will need to rewrite
1112	 * this to prevent race conditions
1113	 */
1114	if (ntb->ntb_transport != NULL)
1115		return (NULL);
1116
1117	ntb->ntb_transport = transport;
1118	return (ntb);
1119}
1120
1121/**
1122 * ntb_unregister_transport() - Unregister the transport with the NTB HW driver
1123 * @ntb - ntb_softc of the transport to be freed
1124 *
1125 * This function unregisters the transport from the HW driver and performs any
1126 * necessary cleanups.
1127 */
1128void
1129ntb_unregister_transport(struct ntb_softc *ntb)
1130{
1131	int i;
1132
1133	if (ntb->ntb_transport == NULL)
1134		return;
1135
1136	for (i = 0; i < ntb->allocated_interrupts; i++)
1137		ntb_unregister_db_callback(ntb, i);
1138
1139	ntb_unregister_event_callback(ntb);
1140	ntb->ntb_transport = NULL;
1141}
1142
1143/**
1144 * ntb_get_max_spads() - get the total scratch regs usable
1145 * @ntb: pointer to ntb_softc instance
1146 *
1147 * This function returns the max 32bit scratchpad registers usable by the
1148 * upper layer.
1149 *
1150 * RETURNS: total number of scratch pad registers available
1151 */
1152int
1153ntb_get_max_spads(struct ntb_softc *ntb)
1154{
1155
1156	return (ntb->limits.max_spads);
1157}
1158
1159/**
1160 * ntb_write_local_spad() - write to the secondary scratchpad register
1161 * @ntb: pointer to ntb_softc instance
1162 * @idx: index to the scratchpad register, 0 based
1163 * @val: the data value to put into the register
1164 *
1165 * This function allows writing of a 32bit value to the indexed scratchpad
1166 * register. The register resides on the secondary (external) side.
1167 *
1168 * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
1169 */
1170int
1171ntb_write_local_spad(struct ntb_softc *ntb, unsigned int idx, uint32_t val)
1172{
1173
1174	if (idx >= ntb->limits.max_spads)
1175		return (EINVAL);
1176
1177	ntb_write_4(ntb->reg_ofs.spad_local + idx * 4, val);
1178
1179	return (0);
1180}
1181
1182/**
1183 * ntb_read_local_spad() - read from the primary scratchpad register
1184 * @ntb: pointer to ntb_softc instance
1185 * @idx: index to scratchpad register, 0 based
1186 * @val: pointer to 32bit integer for storing the register value
1187 *
1188 * This function allows reading of the 32bit scratchpad register on
1189 * the primary (internal) side.
1190 *
1191 * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
1192 */
1193int
1194ntb_read_local_spad(struct ntb_softc *ntb, unsigned int idx, uint32_t *val)
1195{
1196
1197	if (idx >= ntb->limits.max_spads)
1198		return (EINVAL);
1199
1200	*val = ntb_read_4(ntb->reg_ofs.spad_local + idx * 4);
1201
1202	return (0);
1203}
1204
1205/**
1206 * ntb_write_remote_spad() - write to the secondary scratchpad register
1207 * @ntb: pointer to ntb_softc instance
1208 * @idx: index to the scratchpad register, 0 based
1209 * @val: the data value to put into the register
1210 *
1211 * This function allows writing of a 32bit value to the indexed scratchpad
1212 * register. The register resides on the secondary (external) side.
1213 *
1214 * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
1215 */
1216int
1217ntb_write_remote_spad(struct ntb_softc *ntb, unsigned int idx, uint32_t val)
1218{
1219
1220	if (idx >= ntb->limits.max_spads)
1221		return (EINVAL);
1222
1223	ntb_write_4(ntb->reg_ofs.spad_remote + idx * 4, val);
1224
1225	return (0);
1226}
1227
1228/**
1229 * ntb_read_remote_spad() - read from the primary scratchpad register
1230 * @ntb: pointer to ntb_softc instance
1231 * @idx: index to scratchpad register, 0 based
1232 * @val: pointer to 32bit integer for storing the register value
1233 *
1234 * This function allows reading of the 32bit scratchpad register on
1235 * the primary (internal) side.
1236 *
1237 * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
1238 */
1239int
1240ntb_read_remote_spad(struct ntb_softc *ntb, unsigned int idx, uint32_t *val)
1241{
1242
1243	if (idx >= ntb->limits.max_spads)
1244		return (EINVAL);
1245
1246	*val = ntb_read_4(ntb->reg_ofs.spad_remote + idx * 4);
1247
1248	return (0);
1249}
1250
1251/**
1252 * ntb_get_mw_vbase() - get virtual addr for the NTB memory window
1253 * @ntb: pointer to ntb_softc instance
1254 * @mw: memory window number
1255 *
1256 * This function provides the base virtual address of the memory window
1257 * specified.
1258 *
1259 * RETURNS: pointer to virtual address, or NULL on error.
1260 */
1261void *
1262ntb_get_mw_vbase(struct ntb_softc *ntb, unsigned int mw)
1263{
1264
1265	if (mw >= NTB_NUM_MW)
1266		return (NULL);
1267
1268	return (ntb->bar_info[NTB_MW_TO_BAR(mw)].vbase);
1269}
1270
1271vm_paddr_t
1272ntb_get_mw_pbase(struct ntb_softc *ntb, unsigned int mw)
1273{
1274
1275	if (mw >= NTB_NUM_MW)
1276		return (0);
1277
1278	return (ntb->bar_info[NTB_MW_TO_BAR(mw)].pbase);
1279}
1280
1281/**
1282 * ntb_get_mw_size() - return size of NTB memory window
1283 * @ntb: pointer to ntb_softc instance
1284 * @mw: memory window number
1285 *
1286 * This function provides the physical size of the memory window specified
1287 *
1288 * RETURNS: the size of the memory window or zero on error
1289 */
1290u_long
1291ntb_get_mw_size(struct ntb_softc *ntb, unsigned int mw)
1292{
1293
1294	if (mw >= NTB_NUM_MW)
1295		return (0);
1296
1297	return (ntb->bar_info[NTB_MW_TO_BAR(mw)].size);
1298}
1299
1300/**
1301 * ntb_set_mw_addr - set the memory window address
1302 * @ntb: pointer to ntb_softc instance
1303 * @mw: memory window number
1304 * @addr: base address for data
1305 *
1306 * This function sets the base physical address of the memory window.  This
1307 * memory address is where data from the remote system will be transfered into
1308 * or out of depending on how the transport is configured.
1309 */
1310void
1311ntb_set_mw_addr(struct ntb_softc *ntb, unsigned int mw, uint64_t addr)
1312{
1313
1314	if (mw >= NTB_NUM_MW)
1315		return;
1316
1317	switch (NTB_MW_TO_BAR(mw)) {
1318	case NTB_B2B_BAR_1:
1319		ntb_write_8(ntb->reg_ofs.sbar2_xlat, addr);
1320		break;
1321	case NTB_B2B_BAR_2:
1322		ntb_write_8(ntb->reg_ofs.sbar4_xlat, addr);
1323		break;
1324	}
1325}
1326
1327/**
1328 * ntb_ring_sdb() - Set the doorbell on the secondary/external side
1329 * @ntb: pointer to ntb_softc instance
1330 * @db: doorbell to ring
1331 *
1332 * This function allows triggering of a doorbell on the secondary/external
1333 * side that will initiate an interrupt on the remote host
1334 *
1335 * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
1336 */
1337void
1338ntb_ring_sdb(struct ntb_softc *ntb, unsigned int db)
1339{
1340
1341	if (ntb->type == NTB_SOC)
1342		ntb_write_8(ntb->reg_ofs.sdb, (uint64_t) 1 << db);
1343	else
1344		ntb_write_2(ntb->reg_ofs.sdb,
1345		    ((1 << ntb->bits_per_vector) - 1) <<
1346		    (db * ntb->bits_per_vector));
1347}
1348
1349/**
1350 * ntb_query_link_status() - return the hardware link status
1351 * @ndev: pointer to ntb_device instance
1352 *
1353 * Returns true if the hardware is connected to the remote system
1354 *
1355 * RETURNS: true or false based on the hardware link state
1356 */
1357bool
1358ntb_query_link_status(struct ntb_softc *ntb)
1359{
1360
1361	return (ntb->link_status == NTB_LINK_UP);
1362}
1363
1364static void
1365save_bar_parameters(struct ntb_pci_bar_info *bar)
1366{
1367	bar->pci_bus_tag =
1368	    rman_get_bustag(bar->pci_resource);
1369	bar->pci_bus_handle =
1370	    rman_get_bushandle(bar->pci_resource);
1371	bar->pbase =
1372	    rman_get_start(bar->pci_resource);
1373	bar->size =
1374	    rman_get_size(bar->pci_resource);
1375	bar->vbase =
1376	    rman_get_virtual(bar->pci_resource);
1377
1378}
1379
1380device_t ntb_get_device(struct ntb_softc *ntb)
1381{
1382
1383	return (ntb->device);
1384}
1385