USB: serial: mct_u232: clean up urb->status usage
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / usb / serial / mos7720.c
CommitLineData
0f64478c
GKH
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;
325b70c2 106 __u8 *data;
0f64478c
GKH
107 __u8 sp1;
108 __u8 sp2;
0f64478c
GKH
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 */
325b70c2
ON
142
143 /* the above description is inverted
144 * oneukum 2007-03-14 */
145
146 if (unlikely(length != 4)) {
0f64478c
GKH
147 dbg("Wrong data !!!");
148 return;
149 }
150
325b70c2
ON
151 sp1 = data[3];
152 sp2 = data[2];
0f64478c 153
325b70c2 154 if ((sp1 | sp2) & 0x01) {
0f64478c
GKH
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
b963a844
JS
271 if (tty && mos7720_port->open)
272 tty_wakeup(tty);
0f64478c
GKH
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;
fe4b65ec 335 int allocated_urbs = 0;
0f64478c
GKH
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) {
c2cf3f6e 356 urb = usb_alloc_urb(0,GFP_KERNEL);
0f64478c
GKH
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__);
fe4b65ec
ON
368 usb_free_urb(mos7720_port->write_urb_pool[j]);
369 mos7720_port->write_urb_pool[j] = NULL;
0f64478c
GKH
370 continue;
371 }
fe4b65ec 372 allocated_urbs++;
0f64478c
GKH
373 }
374
fe4b65ec
ON
375 if (!allocated_urbs)
376 return -ENOMEM;
377
0f64478c
GKH
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) {
fe4b65ec 535 if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status == -EINPROGRESS)
0f64478c
GKH
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) {
fe4b65ec 638 if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status != -EINPROGRESS)
0f64478c
GKH
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) {
fe4b65ec 673 if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status != -EINPROGRESS) {
0f64478c
GKH
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,
606d099c 1013 struct ktermios *old_termios)
0f64478c
GKH
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,
606d099c 1202 struct ktermios *old_termios)
0f64478c
GKH
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
d9b1b787
JH
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
0f64478c
GKH
1612static struct usb_serial_driver moschip7720_2port_driver = {
1613 .driver = {
1614 .owner = THIS_MODULE,
1615 .name = "moschip7720",
1616 },
1617 .description = "Moschip 2 port adapter",
d9b1b787 1618 .usb_driver = &usb_driver,
0f64478c
GKH
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,
e8e30c76 1637 .read_int_callback = mos7720_interrupt_callback,
0f64478c
GKH
1638};
1639
0f64478c
GKH
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");