19c22d3b1SRuslan Bukin /*-
29a82a56bSRuslan Bukin * Copyright (c) 2015, 2020 Ruslan Bukin <br@bsdpad.com>
39c22d3b1SRuslan Bukin * Copyright (c) 2014 The FreeBSD Foundation
49c22d3b1SRuslan Bukin * All rights reserved.
59c22d3b1SRuslan Bukin *
69c22d3b1SRuslan Bukin * This software was developed by Semihalf under
79c22d3b1SRuslan Bukin * the sponsorship of the FreeBSD Foundation.
89c22d3b1SRuslan Bukin *
99c22d3b1SRuslan Bukin * Redistribution and use in source and binary forms, with or without
109c22d3b1SRuslan Bukin * modification, are permitted provided that the following conditions
119c22d3b1SRuslan Bukin * are met:
129c22d3b1SRuslan Bukin * 1. Redistributions of source code must retain the above copyright
139c22d3b1SRuslan Bukin * notice, this list of conditions and the following disclaimer.
149c22d3b1SRuslan Bukin * 2. Redistributions in binary form must reproduce the above copyright
159c22d3b1SRuslan Bukin * notice, this list of conditions and the following disclaimer in the
169c22d3b1SRuslan Bukin * documentation and/or other materials provided with the distribution.
179c22d3b1SRuslan Bukin *
189c22d3b1SRuslan Bukin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
199c22d3b1SRuslan Bukin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
209c22d3b1SRuslan Bukin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
219c22d3b1SRuslan Bukin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
229c22d3b1SRuslan Bukin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
239c22d3b1SRuslan Bukin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
249c22d3b1SRuslan Bukin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
259c22d3b1SRuslan Bukin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
269c22d3b1SRuslan Bukin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
279c22d3b1SRuslan Bukin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
289c22d3b1SRuslan Bukin * SUCH DAMAGE.
299c22d3b1SRuslan Bukin */
309c22d3b1SRuslan Bukin
319c22d3b1SRuslan Bukin /* Generic ECAM PCIe driver */
329c22d3b1SRuslan Bukin
339c22d3b1SRuslan Bukin #include <sys/cdefs.h>
34fb05500bSWojciech Macek #include "opt_platform.h"
35fb05500bSWojciech Macek
369c22d3b1SRuslan Bukin #include <sys/param.h>
379c22d3b1SRuslan Bukin #include <sys/systm.h>
389c22d3b1SRuslan Bukin #include <sys/malloc.h>
399c22d3b1SRuslan Bukin #include <sys/kernel.h>
409c22d3b1SRuslan Bukin #include <sys/rman.h>
419c22d3b1SRuslan Bukin #include <sys/module.h>
429c22d3b1SRuslan Bukin #include <sys/bus.h>
439c22d3b1SRuslan Bukin #include <sys/endian.h>
44c6b23b0aSAndrew Turner
459c22d3b1SRuslan Bukin #include <dev/pci/pcivar.h>
469c22d3b1SRuslan Bukin #include <dev/pci/pcireg.h>
479c22d3b1SRuslan Bukin #include <dev/pci/pcib_private.h>
48fb05500bSWojciech Macek #include <dev/pci/pci_host_generic.h>
49c6b23b0aSAndrew Turner
509c22d3b1SRuslan Bukin #include <machine/bus.h>
519c22d3b1SRuslan Bukin #include <machine/intr.h>
529c22d3b1SRuslan Bukin
539c22d3b1SRuslan Bukin #include "pcib_if.h"
549c22d3b1SRuslan Bukin
55cb894f74SAndrew Turner #if defined(VM_MEMATTR_DEVICE_NP)
56cb894f74SAndrew Turner #define PCI_UNMAPPED
57cb894f74SAndrew Turner #define PCI_RF_FLAGS RF_UNMAPPED
58cb894f74SAndrew Turner #else
59cb894f74SAndrew Turner #define PCI_RF_FLAGS 0
60cb894f74SAndrew Turner #endif
61cb894f74SAndrew Turner
62b3132299SKyle Evans /*
63b3132299SKyle Evans * We allocate "ranges" specified mappings higher up in the rid space to avoid
64b3132299SKyle Evans * conflicts with various definitions in the wild that may have other registers
65b3132299SKyle Evans * attributed to the controller besides just the config space.
66b3132299SKyle Evans */
67b3132299SKyle Evans #define RANGE_RID(idx) ((idx) + 100)
68cb894f74SAndrew Turner
699c22d3b1SRuslan Bukin /* Forward prototypes */
709c22d3b1SRuslan Bukin
719c22d3b1SRuslan Bukin static uint32_t generic_pcie_read_config(device_t dev, u_int bus, u_int slot,
729c22d3b1SRuslan Bukin u_int func, u_int reg, int bytes);
739c22d3b1SRuslan Bukin static void generic_pcie_write_config(device_t dev, u_int bus, u_int slot,
749c22d3b1SRuslan Bukin u_int func, u_int reg, uint32_t val, int bytes);
759c22d3b1SRuslan Bukin static int generic_pcie_maxslots(device_t dev);
769c22d3b1SRuslan Bukin static int generic_pcie_write_ivar(device_t dev, device_t child, int index,
779c22d3b1SRuslan Bukin uintptr_t value);
78ad90dbb8SWojciech Macek
79fb05500bSWojciech Macek int
pci_host_generic_core_attach(device_t dev)80f94f8e62SAndrew Turner pci_host_generic_core_attach(device_t dev)
819c22d3b1SRuslan Bukin {
82cb894f74SAndrew Turner #ifdef PCI_UNMAPPED
83cb894f74SAndrew Turner struct resource_map_request req;
84cb894f74SAndrew Turner struct resource_map map;
85cb894f74SAndrew Turner #endif
86f94f8e62SAndrew Turner struct generic_pcie_core_softc *sc;
8703713f80SJohn Baldwin struct rman *rm;
889a7053ceSAndrew Turner uint64_t phys_base;
899a7053ceSAndrew Turner uint64_t pci_base;
909a7053ceSAndrew Turner uint64_t size;
91b2867001SJohn Baldwin const char *range_descr;
9251f8ac22SJohn Baldwin char buf[64];
937098f3c7SAndrew Turner int domain, error;
94*c19f1ad1SJohn Baldwin int flags, rid, tuple;
959c22d3b1SRuslan Bukin
969c22d3b1SRuslan Bukin sc = device_get_softc(dev);
979c22d3b1SRuslan Bukin sc->dev = dev;
989c22d3b1SRuslan Bukin
992760c2caSAndrew Turner /* Create the parent DMA tag to pass down the coherent flag */
1002760c2caSAndrew Turner error = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */
1012760c2caSAndrew Turner 1, 0, /* alignment, bounds */
1022760c2caSAndrew Turner BUS_SPACE_MAXADDR, /* lowaddr */
1032760c2caSAndrew Turner BUS_SPACE_MAXADDR, /* highaddr */
1042760c2caSAndrew Turner NULL, NULL, /* filter, filterarg */
1052760c2caSAndrew Turner BUS_SPACE_MAXSIZE, /* maxsize */
1062760c2caSAndrew Turner BUS_SPACE_UNRESTRICTED, /* nsegments */
1072760c2caSAndrew Turner BUS_SPACE_MAXSIZE, /* maxsegsize */
1082760c2caSAndrew Turner sc->coherent ? BUS_DMA_COHERENT : 0, /* flags */
1092760c2caSAndrew Turner NULL, NULL, /* lockfunc, lockarg */
1102760c2caSAndrew Turner &sc->dmat);
1112760c2caSAndrew Turner if (error != 0)
1122760c2caSAndrew Turner return (error);
1132760c2caSAndrew Turner
1147098f3c7SAndrew Turner /*
1157098f3c7SAndrew Turner * Attempt to set the domain. If it's missing, or we are unable to
1167098f3c7SAndrew Turner * set it then memory allocations may be placed in the wrong domain.
1177098f3c7SAndrew Turner */
1187098f3c7SAndrew Turner if (bus_get_domain(dev, &domain) == 0)
1197098f3c7SAndrew Turner (void)bus_dma_tag_set_domain(sc->dmat, domain);
1207098f3c7SAndrew Turner
1217029f2c8SAndrew Turner if ((sc->quirks & PCIE_CUSTOM_CONFIG_SPACE_QUIRK) == 0) {
1229c22d3b1SRuslan Bukin rid = 0;
123cb894f74SAndrew Turner sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
124cb894f74SAndrew Turner PCI_RF_FLAGS | RF_ACTIVE);
1259c22d3b1SRuslan Bukin if (sc->res == NULL) {
126d843dd0eSAndrew Turner device_printf(dev, "could not allocate memory.\n");
127d843dd0eSAndrew Turner error = ENXIO;
128d843dd0eSAndrew Turner goto err_resource;
1299c22d3b1SRuslan Bukin }
130cb894f74SAndrew Turner #ifdef PCI_UNMAPPED
131cb894f74SAndrew Turner resource_init_map_request(&req);
132cb894f74SAndrew Turner req.memattr = VM_MEMATTR_DEVICE_NP;
1337029f2c8SAndrew Turner error = bus_map_resource(dev, SYS_RES_MEMORY, sc->res, &req,
1347029f2c8SAndrew Turner &map);
135cb894f74SAndrew Turner if (error != 0) {
136cb894f74SAndrew Turner device_printf(dev, "could not map memory.\n");
137cb894f74SAndrew Turner return (error);
138cb894f74SAndrew Turner }
139cb894f74SAndrew Turner rman_set_mapping(sc->res, &map);
140cb894f74SAndrew Turner #endif
1417029f2c8SAndrew Turner }
1429c22d3b1SRuslan Bukin
1439a7053ceSAndrew Turner sc->has_pmem = false;
1449a7053ceSAndrew Turner sc->pmem_rman.rm_type = RMAN_ARRAY;
14551f8ac22SJohn Baldwin snprintf(buf, sizeof(buf), "%s prefetch window",
14651f8ac22SJohn Baldwin device_get_nameunit(dev));
14751f8ac22SJohn Baldwin sc->pmem_rman.rm_descr = strdup(buf, M_DEVBUF);
1489a7053ceSAndrew Turner
1499c22d3b1SRuslan Bukin sc->mem_rman.rm_type = RMAN_ARRAY;
15051f8ac22SJohn Baldwin snprintf(buf, sizeof(buf), "%s memory window",
15151f8ac22SJohn Baldwin device_get_nameunit(dev));
15251f8ac22SJohn Baldwin sc->mem_rman.rm_descr = strdup(buf, M_DEVBUF);
1539a7053ceSAndrew Turner
1549c22d3b1SRuslan Bukin sc->io_rman.rm_type = RMAN_ARRAY;
15551f8ac22SJohn Baldwin snprintf(buf, sizeof(buf), "%s I/O port window",
15651f8ac22SJohn Baldwin device_get_nameunit(dev));
15751f8ac22SJohn Baldwin sc->io_rman.rm_descr = strdup(buf, M_DEVBUF);
1589c22d3b1SRuslan Bukin
1599c22d3b1SRuslan Bukin /* Initialize rman and allocate memory regions */
1609a7053ceSAndrew Turner error = rman_init(&sc->pmem_rman);
1619a7053ceSAndrew Turner if (error) {
1629a7053ceSAndrew Turner device_printf(dev, "rman_init() failed. error = %d\n", error);
163d843dd0eSAndrew Turner goto err_pmem_rman;
1649a7053ceSAndrew Turner }
1659a7053ceSAndrew Turner
1669c22d3b1SRuslan Bukin error = rman_init(&sc->mem_rman);
1679c22d3b1SRuslan Bukin if (error) {
1689c22d3b1SRuslan Bukin device_printf(dev, "rman_init() failed. error = %d\n", error);
169d843dd0eSAndrew Turner goto err_mem_rman;
1709c22d3b1SRuslan Bukin }
1719c22d3b1SRuslan Bukin
1729c22d3b1SRuslan Bukin error = rman_init(&sc->io_rman);
1739c22d3b1SRuslan Bukin if (error) {
1749c22d3b1SRuslan Bukin device_printf(dev, "rman_init() failed. error = %d\n", error);
175d843dd0eSAndrew Turner goto err_io_rman;
1769c22d3b1SRuslan Bukin }
1779c22d3b1SRuslan Bukin
1789a7053ceSAndrew Turner for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) {
1799a7053ceSAndrew Turner phys_base = sc->ranges[tuple].phys_base;
1809a7053ceSAndrew Turner pci_base = sc->ranges[tuple].pci_base;
1819a7053ceSAndrew Turner size = sc->ranges[tuple].size;
182b3132299SKyle Evans rid = RANGE_RID(tuple);
183d79b6b8eSJohn Baldwin if (size == 0)
1849a7053ceSAndrew Turner continue; /* empty range element */
1859a7053ceSAndrew Turner switch (FLAG_TYPE(sc->ranges[tuple].flags)) {
1869a7053ceSAndrew Turner case FLAG_TYPE_PMEM:
1879a7053ceSAndrew Turner sc->has_pmem = true;
188b2867001SJohn Baldwin range_descr = "prefetch";
189d79b6b8eSJohn Baldwin flags = RF_PREFETCHABLE;
19003713f80SJohn Baldwin rm = &sc->pmem_rman;
1919a7053ceSAndrew Turner break;
1929a7053ceSAndrew Turner case FLAG_TYPE_MEM:
193b2867001SJohn Baldwin range_descr = "memory";
194d79b6b8eSJohn Baldwin flags = 0;
19503713f80SJohn Baldwin rm = &sc->mem_rman;
1969a7053ceSAndrew Turner break;
1979a7053ceSAndrew Turner case FLAG_TYPE_IO:
198b2867001SJohn Baldwin range_descr = "I/O port";
199d79b6b8eSJohn Baldwin flags = 0;
20003713f80SJohn Baldwin rm = &sc->io_rman;
2019a7053ceSAndrew Turner break;
2029a7053ceSAndrew Turner default:
2039a7053ceSAndrew Turner continue;
2049a7053ceSAndrew Turner }
20503713f80SJohn Baldwin if (bootverbose)
20603713f80SJohn Baldwin device_printf(dev,
20703713f80SJohn Baldwin "PCI addr: 0x%jx, CPU addr: 0x%jx, Size: 0x%jx, Type: %s\n",
20803713f80SJohn Baldwin pci_base, phys_base, size, range_descr);
209*c19f1ad1SJohn Baldwin error = bus_set_resource(dev, SYS_RES_MEMORY, rid, phys_base,
210*c19f1ad1SJohn Baldwin size);
211d79b6b8eSJohn Baldwin if (error != 0) {
212d79b6b8eSJohn Baldwin device_printf(dev,
213d79b6b8eSJohn Baldwin "failed to set resource for range %d: %d\n", tuple,
214d79b6b8eSJohn Baldwin error);
21503713f80SJohn Baldwin continue;
216d79b6b8eSJohn Baldwin }
217b3132299SKyle Evans sc->ranges[tuple].rid = rid;
218*c19f1ad1SJohn Baldwin sc->ranges[tuple].res = bus_alloc_resource_any(dev,
219*c19f1ad1SJohn Baldwin SYS_RES_MEMORY, &rid, RF_ACTIVE | RF_UNMAPPED | flags);
220d79b6b8eSJohn Baldwin if (sc->ranges[tuple].res == NULL) {
221d79b6b8eSJohn Baldwin device_printf(dev,
222d79b6b8eSJohn Baldwin "failed to allocate resource for range %d\n", tuple);
22303713f80SJohn Baldwin continue;
224d79b6b8eSJohn Baldwin }
22503713f80SJohn Baldwin error = rman_manage_region(rm, pci_base, pci_base + size - 1);
22603713f80SJohn Baldwin if (error) {
22703713f80SJohn Baldwin device_printf(dev, "rman_manage_region() failed."
22803713f80SJohn Baldwin "error = %d\n", error);
22903713f80SJohn Baldwin continue;
23003713f80SJohn Baldwin }
231d843dd0eSAndrew Turner }
232d843dd0eSAndrew Turner
233d843dd0eSAndrew Turner return (0);
234d843dd0eSAndrew Turner
235d843dd0eSAndrew Turner err_io_rman:
236d843dd0eSAndrew Turner rman_fini(&sc->mem_rman);
237d843dd0eSAndrew Turner err_mem_rman:
238d843dd0eSAndrew Turner rman_fini(&sc->pmem_rman);
239d843dd0eSAndrew Turner err_pmem_rman:
24051f8ac22SJohn Baldwin free(__DECONST(char *, sc->io_rman.rm_descr), M_DEVBUF);
24151f8ac22SJohn Baldwin free(__DECONST(char *, sc->mem_rman.rm_descr), M_DEVBUF);
24251f8ac22SJohn Baldwin free(__DECONST(char *, sc->pmem_rman.rm_descr), M_DEVBUF);
2437029f2c8SAndrew Turner if (sc->res != NULL)
244d843dd0eSAndrew Turner bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->res);
245d843dd0eSAndrew Turner err_resource:
246d843dd0eSAndrew Turner bus_dma_tag_destroy(sc->dmat);
2479a7053ceSAndrew Turner return (error);
2489a7053ceSAndrew Turner }
249d843dd0eSAndrew Turner
250d843dd0eSAndrew Turner int
pci_host_generic_core_detach(device_t dev)251d843dd0eSAndrew Turner pci_host_generic_core_detach(device_t dev)
252d843dd0eSAndrew Turner {
253d843dd0eSAndrew Turner struct generic_pcie_core_softc *sc;
254*c19f1ad1SJohn Baldwin int error, rid, tuple;
255d843dd0eSAndrew Turner
256d843dd0eSAndrew Turner sc = device_get_softc(dev);
257d843dd0eSAndrew Turner
258d843dd0eSAndrew Turner error = bus_generic_detach(dev);
259d843dd0eSAndrew Turner if (error != 0)
260d843dd0eSAndrew Turner return (error);
261d843dd0eSAndrew Turner
262d79b6b8eSJohn Baldwin for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) {
263b3132299SKyle Evans rid = sc->ranges[tuple].rid;
264b3132299SKyle Evans if (sc->ranges[tuple].size == 0) {
265b3132299SKyle Evans MPASS(sc->ranges[tuple].res == NULL);
266d79b6b8eSJohn Baldwin continue; /* empty range element */
267b3132299SKyle Evans }
268b3132299SKyle Evans
269b3132299SKyle Evans MPASS(rid != -1);
270d79b6b8eSJohn Baldwin switch (FLAG_TYPE(sc->ranges[tuple].flags)) {
271d79b6b8eSJohn Baldwin case FLAG_TYPE_PMEM:
272d79b6b8eSJohn Baldwin case FLAG_TYPE_MEM:
273d79b6b8eSJohn Baldwin case FLAG_TYPE_IO:
274d79b6b8eSJohn Baldwin break;
275d79b6b8eSJohn Baldwin default:
276d79b6b8eSJohn Baldwin continue;
277d79b6b8eSJohn Baldwin }
278d79b6b8eSJohn Baldwin if (sc->ranges[tuple].res != NULL)
279*c19f1ad1SJohn Baldwin bus_release_resource(dev, SYS_RES_MEMORY, rid,
280d79b6b8eSJohn Baldwin sc->ranges[tuple].res);
281*c19f1ad1SJohn Baldwin bus_delete_resource(dev, SYS_RES_MEMORY, rid);
282d79b6b8eSJohn Baldwin }
283d843dd0eSAndrew Turner rman_fini(&sc->io_rman);
284d843dd0eSAndrew Turner rman_fini(&sc->mem_rman);
285d843dd0eSAndrew Turner rman_fini(&sc->pmem_rman);
28651f8ac22SJohn Baldwin free(__DECONST(char *, sc->io_rman.rm_descr), M_DEVBUF);
28751f8ac22SJohn Baldwin free(__DECONST(char *, sc->mem_rman.rm_descr), M_DEVBUF);
28851f8ac22SJohn Baldwin free(__DECONST(char *, sc->pmem_rman.rm_descr), M_DEVBUF);
2897029f2c8SAndrew Turner if (sc->res != NULL)
290d843dd0eSAndrew Turner bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->res);
291d843dd0eSAndrew Turner bus_dma_tag_destroy(sc->dmat);
2929a7053ceSAndrew Turner
2939c22d3b1SRuslan Bukin return (0);
2949c22d3b1SRuslan Bukin }
2959c22d3b1SRuslan Bukin
2969c22d3b1SRuslan Bukin static uint32_t
generic_pcie_read_config(device_t dev,u_int bus,u_int slot,u_int func,u_int reg,int bytes)2979c22d3b1SRuslan Bukin generic_pcie_read_config(device_t dev, u_int bus, u_int slot,
2989c22d3b1SRuslan Bukin u_int func, u_int reg, int bytes)
2999c22d3b1SRuslan Bukin {
300f94f8e62SAndrew Turner struct generic_pcie_core_softc *sc;
3019c22d3b1SRuslan Bukin uint64_t offset;
3029c22d3b1SRuslan Bukin uint32_t data;
3039c22d3b1SRuslan Bukin
304697c57e5SJayachandran C. sc = device_get_softc(dev);
305697c57e5SJayachandran C. if ((bus < sc->bus_start) || (bus > sc->bus_end))
306697c57e5SJayachandran C. return (~0U);
307697c57e5SJayachandran C. if ((slot > PCI_SLOTMAX) || (func > PCI_FUNCMAX) ||
308697c57e5SJayachandran C. (reg > PCIE_REGMAX))
3099c22d3b1SRuslan Bukin return (~0U);
3102de4c7f6SPawel Anikiel if ((sc->quirks & PCIE_ECAM_DESIGNWARE_QUIRK) && bus == 0 && slot > 0)
3112de4c7f6SPawel Anikiel return (~0U);
3129c22d3b1SRuslan Bukin
313697c57e5SJayachandran C. offset = PCIE_ADDR_OFFSET(bus - sc->bus_start, slot, func, reg);
3149c22d3b1SRuslan Bukin
3159c22d3b1SRuslan Bukin switch (bytes) {
3169c22d3b1SRuslan Bukin case 1:
3178bc94f25SAndrew Turner data = bus_read_1(sc->res, offset);
3189c22d3b1SRuslan Bukin break;
3199c22d3b1SRuslan Bukin case 2:
3208bc94f25SAndrew Turner data = le16toh(bus_read_2(sc->res, offset));
3219c22d3b1SRuslan Bukin break;
3229c22d3b1SRuslan Bukin case 4:
3238bc94f25SAndrew Turner data = le32toh(bus_read_4(sc->res, offset));
3249c22d3b1SRuslan Bukin break;
3259c22d3b1SRuslan Bukin default:
3269c22d3b1SRuslan Bukin return (~0U);
3279c22d3b1SRuslan Bukin }
3289c22d3b1SRuslan Bukin
3299c22d3b1SRuslan Bukin return (data);
3309c22d3b1SRuslan Bukin }
3319c22d3b1SRuslan Bukin
3329c22d3b1SRuslan Bukin static void
generic_pcie_write_config(device_t dev,u_int bus,u_int slot,u_int func,u_int reg,uint32_t val,int bytes)3339c22d3b1SRuslan Bukin generic_pcie_write_config(device_t dev, u_int bus, u_int slot,
3349c22d3b1SRuslan Bukin u_int func, u_int reg, uint32_t val, int bytes)
3359c22d3b1SRuslan Bukin {
336f94f8e62SAndrew Turner struct generic_pcie_core_softc *sc;
3379c22d3b1SRuslan Bukin uint64_t offset;
3389c22d3b1SRuslan Bukin
339697c57e5SJayachandran C. sc = device_get_softc(dev);
340697c57e5SJayachandran C. if ((bus < sc->bus_start) || (bus > sc->bus_end))
341697c57e5SJayachandran C. return;
342697c57e5SJayachandran C. if ((slot > PCI_SLOTMAX) || (func > PCI_FUNCMAX) ||
343697c57e5SJayachandran C. (reg > PCIE_REGMAX))
3449c22d3b1SRuslan Bukin return;
3459c22d3b1SRuslan Bukin
346697c57e5SJayachandran C. offset = PCIE_ADDR_OFFSET(bus - sc->bus_start, slot, func, reg);
3479c22d3b1SRuslan Bukin
3489c22d3b1SRuslan Bukin switch (bytes) {
3499c22d3b1SRuslan Bukin case 1:
3508bc94f25SAndrew Turner bus_write_1(sc->res, offset, val);
3519c22d3b1SRuslan Bukin break;
3529c22d3b1SRuslan Bukin case 2:
3538bc94f25SAndrew Turner bus_write_2(sc->res, offset, htole16(val));
3549c22d3b1SRuslan Bukin break;
3559c22d3b1SRuslan Bukin case 4:
3568bc94f25SAndrew Turner bus_write_4(sc->res, offset, htole32(val));
3579c22d3b1SRuslan Bukin break;
3589c22d3b1SRuslan Bukin default:
3599c22d3b1SRuslan Bukin return;
3609c22d3b1SRuslan Bukin }
3619c22d3b1SRuslan Bukin }
3629c22d3b1SRuslan Bukin
3639c22d3b1SRuslan Bukin static int
generic_pcie_maxslots(device_t dev)3649c22d3b1SRuslan Bukin generic_pcie_maxslots(device_t dev)
3659c22d3b1SRuslan Bukin {
3669c22d3b1SRuslan Bukin
3679c22d3b1SRuslan Bukin return (31); /* max slots per bus acc. to standard */
3689c22d3b1SRuslan Bukin }
3699c22d3b1SRuslan Bukin
3707cafe75cSAndrew Turner int
generic_pcie_read_ivar(device_t dev,device_t child,int index,uintptr_t * result)3719c22d3b1SRuslan Bukin generic_pcie_read_ivar(device_t dev, device_t child, int index,
3729c22d3b1SRuslan Bukin uintptr_t *result)
3739c22d3b1SRuslan Bukin {
374f94f8e62SAndrew Turner struct generic_pcie_core_softc *sc;
3759c22d3b1SRuslan Bukin
3769c22d3b1SRuslan Bukin sc = device_get_softc(dev);
377fafb43abSAndrew Turner switch (index) {
378fafb43abSAndrew Turner case PCIB_IVAR_BUS:
379697c57e5SJayachandran C. *result = sc->bus_start;
3809c22d3b1SRuslan Bukin return (0);
381fafb43abSAndrew Turner case PCIB_IVAR_DOMAIN:
3829c22d3b1SRuslan Bukin *result = sc->ecam;
3839c22d3b1SRuslan Bukin return (0);
3849c22d3b1SRuslan Bukin }
3859c22d3b1SRuslan Bukin
386fb05500bSWojciech Macek if (bootverbose)
387fb05500bSWojciech Macek device_printf(dev, "ERROR: Unknown index %d.\n", index);
3889c22d3b1SRuslan Bukin return (ENOENT);
3899c22d3b1SRuslan Bukin }
3909c22d3b1SRuslan Bukin
3919c22d3b1SRuslan Bukin static int
generic_pcie_write_ivar(device_t dev,device_t child,int index,uintptr_t value)3929c22d3b1SRuslan Bukin generic_pcie_write_ivar(device_t dev, device_t child, int index,
3939c22d3b1SRuslan Bukin uintptr_t value)
3949c22d3b1SRuslan Bukin {
3959c22d3b1SRuslan Bukin
3969c22d3b1SRuslan Bukin return (ENOENT);
3979c22d3b1SRuslan Bukin }
3989c22d3b1SRuslan Bukin
3999c22d3b1SRuslan Bukin static struct rman *
generic_pcie_get_rman(device_t dev,int type,u_int flags)400d79b6b8eSJohn Baldwin generic_pcie_get_rman(device_t dev, int type, u_int flags)
4019c22d3b1SRuslan Bukin {
402d79b6b8eSJohn Baldwin struct generic_pcie_core_softc *sc = device_get_softc(dev);
4039c22d3b1SRuslan Bukin
4049c22d3b1SRuslan Bukin switch (type) {
4059c22d3b1SRuslan Bukin case SYS_RES_IOPORT:
4069c22d3b1SRuslan Bukin return (&sc->io_rman);
4079c22d3b1SRuslan Bukin case SYS_RES_MEMORY:
4089a7053ceSAndrew Turner if (sc->has_pmem && (flags & RF_PREFETCHABLE) != 0)
4099a7053ceSAndrew Turner return (&sc->pmem_rman);
4109c22d3b1SRuslan Bukin return (&sc->mem_rman);
4119c22d3b1SRuslan Bukin default:
4129c22d3b1SRuslan Bukin break;
4139c22d3b1SRuslan Bukin }
4149c22d3b1SRuslan Bukin
4159c22d3b1SRuslan Bukin return (NULL);
4169c22d3b1SRuslan Bukin }
4179c22d3b1SRuslan Bukin
418f94f8e62SAndrew Turner int
pci_host_generic_core_release_resource(device_t dev,device_t child,struct resource * res)4199dbf5b0eSJohn Baldwin pci_host_generic_core_release_resource(device_t dev, device_t child,
4209dbf5b0eSJohn Baldwin struct resource *res)
4219c22d3b1SRuslan Bukin {
422f94f8e62SAndrew Turner struct generic_pcie_core_softc *sc;
4239c22d3b1SRuslan Bukin
4249c22d3b1SRuslan Bukin sc = device_get_softc(dev);
4259dbf5b0eSJohn Baldwin switch (rman_get_type(res)) {
426feefc3c7SJohn Baldwin case PCI_RES_BUS:
4279dbf5b0eSJohn Baldwin return (pci_domain_release_bus(sc->ecam, child, res));
428feefc3c7SJohn Baldwin case SYS_RES_IOPORT:
429feefc3c7SJohn Baldwin case SYS_RES_MEMORY:
4309dbf5b0eSJohn Baldwin return (bus_generic_rman_release_resource(dev, child, res));
431feefc3c7SJohn Baldwin default:
4329dbf5b0eSJohn Baldwin return (bus_generic_release_resource(dev, child, res));
433feefc3c7SJohn Baldwin }
4349c22d3b1SRuslan Bukin }
4359c22d3b1SRuslan Bukin
436d79b6b8eSJohn Baldwin static struct pcie_range *
generic_pcie_containing_range(device_t dev,int type,rman_res_t start,rman_res_t end)437d79b6b8eSJohn Baldwin generic_pcie_containing_range(device_t dev, int type, rman_res_t start,
438d79b6b8eSJohn Baldwin rman_res_t end)
4399c22d3b1SRuslan Bukin {
440d79b6b8eSJohn Baldwin struct generic_pcie_core_softc *sc = device_get_softc(dev);
4419a7053ceSAndrew Turner uint64_t pci_base;
4429a7053ceSAndrew Turner uint64_t size;
4439a7053ceSAndrew Turner int i, space;
4449c22d3b1SRuslan Bukin
4459a7053ceSAndrew Turner switch (type) {
4469a7053ceSAndrew Turner case SYS_RES_IOPORT:
4479a7053ceSAndrew Turner case SYS_RES_MEMORY:
448d79b6b8eSJohn Baldwin break;
449d79b6b8eSJohn Baldwin default:
450d79b6b8eSJohn Baldwin return (NULL);
451d79b6b8eSJohn Baldwin }
452d79b6b8eSJohn Baldwin
4539a7053ceSAndrew Turner for (i = 0; i < MAX_RANGES_TUPLES; i++) {
4549a7053ceSAndrew Turner pci_base = sc->ranges[i].pci_base;
4559a7053ceSAndrew Turner size = sc->ranges[i].size;
456d79b6b8eSJohn Baldwin if (size == 0)
457d79b6b8eSJohn Baldwin continue; /* empty range element */
4589a7053ceSAndrew Turner
459d79b6b8eSJohn Baldwin if (start < pci_base || end >= pci_base + size)
4609a7053ceSAndrew Turner continue;
4619a7053ceSAndrew Turner
4629a7053ceSAndrew Turner switch (FLAG_TYPE(sc->ranges[i].flags)) {
4639a7053ceSAndrew Turner case FLAG_TYPE_MEM:
4649a7053ceSAndrew Turner case FLAG_TYPE_PMEM:
4659a7053ceSAndrew Turner space = SYS_RES_MEMORY;
4669a7053ceSAndrew Turner break;
4679a7053ceSAndrew Turner case FLAG_TYPE_IO:
4689a7053ceSAndrew Turner space = SYS_RES_IOPORT;
4699a7053ceSAndrew Turner break;
4709a7053ceSAndrew Turner default:
4719a7053ceSAndrew Turner continue;
4729a7053ceSAndrew Turner }
4739a7053ceSAndrew Turner
474d79b6b8eSJohn Baldwin if (type == space)
475d79b6b8eSJohn Baldwin return (&sc->ranges[i]);
4769a7053ceSAndrew Turner }
477d79b6b8eSJohn Baldwin return (NULL);
478d79b6b8eSJohn Baldwin }
479d79b6b8eSJohn Baldwin
480d79b6b8eSJohn Baldwin static int
generic_pcie_translate_resource(device_t dev,int type,rman_res_t start,rman_res_t * new_start)481291079d0SJohn Baldwin generic_pcie_translate_resource(device_t dev, int type, rman_res_t start,
482291079d0SJohn Baldwin rman_res_t *new_start)
483d79b6b8eSJohn Baldwin {
484d79b6b8eSJohn Baldwin struct pcie_range *range;
485d79b6b8eSJohn Baldwin
486d79b6b8eSJohn Baldwin /* Translate the address from a PCI address to a physical address */
487d79b6b8eSJohn Baldwin switch (type) {
488d79b6b8eSJohn Baldwin case SYS_RES_IOPORT:
489d79b6b8eSJohn Baldwin case SYS_RES_MEMORY:
490291079d0SJohn Baldwin range = generic_pcie_containing_range(dev, type, start, start);
491d79b6b8eSJohn Baldwin if (range == NULL)
492d79b6b8eSJohn Baldwin return (ENOENT);
493d79b6b8eSJohn Baldwin *new_start = start - range->pci_base + range->phys_base;
4949a7053ceSAndrew Turner break;
4959a7053ceSAndrew Turner default:
496372c142bSAndrew Turner /* No translation for non-memory types */
497372c142bSAndrew Turner *new_start = start;
4989a7053ceSAndrew Turner break;
4999a7053ceSAndrew Turner }
5009a7053ceSAndrew Turner
501d79b6b8eSJohn Baldwin return (0);
502372c142bSAndrew Turner }
503372c142bSAndrew Turner
504372c142bSAndrew Turner struct resource *
pci_host_generic_core_alloc_resource(device_t dev,device_t child,int type,int * rid,rman_res_t start,rman_res_t end,rman_res_t count,u_int flags)505372c142bSAndrew Turner pci_host_generic_core_alloc_resource(device_t dev, device_t child, int type,
506372c142bSAndrew Turner int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
507372c142bSAndrew Turner {
508372c142bSAndrew Turner struct generic_pcie_core_softc *sc;
509372c142bSAndrew Turner struct resource *res;
510372c142bSAndrew Turner
511372c142bSAndrew Turner sc = device_get_softc(dev);
512372c142bSAndrew Turner
513d79b6b8eSJohn Baldwin switch (type) {
514d79b6b8eSJohn Baldwin case PCI_RES_BUS:
515d79b6b8eSJohn Baldwin res = pci_domain_alloc_bus(sc->ecam, child, rid, start, end,
516d79b6b8eSJohn Baldwin count, flags);
517d79b6b8eSJohn Baldwin break;
518d79b6b8eSJohn Baldwin case SYS_RES_IOPORT:
519d79b6b8eSJohn Baldwin case SYS_RES_MEMORY:
520d79b6b8eSJohn Baldwin res = bus_generic_rman_alloc_resource(dev, child, type, rid,
521d79b6b8eSJohn Baldwin start, end, count, flags);
522d79b6b8eSJohn Baldwin break;
523d79b6b8eSJohn Baldwin default:
524d79b6b8eSJohn Baldwin res = bus_generic_alloc_resource(dev, child, type, rid, start,
525d79b6b8eSJohn Baldwin end, count, flags);
526d79b6b8eSJohn Baldwin break;
5279c22d3b1SRuslan Bukin }
528d79b6b8eSJohn Baldwin if (res == NULL) {
5299c22d3b1SRuslan Bukin device_printf(dev, "%s FAIL: type=%d, rid=%d, "
5309b0c982bSBjoern A. Zeeb "start=%016jx, end=%016jx, count=%016jx, flags=%x\n",
5319c22d3b1SRuslan Bukin __func__, type, *rid, start, end, count, flags);
532d79b6b8eSJohn Baldwin }
533d79b6b8eSJohn Baldwin return (res);
5349c22d3b1SRuslan Bukin }
5359c22d3b1SRuslan Bukin
5369c22d3b1SRuslan Bukin static int
generic_pcie_activate_resource(device_t dev,device_t child,struct resource * r)5372baed46eSJohn Baldwin generic_pcie_activate_resource(device_t dev, device_t child, struct resource *r)
538bd158cddSJayachandran C. {
539e9eb353bSJohn Baldwin struct generic_pcie_core_softc *sc;
540bd158cddSJayachandran C.
541e9eb353bSJohn Baldwin sc = device_get_softc(dev);
5422baed46eSJohn Baldwin switch (rman_get_type(r)) {
543d79b6b8eSJohn Baldwin case PCI_RES_BUS:
5442baed46eSJohn Baldwin return (pci_domain_activate_bus(sc->ecam, child, r));
545d79b6b8eSJohn Baldwin case SYS_RES_IOPORT:
546d79b6b8eSJohn Baldwin case SYS_RES_MEMORY:
5472baed46eSJohn Baldwin return (bus_generic_rman_activate_resource(dev, child, r));
548d79b6b8eSJohn Baldwin default:
5492baed46eSJohn Baldwin return (bus_generic_activate_resource(dev, child, r));
550d79b6b8eSJohn Baldwin }
551bd158cddSJayachandran C. }
552bd158cddSJayachandran C.
553bd158cddSJayachandran C. static int
generic_pcie_deactivate_resource(device_t dev,device_t child,struct resource * r)5542baed46eSJohn Baldwin generic_pcie_deactivate_resource(device_t dev, device_t child,
5552baed46eSJohn Baldwin struct resource *r)
556bd158cddSJayachandran C. {
557e9eb353bSJohn Baldwin struct generic_pcie_core_softc *sc;
558bd158cddSJayachandran C.
559e9eb353bSJohn Baldwin sc = device_get_softc(dev);
5602baed46eSJohn Baldwin switch (rman_get_type(r)) {
561d79b6b8eSJohn Baldwin case PCI_RES_BUS:
5622baed46eSJohn Baldwin return (pci_domain_deactivate_bus(sc->ecam, child, r));
563bd158cddSJayachandran C. case SYS_RES_IOPORT:
564bd158cddSJayachandran C. case SYS_RES_MEMORY:
5652baed46eSJohn Baldwin return (bus_generic_rman_deactivate_resource(dev, child, r));
566bd158cddSJayachandran C. default:
5672baed46eSJohn Baldwin return (bus_generic_deactivate_resource(dev, child, r));
568bd158cddSJayachandran C. }
569bd158cddSJayachandran C. }
570bd158cddSJayachandran C.
571bd158cddSJayachandran C. static int
generic_pcie_adjust_resource(device_t dev,device_t child,struct resource * res,rman_res_t start,rman_res_t end)572fef01f04SJohn Baldwin generic_pcie_adjust_resource(device_t dev, device_t child,
5732dd1bdf1SJustin Hibbits struct resource *res, rman_res_t start, rman_res_t end)
5749c22d3b1SRuslan Bukin {
575f94f8e62SAndrew Turner struct generic_pcie_core_softc *sc;
5769c22d3b1SRuslan Bukin
5779c22d3b1SRuslan Bukin sc = device_get_softc(dev);
578fef01f04SJohn Baldwin switch (rman_get_type(res)) {
579d79b6b8eSJohn Baldwin case PCI_RES_BUS:
5806d2f7ef6SAndrew Turner return (pci_domain_adjust_bus(sc->ecam, child, res, start,
5816d2f7ef6SAndrew Turner end));
582d79b6b8eSJohn Baldwin case SYS_RES_IOPORT:
583d79b6b8eSJohn Baldwin case SYS_RES_MEMORY:
584fef01f04SJohn Baldwin return (bus_generic_rman_adjust_resource(dev, child, res,
585d79b6b8eSJohn Baldwin start, end));
586d79b6b8eSJohn Baldwin default:
587fef01f04SJohn Baldwin return (bus_generic_adjust_resource(dev, child, res, start,
588fef01f04SJohn Baldwin end));
589d79b6b8eSJohn Baldwin }
590d79b6b8eSJohn Baldwin }
5919c22d3b1SRuslan Bukin
592d79b6b8eSJohn Baldwin static int
generic_pcie_map_resource(device_t dev,device_t child,struct resource * r,struct resource_map_request * argsp,struct resource_map * map)593d77f2092SJohn Baldwin generic_pcie_map_resource(device_t dev, device_t child, struct resource *r,
594d77f2092SJohn Baldwin struct resource_map_request *argsp, struct resource_map *map)
595d79b6b8eSJohn Baldwin {
596d79b6b8eSJohn Baldwin struct resource_map_request args;
597d79b6b8eSJohn Baldwin struct pcie_range *range;
598d79b6b8eSJohn Baldwin rman_res_t length, start;
599d77f2092SJohn Baldwin int error, type;
600d79b6b8eSJohn Baldwin
601d77f2092SJohn Baldwin type = rman_get_type(r);
602d79b6b8eSJohn Baldwin switch (type) {
603d79b6b8eSJohn Baldwin case PCI_RES_BUS:
604d79b6b8eSJohn Baldwin return (EINVAL);
605d79b6b8eSJohn Baldwin case SYS_RES_IOPORT:
606d79b6b8eSJohn Baldwin case SYS_RES_MEMORY:
607d79b6b8eSJohn Baldwin break;
608d79b6b8eSJohn Baldwin default:
609d77f2092SJohn Baldwin return (bus_generic_map_resource(dev, child, r, argsp, map));
610d79b6b8eSJohn Baldwin }
611d79b6b8eSJohn Baldwin
612d79b6b8eSJohn Baldwin /* Resources must be active to be mapped. */
613d79b6b8eSJohn Baldwin if (!(rman_get_flags(r) & RF_ACTIVE))
614d79b6b8eSJohn Baldwin return (ENXIO);
615d79b6b8eSJohn Baldwin
616d79b6b8eSJohn Baldwin resource_init_map_request(&args);
617d79b6b8eSJohn Baldwin error = resource_validate_map_request(r, argsp, &args, &start, &length);
618d79b6b8eSJohn Baldwin if (error)
619d79b6b8eSJohn Baldwin return (error);
620d79b6b8eSJohn Baldwin
621d79b6b8eSJohn Baldwin range = generic_pcie_containing_range(dev, type, rman_get_start(r),
622d79b6b8eSJohn Baldwin rman_get_end(r));
623d79b6b8eSJohn Baldwin if (range == NULL || range->res == NULL)
624d79b6b8eSJohn Baldwin return (ENOENT);
625d79b6b8eSJohn Baldwin
626d79b6b8eSJohn Baldwin args.offset = start - range->pci_base;
627d79b6b8eSJohn Baldwin args.length = length;
62898056127SJohn Baldwin return (bus_map_resource(dev, range->res, &args, map));
629d79b6b8eSJohn Baldwin }
630d79b6b8eSJohn Baldwin
631d79b6b8eSJohn Baldwin static int
generic_pcie_unmap_resource(device_t dev,device_t child,struct resource * r,struct resource_map * map)632d77f2092SJohn Baldwin generic_pcie_unmap_resource(device_t dev, device_t child, struct resource *r,
633d77f2092SJohn Baldwin struct resource_map *map)
634d79b6b8eSJohn Baldwin {
635d79b6b8eSJohn Baldwin struct pcie_range *range;
636d77f2092SJohn Baldwin int type;
637d79b6b8eSJohn Baldwin
638d77f2092SJohn Baldwin type = rman_get_type(r);
639d79b6b8eSJohn Baldwin switch (type) {
640d79b6b8eSJohn Baldwin case PCI_RES_BUS:
641d79b6b8eSJohn Baldwin return (EINVAL);
642d79b6b8eSJohn Baldwin case SYS_RES_IOPORT:
643d79b6b8eSJohn Baldwin case SYS_RES_MEMORY:
644d79b6b8eSJohn Baldwin break;
645d79b6b8eSJohn Baldwin default:
646637ee139SEnji Cooper return (bus_generic_unmap_resource(dev, child, r, map));
647d79b6b8eSJohn Baldwin }
64898056127SJohn Baldwin
64998056127SJohn Baldwin range = generic_pcie_containing_range(dev, type, rman_get_start(r),
65098056127SJohn Baldwin rman_get_end(r));
65198056127SJohn Baldwin if (range == NULL || range->res == NULL)
65298056127SJohn Baldwin return (ENOENT);
65398056127SJohn Baldwin return (bus_unmap_resource(dev, range->res, map));
6549c22d3b1SRuslan Bukin }
6559c22d3b1SRuslan Bukin
6562760c2caSAndrew Turner static bus_dma_tag_t
generic_pcie_get_dma_tag(device_t dev,device_t child)6572760c2caSAndrew Turner generic_pcie_get_dma_tag(device_t dev, device_t child)
6582760c2caSAndrew Turner {
659f94f8e62SAndrew Turner struct generic_pcie_core_softc *sc;
6602760c2caSAndrew Turner
6612760c2caSAndrew Turner sc = device_get_softc(dev);
6622760c2caSAndrew Turner return (sc->dmat);
6632760c2caSAndrew Turner }
6642760c2caSAndrew Turner
6659c22d3b1SRuslan Bukin static device_method_t generic_pcie_methods[] = {
666f94f8e62SAndrew Turner DEVMETHOD(device_attach, pci_host_generic_core_attach),
667d843dd0eSAndrew Turner DEVMETHOD(device_detach, pci_host_generic_core_detach),
668d843dd0eSAndrew Turner
669d79b6b8eSJohn Baldwin DEVMETHOD(bus_get_rman, generic_pcie_get_rman),
6709c22d3b1SRuslan Bukin DEVMETHOD(bus_read_ivar, generic_pcie_read_ivar),
6719c22d3b1SRuslan Bukin DEVMETHOD(bus_write_ivar, generic_pcie_write_ivar),
672f94f8e62SAndrew Turner DEVMETHOD(bus_alloc_resource, pci_host_generic_core_alloc_resource),
6739c22d3b1SRuslan Bukin DEVMETHOD(bus_adjust_resource, generic_pcie_adjust_resource),
674bd158cddSJayachandran C. DEVMETHOD(bus_activate_resource, generic_pcie_activate_resource),
675bd158cddSJayachandran C. DEVMETHOD(bus_deactivate_resource, generic_pcie_deactivate_resource),
676f94f8e62SAndrew Turner DEVMETHOD(bus_release_resource, pci_host_generic_core_release_resource),
6770eb901f7SGreg V DEVMETHOD(bus_translate_resource, generic_pcie_translate_resource),
678d79b6b8eSJohn Baldwin DEVMETHOD(bus_map_resource, generic_pcie_map_resource),
679d79b6b8eSJohn Baldwin DEVMETHOD(bus_unmap_resource, generic_pcie_unmap_resource),
6809c22d3b1SRuslan Bukin DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
6819c22d3b1SRuslan Bukin DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
682c6b23b0aSAndrew Turner
6832760c2caSAndrew Turner DEVMETHOD(bus_get_dma_tag, generic_pcie_get_dma_tag),
6842760c2caSAndrew Turner
685c6b23b0aSAndrew Turner /* pcib interface */
6869c22d3b1SRuslan Bukin DEVMETHOD(pcib_maxslots, generic_pcie_maxslots),
6879c22d3b1SRuslan Bukin DEVMETHOD(pcib_read_config, generic_pcie_read_config),
6889c22d3b1SRuslan Bukin DEVMETHOD(pcib_write_config, generic_pcie_write_config),
689fb05500bSWojciech Macek
6909c22d3b1SRuslan Bukin DEVMETHOD_END
6919c22d3b1SRuslan Bukin };
6929c22d3b1SRuslan Bukin
693f94f8e62SAndrew Turner DEFINE_CLASS_0(pcib, generic_pcie_core_driver,
694f94f8e62SAndrew Turner generic_pcie_methods, sizeof(struct generic_pcie_core_softc));
695