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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [pcmcia/] [socket_sysfs.c] - Blame information for rev 66

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

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * socket_sysfs.c -- most of socket-related sysfs output
3
 *
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License version 2 as
6
 * published by the Free Software Foundation.
7
 *
8
 * (C) 2003 - 2004              Dominik Brodowski
9
 */
10
 
11
#include <linux/module.h>
12
#include <linux/moduleparam.h>
13
#include <linux/init.h>
14
#include <linux/kernel.h>
15
#include <linux/string.h>
16
#include <linux/major.h>
17
#include <linux/errno.h>
18
#include <linux/slab.h>
19
#include <linux/mm.h>
20
#include <linux/interrupt.h>
21
#include <linux/timer.h>
22
#include <linux/ioport.h>
23
#include <linux/delay.h>
24
#include <linux/pm.h>
25
#include <linux/device.h>
26
#include <linux/mutex.h>
27
#include <asm/system.h>
28
#include <asm/irq.h>
29
 
30
#define IN_CARD_SERVICES
31
#include <pcmcia/cs_types.h>
32
#include <pcmcia/ss.h>
33
#include <pcmcia/cs.h>
34
#include <pcmcia/bulkmem.h>
35
#include <pcmcia/cistpl.h>
36
#include <pcmcia/cisreg.h>
37
#include <pcmcia/ds.h>
38
#include "cs_internal.h"
39
 
40
#define to_socket(_dev) container_of(_dev, struct pcmcia_socket, dev)
41
 
42
static ssize_t pccard_show_type(struct device *dev, struct device_attribute *attr,
43
                                char *buf)
44
{
45
        struct pcmcia_socket *s = to_socket(dev);
46
 
47
        if (!(s->state & SOCKET_PRESENT))
48
                return -ENODEV;
49
        if (s->state & SOCKET_CARDBUS)
50
                return sprintf(buf, "32-bit\n");
51
        return sprintf(buf, "16-bit\n");
52
}
53
static DEVICE_ATTR(card_type, 0444, pccard_show_type, NULL);
54
 
55
static ssize_t pccard_show_voltage(struct device *dev, struct device_attribute *attr,
56
                                   char *buf)
57
{
58
        struct pcmcia_socket *s = to_socket(dev);
59
 
60
        if (!(s->state & SOCKET_PRESENT))
61
                return -ENODEV;
62
        if (s->socket.Vcc)
63
                return sprintf(buf, "%d.%dV\n", s->socket.Vcc / 10,
64
                               s->socket.Vcc % 10);
65
        return sprintf(buf, "X.XV\n");
66
}
67
static DEVICE_ATTR(card_voltage, 0444, pccard_show_voltage, NULL);
68
 
69
static ssize_t pccard_show_vpp(struct device *dev, struct device_attribute *attr,
70
                               char *buf)
71
{
72
        struct pcmcia_socket *s = to_socket(dev);
73
        if (!(s->state & SOCKET_PRESENT))
74
                return -ENODEV;
75
        return sprintf(buf, "%d.%dV\n", s->socket.Vpp / 10, s->socket.Vpp % 10);
76
}
77
static DEVICE_ATTR(card_vpp, 0444, pccard_show_vpp, NULL);
78
 
79
static ssize_t pccard_show_vcc(struct device *dev, struct device_attribute *attr,
80
                               char *buf)
81
{
82
        struct pcmcia_socket *s = to_socket(dev);
83
        if (!(s->state & SOCKET_PRESENT))
84
                return -ENODEV;
85
        return sprintf(buf, "%d.%dV\n", s->socket.Vcc / 10, s->socket.Vcc % 10);
86
}
87
static DEVICE_ATTR(card_vcc, 0444, pccard_show_vcc, NULL);
88
 
89
 
90
static ssize_t pccard_store_insert(struct device *dev, struct device_attribute *attr,
91
                                   const char *buf, size_t count)
92
{
93
        ssize_t ret;
94
        struct pcmcia_socket *s = to_socket(dev);
95
 
96
        if (!count)
97
                return -EINVAL;
98
 
99
        ret = pcmcia_insert_card(s);
100
 
101
        return ret ? ret : count;
102
}
103
static DEVICE_ATTR(card_insert, 0200, NULL, pccard_store_insert);
104
 
105
 
106
static ssize_t pccard_show_card_pm_state(struct device *dev,
107
                                         struct device_attribute *attr,
108
                                         char *buf)
109
{
110
        struct pcmcia_socket *s = to_socket(dev);
111
        return sprintf(buf, "%s\n", s->state & SOCKET_SUSPEND ? "off" : "on");
112
}
113
 
114
static ssize_t pccard_store_card_pm_state(struct device *dev,
115
                                          struct device_attribute *attr,
116
                                          const char *buf, size_t count)
117
{
118
        ssize_t ret = -EINVAL;
119
        struct pcmcia_socket *s = to_socket(dev);
120
 
121
        if (!count)
122
                return -EINVAL;
123
 
124
        if (!(s->state & SOCKET_SUSPEND) && !strncmp(buf, "off", 3))
125
                ret = pcmcia_suspend_card(s);
126
        else if ((s->state & SOCKET_SUSPEND) && !strncmp(buf, "on", 2))
127
                ret = pcmcia_resume_card(s);
128
 
129
        return ret ? -ENODEV : count;
130
}
131
static DEVICE_ATTR(card_pm_state, 0644, pccard_show_card_pm_state, pccard_store_card_pm_state);
132
 
133
static ssize_t pccard_store_eject(struct device *dev,
134
                                  struct device_attribute *attr,
135
                                  const char *buf, size_t count)
136
{
137
        ssize_t ret;
138
        struct pcmcia_socket *s = to_socket(dev);
139
 
140
        if (!count)
141
                return -EINVAL;
142
 
143
        ret = pcmcia_eject_card(s);
144
 
145
        return ret ? ret : count;
146
}
147
static DEVICE_ATTR(card_eject, 0200, NULL, pccard_store_eject);
148
 
149
 
150
static ssize_t pccard_show_irq_mask(struct device *dev,
151
                                    struct device_attribute *attr,
152
                                    char *buf)
153
{
154
        struct pcmcia_socket *s = to_socket(dev);
155
        return sprintf(buf, "0x%04x\n", s->irq_mask);
156
}
157
 
158
static ssize_t pccard_store_irq_mask(struct device *dev,
159
                                     struct device_attribute *attr,
160
                                     const char *buf, size_t count)
161
{
162
        ssize_t ret;
163
        struct pcmcia_socket *s = to_socket(dev);
164
        u32 mask;
165
 
166
        if (!count)
167
                return -EINVAL;
168
 
169
        ret = sscanf (buf, "0x%x\n", &mask);
170
 
171
        if (ret == 1) {
172
                s->irq_mask &= mask;
173
                ret = 0;
174
        }
175
 
176
        return ret ? ret : count;
177
}
178
static DEVICE_ATTR(card_irq_mask, 0600, pccard_show_irq_mask, pccard_store_irq_mask);
179
 
180
 
181
static ssize_t pccard_show_resource(struct device *dev,
182
                                    struct device_attribute *attr, char *buf)
183
{
184
        struct pcmcia_socket *s = to_socket(dev);
185
        return sprintf(buf, "%s\n", s->resource_setup_done ? "yes" : "no");
186
}
187
 
188
static ssize_t pccard_store_resource(struct device *dev,
189
                                     struct device_attribute *attr,
190
                                     const char *buf, size_t count)
191
{
192
        unsigned long flags;
193
        struct pcmcia_socket *s = to_socket(dev);
194
 
195
        if (!count)
196
                return -EINVAL;
197
 
198
        spin_lock_irqsave(&s->lock, flags);
199
        if (!s->resource_setup_done)
200
                s->resource_setup_done = 1;
201
        spin_unlock_irqrestore(&s->lock, flags);
202
 
203
        mutex_lock(&s->skt_mutex);
204
        if ((s->callback) &&
205
            (s->state & SOCKET_PRESENT) &&
206
            !(s->state & SOCKET_CARDBUS)) {
207
                if (try_module_get(s->callback->owner)) {
208
                        s->callback->requery(s, 0);
209
                        module_put(s->callback->owner);
210
                }
211
        }
212
        mutex_unlock(&s->skt_mutex);
213
 
214
        return count;
215
}
216
static DEVICE_ATTR(available_resources_setup_done, 0600, pccard_show_resource, pccard_store_resource);
217
 
218
 
219
static ssize_t pccard_extract_cis(struct pcmcia_socket *s, char *buf, loff_t off, size_t count)
220
{
221
        tuple_t tuple;
222
        int status, i;
223
        loff_t pointer = 0;
224
        ssize_t ret = 0;
225
        u_char *tuplebuffer;
226
        u_char *tempbuffer;
227
 
228
        tuplebuffer = kmalloc(sizeof(u_char) * 256, GFP_KERNEL);
229
        if (!tuplebuffer)
230
                return -ENOMEM;
231
 
232
        tempbuffer = kmalloc(sizeof(u_char) * 258, GFP_KERNEL);
233
        if (!tempbuffer) {
234
                ret = -ENOMEM;
235
                goto free_tuple;
236
        }
237
 
238
        memset(&tuple, 0, sizeof(tuple_t));
239
 
240
        tuple.Attributes = TUPLE_RETURN_LINK | TUPLE_RETURN_COMMON;
241
        tuple.DesiredTuple = RETURN_FIRST_TUPLE;
242
        tuple.TupleOffset = 0;
243
 
244
        status = pccard_get_first_tuple(s, BIND_FN_ALL, &tuple);
245
        while (!status) {
246
                tuple.TupleData = tuplebuffer;
247
                tuple.TupleDataMax = 255;
248
                memset(tuplebuffer, 0, sizeof(u_char) * 255);
249
 
250
                status = pccard_get_tuple_data(s, &tuple);
251
                if (status)
252
                        break;
253
 
254
                if (off < (pointer + 2 + tuple.TupleDataLen)) {
255
                        tempbuffer[0] = tuple.TupleCode & 0xff;
256
                        tempbuffer[1] = tuple.TupleLink & 0xff;
257
                        for (i = 0; i < tuple.TupleDataLen; i++)
258
                                tempbuffer[i + 2] = tuplebuffer[i] & 0xff;
259
 
260
                        for (i = 0; i < (2 + tuple.TupleDataLen); i++) {
261
                                if (((i + pointer) >= off) &&
262
                                    (i + pointer) < (off + count)) {
263
                                        buf[ret] = tempbuffer[i];
264
                                        ret++;
265
                                }
266
                        }
267
                }
268
 
269
                pointer += 2 + tuple.TupleDataLen;
270
 
271
                if (pointer >= (off + count))
272
                        break;
273
 
274
                if (tuple.TupleCode == CISTPL_END)
275
                        break;
276
                status = pccard_get_next_tuple(s, BIND_FN_ALL, &tuple);
277
        }
278
 
279
        kfree(tempbuffer);
280
 free_tuple:
281
        kfree(tuplebuffer);
282
 
283
        return (ret);
284
}
285
 
286
static ssize_t pccard_show_cis(struct kobject *kobj,
287
                               struct bin_attribute *bin_attr,
288
                               char *buf, loff_t off, size_t count)
289
{
290
        unsigned int size = 0x200;
291
 
292
        if (off >= size)
293
                count = 0;
294
        else {
295
                struct pcmcia_socket *s;
296
                cisinfo_t cisinfo;
297
 
298
                if (off + count > size)
299
                        count = size - off;
300
 
301
                s = to_socket(container_of(kobj, struct device, kobj));
302
 
303
                if (!(s->state & SOCKET_PRESENT))
304
                        return -ENODEV;
305
                if (pccard_validate_cis(s, BIND_FN_ALL, &cisinfo))
306
                        return -EIO;
307
                if (!cisinfo.Chains)
308
                        return -ENODATA;
309
 
310
                count = pccard_extract_cis(s, buf, off, count);
311
        }
312
 
313
        return (count);
314
}
315
 
316
static ssize_t pccard_store_cis(struct kobject *kobj,
317
                                struct bin_attribute *bin_attr,
318
                                char *buf, loff_t off, size_t count)
319
{
320
        struct pcmcia_socket *s = to_socket(container_of(kobj, struct device, kobj));
321
        cisdump_t *cis;
322
        int error;
323
 
324
        if (off)
325
                return -EINVAL;
326
 
327
        if (count >= 0x200)
328
                return -EINVAL;
329
 
330
        if (!(s->state & SOCKET_PRESENT))
331
                return -ENODEV;
332
 
333
        cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL);
334
        if (!cis)
335
                return -ENOMEM;
336
 
337
        cis->Length = count + 1;
338
        memcpy(cis->Data, buf, count);
339
 
340
        error = pcmcia_replace_cis(s, cis);
341
        kfree(cis);
342
        if (error)
343
                return -EIO;
344
 
345
        mutex_lock(&s->skt_mutex);
346
        if ((s->callback) && (s->state & SOCKET_PRESENT) &&
347
            !(s->state & SOCKET_CARDBUS)) {
348
                if (try_module_get(s->callback->owner)) {
349
                        s->callback->requery(s, 1);
350
                        module_put(s->callback->owner);
351
                }
352
        }
353
        mutex_unlock(&s->skt_mutex);
354
 
355
        return count;
356
}
357
 
358
 
359
static struct device_attribute *pccard_socket_attributes[] = {
360
        &dev_attr_card_type,
361
        &dev_attr_card_voltage,
362
        &dev_attr_card_vpp,
363
        &dev_attr_card_vcc,
364
        &dev_attr_card_insert,
365
        &dev_attr_card_pm_state,
366
        &dev_attr_card_eject,
367
        &dev_attr_card_irq_mask,
368
        &dev_attr_available_resources_setup_done,
369
        NULL,
370
};
371
 
372
static struct bin_attribute pccard_cis_attr = {
373
        .attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR },
374
        .size = 0x200,
375
        .read = pccard_show_cis,
376
        .write = pccard_store_cis,
377
};
378
 
379
static int __devinit pccard_sysfs_add_socket(struct device *dev,
380
                                             struct class_interface *class_intf)
381
{
382
        struct device_attribute **attr;
383
        int ret = 0;
384
 
385
        for (attr = pccard_socket_attributes; *attr; attr++) {
386
                ret = device_create_file(dev, *attr);
387
                if (ret)
388
                        break;
389
        }
390
        if (!ret)
391
                ret = sysfs_create_bin_file(&dev->kobj, &pccard_cis_attr);
392
 
393
        return ret;
394
}
395
 
396
static void __devexit pccard_sysfs_remove_socket(struct device *dev,
397
                                                 struct class_interface *class_intf)
398
{
399
        struct device_attribute **attr;
400
 
401
        sysfs_remove_bin_file(&dev->kobj, &pccard_cis_attr);
402
        for (attr = pccard_socket_attributes; *attr; attr++)
403
                device_remove_file(dev, *attr);
404
}
405
 
406
struct class_interface pccard_sysfs_interface = {
407
        .class = &pcmcia_socket_class,
408
        .add_dev = &pccard_sysfs_add_socket,
409
        .remove_dev = __devexit_p(&pccard_sysfs_remove_socket),
410
};

powered by: WebSVN 2.1.0

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