Merge branch 'sfi-release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb...
[cascardo/linux.git] / drivers / usb / serial / mos7720.c
index ccd4dd3..763e32a 100644 (file)
@@ -85,7 +85,7 @@ static int debug;
 #define MOSCHIP_DEVICE_ID_7720         0x7720
 #define MOSCHIP_DEVICE_ID_7715         0x7715
 
-static struct usb_device_id moschip_port_id_table [] = {
+static struct usb_device_id moschip_port_id_table[] = {
        { USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7720) },
        { } /* terminating entry */
 };
@@ -319,8 +319,7 @@ static int send_mos_cmd(struct usb_serial *serial, __u8 request, __u16 value,
        return status;
 }
 
-static int mos7720_open(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static int mos7720_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
        struct usb_serial *serial;
        struct usb_serial_port *port0;
@@ -378,10 +377,14 @@ static int mos7720_open(struct tty_struct *tty,
         /* Initialize MCS7720 -- Write Init values to corresponding Registers
          *
          * Register Index
+         * 0 : THR/RHR
          * 1 : IER
          * 2 : FCR
          * 3 : LCR
          * 4 : MCR
+         * 5 : LSR
+         * 6 : MSR
+         * 7 : SPR
          *
          * 0x08 : SP1/2 Control Reg
          */
@@ -1250,20 +1253,88 @@ static void mos7720_set_termios(struct tty_struct *tty,
 static int get_lsr_info(struct tty_struct *tty,
                struct moschip_port *mos7720_port, unsigned int __user *value)
 {
-       int count;
+       struct usb_serial_port *port = tty->driver_data;
        unsigned int result = 0;
+       unsigned char data = 0;
+       int port_number = port->number - port->serial->minor;
+       int count;
 
        count = mos7720_chars_in_buffer(tty);
        if (count == 0) {
-               dbg("%s -- Empty", __func__);
-               result = TIOCSER_TEMT;
+               send_mos_cmd(port->serial, MOS_READ, port_number,
+                                                       UART_LSR, &data);
+               if ((data & (UART_LSR_TEMT | UART_LSR_THRE))
+                                       == (UART_LSR_TEMT | UART_LSR_THRE)) {
+                       dbg("%s -- Empty", __func__);
+                       result = TIOCSER_TEMT;
+               }
        }
-
        if (copy_to_user(value, &result, sizeof(int)))
                return -EFAULT;
        return 0;
 }
 
+static int mos7720_tiocmget(struct tty_struct *tty, struct file *file)
+{
+       struct usb_serial_port *port = tty->driver_data;
+       struct moschip_port *mos7720_port = usb_get_serial_port_data(port);
+       unsigned int result = 0;
+       unsigned int mcr ;
+       unsigned int msr ;
+
+       dbg("%s - port %d", __func__, port->number);
+
+       mcr = mos7720_port->shadowMCR;
+       msr = mos7720_port->shadowMSR;
+
+       result = ((mcr & UART_MCR_DTR)  ? TIOCM_DTR : 0)   /* 0x002 */
+         | ((mcr & UART_MCR_RTS)   ? TIOCM_RTS : 0)   /* 0x004 */
+         | ((msr & UART_MSR_CTS)   ? TIOCM_CTS : 0)   /* 0x020 */
+         | ((msr & UART_MSR_DCD)   ? TIOCM_CAR : 0)   /* 0x040 */
+         | ((msr & UART_MSR_RI)    ? TIOCM_RI :  0)   /* 0x080 */
+         | ((msr & UART_MSR_DSR)   ? TIOCM_DSR : 0);  /* 0x100 */
+
+       dbg("%s -- %x", __func__, result);
+
+       return result;
+}
+
+static int mos7720_tiocmset(struct tty_struct *tty, struct file *file,
+                                       unsigned int set, unsigned int clear)
+{
+       struct usb_serial_port *port = tty->driver_data;
+       struct moschip_port *mos7720_port = usb_get_serial_port_data(port);
+       unsigned int mcr ;
+       unsigned char lmcr;
+
+       dbg("%s - port %d", __func__, port->number);
+       dbg("he was at tiocmget");
+
+       mcr = mos7720_port->shadowMCR;
+
+       if (set & TIOCM_RTS)
+               mcr |= UART_MCR_RTS;
+       if (set & TIOCM_DTR)
+               mcr |= UART_MCR_DTR;
+       if (set & TIOCM_LOOP)
+               mcr |= UART_MCR_LOOP;
+
+       if (clear & TIOCM_RTS)
+               mcr &= ~UART_MCR_RTS;
+       if (clear & TIOCM_DTR)
+               mcr &= ~UART_MCR_DTR;
+       if (clear & TIOCM_LOOP)
+               mcr &= ~UART_MCR_LOOP;
+
+       mos7720_port->shadowMCR = mcr;
+       lmcr = mos7720_port->shadowMCR;
+
+       send_mos_cmd(port->serial, MOS_WRITE,
+               port->number - port->serial->minor, UART_MCR, &lmcr);
+
+       return 0;
+}
+
 static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd,
                          unsigned int __user *value)
 {
@@ -1301,14 +1372,6 @@ static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd,
                        mcr &= ~UART_MCR_LOOP;
                break;
 
-       case TIOCMSET:
-               /* turn off the RTS and DTR and LOOPBACK
-                * and then only turn on what was asked to */
-               mcr &=  ~(UART_MCR_RTS | UART_MCR_DTR | UART_MCR_LOOP);
-               mcr |= ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0);
-               mcr |= ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0);
-               mcr |= ((arg & TIOCM_LOOP) ? UART_MCR_LOOP : 0);
-               break;
        }
 
        mos7720_port->shadowMCR = mcr;
@@ -1320,28 +1383,6 @@ static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd,
        return 0;
 }
 
-static int get_modem_info(struct moschip_port *mos7720_port,
-                         unsigned int __user *value)
-{
-       unsigned int result = 0;
-       unsigned int msr = mos7720_port->shadowMSR;
-       unsigned int mcr = mos7720_port->shadowMCR;
-
-       result = ((mcr & UART_MCR_DTR)  ? TIOCM_DTR: 0)   /* 0x002 */
-                 | ((mcr & UART_MCR_RTS)       ? TIOCM_RTS: 0)   /* 0x004 */
-                 | ((msr & UART_MSR_CTS)       ? TIOCM_CTS: 0)   /* 0x020 */
-                 | ((msr & UART_MSR_DCD)       ? TIOCM_CAR: 0)   /* 0x040 */
-                 | ((msr & UART_MSR_RI)        ? TIOCM_RI:  0)   /* 0x080 */
-                 | ((msr & UART_MSR_DSR)       ? TIOCM_DSR: 0);  /* 0x100 */
-
-
-       dbg("%s -- %x", __func__, result);
-
-       if (copy_to_user(value, &result, sizeof(int)))
-               return -EFAULT;
-       return 0;
-}
-
 static int get_serial_info(struct moschip_port *mos7720_port,
                           struct serial_struct __user *retinfo)
 {
@@ -1392,17 +1433,11 @@ static int mos7720_ioctl(struct tty_struct *tty, struct file *file,
        /* FIXME: These should be using the mode methods */
        case TIOCMBIS:
        case TIOCMBIC:
-       case TIOCMSET:
                dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET",
                                        __func__, port->number);
                return set_modem_info(mos7720_port, cmd,
                                      (unsigned int __user *)arg);
 
-       case TIOCMGET:
-               dbg("%s (%d) TIOCMGET", __func__,  port->number);
-               return get_modem_info(mos7720_port,
-                                     (unsigned int __user *)arg);
-
        case TIOCGSERIAL:
                dbg("%s (%d) TIOCGSERIAL", __func__,  port->number);
                return get_serial_info(mos7720_port,
@@ -1557,6 +1592,8 @@ static struct usb_serial_driver moschip7720_2port_driver = {
        .attach                 = mos7720_startup,
        .release                = mos7720_release,
        .ioctl                  = mos7720_ioctl,
+       .tiocmget               = mos7720_tiocmget,
+       .tiocmset               = mos7720_tiocmset,
        .set_termios            = mos7720_set_termios,
        .write                  = mos7720_write,
        .write_room             = mos7720_write_room,