1 /*        $NetBSD: pci_map.c,v 1.44 2020/12/29 15:49:45 skrll Exp $   */
2 
3 /*-
4  * Copyright (c) 1998, 2000, 2020 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Charles M. Hannum; by William R. Studenmund; by Jason R. Thorpe.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * PCI device mapping.
34  */
35 
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: pci_map.c,v 1.44 2020/12/29 15:49:45 skrll Exp $");
38 
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/device.h>
42 
43 #include <dev/pci/pcireg.h>
44 #include <dev/pci/pcivar.h>
45 
46 bool pci_mapreg_map_enable_decode = true;
47 
48 static int
pci_io_find(pci_chipset_tag_t pc,pcitag_t tag,int reg,pcireg_t type,bus_addr_t * basep,bus_size_t * sizep,int * flagsp)49 pci_io_find(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t type,
50     bus_addr_t *basep, bus_size_t *sizep, int *flagsp)
51 {
52           pcireg_t address, mask, csr;
53           int s;
54 
55           if (reg < PCI_MAPREG_START ||
56 #if 0
57               /*
58                * Can't do this check; some devices have mapping registers
59                * way out in left field.
60                */
61               reg >= PCI_MAPREG_END ||
62 #endif
63               (reg & 3))
64                     panic("pci_io_find: bad request");
65 
66           /*
67            * Section 6.2.5.1, `Address Maps', tells us that:
68            *
69            * 1) The builtin software should have already mapped the device in a
70            * reasonable way.
71            *
72            * 2) A device which wants 2^n bytes of memory will hardwire the bottom
73            * n bits of the address to 0.  As recommended, we write all 1s and see
74            * what we get back.
75            */
76           s = splhigh();
77           address = pci_conf_read(pc, tag, reg);
78           /*
79            * Disable decoding via the command register before writing to the
80            * BAR register. Changing the decoding address to all-one is
81            * not a valid address and could have side effects.
82            */
83           csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
84           pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG,
85               csr & ~PCI_COMMAND_IO_ENABLE) ;
86           pci_conf_write(pc, tag, reg, 0xffffffff);
87           mask = pci_conf_read(pc, tag, reg);
88           pci_conf_write(pc, tag, reg, address);
89           pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
90           splx(s);
91 
92           if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_IO) {
93                     aprint_debug("pci_io_find: expected type i/o, found mem\n");
94                     return 1;
95           }
96 
97           if (PCI_MAPREG_IO_SIZE(mask) == 0) {
98                     aprint_debug("pci_io_find: void region\n");
99                     return 1;
100           }
101 
102           if (basep != NULL)
103                     *basep = PCI_MAPREG_IO_ADDR(address);
104           if (sizep != NULL)
105                     *sizep = PCI_MAPREG_IO_SIZE(mask);
106           if (flagsp != NULL)
107                     *flagsp = 0;
108 
109           return 0;
110 }
111 
112 static int
pci_mem_find(pci_chipset_tag_t pc,pcitag_t tag,int reg,pcireg_t type,bus_addr_t * basep,bus_size_t * sizep,int * flagsp)113 pci_mem_find(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t type,
114     bus_addr_t *basep, bus_size_t *sizep, int *flagsp)
115 {
116           pcireg_t address, mask, address1 = 0, mask1 = 0xffffffff;
117           uint64_t waddress, wmask;
118           int s, is64bit, isrom;
119           pcireg_t csr;
120 
121           is64bit = (PCI_MAPREG_MEM_TYPE(type) == PCI_MAPREG_MEM_TYPE_64BIT);
122           isrom = (reg == PCI_MAPREG_ROM);
123 
124           if ((!isrom) && (reg < PCI_MAPREG_START ||
125 #if 0
126               /*
127                * Can't do this check; some devices have mapping registers
128                * way out in left field.
129                */
130               reg >= PCI_MAPREG_END ||
131 #endif
132               (reg & 3)))
133                     panic("pci_mem_find: bad request");
134 
135           if (is64bit && (reg + 4) >= PCI_MAPREG_END)
136                     panic("pci_mem_find: bad 64-bit request");
137 
138           /*
139            * Section 6.2.5.1, `Address Maps', tells us that:
140            *
141            * 1) The builtin software should have already mapped the device in a
142            * reasonable way.
143            *
144            * 2) A device which wants 2^n bytes of memory will hardwire the bottom
145            * n bits of the address to 0.  As recommended, we write all 1s and see
146            * what we get back.  Only probe the upper BAR of a mem64 BAR if bit 31
147            * is readonly.
148            */
149           s = splhigh();
150           address = pci_conf_read(pc, tag, reg);
151           csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
152           /*
153            * Disable decoding via the command register before writing to the
154            * BAR register. Changing the decoding address to all-one is
155            * not a valid address and could have side effects.
156            */
157           pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG,
158               csr & ~PCI_COMMAND_MEM_ENABLE) ;
159           pci_conf_write(pc, tag, reg, 0xffffffff);
160           mask = pci_conf_read(pc, tag, reg);
161           pci_conf_write(pc, tag, reg, address);
162           if (is64bit) {
163                     address1 = pci_conf_read(pc, tag, reg + 4);
164                     if ((mask & 0x80000000) == 0) {
165                               pci_conf_write(pc, tag, reg + 4, 0xffffffff);
166                               mask1 = pci_conf_read(pc, tag, reg + 4);
167                               pci_conf_write(pc, tag, reg + 4, address1);
168                     }
169           }
170           pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
171           splx(s);
172 
173           if (!isrom) {
174                     /*
175                      * roms should have an enable bit instead of a memory
176                      * type decoder bit.  For normal BARs, make sure that
177                      * the address decoder type matches what we asked for.
178                      */
179                     if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_MEM) {
180                               printf("pci_mem_find: expected type mem, found i/o\n");
181                               return 1;
182                     }
183                     /* XXX Allow 64bit bars for 32bit requests.*/
184                     if (PCI_MAPREG_MEM_TYPE(address) !=
185                         PCI_MAPREG_MEM_TYPE(type) &&
186                         PCI_MAPREG_MEM_TYPE(address) !=
187                         PCI_MAPREG_MEM_TYPE_64BIT) {
188                               printf("pci_mem_find: "
189                                   "expected mem type %08x, found %08x\n",
190                                   PCI_MAPREG_MEM_TYPE(type),
191                                   PCI_MAPREG_MEM_TYPE(address));
192                               return 1;
193                     }
194           }
195 
196           waddress = (uint64_t)address1 << 32UL | address;
197           wmask = (uint64_t)mask1 << 32UL | mask;
198 
199           if ((is64bit && PCI_MAPREG_MEM64_SIZE(wmask) == 0) ||
200               (!is64bit && PCI_MAPREG_MEM_SIZE(mask) == 0)) {
201                     aprint_debug("pci_mem_find: void region\n");
202                     return 1;
203           }
204 
205           switch (PCI_MAPREG_MEM_TYPE(address)) {
206           case PCI_MAPREG_MEM_TYPE_32BIT:
207           case PCI_MAPREG_MEM_TYPE_32BIT_1M:
208                     break;
209           case PCI_MAPREG_MEM_TYPE_64BIT:
210                     /*
211                      * Handle the case of a 64-bit memory register on a
212                      * platform with 32-bit addressing.  Make sure that
213                      * the address assigned and the device's memory size
214                      * fit in 32 bits.  We implicitly assume that if
215                      * bus_addr_t is 64-bit, then so is bus_size_t.
216                      */
217                     if (sizeof(uint64_t) > sizeof(bus_addr_t) &&
218                         (address1 != 0 || mask1 != 0xffffffff)) {
219                               printf("pci_mem_find: 64-bit memory map which is "
220                                   "inaccessible on a 32-bit platform\n");
221                               return 1;
222                     }
223                     break;
224           default:
225                     printf("pci_mem_find: reserved mapping register type\n");
226                     return 1;
227           }
228 
229           if (sizeof(uint64_t) > sizeof(bus_addr_t)) {
230                     if (basep != NULL)
231                               *basep = PCI_MAPREG_MEM_ADDR(address);
232                     if (sizep != NULL)
233                               *sizep = PCI_MAPREG_MEM_SIZE(mask);
234           } else {
235                     if (basep != NULL)
236                               *basep = PCI_MAPREG_MEM64_ADDR(waddress);
237                     if (sizep != NULL)
238                               *sizep = PCI_MAPREG_MEM64_SIZE(wmask);
239           }
240           if (flagsp != NULL)
241                     *flagsp = (isrom || PCI_MAPREG_MEM_PREFETCHABLE(address)) ?
242                         BUS_SPACE_MAP_PREFETCHABLE : 0;
243 
244           return 0;
245 }
246 
247 static const char *
bar_type_string(pcireg_t type)248 bar_type_string(pcireg_t type)
249 {
250           if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO)
251                     return "IO";
252 
253           switch (PCI_MAPREG_MEM_TYPE(type)) {
254           case PCI_MAPREG_MEM_TYPE_32BIT:
255                     return "MEM32";
256           case PCI_MAPREG_MEM_TYPE_32BIT_1M:
257                     return "MEM32-1M";
258           case PCI_MAPREG_MEM_TYPE_64BIT:
259                     return "MEM64";
260           }
261           return "<UNKNOWN>";
262 }
263 
264 enum {
265           EA_ptr_dw0                    = 0,
266           EA_ptr_base_lower   = 1,
267           EA_ptr_base_upper   = 2,
268           EA_ptr_maxoffset_lower        = 3,
269           EA_ptr_maxoffset_upper        = 4,
270 
271           EA_PTR_COUNT                  = 5
272 };
273 
274 struct pci_ea_entry {
275           /* entry field pointers */
276           int                 ea_ptrs[EA_PTR_COUNT];
277 
278           /* Raw register values. */
279           pcireg_t  dw0;
280           pcireg_t  base_lower;
281           pcireg_t  base_upper;
282           pcireg_t  maxoffset_lower;
283           pcireg_t  maxoffset_upper;
284 
285           /* Interesting tidbits derived from them. */
286           uint64_t  base;
287           uint64_t  maxoffset;
288           unsigned int        bei;
289           unsigned int        props[2];
290           bool                base_is_64;
291           bool                maxoffset_is_64;
292           bool                enabled;
293           bool                writable;
294 };
295 
296 static int
pci_ea_lookup(pci_chipset_tag_t pc,pcitag_t tag,int ea_cap_ptr,int reg,struct pci_ea_entry * entryp)297 pci_ea_lookup(pci_chipset_tag_t pc, pcitag_t tag, int ea_cap_ptr,
298     int reg, struct pci_ea_entry *entryp)
299 {
300           struct pci_ea_entry entry = {
301                     .ea_ptrs[EA_ptr_dw0] = ea_cap_ptr + 4,
302           };
303           unsigned int i, num_entries;
304           unsigned int wanted_bei;
305           pcireg_t val;
306 
307           if (reg >= PCI_BAR0 && reg <= PCI_BAR5)
308                     wanted_bei = PCI_EA_BEI_BAR0 + ((reg - PCI_BAR0) / 4);
309           else if (reg == PCI_MAPREG_ROM)
310                     wanted_bei = PCI_EA_BEI_EXPROM;
311           else {
312                     /* Invalid BAR. */
313                     return 1;
314           }
315 
316           val = pci_conf_read(pc, tag, ea_cap_ptr + PCI_EA_CAP1);
317           num_entries = __SHIFTOUT(val, PCI_EA_CAP1_NUMENTRIES);
318 
319           val = pci_conf_read(pc, tag, PCI_BHLC_REG);
320           if (PCI_HDRTYPE_TYPE(val) == PCI_HDRTYPE_PPB) {
321                     /* Need to skip over PCI_EA_CAP2 on PPBs. */
322                     entry.ea_ptrs[EA_ptr_dw0] += 4;
323           }
324 
325           for (i = 0; i < num_entries; i++) {
326                     val = pci_conf_read(pc, tag, entry.ea_ptrs[EA_ptr_dw0]);
327                     unsigned int entry_size = __SHIFTOUT(val, PCI_EA_ES);
328 
329                     entry.bei = __SHIFTOUT(val, PCI_EA_BEI);
330                     entry.props[0] = __SHIFTOUT(val, PCI_EA_PP);
331                     entry.props[1] = __SHIFTOUT(val, PCI_EA_SP);
332                     entry.writable = (val & PCI_EA_W) ? true : false;
333                     entry.enabled = (val & PCI_EA_E) ? true : false;
334 
335                     if (entry.bei != wanted_bei || entry_size == 0) {
336                               entry.ea_ptrs[EA_ptr_dw0] += 4 * (entry_size + 1);
337                               continue;
338                     }
339 
340                     entry.ea_ptrs[EA_ptr_base_lower] =
341                         entry.ea_ptrs[EA_ptr_dw0] + 4;
342                     entry.ea_ptrs[EA_ptr_maxoffset_lower] =
343                         entry.ea_ptrs[EA_ptr_dw0] + 8;
344 
345                     /* Base */
346                     entry.base_lower = pci_conf_read(pc, tag,
347                         entry.ea_ptrs[EA_ptr_base_lower]);
348                     entry.base_is_64 =
349                         (entry.base_lower & PCI_EA_BASEMAXOFFSET_64BIT)
350                         ? true : false;
351                     if (entry.base_is_64) {
352                               entry.ea_ptrs[EA_ptr_base_upper] =
353                                   entry.ea_ptrs[EA_ptr_dw0] + 12;
354                               entry.base_upper = pci_conf_read(pc, tag,
355                                   entry.ea_ptrs[EA_ptr_base_upper]);
356                     } else {
357                               entry.ea_ptrs[EA_ptr_base_upper] = 0;
358                               entry.base_upper = 0;
359                     }
360 
361                     entry.base = (entry.base_lower & PCI_EA_LOWMASK) |
362                         ((uint64_t)entry.base_upper << 32);
363 
364                     /* MaxOffset */
365                     entry.maxoffset_lower = pci_conf_read(pc, tag,
366                         entry.ea_ptrs[EA_ptr_maxoffset_lower]);
367                     entry.maxoffset_is_64 =
368                         (entry.maxoffset_lower & PCI_EA_BASEMAXOFFSET_64BIT)
369                         ? true : false;
370                     if (entry.maxoffset_is_64) {
371                               entry.ea_ptrs[EA_ptr_maxoffset_upper] =
372                                   entry.ea_ptrs[EA_ptr_dw0] +
373                                   (entry.base_is_64 ? 16 : 12);
374                               entry.maxoffset_upper = pci_conf_read(pc, tag,
375                                   entry.ea_ptrs[EA_ptr_maxoffset_upper]);
376                     } else {
377                               entry.ea_ptrs[EA_ptr_maxoffset_upper] = 0;
378                               entry.maxoffset_upper = 0;
379                     }
380 
381                     entry.maxoffset = (entry.maxoffset_lower & PCI_EA_LOWMASK) |
382                         ((uint64_t)entry.maxoffset_upper << 32);
383 
384                     if (entryp)
385                               *entryp = entry;
386                     return 0;
387           }
388           return 1;
389 }
390 
391 static int
pci_ea_find(pci_chipset_tag_t pc,pcitag_t tag,int ea_cap_ptr,int reg,pcireg_t type,bus_addr_t * basep,bus_size_t * sizep,int * flagsp,struct pci_ea_entry * entryp)392 pci_ea_find(pci_chipset_tag_t pc, pcitag_t tag, int ea_cap_ptr,
393     int reg, pcireg_t type, bus_addr_t *basep, bus_size_t *sizep, int *flagsp,
394     struct pci_ea_entry *entryp)
395 {
396 
397           struct pci_ea_entry entry;
398           int rv = pci_ea_lookup(pc, tag, ea_cap_ptr, reg, &entry);
399           if (rv)
400                     return rv;
401 
402           pcireg_t wanted_type;
403           if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO)
404                     wanted_type = PCI_MAPREG_TYPE_IO;
405           else {
406                     /*
407                      * This covers ROM as well.  We allow any user-specified
408                      * memory type to match an EA memory region with no regard
409                      * for 32 vs. 64.
410                      *
411                      * XXX Should it?
412                      */
413                     wanted_type = PCI_MAPREG_TYPE_MEM;
414           }
415 
416           /*
417            * MaxOffset is the last offset where you can issue a
418            * 32-bit read in the region.  Therefore, the size of
419            * the region is MaxOffset + 4.
420            */
421           uint64_t region_size = entry.maxoffset + 4;
422 
423           unsigned int which_prop;
424           for (which_prop = 0; which_prop < 2; which_prop++) {
425                     int mapflags = 0;
426 
427                     switch (entry.props[which_prop]) {
428                     case PCI_EA_PROP_MEM_PREF:
429                               mapflags |= BUS_SPACE_MAP_PREFETCHABLE;
430                               /* FALLTHROUGH */
431                     case PCI_EA_PROP_MEM_NONPREF:
432                               if (PCI_MAPREG_TYPE(wanted_type) != PCI_MAPREG_TYPE_MEM)
433                                         goto unexpected_type;
434                               break;
435 
436                     case PCI_EA_PROP_IO:
437                               if (PCI_MAPREG_TYPE(wanted_type) != PCI_MAPREG_TYPE_IO)
438                                         goto unexpected_type;
439                               break;
440 
441                     case PCI_EA_PROP_MEM_UNAVAIL:
442                     case PCI_EA_PROP_IO_UNAVAIL:
443                     case PCI_EA_PROP_UNAVAIL:
444                               return 1;
445 
446                     /* XXX Don't support these yet. */
447                     case PCI_EA_PROP_VF_MEM_PREF:
448                     case PCI_EA_PROP_VF_MEM_NONPREF:
449                     case PCI_EA_PROP_BB_MEM_PREF:
450                     case PCI_EA_PROP_BB_MEM_NONPREF:
451                     case PCI_EA_PROP_BB_IO:
452                     default:
453                               printf("%s: bei %u props[%u]=0x%x\n",
454                                   __func__, entry.bei, which_prop,
455                                   entry.props[which_prop]);
456                                   continue;
457                               continue;
458                     }
459 
460                     if ((sizeof(uint64_t) > sizeof(bus_addr_t) ||
461                          PCI_MAPREG_TYPE(wanted_type) == PCI_MAPREG_TYPE_IO) &&
462                         (entry.base + region_size) > 0x100000000ULL) {
463                               goto inaccessible_64bit_region;
464                     }
465 
466                     *basep  = (bus_addr_t)entry.base;
467                     *sizep  = (bus_size_t)region_size;
468                     *flagsp = mapflags;
469                     if (entryp)
470                               *entryp = entry;
471                     return 0;
472           }
473 
474           /* BAR not found. */
475           return 1;
476 
477  unexpected_type:
478           printf("%s: unexpected type; wanted %s, got 0x%02x\n",
479               __func__, bar_type_string(wanted_type), entry.props[which_prop]);
480           return 1;
481 
482  inaccessible_64bit_region:
483           if (PCI_MAPREG_TYPE(wanted_type) == PCI_MAPREG_TYPE_IO) {
484                     printf("%s: 64-bit IO regions are unsupported\n",
485                         __func__);
486                     return 1;
487           }
488           printf("%s: 64-bit memory region inaccessible on 32-bit platform\n",
489               __func__);
490           return 1;
491 }
492 
493 #define _PCI_MAPREG_TYPEBITS(reg) \
494           (PCI_MAPREG_TYPE(reg) == PCI_MAPREG_TYPE_IO ? \
495           reg & PCI_MAPREG_TYPE_MASK : \
496           reg & (PCI_MAPREG_TYPE_MASK|PCI_MAPREG_MEM_TYPE_MASK))
497 
498 pcireg_t
pci_mapreg_type(pci_chipset_tag_t pc,pcitag_t tag,int reg)499 pci_mapreg_type(pci_chipset_tag_t pc, pcitag_t tag, int reg)
500 {
501 
502           return _PCI_MAPREG_TYPEBITS(pci_conf_read(pc, tag, reg));
503 }
504 
505 int
pci_mapreg_probe(pci_chipset_tag_t pc,pcitag_t tag,int reg,pcireg_t * typep)506 pci_mapreg_probe(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t *typep)
507 {
508           pcireg_t address, mask, csr;
509           int s;
510 
511           s = splhigh();
512           address = pci_conf_read(pc, tag, reg);
513           /*
514            * Disable decoding via the command register before writing to the
515            * BAR register. Changing the decoding address to all-one is
516            * not a valid address and could have side effects.
517            */
518           csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
519           if (PCI_MAPREG_TYPE(address) == PCI_MAPREG_TYPE_IO) {
520                     pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG,
521                         csr & ~PCI_COMMAND_IO_ENABLE);
522           } else {
523                     pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG,
524                         csr & ~PCI_COMMAND_MEM_ENABLE);
525           }
526           pci_conf_write(pc, tag, reg, 0xffffffff);
527           mask = pci_conf_read(pc, tag, reg);
528           pci_conf_write(pc, tag, reg, address);
529           pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
530           splx(s);
531 
532           if (mask == 0) /* unimplemented mapping register */
533                     return 0;
534 
535           if (typep != NULL)
536                     *typep = _PCI_MAPREG_TYPEBITS(address);
537           return 1;
538 }
539 
540 int
pci_mapreg_info(pci_chipset_tag_t pc,pcitag_t tag,int reg,pcireg_t type,bus_addr_t * basep,bus_size_t * sizep,int * flagsp)541 pci_mapreg_info(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t type,
542     bus_addr_t *basep, bus_size_t *sizep, int *flagsp)
543 {
544           int ea_cap_ptr;
545 
546           if (pci_get_capability(pc, tag, PCI_CAP_EA, &ea_cap_ptr, NULL))
547                     return pci_ea_find(pc, tag, ea_cap_ptr, reg, type,
548                         basep, sizep, flagsp, NULL);
549 
550           if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO)
551                     return pci_io_find(pc, tag, reg, type, basep, sizep,
552                         flagsp);
553           else
554                     return pci_mem_find(pc, tag, reg, type, basep, sizep,
555                         flagsp);
556 }
557 
558 int
pci_mapreg_map(const struct pci_attach_args * pa,int reg,pcireg_t type,int busflags,bus_space_tag_t * tagp,bus_space_handle_t * handlep,bus_addr_t * basep,bus_size_t * sizep)559 pci_mapreg_map(const struct pci_attach_args *pa, int reg, pcireg_t type,
560     int busflags, bus_space_tag_t *tagp, bus_space_handle_t *handlep,
561     bus_addr_t *basep, bus_size_t *sizep)
562 {
563           return pci_mapreg_submap(pa, reg, type, busflags, 0, 0, tagp,
564               handlep, basep, sizep);
565 }
566 
567 int
pci_mapreg_submap(const struct pci_attach_args * pa,int reg,pcireg_t type,int busflags,bus_size_t reqsize,bus_size_t offset,bus_space_tag_t * tagp,bus_space_handle_t * handlep,bus_addr_t * basep,bus_size_t * sizep)568 pci_mapreg_submap(const struct pci_attach_args *pa, int reg, pcireg_t type,
569     int busflags, bus_size_t reqsize, bus_size_t offset, bus_space_tag_t *tagp,
570           bus_space_handle_t *handlep, bus_addr_t *basep, bus_size_t *sizep)
571 {
572           bus_space_tag_t tag;
573           bus_space_handle_t handle;
574           bus_addr_t base;
575           bus_size_t realmaxsize;
576           pcireg_t csr;
577           int flags, s;
578           int ea_cap_ptr;
579           bool have_ea = false;
580           struct pci_ea_entry entry;
581 
582           if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO) {
583                     if ((pa->pa_flags & PCI_FLAGS_IO_OKAY) == 0)
584                               return 1;
585                     tag = pa->pa_iot;
586           } else {
587                     if ((pa->pa_flags & PCI_FLAGS_MEM_OKAY) == 0)
588                               return 1;
589                     tag = pa->pa_memt;
590           }
591 
592           if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_EA, &ea_cap_ptr,
593               NULL)) {
594                     have_ea = true;
595                     if (pci_ea_find(pa->pa_pc, pa->pa_tag, ea_cap_ptr, reg, type,
596                         &base, &realmaxsize, &flags, &entry))
597                               return 1;
598                     if (reg != PCI_MAPREG_ROM && !entry.enabled) {
599                               /* Entry not enabled.  Try the regular BAR? */
600                               have_ea = false;
601                     }
602           }
603 
604           if (!have_ea) {
605                     if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO) {
606                               if (pci_io_find(pa->pa_pc, pa->pa_tag, reg, type,
607                                   &base, &realmaxsize, &flags))
608                                         return 1;
609                     } else {
610                               if (pci_mem_find(pa->pa_pc, pa->pa_tag, reg, type,
611                                   &base, &realmaxsize, &flags))
612                                         return 1;
613                     }
614           }
615 
616           if (reg == PCI_MAPREG_ROM) {
617                     /* Enable the ROM address decoder, if necessary. */
618                     if (have_ea) {
619                               if (!entry.enabled) {
620                                         entry.dw0 |= PCI_EA_E;
621                                         pci_conf_write(pa->pa_pc, pa->pa_tag,
622                                             entry.ea_ptrs[EA_ptr_dw0],
623                                             entry.dw0);
624                                         entry.enabled = true;
625                               }
626                     } else {
627                               s = splhigh();
628                               pcireg_t mask =
629                                   pci_conf_read(pa->pa_pc, pa->pa_tag, reg);
630                               if ((mask & PCI_MAPREG_ROM_ENABLE) == 0) {
631                                         mask |= PCI_MAPREG_ROM_ENABLE;
632                                         pci_conf_write(pa->pa_pc, pa->pa_tag, reg,
633                                             mask);
634                               }
635                               splx(s);
636                     }
637           }
638 
639           /*
640            * If we're called with maxsize/offset of 0, behave like
641            * pci_mapreg_map.
642            */
643 
644           reqsize = (reqsize != 0) ? reqsize : realmaxsize;
645           base += offset;
646 
647           if (realmaxsize < (offset + reqsize))
648                     return 1;
649 
650           if (bus_space_map(tag, base, reqsize, busflags, &handle))
651                     return 1;
652 
653           if (pci_mapreg_map_enable_decode) {
654                     s = splhigh();
655                     csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
656                     csr |= (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO) ?
657                         PCI_COMMAND_IO_ENABLE : PCI_COMMAND_MEM_ENABLE;
658                     pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, csr);
659                     splx(s);
660           }
661 
662           if (tagp != NULL)
663                     *tagp = tag;
664           if (handlep != NULL)
665                     *handlep = handle;
666           if (basep != NULL)
667                     *basep = base;
668           if (sizep != NULL)
669                     *sizep = reqsize;
670 
671           return 0;
672 }
673 
674 int
pci_find_rom(const struct pci_attach_args * pa,bus_space_tag_t bst,bus_space_handle_t bsh,bus_size_t sz,int type,bus_space_handle_t * romh,bus_size_t * romsz)675 pci_find_rom(const struct pci_attach_args *pa, bus_space_tag_t bst,
676     bus_space_handle_t bsh, bus_size_t sz, int type,
677     bus_space_handle_t *romh, bus_size_t *romsz)
678 {
679           bus_size_t          offset = 0, imagesz;
680           uint16_t  ptr;
681           int                 done = 0;
682 
683           /*
684            * no upper bound check; i cannot imagine a 4GB ROM, but
685            * it appears the spec would allow it!
686            */
687           if (sz < 1024)
688                     return 1;
689 
690           while (offset < sz && !done){
691                     struct pci_rom_header         hdr;
692                     struct pci_rom                rom;
693 
694                     hdr.romh_magic = bus_space_read_2(bst, bsh,
695                         offset + offsetof (struct pci_rom_header, romh_magic));
696                     hdr.romh_data_ptr = bus_space_read_2(bst, bsh,
697                         offset + offsetof (struct pci_rom_header, romh_data_ptr));
698 
699                     /* no warning: quite possibly ROM is simply not populated */
700                     if (hdr.romh_magic != PCI_ROM_HEADER_MAGIC)
701                               return 1;
702 
703                     ptr = offset + hdr.romh_data_ptr;
704 
705                     if (ptr > sz) {
706                               printf("pci_find_rom: rom data ptr out of range\n");
707                               return 1;
708                     }
709 
710                     rom.rom_signature = bus_space_read_4(bst, bsh, ptr);
711                     rom.rom_vendor = bus_space_read_2(bst, bsh, ptr +
712                         offsetof(struct pci_rom, rom_vendor));
713                     rom.rom_product = bus_space_read_2(bst, bsh, ptr +
714                         offsetof(struct pci_rom, rom_product));
715                     rom.rom_class = bus_space_read_1(bst, bsh,
716                         ptr + offsetof (struct pci_rom, rom_class));
717                     rom.rom_subclass = bus_space_read_1(bst, bsh,
718                         ptr + offsetof (struct pci_rom, rom_subclass));
719                     rom.rom_interface = bus_space_read_1(bst, bsh,
720                         ptr + offsetof (struct pci_rom, rom_interface));
721                     rom.rom_len = bus_space_read_2(bst, bsh,
722                         ptr + offsetof (struct pci_rom, rom_len));
723                     rom.rom_code_type = bus_space_read_1(bst, bsh,
724                         ptr + offsetof (struct pci_rom, rom_code_type));
725                     rom.rom_indicator = bus_space_read_1(bst, bsh,
726                         ptr + offsetof (struct pci_rom, rom_indicator));
727 
728                     if (rom.rom_signature != PCI_ROM_SIGNATURE) {
729                               printf("pci_find_rom: bad rom data signature\n");
730                               return 1;
731                     }
732 
733                     imagesz = rom.rom_len * 512;
734 
735                     if ((rom.rom_vendor == PCI_VENDOR(pa->pa_id)) &&
736                         (rom.rom_product == PCI_PRODUCT(pa->pa_id)) &&
737                         (rom.rom_class == PCI_CLASS(pa->pa_class)) &&
738                         (rom.rom_subclass == PCI_SUBCLASS(pa->pa_class)) &&
739                         (rom.rom_interface == PCI_INTERFACE(pa->pa_class)) &&
740                         (rom.rom_code_type == type)) {
741                               *romsz = imagesz;
742                               bus_space_subregion(bst, bsh, offset, imagesz, romh);
743                               return 0;
744                     }
745 
746                     /* last image check */
747                     if (rom.rom_indicator & PCI_ROM_INDICATOR_LAST)
748                               return 1;
749 
750                     /* offset by size */
751                     offset += imagesz;
752           }
753           return 1;
754 }
755