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
24FILE_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 */
44static int pciea_offset ( struct pci_device *pci, unsigned int bei ) {
45 uint8_t entries;
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 */
88static unsigned long pciea_bar_value ( struct pci_device *pci, unsigned int bei,
89 unsigned int low_offset ) {
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;
102 if ( low & PCIEA_LOW_ATTR_64BIT ) {
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 */
130unsigned 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 */
144unsigned 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}
unsigned int uint32_t
Definition stdint.h:12
unsigned long long uint64_t
Definition stdint.h:13
unsigned char uint8_t
Definition stdint.h:10
uint16_t offset
Offset to command line.
Definition bzimage.h:3
struct ena_llq_option desc
Descriptor counts.
Definition ena.h:9
Error codes.
#define DBGC(...)
Definition compiler.h:505
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ENOENT
No such file or directory.
Definition errno.h:515
int pci_read_config_dword(struct pci_device *pci, unsigned int where, uint32_t *value)
Read 32-bit dword from PCI configuration space.
int pci_read_config_byte(struct pci_device *pci, unsigned int where, uint8_t *value)
Read byte from PCI configuration space.
uint16_t limit
Limit.
Definition librm.h:1
uint32_t base
Base.
Definition librm.h:3
uint32_t high
High 32 bits of address.
Definition myson.h:1
uint32_t low
Low 16 bits of address.
Definition myson.h:0
PCI bus.
#define PCI_FMT
PCI device debug message format.
Definition pci.h:312
#define PCI_ARGS(pci)
PCI device debug message arguments.
Definition pci.h:315
#define PCI_CAP_ID_EA
Enhanced Allocation.
Definition pci.h:100
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
static int pciea_offset(struct pci_device *pci, unsigned int bei)
Locate PCI Enhanced Allocation BAR equivalent entry.
Definition pciea.c:44
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
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
PCI Enhanced Allocation.
#define PCIEA_DESC_ENABLED
Entry is enabled.
Definition pciea.h:48
#define PCIEA_ENTRIES_MASK
Definition pciea.h:16
#define PCIEA_LOW_ATTR_MASK
Low dword attribute bit mask.
Definition pciea.h:60
#define PCIEA_ENTRIES
Number of entries.
Definition pciea.h:15
#define PCIEA_FIRST
First entry.
Definition pciea.h:19
#define PCIEA_LOW_ATTR_64BIT
BAR is 64-bit.
Definition pciea.h:57
#define PCIEA_LOW_LIMIT
Limit low dword.
Definition pciea.h:54
#define PCIEA_DESC_SIZE(desc)
Entry size.
Definition pciea.h:25
#define PCIEA_LOW_BASE
Base address low dword.
Definition pciea.h:51
#define PCIEA_LOW_HIGH
Offset to high dwords.
Definition pciea.h:63
#define PCIEA_DESC_BEI(desc)
BAR equivalent indicator.
Definition pciea.h:28
int pci_find_capability(struct pci_device *pci, int cap)
Look for a PCI capability.
Definition pciextra.c:39
A PCI device.
Definition pci.h:211