mos7720.c revision 0f608f8926968b4beee2cb00ef05522ad84f36eb
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> 364da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox#include <linux/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 */ 674da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Coxstruct moschip_port { 680f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u8 shadowLCR; /* last LCR value received */ 690f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u8 shadowMCR; /* last MCR value received */ 700f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u8 shadowMSR; /* last MSR value received */ 710f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman char open; 720f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct async_icount icount; 730f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_serial_port *port; /* loop back to the owner */ 740f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct urb *write_urb_pool[NUM_URBS]; 750f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman}; 760f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 770f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* This structure holds all of the individual serial device information */ 784da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Coxstruct moschip_serial { 790f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int interrupt_started; 800f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman}; 810f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 820f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic int debug; 830f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 840f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define USB_VENDOR_ID_MOSCHIP 0x9710 850f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define MOSCHIP_DEVICE_ID_7720 0x7720 860f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define MOSCHIP_DEVICE_ID_7715 0x7715 870f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 880f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakersstatic struct usb_device_id moschip_port_id_table[] = { 894da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox { USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7720) }, 900f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { } /* terminating entry */ 910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman}; 920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-HartmanMODULE_DEVICE_TABLE(usb, moschip_port_id_table); 930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* 960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * mos7720_interrupt_callback 970f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * this is the callback function for when we have received data on the 980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * interrupt endpoint. 990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman */ 1000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic void mos7720_interrupt_callback(struct urb *urb) 1010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 1020f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int result; 1030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int length; 10481105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman int status = urb->status; 105325b70c233396f0cfe15012682a5080bf8040901Oliver Neukum __u8 *data; 1060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u8 sp1; 1070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u8 sp2; 1080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1094da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox dbg("%s", " : Entering\n"); 1100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11181105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman switch (status) { 1120f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case 0: 1130f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* success */ 1140f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 1150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case -ECONNRESET: 1160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case -ENOENT: 1170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case -ESHUTDOWN: 1180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* this urb is terminated, clean up */ 119441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - urb shutting down with status: %d", __func__, 12081105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman status); 1210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 1220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman default: 123441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - nonzero urb status received: %d", __func__, 12481105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman status); 1250f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman goto exit; 1260f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 1270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1280f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman length = urb->actual_length; 1290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = urb->transfer_buffer; 1300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Moschip get 4 bytes 1320f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Byte 1 IIR Port 1 (port.number is 0) 1330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Byte 2 IIR Port 2 (port.number is 1) 1340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Byte 3 -------------- 1350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Byte 4 FIFO status for both */ 136325b70c233396f0cfe15012682a5080bf8040901Oliver Neukum 137325b70c233396f0cfe15012682a5080bf8040901Oliver Neukum /* the above description is inverted 138325b70c233396f0cfe15012682a5080bf8040901Oliver Neukum * oneukum 2007-03-14 */ 139325b70c233396f0cfe15012682a5080bf8040901Oliver Neukum 140325b70c233396f0cfe15012682a5080bf8040901Oliver Neukum if (unlikely(length != 4)) { 1410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Wrong data !!!"); 1420f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 1430f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 1440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 145325b70c233396f0cfe15012682a5080bf8040901Oliver Neukum sp1 = data[3]; 146325b70c233396f0cfe15012682a5080bf8040901Oliver Neukum sp2 = data[2]; 1470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 148325b70c233396f0cfe15012682a5080bf8040901Oliver Neukum if ((sp1 | sp2) & 0x01) { 1490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* No Interrupt Pending in both the ports */ 1500f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("No Interrupt !!!"); 1510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } else { 1520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman switch (sp1 & 0x0f) { 1530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case SERIAL_IIR_RLS: 1540f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Serial Port 1: Receiver status error or address " 1550f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman "bit detected in 9-bit mode\n"); 1560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 1570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case SERIAL_IIR_CTI: 1580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Serial Port 1: Receiver time out"); 1590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 1600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case SERIAL_IIR_MS: 1610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Serial Port 1: Modem status change"); 1620f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 1630f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 1640f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1650f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman switch (sp2 & 0x0f) { 1660f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case SERIAL_IIR_RLS: 1670f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Serial Port 2: Receiver status error or address " 1680f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman "bit detected in 9-bit mode"); 1690f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 1700f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case SERIAL_IIR_CTI: 1710f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Serial Port 2: Receiver time out"); 1720f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 1730f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case SERIAL_IIR_MS: 1740f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Serial Port 2: Modem status change"); 1750f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 1760f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 1770f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 1780f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1790f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanexit: 1800f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman result = usb_submit_urb(urb, GFP_ATOMIC); 1810f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (result) 1820f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dev_err(&urb->dev->dev, 1830f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman "%s - Error %d submitting control urb\n", 184441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison __func__, result); 1850f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 1860f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 1870f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1880f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* 1890f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * mos7720_bulk_in_callback 1900f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * this is the callback function for when we have received data on the 1910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * bulk in endpoint. 1920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman */ 1930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic void mos7720_bulk_in_callback(struct urb *urb) 1940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 19581105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman int retval; 1960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned char *data ; 1970f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_serial_port *port; 1980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct moschip_port *mos7720_port; 1990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct tty_struct *tty; 20081105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman int status = urb->status; 2010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 20281105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman if (status) { 20381105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman dbg("nonzero read bulk status received: %d", status); 2040f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 2050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 2060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 2070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port = urb->context; 2080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (!mos7720_port) { 2094da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox dbg("%s", "NULL mos7720_port pointer \n"); 2100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return ; 2110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 2120f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 2130f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port = mos7720_port->port; 2140f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 215441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("Entering...%s", __func__); 2160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 2170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = urb->transfer_buffer; 2180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 2194a90f09b20f4622dcbff1f0e1e6bae1704f8ad8cAlan Cox tty = tty_port_tty_get(&port->port); 2200f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (tty && urb->actual_length) { 2210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tty_buffer_request_room(tty, urb->actual_length); 2220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tty_insert_flip_string(tty, data, urb->actual_length); 2230f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tty_flip_buffer_push(tty); 2240f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 2254a90f09b20f4622dcbff1f0e1e6bae1704f8ad8cAlan Cox tty_kref_put(tty); 2260f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 2270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (!port->read_urb) { 2280f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("URB KILLED !!!"); 2290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 2300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 2310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 2320f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (port->read_urb->status != -EINPROGRESS) { 2330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port->read_urb->dev = port->serial->dev; 2340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 23581105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman retval = usb_submit_urb(port->read_urb, GFP_ATOMIC); 23681105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman if (retval) 23781105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman dbg("usb_submit_urb(read bulk) failed, retval = %d", 23881105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman retval); 2390f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 2400f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 2410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 2420f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* 2430f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * mos7720_bulk_out_data_callback 2440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * this is the callback function for when we have finished sending serial 2450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * data on the bulk out endpoint. 2460f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman */ 2470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic void mos7720_bulk_out_data_callback(struct urb *urb) 2480f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 2490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct moschip_port *mos7720_port; 2500f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct tty_struct *tty; 25181105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman int status = urb->status; 2520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 25381105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman if (status) { 25481105984848481d8876e454e3c503dbd0e8e4dceGreg Kroah-Hartman dbg("nonzero write bulk status received:%d", status); 2550f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 2560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 2570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 2580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port = urb->context; 2590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (!mos7720_port) { 2600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("NULL mos7720_port pointer"); 2610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return ; 2620f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 2630f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 2640f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Entering ........."); 2650f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 2664a90f09b20f4622dcbff1f0e1e6bae1704f8ad8cAlan Cox tty = tty_port_tty_get(&mos7720_port->port->port); 2670f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 268b963a8441cb95999c97bea379607071a869c65f0Jiri Slaby if (tty && mos7720_port->open) 269b963a8441cb95999c97bea379607071a869c65f0Jiri Slaby tty_wakeup(tty); 2704a90f09b20f4622dcbff1f0e1e6bae1704f8ad8cAlan Cox tty_kref_put(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) { 2874da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox if (product == MOSCHIP_DEVICE_ID_7715) 2880f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman value = value*0x100+0x100; 2894da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox else 2900f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman value = value*0x100+0x200; 2910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } else { 2920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman value = 0x0000; 2930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if ((product == MOSCHIP_DEVICE_ID_7715) && 2940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman (index != 0x08)) { 2950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("serial->product== MOSCHIP_DEVICE_ID_7715"); 2964da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox /* index = 0x01 ; */ 2970f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 2980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 2990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 3000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (request == MOS_WRITE) { 3010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman request = (__u8)MOS_WRITE; 3020f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman requesttype = (__u8)0x40; 3030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman value = value + (__u16)*((unsigned char *)data); 3040f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = NULL; 3050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman pipe = usb_sndctrlpipe(serial->dev, 0); 3060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } else { 3070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman request = (__u8)MOS_READ; 3080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman requesttype = (__u8)0xC0; 3090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman size = 0x01; 3104da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox pipe = usb_rcvctrlpipe(serial->dev, 0); 3110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 3120f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 3130f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman status = usb_control_msg(serial->dev, pipe, request, requesttype, 3140f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman value, index, data, size, MOS_WDR_TIMEOUT); 3150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 3160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (status < 0) 3174da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox dbg("Command Write failed Value %x index %x\n", value, index); 3180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 3190f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return status; 3200f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 3210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 32295da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int mos7720_open(struct tty_struct *tty, 3234da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox 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) { 3544da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox 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) { 358194343d9364ea07c9f27c4505380a15a905e8a24Greg Kroah-Hartman dev_err(&port->dev, "No more urbs???\n"); 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) { 365194343d9364ea07c9f27c4505380a15a905e8a24Greg Kroah-Hartman dev_err(&port->dev, 366194343d9364ea07c9f27c4505380a15a905e8a24Greg Kroah-Hartman "%s-out of memory for urb buffers.\n", 367194343d9364ea07c9f27c4505380a15a905e8a24Greg Kroah-Hartman __func__); 368fe4b65ec9127a336eeaa503f878062d9e6f44591Oliver Neukum usb_free_urb(mos7720_port->write_urb_pool[j]); 369fe4b65ec9127a336eeaa503f878062d9e6f44591Oliver Neukum mos7720_port->write_urb_pool[j] = NULL; 3700f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman continue; 3710f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 372fe4b65ec9127a336eeaa503f878062d9e6f44591Oliver Neukum allocated_urbs++; 3730f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 3740f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 375fe4b65ec9127a336eeaa503f878062d9e6f44591Oliver Neukum if (!allocated_urbs) 376fe4b65ec9127a336eeaa503f878062d9e6f44591Oliver Neukum return -ENOMEM; 377fe4b65ec9127a336eeaa503f878062d9e6f44591Oliver Neukum 3780f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Initialize MCS7720 -- Write Init values to corresponding Registers 3790f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * 3800f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Register Index 3810f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * 1 : IER 3820f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * 2 : FCR 3830f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * 3 : LCR 3840f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * 4 : MCR 3850f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * 3860f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * 0x08 : SP1/2 Control Reg 3870f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman */ 3880f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port_number = port->number - port->serial->minor; 3890f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(port->serial, MOS_READ, port_number, UART_LSR, &data); 3904da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox dbg("SS::%p LSR:%x\n", mos7720_port, data); 3910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 3920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Check:Sending Command .........."); 3930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 3940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x02; 3950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x01, &data); 3960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x02; 3970f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x02, &data); 3980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 3990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x00; 4000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); 4010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x00; 4020f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x02, &data); 4030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4040f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0xCF; 4050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x02, &data); 4060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x03; 4074da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox mos7720_port->shadowLCR = data; 4080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data); 4090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x0b; 4104da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox mos7720_port->shadowMCR = data; 4110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); 4120f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x0b; 4130f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); 4140f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x00; 4160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data); 4170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x00; 4180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data); 4190f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4200f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* data = 0x00; 4210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, port_number + 1, &data); 4220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x03; 4230f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1, &data); 4240f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x00; 4254da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox send_mos_cmd(port->serial, MOS_WRITE, MOS_MAX_PORT, 4264da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox port_number + 1, &data); 4270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman*/ 4280f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x00; 4290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data); 4300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = data | (port->number - port->serial->minor + 1); 4320f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data); 4330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x83; 4354da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox mos7720_port->shadowLCR = data; 4360f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data); 4370f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x0c; 4380f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x00, &data); 4390f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x00; 4400f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); 4410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x03; 4424da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox mos7720_port->shadowLCR = data; 4430f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data); 4440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x0c; 4450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); 4460f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x0c; 4470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); 4480f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* see if we've set up our endpoint info yet * 4500f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * (can't set it up in mos7720_startup as the * 4510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * structures were not set up at that time.) */ 4520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (!mos7720_serial->interrupt_started) { 4530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Interrupt buffer NULL !!!"); 4540f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4550f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* not set up yet, so do it now */ 4560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_serial->interrupt_started = 1; 4570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("To Submit URB !!!"); 4590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* set up our interrupt urb */ 4610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_fill_int_urb(port0->interrupt_in_urb, serial->dev, 4624da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox usb_rcvintpipe(serial->dev, 4634da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox port->interrupt_in_endpointAddress), 4644da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox port0->interrupt_in_buffer, 4654da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox port0->interrupt_in_urb->transfer_buffer_length, 4664da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox mos7720_interrupt_callback, mos7720_port, 4674da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox port0->interrupt_in_urb->interval); 4680f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4690f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* start interrupt read for this mos7720 this interrupt * 4704da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox * will continue as long as the mos7720 is connected */ 4710f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Submit URB over !!!"); 4720f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman response = usb_submit_urb(port0->interrupt_in_urb, GFP_KERNEL); 4730f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (response) 4740f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dev_err(&port->dev, 475898eb71cb17644964c5895fb190e79e3d0c49679Joe Perches "%s - Error %d submitting control urb\n", 476441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison __func__, response); 4770f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 4780f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4790f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* set up our bulk in urb */ 4800f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_fill_bulk_urb(port->read_urb, serial->dev, 4810f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_rcvbulkpipe(serial->dev, 4824da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox port->bulk_in_endpointAddress), 4830f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port->bulk_in_buffer, 4840f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port->read_urb->transfer_buffer_length, 4850f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_bulk_in_callback, mos7720_port); 4860f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman response = usb_submit_urb(port->read_urb, GFP_KERNEL); 4870f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (response) 4884da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox dev_err(&port->dev, "%s - Error %d submitting read urb\n", 4894da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox __func__, response); 4900f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* initialize our icount structure */ 4920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman memset(&(mos7720_port->icount), 0x00, sizeof(mos7720_port->icount)); 4930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* initialize our port settings */ 4950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowMCR = UART_MCR_OUT2; /* Must set to enable ints! */ 4960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 4970f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* send a open port command */ 4980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->open = 1; 4990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 5000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return 0; 5010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 5020f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 5030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* 5040f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * mos7720_chars_in_buffer 5050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * this function is called by the tty driver when it wants to know how many 5060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * bytes of data we currently have outstanding in the port (data that has 5070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * been written, but hasn't made it out the port yet) 5080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * If successful, we return the number of bytes left to be written in the 5090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * system, 5100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Otherwise we return a negative error number. 5110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman */ 51295da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int mos7720_chars_in_buffer(struct tty_struct *tty) 5130f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 51495da310e66ee8090119596c70ca8432e57f9a97fAlan Cox struct usb_serial_port *port = tty->driver_data; 5150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int i; 5160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int chars = 0; 5170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct moschip_port *mos7720_port; 5180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 519441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s:entering ...........", __func__); 5200f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 5210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port = usb_get_serial_port_data(port); 5220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) { 523441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s:leaving ...........", __func__); 52423198fda7182969b619613a555f8645fdc3dc334Alan Cox return 0; 5250f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 5260f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 5270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman for (i = 0; i < NUM_URBS; ++i) { 5284da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox if (mos7720_port->write_urb_pool[i] && 5294da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox mos7720_port->write_urb_pool[i]->status == -EINPROGRESS) 5300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman chars += URB_TRANSFER_BUFFER_SIZE; 5310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 532441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - returns %d", __func__, chars); 5330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return chars; 5340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 5350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 536335f8514f200e63d689113d29cb7253a5c282967Alan Coxstatic void mos7720_close(struct usb_serial_port *port) 5370f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 5380f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_serial *serial; 5390f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct moschip_port *mos7720_port; 5400f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman char data; 5410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int j; 5420f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 5430f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("mos7720_close:entering..."); 5440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 5450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman serial = port->serial; 5460f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 5470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port = usb_get_serial_port_data(port); 5480f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) 5490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 5500f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 5510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman for (j = 0; j < NUM_URBS; ++j) 5520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_kill_urb(mos7720_port->write_urb_pool[j]); 5530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 5540f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Freeing Write URBs */ 5550f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman for (j = 0; j < NUM_URBS; ++j) { 5560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port->write_urb_pool[j]) { 5570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman kfree(mos7720_port->write_urb_pool[j]->transfer_buffer); 5580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_free_urb(mos7720_port->write_urb_pool[j]); 5590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 5600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 5610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 5620f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* While closing port, shutdown all bulk read, write * 563a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum * and interrupt read if they exists, otherwise nop */ 564a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum dbg("Shutdown bulk write"); 565a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum usb_kill_urb(port->write_urb); 566a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum dbg("Shutdown bulk read"); 567a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum usb_kill_urb(port->read_urb); 568a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum 569a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum mutex_lock(&serial->disc_mutex); 570a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum /* these commands must not be issued if the device has 571a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum * been disconnected */ 572a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum if (!serial->disconnected) { 573a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum data = 0x00; 5744da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox send_mos_cmd(serial, MOS_WRITE, 5754da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox port->number - port->serial->minor, 0x04, &data); 576a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum 577a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum data = 0x00; 5784da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox send_mos_cmd(serial, MOS_WRITE, 5794da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox port->number - port->serial->minor, 0x01, &data); 5800f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 581a1cd7e99b343543af2be4c8c5755e26f6bfd725aOliver Neukum mutex_unlock(&serial->disc_mutex); 5820f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->open = 0; 5830f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 584441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("Leaving %s", __func__); 5850f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 5860f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 58795da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic void mos7720_break(struct tty_struct *tty, int break_state) 5880f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 58995da310e66ee8090119596c70ca8432e57f9a97fAlan Cox struct usb_serial_port *port = tty->driver_data; 5904da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox unsigned char data; 5910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_serial *serial; 5920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct moschip_port *mos7720_port; 5930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 594441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("Entering %s", __func__); 5950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 5960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman serial = port->serial; 5970f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 5980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port = usb_get_serial_port_data(port); 5990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) 6000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 6010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 6020f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (break_state == -1) 6030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = mos7720_port->shadowLCR | UART_LCR_SBC; 6040f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman else 6050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = mos7720_port->shadowLCR & ~UART_LCR_SBC; 6060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 6070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowLCR = data; 6080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor, 6090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 0x03, &data); 6100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 6110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 6120f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 6130f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 6140f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* 6150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * mos7720_write_room 6160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * this function is called by the tty driver when it wants to know how many 6170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * bytes of data we can accept for a specific port. 6180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * If successful, we return the amount of room that we have for this port 6190f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Otherwise we return a negative error number. 6200f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman */ 62195da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int mos7720_write_room(struct tty_struct *tty) 6220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 62395da310e66ee8090119596c70ca8432e57f9a97fAlan Cox struct usb_serial_port *port = tty->driver_data; 6240f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct moschip_port *mos7720_port; 6250f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int room = 0; 6260f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int i; 6270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 628441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s:entering ...........", __func__); 6290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 6300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port = usb_get_serial_port_data(port); 6310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) { 632441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s:leaving ...........", __func__); 6330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -ENODEV; 6340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 6350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 636a5b6f60c5a30c494017c7a2d11c4067f90d3d0dfAlan Cox /* FIXME: Locking */ 6370f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman for (i = 0; i < NUM_URBS; ++i) { 6384da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox if (mos7720_port->write_urb_pool[i] && 6394da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox 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 64795da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int mos7720_write(struct tty_struct *tty, struct usb_serial_port *port, 64895da310e66ee8090119596c70ca8432e57f9a97fAlan Cox 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) { 6744da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox if (mos7720_port->write_urb_pool[i] && 6754da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox mos7720_port->write_urb_pool[i]->status != -EINPROGRESS) { 6760f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman urb = mos7720_port->write_urb_pool[i]; 6774da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox dbg("URB:%d", i); 6780f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 6790f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 6800f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 6810f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 6820f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (urb == NULL) { 683441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - no more free urbs", __func__); 6840f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman goto exit; 6850f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 6860f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 6870f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (urb->transfer_buffer == NULL) { 6880f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, 6890f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman GFP_KERNEL); 6900f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (urb->transfer_buffer == NULL) { 691194343d9364ea07c9f27c4505380a15a905e8a24Greg Kroah-Hartman dev_err(&port->dev, "%s no more kernel memory...\n", 692194343d9364ea07c9f27c4505380a15a905e8a24Greg Kroah-Hartman __func__); 6930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman goto exit; 6940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 6950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 6964da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE); 6970f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 6980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman memcpy(urb->transfer_buffer, current_position, transfer_size); 699441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison usb_serial_debug_data(debug, &port->dev, __func__, transfer_size, 7000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman urb->transfer_buffer); 7010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7020f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* fill urb with data and submit */ 7030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_fill_bulk_urb(urb, serial->dev, 7040f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_sndbulkpipe(serial->dev, 7054da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox port->bulk_out_endpointAddress), 7060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman urb->transfer_buffer, transfer_size, 7070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_bulk_out_data_callback, mos7720_port); 7080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* send it down the pipe */ 7104da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox status = usb_submit_urb(urb, GFP_ATOMIC); 7110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (status) { 712194343d9364ea07c9f27c4505380a15a905e8a24Greg Kroah-Hartman dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed " 713194343d9364ea07c9f27c4505380a15a905e8a24Greg Kroah-Hartman "with status = %d\n", __func__, status); 7140f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman bytes_sent = status; 7150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman goto exit; 7160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 7170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman bytes_sent = transfer_size; 7180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7190f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanexit: 7200f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return bytes_sent; 7210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 7220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 72395da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic void mos7720_throttle(struct tty_struct *tty) 7240f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 72595da310e66ee8090119596c70ca8432e57f9a97fAlan Cox struct usb_serial_port *port = tty->driver_data; 7260f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct moschip_port *mos7720_port; 7270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int status; 7280f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 729441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s- port %d\n", __func__, port->number); 7300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port = usb_get_serial_port_data(port); 7320f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) 7340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 7350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7360f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (!mos7720_port->open) { 7370f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("port not opened"); 7380f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 7390f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 7400f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 741441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s: Entering ..........", __func__); 7420f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7430f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* if we are implementing XON/XOFF, send the stop character */ 7440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (I_IXOFF(tty)) { 7450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned char stop_char = STOP_CHAR(tty); 74695da310e66ee8090119596c70ca8432e57f9a97fAlan Cox status = mos7720_write(tty, port, &stop_char, 1); 7470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (status <= 0) 7480f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 7490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 7500f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* if we are implementing RTS/CTS, toggle that line */ 7520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (tty->termios->c_cflag & CRTSCTS) { 7530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowMCR &= ~UART_MCR_RTS; 7540f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman status = send_mos_cmd(port->serial, MOS_WRITE, 7550f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port->number - port->serial->minor, 7560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman UART_MCR, &mos7720_port->shadowMCR); 7570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (status != 0) 7580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 7590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 7600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 7610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 76295da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic void mos7720_unthrottle(struct tty_struct *tty) 7630f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 76495da310e66ee8090119596c70ca8432e57f9a97fAlan Cox struct usb_serial_port *port = tty->driver_data; 7650f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct moschip_port *mos7720_port = usb_get_serial_port_data(port); 76695da310e66ee8090119596c70ca8432e57f9a97fAlan Cox int status; 7670f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7680f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) 7690f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 7700f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7710f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (!mos7720_port->open) { 772441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port not opened", __func__); 7730f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 7740f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 7750f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 776441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s: Entering ..........", __func__); 7770f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7780f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* if we are implementing XON/XOFF, send the start character */ 7790f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (I_IXOFF(tty)) { 7800f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned char start_char = START_CHAR(tty); 78195da310e66ee8090119596c70ca8432e57f9a97fAlan Cox status = mos7720_write(tty, port, &start_char, 1); 7820f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (status <= 0) 7830f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 7840f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 7850f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7860f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* if we are implementing RTS/CTS, toggle that line */ 7870f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (tty->termios->c_cflag & CRTSCTS) { 7880f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowMCR |= UART_MCR_RTS; 7890f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman status = send_mos_cmd(port->serial, MOS_WRITE, 7900f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port->number - port->serial->minor, 7910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman UART_MCR, &mos7720_port->shadowMCR); 7920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (status != 0) 7930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 7940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 7950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 7960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 7970f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic int set_higher_rates(struct moschip_port *mos7720_port, 7980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned int baud) 7990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 8000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned char data; 8010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_serial_port *port; 8020f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_serial *serial; 8030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int port_number; 8040f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) 8060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -EINVAL; 8070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port = mos7720_port->port; 8090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman serial = port->serial; 8100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8114da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox /*********************************************** 8124da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox * Init Sequence for higher rates 8134da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox ***********************************************/ 8140f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Sending Setting Commands .........."); 8150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port_number = port->number - port->serial->minor; 8160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x000; 8180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); 8190f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x000; 8200f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x02, &data); 8210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x0CF; 8220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port->number, 0x02, &data); 8230f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x00b; 8244da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox mos7720_port->shadowMCR = data; 8250f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); 8260f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x00b; 8270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); 8280f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x000; 8300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data); 8310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x000; 8320f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data); 8330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8354da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox /*********************************************** 8364da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox * Set for higher rates * 8374da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox ***********************************************/ 8380f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8390f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = baud * 0x10; 8404da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1, &data); 8410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8420f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x003; 8430f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data); 8440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x003; 8450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data); 8460f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x02b; 8484da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox mos7720_port->shadowMCR = data; 8490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); 8500f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x02b; 8510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); 8520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8534da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox /*********************************************** 8544da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox * Set DLL/DLM 8554da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox ***********************************************/ 8560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = mos7720_port->shadowLCR | UART_LCR_DLAB; 8584da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox mos7720_port->shadowLCR = data; 8590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data); 8600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x001; /* DLL */ 8624da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox send_mos_cmd(serial, MOS_WRITE, port_number, 0x00, &data); 8630f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x000; /* DLM */ 8644da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); 8650f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8660f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = mos7720_port->shadowLCR & ~UART_LCR_DLAB; 8674da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox mos7720_port->shadowLCR = data; 8680f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data); 8690f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8700f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return 0; 8710f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 8720f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8730f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* baud rate information */ 8744da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Coxstruct divisor_table_entry { 8750f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u32 baudrate; 8760f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u16 divisor; 8770f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman}; 8780f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 8790f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* Define table of divisors for moschip 7720 hardware * 8800f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * These assume a 3.6864MHz crystal, the standard /16, and * 8810f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * MCR.7 = 0. */ 8820f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic struct divisor_table_entry divisor_table[] = { 8830f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 50, 2304}, 8840f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 110, 1047}, /* 2094.545455 => 230450 => .0217 % over */ 8850f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 134, 857}, /* 1713.011152 => 230398.5 => .00065% under */ 8860f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 150, 768}, 8870f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 300, 384}, 8880f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 600, 192}, 8890f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 1200, 96}, 8900f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 1800, 64}, 8910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 2400, 48}, 8920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 4800, 24}, 8930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 7200, 16}, 8940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 9600, 12}, 8950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 19200, 6}, 8960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 38400, 3}, 8970f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 57600, 2}, 8980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman { 115200, 1}, 8990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman}; 9000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/***************************************************************************** 9020f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * calc_baud_rate_divisor 9030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * this function calculates the proper baud rate divisor for the specified 9040f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * baud rate. 9050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman *****************************************************************************/ 9060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic int calc_baud_rate_divisor(int baudrate, int *divisor) 9070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 9080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int i; 9090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u16 custom; 9100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u16 round1; 9110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u16 round; 9120f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9130f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 914441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - %d", __func__, baudrate); 9150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman for (i = 0; i < ARRAY_SIZE(divisor_table); i++) { 9170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (divisor_table[i].baudrate == baudrate) { 9180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman *divisor = divisor_table[i].divisor; 9190f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return 0; 9200f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 9210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 9220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9234da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox /* After trying for all the standard baud rates * 9244da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox * Try calculating the divisor for this baud rate */ 9250f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (baudrate > 75 && baudrate < 230400) { 9260f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* get the divisor */ 9270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman custom = (__u16)(230400L / baudrate); 9280f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Check for round off */ 9300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman round1 = (__u16)(2304000L / baudrate); 9310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman round = (__u16)(round1 - (custom * 10)); 9320f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (round > 4) 9330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman custom++; 9340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman *divisor = custom; 9350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9364da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox dbg("Baud %d = %d", baudrate, custom); 9370f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return 0; 9380f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 9390f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9400f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Baud calculation Failed..."); 9410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -EINVAL; 9420f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 9430f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* 9450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * send_cmd_write_baud_rate 9460f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * this function sends the proper command to change the baud rate of the 9470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * specified port. 9480f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman */ 9490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic int send_cmd_write_baud_rate(struct moschip_port *mos7720_port, 9500f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int baudrate) 9510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 9520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_serial_port *port; 9530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_serial *serial; 9540f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int divisor; 9550f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int status; 9560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned char data; 9570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned char number; 9580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) 9600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -1; 9610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9620f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port = mos7720_port->port; 9630f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman serial = port->serial; 9640f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 965441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s: Entering ..........", __func__); 9660f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9670f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman number = port->number - port->serial->minor; 968441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port = %d, baud = %d", __func__, port->number, baudrate); 9690f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9704da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox /* Calculate the Divisor */ 9710f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman status = calc_baud_rate_divisor(baudrate, &divisor); 9720f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (status) { 973194343d9364ea07c9f27c4505380a15a905e8a24Greg Kroah-Hartman dev_err(&port->dev, "%s - bad baud rate\n", __func__); 9740f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return status; 9750f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 9760f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9774da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox /* Enable access to divisor latch */ 9784da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox data = mos7720_port->shadowLCR | UART_LCR_DLAB; 9794da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox mos7720_port->shadowLCR = data; 9804da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox send_mos_cmd(serial, MOS_WRITE, number, UART_LCR, &data); 9810f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9820f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Write the divisor */ 9830f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = ((unsigned char)(divisor & 0xff)); 9844da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox send_mos_cmd(serial, MOS_WRITE, number, 0x00, &data); 9850f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9860f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = ((unsigned char)((divisor & 0xff00) >> 8)); 9874da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox send_mos_cmd(serial, MOS_WRITE, number, 0x01, &data); 9880f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9894da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox /* Disable access to divisor latch */ 9904da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox data = mos7720_port->shadowLCR & ~UART_LCR_DLAB; 9914da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox mos7720_port->shadowLCR = data; 9924da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox send_mos_cmd(serial, MOS_WRITE, number, 0x03, &data); 9930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return status; 9950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 9960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 9970f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* 9980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * change_port_settings 9990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * This routine is called to set the UART on the device to match 10000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * the specified new settings. 10010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman */ 100295da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic void change_port_settings(struct tty_struct *tty, 100395da310e66ee8090119596c70ca8432e57f9a97fAlan Cox struct moschip_port *mos7720_port, 1004606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox struct ktermios *old_termios) 10050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 10060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_serial_port *port; 10070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_serial *serial; 10080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int baud; 10090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned cflag; 10100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned iflag; 10110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u8 mask = 0xff; 10120f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u8 lData; 10130f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u8 lParity; 10140f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman __u8 lStop; 10150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int status; 10160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int port_number; 10170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman char data; 10180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10190f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) 10200f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return ; 10210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port = mos7720_port->port; 10230f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman serial = port->serial; 10240f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port_number = port->number - port->serial->minor; 10250f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1026441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port %d", __func__, port->number); 10270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10280f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (!mos7720_port->open) { 1029441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port not opened", __func__); 10300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 10310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 10320f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1033441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s: Entering ..........", __func__); 10340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman lData = UART_LCR_WLEN8; 10360f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman lStop = 0x00; /* 1 stop bit */ 10370f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman lParity = 0x00; /* No parity */ 10380f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10390f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman cflag = tty->termios->c_cflag; 10400f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman iflag = tty->termios->c_iflag; 10410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10420f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Change the number of bits */ 10430f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman switch (cflag & CSIZE) { 10440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case CS5: 10450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman lData = UART_LCR_WLEN5; 10460f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mask = 0x1f; 10470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 10480f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case CS6: 10500f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman lData = UART_LCR_WLEN6; 10510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mask = 0x3f; 10520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 10530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10540f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case CS7: 10550f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman lData = UART_LCR_WLEN7; 10560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mask = 0x7f; 10570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 10580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman default: 10590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case CS8: 10600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman lData = UART_LCR_WLEN8; 10610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 10620f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 10630f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10640f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Change the Parity bit */ 10650f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (cflag & PARENB) { 10660f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (cflag & PARODD) { 10670f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman lParity = UART_LCR_PARITY; 1068441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - parity = odd", __func__); 10690f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } else { 10700f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman lParity = (UART_LCR_EPAR | UART_LCR_PARITY); 1071441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - parity = even", __func__); 10720f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 10730f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10740f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } else { 1075441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - parity = none", __func__); 10760f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 10770f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10780f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (cflag & CMSPAR) 10790f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman lParity = lParity | 0x20; 10800f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10810f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Change the Stop bit */ 10820f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (cflag & CSTOPB) { 10830f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman lStop = UART_LCR_STOP; 1084441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - stop bits = 2", __func__); 10850f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } else { 10860f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman lStop = 0x00; 1087441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - stop bits = 1", __func__); 10880f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 10890f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10900f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define LCR_BITS_MASK 0x03 /* Mask for bits/char field */ 10910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define LCR_STOP_MASK 0x04 /* Mask for stop bits field */ 10920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman#define LCR_PAR_MASK 0x38 /* Mask for parity field */ 10930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Update the LCR with the correct value */ 10954da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox mos7720_port->shadowLCR &= 10964da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK); 10970f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowLCR |= (lData | lParity | lStop); 10980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 10990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Disable Interrupts */ 11010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x00; 11024da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor, 11034da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox UART_IER, &data); 11040f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x00; 11064da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data); 11070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0xcf; 11094da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data); 11100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Send the updated LCR value to the mos7720 */ 11120f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = mos7720_port->shadowLCR; 11134da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox send_mos_cmd(serial, MOS_WRITE, port_number, UART_LCR, &data); 11140f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11154da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox data = 0x00b; 11164da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox mos7720_port->shadowMCR = data; 11174da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); 11184da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox data = 0x00b; 11194da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); 11200f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* set up the MCR register and send it to the mos7720 */ 11220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowMCR = UART_MCR_OUT2; 11230f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (cflag & CBAUD) 11240f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowMCR |= (UART_MCR_DTR | UART_MCR_RTS); 11250f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11260f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (cflag & CRTSCTS) { 11270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowMCR |= (UART_MCR_XONANY); 11284da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox /* To set hardware flow control to the specified * 11294da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox * serial port, in SP1/2_CONTROL_REG */ 11300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (port->number) { 11310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x001; 11320f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 11330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 0x08, &data); 11340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } else { 11350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x002; 11360f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 11370f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 0x08, &data); 11380f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 11390f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } else { 11400f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowMCR &= ~(UART_MCR_XONANY); 11410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 11420f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11430f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = mos7720_port->shadowMCR; 11440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, UART_MCR, &data); 11450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11460f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Determine divisor based on baud rate */ 11470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman baud = tty_get_baud_rate(tty); 11480f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (!baud) { 11490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* pick a default, any default... */ 11500f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Picked default baud..."); 11510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman baud = 9600; 11520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 11530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11540f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (baud >= 230400) { 11550f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman set_higher_rates(mos7720_port, baud); 11560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Enable Interrupts */ 11570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = 0x0c; 11580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(serial, MOS_WRITE, port_number, UART_IER, &data); 11590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 11600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 11610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1162441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - baud rate = %d", __func__, baud); 11630f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman status = send_cmd_write_baud_rate(mos7720_port, baud); 116465d063ab21feea8cf65d64fba50a5c4fa7bfd6beAlan Cox /* FIXME: needs to write actual resulting baud back not just 116565d063ab21feea8cf65d64fba50a5c4fa7bfd6beAlan Cox blindly do so */ 116665d063ab21feea8cf65d64fba50a5c4fa7bfd6beAlan Cox if (cflag & CBAUD) 116765d063ab21feea8cf65d64fba50a5c4fa7bfd6beAlan Cox tty_encode_baud_rate(tty, baud, 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 11720f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (port->read_urb->status != -EINPROGRESS) { 11730f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port->read_urb->dev = serial->dev; 11740f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11750f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman status = usb_submit_urb(port->read_urb, GFP_ATOMIC); 11760f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (status) 11770f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("usb_submit_urb(read bulk) failed, status = %d", 11780f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman status); 11790f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 11800f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 11810f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 11820f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11830f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* 11840f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * mos7720_set_termios 11850f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * this function is called by the tty driver when it wants to change the 11860f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * termios structure. 11870f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman */ 118895da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic void mos7720_set_termios(struct tty_struct *tty, 118995da310e66ee8090119596c70ca8432e57f9a97fAlan Cox struct usb_serial_port *port, struct ktermios *old_termios) 11900f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 11910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int status; 11920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned int cflag; 11930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_serial *serial; 11940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct moschip_port *mos7720_port; 11950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman serial = port->serial; 11970f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 11980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port = usb_get_serial_port_data(port); 11990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 12000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) 12010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 12020f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 12030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (!mos7720_port->open) { 1204441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port not opened", __func__); 12050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 12060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 12070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 12084da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox dbg("%s\n", "setting termios - ASPIRE"); 12090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 12100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman cflag = tty->termios->c_cflag; 12110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1212441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - cflag %08x iflag %08x", __func__, 12130f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tty->termios->c_cflag, 12140f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman RELEVANT_IFLAG(tty->termios->c_iflag)); 12150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1216441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - old cflag %08x old iflag %08x", __func__, 121765d063ab21feea8cf65d64fba50a5c4fa7bfd6beAlan Cox old_termios->c_cflag, 121865d063ab21feea8cf65d64fba50a5c4fa7bfd6beAlan Cox RELEVANT_IFLAG(old_termios->c_iflag)); 12190f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1220441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port %d", __func__, port->number); 12210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 12220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* change the port settings to the new ones specified */ 122395da310e66ee8090119596c70ca8432e57f9a97fAlan Cox change_port_settings(tty, mos7720_port, old_termios); 12240f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 12254da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox if (!port->read_urb) { 12264da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox dbg("%s", "URB KILLED !!!!!\n"); 12270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 12280f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 12290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 12304da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox if (port->read_urb->status != -EINPROGRESS) { 12310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port->read_urb->dev = serial->dev; 12320f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman status = usb_submit_urb(port->read_urb, GFP_ATOMIC); 12330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (status) 12340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("usb_submit_urb(read bulk) failed, status = %d", 12350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman status); 12360f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 12370f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return; 12380f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 12390f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 12400f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* 12410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * get_lsr_info - get line status register info 12420f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * 12430f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * Purpose: Let user call ioctl() to get info when the UART physically 12440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * is emptied. On bus types like RS485, the transmitter must 12450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * release the bus after transmitting. This must be done when 12460f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * the transmit shift register is empty, not be done when the 12470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * transmit holding register is empty. This functionality 12480f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * allows an RS485 driver to be written in user space. 12490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman */ 12504da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Coxstatic int get_lsr_info(struct tty_struct *tty, 12514da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox struct moschip_port *mos7720_port, unsigned int __user *value) 12520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 12530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int count; 12540f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned int result = 0; 12550f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 125695da310e66ee8090119596c70ca8432e57f9a97fAlan Cox count = mos7720_chars_in_buffer(tty); 12570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (count == 0) { 1258441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s -- Empty", __func__); 12590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman result = TIOCSER_TEMT; 12600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 12610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 12620f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (copy_to_user(value, &result, sizeof(int))) 12630f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -EFAULT; 12640f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return 0; 12650f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 12660f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 12670f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakersstatic int mos7720_tiocmget(struct tty_struct *tty, struct file *file) 12680f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers{ 12690f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers struct usb_serial_port *port = tty->driver_data; 12700f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers struct moschip_port *mos7720_port = usb_get_serial_port_data(port); 12710f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers unsigned int result = 0; 12720f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers unsigned int mcr ; 12730f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers unsigned int msr ; 12740f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers 12750f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers dbg("%s - port %d", __func__, port->number); 12760f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers 12770f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers mcr = mos7720_port->shadowMCR; 12780f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers msr = mos7720_port->shadowMSR; 12790f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers 12800f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers result = ((mcr & UART_MCR_DTR) ? TIOCM_DTR : 0) /* 0x002 */ 12810f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers | ((mcr & UART_MCR_RTS) ? TIOCM_RTS : 0) /* 0x004 */ 12820f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers | ((msr & UART_MSR_CTS) ? TIOCM_CTS : 0) /* 0x020 */ 12830f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers | ((msr & UART_MSR_DCD) ? TIOCM_CAR : 0) /* 0x040 */ 12840f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers | ((msr & UART_MSR_RI) ? TIOCM_RI : 0) /* 0x080 */ 12850f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers | ((msr & UART_MSR_DSR) ? TIOCM_DSR : 0); /* 0x100 */ 12860f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers 12870f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers dbg("%s -- %x", __func__, result); 12880f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers 12890f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers return result; 12900f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers} 12910f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers 12920f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakersstatic int mos7720_tiocmset(struct tty_struct *tty, struct file *file, 12930f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers unsigned int set, unsigned int clear) 12940f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers{ 12950f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers struct usb_serial_port *port = tty->driver_data; 12960f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers struct moschip_port *mos7720_port = usb_get_serial_port_data(port); 12970f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers unsigned int mcr ; 12980f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers unsigned char lmcr; 12990f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers 13000f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers dbg("%s - port %d", __func__, port->number); 13010f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers dbg("he was at tiocmget"); 13020f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers 13030f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers mcr = mos7720_port->shadowMCR; 13040f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers 13050f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers if (set & TIOCM_RTS) 13060f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers mcr |= UART_MCR_RTS; 13070f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers if (set & TIOCM_DTR) 13080f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers mcr |= UART_MCR_DTR; 13090f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers if (set & TIOCM_LOOP) 13100f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers mcr |= UART_MCR_LOOP; 13110f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers 13120f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers if (clear & TIOCM_RTS) 13130f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers mcr &= ~UART_MCR_RTS; 13140f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers if (clear & TIOCM_DTR) 13150f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers mcr &= ~UART_MCR_DTR; 13160f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers if (clear & TIOCM_LOOP) 13170f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers mcr &= ~UART_MCR_LOOP; 13180f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers 13190f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers mos7720_port->shadowMCR = mcr; 13200f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers lmcr = mos7720_port->shadowMCR; 13210f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers 13220f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers send_mos_cmd(port->serial, MOS_WRITE, 13230f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers port->number - port->serial->minor, UART_MCR, &lmcr); 13240f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers 13250f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers return 0; 13260f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers} 13270f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers 13280f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd, 13290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned int __user *value) 13300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 13310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned int mcr ; 13320f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned int arg; 13330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned char data; 13340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_serial_port *port; 13360f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13370f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) 13380f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -1; 13390f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13404da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox port = (struct usb_serial_port *)mos7720_port->port; 13410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mcr = mos7720_port->shadowMCR; 13420f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13430f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (copy_from_user(&arg, value, sizeof(int))) 13440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -EFAULT; 13450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13460f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman switch (cmd) { 13470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case TIOCMBIS: 13480f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (arg & TIOCM_RTS) 13490f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mcr |= UART_MCR_RTS; 13500f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (arg & TIOCM_DTR) 13510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mcr |= UART_MCR_RTS; 13520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (arg & TIOCM_LOOP) 13530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mcr |= UART_MCR_LOOP; 13540f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 13550f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case TIOCMBIC: 13570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (arg & TIOCM_RTS) 13580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mcr &= ~UART_MCR_RTS; 13590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (arg & TIOCM_DTR) 13600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mcr &= ~UART_MCR_RTS; 13610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (arg & TIOCM_LOOP) 13620f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mcr &= ~UART_MCR_LOOP; 13630f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 13640f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13650f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 13660f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13670f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->shadowMCR = mcr; 13680f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13690f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman data = mos7720_port->shadowMCR; 13700f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman send_mos_cmd(port->serial, MOS_WRITE, 13710f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman port->number - port->serial->minor, UART_MCR, &data); 13720f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13730f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return 0; 13740f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 13750f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13760f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic int get_serial_info(struct moschip_port *mos7720_port, 13770f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct serial_struct __user *retinfo) 13780f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 13790f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct serial_struct tmp; 13800f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13810f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (!retinfo) 13820f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -EFAULT; 13830f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13840f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman memset(&tmp, 0, sizeof(tmp)); 13850f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13860f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tmp.type = PORT_16550A; 13870f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tmp.line = mos7720_port->port->serial->minor; 13880f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tmp.port = mos7720_port->port->number; 13890f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tmp.irq = 0; 13900f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; 13914da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE; 13920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tmp.baud_base = 9600; 13930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tmp.close_delay = 5*HZ; 13940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman tmp.closing_wait = 30*HZ; 13950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 13960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) 13970f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -EFAULT; 13980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return 0; 13990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 14000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 140195da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int mos7720_ioctl(struct tty_struct *tty, struct file *file, 14020f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman unsigned int cmd, unsigned long arg) 14030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 140495da310e66ee8090119596c70ca8432e57f9a97fAlan Cox struct usb_serial_port *port = tty->driver_data; 14050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct moschip_port *mos7720_port; 14060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct async_icount cnow; 14070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct async_icount cprev; 14080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct serial_icounter_struct icount; 14090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 14100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port = usb_get_serial_port_data(port); 14110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) 14120f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -ENODEV; 14130f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1414441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd); 14150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 14160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman switch (cmd) { 14170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case TIOCSERGETLSR: 1418441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s (%d) TIOCSERGETLSR", __func__, port->number); 14194da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox return get_lsr_info(tty, mos7720_port, 14204da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox (unsigned int __user *)arg); 14210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return 0; 14220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 142395da310e66ee8090119596c70ca8432e57f9a97fAlan Cox /* FIXME: These should be using the mode methods */ 14240f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case TIOCMBIS: 14250f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case TIOCMBIC: 14264da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", 14274da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox __func__, port->number); 14280f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return set_modem_info(mos7720_port, cmd, 14290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman (unsigned int __user *)arg); 14300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 14310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case TIOCGSERIAL: 1432441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s (%d) TIOCGSERIAL", __func__, port->number); 14330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return get_serial_info(mos7720_port, 14340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman (struct serial_struct __user *)arg); 14350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 14360f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case TIOCMIWAIT: 1437441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s (%d) TIOCMIWAIT", __func__, port->number); 14380f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman cprev = mos7720_port->icount; 14390f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman while (1) { 14400f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (signal_pending(current)) 14410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -ERESTARTSYS; 14420f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman cnow = mos7720_port->icount; 14430f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && 14440f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) 14450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -EIO; /* no change => error */ 14460f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || 14470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || 14480f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || 14494da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { 14500f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return 0; 14510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 14520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman cprev = cnow; 14530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 14540f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* NOTREACHED */ 14550f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman break; 14560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 14570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman case TIOCGICOUNT: 14580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman cnow = mos7720_port->icount; 14590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman icount.cts = cnow.cts; 14600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman icount.dsr = cnow.dsr; 14610f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman icount.rng = cnow.rng; 14620f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman icount.dcd = cnow.dcd; 14630f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman icount.rx = cnow.rx; 14640f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman icount.tx = cnow.tx; 14650f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman icount.frame = cnow.frame; 14660f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman icount.overrun = cnow.overrun; 14670f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman icount.parity = cnow.parity; 14680f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman icount.brk = cnow.brk; 14690f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman icount.buf_overrun = cnow.buf_overrun; 14700f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1471441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__, 14724da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox port->number, icount.rx, icount.tx); 14730f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (copy_to_user((void __user *)arg, &icount, sizeof(icount))) 14740f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -EFAULT; 14750f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return 0; 14760f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 14770f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 14780f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -ENOIOCTLCMD; 14790f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 14800f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 14810f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic int mos7720_startup(struct usb_serial *serial) 14820f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 14830f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct moschip_serial *mos7720_serial; 14840f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct moschip_port *mos7720_port; 14850f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman struct usb_device *dev; 14860f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int i; 14870f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman char data; 14880f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1489441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s: Entering ..........", __func__); 14900f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 14910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (!serial) { 14920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("Invalid Handler"); 14930f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -ENODEV; 14940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 14950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 14960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dev = serial->dev; 14970f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 14980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* create our private serial structure */ 14990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_serial = kzalloc(sizeof(struct moschip_serial), GFP_KERNEL); 15000f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_serial == NULL) { 1501194343d9364ea07c9f27c4505380a15a905e8a24Greg Kroah-Hartman dev_err(&dev->dev, "%s - Out of memory\n", __func__); 15020f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -ENOMEM; 15030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 15040f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_set_serial_data(serial, mos7720_serial); 15060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15070f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* we set up the pointers to the endpoints in the mos7720_open * 15080f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * function, as the structures aren't created yet. */ 15090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* set up port private structures */ 15110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman for (i = 0; i < serial->num_ports; ++i) { 15120f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); 15130f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (mos7720_port == NULL) { 1514194343d9364ea07c9f27c4505380a15a905e8a24Greg Kroah-Hartman dev_err(&dev->dev, "%s - Out of memory\n", __func__); 15150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_set_serial_data(serial, NULL); 15160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman kfree(mos7720_serial); 15170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return -ENOMEM; 15180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 15190f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15200f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Initialize all port interrupt end point to port 0 int 15210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * endpoint. Our device has only one interrupt endpoint 15220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman * comman to all ports */ 15234da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox serial->port[i]->interrupt_in_endpointAddress = 15244da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox serial->port[0]->interrupt_in_endpointAddress; 15250f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15260f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman mos7720_port->port = serial->port[i]; 15270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_set_serial_port_data(serial->port[i], mos7720_port); 15280f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("port number is %d", serial->port[i]->number); 15300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman dbg("serial number is %d", serial->minor); 15310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman } 15320f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15340f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* setting configuration feature to one */ 15350f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 15364da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5*HZ); 15370f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15384da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox /* LSR For Port 1 */ 15394da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox send_mos_cmd(serial, MOS_READ, 0x00, UART_LSR, &data); 15404da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox dbg("LSR:%x", data); 15410f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15424da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox /* LSR For Port 2 */ 15434da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox send_mos_cmd(serial, MOS_READ, 0x01, UART_LSR, &data); 15444da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan Cox dbg("LSR:%x", data); 15450f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15460f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return 0; 15470f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 15480f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1549f9c99bb8b3a1ec81af68d484a551307326c2e933Alan Sternstatic void mos7720_release(struct usb_serial *serial) 15500f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 15510f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int i; 15520f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15530f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* free private structure allocated for serial port */ 1554f9c99bb8b3a1ec81af68d484a551307326c2e933Alan Stern for (i = 0; i < serial->num_ports; ++i) 15550f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman kfree(usb_get_serial_port_data(serial->port[i])); 15560f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15570f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* free private structure allocated for serial device */ 15580f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman kfree(usb_get_serial_data(serial)); 15590f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 15600f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1561d9b1b787736852f462dbf277b3ca708cbbf693aeJohannes Hölzlstatic struct usb_driver usb_driver = { 1562d9b1b787736852f462dbf277b3ca708cbbf693aeJohannes Hölzl .name = "moschip7720", 1563d9b1b787736852f462dbf277b3ca708cbbf693aeJohannes Hölzl .probe = usb_serial_probe, 1564d9b1b787736852f462dbf277b3ca708cbbf693aeJohannes Hölzl .disconnect = usb_serial_disconnect, 1565d9b1b787736852f462dbf277b3ca708cbbf693aeJohannes Hölzl .id_table = moschip_port_id_table, 1566d9b1b787736852f462dbf277b3ca708cbbf693aeJohannes Hölzl .no_dynamic_id = 1, 1567d9b1b787736852f462dbf277b3ca708cbbf693aeJohannes Hölzl}; 1568d9b1b787736852f462dbf277b3ca708cbbf693aeJohannes Hölzl 15690f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic struct usb_serial_driver moschip7720_2port_driver = { 15700f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .driver = { 15710f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .owner = THIS_MODULE, 15720f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .name = "moschip7720", 15730f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman }, 15740f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .description = "Moschip 2 port adapter", 1575d9b1b787736852f462dbf277b3ca708cbbf693aeJohannes Hölzl .usb_driver = &usb_driver, 15760f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .id_table = moschip_port_id_table, 15770f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .num_ports = 2, 15780f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .open = mos7720_open, 15790f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .close = mos7720_close, 15800f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .throttle = mos7720_throttle, 15810f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .unthrottle = mos7720_unthrottle, 15820f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .attach = mos7720_startup, 1583f9c99bb8b3a1ec81af68d484a551307326c2e933Alan Stern .release = mos7720_release, 15840f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .ioctl = mos7720_ioctl, 15850f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers .tiocmget = mos7720_tiocmget, 15860f608f8926968b4beee2cb00ef05522ad84f36ebKees Schoenmakers .tiocmset = mos7720_tiocmset, 15870f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .set_termios = mos7720_set_termios, 15880f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .write = mos7720_write, 15890f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .write_room = mos7720_write_room, 15900f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .chars_in_buffer = mos7720_chars_in_buffer, 15910f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .break_ctl = mos7720_break, 15920f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman .read_bulk_callback = mos7720_bulk_in_callback, 1593e8e30c765c5cfa5219918d3e5017fc563cf7ea03Oliver Neukum .read_int_callback = mos7720_interrupt_callback, 15940f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman}; 15950f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 15960f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic int __init moschip7720_init(void) 15970f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 15980f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman int retval; 15990f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1600441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison dbg("%s: Entering ..........", __func__); 16010f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 16020f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Register with the usb serial */ 16030f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman retval = usb_serial_register(&moschip7720_2port_driver); 16040f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (retval) 16050f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman goto failed_port_device_register; 16060f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 1607c197a8db59daf06dc5e77acd5a9681329cb22458Greg Kroah-Hartman printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" 1608c197a8db59daf06dc5e77acd5a9681329cb22458Greg Kroah-Hartman DRIVER_DESC "\n"); 16090f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 16100f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman /* Register with the usb */ 16110f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman retval = usb_register(&usb_driver); 16120f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman if (retval) 16130f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman goto failed_usb_register; 16140f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 16150f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return 0; 16160f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 16170f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanfailed_usb_register: 16180f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_serial_deregister(&moschip7720_2port_driver); 16190f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 16200f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanfailed_port_device_register: 16210f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman return retval; 16220f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 16230f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 16240f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanstatic void __exit moschip7720_exit(void) 16250f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman{ 16260f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_deregister(&usb_driver); 16270f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman usb_serial_deregister(&moschip7720_2port_driver); 16280f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman} 16290f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 16300f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanmodule_init(moschip7720_init); 16310f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanmodule_exit(moschip7720_exit); 16320f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 16330f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman/* Module information */ 16344da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan CoxMODULE_AUTHOR(DRIVER_AUTHOR); 16354da1a17dbc5211ac90264cfc4f0e076c8bdc1732Alan CoxMODULE_DESCRIPTION(DRIVER_DESC); 16360f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-HartmanMODULE_LICENSE("GPL"); 16370f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartman 16380f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-Hartmanmodule_param(debug, bool, S_IRUGO | S_IWUSR); 16390f64478cbc7a008fe7b7e9ae79a73d8a6904ead8Greg Kroah-HartmanMODULE_PARM_DESC(debug, "Debug enabled or not"); 1640