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
13 #include "physmem-access.h"
25 #if defined (__FreeBSD__) || defined (__DragonFly__) || defined(__NetBSD__)
26 #include <sys/sysctl.h>
29 #if defined (__FreeBSD__) || defined (__DragonFly__)
55 char asl_compiler_id[4];
56 u32 asl_compiler_revision;
90 // Back-end data linked to struct pci_access
92 struct acpi_mcfg *mcfg;
93 struct mmap_cache *cache;
94 struct physmem *physmem;
99 get_rsdt_addresses_count(struct acpi_rsdt *rsdt)
101 return (rsdt->sdt.length - ((unsigned char*)&rsdt->sdt_addresses - (unsigned char *)rsdt)) / sizeof(rsdt->sdt_addresses[0]);
105 get_xsdt_addresses_count(struct acpi_xsdt *xsdt)
107 return (xsdt->sdt.length - ((unsigned char*)&xsdt->sdt_addresses - (unsigned char *)xsdt)) / sizeof(xsdt->sdt_addresses[0]);
111 get_mcfg_allocations_count(struct acpi_mcfg *mcfg)
113 return (mcfg->sdt.length - ((unsigned char *)&mcfg->allocations - (unsigned char *)mcfg)) / sizeof(mcfg->allocations[0]);
117 calculate_checksum(const u8 *bytes, int len)
122 checksum -= *(bytes++);
126 static struct acpi_sdt *
127 check_and_map_sdt(struct physmem *physmem, long pagesize, u64 addr, const char *signature, void **map_addr, u32 *map_length)
129 struct acpi_sdt *sdt;
130 char sdt_signature[sizeof(sdt->signature)];
134 if (addr + sizeof(*sdt) < addr)
137 map = physmem_map(physmem, addr & ~(pagesize-1), sizeof(*sdt) + (addr & (pagesize-1)), 0);
138 if (map == (void *)-1)
141 sdt = (struct acpi_sdt *)((unsigned char *)map + (addr & (pagesize-1)));
142 length = sdt->length;
143 memcpy(sdt_signature, sdt->signature, sizeof(sdt->signature));
145 physmem_unmap(physmem, map, sizeof(*sdt) + (addr & (pagesize-1)));
147 if (memcmp(sdt_signature, signature, sizeof(sdt_signature)) != 0)
149 if (length < sizeof(*sdt))
152 map = physmem_map(physmem, addr & ~(pagesize-1), length + (addr & (pagesize-1)), 0);
153 if (map == (void *)-1)
156 sdt = (struct acpi_sdt *)((unsigned char *)map + (addr & (pagesize-1)));
158 if (calculate_checksum((u8 *)sdt, sdt->length) != 0)
160 physmem_unmap(physmem, map, length + (addr & (pagesize-1)));
165 *map_length = length + (addr & (pagesize-1));
170 check_rsdp(struct acpi_rsdp *rsdp)
172 if (memcmp(rsdp->signature, "RSD PTR ", sizeof(rsdp->signature)) != 0)
174 if (calculate_checksum((u8 *)rsdp, sizeof(*rsdp)) != 0)
180 check_and_parse_rsdp(struct physmem *physmem, long pagesize, u64 addr, u32 *rsdt_address, u64 *xsdt_address)
182 struct acpi_rsdp *rsdp;
183 unsigned char buf[sizeof(*rsdp) + sizeof(*rsdp->rsdp20)];
186 map = physmem_map(physmem, addr & ~(pagesize-1), sizeof(buf) + (addr & (pagesize-1)), 0);
187 if (map == (void *)-1)
190 rsdp = (struct acpi_rsdp *)buf;
191 memcpy(rsdp, (unsigned char *)map + (addr & (pagesize-1)), sizeof(buf));
193 physmem_unmap(physmem, map, sizeof(buf));
195 if (!check_rsdp(rsdp))
198 *rsdt_address = rsdp->rsdt_address;
200 if (rsdp->revision != 0 &&
201 (*rsdp->rsdp20).length == sizeof(*rsdp) + sizeof(*rsdp->rsdp20) &&
202 calculate_checksum((u8 *)rsdp, (*rsdp->rsdp20).length) == 0)
203 *xsdt_address = (*rsdp->rsdp20).xsdt_address;
211 find_rsdp_address(struct pci_access *a, const char *efisystab, int use_bsd UNUSED, int use_x86bios UNUSED)
214 #if defined (__FreeBSD__) || defined (__DragonFly__) || defined(__NetBSD__)
221 #if defined(__amd64__) || defined(__i386__)
222 struct ecam_access *eacc = a->backend_data;
223 struct physmem *physmem = eacc->physmem;
224 long pagesize = eacc->pagesize;
237 a->debug("reading EFI system table: %s...", efisystab);
238 f = fopen(efisystab, "r");
241 while (fgets(buf, sizeof(buf), f))
244 while (len > 0 && buf[len-1] == '\n')
246 if (strncmp(buf, "ACPI20=", 7) == 0 && isxdigit(buf[7]))
249 ullnum = strtoull(buf+7, &endptr, 16);
250 if (!errno && !*endptr)
253 else if (strncmp(buf, "ACPI=", 5) == 0 && isxdigit(buf[5]))
256 ullnum = strtoull(buf+5, &endptr, 16);
257 if (!errno && !*endptr)
264 a->debug("opening failed: %s...", strerror(errno));
272 #if defined (__FreeBSD__) || defined (__DragonFly__)
275 /* First try FreeBSD kenv hint.acpi.0.rsdp */
276 a->debug("calling kenv hint.acpi.0.rsdp...");
277 if (kenv(KENV_GET, "hint.acpi.0.rsdp", buf, sizeof(buf)) > 0)
280 ullnum = strtoull(buf, &endptr, 16);
281 if (!errno && !*endptr)
285 /* Then try FreeBSD sysctl machdep.acpi_root */
286 a->debug("calling sysctl machdep.acpi_root...");
288 if (sysctlbyname("machdep.acpi_root", &ulnum, &len, NULL, 0) == 0)
293 #if defined(__NetBSD__)
296 /* Try NetBSD sysctl hw.acpi.root */
297 a->debug("calling sysctl hw.acpi.root...");
299 if (sysctlbyname("hw.acpi.root", &ulnum, &len, NULL, 0) == 0)
304 #if defined(__amd64__) || defined(__i386__)
309 /* Scan first kB of Extended BIOS Data Area */
310 a->debug("reading EBDA location from BDA...");
311 map = physmem_map(physmem, 0, 0x40E + 2, 0);
312 if (map != (void *)-1)
314 ebda = (u64)physmem_readw((unsigned char *)map + 0x40E) << 4;
315 if (physmem_unmap(physmem, map, 0x40E + 2) != 0)
316 a->debug("unmapping of BDA failed: %s...", strerror(errno));
319 a->debug("scanning first kB of EBDA at 0x%" PCI_U64_FMT_X "...", ebda);
320 map = physmem_map(physmem, ebda & ~(pagesize-1), 1024 + (ebda & (pagesize-1)), 0);
321 if (map != (void *)-1)
323 for (addr = ebda & (pagesize-1); addr < (ebda & (pagesize-1)) + 1024; addr += 16)
325 if (check_rsdp((struct acpi_rsdp *)((unsigned char *)map + addr)))
327 rsdp_addr = (ebda & ~(pagesize-1)) + addr;
331 if (physmem_unmap(physmem, map, 1024 + (ebda & (pagesize-1))) != 0)
332 a->debug("unmapping of EBDA failed: %s...", strerror(errno));
335 a->debug("mapping of EBDA failed: %s...", strerror(errno));
338 a->debug("EBDA location 0x%" PCI_U64_FMT_X " is insane...", ebda);
341 a->debug("mapping of BDA failed: %s...", strerror(errno));
347 /* Scan the main BIOS area below 1 MB */
348 a->debug("scanning BIOS below 1 MB...");
349 map = physmem_map(physmem, 0xE0000, 0x20000, 0);
350 if (map != (void *)-1)
352 for (addr = 0x0; addr < 0x20000; addr += 16)
354 if (check_rsdp((struct acpi_rsdp *)((unsigned char *)map + addr)))
356 rsdp_addr = 0xE0000 + addr;
360 if (physmem_unmap(physmem, map, 0x20000) != 0)
361 a->debug("unmapping of BIOS failed: %s...", strerror(errno));
364 a->debug("mapping of BIOS failed: %s...", strerror(errno));
374 static struct acpi_mcfg *
375 find_mcfg(struct pci_access *a, const char *acpimcfg, const char *efisystab, int use_bsd, int use_x86bios)
377 struct ecam_access *eacc = a->backend_data;
378 struct physmem *physmem = eacc->physmem;
379 long pagesize = eacc->pagesize;
380 struct acpi_xsdt *xsdt;
381 struct acpi_rsdt *rsdt;
382 struct acpi_mcfg *mcfg;
383 struct acpi_sdt *sdt;
384 unsigned int i, count;
400 ret = glob(acpimcfg, GLOB_NOCHECK, NULL, &mcfg_glob);
403 path = mcfg_glob.gl_pathv[0];
404 a->debug("reading acpi mcfg file: %s...", path);
405 mcfg_file = fopen(path, "rb");
406 globfree(&mcfg_glob);
409 if (fseek(mcfg_file, 0, SEEK_END) == 0)
410 length = ftell(mcfg_file);
413 if (length > 0 && (size_t)length > sizeof(*mcfg))
416 mcfg = pci_malloc(a, length);
417 if (fread(mcfg, 1, length, mcfg_file) == (size_t)length &&
418 memcmp(mcfg->sdt.signature, "MCFG", 4) == 0 &&
419 mcfg->sdt.length <= (size_t)length &&
420 calculate_checksum((u8 *)mcfg, mcfg->sdt.length) == 0)
428 a->debug("failed...");
431 a->debug("glob(%s) failed: %d...", acpimcfg, ret);
434 a->debug("searching for ACPI RSDP...");
435 rsdp_address = find_rsdp_address(a, efisystab, use_bsd, use_x86bios);
438 a->debug("not found...");
441 a->debug("found at 0x%" PCI_U64_FMT_X "...", rsdp_address);
443 if (!check_and_parse_rsdp(physmem, pagesize, rsdp_address, &rsdt_address, &xsdt_address))
445 a->debug("invalid...");
450 a->debug("searching for ACPI MCFG (XSDT=0x%" PCI_U64_FMT_X ", RSDT=0x%lx)...", xsdt_address, (unsigned long)rsdt_address);
452 xsdt = xsdt_address ? (struct acpi_xsdt *)check_and_map_sdt(physmem, pagesize, xsdt_address, "XSDT", &map_addr, &map_length) : NULL;
455 a->debug("via XSDT...");
456 count = get_xsdt_addresses_count(xsdt);
457 for (i = 0; i < count; i++)
459 sdt = check_and_map_sdt(physmem, pagesize, xsdt->sdt_addresses[i], "MCFG", &map2_addr, &map2_length);
462 mcfg = pci_malloc(a, sdt->length);
463 memcpy(mcfg, sdt, sdt->length);
464 physmem_unmap(physmem, map2_addr, map2_length);
468 physmem_unmap(physmem, map_addr, map_length);
471 a->debug("found...");
476 rsdt = (struct acpi_rsdt *)check_and_map_sdt(physmem, pagesize, rsdt_address, "RSDT", &map_addr, &map_length);
479 a->debug("via RSDT...");
480 count = get_rsdt_addresses_count(rsdt);
481 for (i = 0; i < count; i++)
483 sdt = check_and_map_sdt(physmem, pagesize, rsdt->sdt_addresses[i], "MCFG", &map2_addr, &map2_length);
486 mcfg = pci_malloc(a, sdt->length);
487 memcpy(mcfg, sdt, sdt->length);
488 physmem_unmap(physmem, map2_addr, map2_length);
492 physmem_unmap(physmem, map_addr, map_length);
495 a->debug("found...");
500 a->debug("not found...");
505 get_mcfg_allocation(struct acpi_mcfg *mcfg, unsigned int i, int *domain, u8 *start_bus, u8 *end_bus, u64 *addr, u32 *length)
507 int buses = (int)mcfg->allocations[i].end_bus_number - (int)mcfg->allocations[i].start_bus_number + 1;
510 *domain = mcfg->allocations[i].pci_segment;
512 *start_bus = mcfg->allocations[i].start_bus_number;
514 *end_bus = mcfg->allocations[i].end_bus_number;
516 *addr = mcfg->allocations[i].address;
518 *length = (buses > 0) ? (buses * 32 * 8 * 4096) : 0;
522 parse_next_addrs(const char *addrs, const char **next, int *domain, u8 *start_bus, u8 *end_bus, u64 *addr, u32 *length)
525 const char *sep1, *sep2;
539 endptr = strchr(addrs, ',');
541 addr_len = endptr - addrs;
543 addr_len = strlen(addrs);
546 *next = endptr ? (endptr+1) : NULL;
548 sep1 = memchr(addrs, ':', addr_len);
552 sep2 = memchr(sep1+1, ':', addr_len - (sep1+1 - addrs));
566 if (!isxdigit(*addrs))
569 num = strtol(addrs, &endptr, 16);
570 if (errno || endptr != sep1 || num < 0 || num > INT_MAX)
577 num = strtol(sep1 ? (sep1+1) : addrs, &endptr, 16);
578 if (errno || num < 0 || num > 0xff)
590 num = strtol(endptr+1, &endptr, 16);
591 if (errno || endptr != sep2 || num < 0 || num > 0xff)
593 buses = num - -buses + 1;
600 if (!isxdigit(*(sep2+1)))
604 ullnum = strtoull(sep2+1, &endptr, 16);
605 if (errno || (ullnum & 3))
611 if (endptr == addrs + addr_len)
615 buses = 0xff - -buses + 1;
619 if (start_addr + (unsigned)buses * 32 * 8 * 4096 < start_addr)
622 *length = buses * 32 * 8 * 4096;
626 if (*endptr != '+' || !isxdigit(*(endptr+1)))
629 ullnum = strtoull(endptr+1, &endptr, 16);
630 if (errno || endptr != addrs + addr_len || (ullnum & 3) || ullnum > 256 * 32 * 8 * 4096)
632 if (start_addr + ullnum < start_addr)
634 if (buses > 0 && ullnum > (unsigned)buses * 32 * 8 * 4096)
636 if (buses <= 0 && ullnum > (0xff - (unsigned)-buses + 1) * 32 * 8 * 4096)
640 if (buses <= 0 && end_bus)
641 *end_bus = -buses + (ullnum + 32 * 8 * 4096 - 1) / (32 * 8 * 4096);
648 validate_addrs(const char *addrs)
654 if (!parse_next_addrs(addrs, &addrs, NULL, NULL, NULL, NULL, NULL))
661 calculate_bus_addr(u8 start_bus, u64 start_addr, u32 total_length, u8 bus, u64 *addr, u32 *length)
665 offset = 32*8*4096 * (bus - start_bus);
666 if (offset >= total_length)
669 *addr = start_addr + offset;
670 *length = total_length - offset;
672 if (*length > 32*8*4096)
679 get_bus_addr(struct acpi_mcfg *mcfg, const char *addrs, int domain, u8 bus, u64 *addr, u32 *length)
690 count = get_mcfg_allocations_count(mcfg);
691 for (i = 0; i < count; i++)
693 get_mcfg_allocation(mcfg, i, &cur_domain, &start_bus, &end_bus, &start_addr, &total_length);
694 if (domain == cur_domain && bus >= start_bus && bus <= end_bus)
695 return calculate_bus_addr(start_bus, start_addr, total_length, bus, addr, length);
703 if (!parse_next_addrs(addrs, &addrs, &cur_domain, &start_bus, &end_bus, &start_addr, &total_length))
705 if (domain == cur_domain && bus >= start_bus && bus <= end_bus)
706 return calculate_bus_addr(start_bus, start_addr, total_length, bus, addr, length);
713 munmap_reg(struct pci_access *a)
715 struct ecam_access *eacc = a->backend_data;
716 struct mmap_cache *cache = eacc->cache;
717 struct physmem *physmem = eacc->physmem;
718 long pagesize = eacc->pagesize;
723 physmem_unmap(physmem, cache->map, cache->length + (cache->addr & (pagesize-1)));
729 mmap_reg(struct pci_access *a, int w, int domain, u8 bus, u8 dev, u8 func, int pos, volatile void **reg)
731 struct ecam_access *eacc = a->backend_data;
732 struct mmap_cache *cache = eacc->cache;
733 struct physmem *physmem = eacc->physmem;
734 long pagesize = eacc->pagesize;
741 if (cache && cache->domain == domain && cache->bus == bus && !!cache->w == !!w)
745 length = cache->length;
749 addrs = pci_get_param(a, "ecam.addrs");
750 if (!get_bus_addr(eacc->mcfg, addrs, domain, bus, &addr, &length))
753 map = physmem_map(physmem, addr & ~(pagesize-1), length + (addr & (pagesize-1)), w);
754 if (map == (void *)-1)
758 physmem_unmap(physmem, cache->map, cache->length + (cache->addr & (pagesize-1)));
760 cache = eacc->cache = pci_malloc(a, sizeof(*cache));
764 cache->length = length;
765 cache->domain = domain;
771 * Enhanced Configuration Access Mechanism (ECAM) offset according to:
772 * PCI Express Base Specification, Revision 5.0, Version 1.0, Section 7.2.2, Table 7-1, p. 677
774 offset = ((dev & 0x1f) << 15) | ((func & 0x7) << 12) | (pos & 0xfff);
776 if (offset + 4 > length)
779 *reg = (unsigned char *)map + (addr & (pagesize-1)) + offset;
784 ecam_config(struct pci_access *a)
786 physmem_init_config(a);
787 pci_define_param(a, "ecam.acpimcfg", PCI_PATH_ACPI_MCFG, "Path to the ACPI MCFG table");
788 pci_define_param(a, "ecam.efisystab", PCI_PATH_EFI_SYSTAB, "Path to the EFI system table");
789 #if defined (__FreeBSD__) || defined (__DragonFly__) || defined(__NetBSD__)
790 pci_define_param(a, "ecam.bsd", "1", "Use BSD kenv or sysctl to find ACPI MCFG table");
792 #if defined(__amd64__) || defined(__i386__)
793 pci_define_param(a, "ecam.x86bios", "1", "Scan x86 BIOS memory for ACPI MCFG table");
795 pci_define_param(a, "ecam.addrs", "", "Physical addresses of memory mapped PCIe ECAM interface"); /* format: [domain:]start_bus[-end_bus]:start_addr[+length],... */
799 ecam_detect(struct pci_access *a)
801 int use_addrs = 1, use_acpimcfg = 1, use_efisystab = 1, use_bsd = 1, use_x86bios = 1;
802 const char *acpimcfg = pci_get_param(a, "ecam.acpimcfg");
803 const char *efisystab = pci_get_param(a, "ecam.efisystab");
804 #if defined (__FreeBSD__) || defined (__DragonFly__) || defined(__NetBSD__)
805 const char *bsd = pci_get_param(a, "ecam.bsd");
807 #if defined(__amd64__) || defined(__i386__)
808 const char *x86bios = pci_get_param(a, "ecam.x86bios");
810 const char *addrs = pci_get_param(a, "ecam.addrs");
811 struct ecam_access *eacc;
817 a->debug("ecam.addrs was not specified...");
823 ret = glob(acpimcfg, GLOB_NOCHECK, NULL, &mcfg_glob);
826 if (access(mcfg_glob.gl_pathv[0], R_OK))
828 a->debug("cannot access acpimcfg: %s: %s...", mcfg_glob.gl_pathv[0], strerror(errno));
831 globfree(&mcfg_glob);
835 a->debug("glob(%s) failed: %d...", acpimcfg, ret);
842 if (!efisystab[0] || access(efisystab, R_OK))
845 a->debug("cannot access efisystab: %s: %s...", efisystab, strerror(errno));
849 #if defined (__FreeBSD__) || defined (__DragonFly__) || defined(__NetBSD__)
850 if (strcmp(bsd, "0") == 0)
852 a->debug("not using BSD kenv/sysctl...");
859 #if defined(__amd64__) || defined(__i386__)
860 if (strcmp(x86bios, "0") == 0)
862 a->debug("not using x86 BIOS...");
869 if (!use_addrs && !use_acpimcfg && !use_efisystab && !use_bsd && !use_x86bios)
871 a->debug("no ecam source provided");
875 if (!validate_addrs(addrs))
877 a->debug("ecam.addrs has invalid format %s", addrs);
881 if (physmem_access(a, 0))
883 a->debug("cannot access physical memory: %s", strerror(errno));
889 eacc = pci_malloc(a, sizeof(*eacc));
891 eacc->physmem = physmem_open(a, a->writeable);
894 a->debug("cannot open physcal memory: %s.", strerror(errno));
899 eacc->pagesize = physmem_get_pagesize(eacc->physmem);
900 if (eacc->pagesize <= 0)
902 a->debug("Cannot get page size: %s.", strerror(errno));
903 physmem_close(eacc->physmem);
910 a->backend_data = eacc;
911 eacc->mcfg = find_mcfg(a, acpimcfg, efisystab, use_bsd, use_x86bios);
914 physmem_close(eacc->physmem);
916 a->backend_data = NULL;
922 a->debug("using with ecam addresses %s", addrs);
924 a->debug("using with%s%s%s%s%s%s", use_acpimcfg ? " acpimcfg=" : "", use_acpimcfg ? acpimcfg : "", use_efisystab ? " efisystab=" : "", use_efisystab ? efisystab : "", use_bsd ? " bsd" : "", use_x86bios ? " x86bios" : "");
930 ecam_init(struct pci_access *a)
932 const char *acpimcfg = pci_get_param(a, "ecam.acpimcfg");
933 const char *efisystab = pci_get_param(a, "ecam.efisystab");
934 #if defined (__FreeBSD__) || defined (__DragonFly__) || defined(__NetBSD__)
935 const char *bsd = pci_get_param(a, "ecam.bsd");
937 #if defined(__amd64__) || defined(__i386__)
938 const char *x86bios = pci_get_param(a, "ecam.x86bios");
940 const char *addrs = pci_get_param(a, "ecam.addrs");
941 struct physmem *physmem = NULL;
942 struct ecam_access *eacc = a->backend_data;
948 volatile void *test_reg;
950 if (!validate_addrs(addrs))
951 a->error("Option ecam.addrs has invalid address format \"%s\".", addrs);
955 physmem = physmem_open(a, a->writeable);
957 a->error("Cannot open physcal memory: %s.", strerror(errno));
959 pagesize = physmem_get_pagesize(physmem);
961 a->error("Cannot get page size: %s.", strerror(errno));
963 eacc = pci_malloc(a, sizeof(*eacc));
966 eacc->physmem = physmem;
967 eacc->pagesize = pagesize;
968 a->backend_data = eacc;
973 #if defined (__FreeBSD__) || defined (__DragonFly__)
974 if (strcmp(bsd, "0") != 0)
977 #if defined(__amd64__) || defined(__i386__)
978 if (strcmp(x86bios, "0") != 0)
982 eacc->mcfg = find_mcfg(a, acpimcfg, efisystab, use_bsd, use_x86bios);
984 a->error("Option ecam.addrs was not specified and ACPI MCFG table cannot be found.");
988 get_mcfg_allocation(eacc->mcfg, 0, &test_domain, &test_bus, NULL, NULL, NULL);
990 parse_next_addrs(addrs, NULL, &test_domain, &test_bus, NULL, NULL, NULL);
993 if (!mmap_reg(a, 0, test_domain, test_bus, 0, 0, 0, &test_reg))
994 a->error("Cannot map ecam region: %s.", errno ? strerror(errno) : "Unknown error");
998 ecam_cleanup(struct pci_access *a)
1000 struct ecam_access *eacc = a->backend_data;
1003 physmem_close(eacc->physmem);
1004 pci_mfree(eacc->mcfg);
1006 a->backend_data = NULL;
1010 ecam_scan(struct pci_access *a)
1012 const char *addrs = pci_get_param(a, "ecam.addrs");
1013 struct ecam_access *eacc = a->backend_data;
1018 segments = pci_malloc(a, 0xFFFF/8);
1019 memset(segments, 0, 0xFFFF/8);
1023 count = get_mcfg_allocations_count(eacc->mcfg);
1024 for (i = 0; i < count; i++)
1025 segments[eacc->mcfg->allocations[i].pci_segment / 32] |= 1 << (eacc->mcfg->allocations[i].pci_segment % 32);
1031 if (parse_next_addrs(addrs, &addrs, &domain, NULL, NULL, NULL, NULL))
1032 segments[domain / 32] |= 1 << (domain % 32);
1036 for (i = 0; i < 0xFFFF/32; i++)
1040 for (j = 0; j < 32; j++)
1041 if (segments[i] & (1 << j))
1042 pci_generic_scan_domain(a, 32*i + j);
1045 pci_mfree(segments);
1049 ecam_read(struct pci_dev *d, int pos, byte *buf, int len)
1056 if (len != 1 && len != 2 && len != 4)
1057 return pci_generic_block_read(d, pos, buf, len);
1059 if (!mmap_reg(d->access, 0, d->domain, d->bus, d->dev, d->func, pos, ®))
1065 buf[0] = physmem_readb(reg);
1068 ((u16 *) buf)[0] = physmem_readw(reg);
1071 ((u32 *) buf)[0] = physmem_readl(reg);
1079 ecam_write(struct pci_dev *d, int pos, byte *buf, int len)
1086 if (len != 1 && len != 2 && len != 4)
1087 return pci_generic_block_read(d, pos, buf, len);
1089 if (!mmap_reg(d->access, 1, d->domain, d->bus, d->dev, d->func, pos, ®))
1095 physmem_writeb(buf[0], reg);
1098 physmem_writew(((u16 *) buf)[0], reg);
1101 physmem_writel(((u32 *) buf)[0], reg);
1108 struct pci_methods pm_ecam = {
1110 .help = "Raw memory mapped access using PCIe ECAM interface",
1111 .config = ecam_config,
1112 .detect = ecam_detect,
1114 .cleanup = ecam_cleanup,
1116 .fill_info = pci_generic_fill_info,
1118 .write = ecam_write,