]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * The PCI Library -- Device Filtering | |
3 | * | |
4 | * Copyright (c) 1998--2003 Martin Mares <mj@ucw.cz> | |
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(str, &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_v32(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 | } |