diff options
| -rw-r--r-- | drivers/char/cyclades.c | 153 |
1 files changed, 66 insertions, 87 deletions
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index e1637ad9390e..ed66c3ab230d 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c | |||
| @@ -831,6 +831,7 @@ static void cyy_change_rts_dtr(struct cyclades_port *info, unsigned int set, | |||
| 831 | struct cyclades_card *card = info->card; | 831 | struct cyclades_card *card = info->card; |
| 832 | void __iomem *base_addr; | 832 | void __iomem *base_addr; |
| 833 | int chip, channel, index; | 833 | int chip, channel, index; |
| 834 | u32 rts, dtr, msvrr, msvrd; | ||
| 834 | 835 | ||
| 835 | channel = info->line - card->first_line; | 836 | channel = info->line - card->first_line; |
| 836 | chip = channel >> 2; | 837 | chip = channel >> 2; |
| @@ -838,29 +839,28 @@ static void cyy_change_rts_dtr(struct cyclades_port *info, unsigned int set, | |||
| 838 | index = card->bus_index; | 839 | index = card->bus_index; |
| 839 | base_addr = card->base_addr + (cy_chip_offset[chip] << index); | 840 | base_addr = card->base_addr + (cy_chip_offset[chip] << index); |
| 840 | 841 | ||
| 842 | if (info->rtsdtr_inv) { | ||
| 843 | msvrr = CyMSVR2; | ||
| 844 | msvrd = CyMSVR1; | ||
| 845 | rts = CyDTR; | ||
| 846 | dtr = CyRTS; | ||
| 847 | } else { | ||
| 848 | msvrr = CyMSVR1; | ||
| 849 | msvrd = CyMSVR2; | ||
| 850 | rts = CyRTS; | ||
| 851 | dtr = CyDTR; | ||
| 852 | } | ||
| 841 | if (set & TIOCM_RTS) { | 853 | if (set & TIOCM_RTS) { |
| 842 | cy_writeb(base_addr + (CyCAR << index), (u_char) channel); | 854 | cy_writeb(base_addr + (CyCAR << index), (u8)channel); |
| 843 | if (info->rtsdtr_inv) { | 855 | cy_writeb(base_addr + (msvrr << index), rts); |
| 844 | cy_writeb(base_addr + (CyMSVR2 << index), CyDTR); | ||
| 845 | } else { | ||
| 846 | cy_writeb(base_addr + (CyMSVR1 << index), CyRTS); | ||
| 847 | } | ||
| 848 | } | 856 | } |
| 849 | if (clear & TIOCM_RTS) { | 857 | if (clear & TIOCM_RTS) { |
| 850 | cy_writeb(base_addr + (CyCAR << index), (u_char) channel); | 858 | cy_writeb(base_addr + (CyCAR << index), (u8)channel); |
| 851 | if (info->rtsdtr_inv) { | 859 | cy_writeb(base_addr + (msvrr << index), ~rts); |
| 852 | cy_writeb(base_addr + (CyMSVR2 << index), ~CyDTR); | ||
| 853 | } else { | ||
| 854 | cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS); | ||
| 855 | } | ||
| 856 | } | 860 | } |
| 857 | if (set & TIOCM_DTR) { | 861 | if (set & TIOCM_DTR) { |
| 858 | cy_writeb(base_addr + (CyCAR << index), (u_char) channel); | 862 | cy_writeb(base_addr + (CyCAR << index), (u8)channel); |
| 859 | if (info->rtsdtr_inv) { | 863 | cy_writeb(base_addr + (msvrd << index), dtr); |
| 860 | cy_writeb(base_addr + (CyMSVR1 << index), CyRTS); | ||
| 861 | } else { | ||
| 862 | cy_writeb(base_addr + (CyMSVR2 << index), CyDTR); | ||
| 863 | } | ||
| 864 | #ifdef CY_DEBUG_DTR | 864 | #ifdef CY_DEBUG_DTR |
| 865 | printk(KERN_DEBUG "cyc:set_modem_info raising DTR\n"); | 865 | printk(KERN_DEBUG "cyc:set_modem_info raising DTR\n"); |
| 866 | printk(KERN_DEBUG " status: 0x%x, 0x%x\n", | 866 | printk(KERN_DEBUG " status: 0x%x, 0x%x\n", |
| @@ -869,13 +869,8 @@ static void cyy_change_rts_dtr(struct cyclades_port *info, unsigned int set, | |||
| 869 | #endif | 869 | #endif |
| 870 | } | 870 | } |
| 871 | if (clear & TIOCM_DTR) { | 871 | if (clear & TIOCM_DTR) { |
| 872 | cy_writeb(base_addr + (CyCAR << index), (u_char) channel); | 872 | cy_writeb(base_addr + (CyCAR << index), (u8)channel); |
| 873 | if (info->rtsdtr_inv) { | 873 | cy_writeb(base_addr + (msvrd << index), ~dtr); |
| 874 | cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS); | ||
| 875 | } else { | ||
| 876 | cy_writeb(base_addr + (CyMSVR2 << index), ~CyDTR); | ||
| 877 | } | ||
| 878 | |||
| 879 | #ifdef CY_DEBUG_DTR | 874 | #ifdef CY_DEBUG_DTR |
| 880 | printk(KERN_DEBUG "cyc:set_modem_info dropping DTR\n"); | 875 | printk(KERN_DEBUG "cyc:set_modem_info dropping DTR\n"); |
| 881 | printk(KERN_DEBUG " status: 0x%x, 0x%x\n", | 876 | printk(KERN_DEBUG " status: 0x%x, 0x%x\n", |
| @@ -2518,28 +2513,27 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file) | |||
| 2518 | { | 2513 | { |
| 2519 | struct cyclades_port *info = tty->driver_data; | 2514 | struct cyclades_port *info = tty->driver_data; |
| 2520 | struct cyclades_card *card; | 2515 | struct cyclades_card *card; |
| 2521 | int chip, channel, index; | ||
| 2522 | void __iomem *base_addr; | 2516 | void __iomem *base_addr; |
| 2523 | unsigned long flags; | 2517 | int result, channel; |
| 2524 | unsigned char status; | ||
| 2525 | unsigned long lstatus; | ||
| 2526 | unsigned int result; | ||
| 2527 | 2518 | ||
| 2528 | if (serial_paranoia_check(info, tty->name, __func__)) | 2519 | if (serial_paranoia_check(info, tty->name, __func__)) |
| 2529 | return -ENODEV; | 2520 | return -ENODEV; |
| 2530 | 2521 | ||
| 2531 | lock_kernel(); | ||
| 2532 | |||
| 2533 | card = info->card; | 2522 | card = info->card; |
| 2534 | channel = info->line - card->first_line; | 2523 | channel = info->line - card->first_line; |
| 2524 | |||
| 2525 | lock_kernel(); | ||
| 2535 | if (!cy_is_Z(card)) { | 2526 | if (!cy_is_Z(card)) { |
| 2536 | chip = channel >> 2; | 2527 | unsigned long flags; |
| 2528 | unsigned char status; | ||
| 2529 | int chip = channel >> 2; | ||
| 2530 | int index = card->bus_index; | ||
| 2531 | |||
| 2537 | channel &= 0x03; | 2532 | channel &= 0x03; |
| 2538 | index = card->bus_index; | ||
| 2539 | base_addr = card->base_addr + (cy_chip_offset[chip] << index); | 2533 | base_addr = card->base_addr + (cy_chip_offset[chip] << index); |
| 2540 | 2534 | ||
| 2541 | spin_lock_irqsave(&card->card_lock, flags); | 2535 | spin_lock_irqsave(&card->card_lock, flags); |
| 2542 | cy_writeb(base_addr + (CyCAR << index), (u_char) channel); | 2536 | cy_writeb(base_addr + (CyCAR << index), (u8)channel); |
| 2543 | status = readb(base_addr + (CyMSVR1 << index)); | 2537 | status = readb(base_addr + (CyMSVR1 << index)); |
| 2544 | status |= readb(base_addr + (CyMSVR2 << index)); | 2538 | status |= readb(base_addr + (CyMSVR2 << index)); |
| 2545 | spin_unlock_irqrestore(&card->card_lock, flags); | 2539 | spin_unlock_irqrestore(&card->card_lock, flags); |
| @@ -2556,21 +2550,22 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file) | |||
| 2556 | ((status & CyDSR) ? TIOCM_DSR : 0) | | 2550 | ((status & CyDSR) ? TIOCM_DSR : 0) | |
| 2557 | ((status & CyCTS) ? TIOCM_CTS : 0); | 2551 | ((status & CyCTS) ? TIOCM_CTS : 0); |
| 2558 | } else { | 2552 | } else { |
| 2559 | if (cyz_is_loaded(card)) { | 2553 | u32 lstatus; |
| 2560 | lstatus = readl(&info->u.cyz.ch_ctrl->rs_status); | 2554 | |
| 2561 | result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0) | | 2555 | if (!cyz_is_loaded(card)) { |
| 2562 | ((lstatus & C_RS_DTR) ? TIOCM_DTR : 0) | | 2556 | result = -ENODEV; |
| 2563 | ((lstatus & C_RS_DCD) ? TIOCM_CAR : 0) | | 2557 | goto end; |
| 2564 | ((lstatus & C_RS_RI) ? TIOCM_RNG : 0) | | ||
| 2565 | ((lstatus & C_RS_DSR) ? TIOCM_DSR : 0) | | ||
| 2566 | ((lstatus & C_RS_CTS) ? TIOCM_CTS : 0); | ||
| 2567 | } else { | ||
| 2568 | result = 0; | ||
| 2569 | unlock_kernel(); | ||
| 2570 | return -ENODEV; | ||
| 2571 | } | 2558 | } |
| 2572 | 2559 | ||
| 2560 | lstatus = readl(&info->u.cyz.ch_ctrl->rs_status); | ||
| 2561 | result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0) | | ||
| 2562 | ((lstatus & C_RS_DTR) ? TIOCM_DTR : 0) | | ||
| 2563 | ((lstatus & C_RS_DCD) ? TIOCM_CAR : 0) | | ||
| 2564 | ((lstatus & C_RS_RI) ? TIOCM_RNG : 0) | | ||
| 2565 | ((lstatus & C_RS_DSR) ? TIOCM_DSR : 0) | | ||
| 2566 | ((lstatus & C_RS_CTS) ? TIOCM_CTS : 0); | ||
| 2573 | } | 2567 | } |
| 2568 | end: | ||
| 2574 | unlock_kernel(); | 2569 | unlock_kernel(); |
| 2575 | return result; | 2570 | return result; |
| 2576 | } /* cy_tiomget */ | 2571 | } /* cy_tiomget */ |
| @@ -2582,68 +2577,52 @@ cy_tiocmset(struct tty_struct *tty, struct file *file, | |||
| 2582 | struct cyclades_port *info = tty->driver_data; | 2577 | struct cyclades_port *info = tty->driver_data; |
| 2583 | struct cyclades_card *card; | 2578 | struct cyclades_card *card; |
| 2584 | unsigned long flags; | 2579 | unsigned long flags; |
| 2585 | int channel, retval; | ||
| 2586 | 2580 | ||
| 2587 | if (serial_paranoia_check(info, tty->name, __func__)) | 2581 | if (serial_paranoia_check(info, tty->name, __func__)) |
| 2588 | return -ENODEV; | 2582 | return -ENODEV; |
| 2589 | 2583 | ||
| 2590 | card = info->card; | 2584 | card = info->card; |
| 2591 | channel = (info->line) - (card->first_line); | ||
| 2592 | if (!cy_is_Z(card)) { | 2585 | if (!cy_is_Z(card)) { |
| 2593 | spin_lock_irqsave(&card->card_lock, flags); | 2586 | spin_lock_irqsave(&card->card_lock, flags); |
| 2594 | cyy_change_rts_dtr(info, set, clear); | 2587 | cyy_change_rts_dtr(info, set, clear); |
| 2595 | spin_unlock_irqrestore(&card->card_lock, flags); | 2588 | spin_unlock_irqrestore(&card->card_lock, flags); |
| 2596 | } else { | 2589 | } else { |
| 2597 | if (cyz_is_loaded(card)) { | 2590 | struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; |
| 2598 | struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; | 2591 | int retval, channel = info->line - card->first_line; |
| 2599 | 2592 | u32 rs; | |
| 2600 | if (set & TIOCM_RTS) { | 2593 | |
| 2601 | spin_lock_irqsave(&card->card_lock, flags); | 2594 | if (!cyz_is_loaded(card)) |
| 2602 | cy_writel(&ch_ctrl->rs_control, | 2595 | return -ENODEV; |
| 2603 | readl(&ch_ctrl->rs_control) | C_RS_RTS); | 2596 | |
| 2604 | spin_unlock_irqrestore(&card->card_lock, flags); | 2597 | spin_lock_irqsave(&card->card_lock, flags); |
| 2605 | } | 2598 | rs = readl(&ch_ctrl->rs_control); |
| 2606 | if (clear & TIOCM_RTS) { | 2599 | if (set & TIOCM_RTS) |
| 2607 | spin_lock_irqsave(&card->card_lock, flags); | 2600 | rs |= C_RS_RTS; |
| 2608 | cy_writel(&ch_ctrl->rs_control, | 2601 | if (clear & TIOCM_RTS) |
| 2609 | readl(&ch_ctrl->rs_control) & | 2602 | rs &= ~C_RS_RTS; |
| 2610 | ~C_RS_RTS); | 2603 | if (set & TIOCM_DTR) { |
| 2611 | spin_unlock_irqrestore(&card->card_lock, flags); | 2604 | rs |= C_RS_DTR; |
| 2612 | } | ||
| 2613 | if (set & TIOCM_DTR) { | ||
| 2614 | spin_lock_irqsave(&card->card_lock, flags); | ||
| 2615 | cy_writel(&ch_ctrl->rs_control, | ||
| 2616 | readl(&ch_ctrl->rs_control) | C_RS_DTR); | ||
| 2617 | #ifdef CY_DEBUG_DTR | 2605 | #ifdef CY_DEBUG_DTR |
| 2618 | printk(KERN_DEBUG "cyc:set_modem_info raising " | 2606 | printk(KERN_DEBUG "cyc:set_modem_info raising Z DTR\n"); |
| 2619 | "Z DTR\n"); | ||
| 2620 | #endif | 2607 | #endif |
| 2621 | spin_unlock_irqrestore(&card->card_lock, flags); | 2608 | } |
| 2622 | } | 2609 | if (clear & TIOCM_DTR) { |
| 2623 | if (clear & TIOCM_DTR) { | 2610 | rs &= ~C_RS_DTR; |
| 2624 | spin_lock_irqsave(&card->card_lock, flags); | ||
| 2625 | cy_writel(&ch_ctrl->rs_control, | ||
| 2626 | readl(&ch_ctrl->rs_control) & | ||
| 2627 | ~C_RS_DTR); | ||
| 2628 | #ifdef CY_DEBUG_DTR | 2611 | #ifdef CY_DEBUG_DTR |
| 2629 | printk(KERN_DEBUG "cyc:set_modem_info clearing " | 2612 | printk(KERN_DEBUG "cyc:set_modem_info clearing " |
| 2630 | "Z DTR\n"); | 2613 | "Z DTR\n"); |
| 2631 | #endif | 2614 | #endif |
| 2632 | spin_unlock_irqrestore(&card->card_lock, flags); | ||
| 2633 | } | ||
| 2634 | } else { | ||
| 2635 | return -ENODEV; | ||
| 2636 | } | 2615 | } |
| 2637 | spin_lock_irqsave(&card->card_lock, flags); | 2616 | cy_writel(&ch_ctrl->rs_control, rs); |
| 2638 | retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L); | 2617 | retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L); |
| 2618 | spin_unlock_irqrestore(&card->card_lock, flags); | ||
| 2639 | if (retval != 0) { | 2619 | if (retval != 0) { |
| 2640 | printk(KERN_ERR "cyc:set_modem_info retval on ttyC%d " | 2620 | printk(KERN_ERR "cyc:set_modem_info retval on ttyC%d " |
| 2641 | "was %x\n", info->line, retval); | 2621 | "was %x\n", info->line, retval); |
| 2642 | } | 2622 | } |
| 2643 | spin_unlock_irqrestore(&card->card_lock, flags); | ||
| 2644 | } | 2623 | } |
| 2645 | return 0; | 2624 | return 0; |
| 2646 | } /* cy_tiocmset */ | 2625 | } |
| 2647 | 2626 | ||
| 2648 | /* | 2627 | /* |
| 2649 | * cy_break() --- routine which turns the break handling on or off | 2628 | * cy_break() --- routine which turns the break handling on or off |
