diff options
Diffstat (limited to 'drivers/char/istallion.c')
| -rw-r--r-- | drivers/char/istallion.c | 185 |
1 files changed, 64 insertions, 121 deletions
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 402838f4083e..4cd6c527ee41 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c | |||
| @@ -213,7 +213,6 @@ static int stli_shared; | |||
| 213 | * with the slave. Most of them need to be updated atomically, so always | 213 | * with the slave. Most of them need to be updated atomically, so always |
| 214 | * use the bit setting operations (unless protected by cli/sti). | 214 | * use the bit setting operations (unless protected by cli/sti). |
| 215 | */ | 215 | */ |
| 216 | #define ST_INITIALIZING 1 | ||
| 217 | #define ST_OPENING 2 | 216 | #define ST_OPENING 2 |
| 218 | #define ST_CLOSING 3 | 217 | #define ST_CLOSING 3 |
| 219 | #define ST_CMDING 4 | 218 | #define ST_CMDING 4 |
| @@ -621,7 +620,7 @@ static int stli_brdinit(struct stlibrd *brdp); | |||
| 621 | static int stli_startbrd(struct stlibrd *brdp); | 620 | static int stli_startbrd(struct stlibrd *brdp); |
| 622 | static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp); | 621 | static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp); |
| 623 | static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp); | 622 | static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp); |
| 624 | static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg); | 623 | static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg); |
| 625 | static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp); | 624 | static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp); |
| 626 | static void stli_poll(unsigned long arg); | 625 | static void stli_poll(unsigned long arg); |
| 627 | static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp); | 626 | static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp); |
| @@ -704,7 +703,7 @@ static const struct file_operations stli_fsiomem = { | |||
| 704 | .owner = THIS_MODULE, | 703 | .owner = THIS_MODULE, |
| 705 | .read = stli_memread, | 704 | .read = stli_memread, |
| 706 | .write = stli_memwrite, | 705 | .write = stli_memwrite, |
| 707 | .ioctl = stli_memioctl, | 706 | .unlocked_ioctl = stli_memioctl, |
| 708 | }; | 707 | }; |
| 709 | 708 | ||
| 710 | /*****************************************************************************/ | 709 | /*****************************************************************************/ |
| @@ -783,13 +782,32 @@ static int stli_parsebrd(struct stlconf *confp, char **argp) | |||
| 783 | 782 | ||
| 784 | /*****************************************************************************/ | 783 | /*****************************************************************************/ |
| 785 | 784 | ||
| 785 | /* | ||
| 786 | * On the first open of the device setup the port hardware, and | ||
| 787 | * initialize the per port data structure. Since initializing the port | ||
| 788 | * requires several commands to the board we will need to wait for any | ||
| 789 | * other open that is already initializing the port. | ||
| 790 | * | ||
| 791 | * Locking: protected by the port mutex. | ||
| 792 | */ | ||
| 793 | |||
| 794 | static int stli_activate(struct tty_port *port, struct tty_struct *tty) | ||
| 795 | { | ||
| 796 | struct stliport *portp = container_of(port, struct stliport, port); | ||
| 797 | struct stlibrd *brdp = stli_brds[portp->brdnr]; | ||
| 798 | int rc; | ||
| 799 | |||
| 800 | if ((rc = stli_initopen(tty, brdp, portp)) >= 0) | ||
| 801 | clear_bit(TTY_IO_ERROR, &tty->flags); | ||
| 802 | wake_up_interruptible(&portp->raw_wait); | ||
| 803 | return rc; | ||
| 804 | } | ||
| 805 | |||
| 786 | static int stli_open(struct tty_struct *tty, struct file *filp) | 806 | static int stli_open(struct tty_struct *tty, struct file *filp) |
| 787 | { | 807 | { |
| 788 | struct stlibrd *brdp; | 808 | struct stlibrd *brdp; |
| 789 | struct stliport *portp; | 809 | struct stliport *portp; |
| 790 | struct tty_port *port; | ||
| 791 | unsigned int minordev, brdnr, portnr; | 810 | unsigned int minordev, brdnr, portnr; |
| 792 | int rc; | ||
| 793 | 811 | ||
| 794 | minordev = tty->index; | 812 | minordev = tty->index; |
| 795 | brdnr = MINOR2BRD(minordev); | 813 | brdnr = MINOR2BRD(minordev); |
| @@ -809,95 +827,56 @@ static int stli_open(struct tty_struct *tty, struct file *filp) | |||
| 809 | return -ENODEV; | 827 | return -ENODEV; |
| 810 | if (portp->devnr < 1) | 828 | if (portp->devnr < 1) |
| 811 | return -ENODEV; | 829 | return -ENODEV; |
| 812 | port = &portp->port; | 830 | return tty_port_open(&portp->port, tty, filp); |
| 813 | |||
| 814 | /* | ||
| 815 | * On the first open of the device setup the port hardware, and | ||
| 816 | * initialize the per port data structure. Since initializing the port | ||
| 817 | * requires several commands to the board we will need to wait for any | ||
| 818 | * other open that is already initializing the port. | ||
| 819 | * | ||
| 820 | * Review - locking | ||
| 821 | */ | ||
| 822 | tty_port_tty_set(port, tty); | ||
| 823 | tty->driver_data = portp; | ||
| 824 | port->count++; | ||
| 825 | |||
| 826 | wait_event_interruptible(portp->raw_wait, | ||
| 827 | !test_bit(ST_INITIALIZING, &portp->state)); | ||
| 828 | if (signal_pending(current)) | ||
| 829 | return -ERESTARTSYS; | ||
| 830 | |||
| 831 | if ((portp->port.flags & ASYNC_INITIALIZED) == 0) { | ||
| 832 | set_bit(ST_INITIALIZING, &portp->state); | ||
| 833 | if ((rc = stli_initopen(tty, brdp, portp)) >= 0) { | ||
| 834 | /* Locking */ | ||
| 835 | port->flags |= ASYNC_INITIALIZED; | ||
| 836 | clear_bit(TTY_IO_ERROR, &tty->flags); | ||
| 837 | } | ||
| 838 | clear_bit(ST_INITIALIZING, &portp->state); | ||
| 839 | wake_up_interruptible(&portp->raw_wait); | ||
| 840 | if (rc < 0) | ||
| 841 | return rc; | ||
| 842 | } | ||
| 843 | return tty_port_block_til_ready(&portp->port, tty, filp); | ||
| 844 | } | 831 | } |
| 845 | 832 | ||
| 833 | |||
| 846 | /*****************************************************************************/ | 834 | /*****************************************************************************/ |
| 847 | 835 | ||
| 848 | static void stli_close(struct tty_struct *tty, struct file *filp) | 836 | static void stli_shutdown(struct tty_port *port) |
| 849 | { | 837 | { |
| 850 | struct stlibrd *brdp; | 838 | struct stlibrd *brdp; |
| 851 | struct stliport *portp; | 839 | unsigned long ftype; |
| 852 | struct tty_port *port; | ||
| 853 | unsigned long flags; | 840 | unsigned long flags; |
| 841 | struct stliport *portp = container_of(port, struct stliport, port); | ||
| 854 | 842 | ||
| 855 | portp = tty->driver_data; | 843 | if (portp->brdnr >= stli_nrbrds) |
| 856 | if (portp == NULL) | ||
| 857 | return; | 844 | return; |
| 858 | port = &portp->port; | 845 | brdp = stli_brds[portp->brdnr]; |
| 859 | 846 | if (brdp == NULL) | |
| 860 | if (tty_port_close_start(port, tty, filp) == 0) | ||
| 861 | return; | 847 | return; |
| 862 | 848 | ||
| 863 | /* | 849 | /* |
| 864 | * May want to wait for data to drain before closing. The BUSY flag | 850 | * May want to wait for data to drain before closing. The BUSY |
| 865 | * keeps track of whether we are still transmitting or not. It is | 851 | * flag keeps track of whether we are still transmitting or not. |
| 866 | * updated by messages from the slave - indicating when all chars | 852 | * It is updated by messages from the slave - indicating when all |
| 867 | * really have drained. | 853 | * chars really have drained. |
| 868 | */ | 854 | */ |
| 869 | spin_lock_irqsave(&stli_lock, flags); | ||
| 870 | if (tty == stli_txcooktty) | ||
| 871 | stli_flushchars(tty); | ||
| 872 | spin_unlock_irqrestore(&stli_lock, flags); | ||
| 873 | |||
| 874 | /* We end up doing this twice for the moment. This needs looking at | ||
| 875 | eventually. Note we still use portp->closing_wait as a result */ | ||
| 876 | if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE) | ||
| 877 | tty_wait_until_sent(tty, portp->closing_wait); | ||
| 878 | 855 | ||
| 879 | /* FIXME: port locking here needs attending to */ | 856 | if (!test_bit(ST_CLOSING, &portp->state)) |
| 880 | port->flags &= ~ASYNC_INITIALIZED; | 857 | stli_rawclose(brdp, portp, 0, 0); |
| 881 | 858 | ||
| 882 | brdp = stli_brds[portp->brdnr]; | 859 | spin_lock_irqsave(&stli_lock, flags); |
| 883 | stli_rawclose(brdp, portp, 0, 0); | ||
| 884 | if (tty->termios->c_cflag & HUPCL) { | ||
| 885 | stli_mkasysigs(&portp->asig, 0, 0); | ||
| 886 | if (test_bit(ST_CMDING, &portp->state)) | ||
| 887 | set_bit(ST_DOSIGS, &portp->state); | ||
| 888 | else | ||
| 889 | stli_sendcmd(brdp, portp, A_SETSIGNALS, &portp->asig, | ||
| 890 | sizeof(asysigs_t), 0); | ||
| 891 | } | ||
| 892 | clear_bit(ST_TXBUSY, &portp->state); | 860 | clear_bit(ST_TXBUSY, &portp->state); |
| 893 | clear_bit(ST_RXSTOP, &portp->state); | 861 | clear_bit(ST_RXSTOP, &portp->state); |
| 894 | set_bit(TTY_IO_ERROR, &tty->flags); | 862 | spin_unlock_irqrestore(&stli_lock, flags); |
| 895 | tty_ldisc_flush(tty); | ||
| 896 | set_bit(ST_DOFLUSHRX, &portp->state); | ||
| 897 | stli_flushbuffer(tty); | ||
| 898 | 863 | ||
| 899 | tty_port_close_end(port, tty); | 864 | ftype = FLUSHTX | FLUSHRX; |
| 900 | tty_port_tty_set(port, NULL); | 865 | stli_cmdwait(brdp, portp, A_FLUSH, &ftype, sizeof(u32), 0); |
| 866 | } | ||
| 867 | |||
| 868 | static void stli_close(struct tty_struct *tty, struct file *filp) | ||
| 869 | { | ||
| 870 | struct stliport *portp = tty->driver_data; | ||
| 871 | unsigned long flags; | ||
| 872 | if (portp == NULL) | ||
| 873 | return; | ||
| 874 | spin_lock_irqsave(&stli_lock, flags); | ||
| 875 | /* Flush any internal buffering out first */ | ||
| 876 | if (tty == stli_txcooktty) | ||
| 877 | stli_flushchars(tty); | ||
| 878 | spin_unlock_irqrestore(&stli_lock, flags); | ||
| 879 | tty_port_close(&portp->port, tty, filp); | ||
| 901 | } | 880 | } |
| 902 | 881 | ||
| 903 | /*****************************************************************************/ | 882 | /*****************************************************************************/ |
| @@ -1724,6 +1703,7 @@ static void stli_start(struct tty_struct *tty) | |||
| 1724 | 1703 | ||
| 1725 | /*****************************************************************************/ | 1704 | /*****************************************************************************/ |
| 1726 | 1705 | ||
| 1706 | |||
| 1727 | /* | 1707 | /* |
| 1728 | * Hangup this port. This is pretty much like closing the port, only | 1708 | * Hangup this port. This is pretty much like closing the port, only |
| 1729 | * a little more brutal. No waiting for data to drain. Shutdown the | 1709 | * a little more brutal. No waiting for data to drain. Shutdown the |
| @@ -1733,47 +1713,8 @@ static void stli_start(struct tty_struct *tty) | |||
| 1733 | 1713 | ||
| 1734 | static void stli_hangup(struct tty_struct *tty) | 1714 | static void stli_hangup(struct tty_struct *tty) |
| 1735 | { | 1715 | { |
| 1736 | struct stliport *portp; | 1716 | struct stliport *portp = tty->driver_data; |
| 1737 | struct stlibrd *brdp; | 1717 | tty_port_hangup(&portp->port); |
| 1738 | struct tty_port *port; | ||
| 1739 | unsigned long flags; | ||
| 1740 | |||
| 1741 | portp = tty->driver_data; | ||
| 1742 | if (portp == NULL) | ||
| 1743 | return; | ||
| 1744 | if (portp->brdnr >= stli_nrbrds) | ||
| 1745 | return; | ||
| 1746 | brdp = stli_brds[portp->brdnr]; | ||
| 1747 | if (brdp == NULL) | ||
| 1748 | return; | ||
| 1749 | port = &portp->port; | ||
| 1750 | |||
| 1751 | spin_lock_irqsave(&port->lock, flags); | ||
| 1752 | port->flags &= ~ASYNC_INITIALIZED; | ||
| 1753 | spin_unlock_irqrestore(&port->lock, flags); | ||
| 1754 | |||
| 1755 | if (!test_bit(ST_CLOSING, &portp->state)) | ||
| 1756 | stli_rawclose(brdp, portp, 0, 0); | ||
| 1757 | |||
| 1758 | spin_lock_irqsave(&stli_lock, flags); | ||
| 1759 | if (tty->termios->c_cflag & HUPCL) { | ||
| 1760 | stli_mkasysigs(&portp->asig, 0, 0); | ||
| 1761 | if (test_bit(ST_CMDING, &portp->state)) { | ||
| 1762 | set_bit(ST_DOSIGS, &portp->state); | ||
| 1763 | set_bit(ST_DOFLUSHTX, &portp->state); | ||
| 1764 | set_bit(ST_DOFLUSHRX, &portp->state); | ||
| 1765 | } else { | ||
| 1766 | stli_sendcmd(brdp, portp, A_SETSIGNALSF, | ||
| 1767 | &portp->asig, sizeof(asysigs_t), 0); | ||
| 1768 | } | ||
| 1769 | } | ||
| 1770 | |||
| 1771 | clear_bit(ST_TXBUSY, &portp->state); | ||
| 1772 | clear_bit(ST_RXSTOP, &portp->state); | ||
| 1773 | set_bit(TTY_IO_ERROR, &tty->flags); | ||
| 1774 | spin_unlock_irqrestore(&stli_lock, flags); | ||
| 1775 | |||
| 1776 | tty_port_hangup(port); | ||
| 1777 | } | 1718 | } |
| 1778 | 1719 | ||
| 1779 | /*****************************************************************************/ | 1720 | /*****************************************************************************/ |
| @@ -4311,7 +4252,7 @@ static int stli_getbrdstruct(struct stlibrd __user *arg) | |||
| 4311 | * reset it, and start/stop it. | 4252 | * reset it, and start/stop it. |
| 4312 | */ | 4253 | */ |
| 4313 | 4254 | ||
| 4314 | static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg) | 4255 | static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) |
| 4315 | { | 4256 | { |
| 4316 | struct stlibrd *brdp; | 4257 | struct stlibrd *brdp; |
| 4317 | int brdnr, rc, done; | 4258 | int brdnr, rc, done; |
| @@ -4356,7 +4297,7 @@ static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, un | |||
| 4356 | * Now handle the board specific ioctls. These all depend on the | 4297 | * Now handle the board specific ioctls. These all depend on the |
| 4357 | * minor number of the device they were called from. | 4298 | * minor number of the device they were called from. |
| 4358 | */ | 4299 | */ |
| 4359 | brdnr = iminor(ip); | 4300 | brdnr = iminor(fp->f_dentry->d_inode); |
| 4360 | if (brdnr >= STL_MAXBRDS) | 4301 | if (brdnr >= STL_MAXBRDS) |
| 4361 | return -ENODEV; | 4302 | return -ENODEV; |
| 4362 | brdp = stli_brds[brdnr]; | 4303 | brdp = stli_brds[brdnr]; |
| @@ -4420,6 +4361,8 @@ static const struct tty_operations stli_ops = { | |||
| 4420 | static const struct tty_port_operations stli_port_ops = { | 4361 | static const struct tty_port_operations stli_port_ops = { |
| 4421 | .carrier_raised = stli_carrier_raised, | 4362 | .carrier_raised = stli_carrier_raised, |
| 4422 | .dtr_rts = stli_dtr_rts, | 4363 | .dtr_rts = stli_dtr_rts, |
| 4364 | .activate = stli_activate, | ||
| 4365 | .shutdown = stli_shutdown, | ||
| 4423 | }; | 4366 | }; |
| 4424 | 4367 | ||
| 4425 | /*****************************************************************************/ | 4368 | /*****************************************************************************/ |
