diff options
-rw-r--r-- | drivers/pcmcia/Makefile | 4 | ||||
-rw-r--r-- | drivers/pcmcia/cistpl.c | 158 | ||||
-rw-r--r-- | drivers/pcmcia/cs_internal.h | 44 | ||||
-rw-r--r-- | drivers/pcmcia/ds.c | 10 | ||||
-rw-r--r-- | drivers/pcmcia/rsrc_nonstatic.c | 4 | ||||
-rw-r--r-- | drivers/pcmcia/socket_sysfs.c | 150 |
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 | ||
5 | pcmcia_core-y += cs.o cistpl.o rsrc_mgr.o socket_sysfs.o | 5 | pcmcia_core-y += cs.o rsrc_mgr.o socket_sysfs.o |
6 | pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o | 6 | pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o |
7 | obj-$(CONFIG_PCCARD) += pcmcia_core.o | 7 | obj-$(CONFIG_PCCARD) += pcmcia_core.o |
8 | 8 | ||
9 | pcmcia-y += ds.o pcmcia_resource.o | 9 | pcmcia-y += ds.o pcmcia_resource.o cistpl.o |
10 | pcmcia-$(CONFIG_PCMCIA_IOCTL) += pcmcia_ioctl.o | 10 | pcmcia-$(CONFIG_PCMCIA_IOCTL) += pcmcia_ioctl.o |
11 | obj-$(CONFIG_PCMCIA) += pcmcia.o | 11 | obj-$(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 | } |
79 | EXPORT_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 | } |
198 | EXPORT_SYMBOL(pcmcia_read_cis_mem); | ||
199 | 197 | ||
200 | 198 | ||
201 | void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, | 199 | void 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 | } |
257 | EXPORT_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 | } |
338 | EXPORT_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 | } |
377 | EXPORT_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 | } |
403 | EXPORT_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 | } |
449 | EXPORT_SYMBOL(pccard_get_first_tuple); | ||
450 | 443 | ||
451 | static int follow_link(struct pcmcia_socket *s, tuple_t *tuple) | 444 | static 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 | } |
585 | EXPORT_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 | } |
609 | EXPORT_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 | } |
1382 | EXPORT_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 | } |
1442 | EXPORT_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 | } |
1536 | EXPORT_SYMBOL(pccard_validate_cis); | 1525 | |
1526 | |||
1527 | #define to_socket(_dev) container_of(_dev, struct pcmcia_socket, dev) | ||
1528 | |||
1529 | static 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 | |||
1598 | static 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 | |||
1629 | static 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 | |||
1665 | struct 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 */ | ||
96 | int verify_cis_cache(struct pcmcia_socket *s); | ||
97 | |||
98 | /* socket_sysfs.c */ | 95 | /* socket_sysfs.c */ |
99 | extern int pccard_sysfs_add_socket(struct device *dev); | 96 | extern int pccard_sysfs_add_socket(struct device *dev); |
100 | extern void pccard_sysfs_remove_socket(struct device *dev); | 97 | extern 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 */ |
103 | int cb_alloc(struct pcmcia_socket *s); | 100 | int cb_alloc(struct pcmcia_socket *s); |
104 | void cb_free(struct pcmcia_socket *s); | 101 | void cb_free(struct pcmcia_socket *s); |
105 | int 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); | |||
137 | struct pcmcia_socket *pcmcia_get_socket(struct pcmcia_socket *skt); | 133 | struct pcmcia_socket *pcmcia_get_socket(struct pcmcia_socket *skt); |
138 | void pcmcia_put_socket(struct pcmcia_socket *skt); | 134 | void pcmcia_put_socket(struct pcmcia_socket *skt); |
139 | 135 | ||
136 | /* rsrc_mgr.c */ | ||
137 | int pcmcia_validate_mem(struct pcmcia_socket *s); | ||
138 | struct 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 */ | ||
148 | extern struct bus_type pcmcia_bus_type; | ||
149 | |||
150 | /* pcmcia_resource.c */ | ||
151 | extern int pcmcia_release_configuration(struct pcmcia_device *p_dev); | ||
152 | |||
140 | /* cistpl.c */ | 153 | /* cistpl.c */ |
154 | extern struct bin_attribute pccard_cis_attr; | ||
155 | |||
141 | int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, | 156 | int 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); |
143 | void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, | 158 | void 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, | |||
149 | int pcmcia_replace_cis(struct pcmcia_socket *s, | 164 | int pcmcia_replace_cis(struct pcmcia_socket *s, |
150 | const u8 *data, const size_t len); | 165 | const u8 *data, const size_t len); |
151 | int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *count); | 166 | int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *count); |
167 | int verify_cis_cache(struct pcmcia_socket *s); | ||
152 | 168 | ||
153 | /* loop over CIS entries */ | ||
154 | int pccard_loop_tuple(struct pcmcia_socket *s, unsigned int function, | 169 | int 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, | |||
166 | int pccard_get_tuple_data(struct pcmcia_socket *s, tuple_t *tuple); | 181 | int pccard_get_tuple_data(struct pcmcia_socket *s, tuple_t *tuple); |
167 | 182 | ||
168 | 183 | ||
169 | /* rsrc_mgr.c */ | ||
170 | int pcmcia_validate_mem(struct pcmcia_socket *s); | ||
171 | struct 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 */ | ||
181 | extern struct bus_type pcmcia_bus_type; | ||
182 | |||
183 | /* pcmcia_resource.c */ | ||
184 | extern 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 */ |
188 | extern spinlock_t pcmcia_dev_list_lock; | 186 | extern 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 | } |
214 | static DEVICE_ATTR(available_resources_setup_done, 0600, pccard_show_resource, pccard_store_resource); | 214 | static DEVICE_ATTR(available_resources_setup_done, 0600, pccard_show_resource, pccard_store_resource); |
215 | 215 | ||
216 | |||
217 | static 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 | |||
284 | static 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 | |||
314 | static 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 | |||
348 | static struct attribute *pccard_socket_attributes[] = { | 216 | static 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 | ||
365 | static 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 | |||
372 | int pccard_sysfs_add_socket(struct device *dev) | 233 | int 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 | ||
385 | void pccard_sysfs_remove_socket(struct device *dev) | 238 | void 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 | } |