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