diff options
Diffstat (limited to 'drivers/char/isicom.c')
-rw-r--r-- | drivers/char/isicom.c | 108 |
1 files changed, 48 insertions, 60 deletions
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 01084abffddf..43ab9edc76f5 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c | |||
@@ -183,7 +183,7 @@ static DEFINE_TIMER(tx, isicom_tx, 0, 0); | |||
183 | /* baud index mappings from linux defns to isi */ | 183 | /* baud index mappings from linux defns to isi */ |
184 | 184 | ||
185 | static signed char linuxb_to_isib[] = { | 185 | static signed char linuxb_to_isib[] = { |
186 | -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17, 18, 19 | 186 | -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17, 18, 19, 20, 21 |
187 | }; | 187 | }; |
188 | 188 | ||
189 | struct isi_board { | 189 | struct isi_board { |
@@ -213,8 +213,6 @@ struct isi_port { | |||
213 | struct tty_struct * tty; | 213 | struct tty_struct * tty; |
214 | wait_queue_head_t close_wait; | 214 | wait_queue_head_t close_wait; |
215 | wait_queue_head_t open_wait; | 215 | wait_queue_head_t open_wait; |
216 | struct work_struct hangup_tq; | ||
217 | struct work_struct bh_tqueue; | ||
218 | unsigned char * xmit_buf; | 216 | unsigned char * xmit_buf; |
219 | int xmit_head; | 217 | int xmit_head; |
220 | int xmit_tail; | 218 | int xmit_tail; |
@@ -510,7 +508,7 @@ static void isicom_tx(unsigned long _data) | |||
510 | if (port->xmit_cnt <= 0) | 508 | if (port->xmit_cnt <= 0) |
511 | port->status &= ~ISI_TXOK; | 509 | port->status &= ~ISI_TXOK; |
512 | if (port->xmit_cnt <= WAKEUP_CHARS) | 510 | if (port->xmit_cnt <= WAKEUP_CHARS) |
513 | schedule_work(&port->bh_tqueue); | 511 | tty_wakeup(tty); |
514 | unlock_card(&isi_card[card]); | 512 | unlock_card(&isi_card[card]); |
515 | } | 513 | } |
516 | 514 | ||
@@ -524,21 +522,6 @@ sched_again: | |||
524 | mod_timer(&tx, jiffies + msecs_to_jiffies(10)); | 522 | mod_timer(&tx, jiffies + msecs_to_jiffies(10)); |
525 | } | 523 | } |
526 | 524 | ||
527 | /* Interrupt handlers */ | ||
528 | |||
529 | |||
530 | static void isicom_bottomhalf(struct work_struct *work) | ||
531 | { | ||
532 | struct isi_port *port = container_of(work, struct isi_port, bh_tqueue); | ||
533 | struct tty_struct *tty = port->tty; | ||
534 | |||
535 | if (!tty) | ||
536 | return; | ||
537 | |||
538 | tty_wakeup(tty); | ||
539 | wake_up_interruptible(&tty->write_wait); | ||
540 | } | ||
541 | |||
542 | /* | 525 | /* |
543 | * Main interrupt handler routine | 526 | * Main interrupt handler routine |
544 | */ | 527 | */ |
@@ -557,6 +540,11 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) | |||
557 | return IRQ_NONE; | 540 | return IRQ_NONE; |
558 | 541 | ||
559 | base = card->base; | 542 | base = card->base; |
543 | |||
544 | /* did the card interrupt us? */ | ||
545 | if (!(inw(base + 0x0e) & 0x02)) | ||
546 | return IRQ_NONE; | ||
547 | |||
560 | spin_lock(&card->card_lock); | 548 | spin_lock(&card->card_lock); |
561 | 549 | ||
562 | /* | 550 | /* |
@@ -581,6 +569,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) | |||
581 | port = card->ports + channel; | 569 | port = card->ports + channel; |
582 | if (!(port->flags & ASYNC_INITIALIZED)) { | 570 | if (!(port->flags & ASYNC_INITIALIZED)) { |
583 | outw(0x0000, base+0x04); /* enable interrupts */ | 571 | outw(0x0000, base+0x04); /* enable interrupts */ |
572 | spin_unlock(&card->card_lock); | ||
584 | return IRQ_HANDLED; | 573 | return IRQ_HANDLED; |
585 | } | 574 | } |
586 | 575 | ||
@@ -609,7 +598,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) | |||
609 | pr_dbg("interrupt: DCD->low.\n" | 598 | pr_dbg("interrupt: DCD->low.\n" |
610 | ); | 599 | ); |
611 | port->status &= ~ISI_DCD; | 600 | port->status &= ~ISI_DCD; |
612 | schedule_work(&port->hangup_tq); | 601 | tty_hangup(tty); |
613 | } | 602 | } |
614 | } else if (header & ISI_DCD) { | 603 | } else if (header & ISI_DCD) { |
615 | /* Carrier has been detected */ | 604 | /* Carrier has been detected */ |
@@ -631,7 +620,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) | |||
631 | /* start tx ing */ | 620 | /* start tx ing */ |
632 | port->status |= (ISI_TXOK | 621 | port->status |= (ISI_TXOK |
633 | | ISI_CTS); | 622 | | ISI_CTS); |
634 | schedule_work(&port->bh_tqueue); | 623 | tty_wakeup(tty); |
635 | } | 624 | } |
636 | } else if (!(header & ISI_CTS)) { | 625 | } else if (!(header & ISI_CTS)) { |
637 | port->tty->hw_stopped = 1; | 626 | port->tty->hw_stopped = 1; |
@@ -695,6 +684,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) | |||
695 | tty_flip_buffer_push(tty); | 684 | tty_flip_buffer_push(tty); |
696 | } | 685 | } |
697 | outw(0x0000, base+0x04); /* enable interrupts */ | 686 | outw(0x0000, base+0x04); /* enable interrupts */ |
687 | spin_unlock(&card->card_lock); | ||
698 | 688 | ||
699 | return IRQ_HANDLED; | 689 | return IRQ_HANDLED; |
700 | } | 690 | } |
@@ -720,7 +710,8 @@ static void isicom_config_port(struct isi_port *port) | |||
720 | * respectively. | 710 | * respectively. |
721 | */ | 711 | */ |
722 | 712 | ||
723 | if (baud < 1 || baud > 2) | 713 | /* 1,2,3,4 => 57.6, 115.2, 230, 460 kbps resp. */ |
714 | if (baud < 1 || baud > 4) | ||
724 | port->tty->termios->c_cflag &= ~CBAUDEX; | 715 | port->tty->termios->c_cflag &= ~CBAUDEX; |
725 | else | 716 | else |
726 | baud += 15; | 717 | baud += 15; |
@@ -736,6 +727,10 @@ static void isicom_config_port(struct isi_port *port) | |||
736 | baud++; /* 57.6 Kbps */ | 727 | baud++; /* 57.6 Kbps */ |
737 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) | 728 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) |
738 | baud +=2; /* 115 Kbps */ | 729 | baud +=2; /* 115 Kbps */ |
730 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) | ||
731 | baud += 3; /* 230 kbps*/ | ||
732 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) | ||
733 | baud += 4; /* 460 kbps*/ | ||
739 | } | 734 | } |
740 | if (linuxb_to_isib[baud] == -1) { | 735 | if (linuxb_to_isib[baud] == -1) { |
741 | /* hang up */ | 736 | /* hang up */ |
@@ -1460,17 +1455,6 @@ static void isicom_start(struct tty_struct *tty) | |||
1460 | port->status |= ISI_TXOK; | 1455 | port->status |= ISI_TXOK; |
1461 | } | 1456 | } |
1462 | 1457 | ||
1463 | /* hangup et all */ | ||
1464 | static void do_isicom_hangup(struct work_struct *work) | ||
1465 | { | ||
1466 | struct isi_port *port = container_of(work, struct isi_port, hangup_tq); | ||
1467 | struct tty_struct *tty; | ||
1468 | |||
1469 | tty = port->tty; | ||
1470 | if (tty) | ||
1471 | tty_hangup(tty); | ||
1472 | } | ||
1473 | |||
1474 | static void isicom_hangup(struct tty_struct *tty) | 1458 | static void isicom_hangup(struct tty_struct *tty) |
1475 | { | 1459 | { |
1476 | struct isi_port *port = tty->driver_data; | 1460 | struct isi_port *port = tty->driver_data; |
@@ -1503,7 +1487,6 @@ static void isicom_flush_buffer(struct tty_struct *tty) | |||
1503 | port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; | 1487 | port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; |
1504 | spin_unlock_irqrestore(&card->card_lock, flags); | 1488 | spin_unlock_irqrestore(&card->card_lock, flags); |
1505 | 1489 | ||
1506 | wake_up_interruptible(&tty->write_wait); | ||
1507 | tty_wakeup(tty); | 1490 | tty_wakeup(tty); |
1508 | } | 1491 | } |
1509 | 1492 | ||
@@ -1536,7 +1519,7 @@ static int __devinit reset_card(struct pci_dev *pdev, | |||
1536 | { | 1519 | { |
1537 | struct isi_board *board = pci_get_drvdata(pdev); | 1520 | struct isi_board *board = pci_get_drvdata(pdev); |
1538 | unsigned long base = board->base; | 1521 | unsigned long base = board->base; |
1539 | unsigned int portcount = 0; | 1522 | unsigned int sig, portcount = 0; |
1540 | int retval = 0; | 1523 | int retval = 0; |
1541 | 1524 | ||
1542 | dev_dbg(&pdev->dev, "ISILoad:Resetting Card%d at 0x%lx\n", card + 1, | 1525 | dev_dbg(&pdev->dev, "ISILoad:Resetting Card%d at 0x%lx\n", card + 1, |
@@ -1544,27 +1527,35 @@ static int __devinit reset_card(struct pci_dev *pdev, | |||
1544 | 1527 | ||
1545 | inw(base + 0x8); | 1528 | inw(base + 0x8); |
1546 | 1529 | ||
1547 | mdelay(10); | 1530 | msleep(10); |
1548 | 1531 | ||
1549 | outw(0, base + 0x8); /* Reset */ | 1532 | outw(0, base + 0x8); /* Reset */ |
1550 | 1533 | ||
1551 | msleep(3000); | 1534 | msleep(1000); |
1552 | 1535 | ||
1553 | *signature = inw(base + 0x4) & 0xff; | 1536 | sig = inw(base + 0x4) & 0xff; |
1537 | |||
1538 | if (sig != 0xa5 && sig != 0xbb && sig != 0xcc && sig != 0xdd && | ||
1539 | sig != 0xee) { | ||
1540 | dev_warn(&pdev->dev, "ISILoad:Card%u reset failure (Possible " | ||
1541 | "bad I/O Port Address 0x%lx).\n", card + 1, base); | ||
1542 | dev_dbg(&pdev->dev, "Sig=0x%x\n", sig); | ||
1543 | retval = -EIO; | ||
1544 | goto end; | ||
1545 | } | ||
1546 | |||
1547 | msleep(10); | ||
1554 | 1548 | ||
1555 | portcount = inw(base + 0x2); | 1549 | portcount = inw(base + 0x2); |
1556 | if (!(inw(base + 0xe) & 0x1) || ((portcount != 0) && | 1550 | if (!inw(base + 0xe) & 0x1 || (portcount != 0 && portcount != 4 && |
1557 | (portcount != 4) && (portcount != 8))) { | 1551 | portcount != 8 && portcount != 16)) { |
1558 | dev_dbg(&pdev->dev, "base+0x2=0x%lx, base+0xe=0x%lx\n", | 1552 | dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure.", |
1559 | inw(base + 0x2), inw(base + 0xe)); | 1553 | card + 1); |
1560 | dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure " | ||
1561 | "(Possible bad I/O Port Address 0x%lx).\n", | ||
1562 | card + 1, base); | ||
1563 | retval = -EIO; | 1554 | retval = -EIO; |
1564 | goto end; | 1555 | goto end; |
1565 | } | 1556 | } |
1566 | 1557 | ||
1567 | switch (*signature) { | 1558 | switch (sig) { |
1568 | case 0xa5: | 1559 | case 0xa5: |
1569 | case 0xbb: | 1560 | case 0xbb: |
1570 | case 0xdd: | 1561 | case 0xdd: |
@@ -1572,16 +1563,13 @@ static int __devinit reset_card(struct pci_dev *pdev, | |||
1572 | board->shift_count = 12; | 1563 | board->shift_count = 12; |
1573 | break; | 1564 | break; |
1574 | case 0xcc: | 1565 | case 0xcc: |
1566 | case 0xee: | ||
1575 | board->port_count = 16; | 1567 | board->port_count = 16; |
1576 | board->shift_count = 11; | 1568 | board->shift_count = 11; |
1577 | break; | 1569 | break; |
1578 | default: | ||
1579 | dev_warn(&pdev->dev, "ISILoad:Card%d reset failure (Possible " | ||
1580 | "bad I/O Port Address 0x%lx).\n", card + 1, base); | ||
1581 | dev_dbg(&pdev->dev, "Sig=0x%lx\n", signature); | ||
1582 | retval = -EIO; | ||
1583 | } | 1570 | } |
1584 | dev_info(&pdev->dev, "-Done\n"); | 1571 | dev_info(&pdev->dev, "-Done\n"); |
1572 | *signature = sig; | ||
1585 | 1573 | ||
1586 | end: | 1574 | end: |
1587 | return retval; | 1575 | return retval; |
@@ -1757,7 +1745,7 @@ end: | |||
1757 | /* | 1745 | /* |
1758 | * Insmod can set static symbols so keep these static | 1746 | * Insmod can set static symbols so keep these static |
1759 | */ | 1747 | */ |
1760 | static int card; | 1748 | static unsigned int card_count; |
1761 | 1749 | ||
1762 | static int __devinit isicom_probe(struct pci_dev *pdev, | 1750 | static int __devinit isicom_probe(struct pci_dev *pdev, |
1763 | const struct pci_device_id *ent) | 1751 | const struct pci_device_id *ent) |
@@ -1767,7 +1755,7 @@ static int __devinit isicom_probe(struct pci_dev *pdev, | |||
1767 | u8 pciirq; | 1755 | u8 pciirq; |
1768 | struct isi_board *board = NULL; | 1756 | struct isi_board *board = NULL; |
1769 | 1757 | ||
1770 | if (card >= BOARD_COUNT) | 1758 | if (card_count >= BOARD_COUNT) |
1771 | goto err; | 1759 | goto err; |
1772 | 1760 | ||
1773 | ioaddr = pci_resource_start(pdev, 3); | 1761 | ioaddr = pci_resource_start(pdev, 3); |
@@ -1785,7 +1773,7 @@ static int __devinit isicom_probe(struct pci_dev *pdev, | |||
1785 | board->index = index; | 1773 | board->index = index; |
1786 | board->base = ioaddr; | 1774 | board->base = ioaddr; |
1787 | board->irq = pciirq; | 1775 | board->irq = pciirq; |
1788 | card++; | 1776 | card_count++; |
1789 | 1777 | ||
1790 | pci_set_drvdata(pdev, board); | 1778 | pci_set_drvdata(pdev, board); |
1791 | 1779 | ||
@@ -1795,7 +1783,7 @@ static int __devinit isicom_probe(struct pci_dev *pdev, | |||
1795 | "will be disabled.\n", board->base, board->base + 15, | 1783 | "will be disabled.\n", board->base, board->base + 15, |
1796 | index + 1); | 1784 | index + 1); |
1797 | retval = -EBUSY; | 1785 | retval = -EBUSY; |
1798 | goto err; | 1786 | goto errdec; |
1799 | } | 1787 | } |
1800 | 1788 | ||
1801 | retval = request_irq(board->irq, isicom_interrupt, | 1789 | retval = request_irq(board->irq, isicom_interrupt, |
@@ -1824,8 +1812,10 @@ errunri: | |||
1824 | free_irq(board->irq, board); | 1812 | free_irq(board->irq, board); |
1825 | errunrr: | 1813 | errunrr: |
1826 | pci_release_region(pdev, 3); | 1814 | pci_release_region(pdev, 3); |
1827 | err: | 1815 | errdec: |
1828 | board->base = 0; | 1816 | board->base = 0; |
1817 | card_count--; | ||
1818 | err: | ||
1829 | return retval; | 1819 | return retval; |
1830 | } | 1820 | } |
1831 | 1821 | ||
@@ -1839,6 +1829,8 @@ static void __devexit isicom_remove(struct pci_dev *pdev) | |||
1839 | 1829 | ||
1840 | free_irq(board->irq, board); | 1830 | free_irq(board->irq, board); |
1841 | pci_release_region(pdev, 3); | 1831 | pci_release_region(pdev, 3); |
1832 | board->base = 0; | ||
1833 | card_count--; | ||
1842 | } | 1834 | } |
1843 | 1835 | ||
1844 | static int __init isicom_init(void) | 1836 | static int __init isicom_init(void) |
@@ -1846,8 +1838,6 @@ static int __init isicom_init(void) | |||
1846 | int retval, idx, channel; | 1838 | int retval, idx, channel; |
1847 | struct isi_port *port; | 1839 | struct isi_port *port; |
1848 | 1840 | ||
1849 | card = 0; | ||
1850 | |||
1851 | for(idx = 0; idx < BOARD_COUNT; idx++) { | 1841 | for(idx = 0; idx < BOARD_COUNT; idx++) { |
1852 | port = &isi_ports[idx * 16]; | 1842 | port = &isi_ports[idx * 16]; |
1853 | isi_card[idx].ports = port; | 1843 | isi_card[idx].ports = port; |
@@ -1858,8 +1848,6 @@ static int __init isicom_init(void) | |||
1858 | port->channel = channel; | 1848 | port->channel = channel; |
1859 | port->close_delay = 50 * HZ/100; | 1849 | port->close_delay = 50 * HZ/100; |
1860 | port->closing_wait = 3000 * HZ/100; | 1850 | port->closing_wait = 3000 * HZ/100; |
1861 | INIT_WORK(&port->hangup_tq, do_isicom_hangup); | ||
1862 | INIT_WORK(&port->bh_tqueue, isicom_bottomhalf); | ||
1863 | port->status = 0; | 1851 | port->status = 0; |
1864 | init_waitqueue_head(&port->open_wait); | 1852 | init_waitqueue_head(&port->open_wait); |
1865 | init_waitqueue_head(&port->close_wait); | 1853 | init_waitqueue_head(&port->close_wait); |