]> mj.ucw.cz Git - pciutils.git/blob - lib/ecam.c
libpci: Add constants for Lane Margining at the Receiver Extended Capability
[pciutils.git] / lib / ecam.c
1 /*
2  *      The PCI Library -- Direct Configuration access via PCIe ECAM
3  *
4  *      Copyright (c) 2023 Pali Rohár <pali@kernel.org>
5  *
6  *      Can be freely distributed and used under the terms of the GNU GPL v2+.
7  *
8  *      SPDX-License-Identifier: GPL-2.0-or-later
9  */
10
11 /*
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().
15  */
16 #define _FILE_OFFSET_BITS 64
17
18 #include "internal.h"
19
20 #include <ctype.h>
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <limits.h>
26
27 #include <sys/mman.h>
28 #include <sys/types.h>
29 #include <fcntl.h>
30 #include <glob.h>
31 #include <unistd.h>
32
33 #if defined (__FreeBSD__) || defined (__DragonFly__) || defined(__NetBSD__)
34 #include <sys/sysctl.h>
35 #endif
36
37 #if defined (__FreeBSD__) || defined (__DragonFly__)
38 #include <kenv.h>
39 #endif
40
41 #ifndef OFF_MAX
42 #define OFF_MAX (off_t)((1ULL << (sizeof(off_t) * CHAR_BIT - 1)) - 1)
43 #endif
44
45 static long pagesize;
46
47 struct acpi_rsdp {
48   char signature[8];
49   u8 checksum;
50   char oem_id[6];
51   u8 revision;
52   u32 rsdt_address;
53   struct {
54     u32 length;
55     u64 xsdt_address;
56     u8 ext_checksum;
57     u8 reserved[3];
58   } rsdp20[0];
59 } PCI_PACKED;
60
61 struct acpi_sdt {
62   char signature[4];
63   u32 length;
64   u8 revision;
65   u8 checksum;
66   char oem_id[6];
67   char oem_table_id[8];
68   u32 oem_revision;
69   char asl_compiler_id[4];
70   u32 asl_compiler_revision;
71 } PCI_PACKED;
72
73 struct acpi_rsdt {
74   struct acpi_sdt sdt;
75   u32 sdt_addresses[0];
76 } PCI_PACKED;
77
78 struct acpi_xsdt {
79   struct acpi_sdt sdt;
80   u64 sdt_addresses[0];
81 } PCI_PACKED;
82
83 struct acpi_mcfg {
84   struct acpi_sdt sdt;
85   u64 reserved;
86   struct {
87     u64 address;
88     u16 pci_segment;
89     u8 start_bus_number;
90     u8 end_bus_number;
91     u32 reserved;
92   } allocations[0];
93 } PCI_PACKED;
94
95 static unsigned int
96 get_rsdt_addresses_count(struct acpi_rsdt *rsdt)
97 {
98   return (rsdt->sdt.length - ((unsigned char*)&rsdt->sdt_addresses - (unsigned char *)rsdt)) / sizeof(rsdt->sdt_addresses[0]);
99 }
100
101 static unsigned int
102 get_xsdt_addresses_count(struct acpi_xsdt *xsdt)
103 {
104   return (xsdt->sdt.length - ((unsigned char*)&xsdt->sdt_addresses - (unsigned char *)xsdt)) / sizeof(xsdt->sdt_addresses[0]);
105 }
106
107 static unsigned int
108 get_mcfg_allocations_count(struct acpi_mcfg *mcfg)
109 {
110   return (mcfg->sdt.length - ((unsigned char *)&mcfg->allocations - (unsigned char *)mcfg)) / sizeof(mcfg->allocations[0]);
111 }
112
113 static u8
114 calculate_checksum(const u8 *bytes, int len)
115 {
116   u8 checksum = 0;
117
118   while (len-- > 0)
119     checksum -= *(bytes++);
120   return checksum;
121 }
122
123 static struct acpi_sdt *
124 check_and_map_sdt(int fd, u64 addr, const char *signature, void **map_addr, u32 *map_length)
125 {
126   struct acpi_sdt *sdt;
127   char sdt_signature[sizeof(sdt->signature)];
128   u32 length;
129   void *map;
130
131   if (addr > OFF_MAX - sizeof(*sdt))
132     return NULL;
133
134   map = mmap(NULL, sizeof(*sdt) + (addr & (pagesize-1)), PROT_READ, MAP_SHARED, fd, addr & ~(pagesize-1));
135   if (map == MAP_FAILED)
136     return NULL;
137
138   sdt = (struct acpi_sdt *)((unsigned char *)map + (addr & (pagesize-1)));
139   length = sdt->length;
140   memcpy(sdt_signature, sdt->signature, sizeof(sdt->signature));
141
142   munmap(map, sizeof(*sdt) + (addr & (pagesize-1)));
143
144   if (memcmp(sdt_signature, signature, sizeof(sdt_signature)) != 0)
145     return NULL;
146   if (length < sizeof(*sdt))
147     return NULL;
148
149   map = mmap(NULL, length + (addr & (pagesize-1)), PROT_READ, MAP_SHARED, fd, addr & ~(pagesize-1));
150   if (map == MAP_FAILED)
151     return NULL;
152
153   sdt = (struct acpi_sdt *)((unsigned char *)map + (addr & (pagesize-1)));
154
155   if (calculate_checksum((u8 *)sdt, sdt->length) != 0)
156     {
157       munmap(map, length + (addr & (pagesize-1)));
158       return NULL;
159     }
160
161   *map_addr = map;
162   *map_length = length + (addr & (pagesize-1));
163   return sdt;
164 }
165
166 static int
167 check_rsdp(struct acpi_rsdp *rsdp)
168 {
169   if (memcmp(rsdp->signature, "RSD PTR ", sizeof(rsdp->signature)) != 0)
170     return 0;
171   if (calculate_checksum((u8 *)rsdp, sizeof(*rsdp)) != 0)
172     return 0;
173   return 1;
174 }
175
176 static int
177 check_and_parse_rsdp(int fd, off_t addr, u32 *rsdt_address, u64 *xsdt_address)
178 {
179   struct acpi_rsdp *rsdp;
180   unsigned char buf[sizeof(*rsdp) + sizeof(*rsdp->rsdp20)];
181   void *map;
182
183   map = mmap(NULL, sizeof(buf) + (addr & (pagesize-1)), PROT_READ, MAP_SHARED, fd, addr & ~(pagesize-1));
184   if (map == MAP_FAILED)
185     return 0;
186
187   rsdp = (struct acpi_rsdp *)buf;
188   memcpy(rsdp, (unsigned char *)map + (addr & (pagesize-1)), sizeof(buf));
189
190   munmap(map, sizeof(buf));
191
192   if (!check_rsdp(rsdp))
193     return 0;
194
195   *rsdt_address = rsdp->rsdt_address;
196
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;
201   else
202     *xsdt_address = 0;
203
204   return 1;
205 }
206
207 static off_t
208 find_rsdp_address(struct pci_access *a, const char *efisystab, int use_bsd UNUSED, int use_x86bios UNUSED)
209 {
210   unsigned long long ullnum;
211 #if defined (__FreeBSD__) || defined (__DragonFly__) || defined(__NetBSD__)
212   unsigned long ulnum;
213 #endif
214   char buf[1024];
215   char *endptr;
216   off_t acpi20;
217   off_t acpi;
218 #if defined(__amd64__) || defined(__i386__)
219   off_t rsdp_addr;
220   off_t addr;
221   void *map;
222 #endif
223   size_t len;
224   FILE *f;
225
226   if (efisystab[0])
227     {
228       acpi = 0;
229       acpi20 = 0;
230       a->debug("reading EFI system table: %s...", efisystab);
231       f = fopen(efisystab, "r");
232       if (f)
233         {
234           while (fgets(buf, sizeof(buf), f))
235             {
236               len = strlen(buf);
237               while (len > 0 && buf[len-1] == '\n')
238                 buf[--len] = '\0';
239               if (strncmp(buf, "ACPI20=", 7) == 0 && isxdigit(buf[7]))
240                 {
241                   errno = 0;
242                   ullnum = strtoull(buf+7, &endptr, 16);
243                   if (!errno && !*endptr && ullnum <= OFF_MAX)
244                     acpi20 = ullnum;
245                 }
246               else if (strncmp(buf, "ACPI=", 5) == 0 && isxdigit(buf[5]))
247                 {
248                   errno = 0;
249                   ullnum = strtoull(buf+5, &endptr, 16);
250                   if (!errno && !*endptr && ullnum <= OFF_MAX)
251                     acpi = ullnum;
252                 }
253             }
254           fclose(f);
255         }
256
257       if (acpi20)
258         return acpi20;
259       else if (acpi)
260         return acpi;
261     }
262
263 #if defined (__FreeBSD__) || defined (__DragonFly__)
264   if (use_bsd)
265     {
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)
269         {
270           errno = 0;
271           ullnum = strtoull(buf, &endptr, 16);
272           if (!errno && !*endptr && ullnum <= OFF_MAX)
273             return ullnum;
274         }
275
276       /* Then try FreeBSD sysctl machdep.acpi_root */
277       a->debug("calling sysctl machdep.acpi_root...");
278       len = sizeof(ulnum);
279       if (sysctlbyname("machdep.acpi_root", &ulnum, &len, NULL, 0) == 0 && ulnum <= OFF_MAX)
280         return ulnum;
281     }
282 #endif
283
284 #if defined(__NetBSD__)
285   if (use_bsd)
286     {
287       /* Try NetBSD sysctl hw.acpi.root */
288       a->debug("calling sysctl hw.acpi.root...");
289       len = sizeof(ulnum);
290       if (sysctlbyname("hw.acpi.root", &ulnum, &len, NULL, 0) == 0 && ulnum <= OFF_MAX)
291         return ulnum;
292     }
293 #endif
294
295 #if defined(__amd64__) || defined(__i386__)
296   if (use_x86bios)
297     {
298       rsdp_addr = 0;
299
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)
304         {
305           for (addr = 0x40E; addr < 0x40E + 1024; addr += 16)
306             {
307               if (check_rsdp((struct acpi_rsdp *)((unsigned char *)map + addr)))
308                 {
309                   rsdp_addr = addr;
310                   break;
311                 }
312             }
313           munmap(map, 0x40E + 1024);
314         }
315
316       if (rsdp_addr)
317         return rsdp_addr;
318
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)
323         {
324           for (addr = 0x0; addr < 0x20000; addr += 16)
325             {
326               if (check_rsdp((struct acpi_rsdp *)((unsigned char *)map + addr)))
327                 {
328                   rsdp_addr = 0xE0000 + addr;
329                   break;
330                 }
331             }
332           munmap(map, 0x20000);
333         }
334
335       if (rsdp_addr)
336         return rsdp_addr;
337     }
338 #endif
339
340   return 0;
341 }
342
343 static struct acpi_mcfg *
344 find_mcfg(struct pci_access *a, const char *acpimcfg, const char *efisystab, int use_bsd, int use_x86bios)
345 {
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;
351   off_t rsdp_address;
352   u64 xsdt_address;
353   u32 rsdt_address;
354   void *map_addr;
355   u32 map_length;
356   void *map2_addr;
357   u32 map2_length;
358   off_t length;
359   int mcfg_fd;
360   glob_t mcfg_glob;
361   int ret;
362
363   if (acpimcfg[0])
364     {
365       ret = glob(acpimcfg, GLOB_NOCHECK, NULL, &mcfg_glob);
366       if (ret == 0)
367         {
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);
371           if (mcfg_fd >= 0)
372             {
373               length = lseek(mcfg_fd, 0, SEEK_END);
374               if (length != (off_t)-1 && length > (off_t)sizeof(*mcfg))
375                 {
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)
382                     {
383                       close(mcfg_fd);
384                       return mcfg;
385                     }
386                 }
387               close(mcfg_fd);
388             }
389           a->debug("failed...");
390         }
391       else
392         a->debug("glob(%s) failed: %d...", acpimcfg, ret);
393     }
394
395   a->debug("searching for ACPI RSDP...");
396   rsdp_address = find_rsdp_address(a, efisystab, use_bsd, use_x86bios);
397   if (!rsdp_address)
398     {
399       a->debug("not found...");
400       return NULL;
401     }
402   a->debug("found at 0x%llx...", (unsigned long long)rsdp_address);
403
404   if (!check_and_parse_rsdp(a->fd, rsdp_address, &rsdt_address, &xsdt_address))
405     {
406       a->debug("invalid...");
407       return NULL;
408     }
409
410   mcfg = NULL;
411   a->debug("searching for ACPI MCFG (XSDT=0x%llx, RSDT=0x%x)...", (unsigned long long)xsdt_address, rsdt_address);
412
413   xsdt = xsdt_address ? (struct acpi_xsdt *)check_and_map_sdt(a->fd, xsdt_address, "XSDT", &map_addr, &map_length) : NULL;
414   if (xsdt)
415     {
416       a->debug("via XSDT...");
417       count = get_xsdt_addresses_count(xsdt);
418       for (i = 0; i < count; i++)
419         {
420           sdt = check_and_map_sdt(a->fd, xsdt->sdt_addresses[i], "MCFG", &map2_addr, &map2_length);
421           if (sdt)
422             {
423               mcfg = pci_malloc(a, sdt->length);
424               memcpy(mcfg, sdt, sdt->length);
425               munmap(map2_addr, map2_length);
426               break;
427             }
428         }
429       munmap(map_addr, map_length);
430       if (mcfg)
431         {
432           a->debug("found...");
433           return mcfg;
434         }
435     }
436
437   rsdt = (struct acpi_rsdt *)check_and_map_sdt(a->fd, rsdt_address, "RSDT", &map_addr, &map_length);
438   if (rsdt)
439     {
440       a->debug("via RSDT...");
441       count = get_rsdt_addresses_count(rsdt);
442       for (i = 0; i < count; i++)
443         {
444           sdt = check_and_map_sdt(a->fd, rsdt->sdt_addresses[i], "MCFG", &map2_addr, &map2_length);
445           if (sdt)
446             {
447               mcfg = pci_malloc(a, sdt->length);
448               memcpy(mcfg, sdt, sdt->length);
449               munmap(map2_addr, map2_length);
450               break;
451             }
452         }
453       munmap(map_addr, map_length);
454       if (mcfg)
455         {
456           a->debug("found...");
457           return mcfg;
458         }
459     }
460
461   a->debug("not found...");
462   return NULL;
463 }
464
465 static void
466 get_mcfg_allocation(struct acpi_mcfg *mcfg, unsigned int i, int *domain, u8 *start_bus, u8 *end_bus, off_t *addr, u32 *length)
467 {
468   int buses = (int)mcfg->allocations[i].end_bus_number - (int)mcfg->allocations[i].start_bus_number + 1;
469
470   if (domain)
471     *domain = mcfg->allocations[i].pci_segment;
472   if (start_bus)
473     *start_bus = mcfg->allocations[i].start_bus_number;
474   if (end_bus)
475     *end_bus = mcfg->allocations[i].end_bus_number;
476   if (addr)
477     *addr = mcfg->allocations[i].address;
478   if (length)
479     *length = (buses > 0) ? (buses * 32 * 8 * 4096) : 0;
480 }
481
482 static int
483 parse_next_addrs(const char *addrs, const char **next, int *domain, u8 *start_bus, u8 *end_bus, off_t *addr, u32 *length)
484 {
485   unsigned long long ullnum;
486   const char *sep1, *sep2;
487   int addr_len;
488   char *endptr;
489   long num;
490   int buses;
491   unsigned long long start_addr;
492
493   if (!*addrs)
494     {
495       if (next)
496         *next = NULL;
497       return 0;
498     }
499
500   endptr = strchr(addrs, ',');
501   if (endptr)
502     addr_len = endptr - addrs;
503   else
504     addr_len = strlen(addrs);
505
506   if (next)
507     *next = endptr ? (endptr+1) : NULL;
508
509   sep1 = memchr(addrs, ':', addr_len);
510   if (!sep1)
511     return 0;
512
513   sep2 = memchr(sep1+1, ':', addr_len - (sep1+1 - addrs));
514   if (!sep2)
515     {
516       sep2 = sep1;
517       sep1 = NULL;
518     }
519
520   if (!sep1)
521     {
522       if (domain)
523         *domain = 0;
524     }
525   else
526     {
527       if (!isxdigit(*addrs))
528         return 0;
529       errno = 0;
530       num = strtol(addrs, &endptr, 16);
531       if (errno || endptr != sep1 || num < 0 || num > INT_MAX)
532         return 0;
533       if (domain)
534         *domain = num;
535     }
536
537   errno = 0;
538   num = strtol(sep1 ? (sep1+1) : addrs, &endptr, 16);
539   if (errno || num < 0 || num > 0xff)
540     return 0;
541   if (start_bus)
542     *start_bus = num;
543
544   buses = -num;
545
546   if (endptr != sep2)
547     {
548       if (*endptr != '-')
549         return 0;
550       errno = 0;
551       num = strtol(endptr+1, &endptr, 16);
552       if (errno || endptr != sep2 || num < 0 || num > 0xff)
553         return 0;
554       buses = num - -buses + 1;
555       if (buses <= 0)
556         return 0;
557       if (end_bus)
558         *end_bus = num;
559     }
560
561   if (!isxdigit(*(sep2+1)))
562     return 0;
563
564   errno = 0;
565   ullnum = strtoull(sep2+1, &endptr, 16);
566   if (errno || (ullnum & 3) || ullnum > OFF_MAX)
567     return 0;
568   if (addr)
569     *addr = ullnum;
570   start_addr = ullnum;
571
572   if (endptr == addrs + addr_len)
573     {
574       if (buses <= 0)
575         {
576           buses = 0xff - -buses + 1;
577           if (end_bus)
578             *end_bus = 0xff;
579         }
580       if ((unsigned)buses * 32 * 8 * 4096 > OFF_MAX - start_addr)
581         return 0;
582       if (length)
583         *length = buses * 32 * 8 * 4096;
584     }
585   else
586     {
587       if (*endptr != '+' || !isxdigit(*(endptr+1)))
588         return 0;
589       errno = 0;
590       ullnum = strtoull(endptr+1, &endptr, 16);
591       if (errno || endptr != addrs + addr_len || (ullnum & 3) || ullnum > OFF_MAX || ullnum > 256 * 32 * 8 * 4096)
592         return 0;
593       if (ullnum > OFF_MAX - start_addr)
594         return 0;
595       if (buses > 0 && ullnum > (unsigned)buses * 32 * 8 * 4096)
596         return 0;
597       if (buses <= 0 && ullnum > (0xff - (unsigned)-buses + 1) * 32 * 8 * 4096)
598         return 0;
599       if (length)
600         *length = ullnum;
601       if (buses <= 0 && end_bus)
602         *end_bus = -buses + (ullnum + 32 * 8 * 4096 - 1) / (32 * 8 * 4096);
603     }
604
605   return 1;
606 }
607
608 static int
609 validate_addrs(const char *addrs)
610 {
611   if (!*addrs)
612     return 1;
613
614   while (addrs)
615     if (!parse_next_addrs(addrs, &addrs, NULL, NULL, NULL, NULL, NULL))
616       return 0;
617
618   return 1;
619 }
620
621 static int
622 calculate_bus_addr(u8 start_bus, off_t start_addr, u32 total_length, u8 bus, off_t *addr, u32 *length)
623 {
624   u32 offset;
625
626   offset = 32*8*4096 * (bus - start_bus);
627   if (offset >= total_length)
628     return 0;
629
630   *addr = start_addr + offset;
631   *length = total_length - offset;
632
633   if (*length > 32*8*4096)
634     *length = 32*8*4096;
635
636   return 1;
637 }
638
639 static int
640 get_bus_addr(struct acpi_mcfg *mcfg, const char *addrs, int domain, u8 bus, off_t *addr, u32 *length)
641 {
642   int cur_domain;
643   u8 start_bus;
644   u8 end_bus;
645   off_t start_addr;
646   u32 total_length;
647   int i, count;
648
649   if (mcfg)
650     {
651       count = get_mcfg_allocations_count(mcfg);
652       for (i = 0; i < count; i++)
653         {
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);
657         }
658       return 0;
659     }
660   else
661     {
662       while (addrs)
663         {
664           if (!parse_next_addrs(addrs, &addrs, &cur_domain, &start_bus, &end_bus, &start_addr, &total_length))
665             return 0;
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);
668         }
669       return 0;
670     }
671 }
672
673 struct mmap_cache
674 {
675   void *map;
676   off_t addr;
677   u32 length;
678   int domain;
679   u8 bus;
680   int w;
681 };
682
683 // Back-end data linked to struct pci_access
684 struct ecam_access
685 {
686   struct acpi_mcfg *mcfg;
687   struct mmap_cache *cache;
688 };
689
690 static void
691 munmap_reg(struct pci_access *a)
692 {
693   struct ecam_access *eacc = a->backend_data;
694   struct mmap_cache *cache = eacc->cache;
695
696   if (!cache)
697     return;
698
699   munmap(cache->map, cache->length + (cache->addr & (pagesize-1)));
700   pci_mfree(cache);
701   eacc->cache = NULL;
702 }
703
704 static int
705 mmap_reg(struct pci_access *a, int w, int domain, u8 bus, u8 dev, u8 func, int pos, volatile void **reg)
706 {
707   struct ecam_access *eacc = a->backend_data;
708   struct mmap_cache *cache = eacc->cache;
709   const char *addrs;
710   void *map;
711   off_t addr;
712   u32 length;
713   u32 offset;
714
715   if (cache && cache->domain == domain && cache->bus == bus && !!cache->w == !!w)
716     {
717       map = cache->map;
718       addr = cache->addr;
719       length = cache->length;
720     }
721   else
722     {
723       addrs = pci_get_param(a, "ecam.addrs");
724       if (!get_bus_addr(eacc->mcfg, addrs, domain, bus, &addr, &length))
725         return 0;
726
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)
729         return 0;
730
731       if (cache)
732         munmap(cache->map, cache->length + (cache->addr & (pagesize-1)));
733       else
734         cache = eacc->cache = pci_malloc(a, sizeof(*cache));
735
736       cache->map = map;
737       cache->addr = addr;
738       cache->length = length;
739       cache->domain = domain;
740       cache->bus = bus;
741       cache->w = w;
742     }
743
744   /*
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
747    */
748   offset = ((dev & 0x1f) << 15) | ((func & 0x7) << 12) | (pos & 0xfff);
749
750   if (offset + 4 > length)
751     return 0;
752
753   *reg = (unsigned char *)map + (addr & (pagesize-1)) + offset;
754   return 1;
755 }
756
757 static void
758 writeb(unsigned char value, volatile void *addr)
759 {
760   *(volatile unsigned char *)addr = value;
761 }
762
763 static void
764 writew(unsigned short value, volatile void *addr)
765 {
766   *(volatile unsigned short *)addr = value;
767 }
768
769 static void
770 writel(unsigned int value, volatile void *addr)
771 {
772   *(volatile unsigned int *)addr = value;
773 }
774
775 static unsigned char
776 readb(volatile void *addr)
777 {
778   return *(volatile unsigned char *)addr;
779 }
780
781 static unsigned short
782 readw(volatile void *addr)
783 {
784   return *(volatile unsigned short *)addr;
785 }
786
787 static unsigned int
788 readl(volatile void *addr)
789 {
790   return *(volatile unsigned int *)addr;
791 }
792
793 static void
794 ecam_config(struct pci_access *a)
795 {
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");
801 #endif
802 #if defined(__amd64__) || defined(__i386__)
803   pci_define_param(a, "ecam.x86bios", "1", "Scan x86 BIOS memory for ACPI MCFG table");
804 #endif
805   pci_define_param(a, "ecam.addrs", "", "Physical addresses of memory mapped PCIe ECAM interface"); /* format: [domain:]start_bus[-end_bus]:start_addr[+length],... */
806 }
807
808 static int
809 ecam_detect(struct pci_access *a)
810 {
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");
817 #endif
818 #if defined(__amd64__) || defined(__i386__)
819   const char *x86bios = pci_get_param(a, "ecam.x86bios");
820 #endif
821   const char *addrs = pci_get_param(a, "ecam.addrs");
822   glob_t mcfg_glob;
823   int ret;
824
825   if (!*addrs)
826     {
827       a->debug("ecam.addrs was not specified...");
828       use_addrs = 0;
829     }
830
831   if (acpimcfg[0])
832     {
833       ret = glob(acpimcfg, GLOB_NOCHECK, NULL, &mcfg_glob);
834       if (ret == 0)
835         {
836           if (access(mcfg_glob.gl_pathv[0], R_OK))
837             {
838               a->debug("cannot access acpimcfg: %s: %s...", mcfg_glob.gl_pathv[0], strerror(errno));
839               use_acpimcfg = 0;
840             }
841           globfree(&mcfg_glob);
842         }
843       else
844         {
845           a->debug("glob(%s) failed: %d...", acpimcfg, ret);
846           use_acpimcfg = 0;
847         }
848     }
849   else
850     use_acpimcfg = 0;
851
852   if (access(efisystab, R_OK))
853     {
854       if (efisystab[0])
855         a->debug("cannot access efisystab: %s: %s...", efisystab, strerror(errno));
856       use_efisystab = 0;
857     }
858
859 #if defined (__FreeBSD__) || defined (__DragonFly__) || defined(__NetBSD__)
860   if (strcmp(bsd, "0") == 0)
861     {
862       a->debug("not using BSD kenv/sysctl...");
863       use_bsd = 0;
864     }
865 #else
866   use_bsd = 0;
867 #endif
868
869 #if defined(__amd64__) || defined(__i386__)
870   if (strcmp(x86bios, "0") == 0)
871     {
872       a->debug("not using x86 BIOS...");
873       use_x86bios = 0;
874     }
875 #else
876   use_x86bios = 0;
877 #endif
878
879   if (!use_addrs && !use_acpimcfg && !use_efisystab && !use_bsd && !use_x86bios)
880     {
881       a->debug("no ecam source provided");
882       return 0;
883     }
884
885   if (!validate_addrs(addrs))
886     {
887       a->debug("ecam.addrs has invalid format %s", addrs);
888       return 0;
889     }
890
891   if (access(devmem, R_OK))
892     {
893       a->debug("cannot access physical memory via %s: %s", devmem, strerror(errno));
894       return 0;
895     }
896
897   if (use_addrs)
898     a->debug("using %s with ecam addresses %s", devmem, addrs);
899   else
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" : "");
901
902   return 1;
903 }
904
905 static void
906 ecam_init(struct pci_access *a)
907 {
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");
913 #endif
914 #if defined(__amd64__) || defined(__i386__)
915   const char *x86bios = pci_get_param(a, "ecam.x86bios");
916 #endif
917   const char *addrs = pci_get_param(a, "ecam.addrs");
918   struct acpi_mcfg *mcfg = NULL;
919   struct ecam_access *eacc = NULL;
920   int use_bsd = 0;
921   int use_x86bios = 0;
922   int test_domain = 0;
923   u8 test_bus = 0;
924   volatile void *test_reg;
925
926   pagesize = sysconf(_SC_PAGESIZE);
927   if (pagesize < 0)
928     a->error("Cannot get page size: %s.", strerror(errno));
929
930   if (!validate_addrs(addrs))
931     a->error("Option ecam.addrs has invalid address format \"%s\".", addrs);
932
933   a->fd = open(devmem, (a->writeable ? O_RDWR : O_RDONLY) | O_DSYNC);
934   if (a->fd < 0)
935     a->error("Cannot open %s: %s.", devmem, strerror(errno));
936
937   if (!*addrs)
938     {
939 #if defined (__FreeBSD__) || defined (__DragonFly__)
940       if (strcmp(bsd, "0") != 0)
941         use_bsd = 1;
942 #endif
943 #if defined(__amd64__) || defined(__i386__)
944       if (strcmp(x86bios, "0") != 0)
945         use_x86bios = 1;
946 #endif
947       mcfg = find_mcfg(a, acpimcfg, efisystab, use_bsd, use_x86bios);
948       if (!mcfg)
949         a->error("Option ecam.addrs was not specified and ACPI MCFG table cannot be found.");
950     }
951
952   eacc = pci_malloc(a, sizeof(*eacc));
953   eacc->mcfg = mcfg;
954   eacc->cache = NULL;
955   a->backend_data = eacc;
956
957   if (mcfg)
958     get_mcfg_allocation(mcfg, 0, &test_domain, &test_bus, NULL, NULL, NULL);
959   else
960     parse_next_addrs(addrs, NULL, &test_domain, &test_bus, NULL, NULL, NULL);
961
962   errno = 0;
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");
965 }
966
967 static void
968 ecam_cleanup(struct pci_access *a)
969 {
970   struct ecam_access *eacc = a->backend_data;
971
972   if (a->fd < 0)
973     return;
974
975   munmap_reg(a);
976   pci_mfree(eacc->mcfg);
977   pci_mfree(eacc);
978   a->backend_data = NULL;
979
980   close(a->fd);
981   a->fd = -1;
982 }
983
984 static void
985 ecam_scan(struct pci_access *a)
986 {
987   const char *addrs = pci_get_param(a, "ecam.addrs");
988   struct ecam_access *eacc = a->backend_data;
989   u32 *segments;
990   int i, j, count;
991   int domain;
992
993   segments = pci_malloc(a, 0xFFFF/8);
994   memset(segments, 0, 0xFFFF/8);
995
996   if (eacc->mcfg)
997     {
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);
1001     }
1002   else
1003     {
1004       while (addrs)
1005         {
1006           if (parse_next_addrs(addrs, &addrs, &domain, NULL, NULL, NULL, NULL))
1007             segments[domain / 32] |= 1 << (domain % 32);
1008         }
1009     }
1010
1011   for (i = 0; i < 0xFFFF/32; i++)
1012     {
1013       if (!segments[i])
1014         continue;
1015       for (j = 0; j < 32; j++)
1016         if (segments[i] & (1 << j))
1017           pci_generic_scan_domain(a, 32*i + j);
1018     }
1019
1020   pci_mfree(segments);
1021 }
1022
1023 static int
1024 ecam_read(struct pci_dev *d, int pos, byte *buf, int len)
1025 {
1026   volatile void *reg;
1027
1028   if (pos >= 4096)
1029     return 0;
1030
1031   if (len != 1 && len != 2 && len != 4)
1032     return pci_generic_block_read(d, pos, buf, len);
1033
1034   if (!mmap_reg(d->access, 0, d->domain, d->bus, d->dev, d->func, pos, &reg))
1035     return 0;
1036
1037   switch (len)
1038     {
1039     case 1:
1040       buf[0] = readb(reg);
1041       break;
1042     case 2:
1043       ((u16 *) buf)[0] = readw(reg);
1044       break;
1045     case 4:
1046       ((u32 *) buf)[0] = readl(reg);
1047       break;
1048     }
1049
1050   return 1;
1051 }
1052
1053 static int
1054 ecam_write(struct pci_dev *d, int pos, byte *buf, int len)
1055 {
1056   volatile void *reg;
1057
1058   if (pos >= 4096)
1059     return 0;
1060
1061   if (len != 1 && len != 2 && len != 4)
1062     return pci_generic_block_read(d, pos, buf, len);
1063
1064   if (!mmap_reg(d->access, 1, d->domain, d->bus, d->dev, d->func, pos, &reg))
1065     return 0;
1066
1067   switch (len)
1068     {
1069     case 1:
1070       writeb(buf[0], reg);
1071       break;
1072     case 2:
1073       writew(((u16 *) buf)[0], reg);
1074       break;
1075     case 4:
1076       writel(((u32 *) buf)[0], reg);
1077       break;
1078     }
1079
1080   return 1;
1081 }
1082
1083 struct pci_methods pm_ecam = {
1084   "ecam",
1085   "Raw memory mapped access using PCIe ECAM interface",
1086   ecam_config,
1087   ecam_detect,
1088   ecam_init,
1089   ecam_cleanup,
1090   ecam_scan,
1091   pci_generic_fill_info,
1092   ecam_read,
1093   ecam_write,
1094   NULL,                                 /* read_vpd */
1095   NULL,                                 /* init_dev */
1096   NULL                                  /* cleanup_dev */
1097 };