xref: /openbmc/linux/drivers/usb/serial/io_ti.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds /*
2*1da177e4SLinus Torvalds  * Edgeport USB Serial Converter driver
3*1da177e4SLinus Torvalds  *
4*1da177e4SLinus Torvalds  * Copyright (C) 2000-2002 Inside Out Networks, All rights reserved.
5*1da177e4SLinus Torvalds  * Copyright (C) 2001-2002 Greg Kroah-Hartman <greg@kroah.com>
6*1da177e4SLinus Torvalds  *
7*1da177e4SLinus Torvalds  *	This program is free software; you can redistribute it and/or modify
8*1da177e4SLinus Torvalds  *	it under the terms of the GNU General Public License as published by
9*1da177e4SLinus Torvalds  *	the Free Software Foundation; either version 2 of the License, or
10*1da177e4SLinus Torvalds  *	(at your option) any later version.
11*1da177e4SLinus Torvalds  *
12*1da177e4SLinus Torvalds  * Supports the following devices:
13*1da177e4SLinus Torvalds  *	EP/1 EP/2 EP/4 EP/21 EP/22 EP/221 EP/42 EP/421 WATCHPORT
14*1da177e4SLinus Torvalds  *
15*1da177e4SLinus Torvalds  * For questions or problems with this driver, contact Inside Out
16*1da177e4SLinus Torvalds  * Networks technical support, or Peter Berger <pberger@brimson.com>,
17*1da177e4SLinus Torvalds  * or Al Borchers <alborchers@steinerpoint.com>.
18*1da177e4SLinus Torvalds  *
19*1da177e4SLinus Torvalds  * Version history:
20*1da177e4SLinus Torvalds  *
21*1da177e4SLinus Torvalds  *	July 11, 2002 	Removed 4 port device structure since all TI UMP
22*1da177e4SLinus Torvalds  *			chips have only 2 ports
23*1da177e4SLinus Torvalds  *			David Iacovelli (davidi@ionetworks.com)
24*1da177e4SLinus Torvalds  *
25*1da177e4SLinus Torvalds  */
26*1da177e4SLinus Torvalds 
27*1da177e4SLinus Torvalds #include <linux/config.h>
28*1da177e4SLinus Torvalds #include <linux/kernel.h>
29*1da177e4SLinus Torvalds #include <linux/jiffies.h>
30*1da177e4SLinus Torvalds #include <linux/errno.h>
31*1da177e4SLinus Torvalds #include <linux/init.h>
32*1da177e4SLinus Torvalds #include <linux/slab.h>
33*1da177e4SLinus Torvalds #include <linux/tty.h>
34*1da177e4SLinus Torvalds #include <linux/tty_driver.h>
35*1da177e4SLinus Torvalds #include <linux/tty_flip.h>
36*1da177e4SLinus Torvalds #include <linux/module.h>
37*1da177e4SLinus Torvalds #include <linux/spinlock.h>
38*1da177e4SLinus Torvalds #include <linux/serial.h>
39*1da177e4SLinus Torvalds #include <linux/ioctl.h>
40*1da177e4SLinus Torvalds #include <asm/uaccess.h>
41*1da177e4SLinus Torvalds #include <asm/semaphore.h>
42*1da177e4SLinus Torvalds #include <linux/usb.h>
43*1da177e4SLinus Torvalds 
44*1da177e4SLinus Torvalds #include "usb-serial.h"
45*1da177e4SLinus Torvalds #include "io_16654.h"
46*1da177e4SLinus Torvalds #include "io_usbvend.h"
47*1da177e4SLinus Torvalds #include "io_ti.h"
48*1da177e4SLinus Torvalds 
49*1da177e4SLinus Torvalds /*
50*1da177e4SLinus Torvalds  * Version Information
51*1da177e4SLinus Torvalds  */
52*1da177e4SLinus Torvalds #define DRIVER_VERSION "v0.7"
53*1da177e4SLinus Torvalds #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli"
54*1da177e4SLinus Torvalds #define DRIVER_DESC "Edgeport USB Serial Driver"
55*1da177e4SLinus Torvalds 
56*1da177e4SLinus Torvalds 
57*1da177e4SLinus Torvalds /* firmware image code */
58*1da177e4SLinus Torvalds #define IMAGE_VERSION_NAME	PagableOperationalCodeImageVersion
59*1da177e4SLinus Torvalds #define IMAGE_ARRAY_NAME	PagableOperationalCodeImage
60*1da177e4SLinus Torvalds #define IMAGE_SIZE		PagableOperationalCodeSize
61*1da177e4SLinus Torvalds #include "io_fw_down3.h"	/* Define array OperationalCodeImage[] */
62*1da177e4SLinus Torvalds 
63*1da177e4SLinus Torvalds #define EPROM_PAGE_SIZE		64
64*1da177e4SLinus Torvalds 
65*1da177e4SLinus Torvalds 
66*1da177e4SLinus Torvalds struct edgeport_uart_buf_desc {
67*1da177e4SLinus Torvalds 	__u32 count;		// Number of bytes currently in buffer
68*1da177e4SLinus Torvalds };
69*1da177e4SLinus Torvalds 
70*1da177e4SLinus Torvalds /* different hardware types */
71*1da177e4SLinus Torvalds #define HARDWARE_TYPE_930	0
72*1da177e4SLinus Torvalds #define HARDWARE_TYPE_TIUMP	1
73*1da177e4SLinus Torvalds 
74*1da177e4SLinus Torvalds // IOCTL_PRIVATE_TI_GET_MODE Definitions
75*1da177e4SLinus Torvalds #define	TI_MODE_CONFIGURING	0   // Device has not entered start device
76*1da177e4SLinus Torvalds #define	TI_MODE_BOOT		1   // Staying in boot mode
77*1da177e4SLinus Torvalds #define TI_MODE_DOWNLOAD	2   // Made it to download mode
78*1da177e4SLinus Torvalds #define TI_MODE_TRANSITIONING	3   // Currently in boot mode but transitioning to download mode
79*1da177e4SLinus Torvalds 
80*1da177e4SLinus Torvalds /* read urb state */
81*1da177e4SLinus Torvalds #define EDGE_READ_URB_RUNNING	0
82*1da177e4SLinus Torvalds #define EDGE_READ_URB_STOPPING	1
83*1da177e4SLinus Torvalds #define EDGE_READ_URB_STOPPED	2
84*1da177e4SLinus Torvalds 
85*1da177e4SLinus Torvalds #define EDGE_LOW_LATENCY	1
86*1da177e4SLinus Torvalds #define EDGE_CLOSING_WAIT	4000	/* in .01 sec */
87*1da177e4SLinus Torvalds 
88*1da177e4SLinus Torvalds #define EDGE_OUT_BUF_SIZE	1024
89*1da177e4SLinus Torvalds 
90*1da177e4SLinus Torvalds 
91*1da177e4SLinus Torvalds /* Product information read from the Edgeport */
92*1da177e4SLinus Torvalds struct product_info
93*1da177e4SLinus Torvalds {
94*1da177e4SLinus Torvalds 	int	TiMode;			// Current TI Mode
95*1da177e4SLinus Torvalds 	__u8	hardware_type;		// Type of hardware
96*1da177e4SLinus Torvalds } __attribute__((packed));
97*1da177e4SLinus Torvalds 
98*1da177e4SLinus Torvalds /* circular buffer */
99*1da177e4SLinus Torvalds struct edge_buf {
100*1da177e4SLinus Torvalds 	unsigned int	buf_size;
101*1da177e4SLinus Torvalds 	char		*buf_buf;
102*1da177e4SLinus Torvalds 	char		*buf_get;
103*1da177e4SLinus Torvalds 	char		*buf_put;
104*1da177e4SLinus Torvalds };
105*1da177e4SLinus Torvalds 
106*1da177e4SLinus Torvalds struct edgeport_port {
107*1da177e4SLinus Torvalds 	__u16 uart_base;
108*1da177e4SLinus Torvalds 	__u16 dma_address;
109*1da177e4SLinus Torvalds 	__u8 shadow_msr;
110*1da177e4SLinus Torvalds 	__u8 shadow_mcr;
111*1da177e4SLinus Torvalds 	__u8 shadow_lsr;
112*1da177e4SLinus Torvalds 	__u8 lsr_mask;
113*1da177e4SLinus Torvalds 	__u32 ump_read_timeout;		/* Number of miliseconds the UMP will
114*1da177e4SLinus Torvalds 					   wait without data before completing
115*1da177e4SLinus Torvalds 					   a read short */
116*1da177e4SLinus Torvalds 	int baud_rate;
117*1da177e4SLinus Torvalds 	int close_pending;
118*1da177e4SLinus Torvalds 	int lsr_event;
119*1da177e4SLinus Torvalds 	struct edgeport_uart_buf_desc tx;
120*1da177e4SLinus Torvalds 	struct async_icount	icount;
121*1da177e4SLinus Torvalds 	wait_queue_head_t	delta_msr_wait;	/* for handling sleeping while
122*1da177e4SLinus Torvalds 						   waiting for msr change to
123*1da177e4SLinus Torvalds 						   happen */
124*1da177e4SLinus Torvalds 	struct edgeport_serial	*edge_serial;
125*1da177e4SLinus Torvalds 	struct usb_serial_port	*port;
126*1da177e4SLinus Torvalds 	__u8 bUartMode;		/* Port type, 0: RS232, etc. */
127*1da177e4SLinus Torvalds 	spinlock_t ep_lock;
128*1da177e4SLinus Torvalds 	int ep_read_urb_state;
129*1da177e4SLinus Torvalds 	int ep_write_urb_in_use;
130*1da177e4SLinus Torvalds 	struct edge_buf *ep_out_buf;
131*1da177e4SLinus Torvalds };
132*1da177e4SLinus Torvalds 
133*1da177e4SLinus Torvalds struct edgeport_serial {
134*1da177e4SLinus Torvalds 	struct product_info product_info;
135*1da177e4SLinus Torvalds 	u8 TI_I2C_Type;			// Type of I2C in UMP
136*1da177e4SLinus Torvalds 	u8 TiReadI2C;			// Set to TRUE if we have read the I2c in Boot Mode
137*1da177e4SLinus Torvalds 	struct semaphore es_sem;
138*1da177e4SLinus Torvalds 	int num_ports_open;
139*1da177e4SLinus Torvalds 	struct usb_serial *serial;
140*1da177e4SLinus Torvalds };
141*1da177e4SLinus Torvalds 
142*1da177e4SLinus Torvalds 
143*1da177e4SLinus Torvalds /* Devices that this driver supports */
144*1da177e4SLinus Torvalds static struct usb_device_id edgeport_1port_id_table [] = {
145*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_1) },
146*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_TI3410_EDGEPORT_1) },
147*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_TI3410_EDGEPORT_1I) },
148*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_PROXIMITY) },
149*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_MOTION) },
150*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_MOISTURE) },
151*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_TEMPERATURE) },
152*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_HUMIDITY) },
153*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_POWER) },
154*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_LIGHT) },
155*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_RADIATION) },
156*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_DISTANCE) },
157*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_ACCELERATION) },
158*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_PROX_DIST) },
159*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_PLUS_PWR_HP4CD) },
160*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_PLUS_PWR_PCI) },
161*1da177e4SLinus Torvalds 	{ }
162*1da177e4SLinus Torvalds };
163*1da177e4SLinus Torvalds 
164*1da177e4SLinus Torvalds static struct usb_device_id edgeport_2port_id_table [] = {
165*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2) },
166*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2C) },
167*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2I) },
168*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421) },
169*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21) },
170*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_42) },
171*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4) },
172*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4I) },
173*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22I) },
174*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_221C) },
175*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22C) },
176*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21C) },
177*1da177e4SLinus Torvalds // The 4-port shows up as two 2-port devices
178*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4S) },
179*1da177e4SLinus Torvalds 	{ }
180*1da177e4SLinus Torvalds };
181*1da177e4SLinus Torvalds 
182*1da177e4SLinus Torvalds /* Devices that this driver supports */
183*1da177e4SLinus Torvalds static struct usb_device_id id_table_combined [] = {
184*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_1) },
185*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_TI3410_EDGEPORT_1) },
186*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_TI3410_EDGEPORT_1I) },
187*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_PROXIMITY) },
188*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_MOTION) },
189*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_MOISTURE) },
190*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_TEMPERATURE) },
191*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_HUMIDITY) },
192*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_POWER) },
193*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_LIGHT) },
194*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_RADIATION) },
195*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_DISTANCE) },
196*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_ACCELERATION) },
197*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_PROX_DIST) },
198*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_PLUS_PWR_HP4CD) },
199*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_PLUS_PWR_PCI) },
200*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2) },
201*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2C) },
202*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2I) },
203*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421) },
204*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21) },
205*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_42) },
206*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4) },
207*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4I) },
208*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22I) },
209*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_221C) },
210*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22C) },
211*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21C) },
212*1da177e4SLinus Torvalds 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4S) },
213*1da177e4SLinus Torvalds 	{ }
214*1da177e4SLinus Torvalds };
215*1da177e4SLinus Torvalds 
216*1da177e4SLinus Torvalds MODULE_DEVICE_TABLE (usb, id_table_combined);
217*1da177e4SLinus Torvalds 
218*1da177e4SLinus Torvalds static struct usb_driver io_driver = {
219*1da177e4SLinus Torvalds 	.owner =	THIS_MODULE,
220*1da177e4SLinus Torvalds 	.name =		"io_ti",
221*1da177e4SLinus Torvalds 	.probe =	usb_serial_probe,
222*1da177e4SLinus Torvalds 	.disconnect =	usb_serial_disconnect,
223*1da177e4SLinus Torvalds 	.id_table =	id_table_combined,
224*1da177e4SLinus Torvalds };
225*1da177e4SLinus Torvalds 
226*1da177e4SLinus Torvalds 
227*1da177e4SLinus Torvalds static struct EDGE_FIRMWARE_VERSION_INFO OperationalCodeImageVersion;
228*1da177e4SLinus Torvalds 
229*1da177e4SLinus Torvalds static int debug;
230*1da177e4SLinus Torvalds 
231*1da177e4SLinus Torvalds static int TIStayInBootMode = 0;
232*1da177e4SLinus Torvalds static int low_latency = EDGE_LOW_LATENCY;
233*1da177e4SLinus Torvalds static int closing_wait = EDGE_CLOSING_WAIT;
234*1da177e4SLinus Torvalds static int ignore_cpu_rev = 0;
235*1da177e4SLinus Torvalds 
236*1da177e4SLinus Torvalds 
237*1da177e4SLinus Torvalds static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length);
238*1da177e4SLinus Torvalds 
239*1da177e4SLinus Torvalds static void stop_read(struct edgeport_port *edge_port);
240*1da177e4SLinus Torvalds static int restart_read(struct edgeport_port *edge_port);
241*1da177e4SLinus Torvalds 
242*1da177e4SLinus Torvalds static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios);
243*1da177e4SLinus Torvalds static void edge_send(struct usb_serial_port *port);
244*1da177e4SLinus Torvalds 
245*1da177e4SLinus Torvalds /* circular buffer */
246*1da177e4SLinus Torvalds static struct edge_buf *edge_buf_alloc(unsigned int size);
247*1da177e4SLinus Torvalds static void edge_buf_free(struct edge_buf *eb);
248*1da177e4SLinus Torvalds static void edge_buf_clear(struct edge_buf *eb);
249*1da177e4SLinus Torvalds static unsigned int edge_buf_data_avail(struct edge_buf *eb);
250*1da177e4SLinus Torvalds static unsigned int edge_buf_space_avail(struct edge_buf *eb);
251*1da177e4SLinus Torvalds static unsigned int edge_buf_put(struct edge_buf *eb, const char *buf,
252*1da177e4SLinus Torvalds 	unsigned int count);
253*1da177e4SLinus Torvalds static unsigned int edge_buf_get(struct edge_buf *eb, char *buf,
254*1da177e4SLinus Torvalds 	unsigned int count);
255*1da177e4SLinus Torvalds 
256*1da177e4SLinus Torvalds 
257*1da177e4SLinus Torvalds static int TIReadVendorRequestSync (struct usb_device *dev,
258*1da177e4SLinus Torvalds 				__u8		request,
259*1da177e4SLinus Torvalds 				__u16		value,
260*1da177e4SLinus Torvalds 				__u16		index,
261*1da177e4SLinus Torvalds 				u8 		*data,
262*1da177e4SLinus Torvalds 				int		size)
263*1da177e4SLinus Torvalds {
264*1da177e4SLinus Torvalds 	int status;
265*1da177e4SLinus Torvalds 
266*1da177e4SLinus Torvalds 	status = usb_control_msg (dev,
267*1da177e4SLinus Torvalds 				usb_rcvctrlpipe(dev, 0),
268*1da177e4SLinus Torvalds 				request,
269*1da177e4SLinus Torvalds 				(USB_TYPE_VENDOR |
270*1da177e4SLinus Torvalds 				 USB_RECIP_DEVICE |
271*1da177e4SLinus Torvalds 				 USB_DIR_IN),
272*1da177e4SLinus Torvalds 				value,
273*1da177e4SLinus Torvalds 				index,
274*1da177e4SLinus Torvalds 				data,
275*1da177e4SLinus Torvalds 				size,
276*1da177e4SLinus Torvalds 				1000);
277*1da177e4SLinus Torvalds 	if (status < 0)
278*1da177e4SLinus Torvalds 		return status;
279*1da177e4SLinus Torvalds 	if (status != size) {
280*1da177e4SLinus Torvalds 		dbg ("%s - wanted to write %d, but only wrote %d",
281*1da177e4SLinus Torvalds 		     __FUNCTION__, size, status);
282*1da177e4SLinus Torvalds 		return -ECOMM;
283*1da177e4SLinus Torvalds 	}
284*1da177e4SLinus Torvalds 	return 0;
285*1da177e4SLinus Torvalds }
286*1da177e4SLinus Torvalds 
287*1da177e4SLinus Torvalds static int TISendVendorRequestSync (struct usb_device *dev,
288*1da177e4SLinus Torvalds 				__u8		request,
289*1da177e4SLinus Torvalds 				__u16		value,
290*1da177e4SLinus Torvalds 				__u16		index,
291*1da177e4SLinus Torvalds 				u8 		*data,
292*1da177e4SLinus Torvalds 				int		size)
293*1da177e4SLinus Torvalds {
294*1da177e4SLinus Torvalds 	int status;
295*1da177e4SLinus Torvalds 
296*1da177e4SLinus Torvalds 	status = usb_control_msg (dev,
297*1da177e4SLinus Torvalds 				usb_sndctrlpipe(dev, 0),
298*1da177e4SLinus Torvalds 				request,
299*1da177e4SLinus Torvalds 				(USB_TYPE_VENDOR |
300*1da177e4SLinus Torvalds 				 USB_RECIP_DEVICE |
301*1da177e4SLinus Torvalds 				 USB_DIR_OUT),
302*1da177e4SLinus Torvalds 				value,
303*1da177e4SLinus Torvalds 				index,
304*1da177e4SLinus Torvalds 				data,
305*1da177e4SLinus Torvalds 				size,
306*1da177e4SLinus Torvalds 				1000);
307*1da177e4SLinus Torvalds 	if (status < 0)
308*1da177e4SLinus Torvalds 		return status;
309*1da177e4SLinus Torvalds 	if (status != size) {
310*1da177e4SLinus Torvalds 		dbg ("%s - wanted to write %d, but only wrote %d",
311*1da177e4SLinus Torvalds 		     __FUNCTION__, size, status);
312*1da177e4SLinus Torvalds 		return -ECOMM;
313*1da177e4SLinus Torvalds 	}
314*1da177e4SLinus Torvalds 	return 0;
315*1da177e4SLinus Torvalds }
316*1da177e4SLinus Torvalds 
317*1da177e4SLinus Torvalds static int TIWriteCommandSync (struct usb_device *dev, __u8 command,
318*1da177e4SLinus Torvalds 				__u8 moduleid, __u16 value, u8 *data,
319*1da177e4SLinus Torvalds 				int size)
320*1da177e4SLinus Torvalds {
321*1da177e4SLinus Torvalds 	return TISendVendorRequestSync (dev,
322*1da177e4SLinus Torvalds 					  command,	  		// Request
323*1da177e4SLinus Torvalds 					  value,			// wValue
324*1da177e4SLinus Torvalds 					  moduleid,			// wIndex
325*1da177e4SLinus Torvalds 					  data,				// TransferBuffer
326*1da177e4SLinus Torvalds 					  size);			// TransferBufferLength
327*1da177e4SLinus Torvalds 
328*1da177e4SLinus Torvalds }
329*1da177e4SLinus Torvalds 
330*1da177e4SLinus Torvalds /* clear tx/rx buffers and fifo in TI UMP */
331*1da177e4SLinus Torvalds static int TIPurgeDataSync (struct usb_serial_port *port, __u16 mask)
332*1da177e4SLinus Torvalds {
333*1da177e4SLinus Torvalds 	int port_number = port->number - port->serial->minor;
334*1da177e4SLinus Torvalds 
335*1da177e4SLinus Torvalds 	dbg ("%s - port %d, mask %x", __FUNCTION__, port_number, mask);
336*1da177e4SLinus Torvalds 
337*1da177e4SLinus Torvalds 	return TIWriteCommandSync (port->serial->dev,
338*1da177e4SLinus Torvalds 					UMPC_PURGE_PORT,
339*1da177e4SLinus Torvalds 					(__u8)(UMPM_UART1_PORT + port_number),
340*1da177e4SLinus Torvalds 					mask,
341*1da177e4SLinus Torvalds 					NULL,
342*1da177e4SLinus Torvalds 					0);
343*1da177e4SLinus Torvalds }
344*1da177e4SLinus Torvalds 
345*1da177e4SLinus Torvalds /**
346*1da177e4SLinus Torvalds  * TIReadDownloadMemory - Read edgeport memory from TI chip
347*1da177e4SLinus Torvalds  * @dev: usb device pointer
348*1da177e4SLinus Torvalds  * @start_address: Device CPU address at which to read
349*1da177e4SLinus Torvalds  * @length: Length of above data
350*1da177e4SLinus Torvalds  * @address_type: Can read both XDATA and I2C
351*1da177e4SLinus Torvalds  * @buffer: pointer to input data buffer
352*1da177e4SLinus Torvalds  */
353*1da177e4SLinus Torvalds static int TIReadDownloadMemory(struct usb_device *dev, int start_address,
354*1da177e4SLinus Torvalds 				int length, __u8 address_type, __u8 *buffer)
355*1da177e4SLinus Torvalds {
356*1da177e4SLinus Torvalds 	int status = 0;
357*1da177e4SLinus Torvalds 	__u8 read_length;
358*1da177e4SLinus Torvalds 	__be16 be_start_address;
359*1da177e4SLinus Torvalds 
360*1da177e4SLinus Torvalds 	dbg ("%s - @ %x for %d", __FUNCTION__, start_address, length);
361*1da177e4SLinus Torvalds 
362*1da177e4SLinus Torvalds 	/* Read in blocks of 64 bytes
363*1da177e4SLinus Torvalds 	 * (TI firmware can't handle more than 64 byte reads)
364*1da177e4SLinus Torvalds 	 */
365*1da177e4SLinus Torvalds 	while (length) {
366*1da177e4SLinus Torvalds 		if (length > 64)
367*1da177e4SLinus Torvalds 			read_length= 64;
368*1da177e4SLinus Torvalds 		else
369*1da177e4SLinus Torvalds 			read_length = (__u8)length;
370*1da177e4SLinus Torvalds 
371*1da177e4SLinus Torvalds 		if (read_length > 1) {
372*1da177e4SLinus Torvalds 			dbg ("%s - @ %x for %d", __FUNCTION__,
373*1da177e4SLinus Torvalds 			     start_address, read_length);
374*1da177e4SLinus Torvalds 		}
375*1da177e4SLinus Torvalds 		be_start_address = cpu_to_be16 (start_address);
376*1da177e4SLinus Torvalds 		status = TIReadVendorRequestSync (dev,
377*1da177e4SLinus Torvalds 						  UMPC_MEMORY_READ,	// Request
378*1da177e4SLinus Torvalds 						  (__u16)address_type,	// wValue (Address type)
379*1da177e4SLinus Torvalds 						  (__force __u16)be_start_address,	// wIndex (Address to read)
380*1da177e4SLinus Torvalds 						  buffer,		// TransferBuffer
381*1da177e4SLinus Torvalds 						  read_length);	// TransferBufferLength
382*1da177e4SLinus Torvalds 
383*1da177e4SLinus Torvalds 		if (status) {
384*1da177e4SLinus Torvalds 			dbg ("%s - ERROR %x", __FUNCTION__, status);
385*1da177e4SLinus Torvalds 			return status;
386*1da177e4SLinus Torvalds 		}
387*1da177e4SLinus Torvalds 
388*1da177e4SLinus Torvalds 		if (read_length > 1) {
389*1da177e4SLinus Torvalds 			usb_serial_debug_data(debug, &dev->dev, __FUNCTION__,
390*1da177e4SLinus Torvalds 					      read_length, buffer);
391*1da177e4SLinus Torvalds 		}
392*1da177e4SLinus Torvalds 
393*1da177e4SLinus Torvalds 		/* Update pointers/length */
394*1da177e4SLinus Torvalds 		start_address += read_length;
395*1da177e4SLinus Torvalds 		buffer += read_length;
396*1da177e4SLinus Torvalds 		length -= read_length;
397*1da177e4SLinus Torvalds 	}
398*1da177e4SLinus Torvalds 
399*1da177e4SLinus Torvalds 	return status;
400*1da177e4SLinus Torvalds }
401*1da177e4SLinus Torvalds 
402*1da177e4SLinus Torvalds static int TIReadRam (struct usb_device *dev, int start_address, int length, __u8 *buffer)
403*1da177e4SLinus Torvalds {
404*1da177e4SLinus Torvalds 	return TIReadDownloadMemory (dev,
405*1da177e4SLinus Torvalds 				     start_address,
406*1da177e4SLinus Torvalds 				     length,
407*1da177e4SLinus Torvalds 				     DTK_ADDR_SPACE_XDATA,
408*1da177e4SLinus Torvalds 				     buffer);
409*1da177e4SLinus Torvalds }
410*1da177e4SLinus Torvalds 
411*1da177e4SLinus Torvalds /* Read edgeport memory to a given block */
412*1da177e4SLinus Torvalds static int TIReadBootMemory (struct edgeport_serial *serial, int start_address, int length, __u8 * buffer)
413*1da177e4SLinus Torvalds {
414*1da177e4SLinus Torvalds 	int status = 0;
415*1da177e4SLinus Torvalds 	int i;
416*1da177e4SLinus Torvalds 
417*1da177e4SLinus Torvalds 	for (i=0; i< length; i++) {
418*1da177e4SLinus Torvalds 		status = TIReadVendorRequestSync (serial->serial->dev,
419*1da177e4SLinus Torvalds 					UMPC_MEMORY_READ,		// Request
420*1da177e4SLinus Torvalds 					serial->TI_I2C_Type,		// wValue (Address type)
421*1da177e4SLinus Torvalds 					(__u16)(start_address+i),	// wIndex
422*1da177e4SLinus Torvalds 					&buffer[i],			// TransferBuffer
423*1da177e4SLinus Torvalds 					0x01);				// TransferBufferLength
424*1da177e4SLinus Torvalds 		if (status) {
425*1da177e4SLinus Torvalds 			dbg ("%s - ERROR %x", __FUNCTION__, status);
426*1da177e4SLinus Torvalds 			return status;
427*1da177e4SLinus Torvalds 		}
428*1da177e4SLinus Torvalds 	}
429*1da177e4SLinus Torvalds 
430*1da177e4SLinus Torvalds 	dbg ("%s - start_address = %x, length = %d", __FUNCTION__, start_address, length);
431*1da177e4SLinus Torvalds 	usb_serial_debug_data(debug, &serial->serial->dev->dev, __FUNCTION__, length, buffer);
432*1da177e4SLinus Torvalds 
433*1da177e4SLinus Torvalds 	serial->TiReadI2C = 1;
434*1da177e4SLinus Torvalds 
435*1da177e4SLinus Torvalds 	return status;
436*1da177e4SLinus Torvalds }
437*1da177e4SLinus Torvalds 
438*1da177e4SLinus Torvalds /* Write given block to TI EPROM memory */
439*1da177e4SLinus Torvalds static int TIWriteBootMemory (struct edgeport_serial *serial, int start_address, int length, __u8 *buffer)
440*1da177e4SLinus Torvalds {
441*1da177e4SLinus Torvalds 	int status = 0;
442*1da177e4SLinus Torvalds 	int i;
443*1da177e4SLinus Torvalds 	__u8 temp;
444*1da177e4SLinus Torvalds 
445*1da177e4SLinus Torvalds 	/* Must do a read before write */
446*1da177e4SLinus Torvalds 	if (!serial->TiReadI2C) {
447*1da177e4SLinus Torvalds 		status = TIReadBootMemory(serial, 0, 1, &temp);
448*1da177e4SLinus Torvalds 		if (status)
449*1da177e4SLinus Torvalds 			return status;
450*1da177e4SLinus Torvalds 	}
451*1da177e4SLinus Torvalds 
452*1da177e4SLinus Torvalds 	for (i=0; i < length; ++i) {
453*1da177e4SLinus Torvalds 		status = TISendVendorRequestSync (serial->serial->dev,
454*1da177e4SLinus Torvalds 						UMPC_MEMORY_WRITE,		// Request
455*1da177e4SLinus Torvalds 						buffer[i],			// wValue
456*1da177e4SLinus Torvalds 						(__u16)(i+start_address),	// wIndex
457*1da177e4SLinus Torvalds 						NULL,				// TransferBuffer
458*1da177e4SLinus Torvalds 						0);				// TransferBufferLength
459*1da177e4SLinus Torvalds 		if (status)
460*1da177e4SLinus Torvalds 			return status;
461*1da177e4SLinus Torvalds 	}
462*1da177e4SLinus Torvalds 
463*1da177e4SLinus Torvalds   	dbg ("%s - start_sddr = %x, length = %d", __FUNCTION__, start_address, length);
464*1da177e4SLinus Torvalds 	usb_serial_debug_data(debug, &serial->serial->dev->dev, __FUNCTION__, length, buffer);
465*1da177e4SLinus Torvalds 
466*1da177e4SLinus Torvalds 	return status;
467*1da177e4SLinus Torvalds }
468*1da177e4SLinus Torvalds 
469*1da177e4SLinus Torvalds 
470*1da177e4SLinus Torvalds /* Write edgeport I2C memory to TI chip	*/
471*1da177e4SLinus Torvalds static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address, int length, __u8 address_type, __u8 *buffer)
472*1da177e4SLinus Torvalds {
473*1da177e4SLinus Torvalds 	int status = 0;
474*1da177e4SLinus Torvalds 	int write_length;
475*1da177e4SLinus Torvalds 	__be16 be_start_address;
476*1da177e4SLinus Torvalds 
477*1da177e4SLinus Torvalds 	/* We can only send a maximum of 1 aligned byte page at a time */
478*1da177e4SLinus Torvalds 
479*1da177e4SLinus Torvalds 	/* calulate the number of bytes left in the first page */
480*1da177e4SLinus Torvalds 	write_length = EPROM_PAGE_SIZE - (start_address & (EPROM_PAGE_SIZE - 1));
481*1da177e4SLinus Torvalds 
482*1da177e4SLinus Torvalds 	if (write_length > length)
483*1da177e4SLinus Torvalds 		write_length = length;
484*1da177e4SLinus Torvalds 
485*1da177e4SLinus Torvalds 	dbg ("%s - BytesInFirstPage Addr = %x, length = %d", __FUNCTION__, start_address, write_length);
486*1da177e4SLinus Torvalds 	usb_serial_debug_data(debug, &serial->serial->dev->dev, __FUNCTION__, write_length, buffer);
487*1da177e4SLinus Torvalds 
488*1da177e4SLinus Torvalds 	/* Write first page */
489*1da177e4SLinus Torvalds 	be_start_address = cpu_to_be16 (start_address);
490*1da177e4SLinus Torvalds 	status = TISendVendorRequestSync (serial->serial->dev,
491*1da177e4SLinus Torvalds 					UMPC_MEMORY_WRITE,	// Request
492*1da177e4SLinus Torvalds 					(__u16)address_type,	// wValue
493*1da177e4SLinus Torvalds 					(__force __u16)be_start_address,	// wIndex
494*1da177e4SLinus Torvalds 					buffer,			// TransferBuffer
495*1da177e4SLinus Torvalds 					write_length);
496*1da177e4SLinus Torvalds 	if (status) {
497*1da177e4SLinus Torvalds 		dbg ("%s - ERROR %d", __FUNCTION__, status);
498*1da177e4SLinus Torvalds 		return status;
499*1da177e4SLinus Torvalds 	}
500*1da177e4SLinus Torvalds 
501*1da177e4SLinus Torvalds 	length		-= write_length;
502*1da177e4SLinus Torvalds 	start_address	+= write_length;
503*1da177e4SLinus Torvalds 	buffer		+= write_length;
504*1da177e4SLinus Torvalds 
505*1da177e4SLinus Torvalds 	/* We should be aligned now -- can write max page size bytes at a time */
506*1da177e4SLinus Torvalds 	while (length) {
507*1da177e4SLinus Torvalds 		if (length > EPROM_PAGE_SIZE)
508*1da177e4SLinus Torvalds 			write_length = EPROM_PAGE_SIZE;
509*1da177e4SLinus Torvalds 		else
510*1da177e4SLinus Torvalds 			write_length = length;
511*1da177e4SLinus Torvalds 
512*1da177e4SLinus Torvalds 		dbg ("%s - Page Write Addr = %x, length = %d", __FUNCTION__, start_address, write_length);
513*1da177e4SLinus Torvalds 		usb_serial_debug_data(debug, &serial->serial->dev->dev, __FUNCTION__, write_length, buffer);
514*1da177e4SLinus Torvalds 
515*1da177e4SLinus Torvalds 		/* Write next page */
516*1da177e4SLinus Torvalds 		be_start_address = cpu_to_be16 (start_address);
517*1da177e4SLinus Torvalds 		status = TISendVendorRequestSync (serial->serial->dev,
518*1da177e4SLinus Torvalds 						UMPC_MEMORY_WRITE,	// Request
519*1da177e4SLinus Torvalds 						(__u16)address_type,	// wValue
520*1da177e4SLinus Torvalds 						(__force __u16)be_start_address,	// wIndex
521*1da177e4SLinus Torvalds 						buffer,	  		// TransferBuffer
522*1da177e4SLinus Torvalds 						write_length);		// TransferBufferLength
523*1da177e4SLinus Torvalds 		if (status) {
524*1da177e4SLinus Torvalds 			dev_err (&serial->serial->dev->dev, "%s - ERROR %d\n", __FUNCTION__, status);
525*1da177e4SLinus Torvalds 			return status;
526*1da177e4SLinus Torvalds 		}
527*1da177e4SLinus Torvalds 
528*1da177e4SLinus Torvalds 		length		-= write_length;
529*1da177e4SLinus Torvalds 		start_address	+= write_length;
530*1da177e4SLinus Torvalds 		buffer		+= write_length;
531*1da177e4SLinus Torvalds 	}
532*1da177e4SLinus Torvalds 	return status;
533*1da177e4SLinus Torvalds }
534*1da177e4SLinus Torvalds 
535*1da177e4SLinus Torvalds /* Examine the UMP DMA registers and LSR
536*1da177e4SLinus Torvalds  *
537*1da177e4SLinus Torvalds  * Check the MSBit of the X and Y DMA byte count registers.
538*1da177e4SLinus Torvalds  * A zero in this bit indicates that the TX DMA buffers are empty
539*1da177e4SLinus Torvalds  * then check the TX Empty bit in the UART.
540*1da177e4SLinus Torvalds  */
541*1da177e4SLinus Torvalds static int TIIsTxActive (struct edgeport_port *port)
542*1da177e4SLinus Torvalds {
543*1da177e4SLinus Torvalds 	int status;
544*1da177e4SLinus Torvalds 	struct out_endpoint_desc_block *oedb;
545*1da177e4SLinus Torvalds 	__u8 *lsr;
546*1da177e4SLinus Torvalds 	int bytes_left = 0;
547*1da177e4SLinus Torvalds 
548*1da177e4SLinus Torvalds 	oedb = kmalloc (sizeof (* oedb), GFP_KERNEL);
549*1da177e4SLinus Torvalds 	if (!oedb) {
550*1da177e4SLinus Torvalds 		dev_err (&port->port->dev, "%s - out of memory\n", __FUNCTION__);
551*1da177e4SLinus Torvalds 		return -ENOMEM;
552*1da177e4SLinus Torvalds 	}
553*1da177e4SLinus Torvalds 
554*1da177e4SLinus Torvalds 	lsr = kmalloc (1, GFP_KERNEL);	/* Sigh, that's right, just one byte,
555*1da177e4SLinus Torvalds 					   as not all platforms can do DMA
556*1da177e4SLinus Torvalds 					   from stack */
557*1da177e4SLinus Torvalds 	if (!lsr) {
558*1da177e4SLinus Torvalds 		kfree(oedb);
559*1da177e4SLinus Torvalds 		return -ENOMEM;
560*1da177e4SLinus Torvalds 	}
561*1da177e4SLinus Torvalds 	/* Read the DMA Count Registers */
562*1da177e4SLinus Torvalds 	status = TIReadRam (port->port->serial->dev,
563*1da177e4SLinus Torvalds 			    port->dma_address,
564*1da177e4SLinus Torvalds 			    sizeof( *oedb),
565*1da177e4SLinus Torvalds 			    (void *)oedb);
566*1da177e4SLinus Torvalds 
567*1da177e4SLinus Torvalds 	if (status)
568*1da177e4SLinus Torvalds 		goto exit_is_tx_active;
569*1da177e4SLinus Torvalds 
570*1da177e4SLinus Torvalds 	dbg ("%s - XByteCount    0x%X", __FUNCTION__, oedb->XByteCount);
571*1da177e4SLinus Torvalds 
572*1da177e4SLinus Torvalds 	/* and the LSR */
573*1da177e4SLinus Torvalds 	status = TIReadRam (port->port->serial->dev,
574*1da177e4SLinus Torvalds 			    port->uart_base + UMPMEM_OFFS_UART_LSR,
575*1da177e4SLinus Torvalds 			    1,
576*1da177e4SLinus Torvalds 			    lsr);
577*1da177e4SLinus Torvalds 
578*1da177e4SLinus Torvalds 	if (status)
579*1da177e4SLinus Torvalds 		goto exit_is_tx_active;
580*1da177e4SLinus Torvalds 	dbg ("%s - LSR = 0x%X", __FUNCTION__, *lsr);
581*1da177e4SLinus Torvalds 
582*1da177e4SLinus Torvalds 	/* If either buffer has data or we are transmitting then return TRUE */
583*1da177e4SLinus Torvalds 	if ((oedb->XByteCount & 0x80 ) != 0 )
584*1da177e4SLinus Torvalds 		bytes_left += 64;
585*1da177e4SLinus Torvalds 
586*1da177e4SLinus Torvalds 	if ((*lsr & UMP_UART_LSR_TX_MASK ) == 0 )
587*1da177e4SLinus Torvalds 		bytes_left += 1;
588*1da177e4SLinus Torvalds 
589*1da177e4SLinus Torvalds 	/* We return Not Active if we get any kind of error */
590*1da177e4SLinus Torvalds exit_is_tx_active:
591*1da177e4SLinus Torvalds 	dbg ("%s - return %d", __FUNCTION__, bytes_left );
592*1da177e4SLinus Torvalds 
593*1da177e4SLinus Torvalds 	kfree(lsr);
594*1da177e4SLinus Torvalds 	kfree(oedb);
595*1da177e4SLinus Torvalds 	return bytes_left;
596*1da177e4SLinus Torvalds }
597*1da177e4SLinus Torvalds 
598*1da177e4SLinus Torvalds static void TIChasePort(struct edgeport_port *port, unsigned long timeout, int flush)
599*1da177e4SLinus Torvalds {
600*1da177e4SLinus Torvalds 	int baud_rate;
601*1da177e4SLinus Torvalds 	struct tty_struct *tty = port->port->tty;
602*1da177e4SLinus Torvalds 	wait_queue_t wait;
603*1da177e4SLinus Torvalds 	unsigned long flags;
604*1da177e4SLinus Torvalds 
605*1da177e4SLinus Torvalds 	if (!timeout)
606*1da177e4SLinus Torvalds 		timeout = (HZ*EDGE_CLOSING_WAIT)/100;
607*1da177e4SLinus Torvalds 
608*1da177e4SLinus Torvalds 	/* wait for data to drain from the buffer */
609*1da177e4SLinus Torvalds 	spin_lock_irqsave(&port->ep_lock, flags);
610*1da177e4SLinus Torvalds 	init_waitqueue_entry(&wait, current);
611*1da177e4SLinus Torvalds 	add_wait_queue(&tty->write_wait, &wait);
612*1da177e4SLinus Torvalds 	for (;;) {
613*1da177e4SLinus Torvalds 		set_current_state(TASK_INTERRUPTIBLE);
614*1da177e4SLinus Torvalds 		if (edge_buf_data_avail(port->ep_out_buf) == 0
615*1da177e4SLinus Torvalds 		|| timeout == 0 || signal_pending(current)
616*1da177e4SLinus Torvalds 		|| !usb_get_intfdata(port->port->serial->interface))  /* disconnect */
617*1da177e4SLinus Torvalds 			break;
618*1da177e4SLinus Torvalds 		spin_unlock_irqrestore(&port->ep_lock, flags);
619*1da177e4SLinus Torvalds 		timeout = schedule_timeout(timeout);
620*1da177e4SLinus Torvalds 		spin_lock_irqsave(&port->ep_lock, flags);
621*1da177e4SLinus Torvalds 	}
622*1da177e4SLinus Torvalds 	set_current_state(TASK_RUNNING);
623*1da177e4SLinus Torvalds 	remove_wait_queue(&tty->write_wait, &wait);
624*1da177e4SLinus Torvalds 	if (flush)
625*1da177e4SLinus Torvalds 		edge_buf_clear(port->ep_out_buf);
626*1da177e4SLinus Torvalds 	spin_unlock_irqrestore(&port->ep_lock, flags);
627*1da177e4SLinus Torvalds 
628*1da177e4SLinus Torvalds 	/* wait for data to drain from the device */
629*1da177e4SLinus Torvalds 	timeout += jiffies;
630*1da177e4SLinus Torvalds 	while ((long)(jiffies - timeout) < 0 && !signal_pending(current)
631*1da177e4SLinus Torvalds 	&& usb_get_intfdata(port->port->serial->interface)) {  /* not disconnected */
632*1da177e4SLinus Torvalds 		if (!TIIsTxActive(port))
633*1da177e4SLinus Torvalds 			break;
634*1da177e4SLinus Torvalds 		msleep(10);
635*1da177e4SLinus Torvalds 	}
636*1da177e4SLinus Torvalds 
637*1da177e4SLinus Torvalds 	/* disconnected */
638*1da177e4SLinus Torvalds 	if (!usb_get_intfdata(port->port->serial->interface))
639*1da177e4SLinus Torvalds 		return;
640*1da177e4SLinus Torvalds 
641*1da177e4SLinus Torvalds 	/* wait one more character time, based on baud rate */
642*1da177e4SLinus Torvalds 	/* (TIIsTxActive doesn't seem to wait for the last byte) */
643*1da177e4SLinus Torvalds 	if ((baud_rate=port->baud_rate) == 0)
644*1da177e4SLinus Torvalds 		baud_rate = 50;
645*1da177e4SLinus Torvalds 	msleep(max(1,(10000+baud_rate-1)/baud_rate));
646*1da177e4SLinus Torvalds }
647*1da177e4SLinus Torvalds 
648*1da177e4SLinus Torvalds static int TIChooseConfiguration (struct usb_device *dev)
649*1da177e4SLinus Torvalds {
650*1da177e4SLinus Torvalds 	// There may be multiple configurations on this device, in which case
651*1da177e4SLinus Torvalds 	// we would need to read and parse all of them to find out which one
652*1da177e4SLinus Torvalds 	// we want. However, we just support one config at this point,
653*1da177e4SLinus Torvalds 	// configuration # 1, which is Config Descriptor 0.
654*1da177e4SLinus Torvalds 
655*1da177e4SLinus Torvalds 	dbg ("%s - Number of Interfaces = %d", __FUNCTION__, dev->config->desc.bNumInterfaces);
656*1da177e4SLinus Torvalds 	dbg ("%s - MAX Power            = %d", __FUNCTION__, dev->config->desc.bMaxPower*2);
657*1da177e4SLinus Torvalds 
658*1da177e4SLinus Torvalds 	if (dev->config->desc.bNumInterfaces != 1) {
659*1da177e4SLinus Torvalds 		dev_err (&dev->dev, "%s - bNumInterfaces is not 1, ERROR!\n", __FUNCTION__);
660*1da177e4SLinus Torvalds 		return -ENODEV;
661*1da177e4SLinus Torvalds 	}
662*1da177e4SLinus Torvalds 
663*1da177e4SLinus Torvalds 	return 0;
664*1da177e4SLinus Torvalds }
665*1da177e4SLinus Torvalds 
666*1da177e4SLinus Torvalds static int TIReadRom (struct edgeport_serial *serial, int start_address, int length, __u8 *buffer)
667*1da177e4SLinus Torvalds {
668*1da177e4SLinus Torvalds 	int status;
669*1da177e4SLinus Torvalds 
670*1da177e4SLinus Torvalds 	if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) {
671*1da177e4SLinus Torvalds 		status = TIReadDownloadMemory (serial->serial->dev,
672*1da177e4SLinus Torvalds 					       start_address,
673*1da177e4SLinus Torvalds 					       length,
674*1da177e4SLinus Torvalds 					       serial->TI_I2C_Type,
675*1da177e4SLinus Torvalds 					       buffer);
676*1da177e4SLinus Torvalds 	} else {
677*1da177e4SLinus Torvalds 		status = TIReadBootMemory (serial,
678*1da177e4SLinus Torvalds 					   start_address,
679*1da177e4SLinus Torvalds 					   length,
680*1da177e4SLinus Torvalds 					   buffer);
681*1da177e4SLinus Torvalds 	}
682*1da177e4SLinus Torvalds 
683*1da177e4SLinus Torvalds 	return status;
684*1da177e4SLinus Torvalds }
685*1da177e4SLinus Torvalds 
686*1da177e4SLinus Torvalds static int TIWriteRom (struct edgeport_serial *serial, int start_address, int length, __u8 *buffer)
687*1da177e4SLinus Torvalds {
688*1da177e4SLinus Torvalds 	if (serial->product_info.TiMode == TI_MODE_BOOT)
689*1da177e4SLinus Torvalds 		return TIWriteBootMemory (serial,
690*1da177e4SLinus Torvalds 					  start_address,
691*1da177e4SLinus Torvalds 					  length,
692*1da177e4SLinus Torvalds 					  buffer);
693*1da177e4SLinus Torvalds 
694*1da177e4SLinus Torvalds 	if (serial->product_info.TiMode == TI_MODE_DOWNLOAD)
695*1da177e4SLinus Torvalds 		return TIWriteDownloadI2C (serial,
696*1da177e4SLinus Torvalds 					   start_address,
697*1da177e4SLinus Torvalds 					   length,
698*1da177e4SLinus Torvalds 					   serial->TI_I2C_Type,
699*1da177e4SLinus Torvalds 					   buffer);
700*1da177e4SLinus Torvalds 
701*1da177e4SLinus Torvalds 	return -EINVAL;
702*1da177e4SLinus Torvalds }
703*1da177e4SLinus Torvalds 
704*1da177e4SLinus Torvalds 
705*1da177e4SLinus Torvalds 
706*1da177e4SLinus Torvalds /* Read a descriptor header from I2C based on type */
707*1da177e4SLinus Torvalds static int TIGetDescriptorAddress (struct edgeport_serial *serial, int desc_type, struct ti_i2c_desc *rom_desc)
708*1da177e4SLinus Torvalds {
709*1da177e4SLinus Torvalds 	int start_address;
710*1da177e4SLinus Torvalds 	int status;
711*1da177e4SLinus Torvalds 
712*1da177e4SLinus Torvalds 	/* Search for requested descriptor in I2C */
713*1da177e4SLinus Torvalds 	start_address = 2;
714*1da177e4SLinus Torvalds 	do {
715*1da177e4SLinus Torvalds 		status = TIReadRom (serial,
716*1da177e4SLinus Torvalds 				   start_address,
717*1da177e4SLinus Torvalds 				   sizeof(struct ti_i2c_desc),
718*1da177e4SLinus Torvalds 				   (__u8 *)rom_desc );
719*1da177e4SLinus Torvalds 		if (status)
720*1da177e4SLinus Torvalds 			return 0;
721*1da177e4SLinus Torvalds 
722*1da177e4SLinus Torvalds 		if (rom_desc->Type == desc_type)
723*1da177e4SLinus Torvalds 			return start_address;
724*1da177e4SLinus Torvalds 
725*1da177e4SLinus Torvalds 		start_address = start_address + sizeof(struct ti_i2c_desc) +  rom_desc->Size;
726*1da177e4SLinus Torvalds 
727*1da177e4SLinus Torvalds 	} while ((start_address < TI_MAX_I2C_SIZE) && rom_desc->Type);
728*1da177e4SLinus Torvalds 
729*1da177e4SLinus Torvalds 	return 0;
730*1da177e4SLinus Torvalds }
731*1da177e4SLinus Torvalds 
732*1da177e4SLinus Torvalds /* Validate descriptor checksum */
733*1da177e4SLinus Torvalds static int ValidChecksum(struct ti_i2c_desc *rom_desc, __u8 *buffer)
734*1da177e4SLinus Torvalds {
735*1da177e4SLinus Torvalds 	__u16 i;
736*1da177e4SLinus Torvalds 	__u8 cs = 0;
737*1da177e4SLinus Torvalds 
738*1da177e4SLinus Torvalds 	for (i=0; i < rom_desc->Size; i++) {
739*1da177e4SLinus Torvalds 		cs = (__u8)(cs + buffer[i]);
740*1da177e4SLinus Torvalds 	}
741*1da177e4SLinus Torvalds 	if (cs != rom_desc->CheckSum) {
742*1da177e4SLinus Torvalds 		dbg ("%s - Mismatch %x - %x", __FUNCTION__, rom_desc->CheckSum, cs);
743*1da177e4SLinus Torvalds 		return -EINVAL;
744*1da177e4SLinus Torvalds 	}
745*1da177e4SLinus Torvalds 	return 0;
746*1da177e4SLinus Torvalds }
747*1da177e4SLinus Torvalds 
748*1da177e4SLinus Torvalds /* Make sure that the I2C image is good */
749*1da177e4SLinus Torvalds static int TiValidateI2cImage (struct edgeport_serial *serial)
750*1da177e4SLinus Torvalds {
751*1da177e4SLinus Torvalds 	struct device *dev = &serial->serial->dev->dev;
752*1da177e4SLinus Torvalds 	int status = 0;
753*1da177e4SLinus Torvalds 	struct ti_i2c_desc *rom_desc;
754*1da177e4SLinus Torvalds 	int start_address = 2;
755*1da177e4SLinus Torvalds 	__u8 *buffer;
756*1da177e4SLinus Torvalds 	__u16 ttype;
757*1da177e4SLinus Torvalds 
758*1da177e4SLinus Torvalds 	rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL);
759*1da177e4SLinus Torvalds 	if (!rom_desc) {
760*1da177e4SLinus Torvalds 		dev_err (dev, "%s - out of memory\n", __FUNCTION__);
761*1da177e4SLinus Torvalds 		return -ENOMEM;
762*1da177e4SLinus Torvalds 	}
763*1da177e4SLinus Torvalds 	buffer = kmalloc (TI_MAX_I2C_SIZE, GFP_KERNEL);
764*1da177e4SLinus Torvalds 	if (!buffer) {
765*1da177e4SLinus Torvalds 		dev_err (dev, "%s - out of memory when allocating buffer\n", __FUNCTION__);
766*1da177e4SLinus Torvalds 		kfree (rom_desc);
767*1da177e4SLinus Torvalds 		return -ENOMEM;
768*1da177e4SLinus Torvalds 	}
769*1da177e4SLinus Torvalds 
770*1da177e4SLinus Torvalds 	// Read the first byte (Signature0) must be 0x52 or 0x10
771*1da177e4SLinus Torvalds 	status = TIReadRom (serial, 0, 1, buffer);
772*1da177e4SLinus Torvalds 	if (status)
773*1da177e4SLinus Torvalds 		goto ExitTiValidateI2cImage;
774*1da177e4SLinus Torvalds 
775*1da177e4SLinus Torvalds 	if (*buffer != UMP5152 && *buffer != UMP3410) {
776*1da177e4SLinus Torvalds 		dev_err (dev, "%s - invalid buffer signature\n", __FUNCTION__);
777*1da177e4SLinus Torvalds 		status = -ENODEV;
778*1da177e4SLinus Torvalds 		goto ExitTiValidateI2cImage;
779*1da177e4SLinus Torvalds 	}
780*1da177e4SLinus Torvalds 
781*1da177e4SLinus Torvalds 	do {
782*1da177e4SLinus Torvalds 		// Validate the I2C
783*1da177e4SLinus Torvalds 		status = TIReadRom (serial,
784*1da177e4SLinus Torvalds 				start_address,
785*1da177e4SLinus Torvalds 				sizeof(struct ti_i2c_desc),
786*1da177e4SLinus Torvalds 				(__u8 *)rom_desc);
787*1da177e4SLinus Torvalds 		if (status)
788*1da177e4SLinus Torvalds 			break;
789*1da177e4SLinus Torvalds 
790*1da177e4SLinus Torvalds 		if ((start_address + sizeof(struct ti_i2c_desc) + rom_desc->Size) > TI_MAX_I2C_SIZE) {
791*1da177e4SLinus Torvalds 			status = -ENODEV;
792*1da177e4SLinus Torvalds 			dbg ("%s - structure too big, erroring out.", __FUNCTION__);
793*1da177e4SLinus Torvalds 			break;
794*1da177e4SLinus Torvalds 		}
795*1da177e4SLinus Torvalds 
796*1da177e4SLinus Torvalds 		dbg ("%s Type = 0x%x", __FUNCTION__, rom_desc->Type);
797*1da177e4SLinus Torvalds 
798*1da177e4SLinus Torvalds 		// Skip type 2 record
799*1da177e4SLinus Torvalds 		ttype = rom_desc->Type & 0x0f;
800*1da177e4SLinus Torvalds 		if ( ttype != I2C_DESC_TYPE_FIRMWARE_BASIC
801*1da177e4SLinus Torvalds 			&& ttype != I2C_DESC_TYPE_FIRMWARE_AUTO ) {
802*1da177e4SLinus Torvalds 			// Read the descriptor data
803*1da177e4SLinus Torvalds 			status = TIReadRom(serial,
804*1da177e4SLinus Torvalds 						start_address+sizeof(struct ti_i2c_desc),
805*1da177e4SLinus Torvalds 						rom_desc->Size,
806*1da177e4SLinus Torvalds 						buffer);
807*1da177e4SLinus Torvalds 			if (status)
808*1da177e4SLinus Torvalds 				break;
809*1da177e4SLinus Torvalds 
810*1da177e4SLinus Torvalds 			status = ValidChecksum(rom_desc, buffer);
811*1da177e4SLinus Torvalds 			if (status)
812*1da177e4SLinus Torvalds 				break;
813*1da177e4SLinus Torvalds 		}
814*1da177e4SLinus Torvalds 		start_address = start_address + sizeof(struct ti_i2c_desc) + rom_desc->Size;
815*1da177e4SLinus Torvalds 
816*1da177e4SLinus Torvalds 	} while ((rom_desc->Type != I2C_DESC_TYPE_ION) && (start_address < TI_MAX_I2C_SIZE));
817*1da177e4SLinus Torvalds 
818*1da177e4SLinus Torvalds 	if ((rom_desc->Type != I2C_DESC_TYPE_ION) || (start_address > TI_MAX_I2C_SIZE))
819*1da177e4SLinus Torvalds 		status = -ENODEV;
820*1da177e4SLinus Torvalds 
821*1da177e4SLinus Torvalds ExitTiValidateI2cImage:
822*1da177e4SLinus Torvalds 	kfree (buffer);
823*1da177e4SLinus Torvalds 	kfree (rom_desc);
824*1da177e4SLinus Torvalds 	return status;
825*1da177e4SLinus Torvalds }
826*1da177e4SLinus Torvalds 
827*1da177e4SLinus Torvalds static int TIReadManufDescriptor (struct edgeport_serial *serial, __u8 *buffer)
828*1da177e4SLinus Torvalds {
829*1da177e4SLinus Torvalds 	int status;
830*1da177e4SLinus Torvalds 	int start_address;
831*1da177e4SLinus Torvalds 	struct ti_i2c_desc *rom_desc;
832*1da177e4SLinus Torvalds 	struct edge_ti_manuf_descriptor *desc;
833*1da177e4SLinus Torvalds 
834*1da177e4SLinus Torvalds 	rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL);
835*1da177e4SLinus Torvalds 	if (!rom_desc) {
836*1da177e4SLinus Torvalds 		dev_err (&serial->serial->dev->dev, "%s - out of memory\n", __FUNCTION__);
837*1da177e4SLinus Torvalds 		return -ENOMEM;
838*1da177e4SLinus Torvalds 	}
839*1da177e4SLinus Torvalds 	start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_ION, rom_desc);
840*1da177e4SLinus Torvalds 
841*1da177e4SLinus Torvalds 	if (!start_address) {
842*1da177e4SLinus Torvalds 		dbg ("%s - Edge Descriptor not found in I2C", __FUNCTION__);
843*1da177e4SLinus Torvalds 		status = -ENODEV;
844*1da177e4SLinus Torvalds 		goto exit;
845*1da177e4SLinus Torvalds 	}
846*1da177e4SLinus Torvalds 
847*1da177e4SLinus Torvalds 	// Read the descriptor data
848*1da177e4SLinus Torvalds 	status = TIReadRom (serial,
849*1da177e4SLinus Torvalds 				start_address+sizeof(struct ti_i2c_desc),
850*1da177e4SLinus Torvalds 				rom_desc->Size,
851*1da177e4SLinus Torvalds 				buffer);
852*1da177e4SLinus Torvalds 	if (status)
853*1da177e4SLinus Torvalds 		goto exit;
854*1da177e4SLinus Torvalds 
855*1da177e4SLinus Torvalds 	status = ValidChecksum(rom_desc, buffer);
856*1da177e4SLinus Torvalds 
857*1da177e4SLinus Torvalds 	desc = (struct edge_ti_manuf_descriptor *)buffer;
858*1da177e4SLinus Torvalds 	dbg ( "%s - IonConfig      0x%x", __FUNCTION__, desc->IonConfig 	);
859*1da177e4SLinus Torvalds 	dbg ( "%s - Version          %d", __FUNCTION__, desc->Version	  	);
860*1da177e4SLinus Torvalds 	dbg ( "%s - Cpu/Board      0x%x", __FUNCTION__, desc->CpuRev_BoardRev	);
861*1da177e4SLinus Torvalds 	dbg ( "%s - NumPorts         %d", __FUNCTION__, desc->NumPorts  	);
862*1da177e4SLinus Torvalds 	dbg ( "%s - NumVirtualPorts  %d", __FUNCTION__, desc->NumVirtualPorts	);
863*1da177e4SLinus Torvalds 	dbg ( "%s - TotalPorts       %d", __FUNCTION__, desc->TotalPorts  	);
864*1da177e4SLinus Torvalds 
865*1da177e4SLinus Torvalds exit:
866*1da177e4SLinus Torvalds 	kfree (rom_desc);
867*1da177e4SLinus Torvalds 	return status;
868*1da177e4SLinus Torvalds }
869*1da177e4SLinus Torvalds 
870*1da177e4SLinus Torvalds /* Build firmware header used for firmware update */
871*1da177e4SLinus Torvalds static int BuildI2CFirmwareHeader (__u8 *header, struct device *dev)
872*1da177e4SLinus Torvalds {
873*1da177e4SLinus Torvalds 	__u8 *buffer;
874*1da177e4SLinus Torvalds 	int buffer_size;
875*1da177e4SLinus Torvalds 	int i;
876*1da177e4SLinus Torvalds 	__u8 cs = 0;
877*1da177e4SLinus Torvalds 	struct ti_i2c_desc *i2c_header;
878*1da177e4SLinus Torvalds 	struct ti_i2c_image_header *img_header;
879*1da177e4SLinus Torvalds 	struct ti_i2c_firmware_rec *firmware_rec;
880*1da177e4SLinus Torvalds 
881*1da177e4SLinus Torvalds 	// In order to update the I2C firmware we must change the type 2 record to type 0xF2.
882*1da177e4SLinus Torvalds 	// This will force the UMP to come up in Boot Mode.  Then while in boot mode, the driver
883*1da177e4SLinus Torvalds 	// will download the latest firmware (padded to 15.5k) into the UMP ram.
884*1da177e4SLinus Torvalds 	// And finally when the device comes back up in download mode the driver will cause
885*1da177e4SLinus Torvalds 	// the new firmware to be copied from the UMP Ram to I2C and the firmware will update
886*1da177e4SLinus Torvalds 	// the record type from 0xf2 to 0x02.
887*1da177e4SLinus Torvalds 
888*1da177e4SLinus Torvalds 	// Allocate a 15.5k buffer + 2 bytes for version number (Firmware Record)
889*1da177e4SLinus Torvalds 	buffer_size = (((1024 * 16) - 512 )+ sizeof(struct ti_i2c_firmware_rec));
890*1da177e4SLinus Torvalds 
891*1da177e4SLinus Torvalds 	buffer = kmalloc (buffer_size, GFP_KERNEL);
892*1da177e4SLinus Torvalds 	if (!buffer) {
893*1da177e4SLinus Torvalds 		dev_err (dev, "%s - out of memory\n", __FUNCTION__);
894*1da177e4SLinus Torvalds 		return -ENOMEM;
895*1da177e4SLinus Torvalds 	}
896*1da177e4SLinus Torvalds 
897*1da177e4SLinus Torvalds 	// Set entire image of 0xffs
898*1da177e4SLinus Torvalds 	memset (buffer, 0xff, buffer_size);
899*1da177e4SLinus Torvalds 
900*1da177e4SLinus Torvalds 	// Copy version number into firmware record
901*1da177e4SLinus Torvalds 	firmware_rec = (struct ti_i2c_firmware_rec *)buffer;
902*1da177e4SLinus Torvalds 
903*1da177e4SLinus Torvalds 	firmware_rec->Ver_Major	= OperationalCodeImageVersion.MajorVersion;
904*1da177e4SLinus Torvalds 	firmware_rec->Ver_Minor	= OperationalCodeImageVersion.MinorVersion;
905*1da177e4SLinus Torvalds 
906*1da177e4SLinus Torvalds 	// Pointer to fw_down memory image
907*1da177e4SLinus Torvalds 	img_header = (struct ti_i2c_image_header *)&PagableOperationalCodeImage[0];
908*1da177e4SLinus Torvalds 
909*1da177e4SLinus Torvalds 	memcpy (buffer + sizeof(struct ti_i2c_firmware_rec),
910*1da177e4SLinus Torvalds 		&PagableOperationalCodeImage[sizeof(struct ti_i2c_image_header)],
911*1da177e4SLinus Torvalds 		le16_to_cpu(img_header->Length));
912*1da177e4SLinus Torvalds 
913*1da177e4SLinus Torvalds 	for (i=0; i < buffer_size; i++) {
914*1da177e4SLinus Torvalds 		cs = (__u8)(cs + buffer[i]);
915*1da177e4SLinus Torvalds 	}
916*1da177e4SLinus Torvalds 
917*1da177e4SLinus Torvalds 	kfree (buffer);
918*1da177e4SLinus Torvalds 
919*1da177e4SLinus Torvalds 	// Build new header
920*1da177e4SLinus Torvalds 	i2c_header =  (struct ti_i2c_desc *)header;
921*1da177e4SLinus Torvalds 	firmware_rec =  (struct ti_i2c_firmware_rec*)i2c_header->Data;
922*1da177e4SLinus Torvalds 
923*1da177e4SLinus Torvalds 	i2c_header->Type	= I2C_DESC_TYPE_FIRMWARE_BLANK;
924*1da177e4SLinus Torvalds 	i2c_header->Size	= (__u16)buffer_size;
925*1da177e4SLinus Torvalds 	i2c_header->CheckSum	= cs;
926*1da177e4SLinus Torvalds 	firmware_rec->Ver_Major	= OperationalCodeImageVersion.MajorVersion;
927*1da177e4SLinus Torvalds 	firmware_rec->Ver_Minor	= OperationalCodeImageVersion.MinorVersion;
928*1da177e4SLinus Torvalds 
929*1da177e4SLinus Torvalds 	return 0;
930*1da177e4SLinus Torvalds }
931*1da177e4SLinus Torvalds 
932*1da177e4SLinus Torvalds /* Try to figure out what type of I2c we have */
933*1da177e4SLinus Torvalds static int TIGetI2cTypeInBootMode (struct edgeport_serial *serial)
934*1da177e4SLinus Torvalds {
935*1da177e4SLinus Torvalds 	int status;
936*1da177e4SLinus Torvalds 	__u8 data;
937*1da177e4SLinus Torvalds 
938*1da177e4SLinus Torvalds 	// Try to read type 2
939*1da177e4SLinus Torvalds 	status = TIReadVendorRequestSync (serial->serial->dev,
940*1da177e4SLinus Torvalds 					UMPC_MEMORY_READ,		// Request
941*1da177e4SLinus Torvalds 					DTK_ADDR_SPACE_I2C_TYPE_II,	// wValue (Address type)
942*1da177e4SLinus Torvalds 					0,		 		// wIndex
943*1da177e4SLinus Torvalds 					&data,				// TransferBuffer
944*1da177e4SLinus Torvalds 					0x01);				// TransferBufferLength
945*1da177e4SLinus Torvalds 	if (status)
946*1da177e4SLinus Torvalds 		dbg ("%s - read 2 status error = %d", __FUNCTION__, status);
947*1da177e4SLinus Torvalds 	else
948*1da177e4SLinus Torvalds 		dbg ("%s - read 2 data = 0x%x", __FUNCTION__, data);
949*1da177e4SLinus Torvalds 	if ((!status) && (data == UMP5152 || data == UMP3410)) {
950*1da177e4SLinus Torvalds 		dbg ("%s - ROM_TYPE_II", __FUNCTION__);
951*1da177e4SLinus Torvalds 		serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
952*1da177e4SLinus Torvalds 		return 0;
953*1da177e4SLinus Torvalds 	}
954*1da177e4SLinus Torvalds 
955*1da177e4SLinus Torvalds 	// Try to read type 3
956*1da177e4SLinus Torvalds 	status = TIReadVendorRequestSync (serial->serial->dev,
957*1da177e4SLinus Torvalds 					UMPC_MEMORY_READ,		// Request
958*1da177e4SLinus Torvalds 					DTK_ADDR_SPACE_I2C_TYPE_III,	// wValue (Address type)
959*1da177e4SLinus Torvalds 					0,				// wIndex
960*1da177e4SLinus Torvalds 					&data,				// TransferBuffer
961*1da177e4SLinus Torvalds 					0x01);				// TransferBufferLength
962*1da177e4SLinus Torvalds 	if (status)
963*1da177e4SLinus Torvalds 		dbg ("%s - read 3 status error = %d", __FUNCTION__, status);
964*1da177e4SLinus Torvalds 	else
965*1da177e4SLinus Torvalds 		dbg ("%s - read 2 data = 0x%x", __FUNCTION__, data);
966*1da177e4SLinus Torvalds 	if ((!status) && (data == UMP5152 || data == UMP3410)) {
967*1da177e4SLinus Torvalds 		dbg ("%s - ROM_TYPE_III", __FUNCTION__);
968*1da177e4SLinus Torvalds 		serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_III;
969*1da177e4SLinus Torvalds 		return 0;
970*1da177e4SLinus Torvalds 	}
971*1da177e4SLinus Torvalds 
972*1da177e4SLinus Torvalds 	dbg ("%s - Unknown", __FUNCTION__);
973*1da177e4SLinus Torvalds 	serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
974*1da177e4SLinus Torvalds 	return -ENODEV;
975*1da177e4SLinus Torvalds }
976*1da177e4SLinus Torvalds 
977*1da177e4SLinus Torvalds static int TISendBulkTransferSync (struct usb_serial *serial, void *buffer, int length, int *num_sent)
978*1da177e4SLinus Torvalds {
979*1da177e4SLinus Torvalds 	int status;
980*1da177e4SLinus Torvalds 
981*1da177e4SLinus Torvalds 	status = usb_bulk_msg (serial->dev,
982*1da177e4SLinus Torvalds 				usb_sndbulkpipe(serial->dev,
983*1da177e4SLinus Torvalds 						serial->port[0]->bulk_out_endpointAddress),
984*1da177e4SLinus Torvalds 				buffer,
985*1da177e4SLinus Torvalds 				length,
986*1da177e4SLinus Torvalds 				num_sent,
987*1da177e4SLinus Torvalds 				1000);
988*1da177e4SLinus Torvalds 	return status;
989*1da177e4SLinus Torvalds }
990*1da177e4SLinus Torvalds 
991*1da177e4SLinus Torvalds /* Download given firmware image to the device (IN BOOT MODE) */
992*1da177e4SLinus Torvalds static int TIDownloadCodeImage (struct edgeport_serial *serial, __u8 *image, int image_length)
993*1da177e4SLinus Torvalds {
994*1da177e4SLinus Torvalds 	int status = 0;
995*1da177e4SLinus Torvalds 	int pos;
996*1da177e4SLinus Torvalds 	int transfer;
997*1da177e4SLinus Torvalds 	int done;
998*1da177e4SLinus Torvalds 
999*1da177e4SLinus Torvalds 	// Transfer firmware image
1000*1da177e4SLinus Torvalds 	for (pos = 0; pos < image_length; ) {
1001*1da177e4SLinus Torvalds 		// Read the next buffer from file
1002*1da177e4SLinus Torvalds 		transfer = image_length - pos;
1003*1da177e4SLinus Torvalds 		if (transfer > EDGE_FW_BULK_MAX_PACKET_SIZE)
1004*1da177e4SLinus Torvalds 			transfer = EDGE_FW_BULK_MAX_PACKET_SIZE;
1005*1da177e4SLinus Torvalds 
1006*1da177e4SLinus Torvalds 		// Transfer data
1007*1da177e4SLinus Torvalds 		status = TISendBulkTransferSync (serial->serial, &image[pos], transfer, &done);
1008*1da177e4SLinus Torvalds 		if (status)
1009*1da177e4SLinus Torvalds 			break;
1010*1da177e4SLinus Torvalds 		// Advance buffer pointer
1011*1da177e4SLinus Torvalds 		pos += done;
1012*1da177e4SLinus Torvalds 	}
1013*1da177e4SLinus Torvalds 
1014*1da177e4SLinus Torvalds 	return status;
1015*1da177e4SLinus Torvalds }
1016*1da177e4SLinus Torvalds 
1017*1da177e4SLinus Torvalds // FIXME!!!
1018*1da177e4SLinus Torvalds static int TIConfigureBootDevice (struct usb_device *dev)
1019*1da177e4SLinus Torvalds {
1020*1da177e4SLinus Torvalds 	return 0;
1021*1da177e4SLinus Torvalds }
1022*1da177e4SLinus Torvalds 
1023*1da177e4SLinus Torvalds /**
1024*1da177e4SLinus Torvalds  * DownloadTIFirmware - Download run-time operating firmware to the TI5052
1025*1da177e4SLinus Torvalds  *
1026*1da177e4SLinus Torvalds  * This routine downloads the main operating code into the TI5052, using the
1027*1da177e4SLinus Torvalds  * boot code already burned into E2PROM or ROM.
1028*1da177e4SLinus Torvalds  */
1029*1da177e4SLinus Torvalds static int TIDownloadFirmware (struct edgeport_serial *serial)
1030*1da177e4SLinus Torvalds {
1031*1da177e4SLinus Torvalds 	struct device *dev = &serial->serial->dev->dev;
1032*1da177e4SLinus Torvalds 	int status = 0;
1033*1da177e4SLinus Torvalds 	int start_address;
1034*1da177e4SLinus Torvalds 	struct edge_ti_manuf_descriptor *ti_manuf_desc;
1035*1da177e4SLinus Torvalds 	struct usb_interface_descriptor *interface;
1036*1da177e4SLinus Torvalds 	int download_cur_ver;
1037*1da177e4SLinus Torvalds 	int download_new_ver;
1038*1da177e4SLinus Torvalds 
1039*1da177e4SLinus Torvalds 	/* This routine is entered by both the BOOT mode and the Download mode
1040*1da177e4SLinus Torvalds 	 * We can determine which code is running by the reading the config
1041*1da177e4SLinus Torvalds 	 * descriptor and if we have only one bulk pipe it is in boot mode
1042*1da177e4SLinus Torvalds 	 */
1043*1da177e4SLinus Torvalds 	serial->product_info.hardware_type = HARDWARE_TYPE_TIUMP;
1044*1da177e4SLinus Torvalds 
1045*1da177e4SLinus Torvalds 	/* Default to type 2 i2c */
1046*1da177e4SLinus Torvalds 	serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
1047*1da177e4SLinus Torvalds 
1048*1da177e4SLinus Torvalds 	status = TIChooseConfiguration (serial->serial->dev);
1049*1da177e4SLinus Torvalds 	if (status)
1050*1da177e4SLinus Torvalds 		return status;
1051*1da177e4SLinus Torvalds 
1052*1da177e4SLinus Torvalds 	interface = &serial->serial->interface->cur_altsetting->desc;
1053*1da177e4SLinus Torvalds 	if (!interface) {
1054*1da177e4SLinus Torvalds 		dev_err (dev, "%s - no interface set, error!\n", __FUNCTION__);
1055*1da177e4SLinus Torvalds 		return -ENODEV;
1056*1da177e4SLinus Torvalds 	}
1057*1da177e4SLinus Torvalds 
1058*1da177e4SLinus Torvalds 	// Setup initial mode -- the default mode 0 is TI_MODE_CONFIGURING
1059*1da177e4SLinus Torvalds 	// if we have more than one endpoint we are definitely in download mode
1060*1da177e4SLinus Torvalds 	if (interface->bNumEndpoints > 1)
1061*1da177e4SLinus Torvalds 		serial->product_info.TiMode = TI_MODE_DOWNLOAD;
1062*1da177e4SLinus Torvalds 	else
1063*1da177e4SLinus Torvalds 		// Otherwise we will remain in configuring mode
1064*1da177e4SLinus Torvalds 		serial->product_info.TiMode = TI_MODE_CONFIGURING;
1065*1da177e4SLinus Torvalds 
1066*1da177e4SLinus Torvalds 	// Save Download Version Number
1067*1da177e4SLinus Torvalds 	OperationalCodeImageVersion.MajorVersion = PagableOperationalCodeImageVersion.MajorVersion;
1068*1da177e4SLinus Torvalds 	OperationalCodeImageVersion.MinorVersion = PagableOperationalCodeImageVersion.MinorVersion;
1069*1da177e4SLinus Torvalds 	OperationalCodeImageVersion.BuildNumber	 = PagableOperationalCodeImageVersion.BuildNumber;
1070*1da177e4SLinus Torvalds 
1071*1da177e4SLinus Torvalds 	/********************************************************************/
1072*1da177e4SLinus Torvalds 	/* Download Mode */
1073*1da177e4SLinus Torvalds 	/********************************************************************/
1074*1da177e4SLinus Torvalds 	if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) {
1075*1da177e4SLinus Torvalds 		struct ti_i2c_desc *rom_desc;
1076*1da177e4SLinus Torvalds 
1077*1da177e4SLinus Torvalds 		dbg ("%s - <<<<<<<<<<<<<<<RUNNING IN DOWNLOAD MODE>>>>>>>>>>", __FUNCTION__);
1078*1da177e4SLinus Torvalds 
1079*1da177e4SLinus Torvalds 		status = TiValidateI2cImage (serial);
1080*1da177e4SLinus Torvalds 		if (status) {
1081*1da177e4SLinus Torvalds 			dbg ("%s - <<<<<<<<<<<<<<<DOWNLOAD MODE -- BAD I2C >>>>>>>>>>",
1082*1da177e4SLinus Torvalds 			     __FUNCTION__);
1083*1da177e4SLinus Torvalds 			return status;
1084*1da177e4SLinus Torvalds 		}
1085*1da177e4SLinus Torvalds 
1086*1da177e4SLinus Torvalds 		/* Validate Hardware version number
1087*1da177e4SLinus Torvalds 		 * Read Manufacturing Descriptor from TI Based Edgeport
1088*1da177e4SLinus Torvalds 		 */
1089*1da177e4SLinus Torvalds 		ti_manuf_desc = kmalloc (sizeof (*ti_manuf_desc), GFP_KERNEL);
1090*1da177e4SLinus Torvalds 		if (!ti_manuf_desc) {
1091*1da177e4SLinus Torvalds 			dev_err (dev, "%s - out of memory.\n", __FUNCTION__);
1092*1da177e4SLinus Torvalds 			return -ENOMEM;
1093*1da177e4SLinus Torvalds 		}
1094*1da177e4SLinus Torvalds 		status = TIReadManufDescriptor (serial, (__u8 *)ti_manuf_desc);
1095*1da177e4SLinus Torvalds 		if (status) {
1096*1da177e4SLinus Torvalds 			kfree (ti_manuf_desc);
1097*1da177e4SLinus Torvalds 			return status;
1098*1da177e4SLinus Torvalds 		}
1099*1da177e4SLinus Torvalds 
1100*1da177e4SLinus Torvalds 		// Check version number of ION descriptor
1101*1da177e4SLinus Torvalds 		if (!ignore_cpu_rev && TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev) < 2) {
1102*1da177e4SLinus Torvalds 			dbg ( "%s - Wrong CPU Rev %d (Must be 2)", __FUNCTION__,
1103*1da177e4SLinus Torvalds 			     TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev));
1104*1da177e4SLinus Torvalds 			kfree (ti_manuf_desc);
1105*1da177e4SLinus Torvalds 		   	return -EINVAL;
1106*1da177e4SLinus Torvalds 		}
1107*1da177e4SLinus Torvalds 
1108*1da177e4SLinus Torvalds 		rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL);
1109*1da177e4SLinus Torvalds 		if (!rom_desc) {
1110*1da177e4SLinus Torvalds 			dev_err (dev, "%s - out of memory.\n", __FUNCTION__);
1111*1da177e4SLinus Torvalds 			kfree (ti_manuf_desc);
1112*1da177e4SLinus Torvalds 			return -ENOMEM;
1113*1da177e4SLinus Torvalds 		}
1114*1da177e4SLinus Torvalds 
1115*1da177e4SLinus Torvalds 		// Search for type 2 record (firmware record)
1116*1da177e4SLinus Torvalds 		if ((start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_FIRMWARE_BASIC, rom_desc)) != 0) {
1117*1da177e4SLinus Torvalds 			struct ti_i2c_firmware_rec *firmware_version;
1118*1da177e4SLinus Torvalds 			__u8 record;
1119*1da177e4SLinus Torvalds 
1120*1da177e4SLinus Torvalds 			dbg ("%s - Found Type FIRMWARE (Type 2) record", __FUNCTION__);
1121*1da177e4SLinus Torvalds 
1122*1da177e4SLinus Torvalds 			firmware_version = kmalloc (sizeof (*firmware_version), GFP_KERNEL);
1123*1da177e4SLinus Torvalds 			if (!firmware_version) {
1124*1da177e4SLinus Torvalds 				dev_err (dev, "%s - out of memory.\n", __FUNCTION__);
1125*1da177e4SLinus Torvalds 				kfree (rom_desc);
1126*1da177e4SLinus Torvalds 				kfree (ti_manuf_desc);
1127*1da177e4SLinus Torvalds 				return -ENOMEM;
1128*1da177e4SLinus Torvalds 			}
1129*1da177e4SLinus Torvalds 
1130*1da177e4SLinus Torvalds 			// Validate version number
1131*1da177e4SLinus Torvalds 			// Read the descriptor data
1132*1da177e4SLinus Torvalds 			status = TIReadRom (serial,
1133*1da177e4SLinus Torvalds 					start_address+sizeof(struct ti_i2c_desc),
1134*1da177e4SLinus Torvalds 					sizeof(struct ti_i2c_firmware_rec),
1135*1da177e4SLinus Torvalds 					(__u8 *)firmware_version);
1136*1da177e4SLinus Torvalds 			if (status) {
1137*1da177e4SLinus Torvalds 				kfree (firmware_version);
1138*1da177e4SLinus Torvalds 				kfree (rom_desc);
1139*1da177e4SLinus Torvalds 				kfree (ti_manuf_desc);
1140*1da177e4SLinus Torvalds 				return status;
1141*1da177e4SLinus Torvalds 			}
1142*1da177e4SLinus Torvalds 
1143*1da177e4SLinus Torvalds 			// Check version number of download with current version in I2c
1144*1da177e4SLinus Torvalds 			download_cur_ver = (firmware_version->Ver_Major << 8) +
1145*1da177e4SLinus Torvalds 					   (firmware_version->Ver_Minor);
1146*1da177e4SLinus Torvalds 			download_new_ver = (OperationalCodeImageVersion.MajorVersion << 8) +
1147*1da177e4SLinus Torvalds 					   (OperationalCodeImageVersion.MinorVersion);
1148*1da177e4SLinus Torvalds 
1149*1da177e4SLinus Torvalds 			dbg ("%s - >>>Firmware Versions Device %d.%d  Driver %d.%d",
1150*1da177e4SLinus Torvalds 			     __FUNCTION__,
1151*1da177e4SLinus Torvalds 			     firmware_version->Ver_Major,
1152*1da177e4SLinus Torvalds 			     firmware_version->Ver_Minor,
1153*1da177e4SLinus Torvalds 			     OperationalCodeImageVersion.MajorVersion,
1154*1da177e4SLinus Torvalds 			     OperationalCodeImageVersion.MinorVersion);
1155*1da177e4SLinus Torvalds 
1156*1da177e4SLinus Torvalds 			// Check if we have an old version in the I2C and update if necessary
1157*1da177e4SLinus Torvalds 			if (download_cur_ver != download_new_ver) {
1158*1da177e4SLinus Torvalds 				dbg ("%s - Update I2C Download from %d.%d to %d.%d",
1159*1da177e4SLinus Torvalds 				     __FUNCTION__,
1160*1da177e4SLinus Torvalds 				     firmware_version->Ver_Major,
1161*1da177e4SLinus Torvalds 				     firmware_version->Ver_Minor,
1162*1da177e4SLinus Torvalds 				     OperationalCodeImageVersion.MajorVersion,
1163*1da177e4SLinus Torvalds 				     OperationalCodeImageVersion.MinorVersion);
1164*1da177e4SLinus Torvalds 
1165*1da177e4SLinus Torvalds 				// In order to update the I2C firmware we must change the type 2 record to type 0xF2.
1166*1da177e4SLinus Torvalds 				// This will force the UMP to come up in Boot Mode.  Then while in boot mode, the driver
1167*1da177e4SLinus Torvalds 				// will download the latest firmware (padded to 15.5k) into the UMP ram.
1168*1da177e4SLinus Torvalds 				// And finally when the device comes back up in download mode the driver will cause
1169*1da177e4SLinus Torvalds 				// the new firmware to be copied from the UMP Ram to I2C and the firmware will update
1170*1da177e4SLinus Torvalds 				// the record type from 0xf2 to 0x02.
1171*1da177e4SLinus Torvalds 
1172*1da177e4SLinus Torvalds 				record = I2C_DESC_TYPE_FIRMWARE_BLANK;
1173*1da177e4SLinus Torvalds 
1174*1da177e4SLinus Torvalds 				// Change the I2C Firmware record type to 0xf2 to trigger an update
1175*1da177e4SLinus Torvalds 				status = TIWriteRom (serial,
1176*1da177e4SLinus Torvalds 							start_address,
1177*1da177e4SLinus Torvalds 							sizeof(record),
1178*1da177e4SLinus Torvalds 							&record);
1179*1da177e4SLinus Torvalds 				if (status) {
1180*1da177e4SLinus Torvalds 					kfree (firmware_version);
1181*1da177e4SLinus Torvalds 					kfree (rom_desc);
1182*1da177e4SLinus Torvalds 					kfree (ti_manuf_desc);
1183*1da177e4SLinus Torvalds 					return status;
1184*1da177e4SLinus Torvalds 				}
1185*1da177e4SLinus Torvalds 
1186*1da177e4SLinus Torvalds 				// verify the write -- must do this in order for write to
1187*1da177e4SLinus Torvalds 				// complete before we do the hardware reset
1188*1da177e4SLinus Torvalds 				status = TIReadRom (serial,
1189*1da177e4SLinus Torvalds 							start_address,
1190*1da177e4SLinus Torvalds 							sizeof(record),
1191*1da177e4SLinus Torvalds 							&record);
1192*1da177e4SLinus Torvalds 
1193*1da177e4SLinus Torvalds 				if (status) {
1194*1da177e4SLinus Torvalds 					kfree (firmware_version);
1195*1da177e4SLinus Torvalds 					kfree (rom_desc);
1196*1da177e4SLinus Torvalds 					kfree (ti_manuf_desc);
1197*1da177e4SLinus Torvalds 					return status;
1198*1da177e4SLinus Torvalds 				}
1199*1da177e4SLinus Torvalds 
1200*1da177e4SLinus Torvalds 				if (record != I2C_DESC_TYPE_FIRMWARE_BLANK) {
1201*1da177e4SLinus Torvalds 					dev_err (dev, "%s - error resetting device\n", __FUNCTION__);
1202*1da177e4SLinus Torvalds 					kfree (firmware_version);
1203*1da177e4SLinus Torvalds 					kfree (rom_desc);
1204*1da177e4SLinus Torvalds 					kfree (ti_manuf_desc);
1205*1da177e4SLinus Torvalds 					return -ENODEV;
1206*1da177e4SLinus Torvalds 				}
1207*1da177e4SLinus Torvalds 
1208*1da177e4SLinus Torvalds 				dbg ("%s - HARDWARE RESET", __FUNCTION__);
1209*1da177e4SLinus Torvalds 
1210*1da177e4SLinus Torvalds 				// Reset UMP -- Back to BOOT MODE
1211*1da177e4SLinus Torvalds 				status = TISendVendorRequestSync (serial->serial->dev,
1212*1da177e4SLinus Torvalds 								UMPC_HARDWARE_RESET,	// Request
1213*1da177e4SLinus Torvalds 								0,			// wValue
1214*1da177e4SLinus Torvalds 								0,			// wIndex
1215*1da177e4SLinus Torvalds 								NULL,			// TransferBuffer
1216*1da177e4SLinus Torvalds 								0);			// TransferBufferLength
1217*1da177e4SLinus Torvalds 
1218*1da177e4SLinus Torvalds 				dbg ( "%s - HARDWARE RESET return %d", __FUNCTION__, status);
1219*1da177e4SLinus Torvalds 
1220*1da177e4SLinus Torvalds 				/* return an error on purpose. */
1221*1da177e4SLinus Torvalds 				kfree (firmware_version);
1222*1da177e4SLinus Torvalds 				kfree (rom_desc);
1223*1da177e4SLinus Torvalds 				kfree (ti_manuf_desc);
1224*1da177e4SLinus Torvalds 				return -ENODEV;
1225*1da177e4SLinus Torvalds 			}
1226*1da177e4SLinus Torvalds 			kfree (firmware_version);
1227*1da177e4SLinus Torvalds 		}
1228*1da177e4SLinus Torvalds 		// Search for type 0xF2 record (firmware blank record)
1229*1da177e4SLinus Torvalds 		else if ((start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_FIRMWARE_BLANK, rom_desc)) != 0) {
1230*1da177e4SLinus Torvalds 			#define HEADER_SIZE	(sizeof(struct ti_i2c_desc) + sizeof(struct ti_i2c_firmware_rec))
1231*1da177e4SLinus Torvalds 			__u8 *header;
1232*1da177e4SLinus Torvalds 			__u8 *vheader;
1233*1da177e4SLinus Torvalds 
1234*1da177e4SLinus Torvalds 			header  = kmalloc (HEADER_SIZE, GFP_KERNEL);
1235*1da177e4SLinus Torvalds 			if (!header) {
1236*1da177e4SLinus Torvalds 				dev_err (dev, "%s - out of memory.\n", __FUNCTION__);
1237*1da177e4SLinus Torvalds 				kfree (rom_desc);
1238*1da177e4SLinus Torvalds 				kfree (ti_manuf_desc);
1239*1da177e4SLinus Torvalds 				return -ENOMEM;
1240*1da177e4SLinus Torvalds 			}
1241*1da177e4SLinus Torvalds 
1242*1da177e4SLinus Torvalds 			vheader = kmalloc (HEADER_SIZE, GFP_KERNEL);
1243*1da177e4SLinus Torvalds 			if (!vheader) {
1244*1da177e4SLinus Torvalds 				dev_err (dev, "%s - out of memory.\n", __FUNCTION__);
1245*1da177e4SLinus Torvalds 				kfree (header);
1246*1da177e4SLinus Torvalds 				kfree (rom_desc);
1247*1da177e4SLinus Torvalds 				kfree (ti_manuf_desc);
1248*1da177e4SLinus Torvalds 				return -ENOMEM;
1249*1da177e4SLinus Torvalds 			}
1250*1da177e4SLinus Torvalds 
1251*1da177e4SLinus Torvalds 			dbg ("%s - Found Type BLANK FIRMWARE (Type F2) record", __FUNCTION__);
1252*1da177e4SLinus Torvalds 
1253*1da177e4SLinus Torvalds 			// In order to update the I2C firmware we must change the type 2 record to type 0xF2.
1254*1da177e4SLinus Torvalds 			// This will force the UMP to come up in Boot Mode.  Then while in boot mode, the driver
1255*1da177e4SLinus Torvalds 			// will download the latest firmware (padded to 15.5k) into the UMP ram.
1256*1da177e4SLinus Torvalds 			// And finally when the device comes back up in download mode the driver will cause
1257*1da177e4SLinus Torvalds 			// the new firmware to be copied from the UMP Ram to I2C and the firmware will update
1258*1da177e4SLinus Torvalds 			// the record type from 0xf2 to 0x02.
1259*1da177e4SLinus Torvalds 			status = BuildI2CFirmwareHeader(header, dev);
1260*1da177e4SLinus Torvalds 			if (status) {
1261*1da177e4SLinus Torvalds 				kfree (vheader);
1262*1da177e4SLinus Torvalds 				kfree (header);
1263*1da177e4SLinus Torvalds 				kfree (rom_desc);
1264*1da177e4SLinus Torvalds 				kfree (ti_manuf_desc);
1265*1da177e4SLinus Torvalds 				return status;
1266*1da177e4SLinus Torvalds 			}
1267*1da177e4SLinus Torvalds 
1268*1da177e4SLinus Torvalds 			// Update I2C with type 0xf2 record with correct size and checksum
1269*1da177e4SLinus Torvalds 			status = TIWriteRom (serial,
1270*1da177e4SLinus Torvalds 						start_address,
1271*1da177e4SLinus Torvalds 						HEADER_SIZE,
1272*1da177e4SLinus Torvalds 						header);
1273*1da177e4SLinus Torvalds 			if (status) {
1274*1da177e4SLinus Torvalds 				kfree (vheader);
1275*1da177e4SLinus Torvalds 				kfree (header);
1276*1da177e4SLinus Torvalds 				kfree (rom_desc);
1277*1da177e4SLinus Torvalds 				kfree (ti_manuf_desc);
1278*1da177e4SLinus Torvalds 				return status;
1279*1da177e4SLinus Torvalds 			}
1280*1da177e4SLinus Torvalds 
1281*1da177e4SLinus Torvalds 			// verify the write -- must do this in order for write to
1282*1da177e4SLinus Torvalds 			// complete before we do the hardware reset
1283*1da177e4SLinus Torvalds 			status = TIReadRom (serial,
1284*1da177e4SLinus Torvalds 						start_address,
1285*1da177e4SLinus Torvalds 						HEADER_SIZE,
1286*1da177e4SLinus Torvalds 						vheader);
1287*1da177e4SLinus Torvalds 
1288*1da177e4SLinus Torvalds 			if (status) {
1289*1da177e4SLinus Torvalds 				dbg ("%s - can't read header back", __FUNCTION__);
1290*1da177e4SLinus Torvalds 				kfree (vheader);
1291*1da177e4SLinus Torvalds 				kfree (header);
1292*1da177e4SLinus Torvalds 				kfree (rom_desc);
1293*1da177e4SLinus Torvalds 				kfree (ti_manuf_desc);
1294*1da177e4SLinus Torvalds 				return status;
1295*1da177e4SLinus Torvalds 			}
1296*1da177e4SLinus Torvalds 			if (memcmp(vheader, header, HEADER_SIZE)) {
1297*1da177e4SLinus Torvalds 				dbg ("%s - write download record failed", __FUNCTION__);
1298*1da177e4SLinus Torvalds 				kfree (vheader);
1299*1da177e4SLinus Torvalds 				kfree (header);
1300*1da177e4SLinus Torvalds 				kfree (rom_desc);
1301*1da177e4SLinus Torvalds 				kfree (ti_manuf_desc);
1302*1da177e4SLinus Torvalds 				return status;
1303*1da177e4SLinus Torvalds 			}
1304*1da177e4SLinus Torvalds 
1305*1da177e4SLinus Torvalds 			kfree (vheader);
1306*1da177e4SLinus Torvalds 			kfree (header);
1307*1da177e4SLinus Torvalds 
1308*1da177e4SLinus Torvalds 			dbg ("%s - Start firmware update", __FUNCTION__);
1309*1da177e4SLinus Torvalds 
1310*1da177e4SLinus Torvalds 			// Tell firmware to copy download image into I2C
1311*1da177e4SLinus Torvalds 			status = TISendVendorRequestSync (serial->serial->dev,
1312*1da177e4SLinus Torvalds 						UMPC_COPY_DNLD_TO_I2C,	// Request
1313*1da177e4SLinus Torvalds 						0,			// wValue
1314*1da177e4SLinus Torvalds 						0,			// wIndex
1315*1da177e4SLinus Torvalds 						NULL,			// TransferBuffer
1316*1da177e4SLinus Torvalds 						0);			// TransferBufferLength
1317*1da177e4SLinus Torvalds 
1318*1da177e4SLinus Torvalds 		  	dbg ("%s - Update complete 0x%x", __FUNCTION__, status);
1319*1da177e4SLinus Torvalds 			if (status) {
1320*1da177e4SLinus Torvalds 				dev_err (dev, "%s - UMPC_COPY_DNLD_TO_I2C failed\n", __FUNCTION__);
1321*1da177e4SLinus Torvalds 				kfree (rom_desc);
1322*1da177e4SLinus Torvalds 				kfree (ti_manuf_desc);
1323*1da177e4SLinus Torvalds 				return status;
1324*1da177e4SLinus Torvalds 			}
1325*1da177e4SLinus Torvalds 		}
1326*1da177e4SLinus Torvalds 
1327*1da177e4SLinus Torvalds 		// The device is running the download code
1328*1da177e4SLinus Torvalds 		kfree (rom_desc);
1329*1da177e4SLinus Torvalds 		kfree (ti_manuf_desc);
1330*1da177e4SLinus Torvalds 		return 0;
1331*1da177e4SLinus Torvalds 	}
1332*1da177e4SLinus Torvalds 
1333*1da177e4SLinus Torvalds 	/********************************************************************/
1334*1da177e4SLinus Torvalds 	/* Boot Mode */
1335*1da177e4SLinus Torvalds 	/********************************************************************/
1336*1da177e4SLinus Torvalds 	dbg ("%s - <<<<<<<<<<<<<<<RUNNING IN BOOT MODE>>>>>>>>>>>>>>>",
1337*1da177e4SLinus Torvalds 	     __FUNCTION__);
1338*1da177e4SLinus Torvalds 
1339*1da177e4SLinus Torvalds 	// Configure the TI device so we can use the BULK pipes for download
1340*1da177e4SLinus Torvalds 	status = TIConfigureBootDevice (serial->serial->dev);
1341*1da177e4SLinus Torvalds 	if (status)
1342*1da177e4SLinus Torvalds 		return status;
1343*1da177e4SLinus Torvalds 
1344*1da177e4SLinus Torvalds 	if (le16_to_cpu(serial->serial->dev->descriptor.idVendor) != USB_VENDOR_ID_ION) {
1345*1da177e4SLinus Torvalds 		dbg ("%s - VID = 0x%x", __FUNCTION__,
1346*1da177e4SLinus Torvalds 		     le16_to_cpu(serial->serial->dev->descriptor.idVendor));
1347*1da177e4SLinus Torvalds 		serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
1348*1da177e4SLinus Torvalds 		goto StayInBootMode;
1349*1da177e4SLinus Torvalds 	}
1350*1da177e4SLinus Torvalds 
1351*1da177e4SLinus Torvalds 	// We have an ION device (I2c Must be programmed)
1352*1da177e4SLinus Torvalds 	// Determine I2C image type
1353*1da177e4SLinus Torvalds 	if (TIGetI2cTypeInBootMode(serial)) {
1354*1da177e4SLinus Torvalds 		goto StayInBootMode;
1355*1da177e4SLinus Torvalds 	}
1356*1da177e4SLinus Torvalds 
1357*1da177e4SLinus Torvalds 	// Registry variable set?
1358*1da177e4SLinus Torvalds 	if (TIStayInBootMode) {
1359*1da177e4SLinus Torvalds 		dbg ("%s - TIStayInBootMode", __FUNCTION__);
1360*1da177e4SLinus Torvalds 		goto StayInBootMode;
1361*1da177e4SLinus Torvalds 	}
1362*1da177e4SLinus Torvalds 
1363*1da177e4SLinus Torvalds 	// Check for ION Vendor ID and that the I2C is valid
1364*1da177e4SLinus Torvalds 	if (!TiValidateI2cImage(serial)) {
1365*1da177e4SLinus Torvalds 		struct ti_i2c_image_header *header;
1366*1da177e4SLinus Torvalds 		int i;
1367*1da177e4SLinus Torvalds 		__u8 cs = 0;
1368*1da177e4SLinus Torvalds 		__u8 *buffer;
1369*1da177e4SLinus Torvalds 		int buffer_size;
1370*1da177e4SLinus Torvalds 
1371*1da177e4SLinus Torvalds 		/* Validate Hardware version number
1372*1da177e4SLinus Torvalds 		 * Read Manufacturing Descriptor from TI Based Edgeport
1373*1da177e4SLinus Torvalds 		 */
1374*1da177e4SLinus Torvalds 		ti_manuf_desc = kmalloc (sizeof (*ti_manuf_desc), GFP_KERNEL);
1375*1da177e4SLinus Torvalds 		if (!ti_manuf_desc) {
1376*1da177e4SLinus Torvalds 			dev_err (dev, "%s - out of memory.\n", __FUNCTION__);
1377*1da177e4SLinus Torvalds 			return -ENOMEM;
1378*1da177e4SLinus Torvalds 		}
1379*1da177e4SLinus Torvalds 		status = TIReadManufDescriptor (serial, (__u8 *)ti_manuf_desc);
1380*1da177e4SLinus Torvalds 		if (status) {
1381*1da177e4SLinus Torvalds 			kfree (ti_manuf_desc);
1382*1da177e4SLinus Torvalds 			goto StayInBootMode;
1383*1da177e4SLinus Torvalds 		}
1384*1da177e4SLinus Torvalds 
1385*1da177e4SLinus Torvalds 		// Check for version 2
1386*1da177e4SLinus Torvalds 		if (!ignore_cpu_rev && TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev) < 2) {
1387*1da177e4SLinus Torvalds 			dbg ("%s - Wrong CPU Rev %d (Must be 2)", __FUNCTION__,
1388*1da177e4SLinus Torvalds 			     TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev));
1389*1da177e4SLinus Torvalds 			kfree (ti_manuf_desc);
1390*1da177e4SLinus Torvalds 			goto StayInBootMode;
1391*1da177e4SLinus Torvalds 		}
1392*1da177e4SLinus Torvalds 
1393*1da177e4SLinus Torvalds 		kfree (ti_manuf_desc);
1394*1da177e4SLinus Torvalds 
1395*1da177e4SLinus Torvalds 		// In order to update the I2C firmware we must change the type 2 record to type 0xF2.
1396*1da177e4SLinus Torvalds 		// This will force the UMP to come up in Boot Mode.  Then while in boot mode, the driver
1397*1da177e4SLinus Torvalds 		// will download the latest firmware (padded to 15.5k) into the UMP ram.
1398*1da177e4SLinus Torvalds 		// And finally when the device comes back up in download mode the driver will cause
1399*1da177e4SLinus Torvalds 		// the new firmware to be copied from the UMP Ram to I2C and the firmware will update
1400*1da177e4SLinus Torvalds 		// the record type from 0xf2 to 0x02.
1401*1da177e4SLinus Torvalds 
1402*1da177e4SLinus Torvalds 		/*
1403*1da177e4SLinus Torvalds 		 * Do we really have to copy the whole firmware image,
1404*1da177e4SLinus Torvalds 		 * or could we do this in place!
1405*1da177e4SLinus Torvalds 		 */
1406*1da177e4SLinus Torvalds 
1407*1da177e4SLinus Torvalds 		// Allocate a 15.5k buffer + 3 byte header
1408*1da177e4SLinus Torvalds 		buffer_size = (((1024 * 16) - 512) + sizeof(struct ti_i2c_image_header));
1409*1da177e4SLinus Torvalds 		buffer = kmalloc (buffer_size, GFP_KERNEL);
1410*1da177e4SLinus Torvalds 		if (!buffer) {
1411*1da177e4SLinus Torvalds 			dev_err (dev, "%s - out of memory\n", __FUNCTION__);
1412*1da177e4SLinus Torvalds 			return -ENOMEM;
1413*1da177e4SLinus Torvalds 		}
1414*1da177e4SLinus Torvalds 
1415*1da177e4SLinus Torvalds 		// Initialize the buffer to 0xff (pad the buffer)
1416*1da177e4SLinus Torvalds 		memset (buffer, 0xff, buffer_size);
1417*1da177e4SLinus Torvalds 
1418*1da177e4SLinus Torvalds 		memcpy (buffer, &PagableOperationalCodeImage[0], PagableOperationalCodeSize);
1419*1da177e4SLinus Torvalds 
1420*1da177e4SLinus Torvalds 		for(i = sizeof(struct ti_i2c_image_header); i < buffer_size; i++) {
1421*1da177e4SLinus Torvalds 			cs = (__u8)(cs + buffer[i]);
1422*1da177e4SLinus Torvalds 		}
1423*1da177e4SLinus Torvalds 
1424*1da177e4SLinus Torvalds 		header = (struct ti_i2c_image_header *)buffer;
1425*1da177e4SLinus Torvalds 
1426*1da177e4SLinus Torvalds 		// update length and checksum after padding
1427*1da177e4SLinus Torvalds 		header->Length 	 = cpu_to_le16((__u16)(buffer_size - sizeof(struct ti_i2c_image_header)));
1428*1da177e4SLinus Torvalds 		header->CheckSum = cs;
1429*1da177e4SLinus Torvalds 
1430*1da177e4SLinus Torvalds 		// Download the operational code
1431*1da177e4SLinus Torvalds 		dbg ("%s - Downloading operational code image (TI UMP)", __FUNCTION__);
1432*1da177e4SLinus Torvalds 		status = TIDownloadCodeImage (serial, buffer, buffer_size);
1433*1da177e4SLinus Torvalds 
1434*1da177e4SLinus Torvalds 		kfree (buffer);
1435*1da177e4SLinus Torvalds 
1436*1da177e4SLinus Torvalds 		if (status) {
1437*1da177e4SLinus Torvalds 	  		dbg ("%s - Error downloading operational code image", __FUNCTION__);
1438*1da177e4SLinus Torvalds 			return status;
1439*1da177e4SLinus Torvalds 		}
1440*1da177e4SLinus Torvalds 
1441*1da177e4SLinus Torvalds 		// Device will reboot
1442*1da177e4SLinus Torvalds 		serial->product_info.TiMode = TI_MODE_TRANSITIONING;
1443*1da177e4SLinus Torvalds 
1444*1da177e4SLinus Torvalds   		dbg ("%s - Download successful -- Device rebooting...", __FUNCTION__);
1445*1da177e4SLinus Torvalds 
1446*1da177e4SLinus Torvalds 		/* return an error on purpose */
1447*1da177e4SLinus Torvalds 		return -ENODEV;
1448*1da177e4SLinus Torvalds 	}
1449*1da177e4SLinus Torvalds 
1450*1da177e4SLinus Torvalds StayInBootMode:
1451*1da177e4SLinus Torvalds 	// Eprom is invalid or blank stay in boot mode
1452*1da177e4SLinus Torvalds 	dbg ("%s - <<<<<<<<<<<<<<<STAYING IN BOOT MODE>>>>>>>>>>>>", __FUNCTION__);
1453*1da177e4SLinus Torvalds 	serial->product_info.TiMode = TI_MODE_BOOT;
1454*1da177e4SLinus Torvalds 
1455*1da177e4SLinus Torvalds 	return 0;
1456*1da177e4SLinus Torvalds }
1457*1da177e4SLinus Torvalds 
1458*1da177e4SLinus Torvalds 
1459*1da177e4SLinus Torvalds static int TISetDtr (struct edgeport_port *port)
1460*1da177e4SLinus Torvalds {
1461*1da177e4SLinus Torvalds 	int port_number = port->port->number - port->port->serial->minor;
1462*1da177e4SLinus Torvalds 
1463*1da177e4SLinus Torvalds 	dbg ("%s", __FUNCTION__);
1464*1da177e4SLinus Torvalds 	port->shadow_mcr |= MCR_DTR;
1465*1da177e4SLinus Torvalds 
1466*1da177e4SLinus Torvalds 	return TIWriteCommandSync (port->port->serial->dev,
1467*1da177e4SLinus Torvalds 				UMPC_SET_CLR_DTR,
1468*1da177e4SLinus Torvalds 				(__u8)(UMPM_UART1_PORT + port_number),
1469*1da177e4SLinus Torvalds 				1,	/* set */
1470*1da177e4SLinus Torvalds 				NULL,
1471*1da177e4SLinus Torvalds 				0);
1472*1da177e4SLinus Torvalds }
1473*1da177e4SLinus Torvalds 
1474*1da177e4SLinus Torvalds static int TIClearDtr (struct edgeport_port *port)
1475*1da177e4SLinus Torvalds {
1476*1da177e4SLinus Torvalds 	int port_number = port->port->number - port->port->serial->minor;
1477*1da177e4SLinus Torvalds 
1478*1da177e4SLinus Torvalds 	dbg ("%s", __FUNCTION__);
1479*1da177e4SLinus Torvalds 	port->shadow_mcr &= ~MCR_DTR;
1480*1da177e4SLinus Torvalds 
1481*1da177e4SLinus Torvalds 	return TIWriteCommandSync (port->port->serial->dev,
1482*1da177e4SLinus Torvalds 				UMPC_SET_CLR_DTR,
1483*1da177e4SLinus Torvalds 				(__u8)(UMPM_UART1_PORT + port_number),
1484*1da177e4SLinus Torvalds 				0,	/* clear */
1485*1da177e4SLinus Torvalds 				NULL,
1486*1da177e4SLinus Torvalds 				0);
1487*1da177e4SLinus Torvalds }
1488*1da177e4SLinus Torvalds 
1489*1da177e4SLinus Torvalds static int TISetRts (struct edgeport_port *port)
1490*1da177e4SLinus Torvalds {
1491*1da177e4SLinus Torvalds 	int port_number = port->port->number - port->port->serial->minor;
1492*1da177e4SLinus Torvalds 
1493*1da177e4SLinus Torvalds 	dbg ("%s", __FUNCTION__);
1494*1da177e4SLinus Torvalds 	port->shadow_mcr |= MCR_RTS;
1495*1da177e4SLinus Torvalds 
1496*1da177e4SLinus Torvalds 	return TIWriteCommandSync (port->port->serial->dev,
1497*1da177e4SLinus Torvalds 				UMPC_SET_CLR_RTS,
1498*1da177e4SLinus Torvalds 				(__u8)(UMPM_UART1_PORT + port_number),
1499*1da177e4SLinus Torvalds 				1,	/* set */
1500*1da177e4SLinus Torvalds 				NULL,
1501*1da177e4SLinus Torvalds 				0);
1502*1da177e4SLinus Torvalds }
1503*1da177e4SLinus Torvalds 
1504*1da177e4SLinus Torvalds static int TIClearRts (struct edgeport_port *port)
1505*1da177e4SLinus Torvalds {
1506*1da177e4SLinus Torvalds 	int port_number = port->port->number - port->port->serial->minor;
1507*1da177e4SLinus Torvalds 
1508*1da177e4SLinus Torvalds 	dbg ("%s", __FUNCTION__);
1509*1da177e4SLinus Torvalds 	port->shadow_mcr &= ~MCR_RTS;
1510*1da177e4SLinus Torvalds 
1511*1da177e4SLinus Torvalds 	return TIWriteCommandSync (port->port->serial->dev,
1512*1da177e4SLinus Torvalds 				UMPC_SET_CLR_RTS,
1513*1da177e4SLinus Torvalds 				(__u8)(UMPM_UART1_PORT + port_number),
1514*1da177e4SLinus Torvalds 				0,	/* clear */
1515*1da177e4SLinus Torvalds 				NULL,
1516*1da177e4SLinus Torvalds 				0);
1517*1da177e4SLinus Torvalds }
1518*1da177e4SLinus Torvalds 
1519*1da177e4SLinus Torvalds static int TISetLoopBack (struct edgeport_port *port)
1520*1da177e4SLinus Torvalds {
1521*1da177e4SLinus Torvalds 	int port_number = port->port->number - port->port->serial->minor;
1522*1da177e4SLinus Torvalds 
1523*1da177e4SLinus Torvalds 	dbg ("%s", __FUNCTION__);
1524*1da177e4SLinus Torvalds 
1525*1da177e4SLinus Torvalds 	return TIWriteCommandSync (port->port->serial->dev,
1526*1da177e4SLinus Torvalds 				UMPC_SET_CLR_LOOPBACK,
1527*1da177e4SLinus Torvalds 				(__u8)(UMPM_UART1_PORT + port_number),
1528*1da177e4SLinus Torvalds 				1,	/* set */
1529*1da177e4SLinus Torvalds 				NULL,
1530*1da177e4SLinus Torvalds 				0);
1531*1da177e4SLinus Torvalds }
1532*1da177e4SLinus Torvalds 
1533*1da177e4SLinus Torvalds static int TIClearLoopBack (struct edgeport_port *port)
1534*1da177e4SLinus Torvalds {
1535*1da177e4SLinus Torvalds 	int port_number = port->port->number - port->port->serial->minor;
1536*1da177e4SLinus Torvalds 
1537*1da177e4SLinus Torvalds 	dbg ("%s", __FUNCTION__);
1538*1da177e4SLinus Torvalds 
1539*1da177e4SLinus Torvalds 	return TIWriteCommandSync (port->port->serial->dev,
1540*1da177e4SLinus Torvalds 				UMPC_SET_CLR_LOOPBACK,
1541*1da177e4SLinus Torvalds 				(__u8)(UMPM_UART1_PORT + port_number),
1542*1da177e4SLinus Torvalds 				0,	/* clear */
1543*1da177e4SLinus Torvalds 				NULL,
1544*1da177e4SLinus Torvalds 				0);
1545*1da177e4SLinus Torvalds }
1546*1da177e4SLinus Torvalds 
1547*1da177e4SLinus Torvalds static int TISetBreak (struct edgeport_port *port)
1548*1da177e4SLinus Torvalds {
1549*1da177e4SLinus Torvalds 	int port_number = port->port->number - port->port->serial->minor;
1550*1da177e4SLinus Torvalds 
1551*1da177e4SLinus Torvalds 	dbg ("%s", __FUNCTION__);
1552*1da177e4SLinus Torvalds 
1553*1da177e4SLinus Torvalds 	return TIWriteCommandSync (port->port->serial->dev,
1554*1da177e4SLinus Torvalds 				UMPC_SET_CLR_BREAK,
1555*1da177e4SLinus Torvalds 				(__u8)(UMPM_UART1_PORT + port_number),
1556*1da177e4SLinus Torvalds 				1,	/* set */
1557*1da177e4SLinus Torvalds 				NULL,
1558*1da177e4SLinus Torvalds 				0);
1559*1da177e4SLinus Torvalds }
1560*1da177e4SLinus Torvalds 
1561*1da177e4SLinus Torvalds static int TIClearBreak (struct edgeport_port *port)
1562*1da177e4SLinus Torvalds {
1563*1da177e4SLinus Torvalds 	int port_number = port->port->number - port->port->serial->minor;
1564*1da177e4SLinus Torvalds 
1565*1da177e4SLinus Torvalds 	dbg ("%s", __FUNCTION__);
1566*1da177e4SLinus Torvalds 
1567*1da177e4SLinus Torvalds 	return TIWriteCommandSync (port->port->serial->dev,
1568*1da177e4SLinus Torvalds 				UMPC_SET_CLR_BREAK,
1569*1da177e4SLinus Torvalds 				(__u8)(UMPM_UART1_PORT + port_number),
1570*1da177e4SLinus Torvalds 				0,	/* clear */
1571*1da177e4SLinus Torvalds 				NULL,
1572*1da177e4SLinus Torvalds 				0);
1573*1da177e4SLinus Torvalds }
1574*1da177e4SLinus Torvalds 
1575*1da177e4SLinus Torvalds static int TIRestoreMCR (struct edgeport_port *port, __u8 mcr)
1576*1da177e4SLinus Torvalds {
1577*1da177e4SLinus Torvalds 	int status = 0;
1578*1da177e4SLinus Torvalds 
1579*1da177e4SLinus Torvalds 	dbg ("%s - %x", __FUNCTION__, mcr);
1580*1da177e4SLinus Torvalds 
1581*1da177e4SLinus Torvalds 	if (mcr & MCR_DTR)
1582*1da177e4SLinus Torvalds 		status = TISetDtr (port);
1583*1da177e4SLinus Torvalds 	else
1584*1da177e4SLinus Torvalds 		status = TIClearDtr (port);
1585*1da177e4SLinus Torvalds 
1586*1da177e4SLinus Torvalds 	if (status)
1587*1da177e4SLinus Torvalds 		return status;
1588*1da177e4SLinus Torvalds 
1589*1da177e4SLinus Torvalds 	if (mcr & MCR_RTS)
1590*1da177e4SLinus Torvalds 		status = TISetRts (port);
1591*1da177e4SLinus Torvalds 	else
1592*1da177e4SLinus Torvalds 		status = TIClearRts (port);
1593*1da177e4SLinus Torvalds 
1594*1da177e4SLinus Torvalds 	if (status)
1595*1da177e4SLinus Torvalds 		return status;
1596*1da177e4SLinus Torvalds 
1597*1da177e4SLinus Torvalds 	if (mcr & MCR_LOOPBACK)
1598*1da177e4SLinus Torvalds 		status = TISetLoopBack (port);
1599*1da177e4SLinus Torvalds 	else
1600*1da177e4SLinus Torvalds 		status = TIClearLoopBack (port);
1601*1da177e4SLinus Torvalds 
1602*1da177e4SLinus Torvalds 	return status;
1603*1da177e4SLinus Torvalds }
1604*1da177e4SLinus Torvalds 
1605*1da177e4SLinus Torvalds 
1606*1da177e4SLinus Torvalds 
1607*1da177e4SLinus Torvalds /* Convert TI LSR to standard UART flags */
1608*1da177e4SLinus Torvalds static __u8 MapLineStatus (__u8 ti_lsr)
1609*1da177e4SLinus Torvalds {
1610*1da177e4SLinus Torvalds 	__u8 lsr = 0;
1611*1da177e4SLinus Torvalds 
1612*1da177e4SLinus Torvalds #define MAP_FLAG(flagUmp, flagUart)    \
1613*1da177e4SLinus Torvalds 	if (ti_lsr & flagUmp) \
1614*1da177e4SLinus Torvalds 		lsr |= flagUart;
1615*1da177e4SLinus Torvalds 
1616*1da177e4SLinus Torvalds 	MAP_FLAG(UMP_UART_LSR_OV_MASK, LSR_OVER_ERR)	/* overrun */
1617*1da177e4SLinus Torvalds 	MAP_FLAG(UMP_UART_LSR_PE_MASK, LSR_PAR_ERR)	/* parity error */
1618*1da177e4SLinus Torvalds 	MAP_FLAG(UMP_UART_LSR_FE_MASK, LSR_FRM_ERR)	/* framing error */
1619*1da177e4SLinus Torvalds 	MAP_FLAG(UMP_UART_LSR_BR_MASK, LSR_BREAK)	/* break detected */
1620*1da177e4SLinus Torvalds 	MAP_FLAG(UMP_UART_LSR_RX_MASK, LSR_RX_AVAIL)	/* receive data available */
1621*1da177e4SLinus Torvalds 	MAP_FLAG(UMP_UART_LSR_TX_MASK, LSR_TX_EMPTY)	/* transmit holding register empty */
1622*1da177e4SLinus Torvalds 
1623*1da177e4SLinus Torvalds #undef MAP_FLAG
1624*1da177e4SLinus Torvalds 
1625*1da177e4SLinus Torvalds 	return lsr;
1626*1da177e4SLinus Torvalds }
1627*1da177e4SLinus Torvalds 
1628*1da177e4SLinus Torvalds static void handle_new_msr (struct edgeport_port *edge_port, __u8 msr)
1629*1da177e4SLinus Torvalds {
1630*1da177e4SLinus Torvalds 	struct async_icount *icount;
1631*1da177e4SLinus Torvalds 	struct tty_struct *tty;
1632*1da177e4SLinus Torvalds 
1633*1da177e4SLinus Torvalds 	dbg ("%s - %02x", __FUNCTION__, msr);
1634*1da177e4SLinus Torvalds 
1635*1da177e4SLinus Torvalds 	if (msr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR | EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) {
1636*1da177e4SLinus Torvalds 		icount = &edge_port->icount;
1637*1da177e4SLinus Torvalds 
1638*1da177e4SLinus Torvalds 		/* update input line counters */
1639*1da177e4SLinus Torvalds 		if (msr & EDGEPORT_MSR_DELTA_CTS)
1640*1da177e4SLinus Torvalds 			icount->cts++;
1641*1da177e4SLinus Torvalds 		if (msr & EDGEPORT_MSR_DELTA_DSR)
1642*1da177e4SLinus Torvalds 			icount->dsr++;
1643*1da177e4SLinus Torvalds 		if (msr & EDGEPORT_MSR_DELTA_CD)
1644*1da177e4SLinus Torvalds 			icount->dcd++;
1645*1da177e4SLinus Torvalds 		if (msr & EDGEPORT_MSR_DELTA_RI)
1646*1da177e4SLinus Torvalds 			icount->rng++;
1647*1da177e4SLinus Torvalds 		wake_up_interruptible (&edge_port->delta_msr_wait);
1648*1da177e4SLinus Torvalds 	}
1649*1da177e4SLinus Torvalds 
1650*1da177e4SLinus Torvalds 	/* Save the new modem status */
1651*1da177e4SLinus Torvalds 	edge_port->shadow_msr = msr & 0xf0;
1652*1da177e4SLinus Torvalds 
1653*1da177e4SLinus Torvalds 	tty = edge_port->port->tty;
1654*1da177e4SLinus Torvalds 	/* handle CTS flow control */
1655*1da177e4SLinus Torvalds 	if (tty && C_CRTSCTS(tty)) {
1656*1da177e4SLinus Torvalds 		if (msr & EDGEPORT_MSR_CTS) {
1657*1da177e4SLinus Torvalds 			tty->hw_stopped = 0;
1658*1da177e4SLinus Torvalds 			tty_wakeup(tty);
1659*1da177e4SLinus Torvalds 		} else {
1660*1da177e4SLinus Torvalds 			tty->hw_stopped = 1;
1661*1da177e4SLinus Torvalds 		}
1662*1da177e4SLinus Torvalds 	}
1663*1da177e4SLinus Torvalds 
1664*1da177e4SLinus Torvalds 	return;
1665*1da177e4SLinus Torvalds }
1666*1da177e4SLinus Torvalds 
1667*1da177e4SLinus Torvalds static void handle_new_lsr (struct edgeport_port *edge_port, int lsr_data, __u8 lsr, __u8 data)
1668*1da177e4SLinus Torvalds {
1669*1da177e4SLinus Torvalds 	struct async_icount *icount;
1670*1da177e4SLinus Torvalds 	__u8 new_lsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK));
1671*1da177e4SLinus Torvalds 
1672*1da177e4SLinus Torvalds 	dbg ("%s - %02x", __FUNCTION__, new_lsr);
1673*1da177e4SLinus Torvalds 
1674*1da177e4SLinus Torvalds 	edge_port->shadow_lsr = lsr;
1675*1da177e4SLinus Torvalds 
1676*1da177e4SLinus Torvalds 	if (new_lsr & LSR_BREAK) {
1677*1da177e4SLinus Torvalds 		/*
1678*1da177e4SLinus Torvalds 		 * Parity and Framing errors only count if they
1679*1da177e4SLinus Torvalds 		 * occur exclusive of a break being received.
1680*1da177e4SLinus Torvalds 		 */
1681*1da177e4SLinus Torvalds 		new_lsr &= (__u8)(LSR_OVER_ERR | LSR_BREAK);
1682*1da177e4SLinus Torvalds 	}
1683*1da177e4SLinus Torvalds 
1684*1da177e4SLinus Torvalds 	/* Place LSR data byte into Rx buffer */
1685*1da177e4SLinus Torvalds 	if (lsr_data && edge_port->port->tty)
1686*1da177e4SLinus Torvalds 		edge_tty_recv(&edge_port->port->dev, edge_port->port->tty, &data, 1);
1687*1da177e4SLinus Torvalds 
1688*1da177e4SLinus Torvalds 	/* update input line counters */
1689*1da177e4SLinus Torvalds 	icount = &edge_port->icount;
1690*1da177e4SLinus Torvalds 	if (new_lsr & LSR_BREAK)
1691*1da177e4SLinus Torvalds 		icount->brk++;
1692*1da177e4SLinus Torvalds 	if (new_lsr & LSR_OVER_ERR)
1693*1da177e4SLinus Torvalds 		icount->overrun++;
1694*1da177e4SLinus Torvalds 	if (new_lsr & LSR_PAR_ERR)
1695*1da177e4SLinus Torvalds 		icount->parity++;
1696*1da177e4SLinus Torvalds 	if (new_lsr & LSR_FRM_ERR)
1697*1da177e4SLinus Torvalds 		icount->frame++;
1698*1da177e4SLinus Torvalds }
1699*1da177e4SLinus Torvalds 
1700*1da177e4SLinus Torvalds 
1701*1da177e4SLinus Torvalds static void edge_interrupt_callback (struct urb *urb, struct pt_regs *regs)
1702*1da177e4SLinus Torvalds {
1703*1da177e4SLinus Torvalds 	struct edgeport_serial *edge_serial = (struct edgeport_serial *)urb->context;
1704*1da177e4SLinus Torvalds 	struct usb_serial_port *port;
1705*1da177e4SLinus Torvalds 	struct edgeport_port *edge_port;
1706*1da177e4SLinus Torvalds 	unsigned char *data = urb->transfer_buffer;
1707*1da177e4SLinus Torvalds 	int length = urb->actual_length;
1708*1da177e4SLinus Torvalds 	int port_number;
1709*1da177e4SLinus Torvalds 	int function;
1710*1da177e4SLinus Torvalds 	int status;
1711*1da177e4SLinus Torvalds 	__u8 lsr;
1712*1da177e4SLinus Torvalds 	__u8 msr;
1713*1da177e4SLinus Torvalds 
1714*1da177e4SLinus Torvalds 	dbg("%s", __FUNCTION__);
1715*1da177e4SLinus Torvalds 
1716*1da177e4SLinus Torvalds 	switch (urb->status) {
1717*1da177e4SLinus Torvalds 	case 0:
1718*1da177e4SLinus Torvalds 		/* success */
1719*1da177e4SLinus Torvalds 		break;
1720*1da177e4SLinus Torvalds 	case -ECONNRESET:
1721*1da177e4SLinus Torvalds 	case -ENOENT:
1722*1da177e4SLinus Torvalds 	case -ESHUTDOWN:
1723*1da177e4SLinus Torvalds 		/* this urb is terminated, clean up */
1724*1da177e4SLinus Torvalds 		dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
1725*1da177e4SLinus Torvalds 		return;
1726*1da177e4SLinus Torvalds 	default:
1727*1da177e4SLinus Torvalds 		dev_err(&urb->dev->dev, "%s - nonzero urb status received: %d\n", __FUNCTION__, urb->status);
1728*1da177e4SLinus Torvalds 		goto exit;
1729*1da177e4SLinus Torvalds 	}
1730*1da177e4SLinus Torvalds 
1731*1da177e4SLinus Torvalds 	if (!length) {
1732*1da177e4SLinus Torvalds 		dbg ("%s - no data in urb", __FUNCTION__);
1733*1da177e4SLinus Torvalds 		goto exit;
1734*1da177e4SLinus Torvalds 	}
1735*1da177e4SLinus Torvalds 
1736*1da177e4SLinus Torvalds 	usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __FUNCTION__, length, data);
1737*1da177e4SLinus Torvalds 
1738*1da177e4SLinus Torvalds 	if (length != 2) {
1739*1da177e4SLinus Torvalds 		dbg ("%s - expecting packet of size 2, got %d", __FUNCTION__, length);
1740*1da177e4SLinus Torvalds 		goto exit;
1741*1da177e4SLinus Torvalds 	}
1742*1da177e4SLinus Torvalds 
1743*1da177e4SLinus Torvalds 	port_number = TIUMP_GET_PORT_FROM_CODE (data[0]);
1744*1da177e4SLinus Torvalds 	function    = TIUMP_GET_FUNC_FROM_CODE (data[0]);
1745*1da177e4SLinus Torvalds 	dbg ("%s - port_number %d, function %d, info 0x%x",
1746*1da177e4SLinus Torvalds 	     __FUNCTION__, port_number, function, data[1]);
1747*1da177e4SLinus Torvalds 	port = edge_serial->serial->port[port_number];
1748*1da177e4SLinus Torvalds 	edge_port = usb_get_serial_port_data(port);
1749*1da177e4SLinus Torvalds 	if (!edge_port) {
1750*1da177e4SLinus Torvalds 		dbg ("%s - edge_port not found", __FUNCTION__);
1751*1da177e4SLinus Torvalds 		return;
1752*1da177e4SLinus Torvalds 	}
1753*1da177e4SLinus Torvalds 	switch (function) {
1754*1da177e4SLinus Torvalds 	case TIUMP_INTERRUPT_CODE_LSR:
1755*1da177e4SLinus Torvalds 		lsr = MapLineStatus(data[1]);
1756*1da177e4SLinus Torvalds 		if (lsr & UMP_UART_LSR_DATA_MASK) {
1757*1da177e4SLinus Torvalds 			/* Save the LSR event for bulk read completion routine */
1758*1da177e4SLinus Torvalds 			dbg ("%s - LSR Event Port %u LSR Status = %02x",
1759*1da177e4SLinus Torvalds 			     __FUNCTION__, port_number, lsr);
1760*1da177e4SLinus Torvalds 			edge_port->lsr_event = 1;
1761*1da177e4SLinus Torvalds 			edge_port->lsr_mask = lsr;
1762*1da177e4SLinus Torvalds 		} else {
1763*1da177e4SLinus Torvalds 			dbg ("%s - ===== Port %d LSR Status = %02x ======",
1764*1da177e4SLinus Torvalds 			     __FUNCTION__, port_number, lsr);
1765*1da177e4SLinus Torvalds 			handle_new_lsr (edge_port, 0, lsr, 0);
1766*1da177e4SLinus Torvalds 		}
1767*1da177e4SLinus Torvalds 		break;
1768*1da177e4SLinus Torvalds 
1769*1da177e4SLinus Torvalds 	case TIUMP_INTERRUPT_CODE_MSR:	// MSR
1770*1da177e4SLinus Torvalds 		/* Copy MSR from UMP */
1771*1da177e4SLinus Torvalds 		msr = data[1];
1772*1da177e4SLinus Torvalds 		dbg ("%s - ===== Port %u MSR Status = %02x ======\n",
1773*1da177e4SLinus Torvalds 		     __FUNCTION__, port_number, msr);
1774*1da177e4SLinus Torvalds 		handle_new_msr (edge_port, msr);
1775*1da177e4SLinus Torvalds 		break;
1776*1da177e4SLinus Torvalds 
1777*1da177e4SLinus Torvalds 	default:
1778*1da177e4SLinus Torvalds 		dev_err (&urb->dev->dev, "%s - Unknown Interrupt code from UMP %x\n",
1779*1da177e4SLinus Torvalds 			 __FUNCTION__, data[1]);
1780*1da177e4SLinus Torvalds 		break;
1781*1da177e4SLinus Torvalds 
1782*1da177e4SLinus Torvalds 	}
1783*1da177e4SLinus Torvalds 
1784*1da177e4SLinus Torvalds exit:
1785*1da177e4SLinus Torvalds 	status = usb_submit_urb (urb, GFP_ATOMIC);
1786*1da177e4SLinus Torvalds 	if (status)
1787*1da177e4SLinus Torvalds 		dev_err (&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n",
1788*1da177e4SLinus Torvalds 			 __FUNCTION__, status);
1789*1da177e4SLinus Torvalds }
1790*1da177e4SLinus Torvalds 
1791*1da177e4SLinus Torvalds static void edge_bulk_in_callback (struct urb *urb, struct pt_regs *regs)
1792*1da177e4SLinus Torvalds {
1793*1da177e4SLinus Torvalds 	struct edgeport_port *edge_port = (struct edgeport_port *)urb->context;
1794*1da177e4SLinus Torvalds 	unsigned char *data = urb->transfer_buffer;
1795*1da177e4SLinus Torvalds 	struct tty_struct *tty;
1796*1da177e4SLinus Torvalds 	int status = 0;
1797*1da177e4SLinus Torvalds 	int port_number;
1798*1da177e4SLinus Torvalds 
1799*1da177e4SLinus Torvalds 	dbg("%s", __FUNCTION__);
1800*1da177e4SLinus Torvalds 
1801*1da177e4SLinus Torvalds 	switch (urb->status) {
1802*1da177e4SLinus Torvalds 	case 0:
1803*1da177e4SLinus Torvalds 		/* success */
1804*1da177e4SLinus Torvalds 		break;
1805*1da177e4SLinus Torvalds 	case -ECONNRESET:
1806*1da177e4SLinus Torvalds 	case -ENOENT:
1807*1da177e4SLinus Torvalds 	case -ESHUTDOWN:
1808*1da177e4SLinus Torvalds 		/* this urb is terminated, clean up */
1809*1da177e4SLinus Torvalds 		dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
1810*1da177e4SLinus Torvalds 		return;
1811*1da177e4SLinus Torvalds 	default:
1812*1da177e4SLinus Torvalds 		dev_err (&urb->dev->dev,"%s - nonzero read bulk status received: %d\n",
1813*1da177e4SLinus Torvalds 		     __FUNCTION__, urb->status );
1814*1da177e4SLinus Torvalds 	}
1815*1da177e4SLinus Torvalds 
1816*1da177e4SLinus Torvalds 	if (urb->status == -EPIPE)
1817*1da177e4SLinus Torvalds 		goto exit;
1818*1da177e4SLinus Torvalds 
1819*1da177e4SLinus Torvalds 	if (urb->status) {
1820*1da177e4SLinus Torvalds 		dev_err(&urb->dev->dev,"%s - stopping read!\n", __FUNCTION__);
1821*1da177e4SLinus Torvalds 		return;
1822*1da177e4SLinus Torvalds 	}
1823*1da177e4SLinus Torvalds 
1824*1da177e4SLinus Torvalds 	port_number = edge_port->port->number - edge_port->port->serial->minor;
1825*1da177e4SLinus Torvalds 
1826*1da177e4SLinus Torvalds 	if (edge_port->lsr_event) {
1827*1da177e4SLinus Torvalds 		edge_port->lsr_event = 0;
1828*1da177e4SLinus Torvalds 		dbg ("%s ===== Port %u LSR Status = %02x, Data = %02x ======",
1829*1da177e4SLinus Torvalds 		     __FUNCTION__, port_number, edge_port->lsr_mask, *data);
1830*1da177e4SLinus Torvalds 		handle_new_lsr (edge_port, 1, edge_port->lsr_mask, *data);
1831*1da177e4SLinus Torvalds 		/* Adjust buffer length/pointer */
1832*1da177e4SLinus Torvalds 		--urb->actual_length;
1833*1da177e4SLinus Torvalds 		++data;
1834*1da177e4SLinus Torvalds 	}
1835*1da177e4SLinus Torvalds 
1836*1da177e4SLinus Torvalds 	tty = edge_port->port->tty;
1837*1da177e4SLinus Torvalds 	if (tty && urb->actual_length) {
1838*1da177e4SLinus Torvalds 		usb_serial_debug_data(debug, &edge_port->port->dev, __FUNCTION__, urb->actual_length, data);
1839*1da177e4SLinus Torvalds 
1840*1da177e4SLinus Torvalds 		if (edge_port->close_pending) {
1841*1da177e4SLinus Torvalds 			dbg ("%s - close is pending, dropping data on the floor.", __FUNCTION__);
1842*1da177e4SLinus Torvalds 		} else {
1843*1da177e4SLinus Torvalds 			edge_tty_recv(&edge_port->port->dev, tty, data, urb->actual_length);
1844*1da177e4SLinus Torvalds 		}
1845*1da177e4SLinus Torvalds 		edge_port->icount.rx += urb->actual_length;
1846*1da177e4SLinus Torvalds 	}
1847*1da177e4SLinus Torvalds 
1848*1da177e4SLinus Torvalds exit:
1849*1da177e4SLinus Torvalds 	/* continue read unless stopped */
1850*1da177e4SLinus Torvalds 	spin_lock(&edge_port->ep_lock);
1851*1da177e4SLinus Torvalds 	if (edge_port->ep_read_urb_state == EDGE_READ_URB_RUNNING) {
1852*1da177e4SLinus Torvalds 		urb->dev = edge_port->port->serial->dev;
1853*1da177e4SLinus Torvalds 		status = usb_submit_urb(urb, GFP_ATOMIC);
1854*1da177e4SLinus Torvalds 	} else if (edge_port->ep_read_urb_state == EDGE_READ_URB_STOPPING) {
1855*1da177e4SLinus Torvalds 		edge_port->ep_read_urb_state = EDGE_READ_URB_STOPPED;
1856*1da177e4SLinus Torvalds 	}
1857*1da177e4SLinus Torvalds 	spin_unlock(&edge_port->ep_lock);
1858*1da177e4SLinus Torvalds 	if (status)
1859*1da177e4SLinus Torvalds 		dev_err (&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n",
1860*1da177e4SLinus Torvalds 			 __FUNCTION__, status);
1861*1da177e4SLinus Torvalds }
1862*1da177e4SLinus Torvalds 
1863*1da177e4SLinus Torvalds static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length)
1864*1da177e4SLinus Torvalds {
1865*1da177e4SLinus Torvalds 	int cnt;
1866*1da177e4SLinus Torvalds 
1867*1da177e4SLinus Torvalds 	do {
1868*1da177e4SLinus Torvalds 		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
1869*1da177e4SLinus Torvalds 			tty_flip_buffer_push(tty);
1870*1da177e4SLinus Torvalds 			if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
1871*1da177e4SLinus Torvalds 				dev_err(dev, "%s - dropping data, %d bytes lost\n",
1872*1da177e4SLinus Torvalds 					__FUNCTION__, length);
1873*1da177e4SLinus Torvalds 				return;
1874*1da177e4SLinus Torvalds 			}
1875*1da177e4SLinus Torvalds 		}
1876*1da177e4SLinus Torvalds 		cnt = min(length, TTY_FLIPBUF_SIZE - tty->flip.count);
1877*1da177e4SLinus Torvalds 		memcpy(tty->flip.char_buf_ptr, data, cnt);
1878*1da177e4SLinus Torvalds 		memset(tty->flip.flag_buf_ptr, 0, cnt);
1879*1da177e4SLinus Torvalds 		tty->flip.char_buf_ptr += cnt;
1880*1da177e4SLinus Torvalds 		tty->flip.flag_buf_ptr += cnt;
1881*1da177e4SLinus Torvalds 		tty->flip.count += cnt;
1882*1da177e4SLinus Torvalds 		data += cnt;
1883*1da177e4SLinus Torvalds 		length -= cnt;
1884*1da177e4SLinus Torvalds 	} while (length > 0);
1885*1da177e4SLinus Torvalds 
1886*1da177e4SLinus Torvalds 	tty_flip_buffer_push(tty);
1887*1da177e4SLinus Torvalds }
1888*1da177e4SLinus Torvalds 
1889*1da177e4SLinus Torvalds static void edge_bulk_out_callback (struct urb *urb, struct pt_regs *regs)
1890*1da177e4SLinus Torvalds {
1891*1da177e4SLinus Torvalds 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
1892*1da177e4SLinus Torvalds 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
1893*1da177e4SLinus Torvalds 
1894*1da177e4SLinus Torvalds 	dbg ("%s - port %d", __FUNCTION__, port->number);
1895*1da177e4SLinus Torvalds 
1896*1da177e4SLinus Torvalds 	edge_port->ep_write_urb_in_use = 0;
1897*1da177e4SLinus Torvalds 
1898*1da177e4SLinus Torvalds 	switch (urb->status) {
1899*1da177e4SLinus Torvalds 	case 0:
1900*1da177e4SLinus Torvalds 		/* success */
1901*1da177e4SLinus Torvalds 		break;
1902*1da177e4SLinus Torvalds 	case -ECONNRESET:
1903*1da177e4SLinus Torvalds 	case -ENOENT:
1904*1da177e4SLinus Torvalds 	case -ESHUTDOWN:
1905*1da177e4SLinus Torvalds 		/* this urb is terminated, clean up */
1906*1da177e4SLinus Torvalds 		dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
1907*1da177e4SLinus Torvalds 		return;
1908*1da177e4SLinus Torvalds 	default:
1909*1da177e4SLinus Torvalds 		dev_err (&urb->dev->dev,"%s - nonzero write bulk status received: %d\n",
1910*1da177e4SLinus Torvalds 		     __FUNCTION__, urb->status);
1911*1da177e4SLinus Torvalds 	}
1912*1da177e4SLinus Torvalds 
1913*1da177e4SLinus Torvalds 	/* send any buffered data */
1914*1da177e4SLinus Torvalds 	edge_send(port);
1915*1da177e4SLinus Torvalds }
1916*1da177e4SLinus Torvalds 
1917*1da177e4SLinus Torvalds static int edge_open (struct usb_serial_port *port, struct file * filp)
1918*1da177e4SLinus Torvalds {
1919*1da177e4SLinus Torvalds 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
1920*1da177e4SLinus Torvalds 	struct edgeport_serial *edge_serial;
1921*1da177e4SLinus Torvalds 	struct usb_device *dev;
1922*1da177e4SLinus Torvalds 	struct urb *urb;
1923*1da177e4SLinus Torvalds 	int port_number;
1924*1da177e4SLinus Torvalds 	int status;
1925*1da177e4SLinus Torvalds 	u16 open_settings;
1926*1da177e4SLinus Torvalds 	u8 transaction_timeout;
1927*1da177e4SLinus Torvalds 
1928*1da177e4SLinus Torvalds 	dbg("%s - port %d", __FUNCTION__, port->number);
1929*1da177e4SLinus Torvalds 
1930*1da177e4SLinus Torvalds 	if (edge_port == NULL)
1931*1da177e4SLinus Torvalds 		return -ENODEV;
1932*1da177e4SLinus Torvalds 
1933*1da177e4SLinus Torvalds 	if (port->tty)
1934*1da177e4SLinus Torvalds 		port->tty->low_latency = low_latency;
1935*1da177e4SLinus Torvalds 
1936*1da177e4SLinus Torvalds 	port_number = port->number - port->serial->minor;
1937*1da177e4SLinus Torvalds 	switch (port_number) {
1938*1da177e4SLinus Torvalds 		case 0:
1939*1da177e4SLinus Torvalds 			edge_port->uart_base = UMPMEM_BASE_UART1;
1940*1da177e4SLinus Torvalds 			edge_port->dma_address = UMPD_OEDB1_ADDRESS;
1941*1da177e4SLinus Torvalds 			break;
1942*1da177e4SLinus Torvalds 		case 1:
1943*1da177e4SLinus Torvalds 			edge_port->uart_base = UMPMEM_BASE_UART2;
1944*1da177e4SLinus Torvalds 			edge_port->dma_address = UMPD_OEDB2_ADDRESS;
1945*1da177e4SLinus Torvalds 			break;
1946*1da177e4SLinus Torvalds 		default:
1947*1da177e4SLinus Torvalds 			dev_err (&port->dev, "Unknown port number!!!\n");
1948*1da177e4SLinus Torvalds 			return -ENODEV;
1949*1da177e4SLinus Torvalds 	}
1950*1da177e4SLinus Torvalds 
1951*1da177e4SLinus Torvalds 	dbg ("%s - port_number = %d, uart_base = %04x, dma_address = %04x",
1952*1da177e4SLinus Torvalds 	     __FUNCTION__, port_number, edge_port->uart_base, edge_port->dma_address);
1953*1da177e4SLinus Torvalds 
1954*1da177e4SLinus Torvalds 	dev = port->serial->dev;
1955*1da177e4SLinus Torvalds 
1956*1da177e4SLinus Torvalds 	memset (&(edge_port->icount), 0x00, sizeof(edge_port->icount));
1957*1da177e4SLinus Torvalds 	init_waitqueue_head (&edge_port->delta_msr_wait);
1958*1da177e4SLinus Torvalds 
1959*1da177e4SLinus Torvalds 	/* turn off loopback */
1960*1da177e4SLinus Torvalds 	status = TIClearLoopBack (edge_port);
1961*1da177e4SLinus Torvalds 	if (status) {
1962*1da177e4SLinus Torvalds 		dev_err(&port->dev,"%s - cannot send clear loopback command, %d\n",
1963*1da177e4SLinus Torvalds 			__FUNCTION__, status);
1964*1da177e4SLinus Torvalds 		return status;
1965*1da177e4SLinus Torvalds 	}
1966*1da177e4SLinus Torvalds 
1967*1da177e4SLinus Torvalds 	/* set up the port settings */
1968*1da177e4SLinus Torvalds 	edge_set_termios (port, NULL);
1969*1da177e4SLinus Torvalds 
1970*1da177e4SLinus Torvalds 	/* open up the port */
1971*1da177e4SLinus Torvalds 
1972*1da177e4SLinus Torvalds 	/* milliseconds to timeout for DMA transfer */
1973*1da177e4SLinus Torvalds 	transaction_timeout = 2;
1974*1da177e4SLinus Torvalds 
1975*1da177e4SLinus Torvalds 	edge_port->ump_read_timeout = max (20, ((transaction_timeout * 3) / 2) );
1976*1da177e4SLinus Torvalds 
1977*1da177e4SLinus Torvalds 	// milliseconds to timeout for DMA transfer
1978*1da177e4SLinus Torvalds 	open_settings = (u8)(UMP_DMA_MODE_CONTINOUS |
1979*1da177e4SLinus Torvalds 			     UMP_PIPE_TRANS_TIMEOUT_ENA |
1980*1da177e4SLinus Torvalds 			     (transaction_timeout << 2));
1981*1da177e4SLinus Torvalds 
1982*1da177e4SLinus Torvalds 	dbg ("%s - Sending UMPC_OPEN_PORT", __FUNCTION__);
1983*1da177e4SLinus Torvalds 
1984*1da177e4SLinus Torvalds 	/* Tell TI to open and start the port */
1985*1da177e4SLinus Torvalds 	status = TIWriteCommandSync (dev,
1986*1da177e4SLinus Torvalds 					UMPC_OPEN_PORT,
1987*1da177e4SLinus Torvalds 					(u8)(UMPM_UART1_PORT + port_number),
1988*1da177e4SLinus Torvalds 					open_settings,
1989*1da177e4SLinus Torvalds 					NULL,
1990*1da177e4SLinus Torvalds 					0);
1991*1da177e4SLinus Torvalds 	if (status) {
1992*1da177e4SLinus Torvalds 		dev_err(&port->dev,"%s - cannot send open command, %d\n", __FUNCTION__, status);
1993*1da177e4SLinus Torvalds 		return status;
1994*1da177e4SLinus Torvalds 	}
1995*1da177e4SLinus Torvalds 
1996*1da177e4SLinus Torvalds 	/* Start the DMA? */
1997*1da177e4SLinus Torvalds 	status = TIWriteCommandSync (dev,
1998*1da177e4SLinus Torvalds 					UMPC_START_PORT,
1999*1da177e4SLinus Torvalds 					(u8)(UMPM_UART1_PORT + port_number),
2000*1da177e4SLinus Torvalds 					0,
2001*1da177e4SLinus Torvalds 					NULL,
2002*1da177e4SLinus Torvalds 					0);
2003*1da177e4SLinus Torvalds 	if (status) {
2004*1da177e4SLinus Torvalds 		dev_err(&port->dev,"%s - cannot send start DMA command, %d\n", __FUNCTION__, status);
2005*1da177e4SLinus Torvalds 		return status;
2006*1da177e4SLinus Torvalds 	}
2007*1da177e4SLinus Torvalds 
2008*1da177e4SLinus Torvalds 	/* Clear TX and RX buffers in UMP */
2009*1da177e4SLinus Torvalds 	status = TIPurgeDataSync (port, UMP_PORT_DIR_OUT | UMP_PORT_DIR_IN);
2010*1da177e4SLinus Torvalds 	if (status) {
2011*1da177e4SLinus Torvalds 		dev_err(&port->dev,"%s - cannot send clear buffers command, %d\n", __FUNCTION__, status);
2012*1da177e4SLinus Torvalds 		return status;
2013*1da177e4SLinus Torvalds 	}
2014*1da177e4SLinus Torvalds 
2015*1da177e4SLinus Torvalds 	/* Read Initial MSR */
2016*1da177e4SLinus Torvalds 	status = TIReadVendorRequestSync (dev,
2017*1da177e4SLinus Torvalds 					UMPC_READ_MSR,	// Request
2018*1da177e4SLinus Torvalds 					0,		// wValue
2019*1da177e4SLinus Torvalds 					(__u16)(UMPM_UART1_PORT + port_number),	// wIndex (Address)
2020*1da177e4SLinus Torvalds 					&edge_port->shadow_msr,			// TransferBuffer
2021*1da177e4SLinus Torvalds 					1);					// TransferBufferLength
2022*1da177e4SLinus Torvalds 	if (status) {
2023*1da177e4SLinus Torvalds  		dev_err(&port->dev,"%s - cannot send read MSR command, %d\n", __FUNCTION__, status);
2024*1da177e4SLinus Torvalds 		return status;
2025*1da177e4SLinus Torvalds 	}
2026*1da177e4SLinus Torvalds 
2027*1da177e4SLinus Torvalds 	dbg ("ShadowMSR 0x%X", edge_port->shadow_msr);
2028*1da177e4SLinus Torvalds 
2029*1da177e4SLinus Torvalds 	/* Set Initial MCR */
2030*1da177e4SLinus Torvalds 	edge_port->shadow_mcr = MCR_RTS | MCR_DTR;
2031*1da177e4SLinus Torvalds 	dbg ("ShadowMCR 0x%X", edge_port->shadow_mcr);
2032*1da177e4SLinus Torvalds 
2033*1da177e4SLinus Torvalds 	edge_serial = edge_port->edge_serial;
2034*1da177e4SLinus Torvalds 	if (down_interruptible(&edge_serial->es_sem))
2035*1da177e4SLinus Torvalds 		return -ERESTARTSYS;
2036*1da177e4SLinus Torvalds 	if (edge_serial->num_ports_open == 0) {
2037*1da177e4SLinus Torvalds 		/* we are the first port to be opened, let's post the interrupt urb */
2038*1da177e4SLinus Torvalds 		urb = edge_serial->serial->port[0]->interrupt_in_urb;
2039*1da177e4SLinus Torvalds 		if (!urb) {
2040*1da177e4SLinus Torvalds 			dev_err (&port->dev, "%s - no interrupt urb present, exiting\n", __FUNCTION__);
2041*1da177e4SLinus Torvalds 			status = -EINVAL;
2042*1da177e4SLinus Torvalds 			goto up_es_sem;
2043*1da177e4SLinus Torvalds 		}
2044*1da177e4SLinus Torvalds 		urb->complete = edge_interrupt_callback;
2045*1da177e4SLinus Torvalds 		urb->context = edge_serial;
2046*1da177e4SLinus Torvalds 		urb->dev = dev;
2047*1da177e4SLinus Torvalds 		status = usb_submit_urb (urb, GFP_KERNEL);
2048*1da177e4SLinus Torvalds 		if (status) {
2049*1da177e4SLinus Torvalds 			dev_err (&port->dev, "%s - usb_submit_urb failed with value %d\n", __FUNCTION__, status);
2050*1da177e4SLinus Torvalds 			goto up_es_sem;
2051*1da177e4SLinus Torvalds 		}
2052*1da177e4SLinus Torvalds 	}
2053*1da177e4SLinus Torvalds 
2054*1da177e4SLinus Torvalds 	/*
2055*1da177e4SLinus Torvalds 	 * reset the data toggle on the bulk endpoints to work around bug in
2056*1da177e4SLinus Torvalds 	 * host controllers where things get out of sync some times
2057*1da177e4SLinus Torvalds 	 */
2058*1da177e4SLinus Torvalds 	usb_clear_halt (dev, port->write_urb->pipe);
2059*1da177e4SLinus Torvalds 	usb_clear_halt (dev, port->read_urb->pipe);
2060*1da177e4SLinus Torvalds 
2061*1da177e4SLinus Torvalds 	/* start up our bulk read urb */
2062*1da177e4SLinus Torvalds 	urb = port->read_urb;
2063*1da177e4SLinus Torvalds 	if (!urb) {
2064*1da177e4SLinus Torvalds 		dev_err (&port->dev, "%s - no read urb present, exiting\n", __FUNCTION__);
2065*1da177e4SLinus Torvalds 		status = -EINVAL;
2066*1da177e4SLinus Torvalds 		goto unlink_int_urb;
2067*1da177e4SLinus Torvalds 	}
2068*1da177e4SLinus Torvalds 	edge_port->ep_read_urb_state = EDGE_READ_URB_RUNNING;
2069*1da177e4SLinus Torvalds 	urb->complete = edge_bulk_in_callback;
2070*1da177e4SLinus Torvalds 	urb->context = edge_port;
2071*1da177e4SLinus Torvalds 	urb->dev = dev;
2072*1da177e4SLinus Torvalds 	status = usb_submit_urb (urb, GFP_KERNEL);
2073*1da177e4SLinus Torvalds 	if (status) {
2074*1da177e4SLinus Torvalds 		dev_err (&port->dev, "%s - read bulk usb_submit_urb failed with value %d\n", __FUNCTION__, status);
2075*1da177e4SLinus Torvalds 		goto unlink_int_urb;
2076*1da177e4SLinus Torvalds 	}
2077*1da177e4SLinus Torvalds 
2078*1da177e4SLinus Torvalds 	++edge_serial->num_ports_open;
2079*1da177e4SLinus Torvalds 
2080*1da177e4SLinus Torvalds 	dbg("%s - exited", __FUNCTION__);
2081*1da177e4SLinus Torvalds 
2082*1da177e4SLinus Torvalds 	goto up_es_sem;
2083*1da177e4SLinus Torvalds 
2084*1da177e4SLinus Torvalds unlink_int_urb:
2085*1da177e4SLinus Torvalds 	if (edge_port->edge_serial->num_ports_open == 0)
2086*1da177e4SLinus Torvalds 		usb_kill_urb(port->serial->port[0]->interrupt_in_urb);
2087*1da177e4SLinus Torvalds up_es_sem:
2088*1da177e4SLinus Torvalds 	up(&edge_serial->es_sem);
2089*1da177e4SLinus Torvalds 	return status;
2090*1da177e4SLinus Torvalds }
2091*1da177e4SLinus Torvalds 
2092*1da177e4SLinus Torvalds static void edge_close (struct usb_serial_port *port, struct file *filp)
2093*1da177e4SLinus Torvalds {
2094*1da177e4SLinus Torvalds 	struct edgeport_serial *edge_serial;
2095*1da177e4SLinus Torvalds 	struct edgeport_port *edge_port;
2096*1da177e4SLinus Torvalds 	int port_number;
2097*1da177e4SLinus Torvalds 	int status;
2098*1da177e4SLinus Torvalds 
2099*1da177e4SLinus Torvalds 	dbg("%s - port %d", __FUNCTION__, port->number);
2100*1da177e4SLinus Torvalds 
2101*1da177e4SLinus Torvalds 	edge_serial = usb_get_serial_data(port->serial);
2102*1da177e4SLinus Torvalds 	edge_port = usb_get_serial_port_data(port);
2103*1da177e4SLinus Torvalds 	if ((edge_serial == NULL) || (edge_port == NULL))
2104*1da177e4SLinus Torvalds 		return;
2105*1da177e4SLinus Torvalds 
2106*1da177e4SLinus Torvalds 	/* The bulkreadcompletion routine will check
2107*1da177e4SLinus Torvalds 	 * this flag and dump add read data */
2108*1da177e4SLinus Torvalds 	edge_port->close_pending = 1;
2109*1da177e4SLinus Torvalds 
2110*1da177e4SLinus Torvalds 	/* chase the port close and flush */
2111*1da177e4SLinus Torvalds 	TIChasePort (edge_port, (HZ*closing_wait)/100, 1);
2112*1da177e4SLinus Torvalds 
2113*1da177e4SLinus Torvalds 	usb_kill_urb(port->read_urb);
2114*1da177e4SLinus Torvalds 	usb_kill_urb(port->write_urb);
2115*1da177e4SLinus Torvalds 	edge_port->ep_write_urb_in_use = 0;
2116*1da177e4SLinus Torvalds 
2117*1da177e4SLinus Torvalds 	/* assuming we can still talk to the device,
2118*1da177e4SLinus Torvalds 	 * send a close port command to it */
2119*1da177e4SLinus Torvalds 	dbg("%s - send umpc_close_port", __FUNCTION__);
2120*1da177e4SLinus Torvalds 	port_number = port->number - port->serial->minor;
2121*1da177e4SLinus Torvalds 	status = TIWriteCommandSync (port->serial->dev,
2122*1da177e4SLinus Torvalds 				     UMPC_CLOSE_PORT,
2123*1da177e4SLinus Torvalds 				     (__u8)(UMPM_UART1_PORT + port_number),
2124*1da177e4SLinus Torvalds 				     0,
2125*1da177e4SLinus Torvalds 				     NULL,
2126*1da177e4SLinus Torvalds 				     0);
2127*1da177e4SLinus Torvalds 	down(&edge_serial->es_sem);
2128*1da177e4SLinus Torvalds 	--edge_port->edge_serial->num_ports_open;
2129*1da177e4SLinus Torvalds 	if (edge_port->edge_serial->num_ports_open <= 0) {
2130*1da177e4SLinus Torvalds 		/* last port is now closed, let's shut down our interrupt urb */
2131*1da177e4SLinus Torvalds 		usb_kill_urb(port->serial->port[0]->interrupt_in_urb);
2132*1da177e4SLinus Torvalds 		edge_port->edge_serial->num_ports_open = 0;
2133*1da177e4SLinus Torvalds 	}
2134*1da177e4SLinus Torvalds 	up(&edge_serial->es_sem);
2135*1da177e4SLinus Torvalds 	edge_port->close_pending = 0;
2136*1da177e4SLinus Torvalds 
2137*1da177e4SLinus Torvalds 	dbg("%s - exited", __FUNCTION__);
2138*1da177e4SLinus Torvalds }
2139*1da177e4SLinus Torvalds 
2140*1da177e4SLinus Torvalds static int edge_write (struct usb_serial_port *port, const unsigned char *data, int count)
2141*1da177e4SLinus Torvalds {
2142*1da177e4SLinus Torvalds 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
2143*1da177e4SLinus Torvalds 	unsigned long flags;
2144*1da177e4SLinus Torvalds 
2145*1da177e4SLinus Torvalds 	dbg("%s - port %d", __FUNCTION__, port->number);
2146*1da177e4SLinus Torvalds 
2147*1da177e4SLinus Torvalds 	if (count == 0) {
2148*1da177e4SLinus Torvalds 		dbg("%s - write request of 0 bytes", __FUNCTION__);
2149*1da177e4SLinus Torvalds 		return 0;
2150*1da177e4SLinus Torvalds 	}
2151*1da177e4SLinus Torvalds 
2152*1da177e4SLinus Torvalds 	if (edge_port == NULL)
2153*1da177e4SLinus Torvalds 		return -ENODEV;
2154*1da177e4SLinus Torvalds 	if (edge_port->close_pending == 1)
2155*1da177e4SLinus Torvalds 		return -ENODEV;
2156*1da177e4SLinus Torvalds 
2157*1da177e4SLinus Torvalds 	spin_lock_irqsave(&edge_port->ep_lock, flags);
2158*1da177e4SLinus Torvalds 	count = edge_buf_put(edge_port->ep_out_buf, data, count);
2159*1da177e4SLinus Torvalds 	spin_unlock_irqrestore(&edge_port->ep_lock, flags);
2160*1da177e4SLinus Torvalds 
2161*1da177e4SLinus Torvalds 	edge_send(port);
2162*1da177e4SLinus Torvalds 
2163*1da177e4SLinus Torvalds 	return count;
2164*1da177e4SLinus Torvalds }
2165*1da177e4SLinus Torvalds 
2166*1da177e4SLinus Torvalds static void edge_send(struct usb_serial_port *port)
2167*1da177e4SLinus Torvalds {
2168*1da177e4SLinus Torvalds 	int count, result;
2169*1da177e4SLinus Torvalds 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
2170*1da177e4SLinus Torvalds 	struct tty_struct *tty = port->tty;
2171*1da177e4SLinus Torvalds 	unsigned long flags;
2172*1da177e4SLinus Torvalds 
2173*1da177e4SLinus Torvalds 
2174*1da177e4SLinus Torvalds 	dbg("%s - port %d", __FUNCTION__, port->number);
2175*1da177e4SLinus Torvalds 
2176*1da177e4SLinus Torvalds 	spin_lock_irqsave(&edge_port->ep_lock, flags);
2177*1da177e4SLinus Torvalds 
2178*1da177e4SLinus Torvalds 	if (edge_port->ep_write_urb_in_use) {
2179*1da177e4SLinus Torvalds 		spin_unlock_irqrestore(&edge_port->ep_lock, flags);
2180*1da177e4SLinus Torvalds 		return;
2181*1da177e4SLinus Torvalds 	}
2182*1da177e4SLinus Torvalds 
2183*1da177e4SLinus Torvalds 	count = edge_buf_get(edge_port->ep_out_buf,
2184*1da177e4SLinus Torvalds 				port->write_urb->transfer_buffer,
2185*1da177e4SLinus Torvalds 				port->bulk_out_size);
2186*1da177e4SLinus Torvalds 
2187*1da177e4SLinus Torvalds 	if (count == 0) {
2188*1da177e4SLinus Torvalds 		spin_unlock_irqrestore(&edge_port->ep_lock, flags);
2189*1da177e4SLinus Torvalds 		return;
2190*1da177e4SLinus Torvalds 	}
2191*1da177e4SLinus Torvalds 
2192*1da177e4SLinus Torvalds 	edge_port->ep_write_urb_in_use = 1;
2193*1da177e4SLinus Torvalds 
2194*1da177e4SLinus Torvalds 	spin_unlock_irqrestore(&edge_port->ep_lock, flags);
2195*1da177e4SLinus Torvalds 
2196*1da177e4SLinus Torvalds 	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, port->write_urb->transfer_buffer);
2197*1da177e4SLinus Torvalds 
2198*1da177e4SLinus Torvalds 	/* set up our urb */
2199*1da177e4SLinus Torvalds 	usb_fill_bulk_urb (port->write_urb, port->serial->dev,
2200*1da177e4SLinus Torvalds 			   usb_sndbulkpipe (port->serial->dev,
2201*1da177e4SLinus Torvalds 					    port->bulk_out_endpointAddress),
2202*1da177e4SLinus Torvalds 			   port->write_urb->transfer_buffer, count,
2203*1da177e4SLinus Torvalds 			   edge_bulk_out_callback,
2204*1da177e4SLinus Torvalds 			   port);
2205*1da177e4SLinus Torvalds 
2206*1da177e4SLinus Torvalds 	/* send the data out the bulk port */
2207*1da177e4SLinus Torvalds 	result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
2208*1da177e4SLinus Torvalds 	if (result) {
2209*1da177e4SLinus Torvalds 		dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
2210*1da177e4SLinus Torvalds 		edge_port->ep_write_urb_in_use = 0;
2211*1da177e4SLinus Torvalds 		// TODO: reschedule edge_send
2212*1da177e4SLinus Torvalds 	} else {
2213*1da177e4SLinus Torvalds 		edge_port->icount.tx += count;
2214*1da177e4SLinus Torvalds 	}
2215*1da177e4SLinus Torvalds 
2216*1da177e4SLinus Torvalds 	/* wakeup any process waiting for writes to complete */
2217*1da177e4SLinus Torvalds 	/* there is now more room in the buffer for new writes */
2218*1da177e4SLinus Torvalds 	if (tty) {
2219*1da177e4SLinus Torvalds 		/* let the tty driver wakeup if it has a special write_wakeup function */
2220*1da177e4SLinus Torvalds 		tty_wakeup(tty);
2221*1da177e4SLinus Torvalds 	}
2222*1da177e4SLinus Torvalds }
2223*1da177e4SLinus Torvalds 
2224*1da177e4SLinus Torvalds static int edge_write_room (struct usb_serial_port *port)
2225*1da177e4SLinus Torvalds {
2226*1da177e4SLinus Torvalds 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
2227*1da177e4SLinus Torvalds 	int room = 0;
2228*1da177e4SLinus Torvalds 	unsigned long flags;
2229*1da177e4SLinus Torvalds 
2230*1da177e4SLinus Torvalds 	dbg("%s - port %d", __FUNCTION__, port->number);
2231*1da177e4SLinus Torvalds 
2232*1da177e4SLinus Torvalds 	if (edge_port == NULL)
2233*1da177e4SLinus Torvalds 		return -ENODEV;
2234*1da177e4SLinus Torvalds 	if (edge_port->close_pending == 1)
2235*1da177e4SLinus Torvalds 		return -ENODEV;
2236*1da177e4SLinus Torvalds 
2237*1da177e4SLinus Torvalds 	spin_lock_irqsave(&edge_port->ep_lock, flags);
2238*1da177e4SLinus Torvalds 	room = edge_buf_space_avail(edge_port->ep_out_buf);
2239*1da177e4SLinus Torvalds 	spin_unlock_irqrestore(&edge_port->ep_lock, flags);
2240*1da177e4SLinus Torvalds 
2241*1da177e4SLinus Torvalds 	dbg("%s - returns %d", __FUNCTION__, room);
2242*1da177e4SLinus Torvalds 	return room;
2243*1da177e4SLinus Torvalds }
2244*1da177e4SLinus Torvalds 
2245*1da177e4SLinus Torvalds static int edge_chars_in_buffer (struct usb_serial_port *port)
2246*1da177e4SLinus Torvalds {
2247*1da177e4SLinus Torvalds 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
2248*1da177e4SLinus Torvalds 	int chars = 0;
2249*1da177e4SLinus Torvalds 	unsigned long flags;
2250*1da177e4SLinus Torvalds 
2251*1da177e4SLinus Torvalds 	dbg("%s - port %d", __FUNCTION__, port->number);
2252*1da177e4SLinus Torvalds 
2253*1da177e4SLinus Torvalds 	if (edge_port == NULL)
2254*1da177e4SLinus Torvalds 		return -ENODEV;
2255*1da177e4SLinus Torvalds 	if (edge_port->close_pending == 1)
2256*1da177e4SLinus Torvalds 		return -ENODEV;
2257*1da177e4SLinus Torvalds 
2258*1da177e4SLinus Torvalds 	spin_lock_irqsave(&edge_port->ep_lock, flags);
2259*1da177e4SLinus Torvalds 	chars = edge_buf_data_avail(edge_port->ep_out_buf);
2260*1da177e4SLinus Torvalds 	spin_unlock_irqrestore(&edge_port->ep_lock, flags);
2261*1da177e4SLinus Torvalds 
2262*1da177e4SLinus Torvalds 	dbg ("%s - returns %d", __FUNCTION__, chars);
2263*1da177e4SLinus Torvalds 	return chars;
2264*1da177e4SLinus Torvalds }
2265*1da177e4SLinus Torvalds 
2266*1da177e4SLinus Torvalds static void edge_throttle (struct usb_serial_port *port)
2267*1da177e4SLinus Torvalds {
2268*1da177e4SLinus Torvalds 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
2269*1da177e4SLinus Torvalds 	struct tty_struct *tty;
2270*1da177e4SLinus Torvalds 	int status;
2271*1da177e4SLinus Torvalds 
2272*1da177e4SLinus Torvalds 	dbg("%s - port %d", __FUNCTION__, port->number);
2273*1da177e4SLinus Torvalds 
2274*1da177e4SLinus Torvalds 	if (edge_port == NULL)
2275*1da177e4SLinus Torvalds 		return;
2276*1da177e4SLinus Torvalds 
2277*1da177e4SLinus Torvalds 	tty = port->tty;
2278*1da177e4SLinus Torvalds 	if (!tty) {
2279*1da177e4SLinus Torvalds 		dbg ("%s - no tty available", __FUNCTION__);
2280*1da177e4SLinus Torvalds 		return;
2281*1da177e4SLinus Torvalds 	}
2282*1da177e4SLinus Torvalds 
2283*1da177e4SLinus Torvalds 	/* if we are implementing XON/XOFF, send the stop character */
2284*1da177e4SLinus Torvalds 	if (I_IXOFF(tty)) {
2285*1da177e4SLinus Torvalds 		unsigned char stop_char = STOP_CHAR(tty);
2286*1da177e4SLinus Torvalds 		status = edge_write (port, &stop_char, 1);
2287*1da177e4SLinus Torvalds 		if (status <= 0) {
2288*1da177e4SLinus Torvalds 			dev_err(&port->dev, "%s - failed to write stop character, %d\n", __FUNCTION__, status);
2289*1da177e4SLinus Torvalds 		}
2290*1da177e4SLinus Torvalds 	}
2291*1da177e4SLinus Torvalds 
2292*1da177e4SLinus Torvalds 	/* if we are implementing RTS/CTS, stop reads */
2293*1da177e4SLinus Torvalds 	/* and the Edgeport will clear the RTS line */
2294*1da177e4SLinus Torvalds 	if (C_CRTSCTS(tty))
2295*1da177e4SLinus Torvalds 		stop_read(edge_port);
2296*1da177e4SLinus Torvalds 
2297*1da177e4SLinus Torvalds }
2298*1da177e4SLinus Torvalds 
2299*1da177e4SLinus Torvalds static void edge_unthrottle (struct usb_serial_port *port)
2300*1da177e4SLinus Torvalds {
2301*1da177e4SLinus Torvalds 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
2302*1da177e4SLinus Torvalds 	struct tty_struct *tty;
2303*1da177e4SLinus Torvalds 	int status;
2304*1da177e4SLinus Torvalds 
2305*1da177e4SLinus Torvalds 	dbg("%s - port %d", __FUNCTION__, port->number);
2306*1da177e4SLinus Torvalds 
2307*1da177e4SLinus Torvalds 	if (edge_port == NULL)
2308*1da177e4SLinus Torvalds 		return;
2309*1da177e4SLinus Torvalds 
2310*1da177e4SLinus Torvalds 	tty = port->tty;
2311*1da177e4SLinus Torvalds 	if (!tty) {
2312*1da177e4SLinus Torvalds 		dbg ("%s - no tty available", __FUNCTION__);
2313*1da177e4SLinus Torvalds 		return;
2314*1da177e4SLinus Torvalds 	}
2315*1da177e4SLinus Torvalds 
2316*1da177e4SLinus Torvalds 	/* if we are implementing XON/XOFF, send the start character */
2317*1da177e4SLinus Torvalds 	if (I_IXOFF(tty)) {
2318*1da177e4SLinus Torvalds 		unsigned char start_char = START_CHAR(tty);
2319*1da177e4SLinus Torvalds 		status = edge_write (port, &start_char, 1);
2320*1da177e4SLinus Torvalds 		if (status <= 0) {
2321*1da177e4SLinus Torvalds 			dev_err(&port->dev, "%s - failed to write start character, %d\n", __FUNCTION__, status);
2322*1da177e4SLinus Torvalds 		}
2323*1da177e4SLinus Torvalds 	}
2324*1da177e4SLinus Torvalds 
2325*1da177e4SLinus Torvalds 	/* if we are implementing RTS/CTS, restart reads */
2326*1da177e4SLinus Torvalds 	/* are the Edgeport will assert the RTS line */
2327*1da177e4SLinus Torvalds 	if (C_CRTSCTS(tty)) {
2328*1da177e4SLinus Torvalds 		status = restart_read(edge_port);
2329*1da177e4SLinus Torvalds 		if (status)
2330*1da177e4SLinus Torvalds 			dev_err(&port->dev, "%s - read bulk usb_submit_urb failed with value %d\n", __FUNCTION__, status);
2331*1da177e4SLinus Torvalds 	}
2332*1da177e4SLinus Torvalds 
2333*1da177e4SLinus Torvalds }
2334*1da177e4SLinus Torvalds 
2335*1da177e4SLinus Torvalds static void stop_read(struct edgeport_port *edge_port)
2336*1da177e4SLinus Torvalds {
2337*1da177e4SLinus Torvalds 	unsigned long flags;
2338*1da177e4SLinus Torvalds 
2339*1da177e4SLinus Torvalds 	spin_lock_irqsave(&edge_port->ep_lock, flags);
2340*1da177e4SLinus Torvalds 
2341*1da177e4SLinus Torvalds 	if (edge_port->ep_read_urb_state == EDGE_READ_URB_RUNNING)
2342*1da177e4SLinus Torvalds 		edge_port->ep_read_urb_state = EDGE_READ_URB_STOPPING;
2343*1da177e4SLinus Torvalds 	edge_port->shadow_mcr &= ~MCR_RTS;
2344*1da177e4SLinus Torvalds 
2345*1da177e4SLinus Torvalds 	spin_unlock_irqrestore(&edge_port->ep_lock, flags);
2346*1da177e4SLinus Torvalds }
2347*1da177e4SLinus Torvalds 
2348*1da177e4SLinus Torvalds static int restart_read(struct edgeport_port *edge_port)
2349*1da177e4SLinus Torvalds {
2350*1da177e4SLinus Torvalds 	struct urb *urb;
2351*1da177e4SLinus Torvalds 	int status = 0;
2352*1da177e4SLinus Torvalds 	unsigned long flags;
2353*1da177e4SLinus Torvalds 
2354*1da177e4SLinus Torvalds 	spin_lock_irqsave(&edge_port->ep_lock, flags);
2355*1da177e4SLinus Torvalds 
2356*1da177e4SLinus Torvalds 	if (edge_port->ep_read_urb_state == EDGE_READ_URB_STOPPED) {
2357*1da177e4SLinus Torvalds 		urb = edge_port->port->read_urb;
2358*1da177e4SLinus Torvalds 		urb->complete = edge_bulk_in_callback;
2359*1da177e4SLinus Torvalds 		urb->context = edge_port;
2360*1da177e4SLinus Torvalds 		urb->dev = edge_port->port->serial->dev;
2361*1da177e4SLinus Torvalds 		status = usb_submit_urb(urb, GFP_KERNEL);
2362*1da177e4SLinus Torvalds 	}
2363*1da177e4SLinus Torvalds 	edge_port->ep_read_urb_state = EDGE_READ_URB_RUNNING;
2364*1da177e4SLinus Torvalds 	edge_port->shadow_mcr |= MCR_RTS;
2365*1da177e4SLinus Torvalds 
2366*1da177e4SLinus Torvalds 	spin_unlock_irqrestore(&edge_port->ep_lock, flags);
2367*1da177e4SLinus Torvalds 
2368*1da177e4SLinus Torvalds 	return status;
2369*1da177e4SLinus Torvalds }
2370*1da177e4SLinus Torvalds 
2371*1da177e4SLinus Torvalds static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios)
2372*1da177e4SLinus Torvalds {
2373*1da177e4SLinus Torvalds 	struct ump_uart_config *config;
2374*1da177e4SLinus Torvalds 	struct tty_struct *tty;
2375*1da177e4SLinus Torvalds 	int baud;
2376*1da177e4SLinus Torvalds 	unsigned cflag;
2377*1da177e4SLinus Torvalds 	int status;
2378*1da177e4SLinus Torvalds 	int port_number = edge_port->port->number - edge_port->port->serial->minor;
2379*1da177e4SLinus Torvalds 
2380*1da177e4SLinus Torvalds 	dbg("%s - port %d", __FUNCTION__, edge_port->port->number);
2381*1da177e4SLinus Torvalds 
2382*1da177e4SLinus Torvalds 	tty = edge_port->port->tty;
2383*1da177e4SLinus Torvalds 	if ((!tty) ||
2384*1da177e4SLinus Torvalds 	    (!tty->termios)) {
2385*1da177e4SLinus Torvalds 		dbg("%s - no tty structures", __FUNCTION__);
2386*1da177e4SLinus Torvalds 		return;
2387*1da177e4SLinus Torvalds 	}
2388*1da177e4SLinus Torvalds 
2389*1da177e4SLinus Torvalds 	config = kmalloc (sizeof (*config), GFP_KERNEL);
2390*1da177e4SLinus Torvalds 	if (!config) {
2391*1da177e4SLinus Torvalds 		dev_err (&edge_port->port->dev, "%s - out of memory\n", __FUNCTION__);
2392*1da177e4SLinus Torvalds 		return;
2393*1da177e4SLinus Torvalds 	}
2394*1da177e4SLinus Torvalds 
2395*1da177e4SLinus Torvalds 	cflag = tty->termios->c_cflag;
2396*1da177e4SLinus Torvalds 
2397*1da177e4SLinus Torvalds 	config->wFlags = 0;
2398*1da177e4SLinus Torvalds 
2399*1da177e4SLinus Torvalds 	/* These flags must be set */
2400*1da177e4SLinus Torvalds 	config->wFlags |= UMP_MASK_UART_FLAGS_RECEIVE_MS_INT;
2401*1da177e4SLinus Torvalds 	config->wFlags |= UMP_MASK_UART_FLAGS_AUTO_START_ON_ERR;
2402*1da177e4SLinus Torvalds 	config->bUartMode = (__u8)(edge_port->bUartMode);
2403*1da177e4SLinus Torvalds 
2404*1da177e4SLinus Torvalds 	switch (cflag & CSIZE) {
2405*1da177e4SLinus Torvalds 		case CS5:
2406*1da177e4SLinus Torvalds 			    config->bDataBits = UMP_UART_CHAR5BITS;
2407*1da177e4SLinus Torvalds 			    dbg ("%s - data bits = 5", __FUNCTION__);
2408*1da177e4SLinus Torvalds 			    break;
2409*1da177e4SLinus Torvalds 		case CS6:
2410*1da177e4SLinus Torvalds 			    config->bDataBits = UMP_UART_CHAR6BITS;
2411*1da177e4SLinus Torvalds 			    dbg ("%s - data bits = 6", __FUNCTION__);
2412*1da177e4SLinus Torvalds 			    break;
2413*1da177e4SLinus Torvalds 		case CS7:
2414*1da177e4SLinus Torvalds 			    config->bDataBits = UMP_UART_CHAR7BITS;
2415*1da177e4SLinus Torvalds 			    dbg ("%s - data bits = 7", __FUNCTION__);
2416*1da177e4SLinus Torvalds 			    break;
2417*1da177e4SLinus Torvalds 		default:
2418*1da177e4SLinus Torvalds 		case CS8:
2419*1da177e4SLinus Torvalds 			    config->bDataBits = UMP_UART_CHAR8BITS;
2420*1da177e4SLinus Torvalds 			    dbg ("%s - data bits = 8", __FUNCTION__);
2421*1da177e4SLinus Torvalds 			    break;
2422*1da177e4SLinus Torvalds 	}
2423*1da177e4SLinus Torvalds 
2424*1da177e4SLinus Torvalds 	if (cflag & PARENB) {
2425*1da177e4SLinus Torvalds 		if (cflag & PARODD) {
2426*1da177e4SLinus Torvalds 			config->wFlags |= UMP_MASK_UART_FLAGS_PARITY;
2427*1da177e4SLinus Torvalds 			config->bParity = UMP_UART_ODDPARITY;
2428*1da177e4SLinus Torvalds 			dbg("%s - parity = odd", __FUNCTION__);
2429*1da177e4SLinus Torvalds 		} else {
2430*1da177e4SLinus Torvalds 			config->wFlags |= UMP_MASK_UART_FLAGS_PARITY;
2431*1da177e4SLinus Torvalds 			config->bParity = UMP_UART_EVENPARITY;
2432*1da177e4SLinus Torvalds 			dbg("%s - parity = even", __FUNCTION__);
2433*1da177e4SLinus Torvalds 		}
2434*1da177e4SLinus Torvalds 	} else {
2435*1da177e4SLinus Torvalds 		config->bParity = UMP_UART_NOPARITY;
2436*1da177e4SLinus Torvalds 		dbg("%s - parity = none", __FUNCTION__);
2437*1da177e4SLinus Torvalds 	}
2438*1da177e4SLinus Torvalds 
2439*1da177e4SLinus Torvalds 	if (cflag & CSTOPB) {
2440*1da177e4SLinus Torvalds 		config->bStopBits = UMP_UART_STOPBIT2;
2441*1da177e4SLinus Torvalds 		dbg("%s - stop bits = 2", __FUNCTION__);
2442*1da177e4SLinus Torvalds 	} else {
2443*1da177e4SLinus Torvalds 		config->bStopBits = UMP_UART_STOPBIT1;
2444*1da177e4SLinus Torvalds 		dbg("%s - stop bits = 1", __FUNCTION__);
2445*1da177e4SLinus Torvalds 	}
2446*1da177e4SLinus Torvalds 
2447*1da177e4SLinus Torvalds 	/* figure out the flow control settings */
2448*1da177e4SLinus Torvalds 	if (cflag & CRTSCTS) {
2449*1da177e4SLinus Torvalds 		config->wFlags |= UMP_MASK_UART_FLAGS_OUT_X_CTS_FLOW;
2450*1da177e4SLinus Torvalds 		config->wFlags |= UMP_MASK_UART_FLAGS_RTS_FLOW;
2451*1da177e4SLinus Torvalds 		dbg("%s - RTS/CTS is enabled", __FUNCTION__);
2452*1da177e4SLinus Torvalds 	} else {
2453*1da177e4SLinus Torvalds 		dbg("%s - RTS/CTS is disabled", __FUNCTION__);
2454*1da177e4SLinus Torvalds 		tty->hw_stopped = 0;
2455*1da177e4SLinus Torvalds 		restart_read(edge_port);
2456*1da177e4SLinus Torvalds 	}
2457*1da177e4SLinus Torvalds 
2458*1da177e4SLinus Torvalds 	/* if we are implementing XON/XOFF, set the start and stop character in the device */
2459*1da177e4SLinus Torvalds 	if (I_IXOFF(tty) || I_IXON(tty)) {
2460*1da177e4SLinus Torvalds 		config->cXon  = START_CHAR(tty);
2461*1da177e4SLinus Torvalds 		config->cXoff = STOP_CHAR(tty);
2462*1da177e4SLinus Torvalds 
2463*1da177e4SLinus Torvalds 		/* if we are implementing INBOUND XON/XOFF */
2464*1da177e4SLinus Torvalds 		if (I_IXOFF(tty)) {
2465*1da177e4SLinus Torvalds 			config->wFlags |= UMP_MASK_UART_FLAGS_IN_X;
2466*1da177e4SLinus Torvalds 			dbg ("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
2467*1da177e4SLinus Torvalds 			     __FUNCTION__, config->cXon, config->cXoff);
2468*1da177e4SLinus Torvalds 		} else {
2469*1da177e4SLinus Torvalds 			dbg ("%s - INBOUND XON/XOFF is disabled", __FUNCTION__);
2470*1da177e4SLinus Torvalds 		}
2471*1da177e4SLinus Torvalds 
2472*1da177e4SLinus Torvalds 		/* if we are implementing OUTBOUND XON/XOFF */
2473*1da177e4SLinus Torvalds 		if (I_IXON(tty)) {
2474*1da177e4SLinus Torvalds 			config->wFlags |= UMP_MASK_UART_FLAGS_OUT_X;
2475*1da177e4SLinus Torvalds 			dbg ("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
2476*1da177e4SLinus Torvalds 			     __FUNCTION__, config->cXon, config->cXoff);
2477*1da177e4SLinus Torvalds 		} else {
2478*1da177e4SLinus Torvalds 			dbg ("%s - OUTBOUND XON/XOFF is disabled", __FUNCTION__);
2479*1da177e4SLinus Torvalds 		}
2480*1da177e4SLinus Torvalds 	}
2481*1da177e4SLinus Torvalds 
2482*1da177e4SLinus Torvalds 	/* Round the baud rate */
2483*1da177e4SLinus Torvalds 	baud = tty_get_baud_rate(tty);
2484*1da177e4SLinus Torvalds 	if (!baud) {
2485*1da177e4SLinus Torvalds 		/* pick a default, any default... */
2486*1da177e4SLinus Torvalds 		baud = 9600;
2487*1da177e4SLinus Torvalds 	}
2488*1da177e4SLinus Torvalds 	edge_port->baud_rate = baud;
2489*1da177e4SLinus Torvalds 	config->wBaudRate = (__u16)((461550L + baud/2) / baud);
2490*1da177e4SLinus Torvalds 
2491*1da177e4SLinus Torvalds 	dbg ("%s - baud rate = %d, wBaudRate = %d", __FUNCTION__, baud, config->wBaudRate);
2492*1da177e4SLinus Torvalds 
2493*1da177e4SLinus Torvalds 	dbg ("wBaudRate:   %d", (int)(461550L / config->wBaudRate));
2494*1da177e4SLinus Torvalds 	dbg ("wFlags:    0x%x", config->wFlags);
2495*1da177e4SLinus Torvalds 	dbg ("bDataBits:   %d", config->bDataBits);
2496*1da177e4SLinus Torvalds 	dbg ("bParity:     %d", config->bParity);
2497*1da177e4SLinus Torvalds 	dbg ("bStopBits:   %d", config->bStopBits);
2498*1da177e4SLinus Torvalds 	dbg ("cXon:        %d", config->cXon);
2499*1da177e4SLinus Torvalds 	dbg ("cXoff:       %d", config->cXoff);
2500*1da177e4SLinus Torvalds 	dbg ("bUartMode:   %d", config->bUartMode);
2501*1da177e4SLinus Torvalds 
2502*1da177e4SLinus Torvalds 	/* move the word values into big endian mode */
2503*1da177e4SLinus Torvalds 	cpu_to_be16s (&config->wFlags);
2504*1da177e4SLinus Torvalds 	cpu_to_be16s (&config->wBaudRate);
2505*1da177e4SLinus Torvalds 
2506*1da177e4SLinus Torvalds 	status = TIWriteCommandSync (edge_port->port->serial->dev,
2507*1da177e4SLinus Torvalds 				UMPC_SET_CONFIG,
2508*1da177e4SLinus Torvalds 				(__u8)(UMPM_UART1_PORT + port_number),
2509*1da177e4SLinus Torvalds 				0,
2510*1da177e4SLinus Torvalds 				(__u8 *)config,
2511*1da177e4SLinus Torvalds 				sizeof(*config));
2512*1da177e4SLinus Torvalds 	if (status) {
2513*1da177e4SLinus Torvalds 		dbg ("%s - error %d when trying to write config to device",
2514*1da177e4SLinus Torvalds 		     __FUNCTION__, status);
2515*1da177e4SLinus Torvalds 	}
2516*1da177e4SLinus Torvalds 
2517*1da177e4SLinus Torvalds 	kfree (config);
2518*1da177e4SLinus Torvalds 
2519*1da177e4SLinus Torvalds 	return;
2520*1da177e4SLinus Torvalds }
2521*1da177e4SLinus Torvalds 
2522*1da177e4SLinus Torvalds static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios)
2523*1da177e4SLinus Torvalds {
2524*1da177e4SLinus Torvalds 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
2525*1da177e4SLinus Torvalds 	struct tty_struct *tty = port->tty;
2526*1da177e4SLinus Torvalds 	unsigned int cflag;
2527*1da177e4SLinus Torvalds 
2528*1da177e4SLinus Torvalds 	if (!port->tty || !port->tty->termios) {
2529*1da177e4SLinus Torvalds 		dbg ("%s - no tty or termios", __FUNCTION__);
2530*1da177e4SLinus Torvalds 		return;
2531*1da177e4SLinus Torvalds 	}
2532*1da177e4SLinus Torvalds 
2533*1da177e4SLinus Torvalds 	cflag = tty->termios->c_cflag;
2534*1da177e4SLinus Torvalds 	/* check that they really want us to change something */
2535*1da177e4SLinus Torvalds 	if (old_termios) {
2536*1da177e4SLinus Torvalds 		if (cflag == old_termios->c_cflag &&
2537*1da177e4SLinus Torvalds 		    tty->termios->c_iflag == old_termios->c_iflag) {
2538*1da177e4SLinus Torvalds 			dbg ("%s - nothing to change", __FUNCTION__);
2539*1da177e4SLinus Torvalds 			return;
2540*1da177e4SLinus Torvalds 		}
2541*1da177e4SLinus Torvalds 	}
2542*1da177e4SLinus Torvalds 
2543*1da177e4SLinus Torvalds 	dbg("%s - clfag %08x iflag %08x", __FUNCTION__,
2544*1da177e4SLinus Torvalds 	    tty->termios->c_cflag, tty->termios->c_iflag);
2545*1da177e4SLinus Torvalds 	if (old_termios) {
2546*1da177e4SLinus Torvalds 		dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,
2547*1da177e4SLinus Torvalds 		    old_termios->c_cflag, old_termios->c_iflag);
2548*1da177e4SLinus Torvalds 	}
2549*1da177e4SLinus Torvalds 
2550*1da177e4SLinus Torvalds 	dbg("%s - port %d", __FUNCTION__, port->number);
2551*1da177e4SLinus Torvalds 
2552*1da177e4SLinus Torvalds 	if (edge_port == NULL)
2553*1da177e4SLinus Torvalds 		return;
2554*1da177e4SLinus Torvalds 
2555*1da177e4SLinus Torvalds 	/* change the port settings to the new ones specified */
2556*1da177e4SLinus Torvalds 	change_port_settings (edge_port, old_termios);
2557*1da177e4SLinus Torvalds 
2558*1da177e4SLinus Torvalds 	return;
2559*1da177e4SLinus Torvalds }
2560*1da177e4SLinus Torvalds 
2561*1da177e4SLinus Torvalds static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear)
2562*1da177e4SLinus Torvalds {
2563*1da177e4SLinus Torvalds 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
2564*1da177e4SLinus Torvalds 	unsigned int mcr;
2565*1da177e4SLinus Torvalds 
2566*1da177e4SLinus Torvalds 	dbg("%s - port %d", __FUNCTION__, port->number);
2567*1da177e4SLinus Torvalds 
2568*1da177e4SLinus Torvalds 	mcr = edge_port->shadow_mcr;
2569*1da177e4SLinus Torvalds 	if (set & TIOCM_RTS)
2570*1da177e4SLinus Torvalds 		mcr |= MCR_RTS;
2571*1da177e4SLinus Torvalds 	if (set & TIOCM_DTR)
2572*1da177e4SLinus Torvalds 		mcr |= MCR_DTR;
2573*1da177e4SLinus Torvalds 	if (set & TIOCM_LOOP)
2574*1da177e4SLinus Torvalds 		mcr |= MCR_LOOPBACK;
2575*1da177e4SLinus Torvalds 
2576*1da177e4SLinus Torvalds 	if (clear & TIOCM_RTS)
2577*1da177e4SLinus Torvalds 		mcr &= ~MCR_RTS;
2578*1da177e4SLinus Torvalds 	if (clear & TIOCM_DTR)
2579*1da177e4SLinus Torvalds 		mcr &= ~MCR_DTR;
2580*1da177e4SLinus Torvalds 	if (clear & TIOCM_LOOP)
2581*1da177e4SLinus Torvalds 		mcr &= ~MCR_LOOPBACK;
2582*1da177e4SLinus Torvalds 
2583*1da177e4SLinus Torvalds 	edge_port->shadow_mcr = mcr;
2584*1da177e4SLinus Torvalds 
2585*1da177e4SLinus Torvalds 	TIRestoreMCR (edge_port, mcr);
2586*1da177e4SLinus Torvalds 
2587*1da177e4SLinus Torvalds 	return 0;
2588*1da177e4SLinus Torvalds }
2589*1da177e4SLinus Torvalds 
2590*1da177e4SLinus Torvalds static int edge_tiocmget(struct usb_serial_port *port, struct file *file)
2591*1da177e4SLinus Torvalds {
2592*1da177e4SLinus Torvalds 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
2593*1da177e4SLinus Torvalds 	unsigned int result = 0;
2594*1da177e4SLinus Torvalds 	unsigned int msr;
2595*1da177e4SLinus Torvalds 	unsigned int mcr;
2596*1da177e4SLinus Torvalds 
2597*1da177e4SLinus Torvalds 	dbg("%s - port %d", __FUNCTION__, port->number);
2598*1da177e4SLinus Torvalds 
2599*1da177e4SLinus Torvalds 	msr = edge_port->shadow_msr;
2600*1da177e4SLinus Torvalds 	mcr = edge_port->shadow_mcr;
2601*1da177e4SLinus Torvalds 	result = ((mcr & MCR_DTR)	? TIOCM_DTR: 0)	  /* 0x002 */
2602*1da177e4SLinus Torvalds 		  | ((mcr & MCR_RTS)	? TIOCM_RTS: 0)   /* 0x004 */
2603*1da177e4SLinus Torvalds 		  | ((msr & EDGEPORT_MSR_CTS)	? TIOCM_CTS: 0)   /* 0x020 */
2604*1da177e4SLinus Torvalds 		  | ((msr & EDGEPORT_MSR_CD)	? TIOCM_CAR: 0)   /* 0x040 */
2605*1da177e4SLinus Torvalds 		  | ((msr & EDGEPORT_MSR_RI)	? TIOCM_RI:  0)   /* 0x080 */
2606*1da177e4SLinus Torvalds 		  | ((msr & EDGEPORT_MSR_DSR)	? TIOCM_DSR: 0);  /* 0x100 */
2607*1da177e4SLinus Torvalds 
2608*1da177e4SLinus Torvalds 
2609*1da177e4SLinus Torvalds 	dbg("%s -- %x", __FUNCTION__, result);
2610*1da177e4SLinus Torvalds 
2611*1da177e4SLinus Torvalds 	return result;
2612*1da177e4SLinus Torvalds }
2613*1da177e4SLinus Torvalds 
2614*1da177e4SLinus Torvalds static int get_serial_info (struct edgeport_port *edge_port, struct serial_struct __user *retinfo)
2615*1da177e4SLinus Torvalds {
2616*1da177e4SLinus Torvalds 	struct serial_struct tmp;
2617*1da177e4SLinus Torvalds 
2618*1da177e4SLinus Torvalds 	if (!retinfo)
2619*1da177e4SLinus Torvalds 		return -EFAULT;
2620*1da177e4SLinus Torvalds 
2621*1da177e4SLinus Torvalds 	memset(&tmp, 0, sizeof(tmp));
2622*1da177e4SLinus Torvalds 
2623*1da177e4SLinus Torvalds 	tmp.type		= PORT_16550A;
2624*1da177e4SLinus Torvalds 	tmp.line		= edge_port->port->serial->minor;
2625*1da177e4SLinus Torvalds 	tmp.port		= edge_port->port->number;
2626*1da177e4SLinus Torvalds 	tmp.irq			= 0;
2627*1da177e4SLinus Torvalds 	tmp.flags		= ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
2628*1da177e4SLinus Torvalds 	tmp.xmit_fifo_size	= edge_port->port->bulk_out_size;
2629*1da177e4SLinus Torvalds 	tmp.baud_base		= 9600;
2630*1da177e4SLinus Torvalds 	tmp.close_delay		= 5*HZ;
2631*1da177e4SLinus Torvalds 	tmp.closing_wait	= closing_wait;
2632*1da177e4SLinus Torvalds //	tmp.custom_divisor	= state->custom_divisor;
2633*1da177e4SLinus Torvalds //	tmp.hub6		= state->hub6;
2634*1da177e4SLinus Torvalds //	tmp.io_type		= state->io_type;
2635*1da177e4SLinus Torvalds 
2636*1da177e4SLinus Torvalds 
2637*1da177e4SLinus Torvalds 	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
2638*1da177e4SLinus Torvalds 		return -EFAULT;
2639*1da177e4SLinus Torvalds 	return 0;
2640*1da177e4SLinus Torvalds }
2641*1da177e4SLinus Torvalds 
2642*1da177e4SLinus Torvalds static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg)
2643*1da177e4SLinus Torvalds {
2644*1da177e4SLinus Torvalds 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
2645*1da177e4SLinus Torvalds 	struct async_icount cnow;
2646*1da177e4SLinus Torvalds 	struct async_icount cprev;
2647*1da177e4SLinus Torvalds 
2648*1da177e4SLinus Torvalds 	dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);
2649*1da177e4SLinus Torvalds 
2650*1da177e4SLinus Torvalds 	switch (cmd) {
2651*1da177e4SLinus Torvalds 		case TIOCINQ:
2652*1da177e4SLinus Torvalds 			dbg("%s - (%d) TIOCINQ", __FUNCTION__, port->number);
2653*1da177e4SLinus Torvalds //			return get_number_bytes_avail(edge_port, (unsigned int *) arg);
2654*1da177e4SLinus Torvalds 			break;
2655*1da177e4SLinus Torvalds 
2656*1da177e4SLinus Torvalds 		case TIOCSERGETLSR:
2657*1da177e4SLinus Torvalds 			dbg("%s - (%d) TIOCSERGETLSR", __FUNCTION__, port->number);
2658*1da177e4SLinus Torvalds //			return get_lsr_info(edge_port, (unsigned int *) arg);
2659*1da177e4SLinus Torvalds 			break;
2660*1da177e4SLinus Torvalds 
2661*1da177e4SLinus Torvalds 		case TIOCGSERIAL:
2662*1da177e4SLinus Torvalds 			dbg("%s - (%d) TIOCGSERIAL", __FUNCTION__, port->number);
2663*1da177e4SLinus Torvalds 			return get_serial_info(edge_port, (struct serial_struct __user *) arg);
2664*1da177e4SLinus Torvalds 			break;
2665*1da177e4SLinus Torvalds 
2666*1da177e4SLinus Torvalds 		case TIOCSSERIAL:
2667*1da177e4SLinus Torvalds 			dbg("%s - (%d) TIOCSSERIAL", __FUNCTION__, port->number);
2668*1da177e4SLinus Torvalds 			break;
2669*1da177e4SLinus Torvalds 
2670*1da177e4SLinus Torvalds 		case TIOCMIWAIT:
2671*1da177e4SLinus Torvalds 			dbg("%s - (%d) TIOCMIWAIT", __FUNCTION__, port->number);
2672*1da177e4SLinus Torvalds 			cprev = edge_port->icount;
2673*1da177e4SLinus Torvalds 			while (1) {
2674*1da177e4SLinus Torvalds 				interruptible_sleep_on(&edge_port->delta_msr_wait);
2675*1da177e4SLinus Torvalds 				/* see if a signal did it */
2676*1da177e4SLinus Torvalds 				if (signal_pending(current))
2677*1da177e4SLinus Torvalds 					return -ERESTARTSYS;
2678*1da177e4SLinus Torvalds 				cnow = edge_port->icount;
2679*1da177e4SLinus Torvalds 				if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
2680*1da177e4SLinus Torvalds 				    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
2681*1da177e4SLinus Torvalds 					return -EIO; /* no change => error */
2682*1da177e4SLinus Torvalds 				if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
2683*1da177e4SLinus Torvalds 				    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
2684*1da177e4SLinus Torvalds 				    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
2685*1da177e4SLinus Torvalds 				    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
2686*1da177e4SLinus Torvalds 					return 0;
2687*1da177e4SLinus Torvalds 				}
2688*1da177e4SLinus Torvalds 				cprev = cnow;
2689*1da177e4SLinus Torvalds 			}
2690*1da177e4SLinus Torvalds 			/* not reached */
2691*1da177e4SLinus Torvalds 			break;
2692*1da177e4SLinus Torvalds 
2693*1da177e4SLinus Torvalds 		case TIOCGICOUNT:
2694*1da177e4SLinus Torvalds 			dbg ("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__,
2695*1da177e4SLinus Torvalds 			     port->number, edge_port->icount.rx, edge_port->icount.tx);
2696*1da177e4SLinus Torvalds 			if (copy_to_user((void __user *)arg, &edge_port->icount, sizeof(edge_port->icount)))
2697*1da177e4SLinus Torvalds 				return -EFAULT;
2698*1da177e4SLinus Torvalds 			return 0;
2699*1da177e4SLinus Torvalds 	}
2700*1da177e4SLinus Torvalds 
2701*1da177e4SLinus Torvalds 	return -ENOIOCTLCMD;
2702*1da177e4SLinus Torvalds }
2703*1da177e4SLinus Torvalds 
2704*1da177e4SLinus Torvalds static void edge_break (struct usb_serial_port *port, int break_state)
2705*1da177e4SLinus Torvalds {
2706*1da177e4SLinus Torvalds 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
2707*1da177e4SLinus Torvalds 	int status;
2708*1da177e4SLinus Torvalds 
2709*1da177e4SLinus Torvalds 	dbg ("%s - state = %d", __FUNCTION__, break_state);
2710*1da177e4SLinus Torvalds 
2711*1da177e4SLinus Torvalds 	/* chase the port close */
2712*1da177e4SLinus Torvalds 	TIChasePort (edge_port, 0, 0);
2713*1da177e4SLinus Torvalds 
2714*1da177e4SLinus Torvalds 	if (break_state == -1) {
2715*1da177e4SLinus Torvalds 		status = TISetBreak (edge_port);
2716*1da177e4SLinus Torvalds 	} else {
2717*1da177e4SLinus Torvalds 		status = TIClearBreak (edge_port);
2718*1da177e4SLinus Torvalds 	}
2719*1da177e4SLinus Torvalds 	if (status) {
2720*1da177e4SLinus Torvalds 		dbg ("%s - error %d sending break set/clear command.",
2721*1da177e4SLinus Torvalds 		     __FUNCTION__, status);
2722*1da177e4SLinus Torvalds 	}
2723*1da177e4SLinus Torvalds }
2724*1da177e4SLinus Torvalds 
2725*1da177e4SLinus Torvalds static int edge_startup (struct usb_serial *serial)
2726*1da177e4SLinus Torvalds {
2727*1da177e4SLinus Torvalds 	struct edgeport_serial *edge_serial;
2728*1da177e4SLinus Torvalds 	struct edgeport_port *edge_port;
2729*1da177e4SLinus Torvalds 	struct usb_device *dev;
2730*1da177e4SLinus Torvalds 	int status;
2731*1da177e4SLinus Torvalds 	int i;
2732*1da177e4SLinus Torvalds 
2733*1da177e4SLinus Torvalds 	dev = serial->dev;
2734*1da177e4SLinus Torvalds 
2735*1da177e4SLinus Torvalds 	/* create our private serial structure */
2736*1da177e4SLinus Torvalds 	edge_serial = kmalloc (sizeof(struct edgeport_serial), GFP_KERNEL);
2737*1da177e4SLinus Torvalds 	if (edge_serial == NULL) {
2738*1da177e4SLinus Torvalds 		dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__);
2739*1da177e4SLinus Torvalds 		return -ENOMEM;
2740*1da177e4SLinus Torvalds 	}
2741*1da177e4SLinus Torvalds 	memset (edge_serial, 0, sizeof(struct edgeport_serial));
2742*1da177e4SLinus Torvalds 	sema_init(&edge_serial->es_sem, 1);
2743*1da177e4SLinus Torvalds 	edge_serial->serial = serial;
2744*1da177e4SLinus Torvalds 	usb_set_serial_data(serial, edge_serial);
2745*1da177e4SLinus Torvalds 
2746*1da177e4SLinus Torvalds 	status = TIDownloadFirmware (edge_serial);
2747*1da177e4SLinus Torvalds 	if (status) {
2748*1da177e4SLinus Torvalds 		kfree (edge_serial);
2749*1da177e4SLinus Torvalds 		return status;
2750*1da177e4SLinus Torvalds 	}
2751*1da177e4SLinus Torvalds 
2752*1da177e4SLinus Torvalds 	/* set up our port private structures */
2753*1da177e4SLinus Torvalds 	for (i = 0; i < serial->num_ports; ++i) {
2754*1da177e4SLinus Torvalds 		edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL);
2755*1da177e4SLinus Torvalds 		if (edge_port == NULL) {
2756*1da177e4SLinus Torvalds 			dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__);
2757*1da177e4SLinus Torvalds 			goto cleanup;
2758*1da177e4SLinus Torvalds 		}
2759*1da177e4SLinus Torvalds 		memset (edge_port, 0, sizeof(struct edgeport_port));
2760*1da177e4SLinus Torvalds 		spin_lock_init(&edge_port->ep_lock);
2761*1da177e4SLinus Torvalds 		edge_port->ep_out_buf = edge_buf_alloc(EDGE_OUT_BUF_SIZE);
2762*1da177e4SLinus Torvalds 		if (edge_port->ep_out_buf == NULL) {
2763*1da177e4SLinus Torvalds 			dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__);
2764*1da177e4SLinus Torvalds 			kfree(edge_port);
2765*1da177e4SLinus Torvalds 			goto cleanup;
2766*1da177e4SLinus Torvalds 		}
2767*1da177e4SLinus Torvalds 		edge_port->port = serial->port[i];
2768*1da177e4SLinus Torvalds 		edge_port->edge_serial = edge_serial;
2769*1da177e4SLinus Torvalds 		usb_set_serial_port_data(serial->port[i], edge_port);
2770*1da177e4SLinus Torvalds 		edge_port->bUartMode = 0;	/* Default is RS232 */
2771*1da177e4SLinus Torvalds 	}
2772*1da177e4SLinus Torvalds 
2773*1da177e4SLinus Torvalds 	return 0;
2774*1da177e4SLinus Torvalds 
2775*1da177e4SLinus Torvalds cleanup:
2776*1da177e4SLinus Torvalds 	for (--i; i>=0; --i) {
2777*1da177e4SLinus Torvalds 		edge_port = usb_get_serial_port_data(serial->port[i]);
2778*1da177e4SLinus Torvalds 		edge_buf_free(edge_port->ep_out_buf);
2779*1da177e4SLinus Torvalds 		kfree(edge_port);
2780*1da177e4SLinus Torvalds 		usb_set_serial_port_data(serial->port[i], NULL);
2781*1da177e4SLinus Torvalds 	}
2782*1da177e4SLinus Torvalds 	kfree (edge_serial);
2783*1da177e4SLinus Torvalds 	usb_set_serial_data(serial, NULL);
2784*1da177e4SLinus Torvalds 	return -ENOMEM;
2785*1da177e4SLinus Torvalds }
2786*1da177e4SLinus Torvalds 
2787*1da177e4SLinus Torvalds static void edge_shutdown (struct usb_serial *serial)
2788*1da177e4SLinus Torvalds {
2789*1da177e4SLinus Torvalds 	int i;
2790*1da177e4SLinus Torvalds 	struct edgeport_port *edge_port;
2791*1da177e4SLinus Torvalds 
2792*1da177e4SLinus Torvalds 	dbg ("%s", __FUNCTION__);
2793*1da177e4SLinus Torvalds 
2794*1da177e4SLinus Torvalds 	for (i=0; i < serial->num_ports; ++i) {
2795*1da177e4SLinus Torvalds 		edge_port = usb_get_serial_port_data(serial->port[i]);
2796*1da177e4SLinus Torvalds 		if (edge_port) {
2797*1da177e4SLinus Torvalds 			edge_buf_free(edge_port->ep_out_buf);
2798*1da177e4SLinus Torvalds 			kfree(edge_port);
2799*1da177e4SLinus Torvalds 		}
2800*1da177e4SLinus Torvalds 		usb_set_serial_port_data(serial->port[i], NULL);
2801*1da177e4SLinus Torvalds 	}
2802*1da177e4SLinus Torvalds 	kfree (usb_get_serial_data(serial));
2803*1da177e4SLinus Torvalds 	usb_set_serial_data(serial, NULL);
2804*1da177e4SLinus Torvalds }
2805*1da177e4SLinus Torvalds 
2806*1da177e4SLinus Torvalds 
2807*1da177e4SLinus Torvalds /* Circular Buffer */
2808*1da177e4SLinus Torvalds 
2809*1da177e4SLinus Torvalds /*
2810*1da177e4SLinus Torvalds  * edge_buf_alloc
2811*1da177e4SLinus Torvalds  *
2812*1da177e4SLinus Torvalds  * Allocate a circular buffer and all associated memory.
2813*1da177e4SLinus Torvalds  */
2814*1da177e4SLinus Torvalds 
2815*1da177e4SLinus Torvalds static struct edge_buf *edge_buf_alloc(unsigned int size)
2816*1da177e4SLinus Torvalds {
2817*1da177e4SLinus Torvalds 	struct edge_buf *eb;
2818*1da177e4SLinus Torvalds 
2819*1da177e4SLinus Torvalds 
2820*1da177e4SLinus Torvalds 	if (size == 0)
2821*1da177e4SLinus Torvalds 		return NULL;
2822*1da177e4SLinus Torvalds 
2823*1da177e4SLinus Torvalds 	eb = (struct edge_buf *)kmalloc(sizeof(struct edge_buf), GFP_KERNEL);
2824*1da177e4SLinus Torvalds 	if (eb == NULL)
2825*1da177e4SLinus Torvalds 		return NULL;
2826*1da177e4SLinus Torvalds 
2827*1da177e4SLinus Torvalds 	eb->buf_buf = kmalloc(size, GFP_KERNEL);
2828*1da177e4SLinus Torvalds 	if (eb->buf_buf == NULL) {
2829*1da177e4SLinus Torvalds 		kfree(eb);
2830*1da177e4SLinus Torvalds 		return NULL;
2831*1da177e4SLinus Torvalds 	}
2832*1da177e4SLinus Torvalds 
2833*1da177e4SLinus Torvalds 	eb->buf_size = size;
2834*1da177e4SLinus Torvalds 	eb->buf_get = eb->buf_put = eb->buf_buf;
2835*1da177e4SLinus Torvalds 
2836*1da177e4SLinus Torvalds 	return eb;
2837*1da177e4SLinus Torvalds }
2838*1da177e4SLinus Torvalds 
2839*1da177e4SLinus Torvalds 
2840*1da177e4SLinus Torvalds /*
2841*1da177e4SLinus Torvalds  * edge_buf_free
2842*1da177e4SLinus Torvalds  *
2843*1da177e4SLinus Torvalds  * Free the buffer and all associated memory.
2844*1da177e4SLinus Torvalds  */
2845*1da177e4SLinus Torvalds 
2846*1da177e4SLinus Torvalds void edge_buf_free(struct edge_buf *eb)
2847*1da177e4SLinus Torvalds {
2848*1da177e4SLinus Torvalds 	if (eb != NULL) {
2849*1da177e4SLinus Torvalds 		if (eb->buf_buf != NULL)
2850*1da177e4SLinus Torvalds 			kfree(eb->buf_buf);
2851*1da177e4SLinus Torvalds 		kfree(eb);
2852*1da177e4SLinus Torvalds 	}
2853*1da177e4SLinus Torvalds }
2854*1da177e4SLinus Torvalds 
2855*1da177e4SLinus Torvalds 
2856*1da177e4SLinus Torvalds /*
2857*1da177e4SLinus Torvalds  * edge_buf_clear
2858*1da177e4SLinus Torvalds  *
2859*1da177e4SLinus Torvalds  * Clear out all data in the circular buffer.
2860*1da177e4SLinus Torvalds  */
2861*1da177e4SLinus Torvalds 
2862*1da177e4SLinus Torvalds static void edge_buf_clear(struct edge_buf *eb)
2863*1da177e4SLinus Torvalds {
2864*1da177e4SLinus Torvalds         if (eb != NULL)
2865*1da177e4SLinus Torvalds                 eb->buf_get = eb->buf_put;
2866*1da177e4SLinus Torvalds                 /* equivalent to a get of all data available */
2867*1da177e4SLinus Torvalds }
2868*1da177e4SLinus Torvalds 
2869*1da177e4SLinus Torvalds 
2870*1da177e4SLinus Torvalds /*
2871*1da177e4SLinus Torvalds  * edge_buf_data_avail
2872*1da177e4SLinus Torvalds  *
2873*1da177e4SLinus Torvalds  * Return the number of bytes of data available in the circular
2874*1da177e4SLinus Torvalds  * buffer.
2875*1da177e4SLinus Torvalds  */
2876*1da177e4SLinus Torvalds 
2877*1da177e4SLinus Torvalds static unsigned int edge_buf_data_avail(struct edge_buf *eb)
2878*1da177e4SLinus Torvalds {
2879*1da177e4SLinus Torvalds 	if (eb != NULL)
2880*1da177e4SLinus Torvalds 		return ((eb->buf_size + eb->buf_put - eb->buf_get) % eb->buf_size);
2881*1da177e4SLinus Torvalds 	else
2882*1da177e4SLinus Torvalds 		return 0;
2883*1da177e4SLinus Torvalds }
2884*1da177e4SLinus Torvalds 
2885*1da177e4SLinus Torvalds 
2886*1da177e4SLinus Torvalds /*
2887*1da177e4SLinus Torvalds  * edge_buf_space_avail
2888*1da177e4SLinus Torvalds  *
2889*1da177e4SLinus Torvalds  * Return the number of bytes of space available in the circular
2890*1da177e4SLinus Torvalds  * buffer.
2891*1da177e4SLinus Torvalds  */
2892*1da177e4SLinus Torvalds 
2893*1da177e4SLinus Torvalds static unsigned int edge_buf_space_avail(struct edge_buf *eb)
2894*1da177e4SLinus Torvalds {
2895*1da177e4SLinus Torvalds 	if (eb != NULL)
2896*1da177e4SLinus Torvalds 		return ((eb->buf_size + eb->buf_get - eb->buf_put - 1) % eb->buf_size);
2897*1da177e4SLinus Torvalds 	else
2898*1da177e4SLinus Torvalds 		return 0;
2899*1da177e4SLinus Torvalds }
2900*1da177e4SLinus Torvalds 
2901*1da177e4SLinus Torvalds 
2902*1da177e4SLinus Torvalds /*
2903*1da177e4SLinus Torvalds  * edge_buf_put
2904*1da177e4SLinus Torvalds  *
2905*1da177e4SLinus Torvalds  * Copy data data from a user buffer and put it into the circular buffer.
2906*1da177e4SLinus Torvalds  * Restrict to the amount of space available.
2907*1da177e4SLinus Torvalds  *
2908*1da177e4SLinus Torvalds  * Return the number of bytes copied.
2909*1da177e4SLinus Torvalds  */
2910*1da177e4SLinus Torvalds 
2911*1da177e4SLinus Torvalds static unsigned int edge_buf_put(struct edge_buf *eb, const char *buf,
2912*1da177e4SLinus Torvalds 	unsigned int count)
2913*1da177e4SLinus Torvalds {
2914*1da177e4SLinus Torvalds 	unsigned int len;
2915*1da177e4SLinus Torvalds 
2916*1da177e4SLinus Torvalds 
2917*1da177e4SLinus Torvalds 	if (eb == NULL)
2918*1da177e4SLinus Torvalds 		return 0;
2919*1da177e4SLinus Torvalds 
2920*1da177e4SLinus Torvalds 	len  = edge_buf_space_avail(eb);
2921*1da177e4SLinus Torvalds 	if (count > len)
2922*1da177e4SLinus Torvalds 		count = len;
2923*1da177e4SLinus Torvalds 
2924*1da177e4SLinus Torvalds 	if (count == 0)
2925*1da177e4SLinus Torvalds 		return 0;
2926*1da177e4SLinus Torvalds 
2927*1da177e4SLinus Torvalds 	len = eb->buf_buf + eb->buf_size - eb->buf_put;
2928*1da177e4SLinus Torvalds 	if (count > len) {
2929*1da177e4SLinus Torvalds 		memcpy(eb->buf_put, buf, len);
2930*1da177e4SLinus Torvalds 		memcpy(eb->buf_buf, buf+len, count - len);
2931*1da177e4SLinus Torvalds 		eb->buf_put = eb->buf_buf + count - len;
2932*1da177e4SLinus Torvalds 	} else {
2933*1da177e4SLinus Torvalds 		memcpy(eb->buf_put, buf, count);
2934*1da177e4SLinus Torvalds 		if (count < len)
2935*1da177e4SLinus Torvalds 			eb->buf_put += count;
2936*1da177e4SLinus Torvalds 		else /* count == len */
2937*1da177e4SLinus Torvalds 			eb->buf_put = eb->buf_buf;
2938*1da177e4SLinus Torvalds 	}
2939*1da177e4SLinus Torvalds 
2940*1da177e4SLinus Torvalds 	return count;
2941*1da177e4SLinus Torvalds }
2942*1da177e4SLinus Torvalds 
2943*1da177e4SLinus Torvalds 
2944*1da177e4SLinus Torvalds /*
2945*1da177e4SLinus Torvalds  * edge_buf_get
2946*1da177e4SLinus Torvalds  *
2947*1da177e4SLinus Torvalds  * Get data from the circular buffer and copy to the given buffer.
2948*1da177e4SLinus Torvalds  * Restrict to the amount of data available.
2949*1da177e4SLinus Torvalds  *
2950*1da177e4SLinus Torvalds  * Return the number of bytes copied.
2951*1da177e4SLinus Torvalds  */
2952*1da177e4SLinus Torvalds 
2953*1da177e4SLinus Torvalds static unsigned int edge_buf_get(struct edge_buf *eb, char *buf,
2954*1da177e4SLinus Torvalds 	unsigned int count)
2955*1da177e4SLinus Torvalds {
2956*1da177e4SLinus Torvalds 	unsigned int len;
2957*1da177e4SLinus Torvalds 
2958*1da177e4SLinus Torvalds 
2959*1da177e4SLinus Torvalds 	if (eb == NULL)
2960*1da177e4SLinus Torvalds 		return 0;
2961*1da177e4SLinus Torvalds 
2962*1da177e4SLinus Torvalds 	len = edge_buf_data_avail(eb);
2963*1da177e4SLinus Torvalds 	if (count > len)
2964*1da177e4SLinus Torvalds 		count = len;
2965*1da177e4SLinus Torvalds 
2966*1da177e4SLinus Torvalds 	if (count == 0)
2967*1da177e4SLinus Torvalds 		return 0;
2968*1da177e4SLinus Torvalds 
2969*1da177e4SLinus Torvalds 	len = eb->buf_buf + eb->buf_size - eb->buf_get;
2970*1da177e4SLinus Torvalds 	if (count > len) {
2971*1da177e4SLinus Torvalds 		memcpy(buf, eb->buf_get, len);
2972*1da177e4SLinus Torvalds 		memcpy(buf+len, eb->buf_buf, count - len);
2973*1da177e4SLinus Torvalds 		eb->buf_get = eb->buf_buf + count - len;
2974*1da177e4SLinus Torvalds 	} else {
2975*1da177e4SLinus Torvalds 		memcpy(buf, eb->buf_get, count);
2976*1da177e4SLinus Torvalds 		if (count < len)
2977*1da177e4SLinus Torvalds 			eb->buf_get += count;
2978*1da177e4SLinus Torvalds 		else /* count == len */
2979*1da177e4SLinus Torvalds 			eb->buf_get = eb->buf_buf;
2980*1da177e4SLinus Torvalds 	}
2981*1da177e4SLinus Torvalds 
2982*1da177e4SLinus Torvalds 	return count;
2983*1da177e4SLinus Torvalds }
2984*1da177e4SLinus Torvalds 
2985*1da177e4SLinus Torvalds 
2986*1da177e4SLinus Torvalds static struct usb_serial_device_type edgeport_1port_device = {
2987*1da177e4SLinus Torvalds 	.owner			= THIS_MODULE,
2988*1da177e4SLinus Torvalds 	.name			= "Edgeport TI 1 port adapter",
2989*1da177e4SLinus Torvalds 	.short_name		= "edgeport_ti_1",
2990*1da177e4SLinus Torvalds 	.id_table		= edgeport_1port_id_table,
2991*1da177e4SLinus Torvalds 	.num_interrupt_in	= 1,
2992*1da177e4SLinus Torvalds 	.num_bulk_in		= 1,
2993*1da177e4SLinus Torvalds 	.num_bulk_out		= 1,
2994*1da177e4SLinus Torvalds 	.num_ports		= 1,
2995*1da177e4SLinus Torvalds 	.open			= edge_open,
2996*1da177e4SLinus Torvalds 	.close			= edge_close,
2997*1da177e4SLinus Torvalds 	.throttle		= edge_throttle,
2998*1da177e4SLinus Torvalds 	.unthrottle		= edge_unthrottle,
2999*1da177e4SLinus Torvalds 	.attach			= edge_startup,
3000*1da177e4SLinus Torvalds 	.shutdown		= edge_shutdown,
3001*1da177e4SLinus Torvalds 	.ioctl			= edge_ioctl,
3002*1da177e4SLinus Torvalds 	.set_termios		= edge_set_termios,
3003*1da177e4SLinus Torvalds 	.tiocmget		= edge_tiocmget,
3004*1da177e4SLinus Torvalds 	.tiocmset		= edge_tiocmset,
3005*1da177e4SLinus Torvalds 	.write			= edge_write,
3006*1da177e4SLinus Torvalds 	.write_room		= edge_write_room,
3007*1da177e4SLinus Torvalds 	.chars_in_buffer	= edge_chars_in_buffer,
3008*1da177e4SLinus Torvalds 	.break_ctl		= edge_break,
3009*1da177e4SLinus Torvalds 	.read_int_callback	= edge_interrupt_callback,
3010*1da177e4SLinus Torvalds 	.read_bulk_callback	= edge_bulk_in_callback,
3011*1da177e4SLinus Torvalds 	.write_bulk_callback	= edge_bulk_out_callback,
3012*1da177e4SLinus Torvalds };
3013*1da177e4SLinus Torvalds 
3014*1da177e4SLinus Torvalds static struct usb_serial_device_type edgeport_2port_device = {
3015*1da177e4SLinus Torvalds 	.owner			= THIS_MODULE,
3016*1da177e4SLinus Torvalds 	.name			= "Edgeport TI 2 port adapter",
3017*1da177e4SLinus Torvalds 	.short_name		= "edgeport_ti_2",
3018*1da177e4SLinus Torvalds 	.id_table		= edgeport_2port_id_table,
3019*1da177e4SLinus Torvalds 	.num_interrupt_in	= 1,
3020*1da177e4SLinus Torvalds 	.num_bulk_in		= 2,
3021*1da177e4SLinus Torvalds 	.num_bulk_out		= 2,
3022*1da177e4SLinus Torvalds 	.num_ports		= 2,
3023*1da177e4SLinus Torvalds 	.open			= edge_open,
3024*1da177e4SLinus Torvalds 	.close			= edge_close,
3025*1da177e4SLinus Torvalds 	.throttle		= edge_throttle,
3026*1da177e4SLinus Torvalds 	.unthrottle		= edge_unthrottle,
3027*1da177e4SLinus Torvalds 	.attach			= edge_startup,
3028*1da177e4SLinus Torvalds 	.shutdown		= edge_shutdown,
3029*1da177e4SLinus Torvalds 	.ioctl			= edge_ioctl,
3030*1da177e4SLinus Torvalds 	.set_termios		= edge_set_termios,
3031*1da177e4SLinus Torvalds 	.tiocmget		= edge_tiocmget,
3032*1da177e4SLinus Torvalds 	.tiocmset		= edge_tiocmset,
3033*1da177e4SLinus Torvalds 	.write			= edge_write,
3034*1da177e4SLinus Torvalds 	.write_room		= edge_write_room,
3035*1da177e4SLinus Torvalds 	.chars_in_buffer	= edge_chars_in_buffer,
3036*1da177e4SLinus Torvalds 	.break_ctl		= edge_break,
3037*1da177e4SLinus Torvalds 	.read_int_callback	= edge_interrupt_callback,
3038*1da177e4SLinus Torvalds 	.read_bulk_callback	= edge_bulk_in_callback,
3039*1da177e4SLinus Torvalds 	.write_bulk_callback	= edge_bulk_out_callback,
3040*1da177e4SLinus Torvalds };
3041*1da177e4SLinus Torvalds 
3042*1da177e4SLinus Torvalds 
3043*1da177e4SLinus Torvalds static int __init edgeport_init(void)
3044*1da177e4SLinus Torvalds {
3045*1da177e4SLinus Torvalds 	int retval;
3046*1da177e4SLinus Torvalds 	retval = usb_serial_register(&edgeport_1port_device);
3047*1da177e4SLinus Torvalds 	if (retval)
3048*1da177e4SLinus Torvalds 		goto failed_1port_device_register;
3049*1da177e4SLinus Torvalds 	retval = usb_serial_register(&edgeport_2port_device);
3050*1da177e4SLinus Torvalds 	if (retval)
3051*1da177e4SLinus Torvalds 		goto failed_2port_device_register;
3052*1da177e4SLinus Torvalds 	retval = usb_register(&io_driver);
3053*1da177e4SLinus Torvalds 	if (retval)
3054*1da177e4SLinus Torvalds 		goto failed_usb_register;
3055*1da177e4SLinus Torvalds 	info(DRIVER_DESC " " DRIVER_VERSION);
3056*1da177e4SLinus Torvalds 	return 0;
3057*1da177e4SLinus Torvalds failed_usb_register:
3058*1da177e4SLinus Torvalds 	usb_serial_deregister(&edgeport_2port_device);
3059*1da177e4SLinus Torvalds failed_2port_device_register:
3060*1da177e4SLinus Torvalds 	usb_serial_deregister(&edgeport_1port_device);
3061*1da177e4SLinus Torvalds failed_1port_device_register:
3062*1da177e4SLinus Torvalds 	return retval;
3063*1da177e4SLinus Torvalds }
3064*1da177e4SLinus Torvalds 
3065*1da177e4SLinus Torvalds static void __exit edgeport_exit (void)
3066*1da177e4SLinus Torvalds {
3067*1da177e4SLinus Torvalds 	usb_deregister (&io_driver);
3068*1da177e4SLinus Torvalds 	usb_serial_deregister (&edgeport_1port_device);
3069*1da177e4SLinus Torvalds 	usb_serial_deregister (&edgeport_2port_device);
3070*1da177e4SLinus Torvalds }
3071*1da177e4SLinus Torvalds 
3072*1da177e4SLinus Torvalds module_init(edgeport_init);
3073*1da177e4SLinus Torvalds module_exit(edgeport_exit);
3074*1da177e4SLinus Torvalds 
3075*1da177e4SLinus Torvalds /* Module information */
3076*1da177e4SLinus Torvalds MODULE_AUTHOR(DRIVER_AUTHOR);
3077*1da177e4SLinus Torvalds MODULE_DESCRIPTION(DRIVER_DESC);
3078*1da177e4SLinus Torvalds MODULE_LICENSE("GPL");
3079*1da177e4SLinus Torvalds 
3080*1da177e4SLinus Torvalds module_param(debug, bool, S_IRUGO | S_IWUSR);
3081*1da177e4SLinus Torvalds MODULE_PARM_DESC(debug, "Debug enabled or not");
3082*1da177e4SLinus Torvalds 
3083*1da177e4SLinus Torvalds module_param(low_latency, bool, S_IRUGO | S_IWUSR);
3084*1da177e4SLinus Torvalds MODULE_PARM_DESC(low_latency, "Low latency enabled or not");
3085*1da177e4SLinus Torvalds 
3086*1da177e4SLinus Torvalds module_param(closing_wait, int, S_IRUGO | S_IWUSR);
3087*1da177e4SLinus Torvalds MODULE_PARM_DESC(closing_wait, "Maximum wait for data to drain, in .01 secs");
3088*1da177e4SLinus Torvalds 
3089*1da177e4SLinus Torvalds module_param(ignore_cpu_rev, bool, S_IRUGO | S_IWUSR);
3090*1da177e4SLinus Torvalds MODULE_PARM_DESC(ignore_cpu_rev, "Ignore the cpu revision when connecting to a device");
3091*1da177e4SLinus Torvalds 
3092