diff options
Diffstat (limited to 'drivers/pcmcia/cistpl.c')
-rw-r--r-- | drivers/pcmcia/cistpl.c | 158 |
1 files changed, 146 insertions, 12 deletions
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 | }; | ||