OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [pnp/] [driver.c] - Blame information for rev 65

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * driver.c - device id matching, driver model, etc.
3
 *
4
 * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
5
 */
6
 
7
#include <linux/string.h>
8
#include <linux/list.h>
9
#include <linux/module.h>
10
#include <linux/ctype.h>
11
#include <linux/slab.h>
12
#include <linux/pnp.h>
13
#include "base.h"
14
 
15
static int compare_func(const char *ida, const char *idb)
16
{
17
        int i;
18
 
19
        /* we only need to compare the last 4 chars */
20
        for (i = 3; i < 7; i++) {
21
                if (ida[i] != 'X' &&
22
                    idb[i] != 'X' && toupper(ida[i]) != toupper(idb[i]))
23
                        return 0;
24
        }
25
        return 1;
26
}
27
 
28
int compare_pnp_id(struct pnp_id *pos, const char *id)
29
{
30
        if (!pos || !id || (strlen(id) != 7))
31
                return 0;
32
        if (memcmp(id, "ANYDEVS", 7) == 0)
33
                return 1;
34
        while (pos) {
35
                if (memcmp(pos->id, id, 3) == 0)
36
                        if (compare_func(pos->id, id) == 1)
37
                                return 1;
38
                pos = pos->next;
39
        }
40
        return 0;
41
}
42
 
43
static const struct pnp_device_id *match_device(struct pnp_driver *drv,
44
                                                struct pnp_dev *dev)
45
{
46
        const struct pnp_device_id *drv_id = drv->id_table;
47
 
48
        if (!drv_id)
49
                return NULL;
50
 
51
        while (*drv_id->id) {
52
                if (compare_pnp_id(dev->id, drv_id->id))
53
                        return drv_id;
54
                drv_id++;
55
        }
56
        return NULL;
57
}
58
 
59
int pnp_device_attach(struct pnp_dev *pnp_dev)
60
{
61
        spin_lock(&pnp_lock);
62
        if (pnp_dev->status != PNP_READY) {
63
                spin_unlock(&pnp_lock);
64
                return -EBUSY;
65
        }
66
        pnp_dev->status = PNP_ATTACHED;
67
        spin_unlock(&pnp_lock);
68
        return 0;
69
}
70
 
71
void pnp_device_detach(struct pnp_dev *pnp_dev)
72
{
73
        spin_lock(&pnp_lock);
74
        if (pnp_dev->status == PNP_ATTACHED)
75
                pnp_dev->status = PNP_READY;
76
        spin_unlock(&pnp_lock);
77
        pnp_disable_dev(pnp_dev);
78
}
79
 
80
static int pnp_device_probe(struct device *dev)
81
{
82
        int error;
83
        struct pnp_driver *pnp_drv;
84
        struct pnp_dev *pnp_dev;
85
        const struct pnp_device_id *dev_id = NULL;
86
        pnp_dev = to_pnp_dev(dev);
87
        pnp_drv = to_pnp_driver(dev->driver);
88
 
89
        error = pnp_device_attach(pnp_dev);
90
        if (error < 0)
91
                return error;
92
 
93
        if (pnp_dev->active == 0) {
94
                if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)) {
95
                        error = pnp_activate_dev(pnp_dev);
96
                        if (error < 0)
97
                                return error;
98
                }
99
        } else if ((pnp_drv->flags & PNP_DRIVER_RES_DISABLE)
100
                   == PNP_DRIVER_RES_DISABLE) {
101
                error = pnp_disable_dev(pnp_dev);
102
                if (error < 0)
103
                        return error;
104
        }
105
        error = 0;
106
        if (pnp_drv->probe) {
107
                dev_id = match_device(pnp_drv, pnp_dev);
108
                if (dev_id != NULL)
109
                        error = pnp_drv->probe(pnp_dev, dev_id);
110
        }
111
        if (error >= 0) {
112
                pnp_dev->driver = pnp_drv;
113
                error = 0;
114
        } else
115
                goto fail;
116
 
117
        dev_dbg(dev, "driver attached\n");
118
        return error;
119
 
120
fail:
121
        pnp_device_detach(pnp_dev);
122
        return error;
123
}
124
 
125
static int pnp_device_remove(struct device *dev)
126
{
127
        struct pnp_dev *pnp_dev = to_pnp_dev(dev);
128
        struct pnp_driver *drv = pnp_dev->driver;
129
 
130
        if (drv) {
131
                if (drv->remove)
132
                        drv->remove(pnp_dev);
133
                pnp_dev->driver = NULL;
134
        }
135
        pnp_device_detach(pnp_dev);
136
        return 0;
137
}
138
 
139
static int pnp_bus_match(struct device *dev, struct device_driver *drv)
140
{
141
        struct pnp_dev *pnp_dev = to_pnp_dev(dev);
142
        struct pnp_driver *pnp_drv = to_pnp_driver(drv);
143
 
144
        if (match_device(pnp_drv, pnp_dev) == NULL)
145
                return 0;
146
        return 1;
147
}
148
 
149
static int pnp_bus_suspend(struct device *dev, pm_message_t state)
150
{
151
        struct pnp_dev *pnp_dev = to_pnp_dev(dev);
152
        struct pnp_driver *pnp_drv = pnp_dev->driver;
153
        int error;
154
 
155
        if (!pnp_drv)
156
                return 0;
157
 
158
        if (pnp_drv->suspend) {
159
                error = pnp_drv->suspend(pnp_dev, state);
160
                if (error)
161
                        return error;
162
        }
163
 
164
        if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE) &&
165
            pnp_can_disable(pnp_dev)) {
166
                error = pnp_stop_dev(pnp_dev);
167
                if (error)
168
                        return error;
169
        }
170
 
171
        if (pnp_dev->protocol && pnp_dev->protocol->suspend)
172
                pnp_dev->protocol->suspend(pnp_dev, state);
173
        return 0;
174
}
175
 
176
static int pnp_bus_resume(struct device *dev)
177
{
178
        struct pnp_dev *pnp_dev = to_pnp_dev(dev);
179
        struct pnp_driver *pnp_drv = pnp_dev->driver;
180
        int error;
181
 
182
        if (!pnp_drv)
183
                return 0;
184
 
185
        if (pnp_dev->protocol && pnp_dev->protocol->resume)
186
                pnp_dev->protocol->resume(pnp_dev);
187
 
188
        if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)) {
189
                error = pnp_start_dev(pnp_dev);
190
                if (error)
191
                        return error;
192
        }
193
 
194
        if (pnp_drv->resume)
195
                return pnp_drv->resume(pnp_dev);
196
 
197
        return 0;
198
}
199
 
200
struct bus_type pnp_bus_type = {
201
        .name    = "pnp",
202
        .match   = pnp_bus_match,
203
        .probe   = pnp_device_probe,
204
        .remove  = pnp_device_remove,
205
        .suspend = pnp_bus_suspend,
206
        .resume  = pnp_bus_resume,
207
};
208
 
209
int pnp_register_driver(struct pnp_driver *drv)
210
{
211
        pnp_dbg("the driver '%s' has been registered", drv->name);
212
 
213
        drv->driver.name = drv->name;
214
        drv->driver.bus = &pnp_bus_type;
215
 
216
        return driver_register(&drv->driver);
217
}
218
 
219
void pnp_unregister_driver(struct pnp_driver *drv)
220
{
221
        driver_unregister(&drv->driver);
222
        pnp_dbg("the driver '%s' has been unregistered", drv->name);
223
}
224
 
225
/**
226
 * pnp_add_id - adds an EISA id to the specified device
227
 * @id: pointer to a pnp_id structure
228
 * @dev: pointer to the desired device
229
 */
230
int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev)
231
{
232
        struct pnp_id *ptr;
233
 
234
        id->next = NULL;
235
        ptr = dev->id;
236
        while (ptr && ptr->next)
237
                ptr = ptr->next;
238
        if (ptr)
239
                ptr->next = id;
240
        else
241
                dev->id = id;
242
        return 0;
243
}
244
 
245
EXPORT_SYMBOL(pnp_register_driver);
246
EXPORT_SYMBOL(pnp_unregister_driver);
247
EXPORT_SYMBOL(pnp_device_attach);
248
EXPORT_SYMBOL(pnp_device_detach);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.