diff options
Diffstat (limited to 'drivers/char/cyclades.c')
-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 |