Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/base/isa.c
26378 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* ISA bus.
4
*/
5
6
#include <linux/device.h>
7
#include <linux/kernel.h>
8
#include <linux/slab.h>
9
#include <linux/module.h>
10
#include <linux/init.h>
11
#include <linux/dma-mapping.h>
12
#include <linux/isa.h>
13
14
static struct device isa_bus = {
15
.init_name = "isa"
16
};
17
18
struct isa_dev {
19
struct device dev;
20
struct device *next;
21
unsigned int id;
22
};
23
24
#define to_isa_dev(x) container_of((x), struct isa_dev, dev)
25
26
static int isa_bus_match(struct device *dev, const struct device_driver *driver)
27
{
28
struct isa_driver *isa_driver = to_isa_driver(driver);
29
30
if (dev->platform_data == isa_driver) {
31
if (!isa_driver->match ||
32
isa_driver->match(dev, to_isa_dev(dev)->id))
33
return 1;
34
dev->platform_data = NULL;
35
}
36
return 0;
37
}
38
39
static int isa_bus_probe(struct device *dev)
40
{
41
struct isa_driver *isa_driver = dev->platform_data;
42
43
if (isa_driver && isa_driver->probe)
44
return isa_driver->probe(dev, to_isa_dev(dev)->id);
45
46
return 0;
47
}
48
49
static void isa_bus_remove(struct device *dev)
50
{
51
struct isa_driver *isa_driver = dev->platform_data;
52
53
if (isa_driver && isa_driver->remove)
54
isa_driver->remove(dev, to_isa_dev(dev)->id);
55
}
56
57
static void isa_bus_shutdown(struct device *dev)
58
{
59
struct isa_driver *isa_driver = dev->platform_data;
60
61
if (isa_driver && isa_driver->shutdown)
62
isa_driver->shutdown(dev, to_isa_dev(dev)->id);
63
}
64
65
static int isa_bus_suspend(struct device *dev, pm_message_t state)
66
{
67
struct isa_driver *isa_driver = dev->platform_data;
68
69
if (isa_driver && isa_driver->suspend)
70
return isa_driver->suspend(dev, to_isa_dev(dev)->id, state);
71
72
return 0;
73
}
74
75
static int isa_bus_resume(struct device *dev)
76
{
77
struct isa_driver *isa_driver = dev->platform_data;
78
79
if (isa_driver && isa_driver->resume)
80
return isa_driver->resume(dev, to_isa_dev(dev)->id);
81
82
return 0;
83
}
84
85
static const struct bus_type isa_bus_type = {
86
.name = "isa",
87
.match = isa_bus_match,
88
.probe = isa_bus_probe,
89
.remove = isa_bus_remove,
90
.shutdown = isa_bus_shutdown,
91
.suspend = isa_bus_suspend,
92
.resume = isa_bus_resume
93
};
94
95
static void isa_dev_release(struct device *dev)
96
{
97
kfree(to_isa_dev(dev));
98
}
99
100
void isa_unregister_driver(struct isa_driver *isa_driver)
101
{
102
struct device *dev = isa_driver->devices;
103
104
while (dev) {
105
struct device *tmp = to_isa_dev(dev)->next;
106
device_unregister(dev);
107
dev = tmp;
108
}
109
driver_unregister(&isa_driver->driver);
110
}
111
EXPORT_SYMBOL_GPL(isa_unregister_driver);
112
113
int isa_register_driver(struct isa_driver *isa_driver, unsigned int ndev)
114
{
115
int error;
116
unsigned int id;
117
118
isa_driver->driver.bus = &isa_bus_type;
119
isa_driver->devices = NULL;
120
121
error = driver_register(&isa_driver->driver);
122
if (error)
123
return error;
124
125
for (id = 0; id < ndev; id++) {
126
struct isa_dev *isa_dev;
127
128
isa_dev = kzalloc(sizeof *isa_dev, GFP_KERNEL);
129
if (!isa_dev) {
130
error = -ENOMEM;
131
break;
132
}
133
134
isa_dev->dev.parent = &isa_bus;
135
isa_dev->dev.bus = &isa_bus_type;
136
137
dev_set_name(&isa_dev->dev, "%s.%u",
138
isa_driver->driver.name, id);
139
isa_dev->dev.platform_data = isa_driver;
140
isa_dev->dev.release = isa_dev_release;
141
isa_dev->id = id;
142
143
isa_dev->dev.coherent_dma_mask = DMA_BIT_MASK(24);
144
isa_dev->dev.dma_mask = &isa_dev->dev.coherent_dma_mask;
145
146
error = device_register(&isa_dev->dev);
147
if (error) {
148
put_device(&isa_dev->dev);
149
break;
150
}
151
152
isa_dev->next = isa_driver->devices;
153
isa_driver->devices = &isa_dev->dev;
154
}
155
156
if (!error && !isa_driver->devices)
157
error = -ENODEV;
158
159
if (error)
160
isa_unregister_driver(isa_driver);
161
162
return error;
163
}
164
EXPORT_SYMBOL_GPL(isa_register_driver);
165
166
static int __init isa_bus_init(void)
167
{
168
int error;
169
170
error = bus_register(&isa_bus_type);
171
if (!error) {
172
error = device_register(&isa_bus);
173
if (error)
174
bus_unregister(&isa_bus_type);
175
}
176
return error;
177
}
178
179
postcore_initcall(isa_bus_init);
180
181