diff options
-rw-r--r-- | drivers/char/isicom.c | 109 |
1 files changed, 56 insertions, 53 deletions
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 6812fda20953..57b115272aaa 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c | |||
@@ -126,8 +126,8 @@ | |||
126 | #include <linux/delay.h> | 126 | #include <linux/delay.h> |
127 | #include <linux/ioport.h> | 127 | #include <linux/ioport.h> |
128 | 128 | ||
129 | #include <asm/uaccess.h> | 129 | #include <linux/uaccess.h> |
130 | #include <asm/io.h> | 130 | #include <linux/io.h> |
131 | #include <asm/system.h> | 131 | #include <asm/system.h> |
132 | 132 | ||
133 | #include <linux/pci.h> | 133 | #include <linux/pci.h> |
@@ -189,7 +189,7 @@ struct isi_board { | |||
189 | unsigned short status; | 189 | unsigned short status; |
190 | unsigned short port_status; /* each bit for each port */ | 190 | unsigned short port_status; /* each bit for each port */ |
191 | unsigned short shift_count; | 191 | unsigned short shift_count; |
192 | struct isi_port * ports; | 192 | struct isi_port *ports; |
193 | signed char count; | 193 | signed char count; |
194 | spinlock_t card_lock; /* Card wide lock 11/5/00 -sameer */ | 194 | spinlock_t card_lock; /* Card wide lock 11/5/00 -sameer */ |
195 | unsigned long flags; | 195 | unsigned long flags; |
@@ -205,11 +205,11 @@ struct isi_port { | |||
205 | u16 channel; | 205 | u16 channel; |
206 | u16 status; | 206 | u16 status; |
207 | u16 closing_wait; | 207 | u16 closing_wait; |
208 | struct isi_board * card; | 208 | struct isi_board *card; |
209 | struct tty_struct * tty; | 209 | struct tty_struct *tty; |
210 | wait_queue_head_t close_wait; | 210 | wait_queue_head_t close_wait; |
211 | wait_queue_head_t open_wait; | 211 | wait_queue_head_t open_wait; |
212 | unsigned char * xmit_buf; | 212 | unsigned char *xmit_buf; |
213 | int xmit_head; | 213 | int xmit_head; |
214 | int xmit_tail; | 214 | int xmit_tail; |
215 | int xmit_cnt; | 215 | int xmit_cnt; |
@@ -405,7 +405,7 @@ static void isicom_tx(unsigned long _data) | |||
405 | 405 | ||
406 | /* find next active board */ | 406 | /* find next active board */ |
407 | card = (prev_card + 1) & 0x0003; | 407 | card = (prev_card + 1) & 0x0003; |
408 | while(count-- > 0) { | 408 | while (count-- > 0) { |
409 | if (isi_card[card].status & BOARD_ACTIVE) | 409 | if (isi_card[card].status & BOARD_ACTIVE) |
410 | break; | 410 | break; |
411 | card = (card + 1) & 0x0003; | 411 | card = (card + 1) & 0x0003; |
@@ -428,7 +428,7 @@ static void isicom_tx(unsigned long _data) | |||
428 | if (retries >= 100) | 428 | if (retries >= 100) |
429 | goto unlock; | 429 | goto unlock; |
430 | 430 | ||
431 | for (;count > 0;count--, port++) { | 431 | for (; count > 0; count--, port++) { |
432 | /* port not active or tx disabled to force flow control */ | 432 | /* port not active or tx disabled to force flow control */ |
433 | if (!(port->flags & ASYNC_INITIALIZED) || | 433 | if (!(port->flags & ASYNC_INITIALIZED) || |
434 | !(port->status & ISI_TXOK)) | 434 | !(port->status & ISI_TXOK)) |
@@ -471,9 +471,10 @@ static void isicom_tx(unsigned long _data) | |||
471 | break; | 471 | break; |
472 | } | 472 | } |
473 | } | 473 | } |
474 | if (cnt <= 0) break; | 474 | if (cnt <= 0) |
475 | break; | ||
475 | word_count = cnt >> 1; | 476 | word_count = cnt >> 1; |
476 | outsw(base, port->xmit_buf+port->xmit_tail,word_count); | 477 | outsw(base, port->xmit_buf+port->xmit_tail, word_count); |
477 | port->xmit_tail = (port->xmit_tail | 478 | port->xmit_tail = (port->xmit_tail |
478 | + (word_count << 1)) & (SERIAL_XMIT_SIZE - 1); | 479 | + (word_count << 1)) & (SERIAL_XMIT_SIZE - 1); |
479 | txcount -= (word_count << 1); | 480 | txcount -= (word_count << 1); |
@@ -556,7 +557,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) | |||
556 | tty = port->tty; | 557 | tty = port->tty; |
557 | if (tty == NULL) { | 558 | if (tty == NULL) { |
558 | word_count = byte_count >> 1; | 559 | word_count = byte_count >> 1; |
559 | while(byte_count > 1) { | 560 | while (byte_count > 1) { |
560 | inw(base); | 561 | inw(base); |
561 | byte_count -= 2; | 562 | byte_count -= 2; |
562 | } | 563 | } |
@@ -569,7 +570,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) | |||
569 | 570 | ||
570 | if (header & 0x8000) { /* Status Packet */ | 571 | if (header & 0x8000) { /* Status Packet */ |
571 | header = inw(base); | 572 | header = inw(base); |
572 | switch(header & 0xff) { | 573 | switch (header & 0xff) { |
573 | case 0: /* Change in EIA signals */ | 574 | case 0: /* Change in EIA signals */ |
574 | if (port->flags & ASYNC_CHECK_CD) { | 575 | if (port->flags & ASYNC_CHECK_CD) { |
575 | if (port->status & ISI_DCD) { | 576 | if (port->status & ISI_DCD) { |
@@ -656,7 +657,8 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) | |||
656 | if (byte_count > 0) { | 657 | if (byte_count > 0) { |
657 | pr_dbg("Intr(0x%lx:%d): Flip buffer overflow! dropping " | 658 | pr_dbg("Intr(0x%lx:%d): Flip buffer overflow! dropping " |
658 | "bytes...\n", base, channel + 1); | 659 | "bytes...\n", base, channel + 1); |
659 | while(byte_count > 0) { /* drain out unread xtra data */ | 660 | /* drain out unread xtra data */ |
661 | while (byte_count > 0) { | ||
660 | inw(base); | 662 | inw(base); |
661 | byte_count -= 2; | 663 | byte_count -= 2; |
662 | } | 664 | } |
@@ -679,8 +681,11 @@ static void isicom_config_port(struct isi_port *port) | |||
679 | shift_count = card->shift_count; | 681 | shift_count = card->shift_count; |
680 | unsigned char flow_ctrl; | 682 | unsigned char flow_ctrl; |
681 | 683 | ||
682 | if (!(tty = port->tty) || !tty->termios) | 684 | tty = port->tty; |
685 | |||
686 | if (tty == NULL) | ||
683 | return; | 687 | return; |
688 | /* FIXME: Switch to new tty baud API */ | ||
684 | baud = C_BAUD(tty); | 689 | baud = C_BAUD(tty); |
685 | if (baud & CBAUDEX) { | 690 | if (baud & CBAUDEX) { |
686 | baud &= ~CBAUDEX; | 691 | baud &= ~CBAUDEX; |
@@ -706,7 +711,7 @@ static void isicom_config_port(struct isi_port *port) | |||
706 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) | 711 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) |
707 | baud++; /* 57.6 Kbps */ | 712 | baud++; /* 57.6 Kbps */ |
708 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) | 713 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) |
709 | baud +=2; /* 115 Kbps */ | 714 | baud += 2; /* 115 Kbps */ |
710 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) | 715 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) |
711 | baud += 3; /* 230 kbps*/ | 716 | baud += 3; /* 230 kbps*/ |
712 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) | 717 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) |
@@ -716,15 +721,14 @@ static void isicom_config_port(struct isi_port *port) | |||
716 | /* hang up */ | 721 | /* hang up */ |
717 | drop_dtr(port); | 722 | drop_dtr(port); |
718 | return; | 723 | return; |
719 | } | 724 | } else |
720 | else | ||
721 | raise_dtr(port); | 725 | raise_dtr(port); |
722 | 726 | ||
723 | if (WaitTillCardIsFree(base) == 0) { | 727 | if (WaitTillCardIsFree(base) == 0) { |
724 | outw(0x8000 | (channel << shift_count) |0x03, base); | 728 | outw(0x8000 | (channel << shift_count) | 0x03, base); |
725 | outw(linuxb_to_isib[baud] << 8 | 0x03, base); | 729 | outw(linuxb_to_isib[baud] << 8 | 0x03, base); |
726 | channel_setup = 0; | 730 | channel_setup = 0; |
727 | switch(C_CSIZE(tty)) { | 731 | switch (C_CSIZE(tty)) { |
728 | case CS5: | 732 | case CS5: |
729 | channel_setup |= ISICOM_CS5; | 733 | channel_setup |= ISICOM_CS5; |
730 | break; | 734 | break; |
@@ -767,7 +771,7 @@ static void isicom_config_port(struct isi_port *port) | |||
767 | flow_ctrl |= ISICOM_INITIATE_XONXOFF; | 771 | flow_ctrl |= ISICOM_INITIATE_XONXOFF; |
768 | 772 | ||
769 | if (WaitTillCardIsFree(base) == 0) { | 773 | if (WaitTillCardIsFree(base) == 0) { |
770 | outw(0x8000 | (channel << shift_count) |0x04, base); | 774 | outw(0x8000 | (channel << shift_count) | 0x04, base); |
771 | outw(flow_ctrl << 8 | 0x05, base); | 775 | outw(flow_ctrl << 8 | 0x05, base); |
772 | outw((STOP_CHAR(tty)) << 8 | (START_CHAR(tty)), base); | 776 | outw((STOP_CHAR(tty)) << 8 | (START_CHAR(tty)), base); |
773 | InterruptTheCard(base); | 777 | InterruptTheCard(base); |
@@ -805,20 +809,19 @@ static int isicom_setup_port(struct isi_port *port) | |||
805 | struct isi_board *card = port->card; | 809 | struct isi_board *card = port->card; |
806 | unsigned long flags; | 810 | unsigned long flags; |
807 | 811 | ||
808 | if (port->flags & ASYNC_INITIALIZED) { | 812 | if (port->flags & ASYNC_INITIALIZED) |
809 | return 0; | 813 | return 0; |
810 | } | ||
811 | if (!port->xmit_buf) { | 814 | if (!port->xmit_buf) { |
812 | unsigned long page; | 815 | /* Relies on BKL */ |
816 | void *xmit_buf = (void *)get_zeroed_page(GFP_KERNEL); | ||
813 | 817 | ||
814 | if (!(page = get_zeroed_page(GFP_KERNEL))) | 818 | if (xmit_buf == NULL) |
815 | return -ENOMEM; | 819 | return -ENOMEM; |
816 | |||
817 | if (port->xmit_buf) { | 820 | if (port->xmit_buf) { |
818 | free_page(page); | 821 | free_page((unsigned long)xmit_buf); |
819 | return -ERESTARTSYS; | 822 | return -ERESTARTSYS; |
820 | } | 823 | } |
821 | port->xmit_buf = (unsigned char *) page; | 824 | port->xmit_buf = xmit_buf; |
822 | } | 825 | } |
823 | 826 | ||
824 | spin_lock_irqsave(&card->card_lock, flags); | 827 | spin_lock_irqsave(&card->card_lock, flags); |
@@ -949,21 +952,18 @@ static int isicom_open(struct tty_struct *tty, struct file *filp) | |||
949 | port->count++; | 952 | port->count++; |
950 | tty->driver_data = port; | 953 | tty->driver_data = port; |
951 | port->tty = tty; | 954 | port->tty = tty; |
952 | if ((error = isicom_setup_port(port))!=0) | 955 | error = isicom_setup_port(port); |
953 | return error; | 956 | if (error == 0) |
954 | if ((error = block_til_ready(tty, filp, port))!=0) | 957 | error = block_til_ready(tty, filp, port); |
955 | return error; | 958 | return error; |
956 | |||
957 | return 0; | ||
958 | } | 959 | } |
959 | 960 | ||
960 | /* close et all */ | 961 | /* close et all */ |
961 | 962 | ||
962 | static inline void isicom_shutdown_board(struct isi_board *bp) | 963 | static inline void isicom_shutdown_board(struct isi_board *bp) |
963 | { | 964 | { |
964 | if (bp->status & BOARD_ACTIVE) { | 965 | if (bp->status & BOARD_ACTIVE) |
965 | bp->status &= ~BOARD_ACTIVE; | 966 | bp->status &= ~BOARD_ACTIVE; |
966 | } | ||
967 | } | 967 | } |
968 | 968 | ||
969 | /* card->lock HAS to be held */ | 969 | /* card->lock HAS to be held */ |
@@ -1119,7 +1119,7 @@ static int isicom_write(struct tty_struct *tty, const unsigned char *buf, | |||
1119 | 1119 | ||
1120 | spin_lock_irqsave(&card->card_lock, flags); | 1120 | spin_lock_irqsave(&card->card_lock, flags); |
1121 | 1121 | ||
1122 | while(1) { | 1122 | while (1) { |
1123 | cnt = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt | 1123 | cnt = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt |
1124 | - 1, SERIAL_XMIT_SIZE - port->xmit_head)); | 1124 | - 1, SERIAL_XMIT_SIZE - port->xmit_head)); |
1125 | if (cnt <= 0) | 1125 | if (cnt <= 0) |
@@ -1153,15 +1153,15 @@ static void isicom_put_char(struct tty_struct *tty, unsigned char ch) | |||
1153 | return; | 1153 | return; |
1154 | 1154 | ||
1155 | spin_lock_irqsave(&card->card_lock, flags); | 1155 | spin_lock_irqsave(&card->card_lock, flags); |
1156 | if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) { | 1156 | if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) |
1157 | spin_unlock_irqrestore(&card->card_lock, flags); | 1157 | goto out; |
1158 | return; | ||
1159 | } | ||
1160 | 1158 | ||
1161 | port->xmit_buf[port->xmit_head++] = ch; | 1159 | port->xmit_buf[port->xmit_head++] = ch; |
1162 | port->xmit_head &= (SERIAL_XMIT_SIZE - 1); | 1160 | port->xmit_head &= (SERIAL_XMIT_SIZE - 1); |
1163 | port->xmit_cnt++; | 1161 | port->xmit_cnt++; |
1164 | spin_unlock_irqrestore(&card->card_lock, flags); | 1162 | spin_unlock_irqrestore(&card->card_lock, flags); |
1163 | out: | ||
1164 | return; | ||
1165 | } | 1165 | } |
1166 | 1166 | ||
1167 | /* flush_chars et all */ | 1167 | /* flush_chars et all */ |
@@ -1286,10 +1286,9 @@ static int isicom_set_serial_info(struct isi_port *port, | |||
1286 | unlock_kernel(); | 1286 | unlock_kernel(); |
1287 | return -EPERM; | 1287 | return -EPERM; |
1288 | } | 1288 | } |
1289 | port->flags = ((port->flags & ~ ASYNC_USR_MASK) | | 1289 | port->flags = ((port->flags & ~ASYNC_USR_MASK) | |
1290 | (newinfo.flags & ASYNC_USR_MASK)); | 1290 | (newinfo.flags & ASYNC_USR_MASK)); |
1291 | } | 1291 | } else { |
1292 | else { | ||
1293 | port->close_delay = newinfo.close_delay; | 1292 | port->close_delay = newinfo.close_delay; |
1294 | port->closing_wait = newinfo.closing_wait; | 1293 | port->closing_wait = newinfo.closing_wait; |
1295 | port->flags = ((port->flags & ~ASYNC_FLAGS) | | 1294 | port->flags = ((port->flags & ~ASYNC_FLAGS) | |
@@ -1336,7 +1335,7 @@ static int isicom_ioctl(struct tty_struct *tty, struct file *filp, | |||
1336 | if (isicom_paranoia_check(port, tty->name, "isicom_ioctl")) | 1335 | if (isicom_paranoia_check(port, tty->name, "isicom_ioctl")) |
1337 | return -ENODEV; | 1336 | return -ENODEV; |
1338 | 1337 | ||
1339 | switch(cmd) { | 1338 | switch (cmd) { |
1340 | case TCSBRK: | 1339 | case TCSBRK: |
1341 | retval = tty_check_change(tty); | 1340 | retval = tty_check_change(tty); |
1342 | if (retval) | 1341 | if (retval) |
@@ -1585,7 +1584,7 @@ static int __devinit load_firmware(struct pci_dev *pdev, | |||
1585 | default: | 1584 | default: |
1586 | dev_err(&pdev->dev, "Unknown signature.\n"); | 1585 | dev_err(&pdev->dev, "Unknown signature.\n"); |
1587 | goto end; | 1586 | goto end; |
1588 | } | 1587 | } |
1589 | 1588 | ||
1590 | retval = request_firmware(&fw, name, &pdev->dev); | 1589 | retval = request_firmware(&fw, name, &pdev->dev); |
1591 | if (retval) | 1590 | if (retval) |
@@ -1613,7 +1612,8 @@ static int __devinit load_firmware(struct pci_dev *pdev, | |||
1613 | if (WaitTillCardIsFree(base)) | 1612 | if (WaitTillCardIsFree(base)) |
1614 | goto errrelfw; | 1613 | goto errrelfw; |
1615 | 1614 | ||
1616 | if ((status = inw(base + 0x4)) != 0) { | 1615 | status = inw(base + 0x4); |
1616 | if (status != 0) { | ||
1617 | dev_warn(&pdev->dev, "Card%d rejected load header:\n" | 1617 | dev_warn(&pdev->dev, "Card%d rejected load header:\n" |
1618 | KERN_WARNING "Address:0x%x\n" | 1618 | KERN_WARNING "Address:0x%x\n" |
1619 | KERN_WARNING "Count:0x%x\n" | 1619 | KERN_WARNING "Count:0x%x\n" |
@@ -1630,12 +1630,13 @@ static int __devinit load_firmware(struct pci_dev *pdev, | |||
1630 | if (WaitTillCardIsFree(base)) | 1630 | if (WaitTillCardIsFree(base)) |
1631 | goto errrelfw; | 1631 | goto errrelfw; |
1632 | 1632 | ||
1633 | if ((status = inw(base + 0x4)) != 0) { | 1633 | status = inw(base + 0x4); |
1634 | if (status != 0) { | ||
1634 | dev_err(&pdev->dev, "Card%d got out of sync.Card " | 1635 | dev_err(&pdev->dev, "Card%d got out of sync.Card " |
1635 | "Status:0x%x\n", index + 1, status); | 1636 | "Status:0x%x\n", index + 1, status); |
1636 | goto errrelfw; | 1637 | goto errrelfw; |
1637 | } | 1638 | } |
1638 | } | 1639 | } |
1639 | 1640 | ||
1640 | /* XXX: should we test it by reading it back and comparing with original like | 1641 | /* XXX: should we test it by reading it back and comparing with original like |
1641 | * in load firmware package? */ | 1642 | * in load firmware package? */ |
@@ -1659,7 +1660,8 @@ static int __devinit load_firmware(struct pci_dev *pdev, | |||
1659 | if (WaitTillCardIsFree(base)) | 1660 | if (WaitTillCardIsFree(base)) |
1660 | goto errrelfw; | 1661 | goto errrelfw; |
1661 | 1662 | ||
1662 | if ((status = inw(base + 0x4)) != 0) { | 1663 | status = inw(base + 0x4); |
1664 | if (status != 0) { | ||
1663 | dev_warn(&pdev->dev, "Card%d rejected verify header:\n" | 1665 | dev_warn(&pdev->dev, "Card%d rejected verify header:\n" |
1664 | KERN_WARNING "Address:0x%x\n" | 1666 | KERN_WARNING "Address:0x%x\n" |
1665 | KERN_WARNING "Count:0x%x\n" | 1667 | KERN_WARNING "Count:0x%x\n" |
@@ -1692,7 +1694,8 @@ static int __devinit load_firmware(struct pci_dev *pdev, | |||
1692 | if (WaitTillCardIsFree(base)) | 1694 | if (WaitTillCardIsFree(base)) |
1693 | goto errrelfw; | 1695 | goto errrelfw; |
1694 | 1696 | ||
1695 | if ((status = inw(base + 0x4)) != 0) { | 1697 | status = inw(base + 0x4); |
1698 | if (status != 0) { | ||
1696 | dev_err(&pdev->dev, "Card%d verify got out of sync. " | 1699 | dev_err(&pdev->dev, "Card%d verify got out of sync. " |
1697 | "Card Status:0x%x\n", index + 1, status); | 1700 | "Card Status:0x%x\n", index + 1, status); |
1698 | goto errrelfw; | 1701 | goto errrelfw; |
@@ -1757,7 +1760,7 @@ static int __devinit isicom_probe(struct pci_dev *pdev, | |||
1757 | index + 1); | 1760 | index + 1); |
1758 | retval = -EBUSY; | 1761 | retval = -EBUSY; |
1759 | goto errdec; | 1762 | goto errdec; |
1760 | } | 1763 | } |
1761 | 1764 | ||
1762 | retval = request_irq(board->irq, isicom_interrupt, | 1765 | retval = request_irq(board->irq, isicom_interrupt, |
1763 | IRQF_SHARED | IRQF_DISABLED, ISICOM_NAME, board); | 1766 | IRQF_SHARED | IRQF_DISABLED, ISICOM_NAME, board); |
@@ -1811,7 +1814,7 @@ static int __init isicom_init(void) | |||
1811 | int retval, idx, channel; | 1814 | int retval, idx, channel; |
1812 | struct isi_port *port; | 1815 | struct isi_port *port; |
1813 | 1816 | ||
1814 | for(idx = 0; idx < BOARD_COUNT; idx++) { | 1817 | for (idx = 0; idx < BOARD_COUNT; idx++) { |
1815 | port = &isi_ports[idx * 16]; | 1818 | port = &isi_ports[idx * 16]; |
1816 | isi_card[idx].ports = port; | 1819 | isi_card[idx].ports = port; |
1817 | spin_lock_init(&isi_card[idx].card_lock); | 1820 | spin_lock_init(&isi_card[idx].card_lock); |
@@ -1825,7 +1828,7 @@ static int __init isicom_init(void) | |||
1825 | init_waitqueue_head(&port->open_wait); | 1828 | init_waitqueue_head(&port->open_wait); |
1826 | init_waitqueue_head(&port->close_wait); | 1829 | init_waitqueue_head(&port->close_wait); |
1827 | /* . . . */ | 1830 | /* . . . */ |
1828 | } | 1831 | } |
1829 | isi_card[idx].base = 0; | 1832 | isi_card[idx].base = 0; |
1830 | isi_card[idx].irq = 0; | 1833 | isi_card[idx].irq = 0; |
1831 | } | 1834 | } |