iPXE
pciea.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2016 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 #include <stdint.h>
27 #include <errno.h>
28 #include <ipxe/pci.h>
29 #include <ipxe/pciea.h>
30 
31 /** @file
32  *
33  * PCI Enhanced Allocation
34  *
35  */
36 
37 /**
38  * Locate PCI Enhanced Allocation BAR equivalent entry
39  *
40  * @v pci PCI device
41  * @v bei BAR equivalent indicator
42  * @ret offset PCI Enhanced Allocation entry offset, or negative error
43  */
44 static int pciea_offset ( struct pci_device *pci, unsigned int bei ) {
45  uint8_t entries;
46  uint32_t desc;
47  unsigned int i;
48  int offset;
49 
50  /* Locate Enhanced Allocation capability */
52  if ( offset < 0 )
53  return offset;
54 
55  /* Get number of entries */
56  pci_read_config_byte ( pci, ( offset + PCIEA_ENTRIES ), &entries );
57  entries &= PCIEA_ENTRIES_MASK;
58 
59  /* Locate first entry */
61 
62  /* Search for a matching entry */
63  for ( i = 0 ; i < entries ; i++ ) {
64 
65  /* Read entry descriptor */
67 
68  /* Check for a matching entry */
69  if ( ( desc & PCIEA_DESC_ENABLED ) &&
70  ( bei == PCIEA_DESC_BEI ( desc ) ) )
71  return offset;
72 
73  /* Move to next entry */
74  offset += ( ( PCIEA_DESC_SIZE ( desc ) + 1 ) << 2 );
75  }
76 
77  return -ENOENT;
78 }
79 
80 /**
81  * Read PCI Enhanced Allocation BAR equivalent value
82  *
83  * @v pci PCI device
84  * @v bei BAR equivalent indicator
85  * @v low_offset Offset to low dword of value
86  * @ret value BAR equivalent value
87  */
88 static unsigned long pciea_bar_value ( struct pci_device *pci, unsigned int bei,
89  unsigned int low_offset ) {
90  uint32_t low;
91  uint32_t high;
92  int offset;
93 
94  /* Locate Enhanced Allocation offset for this BEI */
95  offset = pciea_offset ( pci, bei );
96  if ( offset < 0 )
97  return 0;
98 
99  /* Read BAR equivalent */
100  offset += low_offset;
101  pci_read_config_dword ( pci, offset, &low );
102  if ( low & PCIEA_LOW_ATTR_64BIT ) {
104  pci_read_config_dword ( pci, offset, &high );
105  if ( high ) {
106  if ( sizeof ( unsigned long ) > sizeof ( uint32_t ) ) {
107  return ( ( ( uint64_t ) high << 32 ) | low );
108  } else {
109  DBGC ( pci, PCI_FMT " unhandled 64-bit EA BAR "
110  "%08x%08x\n",
111  PCI_ARGS ( pci ), high, low );
112  return 0;
113  }
114  }
115  }
116  return low;
117 }
118 
119 /**
120  * Find the start of a PCI Enhanced Allocation BAR equivalent
121  *
122  * @v pci PCI device
123  * @v bei BAR equivalent indicator
124  * @ret start BAR start address
125  *
126  * If the address exceeds the size of an unsigned long (i.e. if a
127  * 64-bit BAR has a non-zero high dword on a 32-bit machine), the
128  * return value will be zero.
129  */
130 unsigned long pciea_bar_start ( struct pci_device *pci, unsigned int bei ) {
131  unsigned long base;
132 
133  base = pciea_bar_value ( pci, bei, PCIEA_LOW_BASE );
134  return ( base & ~PCIEA_LOW_ATTR_MASK );
135 }
136 
137 /**
138  * Find the size of a PCI Enhanced Allocation BAR equivalent
139  *
140  * @v pci PCI device
141  * @v bei BAR equivalent indicator
142  * @ret size BAR size
143  */
144 unsigned long pciea_bar_size ( struct pci_device *pci, unsigned int bei ) {
145  unsigned long limit;
146 
147  limit = pciea_bar_value ( pci, bei, PCIEA_LOW_LIMIT );
148  return ( limit ? ( ( limit | PCIEA_LOW_ATTR_MASK ) + 1 ) : 0 );
149 }
#define PCIEA_LOW_BASE
Base address low dword.
Definition: pciea.h:51
#define PCIEA_LOW_HIGH
Offset to high dwords.
Definition: pciea.h:63
uint32_t low
Low 16 bits of address.
Definition: myson.h:19
int pci_find_capability(struct pci_device *pci, int cap)
Look for a PCI capability.
Definition: pciextra.c:38
Error codes.
#define PCIEA_DESC_BEI(desc)
BAR equivalent indicator.
Definition: pciea.h:28
#define PCIEA_LOW_ATTR_MASK
Low dword attribute bit mask.
Definition: pciea.h:60
uint64_t desc
Microcode descriptor list physical address.
Definition: ucode.h:12
#define DBGC(...)
Definition: compiler.h:505
#define ENOENT
No such file or directory.
Definition: errno.h:514
unsigned long long uint64_t
Definition: stdint.h:13
#define PCIEA_ENTRIES_MASK
Definition: pciea.h:16
static unsigned long pciea_bar_value(struct pci_device *pci, unsigned int bei, unsigned int low_offset)
Read PCI Enhanced Allocation BAR equivalent value.
Definition: pciea.c:88
#define PCIEA_FIRST
First entry.
Definition: pciea.h:19
static const void * base
Base address.
Definition: crypto.h:335
int pci_read_config_dword(struct pci_device *pci, unsigned int where, uint32_t *value)
Read 32-bit dword from PCI configuration space.
static userptr_t size_t offset
Offset of the first segment within the content.
Definition: deflate.h:259
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
uint32_t high
High 32 bits of address.
Definition: myson.h:20
#define PCIEA_ENTRIES
Number of entries.
Definition: pciea.h:15
static int pciea_offset(struct pci_device *pci, unsigned int bei)
Locate PCI Enhanced Allocation BAR equivalent entry.
Definition: pciea.c:44
uint16_t limit
Limit.
Definition: librm.h:250
#define PCIEA_LOW_LIMIT
Limit low dword.
Definition: pciea.h:54
#define PCI_FMT
PCI device debug message format.
Definition: pci.h:307
PCI bus.
A PCI device.
Definition: pci.h:206
#define PCI_CAP_ID_EA
Enhanced Allocation.
Definition: pci.h:99
unsigned char uint8_t
Definition: stdint.h:10
unsigned long pciea_bar_size(struct pci_device *pci, unsigned int bei)
Find the size of a PCI Enhanced Allocation BAR equivalent.
Definition: pciea.c:144
unsigned int uint32_t
Definition: stdint.h:12
#define PCIEA_DESC_ENABLED
Entry is enabled.
Definition: pciea.h:48
unsigned long pciea_bar_start(struct pci_device *pci, unsigned int bei)
Find the start of a PCI Enhanced Allocation BAR equivalent.
Definition: pciea.c:130
#define PCIEA_DESC_SIZE(desc)
Entry size.
Definition: pciea.h:25
#define PCI_ARGS(pci)
PCI device debug message arguments.
Definition: pci.h:310
PCI Enhanced Allocation.
#define PCIEA_LOW_ATTR_64BIT
BAR is 64-bit.
Definition: pciea.h:57
int pci_read_config_byte(struct pci_device *pci, unsigned int where, uint8_t *value)
Read byte from PCI configuration space.