aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2010-01-06 07:57:43 -0500
committerDominik Brodowski <linux@dominikbrodowski.net>2010-02-17 11:37:30 -0500
commit6e7b51a733fde86d3be748543215a69da04d5bb7 (patch)
tree4c608cf607ef1bb69231f4c67d45a9ac9429e650 /drivers
parent4e8804ff6dd1a842d9531c819a0acc9eb3bcfa3b (diff)
pcmcia: move cistpl.c into pcmcia module
As PCMCIA is the only real user of CIS access functions, include cistpl.c in the PCMCIA module, not in the PCMCIA & CardBus core module. Tested-by: Wolfram Sang <w.sang@pengutronix.de> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pcmcia/Makefile4
-rw-r--r--drivers/pcmcia/cistpl.c158
-rw-r--r--drivers/pcmcia/cs_internal.h44
-rw-r--r--drivers/pcmcia/ds.c10
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c4
-rw-r--r--drivers/pcmcia/socket_sysfs.c150
6 files changed, 183 insertions, 187 deletions
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index 83ff802de544..3c83f68c803a 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -2,11 +2,11 @@
2# Makefile for the kernel pcmcia subsystem (c/o David Hinds) 2# Makefile for the kernel pcmcia subsystem (c/o David Hinds)
3# 3#
4 4
5pcmcia_core-y += cs.o cistpl.o rsrc_mgr.o socket_sysfs.o 5pcmcia_core-y += cs.o rsrc_mgr.o socket_sysfs.o
6pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o 6pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o
7obj-$(CONFIG_PCCARD) += pcmcia_core.o 7obj-$(CONFIG_PCCARD) += pcmcia_core.o
8 8
9pcmcia-y += ds.o pcmcia_resource.o 9pcmcia-y += ds.o pcmcia_resource.o cistpl.o
10pcmcia-$(CONFIG_PCMCIA_IOCTL) += pcmcia_ioctl.o 10pcmcia-$(CONFIG_PCMCIA_IOCTL) += pcmcia_ioctl.o
11obj-$(CONFIG_PCMCIA) += pcmcia.o 11obj-$(CONFIG_PCMCIA) += pcmcia.o
12 12
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 368367ced62b..936417c3e79e 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -76,7 +76,6 @@ void release_cis_mem(struct pcmcia_socket *s)
76 s->cis_virt = NULL; 76 s->cis_virt = NULL;
77 } 77 }
78} 78}
79EXPORT_SYMBOL(release_cis_mem);
80 79
81/* 80/*
82 * Map the card memory at "card_offset" into virtual space. 81 * Map the card memory at "card_offset" into virtual space.
@@ -195,7 +194,6 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
195 *(u_char *)(ptr+2), *(u_char *)(ptr+3)); 194 *(u_char *)(ptr+2), *(u_char *)(ptr+3));
196 return 0; 195 return 0;
197} 196}
198EXPORT_SYMBOL(pcmcia_read_cis_mem);
199 197
200 198
201void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, 199void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
@@ -254,7 +252,6 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
254 } 252 }
255 } 253 }
256} 254}
257EXPORT_SYMBOL(pcmcia_write_cis_mem);
258 255
259 256
260/*====================================================================== 257/*======================================================================
@@ -335,7 +332,6 @@ void destroy_cis_cache(struct pcmcia_socket *s)
335 kfree(cis); 332 kfree(cis);
336 } 333 }
337} 334}
338EXPORT_SYMBOL(destroy_cis_cache);
339 335
340/*====================================================================== 336/*======================================================================
341 337
@@ -374,7 +370,6 @@ int verify_cis_cache(struct pcmcia_socket *s)
374 kfree(buf); 370 kfree(buf);
375 return 0; 371 return 0;
376} 372}
377EXPORT_SYMBOL(verify_cis_cache);
378 373
379/*====================================================================== 374/*======================================================================
380 375
@@ -400,7 +395,6 @@ int pcmcia_replace_cis(struct pcmcia_socket *s,
400 memcpy(s->fake_cis, data, len); 395 memcpy(s->fake_cis, data, len);
401 return 0; 396 return 0;
402} 397}
403EXPORT_SYMBOL(pcmcia_replace_cis);
404 398
405/*====================================================================== 399/*======================================================================
406 400
@@ -446,7 +440,6 @@ int pccard_get_first_tuple(struct pcmcia_socket *s, unsigned int function, tuple
446 } 440 }
447 return pccard_get_next_tuple(s, function, tuple); 441 return pccard_get_next_tuple(s, function, tuple);
448} 442}
449EXPORT_SYMBOL(pccard_get_first_tuple);
450 443
451static int follow_link(struct pcmcia_socket *s, tuple_t *tuple) 444static int follow_link(struct pcmcia_socket *s, tuple_t *tuple)
452{ 445{
@@ -582,7 +575,6 @@ int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function, tuple_
582 tuple->CISOffset = ofs + 2; 575 tuple->CISOffset = ofs + 2;
583 return 0; 576 return 0;
584} 577}
585EXPORT_SYMBOL(pccard_get_next_tuple);
586 578
587/*====================================================================*/ 579/*====================================================================*/
588 580
@@ -606,7 +598,6 @@ int pccard_get_tuple_data(struct pcmcia_socket *s, tuple_t *tuple)
606 _MIN(len, tuple->TupleDataMax), tuple->TupleData); 598 _MIN(len, tuple->TupleDataMax), tuple->TupleData);
607 return 0; 599 return 0;
608} 600}
609EXPORT_SYMBOL(pccard_get_tuple_data);
610 601
611 602
612/*====================================================================== 603/*======================================================================
@@ -1379,7 +1370,6 @@ done:
1379 kfree(buf); 1370 kfree(buf);
1380 return ret; 1371 return ret;
1381} 1372}
1382EXPORT_SYMBOL(pccard_read_tuple);
1383 1373
1384 1374
1385/** 1375/**
@@ -1439,7 +1429,6 @@ next_entry:
1439 kfree(buf); 1429 kfree(buf);
1440 return ret; 1430 return ret;
1441} 1431}
1442EXPORT_SYMBOL(pccard_loop_tuple);
1443 1432
1444 1433
1445/** 1434/**
@@ -1533,4 +1522,149 @@ done:
1533 kfree(p); 1522 kfree(p);
1534 return ret; 1523 return ret;
1535} 1524}
1536EXPORT_SYMBOL(pccard_validate_cis); 1525
1526
1527#define to_socket(_dev) container_of(_dev, struct pcmcia_socket, dev)
1528
1529static ssize_t pccard_extract_cis(struct pcmcia_socket *s, char *buf,
1530 loff_t off, size_t count)
1531{
1532 tuple_t tuple;
1533 int status, i;
1534 loff_t pointer = 0;
1535 ssize_t ret = 0;
1536 u_char *tuplebuffer;
1537 u_char *tempbuffer;
1538
1539 tuplebuffer = kmalloc(sizeof(u_char) * 256, GFP_KERNEL);
1540 if (!tuplebuffer)
1541 return -ENOMEM;
1542
1543 tempbuffer = kmalloc(sizeof(u_char) * 258, GFP_KERNEL);
1544 if (!tempbuffer) {
1545 ret = -ENOMEM;
1546 goto free_tuple;
1547 }
1548
1549 memset(&tuple, 0, sizeof(tuple_t));
1550
1551 tuple.Attributes = TUPLE_RETURN_LINK | TUPLE_RETURN_COMMON;
1552 tuple.DesiredTuple = RETURN_FIRST_TUPLE;
1553 tuple.TupleOffset = 0;
1554
1555 status = pccard_get_first_tuple(s, BIND_FN_ALL, &tuple);
1556 while (!status) {
1557 tuple.TupleData = tuplebuffer;
1558 tuple.TupleDataMax = 255;
1559 memset(tuplebuffer, 0, sizeof(u_char) * 255);
1560
1561 status = pccard_get_tuple_data(s, &tuple);
1562 if (status)
1563 break;
1564
1565 if (off < (pointer + 2 + tuple.TupleDataLen)) {
1566 tempbuffer[0] = tuple.TupleCode & 0xff;
1567 tempbuffer[1] = tuple.TupleLink & 0xff;
1568 for (i = 0; i < tuple.TupleDataLen; i++)
1569 tempbuffer[i + 2] = tuplebuffer[i] & 0xff;
1570
1571 for (i = 0; i < (2 + tuple.TupleDataLen); i++) {
1572 if (((i + pointer) >= off) &&
1573 (i + pointer) < (off + count)) {
1574 buf[ret] = tempbuffer[i];
1575 ret++;
1576 }
1577 }
1578 }
1579
1580 pointer += 2 + tuple.TupleDataLen;
1581
1582 if (pointer >= (off + count))
1583 break;
1584
1585 if (tuple.TupleCode == CISTPL_END)
1586 break;
1587 status = pccard_get_next_tuple(s, BIND_FN_ALL, &tuple);
1588 }
1589
1590 kfree(tempbuffer);
1591 free_tuple:
1592 kfree(tuplebuffer);
1593
1594 return ret;
1595}
1596
1597
1598static ssize_t pccard_show_cis(struct kobject *kobj,
1599 struct bin_attribute *bin_attr,
1600 char *buf, loff_t off, size_t count)
1601{
1602 unsigned int size = 0x200;
1603
1604 if (off >= size)
1605 count = 0;
1606 else {
1607 struct pcmcia_socket *s;
1608 unsigned int chains;
1609
1610 if (off + count > size)
1611 count = size - off;
1612
1613 s = to_socket(container_of(kobj, struct device, kobj));
1614
1615 if (!(s->state & SOCKET_PRESENT))
1616 return -ENODEV;
1617 if (pccard_validate_cis(s, &chains))
1618 return -EIO;
1619 if (!chains)
1620 return -ENODATA;
1621
1622 count = pccard_extract_cis(s, buf, off, count);
1623 }
1624
1625 return count;
1626}
1627
1628
1629static ssize_t pccard_store_cis(struct kobject *kobj,
1630 struct bin_attribute *bin_attr,
1631 char *buf, loff_t off, size_t count)
1632{
1633 struct pcmcia_socket *s;
1634 int error;
1635
1636 s = to_socket(container_of(kobj, struct device, kobj));
1637
1638 if (off)
1639 return -EINVAL;
1640
1641 if (count >= CISTPL_MAX_CIS_SIZE)
1642 return -EINVAL;
1643
1644 if (!(s->state & SOCKET_PRESENT))
1645 return -ENODEV;
1646
1647 error = pcmcia_replace_cis(s, buf, count);
1648 if (error)
1649 return -EIO;
1650
1651 mutex_lock(&s->skt_mutex);
1652 if ((s->callback) && (s->state & SOCKET_PRESENT) &&
1653 !(s->state & SOCKET_CARDBUS)) {
1654 if (try_module_get(s->callback->owner)) {
1655 s->callback->requery(s, 1);
1656 module_put(s->callback->owner);
1657 }
1658 }
1659 mutex_unlock(&s->skt_mutex);
1660
1661 return count;
1662}
1663
1664
1665struct bin_attribute pccard_cis_attr = {
1666 .attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR },
1667 .size = 0x200,
1668 .read = pccard_show_cis,
1669 .write = pccard_store_cis,
1670};
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index ad05e3b59473..3f438afdcd4e 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -92,9 +92,6 @@ struct pccard_resource_ops {
92 * Stuff internal to module "pcmcia_core": 92 * Stuff internal to module "pcmcia_core":
93 */ 93 */
94 94
95/* cistpl.c */
96int verify_cis_cache(struct pcmcia_socket *s);
97
98/* socket_sysfs.c */ 95/* socket_sysfs.c */
99extern int pccard_sysfs_add_socket(struct device *dev); 96extern int pccard_sysfs_add_socket(struct device *dev);
100extern void pccard_sysfs_remove_socket(struct device *dev); 97extern void pccard_sysfs_remove_socket(struct device *dev);
@@ -102,8 +99,6 @@ extern void pccard_sysfs_remove_socket(struct device *dev);
102/* cardbus.c */ 99/* cardbus.c */
103int cb_alloc(struct pcmcia_socket *s); 100int cb_alloc(struct pcmcia_socket *s);
104void cb_free(struct pcmcia_socket *s); 101void cb_free(struct pcmcia_socket *s);
105int read_cb_mem(struct pcmcia_socket *s, int space, u_int addr, u_int len,
106 void *ptr);
107 102
108 103
109 104
@@ -116,6 +111,7 @@ struct pcmcia_callback{
116 int (*event) (struct pcmcia_socket *s, 111 int (*event) (struct pcmcia_socket *s,
117 event_t event, int priority); 112 event_t event, int priority);
118 void (*requery) (struct pcmcia_socket *s, int new_cis); 113 void (*requery) (struct pcmcia_socket *s, int new_cis);
114 int (*validate) (struct pcmcia_socket *s, unsigned int *i);
119 int (*suspend) (struct pcmcia_socket *s); 115 int (*suspend) (struct pcmcia_socket *s);
120 int (*resume) (struct pcmcia_socket *s); 116 int (*resume) (struct pcmcia_socket *s);
121}; 117};
@@ -137,7 +133,26 @@ int pcmcia_insert_card(struct pcmcia_socket *skt);
137struct pcmcia_socket *pcmcia_get_socket(struct pcmcia_socket *skt); 133struct pcmcia_socket *pcmcia_get_socket(struct pcmcia_socket *skt);
138void pcmcia_put_socket(struct pcmcia_socket *skt); 134void pcmcia_put_socket(struct pcmcia_socket *skt);
139 135
136/* rsrc_mgr.c */
137int pcmcia_validate_mem(struct pcmcia_socket *s);
138struct resource *pcmcia_find_mem_region(u_long base,
139 u_long num,
140 u_long align,
141 int low,
142 struct pcmcia_socket *s);
143
144/*
145 * Stuff internal to module "pcmcia".
146 */
147/* ds.c */
148extern struct bus_type pcmcia_bus_type;
149
150/* pcmcia_resource.c */
151extern int pcmcia_release_configuration(struct pcmcia_device *p_dev);
152
140/* cistpl.c */ 153/* cistpl.c */
154extern struct bin_attribute pccard_cis_attr;
155
141int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, 156int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr,
142 u_int addr, u_int len, void *ptr); 157 u_int addr, u_int len, void *ptr);
143void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, 158void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr,
@@ -149,8 +164,8 @@ int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function,
149int pcmcia_replace_cis(struct pcmcia_socket *s, 164int pcmcia_replace_cis(struct pcmcia_socket *s,
150 const u8 *data, const size_t len); 165 const u8 *data, const size_t len);
151int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *count); 166int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *count);
167int verify_cis_cache(struct pcmcia_socket *s);
152 168
153/* loop over CIS entries */
154int pccard_loop_tuple(struct pcmcia_socket *s, unsigned int function, 169int pccard_loop_tuple(struct pcmcia_socket *s, unsigned int function,
155 cisdata_t code, cisparse_t *parse, void *priv_data, 170 cisdata_t code, cisparse_t *parse, void *priv_data,
156 int (*loop_tuple) (tuple_t *tuple, 171 int (*loop_tuple) (tuple_t *tuple,
@@ -166,23 +181,6 @@ int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function,
166int pccard_get_tuple_data(struct pcmcia_socket *s, tuple_t *tuple); 181int pccard_get_tuple_data(struct pcmcia_socket *s, tuple_t *tuple);
167 182
168 183
169/* rsrc_mgr.c */
170int pcmcia_validate_mem(struct pcmcia_socket *s);
171struct resource *pcmcia_find_mem_region(u_long base,
172 u_long num,
173 u_long align,
174 int low,
175 struct pcmcia_socket *s);
176
177/*
178 * Stuff internal to module "pcmcia".
179 */
180/* ds.c */
181extern struct bus_type pcmcia_bus_type;
182
183/* pcmcia_resource.c */
184extern int pcmcia_release_configuration(struct pcmcia_device *p_dev);
185
186#ifdef CONFIG_PCMCIA_IOCTL 184#ifdef CONFIG_PCMCIA_IOCTL
187/* ds.c */ 185/* ds.c */
188extern spinlock_t pcmcia_dev_list_lock; 186extern spinlock_t pcmcia_dev_list_lock;
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 7bb52b003f0e..0ab4fe045920 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -1313,6 +1313,7 @@ static struct pcmcia_callback pcmcia_bus_callback = {
1313 .owner = THIS_MODULE, 1313 .owner = THIS_MODULE,
1314 .event = ds_event, 1314 .event = ds_event,
1315 .requery = pcmcia_bus_rescan, 1315 .requery = pcmcia_bus_rescan,
1316 .validate = pccard_validate_cis,
1316 .suspend = pcmcia_bus_suspend, 1317 .suspend = pcmcia_bus_suspend,
1317 .resume = pcmcia_bus_resume, 1318 .resume = pcmcia_bus_resume,
1318}; 1319};
@@ -1336,6 +1337,13 @@ static int __devinit pcmcia_bus_add_socket(struct device *dev,
1336 */ 1337 */
1337 msleep(250); 1338 msleep(250);
1338 1339
1340 ret = sysfs_create_bin_file(&dev->kobj, &pccard_cis_attr);
1341 if (ret) {
1342 dev_printk(KERN_ERR, dev, "PCMCIA registration failed\n");
1343 pcmcia_put_socket(socket);
1344 return ret;
1345 }
1346
1339#ifdef CONFIG_PCMCIA_IOCTL 1347#ifdef CONFIG_PCMCIA_IOCTL
1340 init_waitqueue_head(&socket->queue); 1348 init_waitqueue_head(&socket->queue);
1341#endif 1349#endif
@@ -1371,6 +1379,8 @@ static void pcmcia_bus_remove_socket(struct device *dev,
1371 release_cis_mem(socket); 1379 release_cis_mem(socket);
1372 mutex_unlock(&socket->skt_mutex); 1380 mutex_unlock(&socket->skt_mutex);
1373 1381
1382 sysfs_remove_bin_file(&dev->kobj, &pccard_cis_attr);
1383
1374 pcmcia_put_socket(socket); 1384 pcmcia_put_socket(socket);
1375 1385
1376 return; 1386 return;
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index 120d5ad99296..91626c17f97b 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -277,7 +277,9 @@ static int readable(struct pcmcia_socket *s, struct resource *res,
277 s->cis_mem.res = res; 277 s->cis_mem.res = res;
278 s->cis_virt = ioremap(res->start, s->map_size); 278 s->cis_virt = ioremap(res->start, s->map_size);
279 if (s->cis_virt) { 279 if (s->cis_virt) {
280 ret = pccard_validate_cis(s, count); 280 /* as we're only called from pcmcia.c, we're safe */
281 if (s->callback->validate)
282 ret = s->callback->validate(s, count);
281 /* invalidate mapping */ 283 /* invalidate mapping */
282 iounmap(s->cis_virt); 284 iounmap(s->cis_virt);
283 s->cis_virt = NULL; 285 s->cis_virt = NULL;
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c
index 7a456000332a..537d79305e7a 100644
--- a/drivers/pcmcia/socket_sysfs.c
+++ b/drivers/pcmcia/socket_sysfs.c
@@ -213,138 +213,6 @@ static ssize_t pccard_store_resource(struct device *dev,
213} 213}
214static DEVICE_ATTR(available_resources_setup_done, 0600, pccard_show_resource, pccard_store_resource); 214static DEVICE_ATTR(available_resources_setup_done, 0600, pccard_show_resource, pccard_store_resource);
215 215
216
217static ssize_t pccard_extract_cis(struct pcmcia_socket *s, char *buf, loff_t off, size_t count)
218{
219 tuple_t tuple;
220 int status, i;
221 loff_t pointer = 0;
222 ssize_t ret = 0;
223 u_char *tuplebuffer;
224 u_char *tempbuffer;
225
226 tuplebuffer = kmalloc(sizeof(u_char) * 256, GFP_KERNEL);
227 if (!tuplebuffer)
228 return -ENOMEM;
229
230 tempbuffer = kmalloc(sizeof(u_char) * 258, GFP_KERNEL);
231 if (!tempbuffer) {
232 ret = -ENOMEM;
233 goto free_tuple;
234 }
235
236 memset(&tuple, 0, sizeof(tuple_t));
237
238 tuple.Attributes = TUPLE_RETURN_LINK | TUPLE_RETURN_COMMON;
239 tuple.DesiredTuple = RETURN_FIRST_TUPLE;
240 tuple.TupleOffset = 0;
241
242 status = pccard_get_first_tuple(s, BIND_FN_ALL, &tuple);
243 while (!status) {
244 tuple.TupleData = tuplebuffer;
245 tuple.TupleDataMax = 255;
246 memset(tuplebuffer, 0, sizeof(u_char) * 255);
247
248 status = pccard_get_tuple_data(s, &tuple);
249 if (status)
250 break;
251
252 if (off < (pointer + 2 + tuple.TupleDataLen)) {
253 tempbuffer[0] = tuple.TupleCode & 0xff;
254 tempbuffer[1] = tuple.TupleLink & 0xff;
255 for (i = 0; i < tuple.TupleDataLen; i++)
256 tempbuffer[i + 2] = tuplebuffer[i] & 0xff;
257
258 for (i = 0; i < (2 + tuple.TupleDataLen); i++) {
259 if (((i + pointer) >= off) &&
260 (i + pointer) < (off + count)) {
261 buf[ret] = tempbuffer[i];
262 ret++;
263 }
264 }
265 }
266
267 pointer += 2 + tuple.TupleDataLen;
268
269 if (pointer >= (off + count))
270 break;
271
272 if (tuple.TupleCode == CISTPL_END)
273 break;
274 status = pccard_get_next_tuple(s, BIND_FN_ALL, &tuple);
275 }
276
277 kfree(tempbuffer);
278 free_tuple:
279 kfree(tuplebuffer);
280
281 return ret;
282}
283
284static ssize_t pccard_show_cis(struct kobject *kobj,
285 struct bin_attribute *bin_attr,
286 char *buf, loff_t off, size_t count)
287{
288 unsigned int size = 0x200;
289
290 if (off >= size)
291 count = 0;
292 else {
293 struct pcmcia_socket *s;
294 unsigned int chains;
295
296 if (off + count > size)
297 count = size - off;
298
299 s = to_socket(container_of(kobj, struct device, kobj));
300
301 if (!(s->state & SOCKET_PRESENT))
302 return -ENODEV;
303 if (pccard_validate_cis(s, &chains))
304 return -EIO;
305 if (!chains)
306 return -ENODATA;
307
308 count = pccard_extract_cis(s, buf, off, count);
309 }
310
311 return count;
312}
313
314static ssize_t pccard_store_cis(struct kobject *kobj,
315 struct bin_attribute *bin_attr,
316 char *buf, loff_t off, size_t count)
317{
318 struct pcmcia_socket *s = to_socket(container_of(kobj, struct device, kobj));
319 int error;
320
321 if (off)
322 return -EINVAL;
323
324 if (count >= CISTPL_MAX_CIS_SIZE)
325 return -EINVAL;
326
327 if (!(s->state & SOCKET_PRESENT))
328 return -ENODEV;
329
330 error = pcmcia_replace_cis(s, buf, count);
331 if (error)
332 return -EIO;
333
334 mutex_lock(&s->skt_mutex);
335 if ((s->callback) && (s->state & SOCKET_PRESENT) &&
336 !(s->state & SOCKET_CARDBUS)) {
337 if (try_module_get(s->callback->owner)) {
338 s->callback->requery(s, 1);
339 module_put(s->callback->owner);
340 }
341 }
342 mutex_unlock(&s->skt_mutex);
343
344 return count;
345}
346
347
348static struct attribute *pccard_socket_attributes[] = { 216static struct attribute *pccard_socket_attributes[] = {
349 &dev_attr_card_type.attr, 217 &dev_attr_card_type.attr,
350 &dev_attr_card_voltage.attr, 218 &dev_attr_card_voltage.attr,
@@ -362,28 +230,12 @@ static const struct attribute_group socket_attrs = {
362 .attrs = pccard_socket_attributes, 230 .attrs = pccard_socket_attributes,
363}; 231};
364 232
365static struct bin_attribute pccard_cis_attr = {
366 .attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR },
367 .size = 0x200,
368 .read = pccard_show_cis,
369 .write = pccard_store_cis,
370};
371
372int pccard_sysfs_add_socket(struct device *dev) 233int pccard_sysfs_add_socket(struct device *dev)
373{ 234{
374 int ret = 0; 235 return sysfs_create_group(&dev->kobj, &socket_attrs);
375
376 ret = sysfs_create_group(&dev->kobj, &socket_attrs);
377 if (!ret) {
378 ret = sysfs_create_bin_file(&dev->kobj, &pccard_cis_attr);
379 if (ret)
380 sysfs_remove_group(&dev->kobj, &socket_attrs);
381 }
382 return ret;
383} 236}
384 237
385void pccard_sysfs_remove_socket(struct device *dev) 238void pccard_sysfs_remove_socket(struct device *dev)
386{ 239{
387 sysfs_remove_bin_file(&dev->kobj, &pccard_cis_attr);
388 sysfs_remove_group(&dev->kobj, &socket_attrs); 240 sysfs_remove_group(&dev->kobj, &socket_attrs);
389} 241}