1/*
2 * mos7720.c
3 *   Controls the Moschip 7720 usb to dual port serial convertor
4 *
5 * Copyright 2006 Moschip Semiconductor Tech. Ltd.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, version 2 of the License.
10 *
11 * Developed by:
12 * 	VijayaKumar.G.N. <vijaykumar@aspirecom.net>
13 *	AjayKumar <ajay@aspirecom.net>
14 *	Gurudeva.N. <gurudev@aspirecom.net>
15 *
16 * Cleaned up from the original by:
17 *	Greg Kroah-Hartman <gregkh@suse.de>
18 *
19 * Originally based on drivers/usb/serial/io_edgeport.c which is:
20 *	Copyright (C) 2000 Inside Out Networks, All rights reserved.
21 *	Copyright (C) 2001-2002 Greg Kroah-Hartman <greg@kroah.com>
22 */
23#include <linux/kernel.h>
24#include <linux/errno.h>
25#include <linux/init.h>
26#include <linux/slab.h>
27#include <linux/tty.h>
28#include <linux/tty_driver.h>
29#include <linux/tty_flip.h>
30#include <linux/module.h>
31#include <linux/spinlock.h>
32#include <linux/serial.h>
33#include <linux/serial_reg.h>
34#include <linux/usb.h>
35#include <linux/usb/serial.h>
36#include <asm/uaccess.h>
37
38
39/*
40 * Version Information
41 */
42#define DRIVER_VERSION "1.0.0.4F"
43#define DRIVER_AUTHOR "Aspire Communications pvt Ltd."
44#define DRIVER_DESC "Moschip USB Serial Driver"
45
46/* default urb timeout */
47#define MOS_WDR_TIMEOUT	(HZ * 5)
48
49#define MOS_PORT1	0x0200
50#define MOS_PORT2	0x0300
51#define MOS_VENREG	0x0000
52#define MOS_MAX_PORT	0x02
53#define MOS_WRITE	0x0E
54#define MOS_READ	0x0D
55
56/* Interrupt Rotinue Defines	*/
57#define SERIAL_IIR_RLS	0x06
58#define SERIAL_IIR_RDA	0x04
59#define SERIAL_IIR_CTI	0x0c
60#define SERIAL_IIR_THR	0x02
61#define SERIAL_IIR_MS	0x00
62
63#define NUM_URBS			16	/* URB Count */
64#define URB_TRANSFER_BUFFER_SIZE	32	/* URB Size */
65
66/* This structure holds all of the local port information */
67struct moschip_port
68{
69	__u8	shadowLCR;		/* last LCR value received */
70	__u8	shadowMCR;		/* last MCR value received */
71	__u8	shadowMSR;		/* last MSR value received */
72	char			open;
73	struct async_icount	icount;
74	struct usb_serial_port	*port;	/* loop back to the owner */
75	struct urb		*write_urb_pool[NUM_URBS];
76};
77
78/* This structure holds all of the individual serial device information */
79struct moschip_serial
80{
81	int interrupt_started;
82};
83
84static int debug;
85
86#define USB_VENDOR_ID_MOSCHIP		0x9710
87#define MOSCHIP_DEVICE_ID_7720		0x7720
88#define MOSCHIP_DEVICE_ID_7715		0x7715
89
90static struct usb_device_id moschip_port_id_table [] = {
91	{ USB_DEVICE(USB_VENDOR_ID_MOSCHIP,MOSCHIP_DEVICE_ID_7720) },
92	{ } /* terminating entry */
93};
94MODULE_DEVICE_TABLE(usb, moschip_port_id_table);
95
96
97/*
98 * mos7720_interrupt_callback
99 *	this is the callback function for when we have received data on the
100 *	interrupt endpoint.
101 */
102static void mos7720_interrupt_callback(struct urb *urb)
103{
104	int result;
105	int length;
106	__u8 *data;
107	__u8 sp1;
108	__u8 sp2;
109
110	dbg("%s"," : Entering\n");
111
112	if (!urb) {
113		dbg("%s","Invalid Pointer !!!!:\n");
114		return;
115	}
116
117	switch (urb->status) {
118	case 0:
119		/* success */
120		break;
121	case -ECONNRESET:
122	case -ENOENT:
123	case -ESHUTDOWN:
124		/* this urb is terminated, clean up */
125		dbg("%s - urb shutting down with status: %d", __FUNCTION__,
126		    urb->status);
127		return;
128	default:
129		dbg("%s - nonzero urb status received: %d", __FUNCTION__,
130		    urb->status);
131		goto exit;
132	}
133
134	length = urb->actual_length;
135	data = urb->transfer_buffer;
136
137	/* Moschip get 4 bytes
138	 * Byte 1 IIR Port 1 (port.number is 0)
139	 * Byte 2 IIR Port 2 (port.number is 1)
140	 * Byte 3 --------------
141	 * Byte 4 FIFO status for both */
142
143	/* the above description is inverted
144	 * 	oneukum 2007-03-14 */
145
146	if (unlikely(length != 4)) {
147		dbg("Wrong data !!!");
148		return;
149	}
150
151	sp1 = data[3];
152	sp2 = data[2];
153
154	if ((sp1 | sp2) & 0x01) {
155		/* No Interrupt Pending in both the ports */
156		dbg("No Interrupt !!!");
157	} else {
158		switch (sp1 & 0x0f) {
159		case SERIAL_IIR_RLS:
160			dbg("Serial Port 1: Receiver status error or address "
161			    "bit detected in 9-bit mode\n");
162			break;
163		case SERIAL_IIR_CTI:
164			dbg("Serial Port 1: Receiver time out");
165			break;
166		case SERIAL_IIR_MS:
167			dbg("Serial Port 1: Modem status change");
168			break;
169		}
170
171		switch (sp2 & 0x0f) {
172		case SERIAL_IIR_RLS:
173			dbg("Serial Port 2: Receiver status error or address "
174			    "bit detected in 9-bit mode");
175			break;
176		case SERIAL_IIR_CTI:
177			dbg("Serial Port 2: Receiver time out");
178			break;
179		case SERIAL_IIR_MS:
180			dbg("Serial Port 2: Modem status change");
181			break;
182		}
183	}
184
185exit:
186	result = usb_submit_urb(urb, GFP_ATOMIC);
187	if (result)
188		dev_err(&urb->dev->dev,
189			"%s - Error %d submitting control urb\n",
190			__FUNCTION__, result);
191	return;
192}
193
194/*
195 * mos7720_bulk_in_callback
196 *	this is the callback function for when we have received data on the
197 *	bulk in endpoint.
198 */
199static void mos7720_bulk_in_callback(struct urb *urb)
200{
201	int status;
202	unsigned char *data ;
203	struct usb_serial_port *port;
204	struct moschip_port *mos7720_port;
205	struct tty_struct *tty;
206
207	if (urb->status) {
208		dbg("nonzero read bulk status received: %d",urb->status);
209		return;
210	}
211
212	mos7720_port = urb->context;
213	if (!mos7720_port) {
214		dbg("%s","NULL mos7720_port pointer \n");
215		return ;
216	}
217
218	port = mos7720_port->port;
219
220	dbg("Entering...%s", __FUNCTION__);
221
222	data = urb->transfer_buffer;
223
224	tty = port->tty;
225	if (tty && urb->actual_length) {
226		tty_buffer_request_room(tty, urb->actual_length);
227		tty_insert_flip_string(tty, data, urb->actual_length);
228		tty_flip_buffer_push(tty);
229	}
230
231	if (!port->read_urb) {
232		dbg("URB KILLED !!!");
233		return;
234	}
235
236	if (port->read_urb->status != -EINPROGRESS) {
237		port->read_urb->dev = port->serial->dev;
238
239		status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
240		if (status)
241			dbg("usb_submit_urb(read bulk) failed, status = %d",
242			    status);
243	}
244}
245
246/*
247 * mos7720_bulk_out_data_callback
248 *	this is the callback function for when we have finished sending serial
249 *	data on the bulk out endpoint.
250 */
251static void mos7720_bulk_out_data_callback(struct urb *urb)
252{
253	struct moschip_port *mos7720_port;
254	struct tty_struct *tty;
255
256	if (urb->status) {
257		dbg("nonzero write bulk status received:%d", urb->status);
258		return;
259	}
260
261	mos7720_port = urb->context;
262	if (!mos7720_port) {
263		dbg("NULL mos7720_port pointer");
264		return ;
265	}
266
267	dbg("Entering .........");
268
269	tty = mos7720_port->port->tty;
270
271	if (tty && mos7720_port->open)
272		tty_wakeup(tty);
273}
274
275/*
276 * send_mos_cmd
277 *	this function will be used for sending command to device
278 */
279static int send_mos_cmd(struct usb_serial *serial, __u8 request, __u16 value,
280			__u16 index, void *data)
281{
282	int status;
283	unsigned int pipe;
284	u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
285	__u8 requesttype;
286	__u16 size = 0x0000;
287
288	if (value < MOS_MAX_PORT) {
289		if (product == MOSCHIP_DEVICE_ID_7715) {
290			value = value*0x100+0x100;
291		} else {
292			value = value*0x100+0x200;
293		}
294	} else {
295		value = 0x0000;
296		if ((product == MOSCHIP_DEVICE_ID_7715) &&
297		    (index != 0x08)) {
298			dbg("serial->product== MOSCHIP_DEVICE_ID_7715");
299			//index = 0x01 ;
300		}
301	}
302
303	if (request == MOS_WRITE) {
304		request = (__u8)MOS_WRITE;
305		requesttype = (__u8)0x40;
306		value  = value + (__u16)*((unsigned char *)data);
307		data = NULL;
308		pipe = usb_sndctrlpipe(serial->dev, 0);
309	} else {
310		request = (__u8)MOS_READ;
311		requesttype = (__u8)0xC0;
312		size = 0x01;
313		pipe = usb_rcvctrlpipe(serial->dev,0);
314	}
315
316	status = usb_control_msg(serial->dev, pipe, request, requesttype,
317				 value, index, data, size, MOS_WDR_TIMEOUT);
318
319	if (status < 0)
320		dbg("Command Write failed Value %x index %x\n",value,index);
321
322	return status;
323}
324
325static int mos7720_open(struct usb_serial_port *port, struct file * filp)
326{
327	struct usb_serial *serial;
328	struct usb_serial_port *port0;
329	struct urb *urb;
330	struct moschip_serial *mos7720_serial;
331	struct moschip_port *mos7720_port;
332	int response;
333	int port_number;
334	char data;
335	int allocated_urbs = 0;
336	int j;
337
338	serial = port->serial;
339
340	mos7720_port = usb_get_serial_port_data(port);
341	if (mos7720_port == NULL)
342		return -ENODEV;
343
344	port0 = serial->port[0];
345
346	mos7720_serial = usb_get_serial_data(serial);
347
348	if (mos7720_serial == NULL || port0 == NULL)
349		return -ENODEV;
350
351	usb_clear_halt(serial->dev, port->write_urb->pipe);
352	usb_clear_halt(serial->dev, port->read_urb->pipe);
353
354	/* Initialising the write urb pool */
355	for (j = 0; j < NUM_URBS; ++j) {
356		urb = usb_alloc_urb(0,GFP_KERNEL);
357		mos7720_port->write_urb_pool[j] = urb;
358
359		if (urb == NULL) {
360			err("No more urbs???");
361			continue;
362		}
363
364		urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
365					       GFP_KERNEL);
366		if (!urb->transfer_buffer) {
367			err("%s-out of memory for urb buffers.", __FUNCTION__);
368			usb_free_urb(mos7720_port->write_urb_pool[j]);
369			mos7720_port->write_urb_pool[j] = NULL;
370			continue;
371		}
372		allocated_urbs++;
373	}
374
375	if (!allocated_urbs)
376		return -ENOMEM;
377
378	 /* Initialize MCS7720 -- Write Init values to corresponding Registers
379	  *
380	  * Register Index
381	  * 1 : IER
382	  * 2 : FCR
383	  * 3 : LCR
384	  * 4 : MCR
385	  *
386	  * 0x08 : SP1/2 Control Reg
387	  */
388	port_number = port->number - port->serial->minor;
389	send_mos_cmd(port->serial, MOS_READ, port_number, UART_LSR, &data);
390	dbg("SS::%p LSR:%x\n",mos7720_port, data);
391
392	dbg("Check:Sending Command ..........");
393
394	data = 0x02;
395	send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x01, &data);
396	data = 0x02;
397	send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x02, &data);
398
399	data = 0x00;
400	send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
401	data = 0x00;
402	send_mos_cmd(serial, MOS_WRITE, port_number, 0x02, &data);
403
404	data = 0xCF;
405	send_mos_cmd(serial, MOS_WRITE, port_number, 0x02, &data);
406	data = 0x03;
407        mos7720_port->shadowLCR  = data;
408	send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data);
409	data = 0x0b;
410        mos7720_port->shadowMCR  = data;
411	send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
412	data = 0x0b;
413	send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
414
415	data = 0x00;
416	send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data);
417	data = 0x00;
418	send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data);
419
420/*	data = 0x00;
421	send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, port_number + 1, &data);
422	data = 0x03;
423	send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1, &data);
424	data = 0x00;
425	send_mos_cmd(port->serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1, &data);
426*/
427	data = 0x00;
428	send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data);
429
430	data = data | (port->number - port->serial->minor + 1);
431	send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data);
432
433	data = 0x83;
434        mos7720_port->shadowLCR  = data;
435	send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data);
436	data = 0x0c;
437	send_mos_cmd(serial, MOS_WRITE, port_number, 0x00, &data);
438	data = 0x00;
439	send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
440	data = 0x03;
441        mos7720_port->shadowLCR  = data;
442	send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data);
443	data = 0x0c;
444	send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
445	data = 0x0c;
446	send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
447
448//Matrix
449
450	/* force low_latency on so that our tty_push actually forces *
451	 * the data through,otherwise it is scheduled, and with      *
452	 * high data rates (like with OHCI) data can get lost.       */
453
454	if (port->tty)
455		port->tty->low_latency = 1;
456
457	/* see if we've set up our endpoint info yet   *
458	 * (can't set it up in mos7720_startup as the  *
459	 * structures were not set up at that time.)   */
460	if (!mos7720_serial->interrupt_started) {
461		dbg("Interrupt buffer NULL !!!");
462
463		/* not set up yet, so do it now */
464		mos7720_serial->interrupt_started = 1;
465
466		dbg("To Submit URB !!!");
467
468		/* set up our interrupt urb */
469		usb_fill_int_urb(port0->interrupt_in_urb, serial->dev,
470				 usb_rcvintpipe(serial->dev,
471				 		port->interrupt_in_endpointAddress),
472				 port0->interrupt_in_buffer,
473				 port0->interrupt_in_urb->transfer_buffer_length,
474				 mos7720_interrupt_callback, mos7720_port,
475				 port0->interrupt_in_urb->interval);
476
477		/* start interrupt read for this mos7720 this interrupt *
478	         * will continue as long as the mos7720 is connected    */
479		dbg("Submit URB over !!!");
480		response = usb_submit_urb(port0->interrupt_in_urb, GFP_KERNEL);
481		if (response)
482			dev_err(&port->dev,
483				"%s - Error %d submitting control urb",
484				__FUNCTION__, response);
485	}
486
487	/* set up our bulk in urb */
488	usb_fill_bulk_urb(port->read_urb, serial->dev,
489			  usb_rcvbulkpipe(serial->dev,
490			  		  port->bulk_in_endpointAddress),
491			  port->bulk_in_buffer,
492			  port->read_urb->transfer_buffer_length,
493			  mos7720_bulk_in_callback, mos7720_port);
494	response = usb_submit_urb(port->read_urb, GFP_KERNEL);
495	if (response)
496		dev_err(&port->dev,
497			"%s - Error %d submitting read urb", __FUNCTION__, response);
498
499	/* initialize our icount structure */
500	memset(&(mos7720_port->icount), 0x00, sizeof(mos7720_port->icount));
501
502	/* initialize our port settings */
503	mos7720_port->shadowMCR = UART_MCR_OUT2; /* Must set to enable ints! */
504
505	/* send a open port command */
506	mos7720_port->open = 1;
507
508	return 0;
509}
510
511/*
512 * mos7720_chars_in_buffer
513 *	this function is called by the tty driver when it wants to know how many
514 *	bytes of data we currently have outstanding in the port (data that has
515 *	been written, but hasn't made it out the port yet)
516 *	If successful, we return the number of bytes left to be written in the
517 *	system,
518 *	Otherwise we return a negative error number.
519 */
520static int mos7720_chars_in_buffer(struct usb_serial_port *port)
521{
522	int i;
523	int chars = 0;
524	struct moschip_port *mos7720_port;
525
526	dbg("%s:entering ...........", __FUNCTION__);
527
528	mos7720_port = usb_get_serial_port_data(port);
529	if (mos7720_port == NULL) {
530		dbg("%s:leaving ...........", __FUNCTION__);
531		return -ENODEV;
532	}
533
534	for (i = 0; i < NUM_URBS; ++i) {
535		if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status == -EINPROGRESS)
536			chars += URB_TRANSFER_BUFFER_SIZE;
537	}
538	dbg("%s - returns %d", __FUNCTION__, chars);
539	return chars;
540}
541
542static void mos7720_close(struct usb_serial_port *port, struct file *filp)
543{
544	struct usb_serial *serial;
545	struct moschip_port *mos7720_port;
546	char data;
547	int j;
548
549	dbg("mos7720_close:entering...");
550
551	serial = port->serial;
552
553	mos7720_port = usb_get_serial_port_data(port);
554	if (mos7720_port == NULL)
555		return;
556
557	for (j = 0; j < NUM_URBS; ++j)
558		usb_kill_urb(mos7720_port->write_urb_pool[j]);
559
560	/* Freeing Write URBs */
561	for (j = 0; j < NUM_URBS; ++j) {
562		if (mos7720_port->write_urb_pool[j]) {
563			kfree(mos7720_port->write_urb_pool[j]->transfer_buffer);
564			usb_free_urb(mos7720_port->write_urb_pool[j]);
565		}
566	}
567
568	/* While closing port, shutdown all bulk read, write  *
569	 * and interrupt read if they exists                  */
570	if (serial->dev) {
571		dbg("Shutdown bulk write");
572		usb_kill_urb(port->write_urb);
573		dbg("Shutdown bulk read");
574		usb_kill_urb(port->read_urb);
575	}
576
577	data = 0x00;
578	send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,
579		     0x04, &data);
580
581	data = 0x00;
582	send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,
583		     0x01, &data);
584
585	mos7720_port->open = 0;
586
587	dbg("Leaving %s", __FUNCTION__);
588}
589
590static void mos7720_break(struct usb_serial_port *port, int break_state)
591{
592        unsigned char data;
593	struct usb_serial *serial;
594	struct moschip_port *mos7720_port;
595
596	dbg("Entering %s", __FUNCTION__);
597
598	serial = port->serial;
599
600	mos7720_port = usb_get_serial_port_data(port);
601	if (mos7720_port == NULL)
602		return;
603
604	if (break_state == -1)
605		data = mos7720_port->shadowLCR | UART_LCR_SBC;
606	else
607		data = mos7720_port->shadowLCR & ~UART_LCR_SBC;
608
609	mos7720_port->shadowLCR  = data;
610	send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,
611		     0x03, &data);
612
613	return;
614}
615
616/*
617 * mos7720_write_room
618 *	this function is called by the tty driver when it wants to know how many
619 *	bytes of data we can accept for a specific port.
620 *	If successful, we return the amount of room that we have for this port
621 *	Otherwise we return a negative error number.
622 */
623static int mos7720_write_room(struct usb_serial_port *port)
624{
625	struct moschip_port *mos7720_port;
626	int room = 0;
627	int i;
628
629	dbg("%s:entering ...........", __FUNCTION__);
630
631	mos7720_port = usb_get_serial_port_data(port);
632	if (mos7720_port == NULL) {
633		dbg("%s:leaving ...........", __FUNCTION__);
634		return -ENODEV;
635	}
636
637	for (i = 0; i < NUM_URBS; ++i) {
638		if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status != -EINPROGRESS)
639			room += URB_TRANSFER_BUFFER_SIZE;
640	}
641
642	dbg("%s - returns %d", __FUNCTION__, room);
643	return room;
644}
645
646static int mos7720_write(struct usb_serial_port *port,
647			 const unsigned char *data, int count)
648{
649	int status;
650	int i;
651	int bytes_sent = 0;
652	int transfer_size;
653
654	struct moschip_port *mos7720_port;
655	struct usb_serial *serial;
656	struct urb    *urb;
657	const unsigned char *current_position = data;
658
659	dbg("%s:entering ...........", __FUNCTION__);
660
661	serial = port->serial;
662
663	mos7720_port = usb_get_serial_port_data(port);
664	if (mos7720_port == NULL) {
665		dbg("mos7720_port is NULL");
666		return -ENODEV;
667	}
668
669	/* try to find a free urb in the list */
670	urb = NULL;
671
672	for (i = 0; i < NUM_URBS; ++i) {
673		if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status != -EINPROGRESS) {
674			urb = mos7720_port->write_urb_pool[i];
675			dbg("URB:%d",i);
676			break;
677		}
678	}
679
680	if (urb == NULL) {
681		dbg("%s - no more free urbs", __FUNCTION__);
682		goto exit;
683	}
684
685	if (urb->transfer_buffer == NULL) {
686		urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
687					       GFP_KERNEL);
688		if (urb->transfer_buffer == NULL) {
689			err("%s no more kernel memory...", __FUNCTION__);
690			goto exit;
691		}
692	}
693	transfer_size = min (count, URB_TRANSFER_BUFFER_SIZE);
694
695	memcpy(urb->transfer_buffer, current_position, transfer_size);
696	usb_serial_debug_data(debug, &port->dev, __FUNCTION__, transfer_size,
697			      urb->transfer_buffer);
698
699	/* fill urb with data and submit  */
700	usb_fill_bulk_urb(urb, serial->dev,
701			  usb_sndbulkpipe(serial->dev,
702			  		  port->bulk_out_endpointAddress),
703			  urb->transfer_buffer, transfer_size,
704			  mos7720_bulk_out_data_callback, mos7720_port);
705
706	/* send it down the pipe */
707	status = usb_submit_urb(urb,GFP_ATOMIC);
708	if (status) {
709		err("%s - usb_submit_urb(write bulk) failed with status = %d",
710		    __FUNCTION__, status);
711		bytes_sent = status;
712		goto exit;
713	}
714	bytes_sent = transfer_size;
715
716exit:
717	return bytes_sent;
718}
719
720static void mos7720_throttle(struct usb_serial_port *port)
721{
722	struct moschip_port *mos7720_port;
723	struct tty_struct *tty;
724	int status;
725
726	dbg("%s- port %d\n", __FUNCTION__, port->number);
727
728	mos7720_port = usb_get_serial_port_data(port);
729
730	if (mos7720_port == NULL)
731		return;
732
733	if (!mos7720_port->open) {
734		dbg("port not opened");
735		return;
736	}
737
738	dbg("%s: Entering ..........", __FUNCTION__);
739
740	tty = port->tty;
741	if (!tty) {
742		dbg("%s - no tty available", __FUNCTION__);
743		return;
744	}
745
746	/* if we are implementing XON/XOFF, send the stop character */
747	if (I_IXOFF(tty)) {
748		unsigned char stop_char = STOP_CHAR(tty);
749		status = mos7720_write(port, &stop_char, 1);
750		if (status <= 0)
751			return;
752	}
753
754	/* if we are implementing RTS/CTS, toggle that line */
755	if (tty->termios->c_cflag & CRTSCTS) {
756		mos7720_port->shadowMCR &= ~UART_MCR_RTS;
757		status = send_mos_cmd(port->serial, MOS_WRITE,
758				      port->number - port->serial->minor,
759				      UART_MCR, &mos7720_port->shadowMCR);
760		if (status != 0)
761			return;
762	}
763}
764
765static void mos7720_unthrottle(struct usb_serial_port *port)
766{
767	struct tty_struct *tty;
768	int status;
769	struct moschip_port *mos7720_port = usb_get_serial_port_data(port);
770
771	if (mos7720_port == NULL)
772		return;
773
774	if (!mos7720_port->open) {
775		dbg("%s - port not opened", __FUNCTION__);
776		return;
777	}
778
779	dbg("%s: Entering ..........", __FUNCTION__);
780
781	tty = port->tty;
782	if (!tty) {
783		dbg("%s - no tty available", __FUNCTION__);
784		return;
785	}
786
787	/* if we are implementing XON/XOFF, send the start character */
788	if (I_IXOFF(tty)) {
789		unsigned char start_char = START_CHAR(tty);
790		status = mos7720_write(port, &start_char, 1);
791		if (status <= 0)
792			return;
793	}
794
795	/* if we are implementing RTS/CTS, toggle that line */
796	if (tty->termios->c_cflag & CRTSCTS) {
797		mos7720_port->shadowMCR |= UART_MCR_RTS;
798		status = send_mos_cmd(port->serial, MOS_WRITE,
799				      port->number - port->serial->minor,
800				      UART_MCR, &mos7720_port->shadowMCR);
801		if (status != 0)
802			return;
803	}
804}
805
806static int set_higher_rates(struct moschip_port *mos7720_port,
807			    unsigned int baud)
808{
809	unsigned char data;
810	struct usb_serial_port *port;
811	struct usb_serial *serial;
812	int port_number;
813
814	if (mos7720_port == NULL)
815		return -EINVAL;
816
817	port = mos7720_port->port;
818	serial = port->serial;
819
820        /***********************************************
821         *      Init Sequence for higher rates
822         ***********************************************/
823	dbg("Sending Setting Commands ..........");
824	port_number = port->number - port->serial->minor;
825
826	data = 0x000;
827	send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
828	data = 0x000;
829	send_mos_cmd(serial, MOS_WRITE, port_number, 0x02, &data);
830	data = 0x0CF;
831	send_mos_cmd(serial, MOS_WRITE, port->number, 0x02, &data);
832	data = 0x00b;
833        mos7720_port->shadowMCR  = data;
834	send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
835	data = 0x00b;
836	send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
837
838	data = 0x000;
839	send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data);
840	data = 0x000;
841	send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data);
842
843
844        /***********************************************
845         *              Set for higher rates           *
846         ***********************************************/
847
848	data = baud * 0x10;
849	send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1,&data);
850
851	data = 0x003;
852	send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data);
853	data = 0x003;
854	send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data);
855
856	data = 0x02b;
857        mos7720_port->shadowMCR  = data;
858	send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
859	data = 0x02b;
860	send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
861
862        /***********************************************
863         *              Set DLL/DLM
864         ***********************************************/
865
866	data = mos7720_port->shadowLCR | UART_LCR_DLAB;
867        mos7720_port->shadowLCR  = data;
868	send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data);
869
870	data =  0x001; /* DLL */
871        send_mos_cmd(serial, MOS_WRITE, port_number, 0x00, &data);
872	data =  0x000; /* DLM */
873        send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
874
875	data = mos7720_port->shadowLCR & ~UART_LCR_DLAB;
876        mos7720_port->shadowLCR  = data;
877	send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data);
878
879	return 0;
880}
881
882/* baud rate information */
883struct divisor_table_entry
884{
885	__u32  baudrate;
886	__u16  divisor;
887};
888
889/* Define table of divisors for moschip 7720 hardware	   *
890 * These assume a 3.6864MHz crystal, the standard /16, and *
891 * MCR.7 = 0.						   */
892static struct divisor_table_entry divisor_table[] = {
893	{   50,		2304},
894	{   110,	1047},	/* 2094.545455 => 230450   => .0217 % over */
895	{   134,	857},	/* 1713.011152 => 230398.5 => .00065% under */
896	{   150,	768},
897	{   300,	384},
898	{   600,	192},
899	{   1200,	96},
900	{   1800,	64},
901	{   2400,	48},
902	{   4800,	24},
903	{   7200,	16},
904	{   9600,	12},
905	{   19200,	6},
906	{   38400,	3},
907	{   57600,	2},
908	{   115200,	1},
909};
910
911/*****************************************************************************
912 * calc_baud_rate_divisor
913 *	this function calculates the proper baud rate divisor for the specified
914 *	baud rate.
915 *****************************************************************************/
916static int calc_baud_rate_divisor(int baudrate, int *divisor)
917{
918	int i;
919	__u16 custom;
920	__u16 round1;
921	__u16 round;
922
923
924	dbg("%s - %d", __FUNCTION__, baudrate);
925
926	for (i = 0; i < ARRAY_SIZE(divisor_table); i++) {
927		if (divisor_table[i].baudrate == baudrate) {
928			*divisor = divisor_table[i].divisor;
929			return 0;
930		}
931	}
932
933        /* After trying for all the standard baud rates    *
934         * Try calculating the divisor for this baud rate  */
935	if (baudrate > 75 &&  baudrate < 230400) {
936		/* get the divisor */
937		custom = (__u16)(230400L  / baudrate);
938
939		/* Check for round off */
940		round1 = (__u16)(2304000L / baudrate);
941		round = (__u16)(round1 - (custom * 10));
942		if (round > 4)
943			custom++;
944		*divisor = custom;
945
946		dbg("Baud %d = %d",baudrate, custom);
947		return 0;
948	}
949
950	dbg("Baud calculation Failed...");
951	return -EINVAL;
952}
953
954/*
955 * send_cmd_write_baud_rate
956 *	this function sends the proper command to change the baud rate of the
957 *	specified port.
958 */
959static int send_cmd_write_baud_rate(struct moschip_port *mos7720_port,
960				    int baudrate)
961{
962	struct usb_serial_port *port;
963	struct usb_serial *serial;
964	int divisor;
965	int status;
966	unsigned char data;
967	unsigned char number;
968
969	if (mos7720_port == NULL)
970		return -1;
971
972	port = mos7720_port->port;
973	serial = port->serial;
974
975	dbg("%s: Entering ..........", __FUNCTION__);
976
977	number = port->number - port->serial->minor;
978	dbg("%s - port = %d, baud = %d", __FUNCTION__, port->number, baudrate);
979
980        /* Calculate the Divisor */
981	status = calc_baud_rate_divisor(baudrate, &divisor);
982	if (status) {
983		err("%s - bad baud rate", __FUNCTION__);
984		return status;
985	}
986
987        /* Enable access to divisor latch */
988        data = mos7720_port->shadowLCR | UART_LCR_DLAB;
989        mos7720_port->shadowLCR  = data;
990        send_mos_cmd(serial, MOS_WRITE, number, UART_LCR, &data);
991
992	/* Write the divisor */
993	data = ((unsigned char)(divisor & 0xff));
994        send_mos_cmd(serial, MOS_WRITE, number, 0x00, &data);
995
996	data = ((unsigned char)((divisor & 0xff00) >> 8));
997        send_mos_cmd(serial, MOS_WRITE, number, 0x01, &data);
998
999        /* Disable access to divisor latch */
1000        data = mos7720_port->shadowLCR & ~UART_LCR_DLAB;
1001        mos7720_port->shadowLCR = data;
1002        send_mos_cmd(serial, MOS_WRITE, number, 0x03, &data);
1003
1004	return status;
1005}
1006
1007/*
1008 * change_port_settings
1009 *	This routine is called to set the UART on the device to match
1010 *      the specified new settings.
1011 */
1012static void change_port_settings(struct moschip_port *mos7720_port,
1013				 struct ktermios *old_termios)
1014{
1015	struct usb_serial_port *port;
1016	struct usb_serial *serial;
1017	struct tty_struct *tty;
1018	int baud;
1019	unsigned cflag;
1020	unsigned iflag;
1021	__u8 mask = 0xff;
1022	__u8 lData;
1023	__u8 lParity;
1024	__u8 lStop;
1025	int status;
1026	int port_number;
1027	char data;
1028
1029	if (mos7720_port == NULL)
1030		return ;
1031
1032	port = mos7720_port->port;
1033	serial = port->serial;
1034	port_number = port->number - port->serial->minor;
1035
1036	dbg("%s - port %d", __FUNCTION__, port->number);
1037
1038	if (!mos7720_port->open) {
1039		dbg("%s - port not opened", __FUNCTION__);
1040		return;
1041	}
1042
1043	tty = mos7720_port->port->tty;
1044
1045	if ((!tty) || (!tty->termios)) {
1046		dbg("%s - no tty structures", __FUNCTION__);
1047		return;
1048	}
1049
1050	dbg("%s: Entering ..........", __FUNCTION__);
1051
1052	lData = UART_LCR_WLEN8;
1053	lStop = 0x00;	/* 1 stop bit */
1054	lParity = 0x00;	/* No parity */
1055
1056	cflag = tty->termios->c_cflag;
1057	iflag = tty->termios->c_iflag;
1058
1059	/* Change the number of bits */
1060	switch (cflag & CSIZE) {
1061	case CS5:
1062		lData = UART_LCR_WLEN5;
1063		mask = 0x1f;
1064		break;
1065
1066	case CS6:
1067		lData = UART_LCR_WLEN6;
1068		mask = 0x3f;
1069		break;
1070
1071	case CS7:
1072		lData = UART_LCR_WLEN7;
1073		mask = 0x7f;
1074		break;
1075	default:
1076	case CS8:
1077		lData = UART_LCR_WLEN8;
1078		break;
1079	}
1080
1081	/* Change the Parity bit */
1082	if (cflag & PARENB) {
1083		if (cflag & PARODD) {
1084			lParity = UART_LCR_PARITY;
1085			dbg("%s - parity = odd", __FUNCTION__);
1086		} else {
1087			lParity = (UART_LCR_EPAR | UART_LCR_PARITY);
1088			dbg("%s - parity = even", __FUNCTION__);
1089		}
1090
1091	} else {
1092		dbg("%s - parity = none", __FUNCTION__);
1093	}
1094
1095	if (cflag & CMSPAR)
1096		lParity = lParity | 0x20;
1097
1098	/* Change the Stop bit */
1099	if (cflag & CSTOPB) {
1100		lStop = UART_LCR_STOP;
1101		dbg("%s - stop bits = 2", __FUNCTION__);
1102	} else {
1103		lStop = 0x00;
1104		dbg("%s - stop bits = 1", __FUNCTION__);
1105	}
1106
1107#define LCR_BITS_MASK		0x03	/* Mask for bits/char field */
1108#define LCR_STOP_MASK		0x04	/* Mask for stop bits field */
1109#define LCR_PAR_MASK		0x38	/* Mask for parity field */
1110
1111	/* Update the LCR with the correct value */
1112	mos7720_port->shadowLCR &= ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK);
1113	mos7720_port->shadowLCR |= (lData | lParity | lStop);
1114
1115
1116	/* Disable Interrupts */
1117	data = 0x00;
1118        send_mos_cmd(serial,MOS_WRITE,port->number - port->serial->minor, UART_IER, &data);
1119
1120	data = 0x00;
1121        send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data);
1122
1123	data = 0xcf;
1124        send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data);
1125
1126	/* Send the updated LCR value to the mos7720 */
1127	data = mos7720_port->shadowLCR;
1128        send_mos_cmd(serial, MOS_WRITE, port_number, UART_LCR, &data);
1129
1130        data = 0x00b;
1131        mos7720_port->shadowMCR = data;
1132        send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
1133        data = 0x00b;
1134        send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
1135
1136	/* set up the MCR register and send it to the mos7720 */
1137	mos7720_port->shadowMCR = UART_MCR_OUT2;
1138	if (cflag & CBAUD)
1139		mos7720_port->shadowMCR |= (UART_MCR_DTR | UART_MCR_RTS);
1140
1141	if (cflag & CRTSCTS) {
1142		mos7720_port->shadowMCR |= (UART_MCR_XONANY);
1143
1144                /* To set hardware flow control to the specified *
1145                 * serial port, in SP1/2_CONTROL_REG             */
1146		if (port->number) {
1147			data = 0x001;
1148			send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT,
1149				     0x08, &data);
1150		} else {
1151			data = 0x002;
1152			send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT,
1153				     0x08, &data);
1154		}
1155	} else {
1156		mos7720_port->shadowMCR &= ~(UART_MCR_XONANY);
1157	}
1158
1159	data = mos7720_port->shadowMCR;
1160	send_mos_cmd(serial, MOS_WRITE, port_number, UART_MCR, &data);
1161
1162	/* Determine divisor based on baud rate */
1163	baud = tty_get_baud_rate(tty);
1164	if (!baud) {
1165		/* pick a default, any default... */
1166		dbg("Picked default baud...");
1167		baud = 9600;
1168	}
1169
1170	if (baud >= 230400) {
1171		set_higher_rates(mos7720_port, baud);
1172		/* Enable Interrupts */
1173		data = 0x0c;
1174		send_mos_cmd(serial, MOS_WRITE, port_number, UART_IER, &data);
1175		return;
1176	}
1177
1178	dbg("%s - baud rate = %d", __FUNCTION__, baud);
1179	status = send_cmd_write_baud_rate(mos7720_port, baud);
1180
1181	/* Enable Interrupts */
1182	data = 0x0c;
1183	send_mos_cmd(serial, MOS_WRITE, port_number, UART_IER, &data);
1184
1185	if (port->read_urb->status != -EINPROGRESS) {
1186		port->read_urb->dev = serial->dev;
1187
1188		status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
1189		if (status)
1190			dbg("usb_submit_urb(read bulk) failed, status = %d",
1191			    status);
1192	}
1193	return;
1194}
1195
1196/*
1197 * mos7720_set_termios
1198 *	this function is called by the tty driver when it wants to change the
1199 *	termios structure.
1200 */
1201static void mos7720_set_termios(struct usb_serial_port *port,
1202				struct ktermios *old_termios)
1203{
1204	int status;
1205	unsigned int cflag;
1206	struct usb_serial *serial;
1207	struct moschip_port *mos7720_port;
1208	struct tty_struct *tty;
1209
1210	serial = port->serial;
1211
1212	mos7720_port = usb_get_serial_port_data(port);
1213
1214	if (mos7720_port == NULL)
1215		return;
1216
1217	tty = port->tty;
1218
1219	if (!port->tty || !port->tty->termios) {
1220		dbg("%s - no tty or termios", __FUNCTION__);
1221		return;
1222	}
1223
1224	if (!mos7720_port->open) {
1225		dbg("%s - port not opened", __FUNCTION__);
1226		return;
1227	}
1228
1229	dbg("%s\n","setting termios - ASPIRE");
1230
1231	cflag = tty->termios->c_cflag;
1232
1233	if (!cflag) {
1234		printk("%s %s\n",__FUNCTION__,"cflag is NULL");
1235		return;
1236	}
1237
1238	/* check that they really want us to change something */
1239	if (old_termios) {
1240		if ((cflag == old_termios->c_cflag) &&
1241		    (RELEVANT_IFLAG(tty->termios->c_iflag) ==
1242		     RELEVANT_IFLAG(old_termios->c_iflag))) {
1243			dbg("Nothing to change");
1244			return;
1245		}
1246	}
1247
1248	dbg("%s - clfag %08x iflag %08x", __FUNCTION__,
1249	    tty->termios->c_cflag,
1250	    RELEVANT_IFLAG(tty->termios->c_iflag));
1251
1252	if (old_termios)
1253		dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,
1254		    old_termios->c_cflag,
1255		    RELEVANT_IFLAG(old_termios->c_iflag));
1256
1257	dbg("%s - port %d", __FUNCTION__, port->number);
1258
1259	/* change the port settings to the new ones specified */
1260	change_port_settings(mos7720_port, old_termios);
1261
1262	if(!port->read_urb) {
1263		dbg("%s","URB KILLED !!!!!\n");
1264		return;
1265	}
1266
1267	if(port->read_urb->status != -EINPROGRESS) {
1268		port->read_urb->dev = serial->dev;
1269		status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
1270		if (status)
1271			dbg("usb_submit_urb(read bulk) failed, status = %d",
1272			    status);
1273	}
1274	return;
1275}
1276
1277/*
1278 * get_lsr_info - get line status register info
1279 *
1280 * Purpose: Let user call ioctl() to get info when the UART physically
1281 * 	    is emptied.  On bus types like RS485, the transmitter must
1282 * 	    release the bus after transmitting. This must be done when
1283 * 	    the transmit shift register is empty, not be done when the
1284 * 	    transmit holding register is empty.  This functionality
1285 * 	    allows an RS485 driver to be written in user space.
1286 */
1287static int get_lsr_info(struct moschip_port *mos7720_port,
1288			unsigned int __user *value)
1289{
1290	int count;
1291	unsigned int result = 0;
1292
1293	count = mos7720_chars_in_buffer(mos7720_port->port);
1294	if (count == 0) {
1295		dbg("%s -- Empty", __FUNCTION__);
1296		result = TIOCSER_TEMT;
1297	}
1298
1299	if (copy_to_user(value, &result, sizeof(int)))
1300		return -EFAULT;
1301	return 0;
1302}
1303
1304/*
1305 * get_number_bytes_avail - get number of bytes available
1306 *
1307 * Purpose: Let user call ioctl to get the count of number of bytes available.
1308 */
1309static int get_number_bytes_avail(struct moschip_port *mos7720_port,
1310				  unsigned int __user *value)
1311{
1312	unsigned int result = 0;
1313	struct tty_struct *tty = mos7720_port->port->tty;
1314
1315	if (!tty)
1316		return -ENOIOCTLCMD;
1317
1318	result = tty->read_cnt;
1319
1320	dbg("%s(%d) = %d", __FUNCTION__,  mos7720_port->port->number, result);
1321	if (copy_to_user(value, &result, sizeof(int)))
1322		return -EFAULT;
1323
1324	return -ENOIOCTLCMD;
1325}
1326
1327static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd,
1328			  unsigned int __user *value)
1329{
1330	unsigned int mcr ;
1331	unsigned int arg;
1332	unsigned char data;
1333
1334	struct usb_serial_port *port;
1335
1336	if (mos7720_port == NULL)
1337		return -1;
1338
1339	port = (struct usb_serial_port*)mos7720_port->port;
1340	mcr = mos7720_port->shadowMCR;
1341
1342	if (copy_from_user(&arg, value, sizeof(int)))
1343		return -EFAULT;
1344
1345	switch (cmd) {
1346	case TIOCMBIS:
1347		if (arg & TIOCM_RTS)
1348			mcr |= UART_MCR_RTS;
1349		if (arg & TIOCM_DTR)
1350			mcr |= UART_MCR_RTS;
1351		if (arg & TIOCM_LOOP)
1352			mcr |= UART_MCR_LOOP;
1353		break;
1354
1355	case TIOCMBIC:
1356		if (arg & TIOCM_RTS)
1357			mcr &= ~UART_MCR_RTS;
1358		if (arg & TIOCM_DTR)
1359			mcr &= ~UART_MCR_RTS;
1360		if (arg & TIOCM_LOOP)
1361			mcr &= ~UART_MCR_LOOP;
1362		break;
1363
1364	case TIOCMSET:
1365		/* turn off the RTS and DTR and LOOPBACK
1366		 * and then only turn on what was asked to */
1367		mcr &=  ~(UART_MCR_RTS | UART_MCR_DTR | UART_MCR_LOOP);
1368		mcr |= ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0);
1369		mcr |= ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0);
1370		mcr |= ((arg & TIOCM_LOOP) ? UART_MCR_LOOP : 0);
1371		break;
1372	}
1373
1374	mos7720_port->shadowMCR = mcr;
1375
1376	data = mos7720_port->shadowMCR;
1377	send_mos_cmd(port->serial, MOS_WRITE,
1378		     port->number - port->serial->minor, UART_MCR, &data);
1379
1380	return 0;
1381}
1382
1383static int get_modem_info(struct moschip_port *mos7720_port,
1384			  unsigned int __user *value)
1385{
1386	unsigned int result = 0;
1387	unsigned int msr = mos7720_port->shadowMSR;
1388	unsigned int mcr = mos7720_port->shadowMCR;
1389
1390	result = ((mcr & UART_MCR_DTR)	? TIOCM_DTR: 0)	  /* 0x002 */
1391		  | ((mcr & UART_MCR_RTS)	? TIOCM_RTS: 0)   /* 0x004 */
1392		  | ((msr & UART_MSR_CTS)	? TIOCM_CTS: 0)   /* 0x020 */
1393		  | ((msr & UART_MSR_DCD)	? TIOCM_CAR: 0)   /* 0x040 */
1394		  | ((msr & UART_MSR_RI)	? TIOCM_RI:  0)   /* 0x080 */
1395		  | ((msr & UART_MSR_DSR)	? TIOCM_DSR: 0);  /* 0x100 */
1396
1397
1398	dbg("%s -- %x", __FUNCTION__, result);
1399
1400	if (copy_to_user(value, &result, sizeof(int)))
1401		return -EFAULT;
1402	return 0;
1403}
1404
1405static int get_serial_info(struct moschip_port *mos7720_port,
1406			   struct serial_struct __user *retinfo)
1407{
1408	struct serial_struct tmp;
1409
1410	if (!retinfo)
1411		return -EFAULT;
1412
1413	memset(&tmp, 0, sizeof(tmp));
1414
1415	tmp.type		= PORT_16550A;
1416	tmp.line		= mos7720_port->port->serial->minor;
1417	tmp.port		= mos7720_port->port->number;
1418	tmp.irq			= 0;
1419	tmp.flags		= ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
1420        tmp.xmit_fifo_size	= NUM_URBS * URB_TRANSFER_BUFFER_SIZE;
1421	tmp.baud_base		= 9600;
1422	tmp.close_delay		= 5*HZ;
1423	tmp.closing_wait	= 30*HZ;
1424
1425	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
1426		return -EFAULT;
1427	return 0;
1428}
1429
1430static int mos7720_ioctl(struct usb_serial_port *port, struct file *file,
1431			 unsigned int cmd, unsigned long arg)
1432{
1433	struct moschip_port *mos7720_port;
1434	struct async_icount cnow;
1435	struct async_icount cprev;
1436	struct serial_icounter_struct icount;
1437
1438	mos7720_port = usb_get_serial_port_data(port);
1439	if (mos7720_port == NULL)
1440		return -ENODEV;
1441
1442	dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);
1443
1444	switch (cmd) {
1445	case TIOCINQ:
1446		/* return number of bytes available */
1447		dbg("%s (%d) TIOCINQ", __FUNCTION__,  port->number);
1448		return get_number_bytes_avail(mos7720_port,
1449					      (unsigned int __user *)arg);
1450		break;
1451
1452	case TIOCSERGETLSR:
1453		dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__,  port->number);
1454		return get_lsr_info(mos7720_port, (unsigned int __user *)arg);
1455		return 0;
1456
1457	case TIOCMBIS:
1458	case TIOCMBIC:
1459	case TIOCMSET:
1460		dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __FUNCTION__,
1461		    port->number);
1462		return set_modem_info(mos7720_port, cmd,
1463				      (unsigned int __user *)arg);
1464
1465	case TIOCMGET:
1466		dbg("%s (%d) TIOCMGET", __FUNCTION__,  port->number);
1467		return get_modem_info(mos7720_port,
1468				      (unsigned int __user *)arg);
1469
1470	case TIOCGSERIAL:
1471		dbg("%s (%d) TIOCGSERIAL", __FUNCTION__,  port->number);
1472		return get_serial_info(mos7720_port,
1473				       (struct serial_struct __user *)arg);
1474
1475	case TIOCSSERIAL:
1476		dbg("%s (%d) TIOCSSERIAL", __FUNCTION__,  port->number);
1477		break;
1478
1479	case TIOCMIWAIT:
1480		dbg("%s (%d) TIOCMIWAIT", __FUNCTION__,  port->number);
1481		cprev = mos7720_port->icount;
1482		while (1) {
1483			if (signal_pending(current))
1484				return -ERESTARTSYS;
1485			cnow = mos7720_port->icount;
1486			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
1487			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
1488				return -EIO; /* no change => error */
1489			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
1490			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
1491			    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
1492			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
1493				return 0;
1494			}
1495			cprev = cnow;
1496		}
1497		/* NOTREACHED */
1498		break;
1499
1500	case TIOCGICOUNT:
1501		cnow = mos7720_port->icount;
1502		icount.cts = cnow.cts;
1503		icount.dsr = cnow.dsr;
1504		icount.rng = cnow.rng;
1505		icount.dcd = cnow.dcd;
1506		icount.rx = cnow.rx;
1507		icount.tx = cnow.tx;
1508		icount.frame = cnow.frame;
1509		icount.overrun = cnow.overrun;
1510		icount.parity = cnow.parity;
1511		icount.brk = cnow.brk;
1512		icount.buf_overrun = cnow.buf_overrun;
1513
1514		dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__,
1515		    port->number, icount.rx, icount.tx );
1516		if (copy_to_user((void __user *)arg, &icount, sizeof(icount)))
1517			return -EFAULT;
1518		return 0;
1519	}
1520
1521	return -ENOIOCTLCMD;
1522}
1523
1524static int mos7720_startup(struct usb_serial *serial)
1525{
1526	struct moschip_serial *mos7720_serial;
1527	struct moschip_port *mos7720_port;
1528	struct usb_device *dev;
1529	int i;
1530	char data;
1531
1532	dbg("%s: Entering ..........", __FUNCTION__);
1533
1534	if (!serial) {
1535		dbg("Invalid Handler");
1536		return -ENODEV;
1537	}
1538
1539	dev = serial->dev;
1540
1541	/* create our private serial structure */
1542	mos7720_serial = kzalloc(sizeof(struct moschip_serial), GFP_KERNEL);
1543	if (mos7720_serial == NULL) {
1544		err("%s - Out of memory", __FUNCTION__);
1545		return -ENOMEM;
1546	}
1547
1548	usb_set_serial_data(serial, mos7720_serial);
1549
1550	/* we set up the pointers to the endpoints in the mos7720_open *
1551	 * function, as the structures aren't created yet.             */
1552
1553	/* set up port private structures */
1554	for (i = 0; i < serial->num_ports; ++i) {
1555		mos7720_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
1556		if (mos7720_port == NULL) {
1557			err("%s - Out of memory", __FUNCTION__);
1558			usb_set_serial_data(serial, NULL);
1559			kfree(mos7720_serial);
1560			return -ENOMEM;
1561		}
1562
1563		/* Initialize all port interrupt end point to port 0 int
1564		 * endpoint.  Our device has only one interrupt endpoint
1565		 * comman to all ports */
1566		serial->port[i]->interrupt_in_endpointAddress = serial->port[0]->interrupt_in_endpointAddress;
1567
1568		mos7720_port->port = serial->port[i];
1569		usb_set_serial_port_data(serial->port[i], mos7720_port);
1570
1571		dbg("port number is %d", serial->port[i]->number);
1572		dbg("serial number is %d", serial->minor);
1573	}
1574
1575
1576	/* setting configuration feature to one */
1577	usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
1578			(__u8)0x03, 0x00,0x01,0x00, NULL, 0x00, 5*HZ);
1579
1580	send_mos_cmd(serial,MOS_READ,0x00, UART_LSR, &data);  // LSR For Port 1
1581	dbg("LSR:%x",data);
1582
1583	send_mos_cmd(serial,MOS_READ,0x01, UART_LSR, &data);  // LSR For Port 2
1584	dbg("LSR:%x",data);
1585
1586	return 0;
1587}
1588
1589static void mos7720_shutdown(struct usb_serial *serial)
1590{
1591	int i;
1592
1593	/* free private structure allocated for serial port */
1594	for (i=0; i < serial->num_ports; ++i) {
1595		kfree(usb_get_serial_port_data(serial->port[i]));
1596		usb_set_serial_port_data(serial->port[i], NULL);
1597	}
1598
1599	/* free private structure allocated for serial device */
1600	kfree(usb_get_serial_data(serial));
1601	usb_set_serial_data(serial, NULL);
1602}
1603
1604static struct usb_driver usb_driver = {
1605	.name =		"moschip7720",
1606	.probe =	usb_serial_probe,
1607	.disconnect =	usb_serial_disconnect,
1608	.id_table =	moschip_port_id_table,
1609	.no_dynamic_id =	1,
1610};
1611
1612static struct usb_serial_driver moschip7720_2port_driver = {
1613	.driver = {
1614		.owner =	THIS_MODULE,
1615		.name =		"moschip7720",
1616	},
1617	.description		= "Moschip 2 port adapter",
1618	.usb_driver		= &usb_driver,
1619	.id_table		= moschip_port_id_table,
1620	.num_interrupt_in	= 1,
1621	.num_bulk_in		= 2,
1622	.num_bulk_out		= 2,
1623	.num_ports		= 2,
1624	.open			= mos7720_open,
1625	.close			= mos7720_close,
1626	.throttle		= mos7720_throttle,
1627	.unthrottle		= mos7720_unthrottle,
1628	.attach			= mos7720_startup,
1629	.shutdown		= mos7720_shutdown,
1630	.ioctl			= mos7720_ioctl,
1631	.set_termios		= mos7720_set_termios,
1632	.write			= mos7720_write,
1633	.write_room		= mos7720_write_room,
1634	.chars_in_buffer	= mos7720_chars_in_buffer,
1635	.break_ctl		= mos7720_break,
1636	.read_bulk_callback	= mos7720_bulk_in_callback,
1637	.read_int_callback	= mos7720_interrupt_callback,
1638};
1639
1640static int __init moschip7720_init(void)
1641{
1642	int retval;
1643
1644	dbg("%s: Entering ..........", __FUNCTION__);
1645
1646	/* Register with the usb serial */
1647	retval = usb_serial_register(&moschip7720_2port_driver);
1648	if (retval)
1649		goto failed_port_device_register;
1650
1651	info(DRIVER_DESC " " DRIVER_VERSION);
1652
1653	/* Register with the usb */
1654	retval = usb_register(&usb_driver);
1655	if (retval)
1656		goto failed_usb_register;
1657
1658	return 0;
1659
1660failed_usb_register:
1661	usb_serial_deregister(&moschip7720_2port_driver);
1662
1663failed_port_device_register:
1664	return retval;
1665}
1666
1667static void __exit moschip7720_exit(void)
1668{
1669	usb_deregister(&usb_driver);
1670	usb_serial_deregister(&moschip7720_2port_driver);
1671}
1672
1673module_init(moschip7720_init);
1674module_exit(moschip7720_exit);
1675
1676/* Module information */
1677MODULE_AUTHOR( DRIVER_AUTHOR );
1678MODULE_DESCRIPTION( DRIVER_DESC );
1679MODULE_LICENSE("GPL");
1680
1681module_param(debug, bool, S_IRUGO | S_IWUSR);
1682MODULE_PARM_DESC(debug, "Debug enabled or not");
1683