aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/cyclades.c153
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 }
2568end:
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