1 /* 2 * The PCI Library -- Device Filtering 3 * 4 * Copyright (c) 1998--2003 Martin Mares <[email protected]> 5 * 6 * Can be freely distributed and used under the terms of the GNU GPL. 7 */ 8 9 #include <stdlib.h> 10 #include <string.h> 11 12 #include "internal.h" 13 14 void 15 pci_filter_init(struct pci_access *a UNUSED, struct pci_filter *f) 16 { 17 f->domain = f->bus = f->slot = f->func = -1; 18 f->vendor = f->device = -1; 19 } 20 21 /* Slot filter syntax: [[[domain]:][bus]:][slot][.[func]] */ 22 23 char * 24 pci_filter_parse_slot(struct pci_filter *f, char *str) 25 { 26 char *colon = strrchr(str, ':'); 27 char *dot = strchr((colon ? colon + 1 : str), '.'); 28 char *mid = str; 29 char *e, *bus, *colon2; 30 31 if (colon) 32 { 33 *colon++ = 0; 34 mid = colon; 35 colon2 = strchr(str, ':'); 36 if (colon2) 37 { 38 *colon2++ = 0; 39 bus = colon2; 40 if (str[0] && strcmp(str, "*")) 41 { 42 long int x = strtol(bus, &e, 16); 43 if ((e && *e) || (x < 0 || x > 0xffff)) 44 return "Invalid domain number"; 45 f->domain = x; 46 } 47 } 48 else 49 bus = str; 50 if (bus[0] && strcmp(bus, "*")) 51 { 52 long int x = strtol(bus, &e, 16); 53 if ((e && *e) || (x < 0 || x > 0xff)) 54 return "Invalid bus number"; 55 f->bus = x; 56 } 57 } 58 if (dot) 59 *dot++ = 0; 60 if (mid[0] && strcmp(mid, "*")) 61 { 62 long int x = strtol(mid, &e, 16); 63 if ((e && *e) || (x < 0 || x > 0x1f)) 64 return "Invalid slot number"; 65 f->slot = x; 66 } 67 if (dot && dot[0] && strcmp(dot, "*")) 68 { 69 long int x = strtol(dot, &e, 16); 70 if ((e && *e) || (x < 0 || x > 7)) 71 return "Invalid function number"; 72 f->func = x; 73 } 74 return NULL; 75 } 76 77 /* ID filter syntax: [vendor]:[device] */ 78 79 char * 80 pci_filter_parse_id(struct pci_filter *f, char *str) 81 { 82 char *s, *e; 83 84 if (!*str) 85 return NULL; 86 s = strchr(str, ':'); 87 if (!s) 88 return "':' expected"; 89 *s++ = 0; 90 if (str[0] && strcmp(str, "*")) 91 { 92 long int x = strtol(str, &e, 16); 93 if ((e && *e) || (x < 0 || x >= 0xffff)) 94 return "Invalid vendor ID"; 95 f->vendor = x; 96 } 97 if (s[0] && strcmp(s, "*")) 98 { 99 long int x = strtol(s, &e, 16); 100 if ((e && *e) || (x < 0 || x >= 0xffff)) 101 return "Invalid device ID"; 102 f->device = x; 103 } 104 return NULL; 105 } 106 107 int 108 pci_filter_match(struct pci_filter *f, struct pci_dev *d) 109 { 110 if ((f->domain >= 0 && f->domain != d->domain) || 111 (f->bus >= 0 && f->bus != d->bus) || 112 (f->slot >= 0 && f->slot != d->dev) || 113 (f->func >= 0 && f->func != d->func)) 114 return 0; 115 if (f->device >= 0 || f->vendor >= 0) 116 { 117 pci_fill_info(d, PCI_FILL_IDENT); 118 if ((f->device >= 0 && f->device != d->device_id) || 119 (f->vendor >= 0 && f->vendor != d->vendor_id)) 120 return 0; 121 } 122 return 1; 123 } 124