serqt_usb2.c revision 20b9d17715017ae4dd4ec87fabc36d33b9de708e
1d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/*
2d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * This code was developed for the Quatech USB line for linux, it used
3d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * much of the code developed by Greg Kroah-Hartman for USB serial devices
4d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton *
5d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton */
6d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
7d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/errno.h>
8d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/init.h>
9d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/slab.h>
10d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/tty.h>
11d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/tty_driver.h>
12d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/tty_flip.h>
13d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/module.h>
14d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/serial.h>
15d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/usb.h>
16d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/usb/serial.h>
17d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/uaccess.h>
18d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
19d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int debug;
20d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
21d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/* Version Information */
22d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define DRIVER_VERSION "v2.14"
23d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define DRIVER_AUTHOR "Tim Gobeli, Quatech, Inc"
24d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define DRIVER_DESC "Quatech USB to Serial Driver"
25d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
26d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define	USB_VENDOR_ID_QUATECH			0x061d	/* Quatech VID */
27d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_SSU100	0xC020	/* SSU100 */
28d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_SSU200	0xC030	/* SSU200 */
29d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_DSU100	0xC040	/* DSU100 */
30d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_DSU200	0xC050	/* DSU200 */
31d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_QSU100	0xC060	/* QSU100 */
32d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_QSU200	0xC070	/* QSU200 */
33d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_ESU100A	0xC080	/* ESU100A */
34d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_ESU100B	0xC081	/* ESU100B */
35d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_ESU200A	0xC0A0	/* ESU200A */
36d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_ESU200B	0xC0A1	/* ESU200B */
37d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_HSU100A	0xC090	/* HSU100A */
38d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_HSU100B	0xC091	/* HSU100B */
39d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_HSU100C	0xC092	/* HSU100C */
40d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_HSU100D	0xC093	/* HSU100D */
41d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_HSU200A	0xC0B0	/* HSU200A */
42d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_HSU200B	0xC0B1	/* HSU200B */
43d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_HSU200C	0xC0B2	/* HSU200C */
44d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_HSU200D	0xC0B3	/* HSU200D */
45d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_SSU100_2  0xC120	/* SSU100_2 */
46d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_DSU100_2  0xC140	/* DSU100_2 */
47d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_DSU400_2  0xC150	/* DSU400_2 */
48d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_QSU100_2  0xC160	/* QSU100_2 */
49d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_QSU400_2  0xC170	/* QSU400_2 */
50d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_ESU400_2  0xC180	/* ESU400_2 */
51d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_ESU100_2  0xC1A0	/* ESU100_2 */
52d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
53d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_SET_GET_DEVICE           0xc2
54d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_OPEN_CLOSE_CHANNEL       0xca
55d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_GET_SET_PREBUF_TRIG_LVL  0xcc
56d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_SET_ATF                  0xcd
57d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_GET_SET_REGISTER         0xc0
58d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_GET_SET_UART             0xc1
59d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_HW_FLOW_CONTROL_MASK     0xc5
60d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_SW_FLOW_CONTROL_MASK     0xc6
61d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_SW_FLOW_CONTROL_DISABLE  0xc7
62d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_BREAK_CONTROL            0xc8
63d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
64d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define USBD_TRANSFER_DIRECTION_IN    0xc0
65d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define USBD_TRANSFER_DIRECTION_OUT   0x40
66d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
67d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  MAX_BAUD_RATE              460800
68d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  MAX_BAUD_REMAINDER         4608
69d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
70d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  DIV_LATCH_LS               0x00
71d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  XMT_HOLD_REGISTER          0x00
72d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  XVR_BUFFER_REGISTER        0x00
73d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  DIV_LATCH_MS               0x01
74d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  FIFO_CONTROL_REGISTER      0x02
75d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  LINE_CONTROL_REGISTER      0x03
76d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  MODEM_CONTROL_REGISTER     0x04
77d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  LINE_STATUS_REGISTER       0x05
78d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  MODEM_STATUS_REGISTER      0x06
79d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
80d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_MCR_DTR             0x01
81d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_MCR_RTS             0x02
82d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_MCR_LOOP            0x10
83d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
84d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_MSR_CTS             0x10
85d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_MSR_CD              0x80
86d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_MSR_RI              0x40
87d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_MSR_DSR             0x20
88d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_MSR_MASK            0xf0
89d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
90d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_8_DATA              0x03
91d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_7_DATA              0x02
92d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_6_DATA              0x01
93d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_5_DATA              0x00
94d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
95d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_ODD_PARITY          0X08
96d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_EVEN_PARITY         0X18
97d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_TWO_STOPB           0x04
98d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_ONE_STOPB           0x00
99d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
100d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define DEFAULT_DIVISOR  0x30	/* gives 9600 baud rate */
101d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define DEFAULT_LCR SERIAL_8_DATA	/* 8, none , 1 */
102d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
103d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define FULLPWRBIT          0x00000080
104d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define NEXT_BOARD_POWER_BIT        0x00000004
105d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
106d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_LSR_OE       0x02
107d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_LSR_PE       0x04
108d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_LSR_FE       0x08
109d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_LSR_BI       0x10
110d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
111d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_MSR_CTS             0x10
112d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_MSR_CD              0x80
113d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_MSR_RI              0x40
114d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_MSR_DSR             0x20
115d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_MSR_MASK            0xf0
116d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
117d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define PREFUFF_LEVEL_CONSERVATIVE  128
118d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define ATC_DISABLED                0x0
119d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
120d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define RR_BITS             0x03	/* for clearing clock bits */
121d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define DUPMODE_BITS        0xc0
122d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define CLKS_X4             0x02
123d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
124d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define LOOPMODE_BITS       0x41	/* LOOP1 = b6, LOOP0 = b0 (PORT B) */
125d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define ALL_LOOPBACK        0x01
126d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define MODEM_CTRL          0x40
127d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define RS232_MODE          0x00
128d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
129a457732b836b970c82c7ba35b4cfc938c9c543f9Németh Mártonstatic const struct usb_device_id serqt_id_table[] = {
130d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU100)},
131d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU200)},
132d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU100)},
133d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU200)},
134d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU100)},
135d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU200)},
136d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU100A)},
137d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU100B)},
138d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU200A)},
139d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU200B)},
140d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU100A)},
141d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU100B)},
142d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU100C)},
143d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU100D)},
144d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU200A)},
145d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU200B)},
146d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU200C)},
147d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU200D)},
148d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU100_2)},
149d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU100_2)},
150d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU400_2)},
151d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU100_2)},
152d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU400_2)},
153d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU400_2)},
154d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU100_2)},
155d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{}			/* Terminating entry */
156d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton};
157d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
158d75662e164d5175c5e5f9339ff4d6f6980613d96Bill PembertonMODULE_DEVICE_TABLE(usb, serqt_id_table);
159d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
160d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstruct qt_get_device_data {
161d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u8 porta;
162d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u8 portb;
163d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u8 portc;
164d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton};
165d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
166d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstruct qt_open_channel_data {
167d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u8 line_status;
168d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u8 modem_status;
169d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton};
170d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
171d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstruct quatech_port {
172d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int port_num;		/* number of the port */
173d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct urb *write_urb;	/* write URB for this port */
174d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct urb *read_urb;	/* read URB for this port */
175d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct urb *int_urb;
176d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
177d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u8 shadowLCR;		/* last LCR value received */
178d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u8 shadowMCR;		/* last MCR value received */
179d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u8 shadowMSR;		/* last MSR value received */
180d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u8 shadowLSR;		/* last LSR value received */
181d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	char open_ports;
182d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
183d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* Used for TIOCMIWAIT */
184d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	wait_queue_head_t msr_wait;
185d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	char prev_status, diff_status;
186d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
187d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	wait_queue_head_t wait;
188d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
189d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct async_icount icount;
190d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
191d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial_port *port;	/* owner of this object */
192d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct qt_get_device_data DeviceData;
193d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	spinlock_t lock;
194d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	bool read_urb_busy;
195d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int RxHolding;
196d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int ReadBulkStopped;
197d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	char closePending;
198d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton};
199d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
200d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic struct usb_driver serqt_usb_driver = {
201d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.name = "quatech-usb-serial",
202d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.probe = usb_serial_probe,
203d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.disconnect = usb_serial_disconnect,
204d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.id_table = serqt_id_table,
205d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.no_dynamic_id = 1,
206d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton};
207d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
208d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int port_paranoia_check(struct usb_serial_port *port,
209d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			       const char *function)
210d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
211d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!port) {
212d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - port == NULL", function);
213d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -1;
214d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
215d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!port->serial) {
216d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - port->serial == NULL\n", function);
217d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -1;
218d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
219d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
220d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return 0;
221d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
222d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
223d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int serial_paranoia_check(struct usb_serial *serial,
224d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 const char *function)
225d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
226d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!serial) {
227d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - serial == NULL\n", function);
228d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -1;
229d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
230d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
231d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!serial->type) {
232d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - serial->type == NULL!", function);
233d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -1;
234d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
235d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
236d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return 0;
237d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
238d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
239d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic inline struct quatech_port *qt_get_port_private(struct usb_serial_port
240d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton						       *port)
241d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
242d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return (struct quatech_port *)usb_get_serial_port_data(port);
243d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
244d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
245d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic inline void qt_set_port_private(struct usb_serial_port *port,
246d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				       struct quatech_port *data)
247d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
248d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	usb_set_serial_port_data(port, (void *)data);
249d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
250d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
251d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic struct usb_serial *get_usb_serial(struct usb_serial_port *port,
252d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					 const char *function)
253d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
254d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* if no port was specified, or it fails a paranoia check */
255d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!port ||
256d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    port_paranoia_check(port, function) ||
257d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    serial_paranoia_check(port->serial, function)) {
258d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/*
259d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		 * then say that we dont have a valid usb_serial thing,
260d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		 * which will end up genrating -ENODEV return values
261d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		 */
262d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return NULL;
263d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
264d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
265d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return port->serial;
266d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
267d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
268d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void ProcessLineStatus(struct quatech_port *qt_port,
269d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			      unsigned char line_status)
270d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
271d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
272d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	qt_port->shadowLSR =
273d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    line_status & (SERIAL_LSR_OE | SERIAL_LSR_PE | SERIAL_LSR_FE |
274d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			   SERIAL_LSR_BI);
275d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return;
276d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
277d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
278d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void ProcessModemStatus(struct quatech_port *qt_port,
279d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			       unsigned char modem_status)
280d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
281d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
282d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	qt_port->shadowMSR = modem_status;
283d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	wake_up_interruptible(&qt_port->wait);
284d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return;
285d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
286d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
28794362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Coxstatic void ProcessRxChar(struct tty_struct *tty, struct usb_serial_port *port,
28894362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Cox						unsigned char data)
289d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
290d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct urb *urb = port->read_urb;
29194362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Cox	if (urb->actual_length)
29294362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Cox		tty_insert_flip_char(tty, data, TTY_NORMAL);
293d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
294d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
295d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void qt_write_bulk_callback(struct urb *urb)
296d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
297d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct tty_struct *tty;
298d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int status;
299d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *quatech_port;
300d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
301d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status = urb->status;
302d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
303d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (status) {
304d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("nonzero write bulk status received:%d\n", status);
305d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return;
306d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
307d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
308d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	quatech_port = urb->context;
309d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
310d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port %d\n", __func__, quatech_port->port_num);
311d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
312d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	tty = tty_port_tty_get(&quatech_port->port->port);
313d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
314d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (tty)
315d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		tty_wakeup(tty);
316d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	tty_kref_put(tty);
317d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
318d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
319d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void qt_interrupt_callback(struct urb *urb)
320d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
321d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* FIXME */
322d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
323d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
324d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void qt_read_bulk_callback(struct urb *urb)
325d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
326d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
327d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial_port *port = urb->context;
328d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial *serial = get_usb_serial(port, __func__);
329d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *qt_port = qt_get_port_private(port);
330d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned char *data;
331d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct tty_struct *tty;
332d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned int index;
333d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned int RxCount;
334d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int i, result;
335d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int flag, flag_data;
336d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
337d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (urb->status) {
338d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		qt_port->ReadBulkStopped = 1;
339d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - nonzero write bulk status received: %d\n",
340d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    __func__, urb->status);
341d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return;
342d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
343d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
344d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	tty = tty_port_tty_get(&port->port);
345d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!tty) {
346d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - bad tty pointer - exiting", __func__);
347d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return;
348d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
349d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
350d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	data = urb->transfer_buffer;
351d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
352d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	RxCount = urb->actual_length;
353d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
354d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* index = MINOR(port->tty->device) - serial->minor; */
355d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	index = tty->index - serial->minor;
356d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
357d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port %d\n", __func__, port->number);
358d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port->RxHolding = %d\n", __func__, qt_port->RxHolding);
359d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
360d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (port_paranoia_check(port, __func__) != 0) {
361d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - port_paranoia_check, exiting\n", __func__);
362d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		qt_port->ReadBulkStopped = 1;
363f3a756883ac028c536479e2eb283477fec80c828Bill Pemberton		goto exit;
364d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
365d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
366d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!serial) {
367d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - bad serial pointer, exiting\n", __func__);
368f3a756883ac028c536479e2eb283477fec80c828Bill Pemberton		goto exit;
369d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
370d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (qt_port->closePending == 1) {
371d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* Were closing , stop reading */
372d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - (qt_port->closepending == 1\n", __func__);
373d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		qt_port->ReadBulkStopped = 1;
374f3a756883ac028c536479e2eb283477fec80c828Bill Pemberton		goto exit;
375d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
376d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
377d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/*
378d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	 * RxHolding is asserted by throttle, if we assert it, we're not
379d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	 * receiving any more characters and let the box handle the flow
380d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	 * control
381d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	 */
382d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (qt_port->RxHolding == 1) {
383d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		qt_port->ReadBulkStopped = 1;
384f3a756883ac028c536479e2eb283477fec80c828Bill Pemberton		goto exit;
385d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
386d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
387d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (urb->status) {
388d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		qt_port->ReadBulkStopped = 1;
389d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
390d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - nonzero read bulk status received: %d\n",
391d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    __func__, urb->status);
392f3a756883ac028c536479e2eb283477fec80c828Bill Pemberton		goto exit;
393d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
394d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
395d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (tty && RxCount) {
396d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		flag_data = 0;
397d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		for (i = 0; i < RxCount; ++i) {
398d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			/* Look ahead code here */
399d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			if ((i <= (RxCount - 3)) && (data[i] == 0x1b)
400d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    && (data[i + 1] == 0x1b)) {
401d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				flag = 0;
402d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				switch (data[i + 2]) {
403d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				case 0x00:
404d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					/* line status change 4th byte must follow */
405d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					if (i > (RxCount - 4)) {
406d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton						dbg("Illegal escape seuences in received data\n");
407d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton						break;
408d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					}
409d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					ProcessLineStatus(qt_port, data[i + 3]);
410d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					i += 3;
411d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					flag = 1;
412d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					break;
413d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
414d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				case 0x01:
415d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					/* Modem status status change 4th byte must follow */
4161695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev					dbg("Modem status status.\n");
417d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					if (i > (RxCount - 4)) {
418d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton						dbg("Illegal escape sequences in received data\n");
419d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton						break;
420d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					}
421d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					ProcessModemStatus(qt_port,
422d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton							   data[i + 3]);
423d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					i += 3;
424d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					flag = 1;
425d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					break;
426d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				case 0xff:
4271695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev					dbg("No status sequence.\n");
428d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
42994362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Cox					if (tty) {
43094362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Cox						ProcessRxChar(tty, port, data[i]);
43194362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Cox						ProcessRxChar(tty, port, data[i + 1]);
43294362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Cox					}
433d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					i += 2;
434d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					break;
435d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				}
436d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				if (flag == 1)
437d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					continue;
438d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			}
439d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
44094362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Cox			if (tty && urb->actual_length)
44194362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Cox				tty_insert_flip_char(tty, data[i], TTY_NORMAL);
442d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
443d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		}
444d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		tty_flip_buffer_push(tty);
445d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
446d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
447d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* Continue trying to always read  */
448d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	usb_fill_bulk_urb(port->read_urb, serial->dev,
449d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			  usb_rcvbulkpipe(serial->dev,
450d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					  port->bulk_in_endpointAddress),
451d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			  port->read_urb->transfer_buffer,
452d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			  port->read_urb->transfer_buffer_length,
453d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			  qt_read_bulk_callback, port);
454d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
455d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (result)
456d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - failed resubmitting read urb, error %d",
457d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    __func__, result);
458d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	else {
459d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (tty && RxCount) {
460d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			tty_flip_buffer_push(tty);
461d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			tty_schedule_flip(tty);
462d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		}
463d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
464d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
465d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	schedule_work(&port->work);
466f3a756883ac028c536479e2eb283477fec80c828Bill Pembertonexit:
467f3a756883ac028c536479e2eb283477fec80c828Bill Pemberton	tty_kref_put(tty);
468d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
469d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
470d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/*
471d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * qt_get_device
472d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton *   Issue a GET_DEVICE vendor-specific request on the default control pipe If
473d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton *   successful, fills in the qt_get_device_data structure pointed to by
474d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton *   device_data, otherwise return a negative error number of the problem.
475d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton */
476d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
477d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_get_device(struct usb_serial *serial,
478d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			 struct qt_get_device_data *device_data)
479d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
480d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int result;
481d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned char *transfer_buffer;
482d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
483d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	transfer_buffer =
484d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    kmalloc(sizeof(struct qt_get_device_data), GFP_KERNEL);
485d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!transfer_buffer)
486d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -ENOMEM;
487d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
488d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
489d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 QT_SET_GET_DEVICE, 0xc0, 0, 0,
490d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 transfer_buffer,
491d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 sizeof(struct qt_get_device_data), 300);
492d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (result > 0)
493d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		memcpy(device_data, transfer_buffer,
494d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		       sizeof(struct qt_get_device_data));
495d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	kfree(transfer_buffer);
496d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
497d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return result;
498d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
499d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
500d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/****************************************************************************
501d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton *  BoxSetPrebufferLevel
502d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton   TELLS BOX WHEN TO ASSERT FLOW CONTROL
503d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton ****************************************************************************/
504d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int BoxSetPrebufferLevel(struct usb_serial *serial)
505d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
506d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int result;
507d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u16 buffer_length;
508d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
509d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	buffer_length = PREFUFF_LEVEL_CONSERVATIVE;
510d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
511d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 QT_GET_SET_PREBUF_TRIG_LVL, 0x40,
512d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 buffer_length, 0, NULL, 0, 300);
513d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return result;
514d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
515d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
516d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/****************************************************************************
517d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton *  BoxSetATC
518d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton   TELLS BOX WHEN TO ASSERT automatic transmitter control
519d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton   ****************************************************************************/
520d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int BoxSetATC(struct usb_serial *serial, __u16 n_Mode)
521d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
522d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int result;
523d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u16 buffer_length;
524d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
525d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	buffer_length = PREFUFF_LEVEL_CONSERVATIVE;
526d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
527d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result =
528d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
529d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    QT_SET_ATF, 0x40, n_Mode, 0, NULL, 0, 300);
530d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
531d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return result;
532d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
533d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
534d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/**
535d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * qt_set_device
536d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton *   Issue a SET_DEVICE vendor-specific request on the default control pipe If
537d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton *   successful returns the number of bytes written, otherwise it returns a
538d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton *   negative error number of the problem.
539d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton */
540d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_set_device(struct usb_serial *serial,
541d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			 struct qt_get_device_data *device_data)
542d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
543d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int result;
544d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u16 length;
545d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u16 PortSettings;
546d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
547d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	PortSettings = ((__u16) (device_data->portb));
548d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	PortSettings = (PortSettings << 8);
549d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	PortSettings += ((__u16) (device_data->porta));
550d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
551d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	length = sizeof(struct qt_get_device_data);
552d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - PortSettings = 0x%x\n", __func__, PortSettings);
553d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
554d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
555d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 QT_SET_GET_DEVICE, 0x40, PortSettings,
556d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 0, NULL, 0, 300);
557d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return result;
558d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
559d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
560d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_open_channel(struct usb_serial *serial, __u16 Uart_Number,
561d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			   struct qt_open_channel_data *pDeviceData)
562d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
563d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int result;
564d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
565d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
566d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 QT_OPEN_CLOSE_CHANNEL,
567d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 USBD_TRANSFER_DIRECTION_IN, 1, Uart_Number,
568d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 pDeviceData,
569d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 sizeof(struct qt_open_channel_data), 300);
570d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
571d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return result;
572d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
573d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
574d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
575d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_close_channel(struct usb_serial *serial, __u16 Uart_Number)
576d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
577d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int result;
578d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
579d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
580d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 QT_OPEN_CLOSE_CHANNEL,
581d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 USBD_TRANSFER_DIRECTION_OUT, 0, Uart_Number,
582d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 NULL, 0, 300);
583d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
584d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return result;
585d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
586d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
587d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
588d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/****************************************************************************
589d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton* BoxGetRegister
590d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton*	issuse a GET_REGISTER vendor-spcific request on the default control pipe
591d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton*	If successful, fills in the  pValue with the register value asked for
592d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton****************************************************************************/
593d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int BoxGetRegister(struct usb_serial *serial, unsigned short Uart_Number,
594d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			  unsigned short Register_Num, __u8 *pValue)
595d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
596d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int result;
597d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u16 current_length;
598d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
599d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	current_length = sizeof(struct qt_get_device_data);
600d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
601d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result =
602d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
603d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    QT_GET_SET_REGISTER, 0xC0, Register_Num,
604d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    Uart_Number, (void *)pValue, sizeof(*pValue), 300);
605d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
606d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return result;
607d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
608d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
609d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/****************************************************************************
610d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton* BoxSetRegister
611d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton*	issuse a GET_REGISTER vendor-spcific request on the default control pipe
612d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton*	If successful, fills in the  pValue with the register value asked for
613d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton****************************************************************************/
614d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int BoxSetRegister(struct usb_serial *serial, unsigned short Uart_Number,
615d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			  unsigned short Register_Num, unsigned short Value)
616d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
617d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int result;
618d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned short RegAndByte;
619d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
620d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	RegAndByte = Value;
621d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	RegAndByte = RegAndByte << 8;
622d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	RegAndByte = RegAndByte + Register_Num;
623d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
624d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/*
625d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
626d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 QT_GET_SET_REGISTER, 0xC0, Register_Num,
627d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 Uart_Number, NULL, 0, 300);
628d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton*/
629d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
630d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result =
631d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
632d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    QT_GET_SET_REGISTER, 0x40, RegAndByte, Uart_Number,
633d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    NULL, 0, 300);
634d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
635d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return result;
636d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
637d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
638d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/*
639d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * qt_setuart
640d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * issuse a SET_UART vendor-spcific request on the default control pipe
641d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * If successful sets baud rate divisor and LCR value
642d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton */
643d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_setuart(struct usb_serial *serial, unsigned short Uart_Number,
644d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		      unsigned short default_divisor, unsigned char default_LCR)
645d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
646d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int result;
647d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned short UartNumandLCR;
648d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
649d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	UartNumandLCR = (default_LCR << 8) + Uart_Number;
650d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
651d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result =
652d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
653d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    QT_GET_SET_UART, 0x40, default_divisor,
654d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    UartNumandLCR, NULL, 0, 300);
655d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
656d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return result;
657d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
658d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
659d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int BoxSetHW_FlowCtrl(struct usb_serial *serial, unsigned int index,
660d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			     int bSet)
661d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
662d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u8 mcr = 0;
663d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u8 msr = 0, MOUT_Value = 0;
664d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned int status;
665d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
666d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (bSet == 1) {
667d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* flow control, box will clear RTS line to prevent remote */
668d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		mcr = SERIAL_MCR_RTS;
669d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	} /* device from xmitting more chars */
670d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	else {
671d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* no flow control to remote device */
672d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		mcr = 0;
673d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
674d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
675d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	MOUT_Value = mcr << 8;
676d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
677d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (bSet == 1) {
678d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* flow control, box will inhibit xmit data if CTS line is
679d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		 * asserted */
680d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		msr = SERIAL_MSR_CTS;
681d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	} else {
682d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* Box will not inhimbe xmit data due to CTS line */
683d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		msr = 0;
684d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
685d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	MOUT_Value |= msr;
686d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
687d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status =
688d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
689d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    QT_HW_FLOW_CONTROL_MASK, 0x40, MOUT_Value,
690d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    index, NULL, 0, 300);
691d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return status;
692d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
693d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
694d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
695d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int BoxSetSW_FlowCtrl(struct usb_serial *serial, __u16 index,
696d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			     unsigned char stop_char, unsigned char start_char)
697d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
698d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u16 nSWflowout;
699d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int result;
700d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
701d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	nSWflowout = start_char << 8;
702d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	nSWflowout = (unsigned short)stop_char;
703d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
704d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result =
705d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
706d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    QT_SW_FLOW_CONTROL_MASK, 0x40, nSWflowout,
707d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    index, NULL, 0, 300);
708d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return result;
709d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
710d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
711d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
712d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int BoxDisable_SW_FlowCtrl(struct usb_serial *serial, __u16 index)
713d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
714d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int result;
715d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
716d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result =
717d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
718d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    QT_SW_FLOW_CONTROL_DISABLE, 0x40, 0, index,
719d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    NULL, 0, 300);
720d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return result;
721d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
722d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
723d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
724d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_startup(struct usb_serial *serial)
725d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
726d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial_port *port;
727d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *qt_port;
728d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct qt_get_device_data DeviceData;
729d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int i;
730d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int status;
731d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
732d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("enterting %s", __func__);
733d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
734d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* Now setup per port private data */
735d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	for (i = 0; i < serial->num_ports; i++) {
736d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		port = serial->port[i];
737d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		qt_port = kzalloc(sizeof(*qt_port), GFP_KERNEL);
738d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (!qt_port) {
739d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			dbg("%s: kmalloc for quatech_port (%d) failed!.",
740d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    __func__, i);
7411695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev			for (--i; i >= 0; i--) {
742de8f8bd63334fe2014be7d9ab3a81ce9b96e5d19Oliver Neukum				port = serial->port[i];
743de8f8bd63334fe2014be7d9ab3a81ce9b96e5d19Oliver Neukum				kfree(usb_get_serial_port_data(port));
744de8f8bd63334fe2014be7d9ab3a81ce9b96e5d19Oliver Neukum				usb_set_serial_port_data(port, NULL);
745de8f8bd63334fe2014be7d9ab3a81ce9b96e5d19Oliver Neukum			}
746d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			return -ENOMEM;
747d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		}
748d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		spin_lock_init(&qt_port->lock);
749d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
750d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		usb_set_serial_port_data(port, qt_port);
751d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
752d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
753d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
754d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status = qt_get_device(serial, &DeviceData);
755d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (status < 0) {
756d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg(__FILE__ "box_get_device failed");
757d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		goto startup_error;
758d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
759d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
760d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg(__FILE__ "DeviceData.portb = 0x%x", DeviceData.portb);
761d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
762d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	DeviceData.portb &= ~FULLPWRBIT;
763d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg(__FILE__ "Changing DeviceData.portb to 0x%x", DeviceData.portb);
764d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
765d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status = qt_set_device(serial, &DeviceData);
766d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (status < 0) {
767d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg(__FILE__ "qt_set_device failed\n");
768d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		goto startup_error;
769d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
770d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
771d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status = qt_get_device(serial, &DeviceData);
772d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (status < 0) {
773d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg(__FILE__ "qt_get_device failed");
774d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		goto startup_error;
775d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
776d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
777d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	switch (serial->dev->descriptor.idProduct) {
778d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_SSU100:
779d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_DSU100:
780d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_QSU100:
781d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_ESU100A:
782d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_ESU100B:
783d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_HSU100A:
784d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_HSU100B:
785d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_HSU100C:
786d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_HSU100D:
787d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		DeviceData.porta &= ~(RR_BITS | DUPMODE_BITS);
788d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		DeviceData.porta |= CLKS_X4;
789d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		DeviceData.portb &= ~(LOOPMODE_BITS);
790d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		DeviceData.portb |= RS232_MODE;
791d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		break;
792d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
793d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_SSU200:
794d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_DSU200:
795d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_QSU200:
796d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_ESU200A:
797d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_ESU200B:
798d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_HSU200A:
799d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_HSU200B:
800d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_HSU200C:
801d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_HSU200D:
802d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		DeviceData.porta &= ~(RR_BITS | DUPMODE_BITS);
803d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		DeviceData.porta |= CLKS_X4;
804d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		DeviceData.portb &= ~(LOOPMODE_BITS);
805d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		DeviceData.portb |= ALL_LOOPBACK;
806d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		break;
807d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	default:
808d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		DeviceData.porta &= ~(RR_BITS | DUPMODE_BITS);
809d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		DeviceData.porta |= CLKS_X4;
810d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		DeviceData.portb &= ~(LOOPMODE_BITS);
811d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		DeviceData.portb |= RS232_MODE;
812d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		break;
813d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
814d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
815d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
816d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status = BoxSetPrebufferLevel(serial);	/* sets to default value */
817d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (status < 0) {
818d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg(__FILE__ "BoxSetPrebufferLevel failed\n");
819d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		goto startup_error;
820d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
821d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
822d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status = BoxSetATC(serial, ATC_DISABLED);
823d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (status < 0) {
824d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg(__FILE__ "BoxSetATC failed\n");
825d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		goto startup_error;
826d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
827d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
828d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg(__FILE__ "DeviceData.portb = 0x%x", DeviceData.portb);
829d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
830d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	DeviceData.portb |= NEXT_BOARD_POWER_BIT;
831d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg(__FILE__ "Changing DeviceData.portb to 0x%x", DeviceData.portb);
832d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
833d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status = qt_set_device(serial, &DeviceData);
834d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (status < 0) {
835d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg(__FILE__ "qt_set_device failed\n");
836d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		goto startup_error;
837d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
838d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
839d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("Exit Success %s\n", __func__);
840d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
841d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return 0;
842d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
843d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstartup_error:
844d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	for (i = 0; i < serial->num_ports; i++) {
845d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		port = serial->port[i];
846d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		qt_port = qt_get_port_private(port);
847d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		kfree(qt_port);
848d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		usb_set_serial_port_data(port, NULL);
849d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
850d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
851d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("Exit fail %s\n", __func__);
852d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
853d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return -EIO;
854d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
855d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
856d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void qt_release(struct usb_serial *serial)
857d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
858d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial_port *port;
859d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *qt_port;
860d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int i;
861d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
862d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("enterting %s", __func__);
863d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
864d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	for (i = 0; i < serial->num_ports; i++) {
865d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		port = serial->port[i];
866d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (!port)
867d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			continue;
868d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
869d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		qt_port = usb_get_serial_port_data(port);
870d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		kfree(qt_port);
871d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		usb_set_serial_port_data(port, NULL);
872d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
873d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
874d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
875d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
87635e2bed559ab80641f1764aae570d92711ddc2faBill Pembertonstatic int qt_open(struct tty_struct *tty,
8772386b331802b1b2664c35f9f4c7aef778aac725fBill Pemberton		   struct usb_serial_port *port)
878d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
879d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial *serial;
880d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *quatech_port;
881d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *port0;
882d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct qt_open_channel_data ChannelData;
883d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
884d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int result;
885d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
886d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (port_paranoia_check(port, __func__))
887d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -ENODEV;
888d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
889d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port %d\n", __func__, port->number);
890d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
891d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	serial = port->serial;
892d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
893d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (serial_paranoia_check(serial, __func__))
894d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -ENODEV;
895d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
896d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	quatech_port = qt_get_port_private(port);
897d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	port0 = qt_get_port_private(serial->port[0]);
898d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
899d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (quatech_port == NULL || port0 == NULL)
900d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -ENODEV;
901d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
902d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	usb_clear_halt(serial->dev, port->write_urb->pipe);
903d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	usb_clear_halt(serial->dev, port->read_urb->pipe);
904d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	port0->open_ports++;
905d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
906d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result = qt_get_device(serial, &port0->DeviceData);
907d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
908d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* Port specific setups */
909d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result = qt_open_channel(serial, port->number, &ChannelData);
910d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (result < 0) {
911d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg(__FILE__ "qt_open_channel failed\n");
912d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return result;
913d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
914d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg(__FILE__ "qt_open_channel completed.\n");
915d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
916d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/* FIXME: are these needed?  Does it even do anything useful? */
917d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	quatech_port->shadowLSR = ChannelData.line_status &
918d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    (SERIAL_LSR_OE | SERIAL_LSR_PE | SERIAL_LSR_FE | SERIAL_LSR_BI);
919d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
920d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	quatech_port->shadowMSR = ChannelData.modem_status &
921d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    (SERIAL_MSR_CTS | SERIAL_MSR_DSR | SERIAL_MSR_RI | SERIAL_MSR_CD);
922d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
923d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* Set Baud rate to default and turn off (default)flow control here */
924d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result = qt_setuart(serial, port->number, DEFAULT_DIVISOR, DEFAULT_LCR);
925d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (result < 0) {
926d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg(__FILE__ "qt_setuart failed\n");
927d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return result;
928d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
929d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg(__FILE__ "qt_setuart completed.\n");
930d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
931d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/*
932bbc9a9916bc1cd997f3bf303e7930d5f3c804d37André Goddard Rosa	 * Put this here to make it responsive to stty and defaults set by
933d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	 * the tty layer
934d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	 */
935d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* FIXME: is this needed? */
936d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* qt_set_termios(tty, port, NULL); */
937d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
938d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/*  Check to see if we've set up our endpoint info yet */
939d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (port0->open_ports == 1) {
940d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (serial->port[0]->interrupt_in_buffer == NULL) {
941d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			/* set up interrupt urb */
942d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			usb_fill_int_urb(serial->port[0]->interrupt_in_urb,
943d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					 serial->dev,
944d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					 usb_rcvintpipe(serial->dev,
945d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton							serial->port[0]->interrupt_in_endpointAddress),
946d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					 serial->port[0]->interrupt_in_buffer,
947d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					 serial->port[0]->
948d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					 interrupt_in_urb->transfer_buffer_length,
949d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					 qt_interrupt_callback, serial,
950d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					 serial->port[0]->
951d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					 interrupt_in_urb->interval);
952d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
953d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			result =
954d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    usb_submit_urb(serial->port[0]->interrupt_in_urb,
955d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					   GFP_KERNEL);
956d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			if (result) {
957d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				dev_err(&port->dev,
958d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					"%s - Error %d submitting "
959d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					"interrupt urb\n", __func__, result);
960d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			}
961d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
962d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		}
963d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
964d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
965d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
9661695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev	dbg("port number is %d\n", port->number);
9671695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev	dbg("serial number is %d\n", port->serial->minor);
9681695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev	dbg("Bulkin endpoint is %d\n", port->bulk_in_endpointAddress);
9691695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev	dbg("BulkOut endpoint is %d\n", port->bulk_out_endpointAddress);
9701695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev	dbg("Interrupt endpoint is %d\n", port->interrupt_in_endpointAddress);
971d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("port's number in the device is %d\n", quatech_port->port_num);
972d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	quatech_port->read_urb = port->read_urb;
973d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
974d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* set up our bulk in urb */
975d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
976d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	usb_fill_bulk_urb(quatech_port->read_urb,
977d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			  serial->dev,
978d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			  usb_rcvbulkpipe(serial->dev,
979d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					  port->bulk_in_endpointAddress),
980d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			  port->bulk_in_buffer,
981d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			  quatech_port->read_urb->transfer_buffer_length,
982d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			  qt_read_bulk_callback, quatech_port);
983d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
984d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("qt_open: bulkin endpoint is %d\n", port->bulk_in_endpointAddress);
985d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	quatech_port->read_urb_busy = true;
986d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result = usb_submit_urb(quatech_port->read_urb, GFP_KERNEL);
987d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (result) {
988d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dev_err(&port->dev,
989d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			"%s - Error %d submitting control urb\n",
990d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			__func__, result);
991d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		quatech_port->read_urb_busy = false;
992d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
993d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
994d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* initialize our wait queues */
995d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	init_waitqueue_head(&quatech_port->wait);
996d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	init_waitqueue_head(&quatech_port->msr_wait);
997d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
998d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* initialize our icount structure */
999d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	memset(&(quatech_port->icount), 0x00, sizeof(quatech_port->icount));
1000d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1001d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return 0;
1002d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1003d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1004d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1005d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_chars_in_buffer(struct tty_struct *tty)
1006d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1007d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial_port *port = tty->driver_data;
1008d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial *serial;
1009d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int chars = 0;
1010d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1011d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	serial = get_usb_serial(port, __func__);
1012d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1013d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port %d\n", __func__, port->number);
1014d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1015d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (serial->num_bulk_out) {
1016d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (port->write_urb->status == -EINPROGRESS)
1017d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			chars = port->write_urb->transfer_buffer_length;
1018d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1019d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1020d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - returns %d\n", __func__, chars);
1021d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1022d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return chars;
1023d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1024d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1025d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void qt_block_until_empty(struct tty_struct *tty,
1026d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 struct quatech_port *qt_port)
1027d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1028d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int timeout = HZ / 10;
1029d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int wait = 30;
1030d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int count;
1031d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1032d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	while (1) {
1033d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1034d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		count = qt_chars_in_buffer(tty);
1035d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1036d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (count <= 0)
1037d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			return;
1038d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1039d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		interruptible_sleep_on_timeout(&qt_port->wait, timeout);
1040d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1041d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		wait--;
1042d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (wait == 0) {
1043d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			dbg("%s - TIMEOUT", __func__);
1044d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			return;
1045d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		} else {
1046d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			wait = 30;
1047d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		}
1048d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1049d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1050d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1051f3a756883ac028c536479e2eb283477fec80c828Bill Pembertonstatic void qt_close(struct usb_serial_port *port)
1052d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1053d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial *serial = port->serial;
1054d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *qt_port;
1055d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *port0;
1056d9dea3c1c0814a87cc579b425e9776b8ed46b31fBill Pemberton	struct tty_struct *tty;
1057d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int status;
1058d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned int index;
1059d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status = 0;
1060d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1061d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port %d\n", __func__, port->number);
1062d9dea3c1c0814a87cc579b425e9776b8ed46b31fBill Pemberton
1063d9dea3c1c0814a87cc579b425e9776b8ed46b31fBill Pemberton	tty = tty_port_tty_get(&port->port);
1064d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	index = tty->index - serial->minor;
1065d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1066d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	qt_port = qt_get_port_private(port);
1067d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	port0 = qt_get_port_private(serial->port[0]);
1068d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1069d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* shutdown any bulk reads that might be going on */
1070d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (serial->num_bulk_out)
1071d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		usb_unlink_urb(port->write_urb);
1072d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (serial->num_bulk_in)
1073d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		usb_unlink_urb(port->read_urb);
1074d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1075d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* wait up to for transmitter to empty */
1076d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (serial->dev)
1077d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		qt_block_until_empty(tty, qt_port);
1078f3a756883ac028c536479e2eb283477fec80c828Bill Pemberton	tty_kref_put(tty);
1079d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1080d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* Close uart channel */
1081d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status = qt_close_channel(serial, index);
1082d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (status < 0)
1083d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - port %d qt_close_channel failed.\n",
1084d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    __func__, port->number);
1085d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1086d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	port0->open_ports--;
1087d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1088d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("qt_num_open_ports in close%d:in port%d\n",
1089d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    port0->open_ports, port->number);
1090d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1091d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (port0->open_ports == 0) {
1092d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (serial->port[0]->interrupt_in_urb) {
1093d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			dbg("%s", "Shutdown interrupt_in_urb\n");
1094d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			usb_kill_urb(serial->port[0]->interrupt_in_urb);
1095d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		}
1096d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1097d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1098d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1099d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (qt_port->write_urb) {
1100d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* if this urb had a transfer buffer already (old tx) free it */
1101d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (qt_port->write_urb->transfer_buffer != NULL)
1102d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			kfree(qt_port->write_urb->transfer_buffer);
1103d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		usb_free_urb(qt_port->write_urb);
1104d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1105d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1106d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1107d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1108d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_write(struct tty_struct *tty, struct usb_serial_port *port,
1109d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    const unsigned char *buf, int count)
1110d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1111d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int result;
1112d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial *serial = get_usb_serial(port, __func__);
1113d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1114d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (serial == NULL)
1115d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -ENODEV;
1116d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1117d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port %d\n", __func__, port->number);
1118d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1119d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (count == 0) {
1120d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - write request of 0 bytes\n", __func__);
1121d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return 0;
1122d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1123d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1124d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* only do something if we have a bulk out endpoint */
1125d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (serial->num_bulk_out) {
1126d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (port->write_urb->status == -EINPROGRESS) {
1127d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			dbg("%s - already writing\n", __func__);
1128d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			return 0;
1129d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		}
1130d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1131d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		count =
1132d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    (count > port->bulk_out_size) ? port->bulk_out_size : count;
1133d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		memcpy(port->write_urb->transfer_buffer, buf, count);
1134d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1135d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* set up our urb */
1136d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1137d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		usb_fill_bulk_urb(port->write_urb, serial->dev,
1138d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				  usb_sndbulkpipe(serial->dev,
1139d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton						  port->
1140d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton						  bulk_out_endpointAddress),
1141d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				  port->write_urb->transfer_buffer, count,
1142d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				  qt_write_bulk_callback, port);
1143d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1144d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* send the data out the bulk port */
1145d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
1146d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (result)
1147d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			dbg("%s - failed submitting write urb, error %d\n",
1148d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    __func__, result);
1149d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		else
1150d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			result = count;
1151d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1152d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return result;
1153d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1154d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1155d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* no bulk out, so return 0 bytes written */
1156d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return 0;
1157d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1158d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1159d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_write_room(struct tty_struct *tty)
1160d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1161d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial_port *port = tty->driver_data;
1162d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial *serial;
1163d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *qt_port;
1164d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned long flags;
1165d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1166d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int retval = -EINVAL;
1167d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1168d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (port_paranoia_check(port, __func__)) {
1169d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s", "Invalid port\n");
1170d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -1;
1171d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1172d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1173d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	serial = get_usb_serial(port, __func__);
1174d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1175d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!serial)
1176d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -ENODEV;
1177d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1178d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	qt_port = qt_get_port_private(port);
1179d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1180d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	spin_lock_irqsave(&qt_port->lock, flags);
1181d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1182d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port %d\n", __func__, port->number);
1183d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1184d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (serial->num_bulk_out) {
1185d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (port->write_urb->status != -EINPROGRESS)
1186d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			retval = port->bulk_out_size;
1187d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1188d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1189d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	spin_unlock_irqrestore(&qt_port->lock, flags);
1190d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return retval;
1191d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1192d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1193d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1194d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_ioctl(struct tty_struct *tty, struct file *file,
1195d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    unsigned int cmd, unsigned long arg)
1196d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1197d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial_port *port = tty->driver_data;
1198d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *qt_port = qt_get_port_private(port);
1199d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial *serial = get_usb_serial(port, __func__);
1200d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned int index;
1201d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1202d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s cmd 0x%04x", __func__, cmd);
1203d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1204d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	index = tty->index - serial->minor;
1205d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1206d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (cmd == TIOCMIWAIT) {
1207d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		while (qt_port != NULL) {
1208d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			interruptible_sleep_on(&qt_port->msr_wait);
1209d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			if (signal_pending(current))
1210d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				return -ERESTARTSYS;
1211d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			else {
1212d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				char diff = qt_port->diff_status;
1213d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1214d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				if (diff == 0)
1215d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					return -EIO;	/* no change => error */
1216d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1217d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				/* Consume all events */
1218d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				qt_port->diff_status = 0;
1219d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1220d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				if (((arg & TIOCM_RNG)
1221d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				     && (diff & SERIAL_MSR_RI))
1222d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				    || ((arg & TIOCM_DSR)
1223d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					&& (diff & SERIAL_MSR_DSR))
1224d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				    || ((arg & TIOCM_CD)
1225d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					&& (diff & SERIAL_MSR_CD))
1226d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				    || ((arg & TIOCM_CTS)
1227d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					&& (diff & SERIAL_MSR_CTS))) {
1228d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					return 0;
1229d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				}
1230d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			}
1231d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		}
1232d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return 0;
1233d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1234d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1235d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s -No ioctl for that one.  port = %d\n", __func__, port->number);
1236d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return -ENOIOCTLCMD;
1237d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1238d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1239d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void qt_set_termios(struct tty_struct *tty,
1240d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			   struct usb_serial_port *port,
1241d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			   struct ktermios *old_termios)
1242d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1243d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct ktermios *termios = tty->termios;
1244d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned char new_LCR = 0;
1245d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned int cflag = termios->c_cflag;
1246d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned int index;
1247d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int baud, divisor, remainder;
1248d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int status;
1249d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1250d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s", __func__);
1251d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1252d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	index = tty->index - port->serial->minor;
1253d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1254d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	switch (cflag) {
1255d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case CS5:
1256d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		new_LCR |= SERIAL_5_DATA;
1257d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		break;
1258d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case CS6:
1259d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		new_LCR |= SERIAL_6_DATA;
1260d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		break;
1261d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case CS7:
1262d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		new_LCR |= SERIAL_7_DATA;
1263d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		break;
1264d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	default:
1265d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case CS8:
1266d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		new_LCR |= SERIAL_8_DATA;
1267d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		break;
1268d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1269d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1270d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* Parity stuff */
1271d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (cflag & PARENB) {
1272d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (cflag & PARODD)
1273d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			new_LCR |= SERIAL_ODD_PARITY;
1274d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		else
1275d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			new_LCR |= SERIAL_EVEN_PARITY;
1276d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1277d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (cflag & CSTOPB)
1278d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		new_LCR |= SERIAL_TWO_STOPB;
1279d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	else
128035f077dca73132dcac2cac1706417229a68f38c3Roel Kluin		new_LCR |= SERIAL_ONE_STOPB;
1281d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1282d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - 4\n", __func__);
1283d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1284d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* Thats the LCR stuff, go ahead and set it */
1285d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	baud = tty_get_baud_rate(tty);
1286d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!baud)
1287d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* pick a default, any default... */
1288d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		baud = 9600;
1289d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1290d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - got baud = %d\n", __func__, baud);
1291d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1292d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	divisor = MAX_BAUD_RATE / baud;
1293d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	remainder = MAX_BAUD_RATE % baud;
1294d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* Round to nearest divisor */
1295d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (((remainder * 2) >= baud) && (baud != 110))
1296d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		divisor++;
1297d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1298d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/*
1299d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	 * Set Baud rate to default and turn off (default)flow control here
1300d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	 */
1301d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status =
1302d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    qt_setuart(port->serial, index, (unsigned short)divisor, new_LCR);
1303d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (status < 0) {
1304d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg(__FILE__ "qt_setuart failed\n");
1305d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return;
1306d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1307d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1308d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* Now determine flow control */
1309d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (cflag & CRTSCTS) {
1310d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - Enabling HW flow control port %d\n", __func__,
1311d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    port->number);
1312d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1313d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* Enable RTS/CTS flow control */
1314d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		status = BoxSetHW_FlowCtrl(port->serial, index, 1);
1315d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1316d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (status < 0) {
1317d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			dbg(__FILE__ "BoxSetHW_FlowCtrl failed\n");
1318d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			return;
1319d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		}
1320d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	} else {
1321d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* Disable RTS/CTS flow control */
1322d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - disabling HW flow control port %d\n", __func__,
1323d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    port->number);
1324d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1325d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		status = BoxSetHW_FlowCtrl(port->serial, index, 0);
1326d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (status < 0) {
1327d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			dbg(__FILE__ "BoxSetHW_FlowCtrl failed\n");
1328d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			return;
1329d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		}
1330d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1331d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1332d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1333d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* if we are implementing XON/XOFF, set the start and stop character in
1334d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	 * the device */
1335d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (I_IXOFF(tty) || I_IXON(tty)) {
1336d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		unsigned char stop_char = STOP_CHAR(tty);
1337d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		unsigned char start_char = START_CHAR(tty);
1338d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		status =
1339d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    BoxSetSW_FlowCtrl(port->serial, index, stop_char,
1340d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				      start_char);
1341d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (status < 0)
1342d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			dbg(__FILE__ "BoxSetSW_FlowCtrl (enabled) failed\n");
1343d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1344d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	} else {
1345d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* disable SW flow control */
1346d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		status = BoxDisable_SW_FlowCtrl(port->serial, index);
1347d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (status < 0)
1348d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			dbg(__FILE__ "BoxSetSW_FlowCtrl (diabling) failed\n");
1349d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1350d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1351d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	tty->termios->c_cflag &= ~CMSPAR;
1352d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* FIXME: Error cases should be returning the actual bits changed only */
1353d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1354d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1355d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void qt_break(struct tty_struct *tty, int break_state)
1356d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1357d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial_port *port = tty->driver_data;
1358d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial *serial = get_usb_serial(port, __func__);
1359d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *qt_port;
1360d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	u16 index, onoff;
1361d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned int result;
1362d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned long flags;
1363d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1364d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	index = tty->index - serial->minor;
1365d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1366d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	qt_port = qt_get_port_private(port);
1367d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1368d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (break_state == -1)
1369d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		onoff = 1;
1370d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	else
1371d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		onoff = 0;
1372d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1373d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	spin_lock_irqsave(&qt_port->lock, flags);
1374d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1375d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port %d\n", __func__, port->number);
1376d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1377d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result =
1378d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
1379d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    QT_BREAK_CONTROL, 0x40, onoff, index, NULL, 0, 300);
1380d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1381d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	spin_unlock_irqrestore(&qt_port->lock, flags);
1382d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1383d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1384d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic inline int qt_real_tiocmget(struct tty_struct *tty,
1385d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				   struct usb_serial_port *port,
138660b33c133ca0b7c0b6072c87234b63fee6e80558Alan Cox				   struct usb_serial *serial)
1387d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1388d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1389d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	u8 mcr;
1390d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	u8 msr;
1391d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned int result = 0;
1392d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int status;
1393d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned int index;
1394d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1395d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port %d, tty =0x%p\n", __func__, port->number, tty);
1396d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1397d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	index = tty->index - serial->minor;
1398d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status =
1399d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    BoxGetRegister(port->serial, index, MODEM_CONTROL_REGISTER, &mcr);
1400d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (status >= 0) {
1401d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		status =
1402d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    BoxGetRegister(port->serial, index,
1403d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				   MODEM_STATUS_REGISTER, &msr);
1404d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1405d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1406d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1407d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (status >= 0) {
1408d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		result = ((mcr & SERIAL_MCR_DTR) ? TIOCM_DTR : 0)
1409d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    /* DTR IS SET */
1410d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    | ((mcr & SERIAL_MCR_RTS) ? TIOCM_RTS : 0)
1411d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    /* RTS IS SET */
1412d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    | ((msr & SERIAL_MSR_CTS) ? TIOCM_CTS : 0)
1413d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    /* CTS is set */
1414d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    | ((msr & SERIAL_MSR_CD) ? TIOCM_CAR : 0)
1415d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    /* Carrier detect is set */
1416d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    | ((msr & SERIAL_MSR_RI) ? TIOCM_RI : 0)
1417d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    /* Ring indicator set */
1418d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    | ((msr & SERIAL_MSR_DSR) ? TIOCM_DSR : 0);
1419d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* DSR is set */
1420d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return result;
1421d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1422d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	} else
1423d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -ESPIPE;
1424d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1425d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1426d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic inline int qt_real_tiocmset(struct tty_struct *tty,
1427d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				   struct usb_serial_port *port,
1428d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				   struct usb_serial *serial,
1429d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				   unsigned int value)
1430d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1431d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1432d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	u8 mcr;
1433d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int status;
1434d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned int index;
1435d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1436d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port %d\n", __func__, port->number);
1437d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1438d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	index = tty->index - serial->minor;
1439d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status =
1440d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    BoxGetRegister(port->serial, index, MODEM_CONTROL_REGISTER, &mcr);
1441d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (status < 0)
1442d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -ESPIPE;
1443d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1444d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/*
1445d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	 * Turn off the RTS and DTR and loopbcck and then only turn on what was
1446d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	 * asked for
1447d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	 */
1448d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	mcr &= ~(SERIAL_MCR_RTS | SERIAL_MCR_DTR | SERIAL_MCR_LOOP);
1449d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (value & TIOCM_RTS)
1450d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		mcr |= SERIAL_MCR_RTS;
1451d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (value & TIOCM_DTR)
1452d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		mcr |= SERIAL_MCR_DTR;
1453d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (value & TIOCM_LOOP)
1454d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		mcr |= SERIAL_MCR_LOOP;
1455d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1456d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status =
1457d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    BoxSetRegister(port->serial, index, MODEM_CONTROL_REGISTER, mcr);
1458d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (status < 0)
1459d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -ESPIPE;
1460d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	else
1461d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return 0;
1462d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1463d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
146460b33c133ca0b7c0b6072c87234b63fee6e80558Alan Coxstatic int qt_tiocmget(struct tty_struct *tty)
1465d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1466d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial_port *port = tty->driver_data;
1467d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial *serial = get_usb_serial(port, __func__);
1468d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *qt_port = qt_get_port_private(port);
1469d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int retval = -ENODEV;
1470d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned long flags;
1471d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
14721695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev	dbg("In %s\n", __func__);
1473d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1474d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!serial)
1475d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -ENODEV;
1476d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1477d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	spin_lock_irqsave(&qt_port->lock, flags);
1478d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1479d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port %d\n", __func__, port->number);
1480d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port->RxHolding = %d\n", __func__, qt_port->RxHolding);
1481d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
148260b33c133ca0b7c0b6072c87234b63fee6e80558Alan Cox	retval = qt_real_tiocmget(tty, port, serial);
1483d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1484d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	spin_unlock_irqrestore(&qt_port->lock, flags);
1485d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return retval;
1486d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1487d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
148820b9d17715017ae4dd4ec87fabc36d33b9de708eAlan Coxstatic int qt_tiocmset(struct tty_struct *tty,
1489d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		       unsigned int set, unsigned int clear)
1490d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1491d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1492d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial_port *port = tty->driver_data;
1493d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial *serial = get_usb_serial(port, __func__);
1494d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *qt_port = qt_get_port_private(port);
1495d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned long flags;
1496d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int retval = -ENODEV;
1497d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
14981695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev	dbg("In %s\n", __func__);
1499d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1500d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!serial)
1501d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -ENODEV;
1502d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1503d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	spin_lock_irqsave(&qt_port->lock, flags);
1504d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
15051695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev	dbg("%s - port %d\n", __func__, port->number);
1506d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - qt_port->RxHolding = %d\n", __func__, qt_port->RxHolding);
1507d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
150820b9d17715017ae4dd4ec87fabc36d33b9de708eAlan Cox	retval = qt_real_tiocmset(tty, port, serial, set);
1509d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1510d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	spin_unlock_irqrestore(&qt_port->lock, flags);
1511d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return retval;
1512d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1513d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1514d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void qt_throttle(struct tty_struct *tty)
1515d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1516d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial_port *port = tty->driver_data;
1517d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial *serial = get_usb_serial(port, __func__);
1518d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *qt_port;
1519d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned long flags;
1520d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1521d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port %d\n", __func__, port->number);
1522d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1523d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!serial)
1524d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return;
1525d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1526d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	qt_port = qt_get_port_private(port);
1527d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1528d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	spin_lock_irqsave(&qt_port->lock, flags);
1529d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1530d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* pass on to the driver specific version of this function */
1531d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	qt_port->RxHolding = 1;
1532d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port->RxHolding = 1\n", __func__);
1533d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1534d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	spin_unlock_irqrestore(&qt_port->lock, flags);
1535d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return;
1536d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1537d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1538d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void qt_unthrottle(struct tty_struct *tty)
1539d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1540d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial_port *port = tty->driver_data;
1541d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial *serial = get_usb_serial(port, __func__);
1542d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *qt_port;
1543d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned long flags;
1544d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned int result;
1545d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1546d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!serial)
1547d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return;
1548d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1549d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	qt_port = qt_get_port_private(port);
1550d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1551d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	spin_lock_irqsave(&qt_port->lock, flags);
1552d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1553d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port %d\n", __func__, port->number);
1554d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1555d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (qt_port->RxHolding == 1) {
1556d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s -qt_port->RxHolding == 1\n", __func__);
1557d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1558d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		qt_port->RxHolding = 0;
1559d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - qt_port->RxHolding = 0\n", __func__);
1560d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1561d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* if we have a bulk endpoint, start it up */
1562d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if ((serial->num_bulk_in) && (qt_port->ReadBulkStopped == 1)) {
1563d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			/* Start reading from the device */
1564d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			usb_fill_bulk_urb(port->read_urb, serial->dev,
1565d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					  usb_rcvbulkpipe(serial->dev,
1566d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton							  port->bulk_in_endpointAddress),
1567d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					  port->read_urb->transfer_buffer,
1568d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					  port->read_urb->
1569d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					  transfer_buffer_length,
1570d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					  qt_read_bulk_callback, port);
1571d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
1572d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			if (result)
1573d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				err("%s - failed restarting read urb, error %d",
1574d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				    __func__, result);
1575d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		}
1576d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1577d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	spin_unlock_irqrestore(&qt_port->lock, flags);
1578d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return;
1579d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1580d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1581d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1582d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_calc_num_ports(struct usb_serial *serial)
1583d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1584d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int num_ports;
1585d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
15861695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev	dbg("numberofendpoints: %d\n",
1587d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    (int)serial->interface->cur_altsetting->desc.bNumEndpoints);
15881695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev	dbg("numberofendpoints: %d\n",
1589d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    (int)serial->interface->altsetting->desc.bNumEndpoints);
1590d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1591d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	num_ports =
1592d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    (serial->interface->cur_altsetting->desc.bNumEndpoints - 1) / 2;
1593d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1594d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return num_ports;
1595d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1596d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1597d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic struct usb_serial_driver quatech_device = {
1598d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.driver = {
1599d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		   .owner = THIS_MODULE,
1600d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		   .name = "serqt",
1601d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		   },
1602d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.description = DRIVER_DESC,
1603d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.usb_driver = &serqt_usb_driver,
1604d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.id_table = serqt_id_table,
1605d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.num_ports = 8,
1606d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.open = qt_open,
1607d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.close = qt_close,
1608d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.write = qt_write,
1609d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.write_room = qt_write_room,
1610d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.chars_in_buffer = qt_chars_in_buffer,
1611d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.throttle = qt_throttle,
1612d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.unthrottle = qt_unthrottle,
1613d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.calc_num_ports = qt_calc_num_ports,
1614d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.ioctl = qt_ioctl,
1615d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.set_termios = qt_set_termios,
1616d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.break_ctl = qt_break,
1617d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.tiocmget = qt_tiocmget,
1618d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.tiocmset = qt_tiocmset,
1619d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.attach = qt_startup,
1620d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.release = qt_release,
1621d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton};
1622d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1623d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int __init serqt_usb_init(void)
1624d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1625d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int retval;
1626d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1627d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s\n", __func__);
1628d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1629d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* register with usb-serial */
1630d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	retval = usb_serial_register(&quatech_device);
1631d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1632d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (retval)
1633d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		goto failed_usb_serial_register;
1634d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1635d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
1636d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	       DRIVER_DESC "\n");
1637d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1638d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* register with usb */
1639d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1640d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	retval = usb_register(&serqt_usb_driver);
1641d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (retval == 0)
1642d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return 0;
1643d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1644d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* if we're here, usb_register() failed */
1645d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	usb_serial_deregister(&quatech_device);
1646d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonfailed_usb_serial_register:
1647d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return retval;
1648d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1649d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1650d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void __exit serqt_usb_exit(void)
1651d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1652d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	usb_deregister(&serqt_usb_driver);
1653d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	usb_serial_deregister(&quatech_device);
1654d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1655d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1656d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonmodule_init(serqt_usb_init);
1657d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonmodule_exit(serqt_usb_exit);
1658d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1659d75662e164d5175c5e5f9339ff4d6f6980613d96Bill PembertonMODULE_AUTHOR(DRIVER_AUTHOR);
1660d75662e164d5175c5e5f9339ff4d6f6980613d96Bill PembertonMODULE_DESCRIPTION(DRIVER_DESC);
1661d75662e164d5175c5e5f9339ff4d6f6980613d96Bill PembertonMODULE_LICENSE("GPL");
1662d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1663d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonmodule_param(debug, bool, S_IRUGO | S_IWUSR);
1664d75662e164d5175c5e5f9339ff4d6f6980613d96Bill PembertonMODULE_PARM_DESC(debug, "Debug enabled or not");
1665