]>
Commit | Line | Data |
---|---|---|
e4842ff3 | 1 | /* |
4284af58 | 2 | * The PCI Library -- Device Filtering |
e4842ff3 | 3 | * |
a832f6f1 | 4 | * Copyright (c) 1998--2003 Martin Mares <mj@ucw.cz> |
e4842ff3 MM |
5 | * |
6 | * Can be freely distributed and used under the terms of the GNU GPL. | |
7 | */ | |
8 | ||
e4842ff3 MM |
9 | #include <stdlib.h> |
10 | #include <string.h> | |
e4842ff3 | 11 | |
727ce158 | 12 | #include "internal.h" |
e4842ff3 MM |
13 | |
14 | void | |
a832f6f1 | 15 | pci_filter_init(struct pci_access *a UNUSED, struct pci_filter *f) |
e4842ff3 | 16 | { |
84c8d1bb | 17 | f->domain = f->bus = f->slot = f->func = -1; |
e4842ff3 MM |
18 | f->vendor = f->device = -1; |
19 | } | |
20 | ||
84c8d1bb | 21 | /* Slot filter syntax: [[[domain]:][bus]:][slot][.[func]] */ |
e4842ff3 MM |
22 | |
23 | char * | |
727ce158 | 24 | pci_filter_parse_slot(struct pci_filter *f, char *str) |
e4842ff3 | 25 | { |
84c8d1bb | 26 | char *colon = strrchr(str, ':'); |
e4842ff3 MM |
27 | char *dot = strchr((colon ? colon + 1 : str), '.'); |
28 | char *mid = str; | |
84c8d1bb | 29 | char *e, *bus, *colon2; |
e4842ff3 MM |
30 | |
31 | if (colon) | |
32 | { | |
33 | *colon++ = 0; | |
34 | mid = colon; | |
84c8d1bb MM |
35 | colon2 = strchr(str, ':'); |
36 | if (colon2) | |
e4842ff3 | 37 | { |
84c8d1bb MM |
38 | *colon2++ = 0; |
39 | bus = colon2; | |
40 | if (str[0] && strcmp(str, "*")) | |
41 | { | |
b9ca9147 | 42 | long int x = strtol(str, &e, 16); |
84c8d1bb MM |
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); | |
cba7c00f | 53 | if ((e && *e) || (x < 0 || x > 0xff)) |
e4842ff3 MM |
54 | return "Invalid bus number"; |
55 | f->bus = x; | |
56 | } | |
57 | } | |
58 | if (dot) | |
59 | *dot++ = 0; | |
60 | if (mid[0] && strcmp(mid, "*")) | |
61 | { | |
71e8f0ae | 62 | long int x = strtol(mid, &e, 16); |
cba7c00f | 63 | if ((e && *e) || (x < 0 || x > 0x1f)) |
e4842ff3 MM |
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); | |
cba7c00f | 70 | if ((e && *e) || (x < 0 || x > 7)) |
e4842ff3 MM |
71 | return "Invalid function number"; |
72 | f->func = x; | |
73 | } | |
74 | return NULL; | |
75 | } | |
76 | ||
77 | /* ID filter syntax: [vendor]:[device] */ | |
78 | ||
79 | char * | |
727ce158 | 80 | pci_filter_parse_id(struct pci_filter *f, char *str) |
e4842ff3 MM |
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); | |
f2505ce4 | 93 | if ((e && *e) || (x < 0 || x > 0xffff)) |
e4842ff3 MM |
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); | |
f2505ce4 | 100 | if ((e && *e) || (x < 0 || x > 0xffff)) |
e4842ff3 MM |
101 | return "Invalid device ID"; |
102 | f->device = x; | |
103 | } | |
104 | return NULL; | |
105 | } | |
106 | ||
107 | int | |
727ce158 | 108 | pci_filter_match(struct pci_filter *f, struct pci_dev *d) |
e4842ff3 | 109 | { |
84c8d1bb MM |
110 | if ((f->domain >= 0 && f->domain != d->domain) || |
111 | (f->bus >= 0 && f->bus != d->bus) || | |
727ce158 MM |
112 | (f->slot >= 0 && f->slot != d->dev) || |
113 | (f->func >= 0 && f->func != d->func)) | |
e4842ff3 | 114 | return 0; |
727ce158 MM |
115 | if (f->device >= 0 || f->vendor >= 0) |
116 | { | |
dbe1e0a6 | 117 | pci_fill_info_v32(d, PCI_FILL_IDENT); |
727ce158 MM |
118 | if ((f->device >= 0 && f->device != d->device_id) || |
119 | (f->vendor >= 0 && f->vendor != d->vendor_id)) | |
120 | return 0; | |
121 | } | |
e4842ff3 MM |
122 | return 1; |
123 | } |