summaryrefslogtreecommitdiffstats
path: root/qemu/roms/ipxe/src/include/ipxe/pcivpd.h
blob: 0abf8a95668c1f86ba837b6dff6d5f35b46c9e7b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#ifndef _IPXE_PCIVPD_H
#define _IPXE_PCIVPD_H

/**
 * @file
 *
 * PCI Vital Product Data
 *
 */

FILE_LICENCE ( GPL2_OR_LATER );

#include <stdint.h>
#include <byteswap.h>
#include <ipxe/isapnp.h>
#include <ipxe/pci.h>

/** PCI VPD address register */
#define PCI_VPD_ADDRESS 0x02

/** PCI VPD write flag */
#define PCI_VPD_FLAG 0x8000

/** PCI VPD data register */
#define PCI_VPD_DATA 0x04

/** A PCI VPD field */
struct pci_vpd_field {
	/** Keyword */
	uint16_t keyword;
	/** Length */
	uint8_t len;
} __attribute__ (( packed ));

/** Maximum PCI VPD field length */
#define PCI_VPD_MAX_LEN 0xff

/** Construct PCI VPD field descriptor
 *
 * @v tag		ISAPnP tag
 * @v keyword1		First character of keyword
 * @v keyword2		Second character of keyword
 * @ret field		VPD field descriptor
 */
#define PCI_VPD_FIELD( tag, keyword1, keyword2 ) \
	( ( (tag) << 16 ) | ( (keyword2) << 8 ) | ( (keyword1) << 0 ) )

/** Construct PCI VPD whole-tag field descriptor
 *
 * @v tag		ISAPnP tag
 * @ret field		VPD field descriptor
 */
#define PCI_VPD_WHOLE_TAG_FIELD( tag ) PCI_VPD_FIELD ( (tag), '\0', '\0' )

/** Extract PCI VPD ISAPnP tag
 *
 * @v field		VPD field descriptor
 * @ret tag		ISAPnP tag
 */
#define PCI_VPD_TAG( field ) ( (field) >> 16 )

/** Extract PCI VPD keyword
 *
 * @v field		VPD field descriptor
 * @ret keyword		Keyword
 */
#define PCI_VPD_KEYWORD( field ) ( cpu_to_le16 ( (field) & 0xffff ) )

/** PCI VPD field debug message format */
#define PCI_VPD_FIELD_FMT "%c%c"

/** PCI VPD field debug message arguments */
#define PCI_VPD_FIELD_ARGS( field ) \
	( (field) >> 0 ), ( (field) >> 8 )

/** PCI VPD Read-Only field tag */
#define PCI_VPD_TAG_RO 0x90

/** PCI VPD Read-Write field tag */
#define PCI_VPD_TAG_RW 0x91

/** PCI VPD Card Name field descriptor */
#define PCI_VPD_FIELD_NAME PCI_VPD_WHOLE_TAG_FIELD ( ISAPNP_TAG_ANSISTR )

/** PCI VPD Part Number field descriptor */
#define PCI_VPD_FIELD_PN PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'P', 'N' )

/** PCI VPD Engineering Change Level field descriptor */
#define PCI_VPD_FIELD_EC PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'E', 'C' )

/** PCI VPD Fabric Geography field descriptor */
#define PCI_VPD_FIELD_FG PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'F', 'G' )

/** PCI VPD Location field descriptor */
#define PCI_VPD_FIELD_LC PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'L', 'C' )

/** PCI VPD Manufacturer ID field descriptor */
#define PCI_VPD_FIELD_MN PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'M', 'N' )

/** PCI VPD PCI Geography field descriptor */
#define PCI_VPD_FIELD_PG PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'P', 'G' )

/** PCI VPD Serial Number field descriptor */
#define PCI_VPD_FIELD_SN PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'S', 'N' )

/** PCI VPD Extended Capability field descriptor */
#define PCI_VPD_FIELD_CP PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'C', 'P' )

/** PCI VPD Checksum and Reserved field descriptor */
#define PCI_VPD_FIELD_RV PCI_VPD_FIELD ( PCI_VPD_TAG_RO, 'R', 'V' )

/** PCI VPD Asset Tag field descriptor */
#define PCI_VPD_FIELD_YA PCI_VPD_FIELD ( PCI_VPD_TAG_RW, 'Y', 'A' )

/** PCI VPD Remaining Read/Write Area field descriptor */
#define PCI_VPD_FIELD_RW PCI_VPD_FIELD ( PCI_VPD_TAG_RW, 'R', 'W' )

/** Maximum wait for PCI VPD (in ms) */
#define PCI_VPD_MAX_WAIT_MS 100

/** PCI VPD cache */
struct pci_vpd_cache {
	/** Address */
	int address;
	/** Data */
	uint32_t data;
};

/** PCI VPD */
struct pci_vpd {
	/** PCI device */
	struct pci_device *pci;
	/** VPD capability offset */
	int cap;
	/** Read cache */
	struct pci_vpd_cache cache;
};

/**
 * Check for presence of PCI VPD
 *
 * @v vpd		PCI VPD
 * @ret is_present	VPD is present
 */
static inline __attribute__ (( always_inline )) int
pci_vpd_is_present ( struct pci_vpd *vpd ) {
	return ( vpd->cap != 0 );
}

/**
 * Check if PCI VPD read cache is valid
 *
 * @v vpd		PCI VPD
 * @ret is_valid	Read cache is valid
 */
static inline __attribute__ (( always_inline )) int
pci_vpd_cache_is_valid ( struct pci_vpd *vpd ) {
	return ( vpd->cache.address >= 0 );
}

/**
 * Invalidate PCI VPD read cache
 *
 * @v vpd		PCI VPD
 */
static inline __attribute__ (( always_inline )) void
pci_vpd_invalidate_cache ( struct pci_vpd *vpd ) {
	vpd->cache.address = -1;
}

extern int pci_vpd_init ( struct pci_vpd *vpd, struct pci_device *pci );
extern int pci_vpd_read ( struct pci_vpd *vpd, unsigned int address,
			  void *buf, size_t len );
extern int pci_vpd_write ( struct pci_vpd *vpd, unsigned int address,
			   const void *buf, size_t len );
extern int pci_vpd_find ( struct pci_vpd *vpd, unsigned int field,
			  unsigned int *address, size_t *len );
extern int pci_vpd_resize ( struct pci_vpd *vpd, unsigned int field,
			    size_t len, unsigned int *address );

#endif /* _IPXE_PCIVPD_H */