Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
xen
xen-pciback
conf_space_quirks.c
Go to the documentation of this file.
1
/*
2
* PCI Backend - Handle special overlays for broken devices.
3
*
4
* Author: Ryan Wilson <
[email protected]
>
5
* Author: Chris Bookholt <
[email protected]
>
6
*/
7
8
#include <linux/kernel.h>
9
#include <linux/pci.h>
10
#include "
pciback.h
"
11
#include "
conf_space.h
"
12
#include "
conf_space_quirks.h
"
13
14
LIST_HEAD
(xen_pcibk_quirks);
15
static
inline
const
struct
pci_device_id
*
16
match_one_device(
const
struct
pci_device_id
*
id
,
const
struct
pci_dev
*
dev
)
17
{
18
if
((id->
vendor
==
PCI_ANY_ID
|| id->
vendor
== dev->
vendor
) &&
19
(id->
device
==
PCI_ANY_ID
|| id->
device
== dev->
device
) &&
20
(id->
subvendor
==
PCI_ANY_ID
||
21
id->
subvendor
== dev->
subsystem_vendor
) &&
22
(id->
subdevice
==
PCI_ANY_ID
||
23
id->
subdevice
== dev->
subsystem_device
) &&
24
!((id->
class
^ dev->
class
) & id->
class_mask
))
25
return
id
;
26
return
NULL
;
27
}
28
29
static
struct
xen_pcibk_config_quirk
*xen_pcibk_find_quirk(
struct
pci_dev
*dev)
30
{
31
struct
xen_pcibk_config_quirk
*tmp_quirk;
32
33
list_for_each_entry
(tmp_quirk, &xen_pcibk_quirks,
quirks_list
)
34
if
(match_one_device(&tmp_quirk->
devid
, dev) !=
NULL
)
35
goto
out
;
36
tmp_quirk =
NULL
;
37
printk
(
KERN_DEBUG
DRV_NAME
38
": quirk didn'
t
match
any
device
known\
n
");
39
out:
40
return
tmp_quirk;
41
}
42
43
static
inline
void
register_quirk(
struct
xen_pcibk_config_quirk
*quirk)
44
{
45
list_add_tail
(&quirk->quirks_list, &xen_pcibk_quirks);
46
}
47
48
int
xen_pcibk_field_is_dup
(
struct
pci_dev
*dev,
unsigned
int
reg
)
49
{
50
int
ret
= 0;
51
struct
xen_pcibk_dev_data
*
dev_data
= pci_get_drvdata(dev);
52
struct
config_field_entry
*
cfg_entry
;
53
54
list_for_each_entry
(cfg_entry, &dev_data->
config_fields
,
list
) {
55
if
(
OFFSET
(cfg_entry) == reg) {
56
ret = 1;
57
break
;
58
}
59
}
60
return
ret
;
61
}
62
63
int
xen_pcibk_config_quirks_add_field
(
struct
pci_dev
*dev,
struct
config_field
64
*
field
)
65
{
66
int
err
= 0;
67
68
switch
(field->
size
) {
69
case
1:
70
field->
u
.
b
.read =
xen_pcibk_read_config_byte
;
71
field->
u
.
b
.write =
xen_pcibk_write_config_byte
;
72
break
;
73
case
2:
74
field->
u
.
w
.read =
xen_pcibk_read_config_word
;
75
field->
u
.
w
.write =
xen_pcibk_write_config_word
;
76
break
;
77
case
4:
78
field->
u
.
dw
.read =
xen_pcibk_read_config_dword
;
79
field->
u
.
dw
.write =
xen_pcibk_write_config_dword
;
80
break
;
81
default
:
82
err = -
EINVAL
;
83
goto
out
;
84
}
85
86
xen_pcibk_config_add_field(dev, field);
87
88
out
:
89
return
err
;
90
}
91
92
int
xen_pcibk_config_quirks_init
(
struct
pci_dev
*dev)
93
{
94
struct
xen_pcibk_config_quirk
*quirk;
95
int
ret
= 0;
96
97
quirk = kzalloc(
sizeof
(*quirk),
GFP_ATOMIC
);
98
if
(!quirk) {
99
ret = -
ENOMEM
;
100
goto
out
;
101
}
102
103
quirk->
devid
.vendor = dev->
vendor
;
104
quirk->
devid
.device = dev->
device
;
105
quirk->
devid
.subvendor = dev->
subsystem_vendor
;
106
quirk->
devid
.subdevice = dev->
subsystem_device
;
107
quirk->
devid
.class = 0;
108
quirk->
devid
.class_mask = 0;
109
quirk->
devid
.driver_data = 0
UL
;
110
111
quirk->
pdev
=
dev
;
112
113
register_quirk(quirk);
114
out
:
115
return
ret
;
116
}
117
118
void
xen_pcibk_config_field_free
(
struct
config_field
*
field
)
119
{
120
kfree
(field);
121
}
122
123
int
xen_pcibk_config_quirk_release
(
struct
pci_dev
*dev)
124
{
125
struct
xen_pcibk_config_quirk
*quirk;
126
int
ret
= 0;
127
128
quirk = xen_pcibk_find_quirk(dev);
129
if
(!quirk) {
130
ret = -
ENXIO
;
131
goto
out
;
132
}
133
134
list_del
(&quirk->
quirks_list
);
135
kfree
(quirk);
136
137
out
:
138
return
ret
;
139
}
Generated on Thu Jan 10 2013 14:43:34 for Linux Kernel by
1.8.2