]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/ntb/ntb_hw/ntb_hw_plx.c
MFV r316862: 6410 teach zdb to perform object lookups by path
[FreeBSD/FreeBSD.git] / sys / dev / ntb / ntb_hw / ntb_hw_plx.c
1 /*-
2  * Copyright (c) 2017 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/cdefs.h>
35 __FBSDID("$FreeBSD$");
36
37 #include <sys/param.h>
38 #include <sys/kernel.h>
39 #include <sys/systm.h>
40 #include <sys/bus.h>
41 #include <sys/interrupt.h>
42 #include <sys/module.h>
43 #include <sys/rman.h>
44 #include <sys/sysctl.h>
45 #include <vm/vm.h>
46 #include <vm/pmap.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>
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
60 struct ntb_plx_mw_info {
61         int                      mw_bar;
62         int                      mw_64bit;
63         int                      mw_rid;
64         struct resource         *mw_res;
65         vm_paddr_t               mw_pbase;
66         caddr_t                  mw_vbase;
67         vm_size_t                mw_size;
68         vm_memattr_t             mw_map_mode;
69         bus_addr_t               mw_xlat_addr;
70         size_t                   mw_xlat_size;
71 };
72
73 struct ntb_plx_softc {
74         /* ntb.c context. Do not move! Must go first! */
75         void                    *ntb_store;
76
77         device_t                 dev;
78         struct resource         *conf_res;
79         int                      conf_rid;
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 */
84
85         int                      int_rid;
86         struct resource         *int_res;
87         void                    *int_tag;
88
89         struct ntb_plx_mw_info   mw_info[PLX_MAX_BARS];
90         int                      mw_count;      /* Number of memory windows. */
91
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. */
98
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. */
102 };
103
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
108
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))
114
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))
120
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))
126
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))
134
135 #define PLX_PORT_BASE(p)                ((p) << 12)
136 #define PLX_STATION_PORT_BASE(sc)       PLX_PORT_BASE((sc)->port & ~7)
137
138 #define PLX_PORT_CONTROL(sc)            (PLX_STATION_PORT_BASE(sc) + 0x208)
139
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);
143
144 static int
145 ntb_plx_probe(device_t dev)
146 {
147
148         switch (pci_get_devid(dev)) {
149         case 0x87a010b5:
150                 device_set_desc(dev, "PLX Non-Transparent Bridge NT0 Link");
151                 return (BUS_PROBE_DEFAULT);
152         case 0x87a110b5:
153                 device_set_desc(dev, "PLX Non-Transparent Bridge NT1 Link");
154                 return (BUS_PROBE_DEFAULT);
155         case 0x87b010b5:
156                 device_set_desc(dev, "PLX Non-Transparent Bridge NT0 Virtual");
157                 return (BUS_PROBE_DEFAULT);
158         case 0x87b110b5:
159                 device_set_desc(dev, "PLX Non-Transparent Bridge NT1 Virtual");
160                 return (BUS_PROBE_DEFAULT);
161         }
162         return (ENXIO);
163 }
164
165 static int
166 ntb_plx_init(device_t dev)
167 {
168         struct ntb_plx_softc *sc = device_get_softc(dev);
169         struct ntb_plx_mw_info *mw;
170         uint64_t val64;
171         int i;
172         uint32_t val;
173
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];
177                 if (mw->mw_64bit) {
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);
182                 } else {
183                         PNTX_WRITE(sc, 0xe4, 0x2);      /* 32-bit */
184                         val = 0x20000000 * mw->mw_bar;
185                         PNTX_WRITE(sc, PCIR_BAR(0), val);
186                 }
187
188                 /* Set Virtual to Link address translation for B2B. */
189                 for (i = 0; i < sc->mw_count; i++) {
190                         mw = &sc->mw_info[i];
191                         if (mw->mw_64bit) {
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);
195                         } else {
196                                 val = 0x20000000 * mw->mw_bar;
197                                 NTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4, val);
198                         }
199                 }
200
201                 /* Make sure Virtual to Link A-LUT is disabled. */
202                 if (sc->alut)
203                         PNTX_WRITE(sc, 0xc94, 0);
204
205                 /* Enable Link Interface LUT entries 0/1 for peer 0/1. */
206                 PNTX_WRITE(sc, 0xdb4, 0x00090001);
207         }
208
209         /*
210          * Enable Virtual Interface LUT entry 0 for 0:0.0 and
211          * entry 1 for our Requester ID reported by chip.
212          */
213         val = (NTX_READ(sc, 0xc90) << 16) | 0x00010001;
214         NTX_WRITE(sc, sc->link ? 0xdb4 : 0xd94, val);
215
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);
221         }
222
223         pci_enable_busmaster(dev);
224         if (sc->b2b_mw >= 0)
225                 PNTX_WRITE(sc, PCIR_COMMAND, PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
226
227         return (0);
228 }
229
230 static void
231 ntb_plx_isr(void *arg)
232 {
233         device_t dev = arg;
234         struct ntb_plx_softc *sc = device_get_softc(dev);
235         uint32_t val;
236
237         ntb_db_event((device_t)arg, 0);
238
239         if (sc->link)   /* Link Interface has no Link Error registers. */
240                 return;
241
242         val = NTX_READ(sc, 0xfe0);
243         if (val == 0)
244                 return;
245         NTX_WRITE(sc, 0xfe0, val);
246         if (val & 1)
247                 device_printf(dev, "Correctable Error\n");
248         if (val & 2)
249                 device_printf(dev, "Uncorrectable Error\n");
250         if (val & 4) {
251                 /* DL_Down resets link side registers, have to reinit. */
252                 ntb_plx_init(dev);
253                 ntb_link_event(dev);
254         }
255         if (val & 8)
256                 device_printf(dev, "Uncorrectable Error Message Drop\n");
257 }
258
259 static int
260 ntb_plx_setup_intr(device_t dev)
261 {
262         struct ntb_plx_softc *sc = device_get_softc(dev);
263         int error;
264
265         /*
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.
272          */
273         sc->int_rid = 0;
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");
278                 return (ENOMEM);
279         }
280         error = bus_setup_intr(dev, sc->int_res, INTR_MPSAFE | INTR_TYPE_MISC,
281             NULL, ntb_plx_isr, dev, &sc->int_tag);
282         if (error != 0) {
283                 device_printf(dev, "bus_setup_intr failed: %d\n", error);
284                 return (error);
285         }
286
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. */
290         }
291         return (0);
292 }
293
294 static void
295 ntb_plx_teardown_intr(device_t dev)
296 {
297         struct ntb_plx_softc *sc = device_get_softc(dev);
298
299         if (!sc->link)  /* Link Interface has no Link Error registers. */
300                 NTX_WRITE(sc, 0xfe4, 0xf);      /* Mask link interrupts. */
301
302         if (sc->int_res) {
303                 bus_teardown_intr(dev, sc->int_res, sc->int_tag);
304                 bus_release_resource(dev, SYS_RES_IRQ, sc->int_rid,
305                     sc->int_res);
306         }
307 }
308
309 static int
310 ntb_plx_attach(device_t dev)
311 {
312         struct ntb_plx_softc *sc = device_get_softc(dev);
313         struct ntb_plx_mw_info *mw;
314         int error = 0, i;
315         uint32_t val;
316         char buf[32];
317
318         /* Identify what we are (what side of what NTx). */
319         sc->dev = dev;
320         val = pci_read_config(dev, 0xc8c, 4);
321         sc->ntx = (val & 1) != 0;
322         sc->link = (val & 0x80000000) != 0;
323
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");
330                 return (ENXIO);
331         }
332
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;
336
337         /* Detect A-LUT enable and size. */
338         val >>= 30;
339         sc->alut = (val == 0x3) ? 1 : ((val & (1 << sc->ntx)) ? 2 : 0);
340         if (sc->alut)
341                 device_printf(dev, "%u A-LUT entries\n", 128 * sc->alut);
342
343         /* Find configured memory windows at BAR2-5. */
344         sc->mw_count = 0;
345         for (i = 2; i <= 5; i++) {
346                 mw = &sc->mw_info[sc->mw_count];
347                 mw->mw_bar = i;
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)
352                         continue;
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;
357                 sc->mw_count++;
358
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) {
362                         mw->mw_64bit = 1;
363                         i++;
364                 }
365         }
366
367         /* Try to identify B2B mode. */
368         i = 1;
369         snprintf(buf, sizeof(buf), "hint.%s.%d.b2b", device_get_name(dev),
370             device_get_unit(dev));
371         TUNABLE_INT_FETCH(buf, &i);
372         if (sc->link) {
373                 device_printf(dev, "NTB-to-Root Port mode (Link Interface)\n");
374                 sc->b2b_mw = -1;
375         } else if (i == 0) {
376                 device_printf(dev, "NTB-to-Root Port mode (Virtual Interface)\n");
377                 sc->b2b_mw = -1;
378         } else {
379                 device_printf(dev, "NTB-to-NTB (back-to-back) mode\n");
380
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");
384                         error = ENXIO;
385                         goto out;
386                 }
387                 sc->b2b_mw = sc->mw_count - 1;
388
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;
393                 else
394                         sc->b2b_off = 0;
395         }
396
397         /*
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.
401          */
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;
410         } else {
411                 /* Otherwise we have share scratchpads with the peer. */
412                 if (sc->link) {
413                         sc->spad_off1 += PLX_NUM_SPAD / 2 * 4;
414                         sc->spad_off2 += PLX_NUM_SPAD_PATT / 2 * 4;
415                 } else {
416                         sc->spad_offp1 += PLX_NUM_SPAD / 2 * 4;
417                         sc->spad_offp2 += PLX_NUM_SPAD_PATT / 2 * 4;
418                 }
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;
423         }
424
425         /* Apply static part of NTB configuration. */
426         ntb_plx_init(dev);
427
428         /* Allocate and setup interrupts. */
429         error = ntb_plx_setup_intr(dev);
430         if (error)
431                 goto out;
432
433         /* Attach children to this controller */
434         error = ntb_register_device(dev);
435
436 out:
437         if (error != 0)
438                 ntb_plx_detach(dev);
439         return (error);
440 }
441
442 static int
443 ntb_plx_detach(device_t dev)
444 {
445         struct ntb_plx_softc *sc = device_get_softc(dev);
446         struct ntb_plx_mw_info *mw;
447         int i;
448
449         /* Detach & delete all children */
450         ntb_unregister_device(dev);
451
452         /* Disable and free interrupts. */
453         ntb_plx_teardown_intr(dev);
454
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,
459                     mw->mw_res);
460         }
461         bus_release_resource(dev, SYS_RES_MEMORY, sc->conf_rid, sc->conf_res);
462         return (0);
463 }
464
465
466 static bool
467 ntb_plx_link_is_up(device_t dev, enum ntb_speed *speed, enum ntb_width *width)
468 {
469         uint16_t link;
470
471         link = pcie_read_config(dev, PCIER_LINK_STA, 2);
472         if (speed != NULL)
473                 *speed = (link & PCIEM_LINK_STA_SPEED);
474         if (width != NULL)
475                 *width = (link & PCIEM_LINK_STA_WIDTH) >> 4;
476         return ((link & PCIEM_LINK_STA_WIDTH) != 0);
477 }
478
479 static int
480 ntb_plx_link_enable(device_t dev, enum ntb_speed speed __unused,
481     enum ntb_width width __unused)
482 {
483         struct ntb_plx_softc *sc = device_get_softc(dev);
484         uint32_t reg, val;
485
486         /* The fact that we see the Link Interface means link is enabled. */
487         if (sc->link) {
488                 ntb_link_event(dev);
489                 return (0);
490         }
491
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. */
496                 ntb_link_event(dev);
497                 return (0);
498         }
499         val &= ~(1 << (sc->port & 7));
500         bus_write_4(sc->conf_res, reg, val);
501         return (0);
502 }
503
504 static int
505 ntb_plx_link_disable(device_t dev)
506 {
507         struct ntb_plx_softc *sc = device_get_softc(dev);
508         uint32_t reg, val;
509
510         /* Link disable for Link Interface would be suicidal. */
511         if (sc->link)
512                 return (0);
513
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);
518         return (0);
519 }
520
521 static bool
522 ntb_plx_link_enabled(device_t dev)
523 {
524         struct ntb_plx_softc *sc = device_get_softc(dev);
525         uint32_t reg, val;
526
527         /* The fact that we see the Link Interface means link is enabled. */
528         if (sc->link)
529                 return (TRUE);
530
531         reg = PLX_PORT_CONTROL(sc);
532         val = bus_read_4(sc->conf_res, reg);
533         return ((val & (1 << (sc->port & 7))) == 0);
534 }
535
536 static uint8_t
537 ntb_plx_mw_count(device_t dev)
538 {
539         struct ntb_plx_softc *sc = device_get_softc(dev);
540
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);
544 }
545
546 static int
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,
549     bus_addr_t *plimit)
550 {
551         struct ntb_plx_softc *sc = device_get_softc(dev);
552         struct ntb_plx_mw_info *mw;
553         size_t off;
554
555         if (mw_idx >= sc->mw_count)
556                 return (EINVAL);
557         off = 0;
558         if (mw_idx == sc->b2b_mw) {
559                 KASSERT(sc->b2b_off != 0,
560                     ("user shouldn't get non-shared b2b mw"));
561                 off = sc->b2b_off;
562         }
563         mw = &sc->mw_info[mw_idx];
564
565         /* Local to remote memory window parameters. */
566         if (base != NULL)
567                 *base = mw->mw_pbase + off;
568         if (vbase != NULL)
569                 *vbase = mw->mw_vbase + off;
570         if (size != NULL)
571                 *size = mw->mw_size - off;
572
573         /*
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.
579          */
580         if (align != NULL) {
581                 if (sc->alut && mw->mw_bar == 2)
582                         *align = (mw->mw_size - off) / 128 / sc->alut;
583                 else
584                         *align = mw->mw_size - off;
585         }
586
587         /*
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.
594          */
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;
600                 else
601                         *align_size = mw->mw_size - off;
602         }
603
604         /* Remote to local memory window translation address upper limit. */
605         if (plimit != NULL)
606                 *plimit = mw->mw_64bit ? BUS_SPACE_MAXADDR :
607                     BUS_SPACE_MAXADDR_32BIT;
608         return (0);
609 }
610
611 static int
612 ntb_plx_mw_set_trans_internal(device_t dev, unsigned mw_idx)
613 {
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;
617         uint32_t val;
618         int i;
619
620         mw = &sc->mw_info[mw_idx];
621         addr = mw->mw_xlat_addr;
622         size = mw->mw_xlat_size;
623         off = 0;
624         if (mw_idx == sc->b2b_mw) {
625                 off = sc->b2b_off;
626                 KASSERT(off != 0, ("user shouldn't get non-shared b2b mw"));
627
628                 /*
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.
632                  */
633                 if (size > mw->mw_size - off)
634                         return (EINVAL);
635         }
636
637         if (size > 0) {
638                 /* Round BAR size to next power of 2 or at least 1MB. */
639                 bsize = size;
640                 if (!powerof2(bsize))
641                         bsize = 1LL << flsll(bsize);
642                 if (bsize < 1024 * 1024)
643                         bsize = 1024 * 1024;
644
645                 /* A-LUT has 128 or 256 times better granularity. */
646                 esize = bsize;
647                 if (sc->alut && mw->mw_bar == 2)
648                         esize /= 128 * sc->alut;
649
650                 /* addr should be aligned to BAR or A-LUT element size. */
651                 if ((addr & (esize - 1)) != 0)
652                         return (EINVAL);
653         } else
654                 esize = bsize = 0;
655
656         if (mw->mw_64bit) {
657                 if (sc->b2b_mw >= 0) {
658                         /* Set Link Interface BAR size and enable/disable it. */
659                         val64 = 0;
660                         if (bsize > 0)
661                                 val64 = (~(bsize - 1) & ~0xfffff);
662                         val64 |= 0xc;
663                         PNTX_WRITE(sc, 0xe8 + (mw->mw_bar - 2) * 4, val64);
664                         PNTX_WRITE(sc, 0xe8 + (mw->mw_bar - 2) * 4 + 4, val64 >> 32);
665
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);
670                 }
671
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);
675         } else {
676                 /* Make sure we fit into 32-bit address space. */
677                 if ((addr & UINT32_MAX) != addr)
678                         return (ERANGE);
679                 if (((addr + bsize) & UINT32_MAX) != (addr + bsize))
680                         return (ERANGE);
681
682                 if (sc->b2b_mw >= 0) {
683                         /* Set Link Interface BAR size and enable/disable it. */
684                         val = 0;
685                         if (bsize > 0)
686                                 val = (~(bsize - 1) & ~0xfffff);
687                         PNTX_WRITE(sc, 0xe8 + (mw->mw_bar - 2) * 4, val);
688
689                         /* Set Link Interface BAR address. */
690                         val64 = 0x20000000 * mw->mw_bar + off;
691                         PNTX_WRITE(sc, PCIR_BAR(mw->mw_bar), val64);
692                 }
693
694                 /* Set Virtual Interface BARs address translation */
695                 PNTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4, addr);
696         }
697
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)) {
701                 eaddr = addr;
702                 for (i = 0; i < 128 * sc->alut; i++) {
703                         val = sc->link ? 0 : 1;
704                         if (sc->alut == 1)
705                                 val += 2 * sc->ntx;
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);
712                         eaddr += esize;
713                 }
714                 NTX_WRITE(sc, 0xc94, 0x10000000);
715         } else if (sc->alut && mw->mw_bar == 2)
716                 NTX_WRITE(sc, 0xc94, 0);
717
718         return (0);
719 }
720
721 static int
722 ntb_plx_mw_set_trans(device_t dev, unsigned mw_idx, bus_addr_t addr, size_t size)
723 {
724         struct ntb_plx_softc *sc = device_get_softc(dev);
725         struct ntb_plx_mw_info *mw;
726
727         if (mw_idx >= sc->mw_count)
728                 return (EINVAL);
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));
733 }
734
735 static int
736 ntb_plx_mw_clear_trans(device_t dev, unsigned mw_idx)
737 {
738
739         return (ntb_plx_mw_set_trans(dev, mw_idx, 0, 0));
740 }
741
742 static int
743 ntb_plx_mw_get_wc(device_t dev, unsigned idx, vm_memattr_t *mode)
744 {
745         struct ntb_plx_softc *sc = device_get_softc(dev);
746         struct ntb_plx_mw_info *mw;
747
748         if (idx >= sc->mw_count)
749                 return (EINVAL);
750         mw = &sc->mw_info[idx];
751         *mode = mw->mw_map_mode;
752         return (0);
753 }
754
755 static int
756 ntb_plx_mw_set_wc(device_t dev, unsigned idx, vm_memattr_t mode)
757 {
758         struct ntb_plx_softc *sc = device_get_softc(dev);
759         struct ntb_plx_mw_info *mw;
760         uint64_t off;
761         int rc;
762
763         if (idx >= sc->mw_count)
764                 return (EINVAL);
765         mw = &sc->mw_info[idx];
766         if (mw->mw_map_mode == mode)
767                 return (0);
768
769         off = 0;
770         if (idx == sc->b2b_mw) {
771                 KASSERT(sc->b2b_off != 0,
772                     ("user shouldn't get non-shared b2b mw"));
773                 off = sc->b2b_off;
774         }
775
776         rc = pmap_change_attr((vm_offset_t)mw->mw_vbase + off,
777             mw->mw_size - off, mode);
778         if (rc == 0)
779                 mw->mw_map_mode = mode;
780         return (rc);
781 }
782
783 static uint8_t
784 ntb_plx_spad_count(device_t dev)
785 {
786         struct ntb_plx_softc *sc = device_get_softc(dev);
787
788         return (sc->spad_count1 + sc->spad_count2);
789 }
790
791 static int
792 ntb_plx_spad_write(device_t dev, unsigned int idx, uint32_t val)
793 {
794         struct ntb_plx_softc *sc = device_get_softc(dev);
795         u_int off;
796
797         if (idx >= sc->spad_count1 + sc->spad_count2)
798                 return (EINVAL);
799
800         if (idx < sc->spad_count1)
801                 off = sc->spad_off1 + idx * 4;
802         else
803                 off = sc->spad_off2 + (idx - sc->spad_count1) * 4;
804         bus_write_4(sc->conf_res, off, val);
805         return (0);
806 }
807
808 static void
809 ntb_plx_spad_clear(device_t dev)
810 {
811         struct ntb_plx_softc *sc = device_get_softc(dev);
812         int i;
813
814         for (i = 0; i < sc->spad_count1 + sc->spad_count2; i++)
815                 ntb_plx_spad_write(dev, i, 0);
816 }
817
818 static int
819 ntb_plx_spad_read(device_t dev, unsigned int idx, uint32_t *val)
820 {
821         struct ntb_plx_softc *sc = device_get_softc(dev);
822         u_int off;
823
824         if (idx >= sc->spad_count1 + sc->spad_count2)
825                 return (EINVAL);
826
827         if (idx < sc->spad_count1)
828                 off = sc->spad_off1 + idx * 4;
829         else
830                 off = sc->spad_off2 + (idx - sc->spad_count1) * 4;
831         *val = bus_read_4(sc->conf_res, off);
832         return (0);
833 }
834
835 static int
836 ntb_plx_peer_spad_write(device_t dev, unsigned int idx, uint32_t val)
837 {
838         struct ntb_plx_softc *sc = device_get_softc(dev);
839         u_int off;
840
841         if (idx >= sc->spad_count1 + sc->spad_count2)
842                 return (EINVAL);
843
844         if (idx < sc->spad_count1)
845                 off = sc->spad_offp1 + idx * 4;
846         else
847                 off = sc->spad_offp2 + (idx - sc->spad_count1) * 4;
848         if (sc->b2b_mw >= 0)
849                 bus_write_4(sc->mw_info[sc->b2b_mw].mw_res, off, val);
850         else
851                 bus_write_4(sc->conf_res, off, val);
852         return (0);
853 }
854
855 static int
856 ntb_plx_peer_spad_read(device_t dev, unsigned int idx, uint32_t *val)
857 {
858         struct ntb_plx_softc *sc = device_get_softc(dev);
859         u_int off;
860
861         if (idx >= sc->spad_count1 + sc->spad_count2)
862                 return (EINVAL);
863
864         if (idx < sc->spad_count1)
865                 off = sc->spad_offp1 + idx * 4;
866         else
867                 off = sc->spad_offp2 + (idx - sc->spad_count1) * 4;
868         if (sc->b2b_mw >= 0)
869                 *val = bus_read_4(sc->mw_info[sc->b2b_mw].mw_res, off);
870         else
871                 *val = bus_read_4(sc->conf_res, off);
872         return (0);
873 }
874
875 static uint64_t
876 ntb_plx_db_valid_mask(device_t dev)
877 {
878
879         return ((1LL << PLX_NUM_DB) - 1);
880 }
881
882 static int
883 ntb_plx_db_vector_count(device_t dev)
884 {
885
886         return (1);
887 }
888
889 static uint64_t
890 ntb_plx_db_vector_mask(device_t dev, uint32_t vector)
891 {
892
893         if (vector > 0)
894                 return (0);
895         return ((1LL << PLX_NUM_DB) - 1);
896 }
897
898 static void
899 ntb_plx_db_clear(device_t dev, uint64_t bits)
900 {
901         struct ntb_plx_softc *sc = device_get_softc(dev);
902
903         NTX_WRITE(sc, sc->link ? 0xc60 : 0xc50, bits);
904 }
905
906 static void
907 ntb_plx_db_clear_mask(device_t dev, uint64_t bits)
908 {
909         struct ntb_plx_softc *sc = device_get_softc(dev);
910
911         NTX_WRITE(sc, sc->link ? 0xc68 : 0xc58, bits);
912 }
913
914 static uint64_t
915 ntb_plx_db_read(device_t dev)
916 {
917         struct ntb_plx_softc *sc = device_get_softc(dev);
918
919         return (NTX_READ(sc, sc->link ? 0xc5c : 0xc4c));
920 }
921
922 static void
923 ntb_plx_db_set_mask(device_t dev, uint64_t bits)
924 {
925         struct ntb_plx_softc *sc = device_get_softc(dev);
926
927         NTX_WRITE(sc, sc->link ? 0xc64 : 0xc54, bits);
928 }
929
930 static int
931 ntb_plx_peer_db_addr(device_t dev, bus_addr_t *db_addr, vm_size_t *db_size)
932 {
933         struct ntb_plx_softc *sc = device_get_softc(dev);
934         struct ntb_plx_mw_info *mw;
935
936         KASSERT((db_addr != NULL && db_size != NULL), ("must be non-NULL"));
937
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;
941         } else {
942                 *db_addr = rman_get_start(sc->conf_res) + PLX_NTX_BASE(sc);
943                 *db_addr += sc->link ? 0xc4c : 0xc5c;
944         }
945         *db_size = 4;
946         return (0);
947 }
948
949 static void
950 ntb_plx_peer_db_set(device_t dev, uint64_t bit)
951 {
952         struct ntb_plx_softc *sc = device_get_softc(dev);
953
954         if (sc->b2b_mw >= 0)
955                 BNTX_WRITE(sc, 0xc4c, bit);
956         else
957                 NTX_WRITE(sc, sc->link ? 0xc4c : 0xc5c, bit);
958 }
959
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),
965         /* Bus interface */
966         DEVMETHOD(bus_child_location_str, ntb_child_location_str),
967         DEVMETHOD(bus_print_child,      ntb_print_child),
968         /* NTB interface */
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),
994         DEVMETHOD_END
995 };
996
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);