1 /* 2 * The PCI Library -- User Access 3 * 4 * Copyright (c) 1997--2022 Martin Mares <[email protected]> 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 #include <stdio.h> 12 #include <stdlib.h> 13 #include <stdarg.h> 14 #include <string.h> 15 16 #include "internal.h" 17 18 void 19 pci_scan_bus(struct pci_access *a) 20 { 21 a->methods->scan(a); 22 } 23 24 struct pci_dev * 25 pci_alloc_dev(struct pci_access *a) 26 { 27 struct pci_dev *d = pci_malloc(a, sizeof(struct pci_dev)); 28 29 memset(d, 0, sizeof(*d)); 30 d->access = a; 31 d->methods = a->methods; 32 d->hdrtype = -1; 33 d->numa_node = -1; 34 if (d->methods->init_dev) 35 d->methods->init_dev(d); 36 return d; 37 } 38 39 int 40 pci_link_dev(struct pci_access *a, struct pci_dev *d) 41 { 42 d->next = a->devices; 43 a->devices = d; 44 45 /* 46 * Applications compiled with older versions of libpci do not expect 47 * 32-bit domain numbers. To keep them working, we keep a 16-bit 48 * version of the domain number at the previous location in struct 49 * pci_dev. This will keep backward compatibility on systems which 50 * don't require large domain numbers. 51 */ 52 if (d->domain > 0xffff) 53 d->domain_16 = 0xffff; 54 else 55 d->domain_16 = d->domain; 56 57 return 1; 58 } 59 60 struct pci_dev * 61 pci_get_dev(struct pci_access *a, int domain, int bus, int dev, int func) 62 { 63 struct pci_dev *d = pci_alloc_dev(a); 64 65 d->domain = domain; 66 d->bus = bus; 67 d->dev = dev; 68 d->func = func; 69 return d; 70 } 71 72 static void 73 pci_free_properties(struct pci_dev *d) 74 { 75 struct pci_property *p; 76 77 while (p = d->properties) 78 { 79 d->properties = p->next; 80 pci_mfree(p); 81 } 82 } 83 84 void pci_free_dev(struct pci_dev *d) 85 { 86 if (d->methods->cleanup_dev) 87 d->methods->cleanup_dev(d); 88 89 pci_free_caps(d); 90 pci_free_properties(d); 91 pci_mfree(d); 92 } 93 94 static inline void 95 pci_read_data(struct pci_dev *d, void *buf, int pos, int len) 96 { 97 if (pos & (len-1)) 98 d->access->error("Unaligned read: pos=%02x, len=%d", pos, len); 99 if (pos + len <= d->cache_len) 100 memcpy(buf, d->cache + pos, len); 101 else if (!d->methods->read(d, pos, buf, len)) 102 memset(buf, 0xff, len); 103 } 104 105 byte 106 pci_read_byte(struct pci_dev *d, int pos) 107 { 108 byte buf; 109 pci_read_data(d, &buf, pos, 1); 110 return buf; 111 } 112 113 word 114 pci_read_word(struct pci_dev *d, int pos) 115 { 116 word buf; 117 pci_read_data(d, &buf, pos, 2); 118 return le16_to_cpu(buf); 119 } 120 121 u32 122 pci_read_long(struct pci_dev *d, int pos) 123 { 124 u32 buf; 125 pci_read_data(d, &buf, pos, 4); 126 return le32_to_cpu(buf); 127 } 128 129 int 130 pci_read_block(struct pci_dev *d, int pos, byte *buf, int len) 131 { 132 return d->methods->read(d, pos, buf, len); 133 } 134 135 int 136 pci_read_vpd(struct pci_dev *d, int pos, byte *buf, int len) 137 { 138 return d->methods->read_vpd ? d->methods->read_vpd(d, pos, buf, len) : 0; 139 } 140 141 static inline int 142 pci_write_data(struct pci_dev *d, void *buf, int pos, int len) 143 { 144 if (pos & (len-1)) 145 d->access->error("Unaligned write: pos=%02x,len=%d", pos, len); 146 if (pos + len <= d->cache_len) 147 memcpy(d->cache + pos, buf, len); 148 return d->methods->write(d, pos, buf, len); 149 } 150 151 int 152 pci_write_byte(struct pci_dev *d, int pos, byte data) 153 { 154 return pci_write_data(d, &data, pos, 1); 155 } 156 157 int 158 pci_write_word(struct pci_dev *d, int pos, word data) 159 { 160 word buf = cpu_to_le16(data); 161 return pci_write_data(d, &buf, pos, 2); 162 } 163 164 int 165 pci_write_long(struct pci_dev *d, int pos, u32 data) 166 { 167 u32 buf = cpu_to_le32(data); 168 return pci_write_data(d, &buf, pos, 4); 169 } 170 171 int 172 pci_write_block(struct pci_dev *d, int pos, byte *buf, int len) 173 { 174 if (pos < d->cache_len) 175 { 176 int l = (pos + len >= d->cache_len) ? (d->cache_len - pos) : len; 177 memcpy(d->cache + pos, buf, l); 178 } 179 return d->methods->write(d, pos, buf, len); 180 } 181 182 static void 183 pci_reset_properties(struct pci_dev *d) 184 { 185 d->known_fields = 0; 186 d->phy_slot = NULL; 187 d->module_alias = NULL; 188 d->label = NULL; 189 pci_free_caps(d); 190 pci_free_properties(d); 191 } 192 193 int 194 pci_fill_info_v38(struct pci_dev *d, int flags) 195 { 196 unsigned int uflags = flags; 197 if (uflags & PCI_FILL_RESCAN) 198 { 199 uflags &= ~PCI_FILL_RESCAN; 200 pci_reset_properties(d); 201 } 202 if (uflags & ~d->known_fields) 203 d->methods->fill_info(d, uflags); 204 return d->known_fields; 205 } 206 207 /* In version 3.1, pci_fill_info got new flags => versioned alias */ 208 /* In versions 3.2, 3.3, 3.4, 3.5 and 3.8, the same has happened */ 209 STATIC_ALIAS(int pci_fill_info(struct pci_dev *d, int flags), pci_fill_info_v38(d, flags)); 210 DEFINE_ALIAS(int pci_fill_info_v30(struct pci_dev *d, int flags), pci_fill_info_v38); 211 DEFINE_ALIAS(int pci_fill_info_v31(struct pci_dev *d, int flags), pci_fill_info_v38); 212 DEFINE_ALIAS(int pci_fill_info_v32(struct pci_dev *d, int flags), pci_fill_info_v38); 213 DEFINE_ALIAS(int pci_fill_info_v33(struct pci_dev *d, int flags), pci_fill_info_v38); 214 DEFINE_ALIAS(int pci_fill_info_v34(struct pci_dev *d, int flags), pci_fill_info_v38); 215 DEFINE_ALIAS(int pci_fill_info_v35(struct pci_dev *d, int flags), pci_fill_info_v38); 216 SYMBOL_VERSION(pci_fill_info_v30, pci_fill_info@LIBPCI_3.0); 217 SYMBOL_VERSION(pci_fill_info_v31, pci_fill_info@LIBPCI_3.1); 218 SYMBOL_VERSION(pci_fill_info_v32, pci_fill_info@LIBPCI_3.2); 219 SYMBOL_VERSION(pci_fill_info_v33, pci_fill_info@LIBPCI_3.3); 220 SYMBOL_VERSION(pci_fill_info_v34, pci_fill_info@LIBPCI_3.4); 221 SYMBOL_VERSION(pci_fill_info_v35, pci_fill_info@LIBPCI_3.5); 222 SYMBOL_VERSION(pci_fill_info_v38, pci_fill_info@@LIBPCI_3.8); 223 224 void 225 pci_setup_cache(struct pci_dev *d, byte *cache, int len) 226 { 227 d->cache = cache; 228 d->cache_len = len; 229 } 230 231 char * 232 pci_set_property(struct pci_dev *d, u32 key, char *value) 233 { 234 struct pci_property *p; 235 struct pci_property **pp = &d->properties; 236 237 while (p = *pp) 238 { 239 if (p->key == key) 240 { 241 *pp = p->next; 242 pci_mfree(p); 243 } 244 else 245 pp = &p->next; 246 } 247 248 if (!value) 249 return NULL; 250 251 p = pci_malloc(d->access, sizeof(*p) + strlen(value)); 252 *pp = p; 253 p->next = NULL; 254 p->key = key; 255 strcpy(p->value, value); 256 257 return p->value; 258 } 259 260 char * 261 pci_get_string_property(struct pci_dev *d, u32 prop) 262 { 263 struct pci_property *p; 264 265 for (p = d->properties; p; p = p->next) 266 if (p->key == prop) 267 return p->value; 268 269 return NULL; 270 } 271