mos7720.c revision 441b62c1edb986827154768d89bbac0ba779984f
10f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* 20f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * mos7720.c 30f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Controls the Moschip 7720 usb to dual port serial convertor 40f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * 50f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Copyright 2006 Moschip Semiconductor Tech. Ltd. 60f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * 70f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * This program is free software; you can redistribute it and/or modify 80f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * it under the terms of the GNU General Public License as published by 90f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * the Free Software Foundation, version 2 of the License. 100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * 110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Developed by: 1250d2dc7266573dfbdc84fc207494dd21315782efGreg Kroah-Hartman * Vijaya Kumar <vijaykumar.gn@gmail.com> 1350d2dc7266573dfbdc84fc207494dd21315782efGreg Kroah-Hartman * Ajay Kumar <naanuajay@yahoo.com> 1450d2dc7266573dfbdc84fc207494dd21315782efGreg Kroah-Hartman * Gurudeva <ngurudeva@yahoo.com> 150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * 160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Cleaned up from the original by: 170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Greg Kroah-Hartman <gregkh@suse.de> 180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * 190f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Originally based on drivers/usb/serial/io_edgeport.c which is: 200f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Copyright (C) 2000 Inside Out Networks, All rights reserved. 210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Copyright (C) 2001-2002 Greg Kroah-Hartman <greg@kroah.com> 220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman */ 230f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#include <linux/kernel.h> 240f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#include <linux/errno.h> 250f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#include <linux/init.h> 260f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#include <linux/slab.h> 270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#include <linux/tty.h> 280f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#include <linux/tty_driver.h> 290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#include <linux/tty_flip.h> 300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#include <linux/module.h> 310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#include <linux/spinlock.h> 320f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#include <linux/serial.h> 330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#include <linux/serial_reg.h> 340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#include <linux/usb.h> 350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#include <linux/usb/serial.h> 360f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#include <asm/uaccess.h> 370f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 380f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 390f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* 400f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Version Information 410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman */ 420f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define DRIVER_VERSION "1.0.0.4F" 430f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define DRIVER_AUTHOR "Aspire Communications pvt Ltd." 440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define DRIVER_DESC "Moschip USB Serial Driver" 450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 460f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* default urb timeout */ 470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define MOS_WDR_TIMEOUT (HZ * 5) 480f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define MOS_PORT1 0x0200 500f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define MOS_PORT2 0x0300 510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define MOS_VENREG 0x0000 520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define MOS_MAX_PORT 0x02 530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define MOS_WRITE 0x0E 540f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define MOS_READ 0x0D 550f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* Interrupt Rotinue Defines */ 570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define SERIAL_IIR_RLS 0x06 580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define SERIAL_IIR_RDA 0x04 590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define SERIAL_IIR_CTI 0x0c 600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define SERIAL_IIR_THR 0x02 610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define SERIAL_IIR_MS 0x00 620f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 630f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define NUM_URBS 16 /* URB Count */ 640f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define URB_TRANSFER_BUFFER_SIZE 32 /* URB Size */ 650f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 660f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* This structure holds all of the local port information */ 670f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstruct moschip_port 680f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 690f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u8 shadowLCR; /* last LCR value received */ 700f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u8 shadowMCR; /* last MCR value received */ 710f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u8 shadowMSR; /* last MSR value received */ 720f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman char open; 730f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct async_icount icount; 740f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_serial_port *port; /* loop back to the owner */ 750f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct urb *write_urb_pool[NUM_URBS]; 760f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman}; 770f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 780f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* This structure holds all of the individual serial device information */ 790f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstruct moschip_serial 800f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 810f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int interrupt_started; 820f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman}; 830f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 840f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic int debug; 850f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 860f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define USB_VENDOR_ID_MOSCHIP 0x9710 870f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define MOSCHIP_DEVICE_ID_7720 0x7720 880f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define MOSCHIP_DEVICE_ID_7715 0x7715 890f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 900f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic struct usb_device_id moschip_port_id_table [] = { 910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { USB_DEVICE(USB_VENDOR_ID_MOSCHIP,MOSCHIP_DEVICE_ID_7720) }, 920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { } /* terminating entry */ 930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman}; 940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-HartmanMODULE_DEVICE_TABLE(usb, moschip_port_id_table); 950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 970f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* 980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * mos7720_interrupt_callback 990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * this is the callback function for when we have received data on the 1000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * interrupt endpoint. 1010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman */ 1020f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic void mos7720_interrupt_callback(struct urb *urb) 1030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 1040f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int result; 1050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int length; 10681105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman int status = urb->status; 107325b70c233396f0cfe15012682a5080bf8040901Oliver Neukum __u8 *data; 1080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u8 sp1; 1090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u8 sp2; 1100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("%s"," : Entering\n"); 1120f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11381105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman switch (status) { 1140f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case 0: 1150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* success */ 1160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 1170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case -ECONNRESET: 1180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case -ENOENT: 1190f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case -ESHUTDOWN: 1200f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* this urb is terminated, clean up */ 121441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - urb shutting down with status: %d", __func__, 12281105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman status); 1230f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 1240f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman default: 125441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - nonzero urb status received: %d", __func__, 12681105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman status); 1270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman goto exit; 1280f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 1290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman length = urb->actual_length; 1310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = urb->transfer_buffer; 1320f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Moschip get 4 bytes 1340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Byte 1 IIR Port 1 (port.number is 0) 1350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Byte 2 IIR Port 2 (port.number is 1) 1360f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Byte 3 -------------- 1370f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Byte 4 FIFO status for both */ 138325b70c233396f0cfe15012682a5080bf8040901Oliver Neukum 139325b70c233396f0cfe15012682a5080bf8040901Oliver Neukum /* the above description is inverted 140325b70c233396f0cfe15012682a5080bf8040901Oliver Neukum * oneukum 2007-03-14 */ 141325b70c233396f0cfe15012682a5080bf8040901Oliver Neukum 142325b70c233396f0cfe15012682a5080bf8040901Oliver Neukum if (unlikely(length != 4)) { 1430f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Wrong data !!!"); 1440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 1450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 1460f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 147325b70c233396f0cfe15012682a5080bf8040901Oliver Neukum sp1 = data[3]; 148325b70c233396f0cfe15012682a5080bf8040901Oliver Neukum sp2 = data[2]; 1490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 150325b70c233396f0cfe15012682a5080bf8040901Oliver Neukum if ((sp1 | sp2) & 0x01) { 1510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* No Interrupt Pending in both the ports */ 1520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("No Interrupt !!!"); 1530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } else { 1540f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman switch (sp1 & 0x0f) { 1550f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case SERIAL_IIR_RLS: 1560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Serial Port 1: Receiver status error or address " 1570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman "bit detected in 9-bit mode\n"); 1580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 1590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case SERIAL_IIR_CTI: 1600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Serial Port 1: Receiver time out"); 1610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 1620f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case SERIAL_IIR_MS: 1630f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Serial Port 1: Modem status change"); 1640f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 1650f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 1660f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1670f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman switch (sp2 & 0x0f) { 1680f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case SERIAL_IIR_RLS: 1690f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Serial Port 2: Receiver status error or address " 1700f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman "bit detected in 9-bit mode"); 1710f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 1720f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case SERIAL_IIR_CTI: 1730f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Serial Port 2: Receiver time out"); 1740f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 1750f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case SERIAL_IIR_MS: 1760f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Serial Port 2: Modem status change"); 1770f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 1780f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 1790f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 1800f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1810f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanexit: 1820f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman result = usb_submit_urb(urb, GFP_ATOMIC); 1830f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (result) 1840f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dev_err(&urb->dev->dev, 1850f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman "%s - Error %d submitting control urb\n", 186441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison __func__, result); 1870f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 1880f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 1890f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1900f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* 1910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * mos7720_bulk_in_callback 1920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * this is the callback function for when we have received data on the 1930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * bulk in endpoint. 1940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman */ 1950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic void mos7720_bulk_in_callback(struct urb *urb) 1960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 19781105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman int retval; 1980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned char *data ; 1990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_serial_port *port; 2000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct moschip_port *mos7720_port; 2010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct tty_struct *tty; 20281105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman int status = urb->status; 2030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 20481105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman if (status) { 20581105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman dbg("nonzero read bulk status received: %d", status); 2060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 2070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 2080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 2090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port = urb->context; 2100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (!mos7720_port) { 2110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("%s","NULL mos7720_port pointer \n"); 2120f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return ; 2130f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 2140f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 2150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port = mos7720_port->port; 2160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 217441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("Entering...%s", __func__); 2180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 2190f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = urb->transfer_buffer; 2200f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 2210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tty = port->tty; 2220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (tty && urb->actual_length) { 2230f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tty_buffer_request_room(tty, urb->actual_length); 2240f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tty_insert_flip_string(tty, data, urb->actual_length); 2250f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tty_flip_buffer_push(tty); 2260f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 2270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 2280f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (!port->read_urb) { 2290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("URB KILLED !!!"); 2300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 2310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 2320f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 2330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (port->read_urb->status != -EINPROGRESS) { 2340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port->read_urb->dev = port->serial->dev; 2350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 23681105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman retval = usb_submit_urb(port->read_urb, GFP_ATOMIC); 23781105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman if (retval) 23881105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman dbg("usb_submit_urb(read bulk) failed, retval = %d", 23981105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman retval); 2400f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 2410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 2420f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 2430f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* 2440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * mos7720_bulk_out_data_callback 2450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * this is the callback function for when we have finished sending serial 2460f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * data on the bulk out endpoint. 2470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman */ 2480f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic void mos7720_bulk_out_data_callback(struct urb *urb) 2490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 2500f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct moschip_port *mos7720_port; 2510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct tty_struct *tty; 25281105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman int status = urb->status; 2530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 25481105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman if (status) { 25581105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman dbg("nonzero write bulk status received:%d", status); 2560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 2570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 2580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 2590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port = urb->context; 2600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (!mos7720_port) { 2610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("NULL mos7720_port pointer"); 2620f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return ; 2630f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 2640f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 2650f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Entering ........."); 2660f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 2670f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tty = mos7720_port->port->tty; 2680f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 269b963a8441cb95999c97bea379607071a869c65f0Jiri Slaby if (tty && mos7720_port->open) 270b963a8441cb95999c97bea379607071a869c65f0Jiri Slaby tty_wakeup(tty); 2710f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 2720f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 2730f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* 2740f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * send_mos_cmd 2750f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * this function will be used for sending command to device 2760f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman */ 2770f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic int send_mos_cmd(struct usb_serial *serial, __u8 request, __u16 value, 2780f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u16 index, void *data) 2790f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 2800f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int status; 2810f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned int pipe; 2820f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman u16 product = le16_to_cpu(serial->dev->descriptor.idProduct); 2830f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u8 requesttype; 2840f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u16 size = 0x0000; 2850f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 2860f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (value < MOS_MAX_PORT) { 2870f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (product == MOSCHIP_DEVICE_ID_7715) { 2880f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman value = value*0x100+0x100; 2890f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } else { 2900f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman value = value*0x100+0x200; 2910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 2920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } else { 2930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman value = 0x0000; 2940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if ((product == MOSCHIP_DEVICE_ID_7715) && 2950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman (index != 0x08)) { 2960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("serial->product== MOSCHIP_DEVICE_ID_7715"); 2970f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman //index = 0x01 ; 2980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 2990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 3000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 3010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (request == MOS_WRITE) { 3020f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman request = (__u8)MOS_WRITE; 3030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman requesttype = (__u8)0x40; 3040f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman value = value + (__u16)*((unsigned char *)data); 3050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = NULL; 3060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman pipe = usb_sndctrlpipe(serial->dev, 0); 3070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } else { 3080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman request = (__u8)MOS_READ; 3090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman requesttype = (__u8)0xC0; 3100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman size = 0x01; 3110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman pipe = usb_rcvctrlpipe(serial->dev,0); 3120f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 3130f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 3140f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman status = usb_control_msg(serial->dev, pipe, request, requesttype, 3150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman value, index, data, size, MOS_WDR_TIMEOUT); 3160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 3170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (status < 0) 3180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Command Write failed Value %x index %x\n",value,index); 3190f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 3200f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return status; 3210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 3220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 3230f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic int mos7720_open(struct usb_serial_port *port, struct file * filp) 3240f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 3250f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_serial *serial; 3260f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_serial_port *port0; 3270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct urb *urb; 3280f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct moschip_serial *mos7720_serial; 3290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct moschip_port *mos7720_port; 3300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int response; 3310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int port_number; 3320f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman char data; 333fe4b65ec9127a336eeaa503f878062d9e6f44591Oliver Neukum int allocated_urbs = 0; 3340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int j; 3350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 3360f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman serial = port->serial; 3370f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 3380f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port = usb_get_serial_port_data(port); 3390f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) 3400f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -ENODEV; 3410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 3420f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port0 = serial->port[0]; 3430f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 3440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_serial = usb_get_serial_data(serial); 3450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 3460f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_serial == NULL || port0 == NULL) 3470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -ENODEV; 3480f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 3490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_clear_halt(serial->dev, port->write_urb->pipe); 3500f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_clear_halt(serial->dev, port->read_urb->pipe); 3510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 3520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Initialising the write urb pool */ 3530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman for (j = 0; j < NUM_URBS; ++j) { 354c2cf3f6ec58cf1d9e2a92cd74506dcf2265b31a1Oliver Neukum urb = usb_alloc_urb(0,GFP_KERNEL); 3550f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->write_urb_pool[j] = urb; 3560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 3570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (urb == NULL) { 3580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman err("No more urbs???"); 3590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman continue; 3600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 3610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 3620f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, 3630f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman GFP_KERNEL); 3640f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (!urb->transfer_buffer) { 365441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison err("%s-out of memory for urb buffers.", __func__); 366fe4b65ec9127a336eeaa503f878062d9e6f44591Oliver Neukum usb_free_urb(mos7720_port->write_urb_pool[j]); 367fe4b65ec9127a336eeaa503f878062d9e6f44591Oliver Neukum mos7720_port->write_urb_pool[j] = NULL; 3680f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman continue; 3690f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 370fe4b65ec9127a336eeaa503f878062d9e6f44591Oliver Neukum allocated_urbs++; 3710f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 3720f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 373fe4b65ec9127a336eeaa503f878062d9e6f44591Oliver Neukum if (!allocated_urbs) 374fe4b65ec9127a336eeaa503f878062d9e6f44591Oliver Neukum return -ENOMEM; 375fe4b65ec9127a336eeaa503f878062d9e6f44591Oliver Neukum 3760f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Initialize MCS7720 -- Write Init values to corresponding Registers 3770f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * 3780f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Register Index 3790f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * 1 : IER 3800f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * 2 : FCR 3810f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * 3 : LCR 3820f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * 4 : MCR 3830f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * 3840f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * 0x08 : SP1/2 Control Reg 3850f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman */ 3860f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port_number = port->number - port->serial->minor; 3870f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(port->serial, MOS_READ, port_number, UART_LSR, &data); 3880f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("SS::%p LSR:%x\n",mos7720_port, data); 3890f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 3900f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Check:Sending Command .........."); 3910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 3920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x02; 3930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x01, &data); 3940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x02; 3950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x02, &data); 3960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 3970f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x00; 3980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); 3990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x00; 4000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x02, &data); 4010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4020f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0xCF; 4030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x02, &data); 4040f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x03; 4050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowLCR = data; 4060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data); 4070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x0b; 4080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowMCR = data; 4090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); 4100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x0b; 4110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); 4120f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4130f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x00; 4140f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data); 4150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x00; 4160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data); 4170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* data = 0x00; 4190f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, port_number + 1, &data); 4200f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x03; 4210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1, &data); 4220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x00; 4230f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(port->serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1, &data); 4240f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman*/ 4250f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x00; 4260f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data); 4270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4280f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = data | (port->number - port->serial->minor + 1); 4290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data); 4300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x83; 4320f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowLCR = data; 4330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data); 4340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x0c; 4350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x00, &data); 4360f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x00; 4370f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); 4380f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x03; 4390f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowLCR = data; 4400f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data); 4410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x0c; 4420f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); 4430f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x0c; 4440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); 4450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4460f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman//Matrix 4470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4480f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* force low_latency on so that our tty_push actually forces * 4490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * the data through,otherwise it is scheduled, and with * 4500f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * high data rates (like with OHCI) data can get lost. */ 4510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (port->tty) 4530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port->tty->low_latency = 1; 4540f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4550f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* see if we've set up our endpoint info yet * 4560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * (can't set it up in mos7720_startup as the * 4570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * structures were not set up at that time.) */ 4580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (!mos7720_serial->interrupt_started) { 4590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Interrupt buffer NULL !!!"); 4600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* not set up yet, so do it now */ 4620f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_serial->interrupt_started = 1; 4630f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4640f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("To Submit URB !!!"); 4650f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4660f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* set up our interrupt urb */ 4670f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_fill_int_urb(port0->interrupt_in_urb, serial->dev, 4680f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_rcvintpipe(serial->dev, 4690f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port->interrupt_in_endpointAddress), 4700f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port0->interrupt_in_buffer, 4710f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port0->interrupt_in_urb->transfer_buffer_length, 4720f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_interrupt_callback, mos7720_port, 4730f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port0->interrupt_in_urb->interval); 4740f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4750f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* start interrupt read for this mos7720 this interrupt * 4760f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * will continue as long as the mos7720 is connected */ 4770f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Submit URB over !!!"); 4780f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman response = usb_submit_urb(port0->interrupt_in_urb, GFP_KERNEL); 4790f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (response) 4800f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dev_err(&port->dev, 481898eb71cb17644964c5895fb190e79e3d0c49679Joe Perches "%s - Error %d submitting control urb\n", 482441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison __func__, response); 4830f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 4840f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4850f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* set up our bulk in urb */ 4860f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_fill_bulk_urb(port->read_urb, serial->dev, 4870f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_rcvbulkpipe(serial->dev, 4880f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port->bulk_in_endpointAddress), 4890f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port->bulk_in_buffer, 4900f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port->read_urb->transfer_buffer_length, 4910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_bulk_in_callback, mos7720_port); 4920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman response = usb_submit_urb(port->read_urb, GFP_KERNEL); 4930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (response) 4940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dev_err(&port->dev, 495441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison "%s - Error %d submitting read urb\n", __func__, response); 4960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4970f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* initialize our icount structure */ 4980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman memset(&(mos7720_port->icount), 0x00, sizeof(mos7720_port->icount)); 4990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 5000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* initialize our port settings */ 5010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowMCR = UART_MCR_OUT2; /* Must set to enable ints! */ 5020f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 5030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* send a open port command */ 5040f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->open = 1; 5050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 5060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return 0; 5070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 5080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 5090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* 5100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * mos7720_chars_in_buffer 5110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * this function is called by the tty driver when it wants to know how many 5120f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * bytes of data we currently have outstanding in the port (data that has 5130f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * been written, but hasn't made it out the port yet) 5140f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * If successful, we return the number of bytes left to be written in the 5150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * system, 5160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Otherwise we return a negative error number. 5170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman */ 5180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic int mos7720_chars_in_buffer(struct usb_serial_port *port) 5190f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 5200f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int i; 5210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int chars = 0; 5220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct moschip_port *mos7720_port; 5230f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 524441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s:entering ...........", __func__); 5250f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 5260f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port = usb_get_serial_port_data(port); 5270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) { 528441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s:leaving ...........", __func__); 5290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -ENODEV; 5300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 5310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 5320f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman for (i = 0; i < NUM_URBS; ++i) { 533fe4b65ec9127a336eeaa503f878062d9e6f44591Oliver Neukum if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status == -EINPROGRESS) 5340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman chars += URB_TRANSFER_BUFFER_SIZE; 5350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 536441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - returns %d", __func__, chars); 5370f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return chars; 5380f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 5390f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 5400f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic void mos7720_close(struct usb_serial_port *port, struct file *filp) 5410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 5420f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_serial *serial; 5430f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct moschip_port *mos7720_port; 5440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman char data; 5450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int j; 5460f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 5470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("mos7720_close:entering..."); 5480f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 5490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman serial = port->serial; 5500f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 5510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port = usb_get_serial_port_data(port); 5520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) 5530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 5540f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 5550f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman for (j = 0; j < NUM_URBS; ++j) 5560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_kill_urb(mos7720_port->write_urb_pool[j]); 5570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 5580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Freeing Write URBs */ 5590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman for (j = 0; j < NUM_URBS; ++j) { 5600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port->write_urb_pool[j]) { 5610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman kfree(mos7720_port->write_urb_pool[j]->transfer_buffer); 5620f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_free_urb(mos7720_port->write_urb_pool[j]); 5630f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 5640f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 5650f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 5660f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* While closing port, shutdown all bulk read, write * 567a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum * and interrupt read if they exists, otherwise nop */ 568a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum dbg("Shutdown bulk write"); 569a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum usb_kill_urb(port->write_urb); 570a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum dbg("Shutdown bulk read"); 571a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum usb_kill_urb(port->read_urb); 572a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum 573a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum mutex_lock(&serial->disc_mutex); 574a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum /* these commands must not be issued if the device has 575a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum * been disconnected */ 576a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum if (!serial->disconnected) { 577a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum data = 0x00; 578a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor, 579a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum 0x04, &data); 580a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum 581a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum data = 0x00; 582a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor, 583a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum 0x01, &data); 5840f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 585a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum mutex_unlock(&serial->disc_mutex); 5860f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->open = 0; 5870f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 588441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("Leaving %s", __func__); 5890f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 5900f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 5910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic void mos7720_break(struct usb_serial_port *port, int break_state) 5920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 5930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned char data; 5940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_serial *serial; 5950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct moschip_port *mos7720_port; 5960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 597441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("Entering %s", __func__); 5980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 5990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman serial = port->serial; 6000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 6010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port = usb_get_serial_port_data(port); 6020f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) 6030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 6040f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 6050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (break_state == -1) 6060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = mos7720_port->shadowLCR | UART_LCR_SBC; 6070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman else 6080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = mos7720_port->shadowLCR & ~UART_LCR_SBC; 6090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 6100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowLCR = data; 6110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor, 6120f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 0x03, &data); 6130f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 6140f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 6150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 6160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 6170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* 6180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * mos7720_write_room 6190f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * this function is called by the tty driver when it wants to know how many 6200f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * bytes of data we can accept for a specific port. 6210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * If successful, we return the amount of room that we have for this port 6220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Otherwise we return a negative error number. 6230f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman */ 6240f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic int mos7720_write_room(struct usb_serial_port *port) 6250f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 6260f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct moschip_port *mos7720_port; 6270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int room = 0; 6280f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int i; 6290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 630441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s:entering ...........", __func__); 6310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 6320f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port = usb_get_serial_port_data(port); 6330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) { 634441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s:leaving ...........", __func__); 6350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -ENODEV; 6360f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 6370f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 6380f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman for (i = 0; i < NUM_URBS; ++i) { 639fe4b65ec9127a336eeaa503f878062d9e6f44591Oliver Neukum if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status != -EINPROGRESS) 6400f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman room += URB_TRANSFER_BUFFER_SIZE; 6410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 6420f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 643441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - returns %d", __func__, room); 6440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return room; 6450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 6460f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 6470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic int mos7720_write(struct usb_serial_port *port, 6480f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman const unsigned char *data, int count) 6490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 6500f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int status; 6510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int i; 6520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int bytes_sent = 0; 6530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int transfer_size; 6540f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 6550f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct moschip_port *mos7720_port; 6560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_serial *serial; 6570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct urb *urb; 6580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman const unsigned char *current_position = data; 6590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 660441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s:entering ...........", __func__); 6610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 6620f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman serial = port->serial; 6630f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 6640f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port = usb_get_serial_port_data(port); 6650f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) { 6660f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("mos7720_port is NULL"); 6670f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -ENODEV; 6680f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 6690f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 6700f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* try to find a free urb in the list */ 6710f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman urb = NULL; 6720f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 6730f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman for (i = 0; i < NUM_URBS; ++i) { 674fe4b65ec9127a336eeaa503f878062d9e6f44591Oliver Neukum if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status != -EINPROGRESS) { 6750f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman urb = mos7720_port->write_urb_pool[i]; 6760f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("URB:%d",i); 6770f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 6780f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 6790f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 6800f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 6810f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (urb == NULL) { 682441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - no more free urbs", __func__); 6830f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman goto exit; 6840f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 6850f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 6860f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (urb->transfer_buffer == NULL) { 6870f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, 6880f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman GFP_KERNEL); 6890f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (urb->transfer_buffer == NULL) { 690441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison err("%s no more kernel memory...", __func__); 6910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman goto exit; 6920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 6930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 6940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman transfer_size = min (count, URB_TRANSFER_BUFFER_SIZE); 6950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 6960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman memcpy(urb->transfer_buffer, current_position, transfer_size); 697441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison usb_serial_debug_data(debug, &port->dev, __func__, transfer_size, 6980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman urb->transfer_buffer); 6990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* fill urb with data and submit */ 7010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_fill_bulk_urb(urb, serial->dev, 7020f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_sndbulkpipe(serial->dev, 7030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port->bulk_out_endpointAddress), 7040f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman urb->transfer_buffer, transfer_size, 7050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_bulk_out_data_callback, mos7720_port); 7060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* send it down the pipe */ 7080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman status = usb_submit_urb(urb,GFP_ATOMIC); 7090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (status) { 7100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman err("%s - usb_submit_urb(write bulk) failed with status = %d", 711441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison __func__, status); 7120f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman bytes_sent = status; 7130f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman goto exit; 7140f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 7150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman bytes_sent = transfer_size; 7160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanexit: 7180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return bytes_sent; 7190f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 7200f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic void mos7720_throttle(struct usb_serial_port *port) 7220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 7230f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct moschip_port *mos7720_port; 7240f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct tty_struct *tty; 7250f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int status; 7260f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 727441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s- port %d\n", __func__, port->number); 7280f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port = usb_get_serial_port_data(port); 7300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) 7320f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 7330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (!mos7720_port->open) { 7350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("port not opened"); 7360f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 7370f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 7380f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 739441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s: Entering ..........", __func__); 7400f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tty = port->tty; 7420f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (!tty) { 743441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - no tty available", __func__); 7440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 7450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 7460f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* if we are implementing XON/XOFF, send the stop character */ 7480f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (I_IXOFF(tty)) { 7490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned char stop_char = STOP_CHAR(tty); 7500f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman status = mos7720_write(port, &stop_char, 1); 7510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (status <= 0) 7520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 7530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 7540f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7550f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* if we are implementing RTS/CTS, toggle that line */ 7560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (tty->termios->c_cflag & CRTSCTS) { 7570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowMCR &= ~UART_MCR_RTS; 7580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman status = send_mos_cmd(port->serial, MOS_WRITE, 7590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port->number - port->serial->minor, 7600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman UART_MCR, &mos7720_port->shadowMCR); 7610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (status != 0) 7620f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 7630f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 7640f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 7650f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7660f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic void mos7720_unthrottle(struct usb_serial_port *port) 7670f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 7680f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct tty_struct *tty; 7690f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int status; 7700f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct moschip_port *mos7720_port = usb_get_serial_port_data(port); 7710f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7720f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) 7730f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 7740f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7750f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (!mos7720_port->open) { 776441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port not opened", __func__); 7770f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 7780f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 7790f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 780441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s: Entering ..........", __func__); 7810f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7820f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tty = port->tty; 7830f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (!tty) { 784441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - no tty available", __func__); 7850f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 7860f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 7870f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7880f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* if we are implementing XON/XOFF, send the start character */ 7890f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (I_IXOFF(tty)) { 7900f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned char start_char = START_CHAR(tty); 7910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman status = mos7720_write(port, &start_char, 1); 7920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (status <= 0) 7930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 7940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 7950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* if we are implementing RTS/CTS, toggle that line */ 7970f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (tty->termios->c_cflag & CRTSCTS) { 7980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowMCR |= UART_MCR_RTS; 7990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman status = send_mos_cmd(port->serial, MOS_WRITE, 8000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port->number - port->serial->minor, 8010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman UART_MCR, &mos7720_port->shadowMCR); 8020f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (status != 0) 8030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 8040f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 8050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 8060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic int set_higher_rates(struct moschip_port *mos7720_port, 8080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned int baud) 8090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 8100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned char data; 8110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_serial_port *port; 8120f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_serial *serial; 8130f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int port_number; 8140f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) 8160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -EINVAL; 8170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port = mos7720_port->port; 8190f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman serial = port->serial; 8200f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /*********************************************** 8220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Init Sequence for higher rates 8230f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman ***********************************************/ 8240f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Sending Setting Commands .........."); 8250f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port_number = port->number - port->serial->minor; 8260f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x000; 8280f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); 8290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x000; 8300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x02, &data); 8310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x0CF; 8320f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port->number, 0x02, &data); 8330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x00b; 8340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowMCR = data; 8350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); 8360f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x00b; 8370f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); 8380f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8390f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x000; 8400f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data); 8410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x000; 8420f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data); 8430f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /*********************************************** 8460f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Set for higher rates * 8470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman ***********************************************/ 8480f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = baud * 0x10; 8500f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1,&data); 8510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x003; 8530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data); 8540f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x003; 8550f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data); 8560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x02b; 8580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowMCR = data; 8590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); 8600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x02b; 8610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); 8620f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8630f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /*********************************************** 8640f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Set DLL/DLM 8650f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman ***********************************************/ 8660f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8670f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = mos7720_port->shadowLCR | UART_LCR_DLAB; 8680f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowLCR = data; 8690f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data); 8700f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8710f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x001; /* DLL */ 8720f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x00, &data); 8730f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x000; /* DLM */ 8740f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); 8750f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8760f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = mos7720_port->shadowLCR & ~UART_LCR_DLAB; 8770f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowLCR = data; 8780f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data); 8790f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8800f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return 0; 8810f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 8820f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8830f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* baud rate information */ 8840f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstruct divisor_table_entry 8850f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 8860f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u32 baudrate; 8870f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u16 divisor; 8880f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman}; 8890f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8900f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* Define table of divisors for moschip 7720 hardware * 8910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * These assume a 3.6864MHz crystal, the standard /16, and * 8920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * MCR.7 = 0. */ 8930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic struct divisor_table_entry divisor_table[] = { 8940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 50, 2304}, 8950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 110, 1047}, /* 2094.545455 => 230450 => .0217 % over */ 8960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 134, 857}, /* 1713.011152 => 230398.5 => .00065% under */ 8970f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 150, 768}, 8980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 300, 384}, 8990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 600, 192}, 9000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 1200, 96}, 9010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 1800, 64}, 9020f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 2400, 48}, 9030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 4800, 24}, 9040f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 7200, 16}, 9050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 9600, 12}, 9060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 19200, 6}, 9070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 38400, 3}, 9080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 57600, 2}, 9090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 115200, 1}, 9100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman}; 9110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9120f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/***************************************************************************** 9130f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * calc_baud_rate_divisor 9140f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * this function calculates the proper baud rate divisor for the specified 9150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * baud rate. 9160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman *****************************************************************************/ 9170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic int calc_baud_rate_divisor(int baudrate, int *divisor) 9180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 9190f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int i; 9200f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u16 custom; 9210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u16 round1; 9220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u16 round; 9230f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9240f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 925441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - %d", __func__, baudrate); 9260f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman for (i = 0; i < ARRAY_SIZE(divisor_table); i++) { 9280f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (divisor_table[i].baudrate == baudrate) { 9290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman *divisor = divisor_table[i].divisor; 9300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return 0; 9310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 9320f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 9330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* After trying for all the standard baud rates * 9350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Try calculating the divisor for this baud rate */ 9360f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (baudrate > 75 && baudrate < 230400) { 9370f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* get the divisor */ 9380f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman custom = (__u16)(230400L / baudrate); 9390f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9400f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Check for round off */ 9410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman round1 = (__u16)(2304000L / baudrate); 9420f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman round = (__u16)(round1 - (custom * 10)); 9430f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (round > 4) 9440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman custom++; 9450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman *divisor = custom; 9460f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Baud %d = %d",baudrate, custom); 9480f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return 0; 9490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 9500f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Baud calculation Failed..."); 9520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -EINVAL; 9530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 9540f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9550f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* 9560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * send_cmd_write_baud_rate 9570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * this function sends the proper command to change the baud rate of the 9580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * specified port. 9590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman */ 9600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic int send_cmd_write_baud_rate(struct moschip_port *mos7720_port, 9610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int baudrate) 9620f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 9630f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_serial_port *port; 9640f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_serial *serial; 9650f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int divisor; 9660f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int status; 9670f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned char data; 9680f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned char number; 9690f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9700f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) 9710f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -1; 9720f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9730f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port = mos7720_port->port; 9740f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman serial = port->serial; 9750f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 976441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s: Entering ..........", __func__); 9770f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9780f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman number = port->number - port->serial->minor; 979441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port = %d, baud = %d", __func__, port->number, baudrate); 9800f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9810f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Calculate the Divisor */ 9820f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman status = calc_baud_rate_divisor(baudrate, &divisor); 9830f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (status) { 984441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison err("%s - bad baud rate", __func__); 9850f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return status; 9860f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 9870f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9880f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Enable access to divisor latch */ 9890f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = mos7720_port->shadowLCR | UART_LCR_DLAB; 9900f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowLCR = data; 9910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, number, UART_LCR, &data); 9920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Write the divisor */ 9940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = ((unsigned char)(divisor & 0xff)); 9950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, number, 0x00, &data); 9960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9970f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = ((unsigned char)((divisor & 0xff00) >> 8)); 9980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, number, 0x01, &data); 9990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Disable access to divisor latch */ 10010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = mos7720_port->shadowLCR & ~UART_LCR_DLAB; 10020f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowLCR = data; 10030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, number, 0x03, &data); 10040f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return status; 10060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 10070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* 10090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * change_port_settings 10100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * This routine is called to set the UART on the device to match 10110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * the specified new settings. 10120f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman */ 10130f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic void change_port_settings(struct moschip_port *mos7720_port, 1014606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox struct ktermios *old_termios) 10150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 10160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_serial_port *port; 10170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_serial *serial; 10180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct tty_struct *tty; 10190f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int baud; 10200f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned cflag; 10210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned iflag; 10220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u8 mask = 0xff; 10230f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u8 lData; 10240f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u8 lParity; 10250f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u8 lStop; 10260f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int status; 10270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int port_number; 10280f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman char data; 10290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) 10310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return ; 10320f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port = mos7720_port->port; 10340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman serial = port->serial; 10350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port_number = port->number - port->serial->minor; 10360f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1037441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port %d", __func__, port->number); 10380f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10390f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (!mos7720_port->open) { 1040441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port not opened", __func__); 10410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 10420f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 10430f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tty = mos7720_port->port->tty; 10450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1046441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s: Entering ..........", __func__); 10470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10480f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman lData = UART_LCR_WLEN8; 10490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman lStop = 0x00; /* 1 stop bit */ 10500f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman lParity = 0x00; /* No parity */ 10510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman cflag = tty->termios->c_cflag; 10530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman iflag = tty->termios->c_iflag; 10540f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10550f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Change the number of bits */ 10560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman switch (cflag & CSIZE) { 10570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case CS5: 10580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman lData = UART_LCR_WLEN5; 10590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mask = 0x1f; 10600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 10610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10620f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case CS6: 10630f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman lData = UART_LCR_WLEN6; 10640f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mask = 0x3f; 10650f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 10660f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10670f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case CS7: 10680f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman lData = UART_LCR_WLEN7; 10690f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mask = 0x7f; 10700f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 10710f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman default: 10720f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case CS8: 10730f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman lData = UART_LCR_WLEN8; 10740f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 10750f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 10760f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10770f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Change the Parity bit */ 10780f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (cflag & PARENB) { 10790f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (cflag & PARODD) { 10800f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman lParity = UART_LCR_PARITY; 1081441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - parity = odd", __func__); 10820f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } else { 10830f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman lParity = (UART_LCR_EPAR | UART_LCR_PARITY); 1084441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - parity = even", __func__); 10850f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 10860f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10870f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } else { 1088441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - parity = none", __func__); 10890f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 10900f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (cflag & CMSPAR) 10920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman lParity = lParity | 0x20; 10930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Change the Stop bit */ 10950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (cflag & CSTOPB) { 10960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman lStop = UART_LCR_STOP; 1097441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - stop bits = 2", __func__); 10980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } else { 10990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman lStop = 0x00; 1100441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - stop bits = 1", __func__); 11010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 11020f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define LCR_BITS_MASK 0x03 /* Mask for bits/char field */ 11040f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define LCR_STOP_MASK 0x04 /* Mask for stop bits field */ 11050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define LCR_PAR_MASK 0x38 /* Mask for parity field */ 11060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Update the LCR with the correct value */ 11080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowLCR &= ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK); 11090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowLCR |= (lData | lParity | lStop); 11100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11120f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Disable Interrupts */ 11130f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x00; 11140f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial,MOS_WRITE,port->number - port->serial->minor, UART_IER, &data); 11150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x00; 11170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data); 11180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11190f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0xcf; 11200f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data); 11210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Send the updated LCR value to the mos7720 */ 11230f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = mos7720_port->shadowLCR; 11240f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, UART_LCR, &data); 11250f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11260f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x00b; 11270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowMCR = data; 11280f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); 11290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x00b; 11300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); 11310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11320f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* set up the MCR register and send it to the mos7720 */ 11330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowMCR = UART_MCR_OUT2; 11340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (cflag & CBAUD) 11350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowMCR |= (UART_MCR_DTR | UART_MCR_RTS); 11360f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11370f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (cflag & CRTSCTS) { 11380f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowMCR |= (UART_MCR_XONANY); 11390f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11400f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* To set hardware flow control to the specified * 11410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * serial port, in SP1/2_CONTROL_REG */ 11420f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (port->number) { 11430f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x001; 11440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 11450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 0x08, &data); 11460f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } else { 11470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x002; 11480f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 11490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 0x08, &data); 11500f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 11510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } else { 11520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowMCR &= ~(UART_MCR_XONANY); 11530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 11540f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11550f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = mos7720_port->shadowMCR; 11560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, UART_MCR, &data); 11570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Determine divisor based on baud rate */ 11590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman baud = tty_get_baud_rate(tty); 11600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (!baud) { 11610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* pick a default, any default... */ 11620f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Picked default baud..."); 11630f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman baud = 9600; 11640f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 11650f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11660f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (baud >= 230400) { 11670f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman set_higher_rates(mos7720_port, baud); 11680f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Enable Interrupts */ 11690f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x0c; 11700f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, UART_IER, &data); 11710f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 11720f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 11730f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1174441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - baud rate = %d", __func__, baud); 11750f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman status = send_cmd_write_baud_rate(mos7720_port, baud); 117665d063ab21feea8cf65d64fba50a5c4fa7bfd6beAlan Cox /* FIXME: needs to write actual resulting baud back not just 117765d063ab21feea8cf65d64fba50a5c4fa7bfd6beAlan Cox blindly do so */ 117865d063ab21feea8cf65d64fba50a5c4fa7bfd6beAlan Cox if (cflag & CBAUD) 117965d063ab21feea8cf65d64fba50a5c4fa7bfd6beAlan Cox tty_encode_baud_rate(tty, baud, baud); 11800f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Enable Interrupts */ 11810f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x0c; 11820f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, UART_IER, &data); 11830f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11840f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (port->read_urb->status != -EINPROGRESS) { 11850f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port->read_urb->dev = serial->dev; 11860f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11870f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman status = usb_submit_urb(port->read_urb, GFP_ATOMIC); 11880f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (status) 11890f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("usb_submit_urb(read bulk) failed, status = %d", 11900f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman status); 11910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 11920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 11930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 11940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* 11960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * mos7720_set_termios 11970f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * this function is called by the tty driver when it wants to change the 11980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * termios structure. 11990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman */ 12000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic void mos7720_set_termios(struct usb_serial_port *port, 1201606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox struct ktermios *old_termios) 12020f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 12030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int status; 12040f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned int cflag; 12050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_serial *serial; 12060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct moschip_port *mos7720_port; 12070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct tty_struct *tty; 12080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 12090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman serial = port->serial; 12100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 12110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port = usb_get_serial_port_data(port); 12120f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 12130f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) 12140f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 12150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 12160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tty = port->tty; 12170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 12180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 12190f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (!mos7720_port->open) { 1220441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port not opened", __func__); 12210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 12220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 12230f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 12240f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("%s\n","setting termios - ASPIRE"); 12250f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 12260f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman cflag = tty->termios->c_cflag; 12270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1228441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - cflag %08x iflag %08x", __func__, 12290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tty->termios->c_cflag, 12300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman RELEVANT_IFLAG(tty->termios->c_iflag)); 12310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1232441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - old cflag %08x old iflag %08x", __func__, 123365d063ab21feea8cf65d64fba50a5c4fa7bfd6beAlan Cox old_termios->c_cflag, 123465d063ab21feea8cf65d64fba50a5c4fa7bfd6beAlan Cox RELEVANT_IFLAG(old_termios->c_iflag)); 12350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1236441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port %d", __func__, port->number); 12370f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 12380f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* change the port settings to the new ones specified */ 12390f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman change_port_settings(mos7720_port, old_termios); 12400f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 12410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if(!port->read_urb) { 12420f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("%s","URB KILLED !!!!!\n"); 12430f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 12440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 12450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 12460f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if(port->read_urb->status != -EINPROGRESS) { 12470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port->read_urb->dev = serial->dev; 12480f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman status = usb_submit_urb(port->read_urb, GFP_ATOMIC); 12490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (status) 12500f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("usb_submit_urb(read bulk) failed, status = %d", 12510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman status); 12520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 12530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 12540f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 12550f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 12560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* 12570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * get_lsr_info - get line status register info 12580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * 12590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Purpose: Let user call ioctl() to get info when the UART physically 12600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * is emptied. On bus types like RS485, the transmitter must 12610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * release the bus after transmitting. This must be done when 12620f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * the transmit shift register is empty, not be done when the 12630f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * transmit holding register is empty. This functionality 12640f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * allows an RS485 driver to be written in user space. 12650f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman */ 12660f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic int get_lsr_info(struct moschip_port *mos7720_port, 12670f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned int __user *value) 12680f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 12690f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int count; 12700f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned int result = 0; 12710f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 12720f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman count = mos7720_chars_in_buffer(mos7720_port->port); 12730f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (count == 0) { 1274441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s -- Empty", __func__); 12750f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman result = TIOCSER_TEMT; 12760f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 12770f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 12780f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (copy_to_user(value, &result, sizeof(int))) 12790f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -EFAULT; 12800f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return 0; 12810f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 12820f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 12830f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* 12840f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * get_number_bytes_avail - get number of bytes available 12850f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * 12860f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Purpose: Let user call ioctl to get the count of number of bytes available. 12870f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman */ 12880f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic int get_number_bytes_avail(struct moschip_port *mos7720_port, 12890f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned int __user *value) 12900f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 12910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned int result = 0; 12920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct tty_struct *tty = mos7720_port->port->tty; 12930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 12940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (!tty) 12950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -ENOIOCTLCMD; 12960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 12970f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman result = tty->read_cnt; 12980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1299441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s(%d) = %d", __func__, mos7720_port->port->number, result); 13000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (copy_to_user(value, &result, sizeof(int))) 13010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -EFAULT; 13020f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -ENOIOCTLCMD; 13040f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 13050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd, 13070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned int __user *value) 13080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 13090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned int mcr ; 13100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned int arg; 13110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned char data; 13120f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13130f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_serial_port *port; 13140f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) 13160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -1; 13170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port = (struct usb_serial_port*)mos7720_port->port; 13190f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mcr = mos7720_port->shadowMCR; 13200f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (copy_from_user(&arg, value, sizeof(int))) 13220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -EFAULT; 13230f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13240f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman switch (cmd) { 13250f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case TIOCMBIS: 13260f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (arg & TIOCM_RTS) 13270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mcr |= UART_MCR_RTS; 13280f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (arg & TIOCM_DTR) 13290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mcr |= UART_MCR_RTS; 13300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (arg & TIOCM_LOOP) 13310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mcr |= UART_MCR_LOOP; 13320f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 13330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case TIOCMBIC: 13350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (arg & TIOCM_RTS) 13360f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mcr &= ~UART_MCR_RTS; 13370f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (arg & TIOCM_DTR) 13380f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mcr &= ~UART_MCR_RTS; 13390f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (arg & TIOCM_LOOP) 13400f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mcr &= ~UART_MCR_LOOP; 13410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 13420f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13430f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case TIOCMSET: 13440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* turn off the RTS and DTR and LOOPBACK 13450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * and then only turn on what was asked to */ 13460f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mcr &= ~(UART_MCR_RTS | UART_MCR_DTR | UART_MCR_LOOP); 13470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mcr |= ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0); 13480f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mcr |= ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0); 13490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mcr |= ((arg & TIOCM_LOOP) ? UART_MCR_LOOP : 0); 13500f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 13510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 13520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowMCR = mcr; 13540f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13550f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = mos7720_port->shadowMCR; 13560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(port->serial, MOS_WRITE, 13570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port->number - port->serial->minor, UART_MCR, &data); 13580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return 0; 13600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 13610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13620f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic int get_modem_info(struct moschip_port *mos7720_port, 13630f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned int __user *value) 13640f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 13650f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned int result = 0; 13660f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned int msr = mos7720_port->shadowMSR; 13670f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned int mcr = mos7720_port->shadowMCR; 13680f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13690f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman result = ((mcr & UART_MCR_DTR) ? TIOCM_DTR: 0) /* 0x002 */ 13700f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman | ((mcr & UART_MCR_RTS) ? TIOCM_RTS: 0) /* 0x004 */ 13710f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman | ((msr & UART_MSR_CTS) ? TIOCM_CTS: 0) /* 0x020 */ 13720f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman | ((msr & UART_MSR_DCD) ? TIOCM_CAR: 0) /* 0x040 */ 13730f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman | ((msr & UART_MSR_RI) ? TIOCM_RI: 0) /* 0x080 */ 13740f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman | ((msr & UART_MSR_DSR) ? TIOCM_DSR: 0); /* 0x100 */ 13750f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13760f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1377441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s -- %x", __func__, result); 13780f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13790f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (copy_to_user(value, &result, sizeof(int))) 13800f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -EFAULT; 13810f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return 0; 13820f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 13830f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13840f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic int get_serial_info(struct moschip_port *mos7720_port, 13850f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct serial_struct __user *retinfo) 13860f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 13870f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct serial_struct tmp; 13880f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13890f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (!retinfo) 13900f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -EFAULT; 13910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman memset(&tmp, 0, sizeof(tmp)); 13930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tmp.type = PORT_16550A; 13950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tmp.line = mos7720_port->port->serial->minor; 13960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tmp.port = mos7720_port->port->number; 13970f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tmp.irq = 0; 13980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; 13990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE; 14000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tmp.baud_base = 9600; 14010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tmp.close_delay = 5*HZ; 14020f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tmp.closing_wait = 30*HZ; 14030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 14040f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) 14050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -EFAULT; 14060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return 0; 14070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 14080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 14090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic int mos7720_ioctl(struct usb_serial_port *port, struct file *file, 14100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned int cmd, unsigned long arg) 14110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 14120f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct moschip_port *mos7720_port; 14130f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct async_icount cnow; 14140f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct async_icount cprev; 14150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct serial_icounter_struct icount; 14160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 14170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port = usb_get_serial_port_data(port); 14180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) 14190f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -ENODEV; 14200f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1421441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd); 14220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 14230f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman switch (cmd) { 14240f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case TIOCINQ: 14250f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* return number of bytes available */ 1426441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s (%d) TIOCINQ", __func__, port->number); 14270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return get_number_bytes_avail(mos7720_port, 14280f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman (unsigned int __user *)arg); 14290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 14300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 14310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case TIOCSERGETLSR: 1432441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s (%d) TIOCSERGETLSR", __func__, port->number); 14330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return get_lsr_info(mos7720_port, (unsigned int __user *)arg); 14340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return 0; 14350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 14360f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case TIOCMBIS: 14370f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case TIOCMBIC: 14380f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case TIOCMSET: 1439441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __func__, 14400f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port->number); 14410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return set_modem_info(mos7720_port, cmd, 14420f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman (unsigned int __user *)arg); 14430f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 14440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case TIOCMGET: 1445441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s (%d) TIOCMGET", __func__, port->number); 14460f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return get_modem_info(mos7720_port, 14470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman (unsigned int __user *)arg); 14480f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 14490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case TIOCGSERIAL: 1450441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s (%d) TIOCGSERIAL", __func__, port->number); 14510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return get_serial_info(mos7720_port, 14520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman (struct serial_struct __user *)arg); 14530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 14540f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case TIOCSSERIAL: 1455441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s (%d) TIOCSSERIAL", __func__, port->number); 14560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 14570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 14580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case TIOCMIWAIT: 1459441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s (%d) TIOCMIWAIT", __func__, port->number); 14600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman cprev = mos7720_port->icount; 14610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman while (1) { 14620f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (signal_pending(current)) 14630f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -ERESTARTSYS; 14640f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman cnow = mos7720_port->icount; 14650f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && 14660f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) 14670f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -EIO; /* no change => error */ 14680f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || 14690f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || 14700f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || 14710f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { 14720f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return 0; 14730f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 14740f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman cprev = cnow; 14750f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 14760f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* NOTREACHED */ 14770f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 14780f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 14790f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case TIOCGICOUNT: 14800f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman cnow = mos7720_port->icount; 14810f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman icount.cts = cnow.cts; 14820f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman icount.dsr = cnow.dsr; 14830f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman icount.rng = cnow.rng; 14840f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman icount.dcd = cnow.dcd; 14850f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman icount.rx = cnow.rx; 14860f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman icount.tx = cnow.tx; 14870f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman icount.frame = cnow.frame; 14880f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman icount.overrun = cnow.overrun; 14890f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman icount.parity = cnow.parity; 14900f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman icount.brk = cnow.brk; 14910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman icount.buf_overrun = cnow.buf_overrun; 14920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1493441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__, 14940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port->number, icount.rx, icount.tx ); 14950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (copy_to_user((void __user *)arg, &icount, sizeof(icount))) 14960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -EFAULT; 14970f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return 0; 14980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 14990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -ENOIOCTLCMD; 15010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 15020f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic int mos7720_startup(struct usb_serial *serial) 15040f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 15050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct moschip_serial *mos7720_serial; 15060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct moschip_port *mos7720_port; 15070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_device *dev; 15080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int i; 15090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman char data; 15100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1511441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s: Entering ..........", __func__); 15120f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15130f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (!serial) { 15140f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Invalid Handler"); 15150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -ENODEV; 15160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 15170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dev = serial->dev; 15190f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15200f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* create our private serial structure */ 15210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_serial = kzalloc(sizeof(struct moschip_serial), GFP_KERNEL); 15220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_serial == NULL) { 1523441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison err("%s - Out of memory", __func__); 15240f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -ENOMEM; 15250f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 15260f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_set_serial_data(serial, mos7720_serial); 15280f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* we set up the pointers to the endpoints in the mos7720_open * 15300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * function, as the structures aren't created yet. */ 15310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15320f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* set up port private structures */ 15330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman for (i = 0; i < serial->num_ports; ++i) { 15340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); 15350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) { 1536441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison err("%s - Out of memory", __func__); 15370f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_set_serial_data(serial, NULL); 15380f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman kfree(mos7720_serial); 15390f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -ENOMEM; 15400f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 15410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15420f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Initialize all port interrupt end point to port 0 int 15430f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * endpoint. Our device has only one interrupt endpoint 15440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * comman to all ports */ 15450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman serial->port[i]->interrupt_in_endpointAddress = serial->port[0]->interrupt_in_endpointAddress; 15460f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->port = serial->port[i]; 15480f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_set_serial_port_data(serial->port[i], mos7720_port); 15490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15500f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("port number is %d", serial->port[i]->number); 15510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("serial number is %d", serial->minor); 15520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 15530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15540f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15550f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* setting configuration feature to one */ 15560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 15570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman (__u8)0x03, 0x00,0x01,0x00, NULL, 0x00, 5*HZ); 15580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial,MOS_READ,0x00, UART_LSR, &data); // LSR For Port 1 15600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("LSR:%x",data); 15610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15620f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial,MOS_READ,0x01, UART_LSR, &data); // LSR For Port 2 15630f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("LSR:%x",data); 15640f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15650f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return 0; 15660f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 15670f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15680f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic void mos7720_shutdown(struct usb_serial *serial) 15690f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 15700f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int i; 15710f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15720f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* free private structure allocated for serial port */ 15730f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman for (i=0; i < serial->num_ports; ++i) { 15740f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman kfree(usb_get_serial_port_data(serial->port[i])); 15750f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_set_serial_port_data(serial->port[i], NULL); 15760f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 15770f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15780f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* free private structure allocated for serial device */ 15790f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman kfree(usb_get_serial_data(serial)); 15800f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_set_serial_data(serial, NULL); 15810f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 15820f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1583d9b1b787736852f462dbf277b3ca708cbbf693aeJohannes Hölzlstatic struct usb_driver usb_driver = { 1584d9b1b787736852f462dbf277b3ca708cbbf693aeJohannes Hölzl .name = "moschip7720", 1585d9b1b787736852f462dbf277b3ca708cbbf693aeJohannes Hölzl .probe = usb_serial_probe, 1586d9b1b787736852f462dbf277b3ca708cbbf693aeJohannes Hölzl .disconnect = usb_serial_disconnect, 1587d9b1b787736852f462dbf277b3ca708cbbf693aeJohannes Hölzl .id_table = moschip_port_id_table, 1588d9b1b787736852f462dbf277b3ca708cbbf693aeJohannes Hölzl .no_dynamic_id = 1, 1589d9b1b787736852f462dbf277b3ca708cbbf693aeJohannes Hölzl}; 1590d9b1b787736852f462dbf277b3ca708cbbf693aeJohannes Hölzl 15910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic struct usb_serial_driver moschip7720_2port_driver = { 15920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .driver = { 15930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .owner = THIS_MODULE, 15940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .name = "moschip7720", 15950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman }, 15960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .description = "Moschip 2 port adapter", 1597d9b1b787736852f462dbf277b3ca708cbbf693aeJohannes Hölzl .usb_driver = &usb_driver, 15980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .id_table = moschip_port_id_table, 15990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .num_ports = 2, 16000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .open = mos7720_open, 16010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .close = mos7720_close, 16020f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .throttle = mos7720_throttle, 16030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .unthrottle = mos7720_unthrottle, 16040f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .attach = mos7720_startup, 16050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .shutdown = mos7720_shutdown, 16060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .ioctl = mos7720_ioctl, 16070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .set_termios = mos7720_set_termios, 16080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .write = mos7720_write, 16090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .write_room = mos7720_write_room, 16100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .chars_in_buffer = mos7720_chars_in_buffer, 16110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .break_ctl = mos7720_break, 16120f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .read_bulk_callback = mos7720_bulk_in_callback, 1613e8e30c765c5cfa5219918d3e5017fc563cf7ea03Oliver Neukum .read_int_callback = mos7720_interrupt_callback, 16140f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman}; 16150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 16160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic int __init moschip7720_init(void) 16170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 16180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int retval; 16190f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1620441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s: Entering ..........", __func__); 16210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 16220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Register with the usb serial */ 16230f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman retval = usb_serial_register(&moschip7720_2port_driver); 16240f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (retval) 16250f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman goto failed_port_device_register; 16260f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 16270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman info(DRIVER_DESC " " DRIVER_VERSION); 16280f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 16290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Register with the usb */ 16300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman retval = usb_register(&usb_driver); 16310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (retval) 16320f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman goto failed_usb_register; 16330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 16340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return 0; 16350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 16360f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanfailed_usb_register: 16370f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_serial_deregister(&moschip7720_2port_driver); 16380f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 16390f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanfailed_port_device_register: 16400f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return retval; 16410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 16420f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 16430f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic void __exit moschip7720_exit(void) 16440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 16450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_deregister(&usb_driver); 16460f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_serial_deregister(&moschip7720_2port_driver); 16470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 16480f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 16490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanmodule_init(moschip7720_init); 16500f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanmodule_exit(moschip7720_exit); 16510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 16520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* Module information */ 16530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-HartmanMODULE_AUTHOR( DRIVER_AUTHOR ); 16540f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-HartmanMODULE_DESCRIPTION( DRIVER_DESC ); 16550f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-HartmanMODULE_LICENSE("GPL"); 16560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 16570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanmodule_param(debug, bool, S_IRUGO | S_IWUSR); 16580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-HartmanMODULE_PARM_DESC(debug, "Debug enabled or not"); 1659