[PATCH] drivers/char/mxser.c, 2.4.23-pre5, fix TIOCSBRK/TIOCCBRK.

Sergei Organov
2003-09-23T08:52:05Z

Problem:
drivers/char/mxser.c doesn't handle TIOCSBRK/TIOCCBRK ioctls.

Fix: The patch below fixes TIOCSBRK/TIOCCBRK handling in 'mxser.c' by means of
defining break_ctl routine for tty_driver thus lets upper-level tty driver
handle all break related ioctls.

diff -Naur linux-2.4.23-pre5/drivers/char/mxser.c linux-2.4.23-pre5.patched/drivers/char/mxser.c
--- linux-2.4.23-pre5/drivers/char/mxser.c Fri Nov 29 02:53:12 2002
+++ linux-2.4.23-pre5.patched/drivers/char/mxser.c Mon Sep 22 17:01:20 2003
@@ -29,11 +29,14 @@
*
* for : LINUX 2.0.X, 2.2.X, 2.4.X
* date : 2001/05/01
- * version : 1.2
+ * version : 1.2
*
* Fixes for C104H/PCI by Tim Hockin <thockin@sun.com>
* Added support for: C102, CI-132, CI-134, CP-132, CP-114, CT-114 cards
* by Damian Wrobel <dwrobel@ertel.com.pl>
+ * 09/03: Use tty_driver.break_ctl for break control. This fixes handling
+ * of TIOCSBRK/TIOCCBRK by the driver.
+ * by Sergei Organov <osv@topconrd.ru>
*
*/

@@ -65,7 +68,7 @@
#include <asm/bitops.h>
#include <asm/uaccess.h>

-#define MXSER_VERSION "1.2.1"
+#define MXSER_VERSION "1.2.2"

#define MXSERMAJOR 174
#define MXSERCUMAJOR 175
@@ -368,7 +371,7 @@
static int mxser_get_serial_info(struct mxser_struct *, struct serial_struct *);
static int mxser_set_serial_info(struct mxser_struct *, struct serial_struct *);
static int mxser_get_lsr_info(struct mxser_struct *, unsigned int *);
-static void mxser_send_break(struct mxser_struct *, int);
+static void mxser_break_ctl(struct tty_struct *, int);
static int mxser_get_modem_info(struct mxser_struct *, unsigned int *);
static int mxser_set_modem_info(struct mxser_struct *, unsigned int, unsigned int *);

@@ -556,6 +559,7 @@
mxvar_sdriver.stop = mxser_stop;
mxvar_sdriver.start = mxser_start;
mxvar_sdriver.hangup = mxser_hangup;
+ mxvar_sdriver.break_ctl = mxser_break_ctl;

/*
* The callout device is just like normal device except for
@@ -1061,7 +1065,6 @@
{
unsigned long flags;
struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
- int retval;
struct async_icount cprev, cnow; /* kernel counter temps */
struct serial_icounter_struct *p_cuser; /* user space */
unsigned long templ;
@@ -1074,21 +1077,6 @@
return (-EIO);
}
switch (cmd) {
- case TCSBRK: /* SVID version: non-zero arg --> no break */
- retval = tty_check_change(tty);
- if (retval)
- return (retval);
- tty_wait_until_sent(tty, 0);
- if (!arg)
- mxser_send_break(info, HZ / 4); /* 1/4 second */
- return (0);
- case TCSBRKP: /* support for POSIX tcsendbreak() */
- retval = tty_check_change(tty);
- if (retval)
- return (retval);
- tty_wait_until_sent(tty, 0);
- mxser_send_break(info, arg ? arg * (HZ / 10) : HZ / 4);
- return (0);
case TIOCGSOFTCAR:
return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg);
case TIOCSSOFTCAR:
@@ -2253,19 +2241,18 @@
}

/*
- * This routine sends a break character out the serial port.
+ * This routine turns the break condition on or off
*/
-static void mxser_send_break(struct mxser_struct *info, int duration)
+static void mxser_break_ctl(struct tty_struct *tty, int break_state)
{
+ struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
unsigned long flags;
- if (!info->base)
- return;
- set_current_state(TASK_INTERRUPTIBLE);
- save_flags(flags);
- cli();
- outb(inb(info->base + UART_LCR) | UART_LCR_SBC, info->base + UART_LCR);
- schedule_timeout(duration);
- outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC, info->base + UART_LCR);
+
+ save_flags(flags); cli();
+ if (break_state == -1)
+ outb(inb(info->base + UART_LCR) | UART_LCR_SBC, info->base + UART_LCR);
+ else
+ outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC, info->base + UART_LCR);
restore_flags(flags);
}