aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia/cistpl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pcmcia/cistpl.c')
-rw-r--r--drivers/pcmcia/cistpl.c158
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}
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};