diff options
Diffstat (limited to 'drivers/char/nozomi.c')
-rw-r--r-- | drivers/char/nozomi.c | 115 |
1 files changed, 68 insertions, 47 deletions
diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index 2ad7d37afbd0..cd405bcf53a6 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c | |||
@@ -371,6 +371,8 @@ struct port { | |||
371 | struct mutex tty_sem; | 371 | struct mutex tty_sem; |
372 | wait_queue_head_t tty_wait; | 372 | wait_queue_head_t tty_wait; |
373 | struct async_icount tty_icount; | 373 | struct async_icount tty_icount; |
374 | |||
375 | struct nozomi *dc; | ||
374 | }; | 376 | }; |
375 | 377 | ||
376 | /* Private data one for each card in the system */ | 378 | /* Private data one for each card in the system */ |
@@ -414,6 +416,8 @@ MODULE_DEVICE_TABLE(pci, nozomi_pci_tbl); | |||
414 | static struct nozomi *ndevs[NOZOMI_MAX_CARDS]; | 416 | static struct nozomi *ndevs[NOZOMI_MAX_CARDS]; |
415 | static struct tty_driver *ntty_driver; | 417 | static struct tty_driver *ntty_driver; |
416 | 418 | ||
419 | static const struct tty_port_operations noz_tty_port_ops; | ||
420 | |||
417 | /* | 421 | /* |
418 | * find card by tty_index | 422 | * find card by tty_index |
419 | */ | 423 | */ |
@@ -1473,9 +1477,11 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev, | |||
1473 | 1477 | ||
1474 | for (i = 0; i < MAX_PORT; i++) { | 1478 | for (i = 0; i < MAX_PORT; i++) { |
1475 | struct device *tty_dev; | 1479 | struct device *tty_dev; |
1476 | 1480 | struct port *port = &dc->port[i]; | |
1477 | mutex_init(&dc->port[i].tty_sem); | 1481 | port->dc = dc; |
1478 | tty_port_init(&dc->port[i].port); | 1482 | mutex_init(&port->tty_sem); |
1483 | tty_port_init(&port->port); | ||
1484 | port->port.ops = &noz_tty_port_ops; | ||
1479 | tty_dev = tty_register_device(ntty_driver, dc->index_start + i, | 1485 | tty_dev = tty_register_device(ntty_driver, dc->index_start + i, |
1480 | &pdev->dev); | 1486 | &pdev->dev); |
1481 | 1487 | ||
@@ -1600,67 +1606,74 @@ static void set_dtr(const struct tty_struct *tty, int dtr) | |||
1600 | * ---------------------------------------------------------------------------- | 1606 | * ---------------------------------------------------------------------------- |
1601 | */ | 1607 | */ |
1602 | 1608 | ||
1603 | /* Called when the userspace process opens the tty, /dev/noz*. */ | 1609 | static int ntty_install(struct tty_driver *driver, struct tty_struct *tty) |
1604 | static int ntty_open(struct tty_struct *tty, struct file *file) | ||
1605 | { | 1610 | { |
1606 | struct port *port = get_port_by_tty(tty); | 1611 | struct port *port = get_port_by_tty(tty); |
1607 | struct nozomi *dc = get_dc_by_tty(tty); | 1612 | struct nozomi *dc = get_dc_by_tty(tty); |
1608 | unsigned long flags; | 1613 | int ret; |
1609 | |||
1610 | if (!port || !dc || dc->state != NOZOMI_STATE_READY) | 1614 | if (!port || !dc || dc->state != NOZOMI_STATE_READY) |
1611 | return -ENODEV; | 1615 | return -ENODEV; |
1612 | 1616 | ret = tty_init_termios(tty); | |
1613 | if (mutex_lock_interruptible(&port->tty_sem)) | 1617 | if (ret == 0) { |
1614 | return -ERESTARTSYS; | 1618 | tty_driver_kref_get(driver); |
1615 | 1619 | driver->ttys[tty->index] = tty; | |
1616 | port->port.count++; | ||
1617 | dc->open_ttys++; | ||
1618 | |||
1619 | /* Enable interrupt downlink for channel */ | ||
1620 | if (port->port.count == 1) { | ||
1621 | tty->driver_data = port; | ||
1622 | tty_port_tty_set(&port->port, tty); | ||
1623 | DBG1("open: %d", port->token_dl); | ||
1624 | spin_lock_irqsave(&dc->spin_mutex, flags); | ||
1625 | dc->last_ier = dc->last_ier | port->token_dl; | ||
1626 | writew(dc->last_ier, dc->reg_ier); | ||
1627 | spin_unlock_irqrestore(&dc->spin_mutex, flags); | ||
1628 | } | 1620 | } |
1629 | mutex_unlock(&port->tty_sem); | 1621 | return ret; |
1630 | return 0; | ||
1631 | } | 1622 | } |
1632 | 1623 | ||
1633 | /* Called when the userspace process close the tty, /dev/noz*. Also | 1624 | static void ntty_cleanup(struct tty_struct *tty) |
1634 | called immediately if ntty_open fails in which case tty->driver_data | 1625 | { |
1635 | will be NULL an we exit by the first return */ | 1626 | tty->driver_data = NULL; |
1627 | } | ||
1636 | 1628 | ||
1637 | static void ntty_close(struct tty_struct *tty, struct file *file) | 1629 | static int ntty_activate(struct tty_port *tport, struct tty_struct *tty) |
1638 | { | 1630 | { |
1639 | struct nozomi *dc = get_dc_by_tty(tty); | 1631 | struct port *port = container_of(tport, struct port, port); |
1640 | struct port *nport = tty->driver_data; | 1632 | struct nozomi *dc = port->dc; |
1641 | struct tty_port *port = &nport->port; | ||
1642 | unsigned long flags; | 1633 | unsigned long flags; |
1643 | 1634 | ||
1644 | if (!dc || !nport) | 1635 | DBG1("open: %d", port->token_dl); |
1645 | return; | 1636 | spin_lock_irqsave(&dc->spin_mutex, flags); |
1637 | dc->last_ier = dc->last_ier | port->token_dl; | ||
1638 | writew(dc->last_ier, dc->reg_ier); | ||
1639 | dc->open_ttys++; | ||
1640 | spin_unlock_irqrestore(&dc->spin_mutex, flags); | ||
1641 | printk("noz: activated %d: %p\n", tty->index, tport); | ||
1642 | return 0; | ||
1643 | } | ||
1646 | 1644 | ||
1647 | /* Users cannot interrupt a close */ | 1645 | static int ntty_open(struct tty_struct *tty, struct file *filp) |
1648 | mutex_lock(&nport->tty_sem); | 1646 | { |
1647 | struct port *port = get_port_by_tty(tty); | ||
1648 | return tty_port_open(&port->port, tty, filp); | ||
1649 | } | ||
1649 | 1650 | ||
1650 | WARN_ON(!port->count); | 1651 | static void ntty_shutdown(struct tty_port *tport) |
1652 | { | ||
1653 | struct port *port = container_of(tport, struct port, port); | ||
1654 | struct nozomi *dc = port->dc; | ||
1655 | unsigned long flags; | ||
1651 | 1656 | ||
1657 | DBG1("close: %d", port->token_dl); | ||
1658 | spin_lock_irqsave(&dc->spin_mutex, flags); | ||
1659 | dc->last_ier &= ~(port->token_dl); | ||
1660 | writew(dc->last_ier, dc->reg_ier); | ||
1652 | dc->open_ttys--; | 1661 | dc->open_ttys--; |
1653 | port->count--; | 1662 | spin_unlock_irqrestore(&dc->spin_mutex, flags); |
1663 | printk("noz: shutdown %p\n", tport); | ||
1664 | } | ||
1654 | 1665 | ||
1655 | if (port->count == 0) { | 1666 | static void ntty_close(struct tty_struct *tty, struct file *filp) |
1656 | DBG1("close: %d", nport->token_dl); | 1667 | { |
1657 | tty_port_tty_set(port, NULL); | 1668 | struct port *port = tty->driver_data; |
1658 | spin_lock_irqsave(&dc->spin_mutex, flags); | 1669 | if (port) |
1659 | dc->last_ier &= ~(nport->token_dl); | 1670 | tty_port_close(&port->port, tty, filp); |
1660 | writew(dc->last_ier, dc->reg_ier); | 1671 | } |
1661 | spin_unlock_irqrestore(&dc->spin_mutex, flags); | 1672 | |
1662 | } | 1673 | static void ntty_hangup(struct tty_struct *tty) |
1663 | mutex_unlock(&nport->tty_sem); | 1674 | { |
1675 | struct port *port = tty->driver_data; | ||
1676 | tty_port_hangup(&port->port); | ||
1664 | } | 1677 | } |
1665 | 1678 | ||
1666 | /* | 1679 | /* |
@@ -1906,10 +1919,16 @@ exit_in_buffer: | |||
1906 | return rval; | 1919 | return rval; |
1907 | } | 1920 | } |
1908 | 1921 | ||
1922 | static const struct tty_port_operations noz_tty_port_ops = { | ||
1923 | .activate = ntty_activate, | ||
1924 | .shutdown = ntty_shutdown, | ||
1925 | }; | ||
1926 | |||
1909 | static const struct tty_operations tty_ops = { | 1927 | static const struct tty_operations tty_ops = { |
1910 | .ioctl = ntty_ioctl, | 1928 | .ioctl = ntty_ioctl, |
1911 | .open = ntty_open, | 1929 | .open = ntty_open, |
1912 | .close = ntty_close, | 1930 | .close = ntty_close, |
1931 | .hangup = ntty_hangup, | ||
1913 | .write = ntty_write, | 1932 | .write = ntty_write, |
1914 | .write_room = ntty_write_room, | 1933 | .write_room = ntty_write_room, |
1915 | .unthrottle = ntty_unthrottle, | 1934 | .unthrottle = ntty_unthrottle, |
@@ -1917,6 +1936,8 @@ static const struct tty_operations tty_ops = { | |||
1917 | .chars_in_buffer = ntty_chars_in_buffer, | 1936 | .chars_in_buffer = ntty_chars_in_buffer, |
1918 | .tiocmget = ntty_tiocmget, | 1937 | .tiocmget = ntty_tiocmget, |
1919 | .tiocmset = ntty_tiocmset, | 1938 | .tiocmset = ntty_tiocmset, |
1939 | .install = ntty_install, | ||
1940 | .cleanup = ntty_cleanup, | ||
1920 | }; | 1941 | }; |
1921 | 1942 | ||
1922 | /* Module initialization */ | 1943 | /* Module initialization */ |