2 * The PCI Library -- Direct Configuration access via PCIe ECAM
4 * Copyright (c) 2023 Pali Rohár <pali@kernel.org>
6 * Can be freely distributed and used under the terms of the GNU GPL v2+.
8 * SPDX-License-Identifier: GPL-2.0-or-later
12 * Tell 32-bit platforms that we are interested in 64-bit variant of off_t type
13 * as 32-bit variant of off_t type is signed and so it cannot represent all
14 * possible 32-bit offsets. It is required because off_t type is used by mmap().
16 #define _FILE_OFFSET_BITS 64
28 #include <sys/types.h>
33 #if defined (__FreeBSD__) || defined (__DragonFly__) || defined(__NetBSD__)
34 #include <sys/sysctl.h>
37 #if defined (__FreeBSD__) || defined (__DragonFly__)
42 #define OFF_MAX (off_t)((1ULL << (sizeof(off_t) * CHAR_BIT - 1)) - 1)
69 char asl_compiler_id[4];
70 u32 asl_compiler_revision;
96 get_rsdt_addresses_count(struct acpi_rsdt *rsdt)
98 return (rsdt->sdt.length - ((unsigned char*)&rsdt->sdt_addresses - (unsigned char *)rsdt)) / sizeof(rsdt->sdt_addresses[0]);
102 get_xsdt_addresses_count(struct acpi_xsdt *xsdt)
104 return (xsdt->sdt.length - ((unsigned char*)&xsdt->sdt_addresses - (unsigned char *)xsdt)) / sizeof(xsdt->sdt_addresses[0]);
108 get_mcfg_allocations_count(struct acpi_mcfg *mcfg)
110 return (mcfg->sdt.length - ((unsigned char *)&mcfg->allocations - (unsigned char *)mcfg)) / sizeof(mcfg->allocations[0]);
114 calculate_checksum(const u8 *bytes, int len)
119 checksum -= *(bytes++);
123 static struct acpi_sdt *
124 check_and_map_sdt(int fd, u64 addr, const char *signature, void **map_addr, u32 *map_length)
126 struct acpi_sdt *sdt;
127 char sdt_signature[sizeof(sdt->signature)];
131 if (addr > OFF_MAX - sizeof(*sdt))
134 map = mmap(NULL, sizeof(*sdt) + (addr & (pagesize-1)), PROT_READ, MAP_SHARED, fd, addr & ~(pagesize-1));
135 if (map == MAP_FAILED)
138 sdt = (struct acpi_sdt *)((unsigned char *)map + (addr & (pagesize-1)));
139 length = sdt->length;
140 memcpy(sdt_signature, sdt->signature, sizeof(sdt->signature));
142 munmap(map, sizeof(*sdt) + (addr & (pagesize-1)));
144 if (memcmp(sdt_signature, signature, sizeof(sdt_signature)) != 0)
146 if (length < sizeof(*sdt))
149 map = mmap(NULL, length + (addr & (pagesize-1)), PROT_READ, MAP_SHARED, fd, addr & ~(pagesize-1));
150 if (map == MAP_FAILED)
153 sdt = (struct acpi_sdt *)((unsigned char *)map + (addr & (pagesize-1)));
155 if (calculate_checksum((u8 *)sdt, sdt->length) != 0)
157 munmap(map, length + (addr & (pagesize-1)));
162 *map_length = length + (addr & (pagesize-1));
167 check_rsdp(struct acpi_rsdp *rsdp)
169 if (memcmp(rsdp->signature, "RSD PTR ", sizeof(rsdp->signature)) != 0)
171 if (calculate_checksum((u8 *)rsdp, sizeof(*rsdp)) != 0)
177 check_and_parse_rsdp(int fd, off_t addr, u32 *rsdt_address, u64 *xsdt_address)
179 struct acpi_rsdp *rsdp;
180 unsigned char buf[sizeof(*rsdp) + sizeof(*rsdp->rsdp20)];
183 map = mmap(NULL, sizeof(buf) + (addr & (pagesize-1)), PROT_READ, MAP_SHARED, fd, addr & ~(pagesize-1));
184 if (map == MAP_FAILED)
187 rsdp = (struct acpi_rsdp *)buf;
188 memcpy(rsdp, (unsigned char *)map + (addr & (pagesize-1)), sizeof(buf));
190 munmap(map, sizeof(buf));
192 if (!check_rsdp(rsdp))
195 *rsdt_address = rsdp->rsdt_address;
197 if (rsdp->revision != 0 &&
198 (*rsdp->rsdp20).length == sizeof(*rsdp) + sizeof(*rsdp->rsdp20) &&
199 calculate_checksum((u8 *)rsdp, (*rsdp->rsdp20).length) == 0)
200 *xsdt_address = (*rsdp->rsdp20).xsdt_address;
208 find_rsdp_address(struct pci_access *a, const char *efisystab, int use_bsd UNUSED, int use_x86bios UNUSED)
210 unsigned long long ullnum;
211 #if defined (__FreeBSD__) || defined (__DragonFly__) || defined(__NetBSD__)
218 #if defined(__amd64__) || defined(__i386__)
230 a->debug("reading EFI system table: %s...", efisystab);
231 f = fopen(efisystab, "r");
234 while (fgets(buf, sizeof(buf), f))
237 while (len > 0 && buf[len-1] == '\n')
239 if (strncmp(buf, "ACPI20=", 7) == 0 && isxdigit(buf[7]))
242 ullnum = strtoull(buf+7, &endptr, 16);
243 if (!errno && !*endptr && ullnum <= OFF_MAX)
246 else if (strncmp(buf, "ACPI=", 5) == 0 && isxdigit(buf[5]))
249 ullnum = strtoull(buf+5, &endptr, 16);
250 if (!errno && !*endptr && ullnum <= OFF_MAX)
263 #if defined (__FreeBSD__) || defined (__DragonFly__)
266 /* First try FreeBSD kenv hint.acpi.0.rsdp */
267 a->debug("calling kenv hint.acpi.0.rsdp...");
268 if (kenv(KENV_GET, "hint.acpi.0.rsdp", buf, sizeof(buf)) > 0)
271 ullnum = strtoull(buf, &endptr, 16);
272 if (!errno && !*endptr && ullnum <= OFF_MAX)
276 /* Then try FreeBSD sysctl machdep.acpi_root */
277 a->debug("calling sysctl machdep.acpi_root...");
279 if (sysctlbyname("machdep.acpi_root", &ulnum, &len, NULL, 0) == 0 && ulnum <= OFF_MAX)
284 #if defined(__NetBSD__)
287 /* Try NetBSD sysctl hw.acpi.root */
288 a->debug("calling sysctl hw.acpi.root...");
290 if (sysctlbyname("hw.acpi.root", &ulnum, &len, NULL, 0) == 0 && ulnum <= OFF_MAX)
295 #if defined(__amd64__) || defined(__i386__)
300 /* Scan first kB of Extended BIOS Data Area */
301 a->debug("scanning first kB of EBDA...");
302 map = mmap(NULL, 0x40E + 1024, PROT_READ, MAP_SHARED, a->fd, 0);
303 if (map != MAP_FAILED)
305 for (addr = 0x40E; addr < 0x40E + 1024; addr += 16)
307 if (check_rsdp((struct acpi_rsdp *)((unsigned char *)map + addr)))
313 munmap(map, 0x40E + 1024);
319 /* Scan the main BIOS area below 1 MB */
320 a->debug("scanning BIOS below 1 MB...");
321 map = mmap(NULL, 0x20000, PROT_READ, MAP_SHARED, a->fd, 0xE0000);
322 if (map != MAP_FAILED)
324 for (addr = 0x0; addr < 0x20000; addr += 16)
326 if (check_rsdp((struct acpi_rsdp *)((unsigned char *)map + addr)))
328 rsdp_addr = 0xE0000 + addr;
332 munmap(map, 0x20000);
343 static struct acpi_mcfg *
344 find_mcfg(struct pci_access *a, const char *acpimcfg, const char *efisystab, int use_bsd, int use_x86bios)
346 struct acpi_xsdt *xsdt;
347 struct acpi_rsdt *rsdt;
348 struct acpi_mcfg *mcfg;
349 struct acpi_sdt *sdt;
350 unsigned int i, count;
365 ret = glob(acpimcfg, GLOB_NOCHECK, NULL, &mcfg_glob);
368 a->debug("reading acpi mcfg file: %s...", mcfg_glob.gl_pathv[0]);
369 mcfg_fd = open(mcfg_glob.gl_pathv[0], O_RDONLY);
370 globfree(&mcfg_glob);
373 length = lseek(mcfg_fd, 0, SEEK_END);
374 if (length != (off_t)-1 && length > (off_t)sizeof(*mcfg))
376 lseek(mcfg_fd, 0, SEEK_SET);
377 mcfg = pci_malloc(a, length);
378 if (read(mcfg_fd, mcfg, length) == length &&
379 memcmp(mcfg->sdt.signature, "MCFG", 4) == 0 &&
380 mcfg->sdt.length <= length &&
381 calculate_checksum((u8 *)mcfg, mcfg->sdt.length) == 0)
389 a->debug("failed...");
392 a->debug("glob(%s) failed: %d...", acpimcfg, ret);
395 a->debug("searching for ACPI RSDP...");
396 rsdp_address = find_rsdp_address(a, efisystab, use_bsd, use_x86bios);
399 a->debug("not found...");
402 a->debug("found at 0x%llx...", (unsigned long long)rsdp_address);
404 if (!check_and_parse_rsdp(a->fd, rsdp_address, &rsdt_address, &xsdt_address))
406 a->debug("invalid...");
411 a->debug("searching for ACPI MCFG (XSDT=0x%llx, RSDT=0x%x)...", (unsigned long long)xsdt_address, rsdt_address);
413 xsdt = xsdt_address ? (struct acpi_xsdt *)check_and_map_sdt(a->fd, xsdt_address, "XSDT", &map_addr, &map_length) : NULL;
416 a->debug("via XSDT...");
417 count = get_xsdt_addresses_count(xsdt);
418 for (i = 0; i < count; i++)
420 sdt = check_and_map_sdt(a->fd, xsdt->sdt_addresses[i], "MCFG", &map2_addr, &map2_length);
423 mcfg = pci_malloc(a, sdt->length);
424 memcpy(mcfg, sdt, sdt->length);
425 munmap(map2_addr, map2_length);
429 munmap(map_addr, map_length);
432 a->debug("found...");
437 rsdt = (struct acpi_rsdt *)check_and_map_sdt(a->fd, rsdt_address, "RSDT", &map_addr, &map_length);
440 a->debug("via RSDT...");
441 count = get_rsdt_addresses_count(rsdt);
442 for (i = 0; i < count; i++)
444 sdt = check_and_map_sdt(a->fd, rsdt->sdt_addresses[i], "MCFG", &map2_addr, &map2_length);
447 mcfg = pci_malloc(a, sdt->length);
448 memcpy(mcfg, sdt, sdt->length);
449 munmap(map2_addr, map2_length);
453 munmap(map_addr, map_length);
456 a->debug("found...");
461 a->debug("not found...");
466 get_mcfg_allocation(struct acpi_mcfg *mcfg, unsigned int i, int *domain, u8 *start_bus, u8 *end_bus, off_t *addr, u32 *length)
468 int buses = (int)mcfg->allocations[i].end_bus_number - (int)mcfg->allocations[i].start_bus_number + 1;
471 *domain = mcfg->allocations[i].pci_segment;
473 *start_bus = mcfg->allocations[i].start_bus_number;
475 *end_bus = mcfg->allocations[i].end_bus_number;
477 *addr = mcfg->allocations[i].address;
479 *length = (buses > 0) ? (buses * 32 * 8 * 4096) : 0;
483 parse_next_addrs(const char *addrs, const char **next, int *domain, u8 *start_bus, u8 *end_bus, off_t *addr, u32 *length)
485 unsigned long long ullnum;
486 const char *sep1, *sep2;
491 unsigned long long start_addr;
500 endptr = strchr(addrs, ',');
502 addr_len = endptr - addrs;
504 addr_len = strlen(addrs);
507 *next = endptr ? (endptr+1) : NULL;
509 sep1 = memchr(addrs, ':', addr_len);
513 sep2 = memchr(sep1+1, ':', addr_len - (sep1+1 - addrs));
527 if (!isxdigit(*addrs))
530 num = strtol(addrs, &endptr, 16);
531 if (errno || endptr != sep1 || num < 0 || num > INT_MAX)
538 num = strtol(sep1 ? (sep1+1) : addrs, &endptr, 16);
539 if (errno || num < 0 || num > 0xff)
551 num = strtol(endptr+1, &endptr, 16);
552 if (errno || endptr != sep2 || num < 0 || num > 0xff)
554 buses = num - -buses + 1;
561 if (!isxdigit(*(sep2+1)))
565 ullnum = strtoull(sep2+1, &endptr, 16);
566 if (errno || (ullnum & 3) || ullnum > OFF_MAX)
572 if (endptr == addrs + addr_len)
576 buses = 0xff - -buses + 1;
580 if ((unsigned)buses * 32 * 8 * 4096 > OFF_MAX - start_addr)
583 *length = buses * 32 * 8 * 4096;
587 if (*endptr != '+' || !isxdigit(*(endptr+1)))
590 ullnum = strtoull(endptr+1, &endptr, 16);
591 if (errno || endptr != addrs + addr_len || (ullnum & 3) || ullnum > OFF_MAX || ullnum > 256 * 32 * 8 * 4096)
593 if (ullnum > OFF_MAX - start_addr)
595 if (buses > 0 && ullnum > (unsigned)buses * 32 * 8 * 4096)
597 if (buses <= 0 && ullnum > (0xff - (unsigned)-buses + 1) * 32 * 8 * 4096)
601 if (buses <= 0 && end_bus)
602 *end_bus = -buses + (ullnum + 32 * 8 * 4096 - 1) / (32 * 8 * 4096);
609 validate_addrs(const char *addrs)
615 if (!parse_next_addrs(addrs, &addrs, NULL, NULL, NULL, NULL, NULL))
622 calculate_bus_addr(u8 start_bus, off_t start_addr, u32 total_length, u8 bus, off_t *addr, u32 *length)
626 offset = 32*8*4096 * (bus - start_bus);
627 if (offset >= total_length)
630 *addr = start_addr + offset;
631 *length = total_length - offset;
633 if (*length > 32*8*4096)
640 get_bus_addr(struct acpi_mcfg *mcfg, const char *addrs, int domain, u8 bus, off_t *addr, u32 *length)
651 count = get_mcfg_allocations_count(mcfg);
652 for (i = 0; i < count; i++)
654 get_mcfg_allocation(mcfg, i, &cur_domain, &start_bus, &end_bus, &start_addr, &total_length);
655 if (domain == cur_domain && bus >= start_bus && bus <= end_bus)
656 return calculate_bus_addr(start_bus, start_addr, total_length, bus, addr, length);
664 if (!parse_next_addrs(addrs, &addrs, &cur_domain, &start_bus, &end_bus, &start_addr, &total_length))
666 if (domain == cur_domain && bus >= start_bus && bus <= end_bus)
667 return calculate_bus_addr(start_bus, start_addr, total_length, bus, addr, length);
683 // Back-end data linked to struct pci_access
686 struct acpi_mcfg *mcfg;
687 struct mmap_cache *cache;
691 munmap_reg(struct pci_access *a)
693 struct ecam_access *eacc = a->backend_data;
694 struct mmap_cache *cache = eacc->cache;
699 munmap(cache->map, cache->length + (cache->addr & (pagesize-1)));
705 mmap_reg(struct pci_access *a, int w, int domain, u8 bus, u8 dev, u8 func, int pos, volatile void **reg)
707 struct ecam_access *eacc = a->backend_data;
708 struct mmap_cache *cache = eacc->cache;
715 if (cache && cache->domain == domain && cache->bus == bus && !!cache->w == !!w)
719 length = cache->length;
723 addrs = pci_get_param(a, "ecam.addrs");
724 if (!get_bus_addr(eacc->mcfg, addrs, domain, bus, &addr, &length))
727 map = mmap(NULL, length + (addr & (pagesize-1)), w ? PROT_WRITE : PROT_READ, MAP_SHARED, a->fd, addr & ~(pagesize-1));
728 if (map == MAP_FAILED)
732 munmap(cache->map, cache->length + (cache->addr & (pagesize-1)));
734 cache = eacc->cache = pci_malloc(a, sizeof(*cache));
738 cache->length = length;
739 cache->domain = domain;
745 * Enhanced Configuration Access Mechanism (ECAM) offset according to:
746 * PCI Express Base Specification, Revision 5.0, Version 1.0, Section 7.2.2, Table 7-1, p. 677
748 offset = ((dev & 0x1f) << 15) | ((func & 0x7) << 12) | (pos & 0xfff);
750 if (offset + 4 > length)
753 *reg = (unsigned char *)map + (addr & (pagesize-1)) + offset;
758 writeb(unsigned char value, volatile void *addr)
760 *(volatile unsigned char *)addr = value;
764 writew(unsigned short value, volatile void *addr)
766 *(volatile unsigned short *)addr = value;
770 writel(unsigned int value, volatile void *addr)
772 *(volatile unsigned int *)addr = value;
776 readb(volatile void *addr)
778 return *(volatile unsigned char *)addr;
781 static unsigned short
782 readw(volatile void *addr)
784 return *(volatile unsigned short *)addr;
788 readl(volatile void *addr)
790 return *(volatile unsigned int *)addr;
794 ecam_config(struct pci_access *a)
796 pci_define_param(a, "devmem.path", PCI_PATH_DEVMEM_DEVICE, "Path to the /dev/mem device");
797 pci_define_param(a, "ecam.acpimcfg", PCI_PATH_ACPI_MCFG, "Path to the ACPI MCFG table");
798 pci_define_param(a, "ecam.efisystab", PCI_PATH_EFI_SYSTAB, "Path to the EFI system table");
799 #if defined (__FreeBSD__) || defined (__DragonFly__) || defined(__NetBSD__)
800 pci_define_param(a, "ecam.bsd", "1", "Use BSD kenv or sysctl to find ACPI MCFG table");
802 #if defined(__amd64__) || defined(__i386__)
803 pci_define_param(a, "ecam.x86bios", "1", "Scan x86 BIOS memory for ACPI MCFG table");
805 pci_define_param(a, "ecam.addrs", "", "Physical addresses of memory mapped PCIe ECAM interface"); /* format: [domain:]start_bus[-end_bus]:start_addr[+length],... */
809 ecam_detect(struct pci_access *a)
811 int use_addrs = 1, use_acpimcfg = 1, use_efisystab = 1, use_bsd = 1, use_x86bios = 1;
812 const char *devmem = pci_get_param(a, "devmem.path");
813 const char *acpimcfg = pci_get_param(a, "ecam.acpimcfg");
814 const char *efisystab = pci_get_param(a, "ecam.efisystab");
815 #if defined (__FreeBSD__) || defined (__DragonFly__) || defined(__NetBSD__)
816 const char *bsd = pci_get_param(a, "ecam.bsd");
818 #if defined(__amd64__) || defined(__i386__)
819 const char *x86bios = pci_get_param(a, "ecam.x86bios");
821 const char *addrs = pci_get_param(a, "ecam.addrs");
827 a->debug("ecam.addrs was not specified...");
833 ret = glob(acpimcfg, GLOB_NOCHECK, NULL, &mcfg_glob);
836 if (access(mcfg_glob.gl_pathv[0], R_OK))
838 a->debug("cannot access acpimcfg: %s: %s...", mcfg_glob.gl_pathv[0], strerror(errno));
841 globfree(&mcfg_glob);
845 a->debug("glob(%s) failed: %d...", acpimcfg, ret);
852 if (access(efisystab, R_OK))
855 a->debug("cannot access efisystab: %s: %s...", efisystab, strerror(errno));
859 #if defined (__FreeBSD__) || defined (__DragonFly__) || defined(__NetBSD__)
860 if (strcmp(bsd, "0") == 0)
862 a->debug("not using BSD kenv/sysctl...");
869 #if defined(__amd64__) || defined(__i386__)
870 if (strcmp(x86bios, "0") == 0)
872 a->debug("not using x86 BIOS...");
879 if (!use_addrs && !use_acpimcfg && !use_efisystab && !use_bsd && !use_x86bios)
881 a->debug("no ecam source provided");
885 if (!validate_addrs(addrs))
887 a->debug("ecam.addrs has invalid format %s", addrs);
891 if (access(devmem, R_OK))
893 a->debug("cannot access physical memory via %s: %s", devmem, strerror(errno));
898 a->debug("using %s with ecam addresses %s", devmem, addrs);
900 a->debug("using %s with%s%s%s%s%s%s", devmem, use_acpimcfg ? " acpimcfg=" : "", use_acpimcfg ? acpimcfg : "", use_efisystab ? " efisystab=" : "", use_efisystab ? efisystab : "", use_bsd ? " bsd" : "", use_x86bios ? " x86bios" : "");
906 ecam_init(struct pci_access *a)
908 const char *devmem = pci_get_param(a, "devmem.path");
909 const char *acpimcfg = pci_get_param(a, "ecam.acpimcfg");
910 const char *efisystab = pci_get_param(a, "ecam.efisystab");
911 #if defined (__FreeBSD__) || defined (__DragonFly__) || defined(__NetBSD__)
912 const char *bsd = pci_get_param(a, "ecam.bsd");
914 #if defined(__amd64__) || defined(__i386__)
915 const char *x86bios = pci_get_param(a, "ecam.x86bios");
917 const char *addrs = pci_get_param(a, "ecam.addrs");
918 struct acpi_mcfg *mcfg = NULL;
919 struct ecam_access *eacc = NULL;
924 volatile void *test_reg;
926 pagesize = sysconf(_SC_PAGESIZE);
928 a->error("Cannot get page size: %s.", strerror(errno));
930 if (!validate_addrs(addrs))
931 a->error("Option ecam.addrs has invalid address format \"%s\".", addrs);
933 a->fd = open(devmem, (a->writeable ? O_RDWR : O_RDONLY) | O_DSYNC);
935 a->error("Cannot open %s: %s.", devmem, strerror(errno));
939 #if defined (__FreeBSD__) || defined (__DragonFly__)
940 if (strcmp(bsd, "0") != 0)
943 #if defined(__amd64__) || defined(__i386__)
944 if (strcmp(x86bios, "0") != 0)
947 mcfg = find_mcfg(a, acpimcfg, efisystab, use_bsd, use_x86bios);
949 a->error("Option ecam.addrs was not specified and ACPI MCFG table cannot be found.");
952 eacc = pci_malloc(a, sizeof(*eacc));
955 a->backend_data = eacc;
958 get_mcfg_allocation(mcfg, 0, &test_domain, &test_bus, NULL, NULL, NULL);
960 parse_next_addrs(addrs, NULL, &test_domain, &test_bus, NULL, NULL, NULL);
963 if (!mmap_reg(a, 0, test_domain, test_bus, 0, 0, 0, &test_reg))
964 a->error("Cannot map ecam region: %s.", errno ? strerror(errno) : "Unknown error");
968 ecam_cleanup(struct pci_access *a)
970 struct ecam_access *eacc = a->backend_data;
976 pci_mfree(eacc->mcfg);
978 a->backend_data = NULL;
985 ecam_scan(struct pci_access *a)
987 const char *addrs = pci_get_param(a, "ecam.addrs");
988 struct ecam_access *eacc = a->backend_data;
993 segments = pci_malloc(a, 0xFFFF/8);
994 memset(segments, 0, 0xFFFF/8);
998 count = get_mcfg_allocations_count(eacc->mcfg);
999 for (i = 0; i < count; i++)
1000 segments[eacc->mcfg->allocations[i].pci_segment / 32] |= 1 << (eacc->mcfg->allocations[i].pci_segment % 32);
1006 if (parse_next_addrs(addrs, &addrs, &domain, NULL, NULL, NULL, NULL))
1007 segments[domain / 32] |= 1 << (domain % 32);
1011 for (i = 0; i < 0xFFFF/32; i++)
1015 for (j = 0; j < 32; j++)
1016 if (segments[i] & (1 << j))
1017 pci_generic_scan_domain(a, 32*i + j);
1020 pci_mfree(segments);
1024 ecam_read(struct pci_dev *d, int pos, byte *buf, int len)
1031 if (len != 1 && len != 2 && len != 4)
1032 return pci_generic_block_read(d, pos, buf, len);
1034 if (!mmap_reg(d->access, 0, d->domain, d->bus, d->dev, d->func, pos, ®))
1040 buf[0] = readb(reg);
1043 ((u16 *) buf)[0] = readw(reg);
1046 ((u32 *) buf)[0] = readl(reg);
1054 ecam_write(struct pci_dev *d, int pos, byte *buf, int len)
1061 if (len != 1 && len != 2 && len != 4)
1062 return pci_generic_block_read(d, pos, buf, len);
1064 if (!mmap_reg(d->access, 1, d->domain, d->bus, d->dev, d->func, pos, ®))
1070 writeb(buf[0], reg);
1073 writew(((u16 *) buf)[0], reg);
1076 writel(((u32 *) buf)[0], reg);
1083 struct pci_methods pm_ecam = {
1085 "Raw memory mapped access using PCIe ECAM interface",
1091 pci_generic_fill_info,
1094 NULL, /* read_vpd */
1095 NULL, /* init_dev */
1096 NULL /* cleanup_dev */