blob: a6678826452fa7f6e427c3689ea278718a3906b8 [file] [log] [blame]
Paul B Schroeder3f542972006-08-31 19:41:47 -05001/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 *
16 * Clean ups from Moschip version and a few ioctl implementations by:
17 * Paul B Schroeder <pschroeder "at" uplogix "dot" com>
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 */
24
25#include <linux/kernel.h>
26#include <linux/errno.h>
27#include <linux/init.h>
28#include <linux/slab.h>
29#include <linux/tty.h>
30#include <linux/tty_driver.h>
31#include <linux/tty_flip.h>
32#include <linux/module.h>
33#include <linux/serial.h>
34#include <linux/usb.h>
35#include <linux/usb/serial.h>
36#include <asm/uaccess.h>
37
38/*
39 * Version Information
40 */
41#define DRIVER_VERSION "1.3.1"
42#define DRIVER_DESC "Moschip 7840/7820 USB Serial Driver"
43
44/*
45 * 16C50 UART register defines
46 */
47
48#define LCR_BITS_5 0x00 /* 5 bits/char */
49#define LCR_BITS_6 0x01 /* 6 bits/char */
50#define LCR_BITS_7 0x02 /* 7 bits/char */
51#define LCR_BITS_8 0x03 /* 8 bits/char */
52#define LCR_BITS_MASK 0x03 /* Mask for bits/char field */
53
54#define LCR_STOP_1 0x00 /* 1 stop bit */
55#define LCR_STOP_1_5 0x04 /* 1.5 stop bits (if 5 bits/char) */
56#define LCR_STOP_2 0x04 /* 2 stop bits (if 6-8 bits/char) */
57#define LCR_STOP_MASK 0x04 /* Mask for stop bits field */
58
59#define LCR_PAR_NONE 0x00 /* No parity */
60#define LCR_PAR_ODD 0x08 /* Odd parity */
61#define LCR_PAR_EVEN 0x18 /* Even parity */
62#define LCR_PAR_MARK 0x28 /* Force parity bit to 1 */
63#define LCR_PAR_SPACE 0x38 /* Force parity bit to 0 */
64#define LCR_PAR_MASK 0x38 /* Mask for parity field */
65
66#define LCR_SET_BREAK 0x40 /* Set Break condition */
67#define LCR_DL_ENABLE 0x80 /* Enable access to divisor latch */
68
69#define MCR_DTR 0x01 /* Assert DTR */
70#define MCR_RTS 0x02 /* Assert RTS */
71#define MCR_OUT1 0x04 /* Loopback only: Sets state of RI */
72#define MCR_MASTER_IE 0x08 /* Enable interrupt outputs */
73#define MCR_LOOPBACK 0x10 /* Set internal (digital) loopback mode */
74#define MCR_XON_ANY 0x20 /* Enable any char to exit XOFF mode */
75
76#define MOS7840_MSR_CTS 0x10 /* Current state of CTS */
77#define MOS7840_MSR_DSR 0x20 /* Current state of DSR */
78#define MOS7840_MSR_RI 0x40 /* Current state of RI */
79#define MOS7840_MSR_CD 0x80 /* Current state of CD */
80
81/*
82 * Defines used for sending commands to port
83 */
84
85#define WAIT_FOR_EVER (HZ * 0 ) /* timeout urb is wait for ever */
86#define MOS_WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
87
88#define MOS_PORT1 0x0200
89#define MOS_PORT2 0x0300
90#define MOS_VENREG 0x0000
91#define MOS_MAX_PORT 0x02
92#define MOS_WRITE 0x0E
93#define MOS_READ 0x0D
94
95/* Requests */
96#define MCS_RD_RTYPE 0xC0
97#define MCS_WR_RTYPE 0x40
98#define MCS_RDREQ 0x0D
99#define MCS_WRREQ 0x0E
100#define MCS_CTRL_TIMEOUT 500
101#define VENDOR_READ_LENGTH (0x01)
102
103#define MAX_NAME_LEN 64
104
105#define ZLP_REG1 0x3A //Zero_Flag_Reg1 58
106#define ZLP_REG5 0x3E //Zero_Flag_Reg5 62
107
108/* For higher baud Rates use TIOCEXBAUD */
109#define TIOCEXBAUD 0x5462
110
111/* vendor id and device id defines */
112
113#define USB_VENDOR_ID_MOSCHIP 0x9710
114#define MOSCHIP_DEVICE_ID_7840 0x7840
115#define MOSCHIP_DEVICE_ID_7820 0x7820
116
117/* Interrupt Rotinue Defines */
118
119#define SERIAL_IIR_RLS 0x06
120#define SERIAL_IIR_MS 0x00
121
122/*
123 * Emulation of the bit mask on the LINE STATUS REGISTER.
124 */
125#define SERIAL_LSR_DR 0x0001
126#define SERIAL_LSR_OE 0x0002
127#define SERIAL_LSR_PE 0x0004
128#define SERIAL_LSR_FE 0x0008
129#define SERIAL_LSR_BI 0x0010
130
131#define MOS_MSR_DELTA_CTS 0x10
132#define MOS_MSR_DELTA_DSR 0x20
133#define MOS_MSR_DELTA_RI 0x40
134#define MOS_MSR_DELTA_CD 0x80
135
136// Serial Port register Address
137#define INTERRUPT_ENABLE_REGISTER ((__u16)(0x01))
138#define FIFO_CONTROL_REGISTER ((__u16)(0x02))
139#define LINE_CONTROL_REGISTER ((__u16)(0x03))
140#define MODEM_CONTROL_REGISTER ((__u16)(0x04))
141#define LINE_STATUS_REGISTER ((__u16)(0x05))
142#define MODEM_STATUS_REGISTER ((__u16)(0x06))
143#define SCRATCH_PAD_REGISTER ((__u16)(0x07))
144#define DIVISOR_LATCH_LSB ((__u16)(0x00))
145#define DIVISOR_LATCH_MSB ((__u16)(0x01))
146
147#define CLK_MULTI_REGISTER ((__u16)(0x02))
148#define CLK_START_VALUE_REGISTER ((__u16)(0x03))
149
150#define SERIAL_LCR_DLAB ((__u16)(0x0080))
151
152/*
153 * URB POOL related defines
154 */
155#define NUM_URBS 16 /* URB Count */
156#define URB_TRANSFER_BUFFER_SIZE 32 /* URB Size */
157
158
159static struct usb_device_id moschip_port_id_table[] = {
160 {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
161 {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
162 {} /* terminating entry */
163};
164
165static __devinitdata struct usb_device_id moschip_id_table_combined[] = {
166 {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
167 {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
168 {} /* terminating entry */
169};
170
171MODULE_DEVICE_TABLE(usb, moschip_id_table_combined);
172
173/* This structure holds all of the local port information */
174
175struct moschip_port {
176 int port_num; /*Actual port number in the device(1,2,etc) */
177 struct urb *write_urb; /* write URB for this port */
178 struct urb *read_urb; /* read URB for this port */
Oliver Neukum0de9a702007-03-16 20:28:28 +0100179 struct urb *int_urb;
Paul B Schroeder3f542972006-08-31 19:41:47 -0500180 __u8 shadowLCR; /* last LCR value received */
181 __u8 shadowMCR; /* last MCR value received */
182 char open;
Oliver Neukum0de9a702007-03-16 20:28:28 +0100183 char open_ports;
184 char zombie;
Paul B Schroeder3f542972006-08-31 19:41:47 -0500185 wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */
186 wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */
187 int delta_msr_cond;
188 struct async_icount icount;
189 struct usb_serial_port *port; /* loop back to the owner of this object */
190
191 /*Offsets */
192 __u8 SpRegOffset;
193 __u8 ControlRegOffset;
194 __u8 DcrRegOffset;
195 //for processing control URBS in interrupt context
196 struct urb *control_urb;
Oliver Neukum0de9a702007-03-16 20:28:28 +0100197 struct usb_ctrlrequest *dr;
Paul B Schroeder3f542972006-08-31 19:41:47 -0500198 char *ctrl_buf;
199 int MsrLsr;
200
Oliver Neukum0de9a702007-03-16 20:28:28 +0100201 spinlock_t pool_lock;
Paul B Schroeder3f542972006-08-31 19:41:47 -0500202 struct urb *write_urb_pool[NUM_URBS];
Oliver Neukum0de9a702007-03-16 20:28:28 +0100203 char busy[NUM_URBS];
Paul B Schroeder3f542972006-08-31 19:41:47 -0500204};
205
206
207static int debug;
Paul B Schroeder3f542972006-08-31 19:41:47 -0500208
209/*
210 * mos7840_set_reg_sync
211 * To set the Control register by calling usb_fill_control_urb function
212 * by passing usb_sndctrlpipe function as parameter.
213 */
214
215static int mos7840_set_reg_sync(struct usb_serial_port *port, __u16 reg,
216 __u16 val)
217{
218 struct usb_device *dev = port->serial->dev;
219 val = val & 0x00ff;
220 dbg("mos7840_set_reg_sync offset is %x, value %x\n", reg, val);
221
222 return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ,
223 MCS_WR_RTYPE, val, reg, NULL, 0,
224 MOS_WDR_TIMEOUT);
225}
226
227/*
228 * mos7840_get_reg_sync
229 * To set the Uart register by calling usb_fill_control_urb function by
230 * passing usb_rcvctrlpipe function as parameter.
231 */
232
233static int mos7840_get_reg_sync(struct usb_serial_port *port, __u16 reg,
234 __u16 * val)
235{
236 struct usb_device *dev = port->serial->dev;
237 int ret = 0;
238
239 ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ,
240 MCS_RD_RTYPE, 0, reg, val, VENDOR_READ_LENGTH,
241 MOS_WDR_TIMEOUT);
242 dbg("mos7840_get_reg_sync offset is %x, return val %x\n", reg, *val);
243 *val = (*val) & 0x00ff;
244 return ret;
245}
246
247/*
248 * mos7840_set_uart_reg
249 * To set the Uart register by calling usb_fill_control_urb function by
250 * passing usb_sndctrlpipe function as parameter.
251 */
252
253static int mos7840_set_uart_reg(struct usb_serial_port *port, __u16 reg,
254 __u16 val)
255{
256
257 struct usb_device *dev = port->serial->dev;
258 val = val & 0x00ff;
259 // For the UART control registers, the application number need to be Or'ed
Oliver Neukum0de9a702007-03-16 20:28:28 +0100260 if (port->serial->num_ports == 4) {
Paul B Schroeder3f542972006-08-31 19:41:47 -0500261 val |=
262 (((__u16) port->number - (__u16) (port->serial->minor)) +
263 1) << 8;
264 dbg("mos7840_set_uart_reg application number is %x\n", val);
265 } else {
266 if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) {
267 val |=
268 (((__u16) port->number -
269 (__u16) (port->serial->minor)) + 1) << 8;
270 dbg("mos7840_set_uart_reg application number is %x\n",
271 val);
272 } else {
273 val |=
274 (((__u16) port->number -
275 (__u16) (port->serial->minor)) + 2) << 8;
276 dbg("mos7840_set_uart_reg application number is %x\n",
277 val);
278 }
279 }
280 return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ,
281 MCS_WR_RTYPE, val, reg, NULL, 0,
282 MOS_WDR_TIMEOUT);
283
284}
285
286/*
287 * mos7840_get_uart_reg
288 * To set the Control register by calling usb_fill_control_urb function
289 * by passing usb_rcvctrlpipe function as parameter.
290 */
291static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg,
292 __u16 * val)
293{
294 struct usb_device *dev = port->serial->dev;
295 int ret = 0;
296 __u16 Wval;
297
298 //dbg("application number is %4x \n",(((__u16)port->number - (__u16)(port->serial->minor))+1)<<8);
299 /*Wval is same as application number */
Oliver Neukum0de9a702007-03-16 20:28:28 +0100300 if (port->serial->num_ports == 4) {
Paul B Schroeder3f542972006-08-31 19:41:47 -0500301 Wval =
302 (((__u16) port->number - (__u16) (port->serial->minor)) +
303 1) << 8;
304 dbg("mos7840_get_uart_reg application number is %x\n", Wval);
305 } else {
306 if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) {
307 Wval =
308 (((__u16) port->number -
309 (__u16) (port->serial->minor)) + 1) << 8;
310 dbg("mos7840_get_uart_reg application number is %x\n",
311 Wval);
312 } else {
313 Wval =
314 (((__u16) port->number -
315 (__u16) (port->serial->minor)) + 2) << 8;
316 dbg("mos7840_get_uart_reg application number is %x\n",
317 Wval);
318 }
319 }
320 ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ,
321 MCS_RD_RTYPE, Wval, reg, val, VENDOR_READ_LENGTH,
322 MOS_WDR_TIMEOUT);
323 *val = (*val) & 0x00ff;
324 return ret;
325}
326
327static void mos7840_dump_serial_port(struct moschip_port *mos7840_port)
328{
329
330 dbg("***************************************\n");
331 dbg("SpRegOffset is %2x\n", mos7840_port->SpRegOffset);
332 dbg("ControlRegOffset is %2x \n", mos7840_port->ControlRegOffset);
333 dbg("DCRRegOffset is %2x \n", mos7840_port->DcrRegOffset);
334 dbg("***************************************\n");
335
336}
337
338/************************************************************************/
339/************************************************************************/
340/* I N T E R F A C E F U N C T I O N S */
341/* I N T E R F A C E F U N C T I O N S */
342/************************************************************************/
343/************************************************************************/
344
345static inline void mos7840_set_port_private(struct usb_serial_port *port,
346 struct moschip_port *data)
347{
348 usb_set_serial_port_data(port, (void *)data);
349}
350
351static inline struct moschip_port *mos7840_get_port_private(struct
352 usb_serial_port
353 *port)
354{
355 return (struct moschip_port *)usb_get_serial_port_data(port);
356}
357
Oliver Neukum0de9a702007-03-16 20:28:28 +0100358static void mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr)
Paul B Schroeder3f542972006-08-31 19:41:47 -0500359{
360 struct moschip_port *mos7840_port;
361 struct async_icount *icount;
362 mos7840_port = port;
363 icount = &mos7840_port->icount;
364 if (new_msr &
365 (MOS_MSR_DELTA_CTS | MOS_MSR_DELTA_DSR | MOS_MSR_DELTA_RI |
366 MOS_MSR_DELTA_CD)) {
367 icount = &mos7840_port->icount;
368
369 /* update input line counters */
370 if (new_msr & MOS_MSR_DELTA_CTS) {
371 icount->cts++;
Oliver Neukum0de9a702007-03-16 20:28:28 +0100372 smp_wmb();
Paul B Schroeder3f542972006-08-31 19:41:47 -0500373 }
374 if (new_msr & MOS_MSR_DELTA_DSR) {
375 icount->dsr++;
Oliver Neukum0de9a702007-03-16 20:28:28 +0100376 smp_wmb();
Paul B Schroeder3f542972006-08-31 19:41:47 -0500377 }
378 if (new_msr & MOS_MSR_DELTA_CD) {
379 icount->dcd++;
Oliver Neukum0de9a702007-03-16 20:28:28 +0100380 smp_wmb();
Paul B Schroeder3f542972006-08-31 19:41:47 -0500381 }
382 if (new_msr & MOS_MSR_DELTA_RI) {
383 icount->rng++;
Oliver Neukum0de9a702007-03-16 20:28:28 +0100384 smp_wmb();
Paul B Schroeder3f542972006-08-31 19:41:47 -0500385 }
386 }
Paul B Schroeder3f542972006-08-31 19:41:47 -0500387}
388
Oliver Neukum0de9a702007-03-16 20:28:28 +0100389static void mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr)
Paul B Schroeder3f542972006-08-31 19:41:47 -0500390{
391 struct async_icount *icount;
392
393 dbg("%s - %02x", __FUNCTION__, new_lsr);
394
395 if (new_lsr & SERIAL_LSR_BI) {
396 //
397 // Parity and Framing errors only count if they
398 // occur exclusive of a break being
399 // received.
400 //
401 new_lsr &= (__u8) (SERIAL_LSR_OE | SERIAL_LSR_BI);
402 }
403
404 /* update input line counters */
405 icount = &port->icount;
406 if (new_lsr & SERIAL_LSR_BI) {
407 icount->brk++;
Oliver Neukum0de9a702007-03-16 20:28:28 +0100408 smp_wmb();
Paul B Schroeder3f542972006-08-31 19:41:47 -0500409 }
410 if (new_lsr & SERIAL_LSR_OE) {
411 icount->overrun++;
Oliver Neukum0de9a702007-03-16 20:28:28 +0100412 smp_wmb();
Paul B Schroeder3f542972006-08-31 19:41:47 -0500413 }
414 if (new_lsr & SERIAL_LSR_PE) {
415 icount->parity++;
Oliver Neukum0de9a702007-03-16 20:28:28 +0100416 smp_wmb();
Paul B Schroeder3f542972006-08-31 19:41:47 -0500417 }
418 if (new_lsr & SERIAL_LSR_FE) {
419 icount->frame++;
Oliver Neukum0de9a702007-03-16 20:28:28 +0100420 smp_wmb();
Paul B Schroeder3f542972006-08-31 19:41:47 -0500421 }
Paul B Schroeder3f542972006-08-31 19:41:47 -0500422}
423
424/************************************************************************/
425/************************************************************************/
426/* U S B C A L L B A C K F U N C T I O N S */
427/* U S B C A L L B A C K F U N C T I O N S */
428/************************************************************************/
429/************************************************************************/
430
David Howells7d12e782006-10-05 14:55:46 +0100431static void mos7840_control_callback(struct urb *urb)
Paul B Schroeder3f542972006-08-31 19:41:47 -0500432{
433 unsigned char *data;
434 struct moschip_port *mos7840_port;
435 __u8 regval = 0x0;
Oliver Neukum0de9a702007-03-16 20:28:28 +0100436 int result = 0;
Greg Kroah-Hartman0643c722007-06-15 15:44:13 -0700437 int status = urb->status;
Paul B Schroeder3f542972006-08-31 19:41:47 -0500438
439 if (!urb) {
440 dbg("%s", "Invalid Pointer !!!!:\n");
441 return;
442 }
443
Oliver Neukum0de9a702007-03-16 20:28:28 +0100444 mos7840_port = (struct moschip_port *)urb->context;
445
Greg Kroah-Hartman0643c722007-06-15 15:44:13 -0700446 switch (status) {
Paul B Schroeder3f542972006-08-31 19:41:47 -0500447 case 0:
448 /* success */
449 break;
450 case -ECONNRESET:
451 case -ENOENT:
452 case -ESHUTDOWN:
453 /* this urb is terminated, clean up */
454 dbg("%s - urb shutting down with status: %d", __FUNCTION__,
Greg Kroah-Hartman0643c722007-06-15 15:44:13 -0700455 status);
Paul B Schroeder3f542972006-08-31 19:41:47 -0500456 return;
457 default:
458 dbg("%s - nonzero urb status received: %d", __FUNCTION__,
Greg Kroah-Hartman0643c722007-06-15 15:44:13 -0700459 status);
Paul B Schroeder3f542972006-08-31 19:41:47 -0500460 goto exit;
461 }
462
Paul B Schroeder3f542972006-08-31 19:41:47 -0500463 dbg("%s urb buffer size is %d\n", __FUNCTION__, urb->actual_length);
464 dbg("%s mos7840_port->MsrLsr is %d port %d\n", __FUNCTION__,
465 mos7840_port->MsrLsr, mos7840_port->port_num);
466 data = urb->transfer_buffer;
467 regval = (__u8) data[0];
468 dbg("%s data is %x\n", __FUNCTION__, regval);
469 if (mos7840_port->MsrLsr == 0)
470 mos7840_handle_new_msr(mos7840_port, regval);
471 else if (mos7840_port->MsrLsr == 1)
472 mos7840_handle_new_lsr(mos7840_port, regval);
473
Oliver Neukum0de9a702007-03-16 20:28:28 +0100474exit:
475 spin_lock(&mos7840_port->pool_lock);
476 if (!mos7840_port->zombie)
477 result = usb_submit_urb(mos7840_port->int_urb, GFP_ATOMIC);
478 spin_unlock(&mos7840_port->pool_lock);
479 if (result) {
480 dev_err(&urb->dev->dev,
481 "%s - Error %d submitting interrupt urb\n",
482 __FUNCTION__, result);
483 }
Paul B Schroeder3f542972006-08-31 19:41:47 -0500484}
485
486static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
487 __u16 * val)
488{
489 struct usb_device *dev = mcs->port->serial->dev;
Oliver Neukum0de9a702007-03-16 20:28:28 +0100490 struct usb_ctrlrequest *dr = mcs->dr;
491 unsigned char *buffer = mcs->ctrl_buf;
492 int ret;
Paul B Schroeder3f542972006-08-31 19:41:47 -0500493
Paul B Schroeder3f542972006-08-31 19:41:47 -0500494 dr->bRequestType = MCS_RD_RTYPE;
495 dr->bRequest = MCS_RDREQ;
496 dr->wValue = cpu_to_le16(Wval); //0;
497 dr->wIndex = cpu_to_le16(reg);
498 dr->wLength = cpu_to_le16(2);
499
500 usb_fill_control_urb(mcs->control_urb, dev, usb_rcvctrlpipe(dev, 0),
501 (unsigned char *)dr, buffer, 2,
502 mos7840_control_callback, mcs);
503 mcs->control_urb->transfer_buffer_length = 2;
504 ret = usb_submit_urb(mcs->control_urb, GFP_ATOMIC);
505 return ret;
506}
507
508/*****************************************************************************
509 * mos7840_interrupt_callback
510 * this is the callback function for when we have received data on the
511 * interrupt endpoint.
512 *****************************************************************************/
513
David Howells7d12e782006-10-05 14:55:46 +0100514static void mos7840_interrupt_callback(struct urb *urb)
Paul B Schroeder3f542972006-08-31 19:41:47 -0500515{
516 int result;
517 int length;
518 struct moschip_port *mos7840_port;
519 struct usb_serial *serial;
520 __u16 Data;
521 unsigned char *data;
522 __u8 sp[5], st;
Oliver Neukum0de9a702007-03-16 20:28:28 +0100523 int i, rv = 0;
524 __u16 wval, wreg = 0;
Greg Kroah-Hartman0643c722007-06-15 15:44:13 -0700525 int status = urb->status;
Paul B Schroeder3f542972006-08-31 19:41:47 -0500526
527 dbg("%s", " : Entering\n");
528 if (!urb) {
529 dbg("%s", "Invalid Pointer !!!!:\n");
530 return;
531 }
532
Greg Kroah-Hartman0643c722007-06-15 15:44:13 -0700533 switch (status) {
Paul B Schroeder3f542972006-08-31 19:41:47 -0500534 case 0:
535 /* success */
536 break;
537 case -ECONNRESET:
538 case -ENOENT:
539 case -ESHUTDOWN:
540 /* this urb is terminated, clean up */
541 dbg("%s - urb shutting down with status: %d", __FUNCTION__,
Greg Kroah-Hartman0643c722007-06-15 15:44:13 -0700542 status);
Paul B Schroeder3f542972006-08-31 19:41:47 -0500543 return;
544 default:
545 dbg("%s - nonzero urb status received: %d", __FUNCTION__,
Greg Kroah-Hartman0643c722007-06-15 15:44:13 -0700546 status);
Paul B Schroeder3f542972006-08-31 19:41:47 -0500547 goto exit;
548 }
549
550 length = urb->actual_length;
551 data = urb->transfer_buffer;
552
553 serial = (struct usb_serial *)urb->context;
554
555 /* Moschip get 5 bytes
556 * Byte 1 IIR Port 1 (port.number is 0)
557 * Byte 2 IIR Port 2 (port.number is 1)
558 * Byte 3 IIR Port 3 (port.number is 2)
559 * Byte 4 IIR Port 4 (port.number is 3)
560 * Byte 5 FIFO status for both */
561
562 if (length && length > 5) {
563 dbg("%s \n", "Wrong data !!!");
564 return;
565 }
566
567 sp[0] = (__u8) data[0];
568 sp[1] = (__u8) data[1];
569 sp[2] = (__u8) data[2];
570 sp[3] = (__u8) data[3];
571 st = (__u8) data[4];
572
573 for (i = 0; i < serial->num_ports; i++) {
574 mos7840_port = mos7840_get_port_private(serial->port[i]);
575 wval =
576 (((__u16) serial->port[i]->number -
577 (__u16) (serial->minor)) + 1) << 8;
578 if (mos7840_port->open) {
579 if (sp[i] & 0x01) {
580 dbg("SP%d No Interrupt !!!\n", i);
581 } else {
582 switch (sp[i] & 0x0f) {
583 case SERIAL_IIR_RLS:
584 dbg("Serial Port %d: Receiver status error or ", i);
585 dbg("address bit detected in 9-bit mode\n");
586 mos7840_port->MsrLsr = 1;
Oliver Neukum0de9a702007-03-16 20:28:28 +0100587 wreg = LINE_STATUS_REGISTER;
Paul B Schroeder3f542972006-08-31 19:41:47 -0500588 break;
589 case SERIAL_IIR_MS:
590 dbg("Serial Port %d: Modem status change\n", i);
591 mos7840_port->MsrLsr = 0;
Oliver Neukum0de9a702007-03-16 20:28:28 +0100592 wreg = MODEM_STATUS_REGISTER;
Paul B Schroeder3f542972006-08-31 19:41:47 -0500593 break;
594 }
Oliver Neukum0de9a702007-03-16 20:28:28 +0100595 spin_lock(&mos7840_port->pool_lock);
596 if (!mos7840_port->zombie) {
597 rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data);
598 } else {
599 spin_unlock(&mos7840_port->pool_lock);
600 return;
601 }
602 spin_unlock(&mos7840_port->pool_lock);
Paul B Schroeder3f542972006-08-31 19:41:47 -0500603 }
604 }
605 }
Oliver Neukum0de9a702007-03-16 20:28:28 +0100606 if (!(rv < 0)) /* the completion handler for the control urb will resubmit */
607 return;
608exit:
Paul B Schroeder3f542972006-08-31 19:41:47 -0500609 result = usb_submit_urb(urb, GFP_ATOMIC);
610 if (result) {
611 dev_err(&urb->dev->dev,
612 "%s - Error %d submitting interrupt urb\n",
613 __FUNCTION__, result);
614 }
Paul B Schroeder3f542972006-08-31 19:41:47 -0500615}
616
617static int mos7840_port_paranoia_check(struct usb_serial_port *port,
618 const char *function)
619{
620 if (!port) {
621 dbg("%s - port == NULL", function);
622 return -1;
623 }
624 if (!port->serial) {
625 dbg("%s - port->serial == NULL", function);
626 return -1;
627 }
628
629 return 0;
630}
631
632/* Inline functions to check the sanity of a pointer that is passed to us */
633static int mos7840_serial_paranoia_check(struct usb_serial *serial,
634 const char *function)
635{
636 if (!serial) {
637 dbg("%s - serial == NULL", function);
638 return -1;
639 }
640 if (!serial->type) {
641 dbg("%s - serial->type == NULL!", function);
642 return -1;
643 }
644
645 return 0;
646}
647
648static struct usb_serial *mos7840_get_usb_serial(struct usb_serial_port *port,
649 const char *function)
650{
651 /* if no port was specified, or it fails a paranoia check */
652 if (!port ||
653 mos7840_port_paranoia_check(port, function) ||
654 mos7840_serial_paranoia_check(port->serial, function)) {
Oliver Neukum0de9a702007-03-16 20:28:28 +0100655 /* then say that we don't have a valid usb_serial thing, which will
656 * end up genrating -ENODEV return values */
Paul B Schroeder3f542972006-08-31 19:41:47 -0500657 return NULL;
658 }
659
660 return port->serial;
661}
662
663/*****************************************************************************
664 * mos7840_bulk_in_callback
665 * this is the callback function for when we have received data on the
666 * bulk in endpoint.
667 *****************************************************************************/
668
David Howells7d12e782006-10-05 14:55:46 +0100669static void mos7840_bulk_in_callback(struct urb *urb)
Paul B Schroeder3f542972006-08-31 19:41:47 -0500670{
Greg Kroah-Hartman0643c722007-06-15 15:44:13 -0700671 int retval;
Paul B Schroeder3f542972006-08-31 19:41:47 -0500672 unsigned char *data;
673 struct usb_serial *serial;
674 struct usb_serial_port *port;
675 struct moschip_port *mos7840_port;
676 struct tty_struct *tty;
Greg Kroah-Hartman0643c722007-06-15 15:44:13 -0700677 int status = urb->status;
Paul B Schroeder3f542972006-08-31 19:41:47 -0500678
679 if (!urb) {
680 dbg("%s", "Invalid Pointer !!!!:\n");
681 return;
682 }
683
Greg Kroah-Hartman0643c722007-06-15 15:44:13 -0700684 if (status) {
685 dbg("nonzero read bulk status received: %d", status);
Paul B Schroeder3f542972006-08-31 19:41:47 -0500686 return;
687 }
688
689 mos7840_port = (struct moschip_port *)urb->context;
690 if (!mos7840_port) {
691 dbg("%s", "NULL mos7840_port pointer \n");
692 return;
693 }
694
695 port = (struct usb_serial_port *)mos7840_port->port;
696 if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
697 dbg("%s", "Port Paranoia failed \n");
698 return;
699 }
700
701 serial = mos7840_get_usb_serial(port, __FUNCTION__);
702 if (!serial) {
703 dbg("%s\n", "Bad serial pointer ");
704 return;
705 }
706
707 dbg("%s\n", "Entering... \n");
708
709 data = urb->transfer_buffer;
710
711 dbg("%s", "Entering ........... \n");
712
713 if (urb->actual_length) {
714 tty = mos7840_port->port->tty;
715 if (tty) {
716 tty_buffer_request_room(tty, urb->actual_length);
717 tty_insert_flip_string(tty, data, urb->actual_length);
718 dbg(" %s \n", data);
719 tty_flip_buffer_push(tty);
720 }
721 mos7840_port->icount.rx += urb->actual_length;
Oliver Neukum0de9a702007-03-16 20:28:28 +0100722 smp_wmb();
Paul B Schroeder3f542972006-08-31 19:41:47 -0500723 dbg("mos7840_port->icount.rx is %d:\n",
724 mos7840_port->icount.rx);
725 }
726
727 if (!mos7840_port->read_urb) {
728 dbg("%s", "URB KILLED !!!\n");
729 return;
730 }
731
Paul B Schroeder3f542972006-08-31 19:41:47 -0500732
Oliver Neukum0de9a702007-03-16 20:28:28 +0100733 mos7840_port->read_urb->dev = serial->dev;
Paul B Schroeder3f542972006-08-31 19:41:47 -0500734
Greg Kroah-Hartman0643c722007-06-15 15:44:13 -0700735 retval = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
Oliver Neukum0de9a702007-03-16 20:28:28 +0100736
Greg Kroah-Hartman0643c722007-06-15 15:44:13 -0700737 if (retval) {
738 dbg(" usb_submit_urb(read bulk) failed, retval = %d",
739 retval);
Paul B Schroeder3f542972006-08-31 19:41:47 -0500740 }
741}
742
743/*****************************************************************************
744 * mos7840_bulk_out_data_callback
745 * this is the callback function for when we have finished sending serial data
746 * on the bulk out endpoint.
747 *****************************************************************************/
748
David Howells7d12e782006-10-05 14:55:46 +0100749static void mos7840_bulk_out_data_callback(struct urb *urb)
Paul B Schroeder3f542972006-08-31 19:41:47 -0500750{
751 struct moschip_port *mos7840_port;
752 struct tty_struct *tty;
Greg Kroah-Hartman0643c722007-06-15 15:44:13 -0700753 int status = urb->status;
Oliver Neukum0de9a702007-03-16 20:28:28 +0100754 int i;
755
Paul B Schroeder3f542972006-08-31 19:41:47 -0500756 if (!urb) {
757 dbg("%s", "Invalid Pointer !!!!:\n");
758 return;
759 }
760
Oliver Neukum0de9a702007-03-16 20:28:28 +0100761 mos7840_port = (struct moschip_port *)urb->context;
762 spin_lock(&mos7840_port->pool_lock);
763 for (i = 0; i < NUM_URBS; i++) {
764 if (urb == mos7840_port->write_urb_pool[i]) {
765 mos7840_port->busy[i] = 0;
766 break;
767 }
768 }
769 spin_unlock(&mos7840_port->pool_lock);
770
Greg Kroah-Hartman0643c722007-06-15 15:44:13 -0700771 if (status) {
772 dbg("nonzero write bulk status received:%d\n", status);
Paul B Schroeder3f542972006-08-31 19:41:47 -0500773 return;
774 }
775
Paul B Schroeder3f542972006-08-31 19:41:47 -0500776 if (mos7840_port_paranoia_check(mos7840_port->port, __FUNCTION__)) {
777 dbg("%s", "Port Paranoia failed \n");
778 return;
779 }
780
781 dbg("%s \n", "Entering .........");
782
783 tty = mos7840_port->port->tty;
784
Jiri Slabyb963a842007-02-10 01:44:55 -0800785 if (tty && mos7840_port->open)
786 tty_wakeup(tty);
Paul B Schroeder3f542972006-08-31 19:41:47 -0500787
788}
789
790/************************************************************************/
791/* D R I V E R T T Y I N T E R F A C E F U N C T I O N S */
792/************************************************************************/
793#ifdef MCSSerialProbe
794static int mos7840_serial_probe(struct usb_serial *serial,
795 const struct usb_device_id *id)
796{
797
798 /*need to implement the mode_reg reading and updating\
799 structures usb_serial_ device_type\
800 (i.e num_ports, num_bulkin,bulkout etc) */
801 /* Also we can update the changes attach */
802 return 1;
803}
804#endif
805
806/*****************************************************************************
807 * mos7840_open
808 * this function is called by the tty driver when a port is opened
809 * If successful, we return 0
810 * Otherwise we return a negative error number.
811 *****************************************************************************/
812
813static int mos7840_open(struct usb_serial_port *port, struct file *filp)
814{
815 int response;
816 int j;
817 struct usb_serial *serial;
818 struct urb *urb;
819 __u16 Data;
820 int status;
821 struct moschip_port *mos7840_port;
Oliver Neukum0de9a702007-03-16 20:28:28 +0100822 struct moschip_port *port0;
Paul B Schroeder3f542972006-08-31 19:41:47 -0500823
824 if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
825 dbg("%s", "Port Paranoia failed \n");
826 return -ENODEV;
827 }
828
Paul B Schroeder3f542972006-08-31 19:41:47 -0500829 serial = port->serial;
830
831 if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) {
832 dbg("%s", "Serial Paranoia failed \n");
833 return -ENODEV;
834 }
835
836 mos7840_port = mos7840_get_port_private(port);
Oliver Neukum0de9a702007-03-16 20:28:28 +0100837 port0 = mos7840_get_port_private(serial->port[0]);
Paul B Schroeder3f542972006-08-31 19:41:47 -0500838
Oliver Neukum0de9a702007-03-16 20:28:28 +0100839 if (mos7840_port == NULL || port0 == NULL)
Paul B Schroeder3f542972006-08-31 19:41:47 -0500840 return -ENODEV;
841
842 usb_clear_halt(serial->dev, port->write_urb->pipe);
843 usb_clear_halt(serial->dev, port->read_urb->pipe);
Oliver Neukum0de9a702007-03-16 20:28:28 +0100844 port0->open_ports++;
Paul B Schroeder3f542972006-08-31 19:41:47 -0500845
846 /* Initialising the write urb pool */
847 for (j = 0; j < NUM_URBS; ++j) {
Oliver Neukum0de9a702007-03-16 20:28:28 +0100848 urb = usb_alloc_urb(0, GFP_KERNEL);
Paul B Schroeder3f542972006-08-31 19:41:47 -0500849 mos7840_port->write_urb_pool[j] = urb;
850
851 if (urb == NULL) {
852 err("No more urbs???");
853 continue;
854 }
855
Oliver Neukum0de9a702007-03-16 20:28:28 +0100856 urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
Paul B Schroeder3f542972006-08-31 19:41:47 -0500857 if (!urb->transfer_buffer) {
Oliver Neukum0de9a702007-03-16 20:28:28 +0100858 usb_free_urb(urb);
859 mos7840_port->write_urb_pool[j] = NULL;
Paul B Schroeder3f542972006-08-31 19:41:47 -0500860 err("%s-out of memory for urb buffers.", __FUNCTION__);
861 continue;
862 }
863 }
864
865/*****************************************************************************
866 * Initialize MCS7840 -- Write Init values to corresponding Registers
867 *
868 * Register Index
869 * 1 : IER
870 * 2 : FCR
871 * 3 : LCR
872 * 4 : MCR
873 *
874 * 0x08 : SP1/2 Control Reg
875 *****************************************************************************/
876
877//NEED to check the following Block
878
879 status = 0;
880 Data = 0x0;
881 status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data);
882 if (status < 0) {
883 dbg("Reading Spreg failed\n");
884 return -1;
885 }
886 Data |= 0x80;
887 status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
888 if (status < 0) {
889 dbg("writing Spreg failed\n");
890 return -1;
891 }
892
893 Data &= ~0x80;
894 status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
895 if (status < 0) {
896 dbg("writing Spreg failed\n");
897 return -1;
898 }
899//End of block to be checked
900
901 status = 0;
902 Data = 0x0;
903 status =
904 mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data);
905 if (status < 0) {
906 dbg("Reading Controlreg failed\n");
907 return -1;
908 }
909 Data |= 0x08; //Driver done bit
910 Data |= 0x20; //rx_disable
Oliver Neukum0de9a702007-03-16 20:28:28 +0100911 status = mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data);
Paul B Schroeder3f542972006-08-31 19:41:47 -0500912 if (status < 0) {
913 dbg("writing Controlreg failed\n");
914 return -1;
915 }
916 //do register settings here
917 // Set all regs to the device default values.
918 ////////////////////////////////////
919 // First Disable all interrupts.
920 ////////////////////////////////////
921
922 Data = 0x00;
Paul B Schroeder3f542972006-08-31 19:41:47 -0500923 status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
924 if (status < 0) {
925 dbg("disableing interrupts failed\n");
926 return -1;
927 }
928 // Set FIFO_CONTROL_REGISTER to the default value
929 Data = 0x00;
Paul B Schroeder3f542972006-08-31 19:41:47 -0500930 status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
931 if (status < 0) {
932 dbg("Writing FIFO_CONTROL_REGISTER failed\n");
933 return -1;
934 }
935
936 Data = 0xcf;
Paul B Schroeder3f542972006-08-31 19:41:47 -0500937 status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
938 if (status < 0) {
939 dbg("Writing FIFO_CONTROL_REGISTER failed\n");
940 return -1;
941 }
942
943 Data = 0x03;
Paul B Schroeder3f542972006-08-31 19:41:47 -0500944 status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
945 mos7840_port->shadowLCR = Data;
946
947 Data = 0x0b;
Paul B Schroeder3f542972006-08-31 19:41:47 -0500948 status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
949 mos7840_port->shadowMCR = Data;
950
951 Data = 0x00;
Paul B Schroeder3f542972006-08-31 19:41:47 -0500952 status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data);
953 mos7840_port->shadowLCR = Data;
954
955 Data |= SERIAL_LCR_DLAB; //data latch enable in LCR 0x80
Paul B Schroeder3f542972006-08-31 19:41:47 -0500956 status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
957
958 Data = 0x0c;
959 status = 0;
960 status = mos7840_set_uart_reg(port, DIVISOR_LATCH_LSB, Data);
961
962 Data = 0x0;
963 status = 0;
964 status = mos7840_set_uart_reg(port, DIVISOR_LATCH_MSB, Data);
965
966 Data = 0x00;
967 status = 0;
968 status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data);
969
970 Data = Data & ~SERIAL_LCR_DLAB;
971 status = 0;
972 status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
973 mos7840_port->shadowLCR = Data;
974
975 //clearing Bulkin and Bulkout Fifo
976 Data = 0x0;
977 status = 0;
978 status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data);
979
980 Data = Data | 0x0c;
981 status = 0;
982 status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
983
984 Data = Data & ~0x0c;
985 status = 0;
986 status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
987 //Finally enable all interrupts
988 Data = 0x0;
989 Data = 0x0c;
990 status = 0;
991 status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
992
993 //clearing rx_disable
994 Data = 0x0;
995 status = 0;
996 status =
997 mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data);
998 Data = Data & ~0x20;
999 status = 0;
1000 status =
1001 mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data);
1002
1003 // rx_negate
1004 Data = 0x0;
1005 status = 0;
1006 status =
1007 mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data);
1008 Data = Data | 0x10;
1009 status = 0;
1010 status =
1011 mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data);
1012
1013 /* force low_latency on so that our tty_push actually forces *
1014 * the data through,otherwise it is scheduled, and with *
1015 * high data rates (like with OHCI) data can get lost. */
1016
1017 if (port->tty)
1018 port->tty->low_latency = 1;
1019/* Check to see if we've set up our endpoint info yet *
1020 * (can't set it up in mos7840_startup as the structures *
1021 * were not set up at that time.) */
Oliver Neukum0de9a702007-03-16 20:28:28 +01001022 if (port0->open_ports == 1) {
Paul B Schroeder3f542972006-08-31 19:41:47 -05001023 if (serial->port[0]->interrupt_in_buffer == NULL) {
1024
1025 /* set up interrupt urb */
1026
1027 usb_fill_int_urb(serial->port[0]->interrupt_in_urb,
1028 serial->dev,
1029 usb_rcvintpipe(serial->dev,
1030 serial->port[0]->
1031 interrupt_in_endpointAddress),
1032 serial->port[0]->interrupt_in_buffer,
1033 serial->port[0]->interrupt_in_urb->
1034 transfer_buffer_length,
1035 mos7840_interrupt_callback,
1036 serial,
1037 serial->port[0]->interrupt_in_urb->
1038 interval);
1039
1040 /* start interrupt read for mos7840 *
1041 * will continue as long as mos7840 is connected */
1042
1043 response =
1044 usb_submit_urb(serial->port[0]->interrupt_in_urb,
1045 GFP_KERNEL);
1046 if (response) {
1047 err("%s - Error %d submitting interrupt urb",
1048 __FUNCTION__, response);
1049 }
1050
1051 }
1052
1053 }
1054
1055 /* see if we've set up our endpoint info yet *
1056 * (can't set it up in mos7840_startup as the *
1057 * structures were not set up at that time.) */
1058
1059 dbg("port number is %d \n", port->number);
1060 dbg("serial number is %d \n", port->serial->minor);
1061 dbg("Bulkin endpoint is %d \n", port->bulk_in_endpointAddress);
1062 dbg("BulkOut endpoint is %d \n", port->bulk_out_endpointAddress);
1063 dbg("Interrupt endpoint is %d \n", port->interrupt_in_endpointAddress);
1064 dbg("port's number in the device is %d\n", mos7840_port->port_num);
1065 mos7840_port->read_urb = port->read_urb;
1066
1067 /* set up our bulk in urb */
1068
1069 usb_fill_bulk_urb(mos7840_port->read_urb,
1070 serial->dev,
1071 usb_rcvbulkpipe(serial->dev,
1072 port->bulk_in_endpointAddress),
1073 port->bulk_in_buffer,
1074 mos7840_port->read_urb->transfer_buffer_length,
1075 mos7840_bulk_in_callback, mos7840_port);
1076
1077 dbg("mos7840_open: bulkin endpoint is %d\n",
1078 port->bulk_in_endpointAddress);
1079 response = usb_submit_urb(mos7840_port->read_urb, GFP_KERNEL);
1080 if (response) {
1081 err("%s - Error %d submitting control urb", __FUNCTION__,
1082 response);
1083 }
1084
1085 /* initialize our wait queues */
1086 init_waitqueue_head(&mos7840_port->wait_chase);
1087 init_waitqueue_head(&mos7840_port->delta_msr_wait);
1088
1089 /* initialize our icount structure */
1090 memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount));
1091
1092 /* initialize our port settings */
1093 mos7840_port->shadowMCR = MCR_MASTER_IE; /* Must set to enable ints! */
1094 /* send a open port command */
1095 mos7840_port->open = 1;
1096 //mos7840_change_port_settings(mos7840_port,old_termios);
1097 mos7840_port->icount.tx = 0;
1098 mos7840_port->icount.rx = 0;
1099
Al Viro97c49652006-10-09 20:29:03 +01001100 dbg("\n\nusb_serial serial:%p mos7840_port:%p\n usb_serial_port port:%p\n\n", serial, mos7840_port, port);
Paul B Schroeder3f542972006-08-31 19:41:47 -05001101
1102 return 0;
1103
1104}
1105
1106/*****************************************************************************
1107 * mos7840_chars_in_buffer
1108 * this function is called by the tty driver when it wants to know how many
1109 * bytes of data we currently have outstanding in the port (data that has
1110 * been written, but hasn't made it out the port yet)
1111 * If successful, we return the number of bytes left to be written in the
1112 * system,
1113 * Otherwise we return a negative error number.
1114 *****************************************************************************/
1115
1116static int mos7840_chars_in_buffer(struct usb_serial_port *port)
1117{
1118 int i;
1119 int chars = 0;
Oliver Neukum0de9a702007-03-16 20:28:28 +01001120 unsigned long flags;
Paul B Schroeder3f542972006-08-31 19:41:47 -05001121 struct moschip_port *mos7840_port;
1122
1123 dbg("%s \n", " mos7840_chars_in_buffer:entering ...........");
1124
1125 if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
1126 dbg("%s", "Invalid port \n");
1127 return -1;
1128 }
1129
1130 mos7840_port = mos7840_get_port_private(port);
1131 if (mos7840_port == NULL) {
1132 dbg("%s \n", "mos7840_break:leaving ...........");
1133 return -1;
1134 }
1135
Oliver Neukum0de9a702007-03-16 20:28:28 +01001136 spin_lock_irqsave(&mos7840_port->pool_lock,flags);
Paul B Schroeder3f542972006-08-31 19:41:47 -05001137 for (i = 0; i < NUM_URBS; ++i) {
Oliver Neukum0de9a702007-03-16 20:28:28 +01001138 if (mos7840_port->busy[i]) {
Paul B Schroeder3f542972006-08-31 19:41:47 -05001139 chars += URB_TRANSFER_BUFFER_SIZE;
1140 }
1141 }
Oliver Neukum0de9a702007-03-16 20:28:28 +01001142 spin_unlock_irqrestore(&mos7840_port->pool_lock,flags);
Paul B Schroeder3f542972006-08-31 19:41:47 -05001143 dbg("%s - returns %d", __FUNCTION__, chars);
Oliver Neukum0de9a702007-03-16 20:28:28 +01001144 return chars;
Paul B Schroeder3f542972006-08-31 19:41:47 -05001145
1146}
1147
1148/************************************************************************
1149 *
1150 * mos7840_block_until_tx_empty
1151 *
1152 * This function will block the close until one of the following:
1153 * 1. TX count are 0
1154 * 2. The mos7840 has stopped
1155 * 3. A timout of 3 seconds without activity has expired
1156 *
1157 ************************************************************************/
1158static void mos7840_block_until_tx_empty(struct moschip_port *mos7840_port)
1159{
1160 int timeout = HZ / 10;
1161 int wait = 30;
1162 int count;
1163
1164 while (1) {
1165
1166 count = mos7840_chars_in_buffer(mos7840_port->port);
1167
1168 /* Check for Buffer status */
1169 if (count <= 0) {
1170 return;
1171 }
1172
1173 /* Block the thread for a while */
1174 interruptible_sleep_on_timeout(&mos7840_port->wait_chase,
1175 timeout);
1176
1177 /* No activity.. count down section */
1178 wait--;
1179 if (wait == 0) {
1180 dbg("%s - TIMEOUT", __FUNCTION__);
1181 return;
1182 } else {
1183 /* Reset timout value back to seconds */
1184 wait = 30;
1185 }
1186 }
1187}
1188
1189/*****************************************************************************
1190 * mos7840_close
1191 * this function is called by the tty driver when a port is closed
1192 *****************************************************************************/
1193
1194static void mos7840_close(struct usb_serial_port *port, struct file *filp)
1195{
1196 struct usb_serial *serial;
1197 struct moschip_port *mos7840_port;
Oliver Neukum0de9a702007-03-16 20:28:28 +01001198 struct moschip_port *port0;
Paul B Schroeder3f542972006-08-31 19:41:47 -05001199 int j;
1200 __u16 Data;
1201
1202 dbg("%s\n", "mos7840_close:entering...");
1203
1204 if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
1205 dbg("%s", "Port Paranoia failed \n");
1206 return;
1207 }
1208
1209 serial = mos7840_get_usb_serial(port, __FUNCTION__);
1210 if (!serial) {
1211 dbg("%s", "Serial Paranoia failed \n");
1212 return;
1213 }
1214
1215 mos7840_port = mos7840_get_port_private(port);
Oliver Neukum0de9a702007-03-16 20:28:28 +01001216 port0 = mos7840_get_port_private(serial->port[0]);
Paul B Schroeder3f542972006-08-31 19:41:47 -05001217
Oliver Neukum0de9a702007-03-16 20:28:28 +01001218 if (mos7840_port == NULL || port0 == NULL)
Paul B Schroeder3f542972006-08-31 19:41:47 -05001219 return;
Paul B Schroeder3f542972006-08-31 19:41:47 -05001220
1221 for (j = 0; j < NUM_URBS; ++j)
1222 usb_kill_urb(mos7840_port->write_urb_pool[j]);
1223
1224 /* Freeing Write URBs */
1225 for (j = 0; j < NUM_URBS; ++j) {
1226 if (mos7840_port->write_urb_pool[j]) {
1227 if (mos7840_port->write_urb_pool[j]->transfer_buffer)
1228 kfree(mos7840_port->write_urb_pool[j]->
1229 transfer_buffer);
1230
1231 usb_free_urb(mos7840_port->write_urb_pool[j]);
1232 }
1233 }
1234
1235 if (serial->dev) {
1236 /* flush and block until tx is empty */
1237 mos7840_block_until_tx_empty(mos7840_port);
1238 }
1239
1240 /* While closing port, shutdown all bulk read, write *
1241 * and interrupt read if they exists */
1242 if (serial->dev) {
1243
1244 if (mos7840_port->write_urb) {
1245 dbg("%s", "Shutdown bulk write\n");
1246 usb_kill_urb(mos7840_port->write_urb);
1247 }
1248
1249 if (mos7840_port->read_urb) {
1250 dbg("%s", "Shutdown bulk read\n");
1251 usb_kill_urb(mos7840_port->read_urb);
1252 }
1253 if ((&mos7840_port->control_urb)) {
1254 dbg("%s", "Shutdown control read\n");
1255 // usb_kill_urb (mos7840_port->control_urb);
1256
1257 }
1258 }
1259// if(mos7840_port->ctrl_buf != NULL)
1260// kfree(mos7840_port->ctrl_buf);
Oliver Neukum0de9a702007-03-16 20:28:28 +01001261 port0->open_ports--;
Paul B Schroeder3f542972006-08-31 19:41:47 -05001262 dbg("mos7840_num_open_ports in close%d:in port%d\n",
Oliver Neukum0de9a702007-03-16 20:28:28 +01001263 port0->open_ports, port->number);
1264 if (port0->open_ports == 0) {
Paul B Schroeder3f542972006-08-31 19:41:47 -05001265 if (serial->port[0]->interrupt_in_urb) {
1266 dbg("%s", "Shutdown interrupt_in_urb\n");
Oliver Neukum0de9a702007-03-16 20:28:28 +01001267 usb_kill_urb(serial->port[0]->interrupt_in_urb);
Paul B Schroeder3f542972006-08-31 19:41:47 -05001268 }
1269 }
1270
1271 if (mos7840_port->write_urb) {
1272 /* if this urb had a transfer buffer already (old tx) free it */
1273
1274 if (mos7840_port->write_urb->transfer_buffer != NULL) {
1275 kfree(mos7840_port->write_urb->transfer_buffer);
1276 }
1277 usb_free_urb(mos7840_port->write_urb);
1278 }
1279
1280 Data = 0x0;
1281 mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
1282
1283 Data = 0x00;
1284 mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
1285
1286 mos7840_port->open = 0;
1287
1288 dbg("%s \n", "Leaving ............");
1289}
1290
1291/************************************************************************
1292 *
1293 * mos7840_block_until_chase_response
1294 *
1295 * This function will block the close until one of the following:
1296 * 1. Response to our Chase comes from mos7840
1297 * 2. A timout of 10 seconds without activity has expired
1298 * (1K of mos7840 data @ 2400 baud ==> 4 sec to empty)
1299 *
1300 ************************************************************************/
1301
1302static void mos7840_block_until_chase_response(struct moschip_port
1303 *mos7840_port)
1304{
1305 int timeout = 1 * HZ;
1306 int wait = 10;
1307 int count;
1308
1309 while (1) {
1310 count = mos7840_chars_in_buffer(mos7840_port->port);
1311
1312 /* Check for Buffer status */
1313 if (count <= 0) {
1314 return;
1315 }
1316
1317 /* Block the thread for a while */
1318 interruptible_sleep_on_timeout(&mos7840_port->wait_chase,
1319 timeout);
1320 /* No activity.. count down section */
1321 wait--;
1322 if (wait == 0) {
1323 dbg("%s - TIMEOUT", __FUNCTION__);
1324 return;
1325 } else {
1326 /* Reset timout value back to seconds */
1327 wait = 10;
1328 }
1329 }
1330
1331}
1332
1333/*****************************************************************************
1334 * mos7840_break
1335 * this function sends a break to the port
1336 *****************************************************************************/
1337static void mos7840_break(struct usb_serial_port *port, int break_state)
1338{
1339 unsigned char data;
1340 struct usb_serial *serial;
1341 struct moschip_port *mos7840_port;
1342
1343 dbg("%s \n", "Entering ...........");
1344 dbg("mos7840_break: Start\n");
1345
1346 if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
1347 dbg("%s", "Port Paranoia failed \n");
1348 return;
1349 }
1350
1351 serial = mos7840_get_usb_serial(port, __FUNCTION__);
1352 if (!serial) {
1353 dbg("%s", "Serial Paranoia failed \n");
1354 return;
1355 }
1356
1357 mos7840_port = mos7840_get_port_private(port);
1358
1359 if (mos7840_port == NULL) {
1360 return;
1361 }
1362
1363 if (serial->dev) {
1364
1365 /* flush and block until tx is empty */
1366 mos7840_block_until_chase_response(mos7840_port);
1367 }
1368
1369 if (break_state == -1) {
1370 data = mos7840_port->shadowLCR | LCR_SET_BREAK;
1371 } else {
1372 data = mos7840_port->shadowLCR & ~LCR_SET_BREAK;
1373 }
1374
1375 mos7840_port->shadowLCR = data;
1376 dbg("mcs7840_break mos7840_port->shadowLCR is %x\n",
1377 mos7840_port->shadowLCR);
1378 mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER,
1379 mos7840_port->shadowLCR);
1380
1381 return;
1382}
1383
1384/*****************************************************************************
1385 * mos7840_write_room
1386 * this function is called by the tty driver when it wants to know how many
1387 * bytes of data we can accept for a specific port.
1388 * If successful, we return the amount of room that we have for this port
1389 * Otherwise we return a negative error number.
1390 *****************************************************************************/
1391
1392static int mos7840_write_room(struct usb_serial_port *port)
1393{
1394 int i;
1395 int room = 0;
Oliver Neukum0de9a702007-03-16 20:28:28 +01001396 unsigned long flags;
Paul B Schroeder3f542972006-08-31 19:41:47 -05001397 struct moschip_port *mos7840_port;
1398
1399 dbg("%s \n", " mos7840_write_room:entering ...........");
1400
1401 if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
1402 dbg("%s", "Invalid port \n");
1403 dbg("%s \n", " mos7840_write_room:leaving ...........");
1404 return -1;
1405 }
1406
1407 mos7840_port = mos7840_get_port_private(port);
1408 if (mos7840_port == NULL) {
1409 dbg("%s \n", "mos7840_break:leaving ...........");
1410 return -1;
1411 }
1412
Oliver Neukum0de9a702007-03-16 20:28:28 +01001413 spin_lock_irqsave(&mos7840_port->pool_lock, flags);
Paul B Schroeder3f542972006-08-31 19:41:47 -05001414 for (i = 0; i < NUM_URBS; ++i) {
Oliver Neukum0de9a702007-03-16 20:28:28 +01001415 if (!mos7840_port->busy[i]) {
Paul B Schroeder3f542972006-08-31 19:41:47 -05001416 room += URB_TRANSFER_BUFFER_SIZE;
1417 }
1418 }
Oliver Neukum0de9a702007-03-16 20:28:28 +01001419 spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
Paul B Schroeder3f542972006-08-31 19:41:47 -05001420
Oliver Neukum0de9a702007-03-16 20:28:28 +01001421 room = (room == 0) ? 0 : room - URB_TRANSFER_BUFFER_SIZE + 1;
Paul B Schroeder3f542972006-08-31 19:41:47 -05001422 dbg("%s - returns %d", __FUNCTION__, room);
Oliver Neukum0de9a702007-03-16 20:28:28 +01001423 return room;
Paul B Schroeder3f542972006-08-31 19:41:47 -05001424
1425}
1426
1427/*****************************************************************************
1428 * mos7840_write
1429 * this function is called by the tty driver when data should be written to
1430 * the port.
1431 * If successful, we return the number of bytes written, otherwise we
1432 * return a negative error number.
1433 *****************************************************************************/
1434
1435static int mos7840_write(struct usb_serial_port *port,
1436 const unsigned char *data, int count)
1437{
1438 int status;
1439 int i;
1440 int bytes_sent = 0;
1441 int transfer_size;
Oliver Neukum0de9a702007-03-16 20:28:28 +01001442 unsigned long flags;
Paul B Schroeder3f542972006-08-31 19:41:47 -05001443
1444 struct moschip_port *mos7840_port;
1445 struct usb_serial *serial;
1446 struct urb *urb;
1447 //__u16 Data;
1448 const unsigned char *current_position = data;
1449 unsigned char *data1;
1450 dbg("%s \n", "entering ...........");
1451 //dbg("mos7840_write: mos7840_port->shadowLCR is %x\n",mos7840_port->shadowLCR);
1452
1453#ifdef NOTMOS7840
1454 Data = 0x00;
1455 status = 0;
1456 status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data);
1457 mos7840_port->shadowLCR = Data;
1458 dbg("mos7840_write: LINE_CONTROL_REGISTER is %x\n", Data);
1459 dbg("mos7840_write: mos7840_port->shadowLCR is %x\n",
1460 mos7840_port->shadowLCR);
1461
1462 //Data = 0x03;
1463 //status = mos7840_set_uart_reg(port,LINE_CONTROL_REGISTER,Data);
1464 //mos7840_port->shadowLCR=Data;//Need to add later
1465
1466 Data |= SERIAL_LCR_DLAB; //data latch enable in LCR 0x80
1467 status = 0;
1468 status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
1469
1470 //Data = 0x0c;
1471 //status = mos7840_set_uart_reg(port,DIVISOR_LATCH_LSB,Data);
1472 Data = 0x00;
1473 status = 0;
1474 status = mos7840_get_uart_reg(port, DIVISOR_LATCH_LSB, &Data);
1475 dbg("mos7840_write:DLL value is %x\n", Data);
1476
1477 Data = 0x0;
1478 status = 0;
1479 status = mos7840_get_uart_reg(port, DIVISOR_LATCH_MSB, &Data);
1480 dbg("mos7840_write:DLM value is %x\n", Data);
1481
1482 Data = Data & ~SERIAL_LCR_DLAB;
1483 dbg("mos7840_write: mos7840_port->shadowLCR is %x\n",
1484 mos7840_port->shadowLCR);
1485 status = 0;
1486 status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
1487#endif
1488
1489 if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
1490 dbg("%s", "Port Paranoia failed \n");
1491 return -1;
1492 }
1493
1494 serial = port->serial;
1495 if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) {
1496 dbg("%s", "Serial Paranoia failed \n");
1497 return -1;
1498 }
1499
1500 mos7840_port = mos7840_get_port_private(port);
1501 if (mos7840_port == NULL) {
1502 dbg("%s", "mos7840_port is NULL\n");
1503 return -1;
1504 }
1505
1506 /* try to find a free urb in the list */
1507 urb = NULL;
1508
Oliver Neukum0de9a702007-03-16 20:28:28 +01001509 spin_lock_irqsave(&mos7840_port->pool_lock, flags);
Paul B Schroeder3f542972006-08-31 19:41:47 -05001510 for (i = 0; i < NUM_URBS; ++i) {
Oliver Neukum0de9a702007-03-16 20:28:28 +01001511 if (!mos7840_port->busy[i]) {
1512 mos7840_port->busy[i] = 1;
Paul B Schroeder3f542972006-08-31 19:41:47 -05001513 urb = mos7840_port->write_urb_pool[i];
1514 dbg("\nURB:%d", i);
1515 break;
1516 }
1517 }
Oliver Neukum0de9a702007-03-16 20:28:28 +01001518 spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
Paul B Schroeder3f542972006-08-31 19:41:47 -05001519
1520 if (urb == NULL) {
1521 dbg("%s - no more free urbs", __FUNCTION__);
1522 goto exit;
1523 }
1524
1525 if (urb->transfer_buffer == NULL) {
1526 urb->transfer_buffer =
1527 kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
1528
1529 if (urb->transfer_buffer == NULL) {
1530 err("%s no more kernel memory...", __FUNCTION__);
1531 goto exit;
1532 }
1533 }
1534 transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE);
1535
Al Viro97c49652006-10-09 20:29:03 +01001536 memcpy(urb->transfer_buffer, current_position, transfer_size);
Paul B Schroeder3f542972006-08-31 19:41:47 -05001537
1538 /* fill urb with data and submit */
1539 usb_fill_bulk_urb(urb,
1540 serial->dev,
1541 usb_sndbulkpipe(serial->dev,
1542 port->bulk_out_endpointAddress),
1543 urb->transfer_buffer,
1544 transfer_size,
1545 mos7840_bulk_out_data_callback, mos7840_port);
1546
1547 data1 = urb->transfer_buffer;
1548 dbg("\nbulkout endpoint is %d", port->bulk_out_endpointAddress);
1549
1550 /* send it down the pipe */
1551 status = usb_submit_urb(urb, GFP_ATOMIC);
1552
1553 if (status) {
Oliver Neukum0de9a702007-03-16 20:28:28 +01001554 mos7840_port->busy[i] = 0;
Paul B Schroeder3f542972006-08-31 19:41:47 -05001555 err("%s - usb_submit_urb(write bulk) failed with status = %d",
1556 __FUNCTION__, status);
1557 bytes_sent = status;
1558 goto exit;
1559 }
1560 bytes_sent = transfer_size;
1561 mos7840_port->icount.tx += transfer_size;
Oliver Neukum0de9a702007-03-16 20:28:28 +01001562 smp_wmb();
Paul B Schroeder3f542972006-08-31 19:41:47 -05001563 dbg("mos7840_port->icount.tx is %d:\n", mos7840_port->icount.tx);
1564 exit:
1565
1566 return bytes_sent;
1567
1568}
1569
1570/*****************************************************************************
1571 * mos7840_throttle
1572 * this function is called by the tty driver when it wants to stop the data
1573 * being read from the port.
1574 *****************************************************************************/
1575
1576static void mos7840_throttle(struct usb_serial_port *port)
1577{
1578 struct moschip_port *mos7840_port;
1579 struct tty_struct *tty;
1580 int status;
1581
1582 if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
1583 dbg("%s", "Invalid port \n");
1584 return;
1585 }
1586
1587 dbg("- port %d\n", port->number);
1588
1589 mos7840_port = mos7840_get_port_private(port);
1590
1591 if (mos7840_port == NULL)
1592 return;
1593
1594 if (!mos7840_port->open) {
1595 dbg("%s\n", "port not opened");
1596 return;
1597 }
1598
1599 dbg("%s", "Entering .......... \n");
1600
1601 tty = port->tty;
1602 if (!tty) {
1603 dbg("%s - no tty available", __FUNCTION__);
1604 return;
1605 }
1606
1607 /* if we are implementing XON/XOFF, send the stop character */
1608 if (I_IXOFF(tty)) {
1609 unsigned char stop_char = STOP_CHAR(tty);
1610 status = mos7840_write(port, &stop_char, 1);
1611 if (status <= 0) {
1612 return;
1613 }
1614 }
1615
1616 /* if we are implementing RTS/CTS, toggle that line */
1617 if (tty->termios->c_cflag & CRTSCTS) {
1618 mos7840_port->shadowMCR &= ~MCR_RTS;
1619 status = 0;
1620 status =
1621 mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
1622 mos7840_port->shadowMCR);
1623
1624 if (status < 0) {
1625 return;
1626 }
1627 }
1628
1629 return;
1630}
1631
1632/*****************************************************************************
1633 * mos7840_unthrottle
1634 * this function is called by the tty driver when it wants to resume the data
1635 * being read from the port (called after SerialThrottle is called)
1636 *****************************************************************************/
1637static void mos7840_unthrottle(struct usb_serial_port *port)
1638{
1639 struct tty_struct *tty;
1640 int status;
1641 struct moschip_port *mos7840_port = mos7840_get_port_private(port);
1642
1643 if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
1644 dbg("%s", "Invalid port \n");
1645 return;
1646 }
1647
1648 if (mos7840_port == NULL)
1649 return;
1650
1651 if (!mos7840_port->open) {
1652 dbg("%s - port not opened", __FUNCTION__);
1653 return;
1654 }
1655
1656 dbg("%s", "Entering .......... \n");
1657
1658 tty = port->tty;
1659 if (!tty) {
1660 dbg("%s - no tty available", __FUNCTION__);
1661 return;
1662 }
1663
1664 /* if we are implementing XON/XOFF, send the start character */
1665 if (I_IXOFF(tty)) {
1666 unsigned char start_char = START_CHAR(tty);
1667 status = mos7840_write(port, &start_char, 1);
1668 if (status <= 0) {
1669 return;
1670 }
1671 }
1672
1673 /* if we are implementing RTS/CTS, toggle that line */
1674 if (tty->termios->c_cflag & CRTSCTS) {
1675 mos7840_port->shadowMCR |= MCR_RTS;
1676 status = 0;
1677 status =
1678 mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
1679 mos7840_port->shadowMCR);
1680 if (status < 0) {
1681 return;
1682 }
1683 }
1684
1685 return;
1686}
1687
1688static int mos7840_tiocmget(struct usb_serial_port *port, struct file *file)
1689{
1690 struct moschip_port *mos7840_port;
1691 unsigned int result;
1692 __u16 msr;
1693 __u16 mcr;
1694 int status = 0;
1695 mos7840_port = mos7840_get_port_private(port);
1696
1697 dbg("%s - port %d", __FUNCTION__, port->number);
1698
1699 if (mos7840_port == NULL)
1700 return -ENODEV;
1701
1702 status = mos7840_get_uart_reg(port, MODEM_STATUS_REGISTER, &msr);
1703 status = mos7840_get_uart_reg(port, MODEM_CONTROL_REGISTER, &mcr);
1704 result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0)
1705 | ((mcr & MCR_RTS) ? TIOCM_RTS : 0)
1706 | ((mcr & MCR_LOOPBACK) ? TIOCM_LOOP : 0)
1707 | ((msr & MOS7840_MSR_CTS) ? TIOCM_CTS : 0)
1708 | ((msr & MOS7840_MSR_CD) ? TIOCM_CAR : 0)
1709 | ((msr & MOS7840_MSR_RI) ? TIOCM_RI : 0)
1710 | ((msr & MOS7840_MSR_DSR) ? TIOCM_DSR : 0);
1711
1712 dbg("%s - 0x%04X", __FUNCTION__, result);
1713
1714 return result;
1715}
1716
1717static int mos7840_tiocmset(struct usb_serial_port *port, struct file *file,
1718 unsigned int set, unsigned int clear)
1719{
1720 struct moschip_port *mos7840_port;
1721 unsigned int mcr;
1722 unsigned int status;
1723
1724 dbg("%s - port %d", __FUNCTION__, port->number);
1725
1726 mos7840_port = mos7840_get_port_private(port);
1727
1728 if (mos7840_port == NULL)
1729 return -ENODEV;
1730
1731 mcr = mos7840_port->shadowMCR;
1732 if (clear & TIOCM_RTS)
1733 mcr &= ~MCR_RTS;
1734 if (clear & TIOCM_DTR)
1735 mcr &= ~MCR_DTR;
1736 if (clear & TIOCM_LOOP)
1737 mcr &= ~MCR_LOOPBACK;
1738
1739 if (set & TIOCM_RTS)
1740 mcr |= MCR_RTS;
1741 if (set & TIOCM_DTR)
1742 mcr |= MCR_DTR;
1743 if (set & TIOCM_LOOP)
1744 mcr |= MCR_LOOPBACK;
1745
1746 mos7840_port->shadowMCR = mcr;
1747
1748 status = 0;
1749 status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, mcr);
1750 if (status < 0) {
1751 dbg("setting MODEM_CONTROL_REGISTER Failed\n");
1752 return -1;
1753 }
1754
1755 return 0;
1756}
1757
1758/*****************************************************************************
1759 * mos7840_calc_baud_rate_divisor
1760 * this function calculates the proper baud rate divisor for the specified
1761 * baud rate.
1762 *****************************************************************************/
1763static int mos7840_calc_baud_rate_divisor(int baudRate, int *divisor,
1764 __u16 * clk_sel_val)
1765{
1766
1767 dbg("%s - %d", __FUNCTION__, baudRate);
1768
1769 if (baudRate <= 115200) {
1770 *divisor = 115200 / baudRate;
1771 *clk_sel_val = 0x0;
1772 }
1773 if ((baudRate > 115200) && (baudRate <= 230400)) {
1774 *divisor = 230400 / baudRate;
1775 *clk_sel_val = 0x10;
1776 } else if ((baudRate > 230400) && (baudRate <= 403200)) {
1777 *divisor = 403200 / baudRate;
1778 *clk_sel_val = 0x20;
1779 } else if ((baudRate > 403200) && (baudRate <= 460800)) {
1780 *divisor = 460800 / baudRate;
1781 *clk_sel_val = 0x30;
1782 } else if ((baudRate > 460800) && (baudRate <= 806400)) {
1783 *divisor = 806400 / baudRate;
1784 *clk_sel_val = 0x40;
1785 } else if ((baudRate > 806400) && (baudRate <= 921600)) {
1786 *divisor = 921600 / baudRate;
1787 *clk_sel_val = 0x50;
1788 } else if ((baudRate > 921600) && (baudRate <= 1572864)) {
1789 *divisor = 1572864 / baudRate;
1790 *clk_sel_val = 0x60;
1791 } else if ((baudRate > 1572864) && (baudRate <= 3145728)) {
1792 *divisor = 3145728 / baudRate;
1793 *clk_sel_val = 0x70;
1794 }
1795 return 0;
1796
1797#ifdef NOTMCS7840
1798
1799 for (i = 0; i < ARRAY_SIZE(mos7840_divisor_table); i++) {
1800 if (mos7840_divisor_table[i].BaudRate == baudrate) {
1801 *divisor = mos7840_divisor_table[i].Divisor;
1802 return 0;
1803 }
1804 }
1805
1806 /* After trying for all the standard baud rates *
1807 * Try calculating the divisor for this baud rate */
1808
1809 if (baudrate > 75 && baudrate < 230400) {
1810 /* get the divisor */
1811 custom = (__u16) (230400L / baudrate);
1812
1813 /* Check for round off */
1814 round1 = (__u16) (2304000L / baudrate);
1815 round = (__u16) (round1 - (custom * 10));
1816 if (round > 4) {
1817 custom++;
1818 }
1819 *divisor = custom;
1820
1821 dbg(" Baud %d = %d\n", baudrate, custom);
1822 return 0;
1823 }
1824
1825 dbg("%s\n", " Baud calculation Failed...");
1826 return -1;
1827#endif
1828}
1829
1830/*****************************************************************************
1831 * mos7840_send_cmd_write_baud_rate
1832 * this function sends the proper command to change the baud rate of the
1833 * specified port.
1834 *****************************************************************************/
1835
1836static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
1837 int baudRate)
1838{
1839 int divisor = 0;
1840 int status;
1841 __u16 Data;
1842 unsigned char number;
1843 __u16 clk_sel_val;
1844 struct usb_serial_port *port;
1845
1846 if (mos7840_port == NULL)
1847 return -1;
1848
1849 port = (struct usb_serial_port *)mos7840_port->port;
1850 if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
1851 dbg("%s", "Invalid port \n");
1852 return -1;
1853 }
1854
1855 if (mos7840_serial_paranoia_check(port->serial, __FUNCTION__)) {
1856 dbg("%s", "Invalid Serial \n");
1857 return -1;
1858 }
1859
1860 dbg("%s", "Entering .......... \n");
1861
1862 number = mos7840_port->port->number - mos7840_port->port->serial->minor;
1863
1864 dbg("%s - port = %d, baud = %d", __FUNCTION__,
1865 mos7840_port->port->number, baudRate);
1866 //reset clk_uart_sel in spregOffset
1867 if (baudRate > 115200) {
1868#ifdef HW_flow_control
1869 //NOTE: need to see the pther register to modify
1870 //setting h/w flow control bit to 1;
1871 status = 0;
1872 Data = 0x2b;
1873 mos7840_port->shadowMCR = Data;
1874 status =
1875 mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
1876 if (status < 0) {
1877 dbg("Writing spreg failed in set_serial_baud\n");
1878 return -1;
1879 }
1880#endif
1881
1882 } else {
1883#ifdef HW_flow_control
1884 //setting h/w flow control bit to 0;
1885 status = 0;
1886 Data = 0xb;
1887 mos7840_port->shadowMCR = Data;
1888 status =
1889 mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
1890 if (status < 0) {
1891 dbg("Writing spreg failed in set_serial_baud\n");
1892 return -1;
1893 }
1894#endif
1895
1896 }
1897
1898 if (1) //baudRate <= 115200)
1899 {
1900 clk_sel_val = 0x0;
1901 Data = 0x0;
1902 status = 0;
1903 status =
1904 mos7840_calc_baud_rate_divisor(baudRate, &divisor,
1905 &clk_sel_val);
1906 status =
1907 mos7840_get_reg_sync(port, mos7840_port->SpRegOffset,
1908 &Data);
1909 if (status < 0) {
1910 dbg("reading spreg failed in set_serial_baud\n");
1911 return -1;
1912 }
1913 Data = (Data & 0x8f) | clk_sel_val;
1914 status = 0;
1915 status =
1916 mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
1917 if (status < 0) {
1918 dbg("Writing spreg failed in set_serial_baud\n");
1919 return -1;
1920 }
1921 /* Calculate the Divisor */
1922
1923 if (status) {
1924 err("%s - bad baud rate", __FUNCTION__);
1925 dbg("%s\n", "bad baud rate");
1926 return status;
1927 }
1928 /* Enable access to divisor latch */
1929 Data = mos7840_port->shadowLCR | SERIAL_LCR_DLAB;
1930 mos7840_port->shadowLCR = Data;
1931 mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
1932
1933 /* Write the divisor */
1934 Data = (unsigned char)(divisor & 0xff);
1935 dbg("set_serial_baud Value to write DLL is %x\n", Data);
1936 mos7840_set_uart_reg(port, DIVISOR_LATCH_LSB, Data);
1937
1938 Data = (unsigned char)((divisor & 0xff00) >> 8);
1939 dbg("set_serial_baud Value to write DLM is %x\n", Data);
1940 mos7840_set_uart_reg(port, DIVISOR_LATCH_MSB, Data);
1941
1942 /* Disable access to divisor latch */
1943 Data = mos7840_port->shadowLCR & ~SERIAL_LCR_DLAB;
1944 mos7840_port->shadowLCR = Data;
1945 mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
1946
1947 }
1948
1949 return status;
1950}
1951
1952/*****************************************************************************
1953 * mos7840_change_port_settings
1954 * This routine is called to set the UART on the device to match
1955 * the specified new settings.
1956 *****************************************************************************/
1957
1958static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
Alan Cox606d0992006-12-08 02:38:45 -08001959 struct ktermios *old_termios)
Paul B Schroeder3f542972006-08-31 19:41:47 -05001960{
1961 struct tty_struct *tty;
1962 int baud;
1963 unsigned cflag;
1964 unsigned iflag;
1965 __u8 lData;
1966 __u8 lParity;
1967 __u8 lStop;
1968 int status;
1969 __u16 Data;
1970 struct usb_serial_port *port;
1971 struct usb_serial *serial;
1972
1973 if (mos7840_port == NULL)
1974 return;
1975
1976 port = (struct usb_serial_port *)mos7840_port->port;
1977
1978 if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
1979 dbg("%s", "Invalid port \n");
1980 return;
1981 }
1982
1983 if (mos7840_serial_paranoia_check(port->serial, __FUNCTION__)) {
1984 dbg("%s", "Invalid Serial \n");
1985 return;
1986 }
1987
1988 serial = port->serial;
1989
1990 dbg("%s - port %d", __FUNCTION__, mos7840_port->port->number);
1991
1992 if (!mos7840_port->open) {
1993 dbg("%s - port not opened", __FUNCTION__);
1994 return;
1995 }
1996
1997 tty = mos7840_port->port->tty;
1998
1999 if ((!tty) || (!tty->termios)) {
2000 dbg("%s - no tty structures", __FUNCTION__);
2001 return;
2002 }
2003
2004 dbg("%s", "Entering .......... \n");
2005
2006 lData = LCR_BITS_8;
2007 lStop = LCR_STOP_1;
2008 lParity = LCR_PAR_NONE;
2009
2010 cflag = tty->termios->c_cflag;
2011 iflag = tty->termios->c_iflag;
2012
2013 /* Change the number of bits */
2014 if (cflag & CSIZE) {
2015 switch (cflag & CSIZE) {
2016 case CS5:
2017 lData = LCR_BITS_5;
2018 break;
2019
2020 case CS6:
2021 lData = LCR_BITS_6;
2022 break;
2023
2024 case CS7:
2025 lData = LCR_BITS_7;
2026 break;
2027 default:
2028 case CS8:
2029 lData = LCR_BITS_8;
2030 break;
2031 }
2032 }
2033 /* Change the Parity bit */
2034 if (cflag & PARENB) {
2035 if (cflag & PARODD) {
2036 lParity = LCR_PAR_ODD;
2037 dbg("%s - parity = odd", __FUNCTION__);
2038 } else {
2039 lParity = LCR_PAR_EVEN;
2040 dbg("%s - parity = even", __FUNCTION__);
2041 }
2042
2043 } else {
2044 dbg("%s - parity = none", __FUNCTION__);
2045 }
2046
2047 if (cflag & CMSPAR) {
2048 lParity = lParity | 0x20;
2049 }
2050
2051 /* Change the Stop bit */
2052 if (cflag & CSTOPB) {
2053 lStop = LCR_STOP_2;
2054 dbg("%s - stop bits = 2", __FUNCTION__);
2055 } else {
2056 lStop = LCR_STOP_1;
2057 dbg("%s - stop bits = 1", __FUNCTION__);
2058 }
2059
2060 /* Update the LCR with the correct value */
2061 mos7840_port->shadowLCR &=
2062 ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK);
2063 mos7840_port->shadowLCR |= (lData | lParity | lStop);
2064
2065 dbg("mos7840_change_port_settings mos7840_port->shadowLCR is %x\n",
2066 mos7840_port->shadowLCR);
2067 /* Disable Interrupts */
2068 Data = 0x00;
2069 mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
2070
2071 Data = 0x00;
2072 mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
2073
2074 Data = 0xcf;
2075 mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
2076
2077 /* Send the updated LCR value to the mos7840 */
2078 Data = mos7840_port->shadowLCR;
2079
2080 mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
2081
2082 Data = 0x00b;
2083 mos7840_port->shadowMCR = Data;
2084 mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
2085 Data = 0x00b;
2086 mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
2087
2088 /* set up the MCR register and send it to the mos7840 */
2089
2090 mos7840_port->shadowMCR = MCR_MASTER_IE;
2091 if (cflag & CBAUD) {
2092 mos7840_port->shadowMCR |= (MCR_DTR | MCR_RTS);
2093 }
2094
2095 if (cflag & CRTSCTS) {
2096 mos7840_port->shadowMCR |= (MCR_XON_ANY);
2097
2098 } else {
2099 mos7840_port->shadowMCR &= ~(MCR_XON_ANY);
2100 }
2101
2102 Data = mos7840_port->shadowMCR;
2103 mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
2104
2105 /* Determine divisor based on baud rate */
2106 baud = tty_get_baud_rate(tty);
2107
2108 if (!baud) {
2109 /* pick a default, any default... */
2110 dbg("%s\n", "Picked default baud...");
2111 baud = 9600;
2112 }
2113
2114 dbg("%s - baud rate = %d", __FUNCTION__, baud);
2115 status = mos7840_send_cmd_write_baud_rate(mos7840_port, baud);
2116
2117 /* Enable Interrupts */
2118 Data = 0x0c;
2119 mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
2120
2121 if (mos7840_port->read_urb->status != -EINPROGRESS) {
2122 mos7840_port->read_urb->dev = serial->dev;
2123
2124 status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
2125
2126 if (status) {
2127 dbg(" usb_submit_urb(read bulk) failed, status = %d",
2128 status);
2129 }
2130 }
2131 wake_up(&mos7840_port->delta_msr_wait);
2132 mos7840_port->delta_msr_cond = 1;
2133 dbg("mos7840_change_port_settings mos7840_port->shadowLCR is End %x\n",
2134 mos7840_port->shadowLCR);
2135
2136 return;
2137}
2138
2139/*****************************************************************************
2140 * mos7840_set_termios
2141 * this function is called by the tty driver when it wants to change
2142 * the termios structure
2143 *****************************************************************************/
2144
2145static void mos7840_set_termios(struct usb_serial_port *port,
Alan Cox606d0992006-12-08 02:38:45 -08002146 struct ktermios *old_termios)
Paul B Schroeder3f542972006-08-31 19:41:47 -05002147{
2148 int status;
2149 unsigned int cflag;
2150 struct usb_serial *serial;
2151 struct moschip_port *mos7840_port;
2152 struct tty_struct *tty;
2153 dbg("mos7840_set_termios: START\n");
2154 if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
2155 dbg("%s", "Invalid port \n");
2156 return;
2157 }
2158
2159 serial = port->serial;
2160
2161 if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) {
2162 dbg("%s", "Invalid Serial \n");
2163 return;
2164 }
2165
2166 mos7840_port = mos7840_get_port_private(port);
2167
2168 if (mos7840_port == NULL)
2169 return;
2170
2171 tty = port->tty;
2172
2173 if (!port->tty || !port->tty->termios) {
2174 dbg("%s - no tty or termios", __FUNCTION__);
2175 return;
2176 }
2177
2178 if (!mos7840_port->open) {
2179 dbg("%s - port not opened", __FUNCTION__);
2180 return;
2181 }
2182
2183 dbg("%s\n", "setting termios - ");
2184
2185 cflag = tty->termios->c_cflag;
2186
2187 if (!cflag) {
2188 dbg("%s %s\n", __FUNCTION__, "cflag is NULL");
2189 return;
2190 }
2191
2192 /* check that they really want us to change something */
2193 if (old_termios) {
2194 if ((cflag == old_termios->c_cflag) &&
2195 (RELEVANT_IFLAG(tty->termios->c_iflag) ==
2196 RELEVANT_IFLAG(old_termios->c_iflag))) {
2197 dbg("%s\n", "Nothing to change");
2198 return;
2199 }
2200 }
2201
2202 dbg("%s - clfag %08x iflag %08x", __FUNCTION__,
2203 tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag));
2204
2205 if (old_termios) {
2206 dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,
2207 old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag));
2208 }
2209
2210 dbg("%s - port %d", __FUNCTION__, port->number);
2211
2212 /* change the port settings to the new ones specified */
2213
2214 mos7840_change_port_settings(mos7840_port, old_termios);
2215
2216 if (!mos7840_port->read_urb) {
2217 dbg("%s", "URB KILLED !!!!!\n");
2218 return;
2219 }
2220
2221 if (mos7840_port->read_urb->status != -EINPROGRESS) {
2222 mos7840_port->read_urb->dev = serial->dev;
2223 status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
2224 if (status) {
2225 dbg(" usb_submit_urb(read bulk) failed, status = %d",
2226 status);
2227 }
2228 }
2229 return;
2230}
2231
2232/*****************************************************************************
2233 * mos7840_get_lsr_info - get line status register info
2234 *
2235 * Purpose: Let user call ioctl() to get info when the UART physically
2236 * is emptied. On bus types like RS485, the transmitter must
2237 * release the bus after transmitting. This must be done when
2238 * the transmit shift register is empty, not be done when the
2239 * transmit holding register is empty. This functionality
2240 * allows an RS485 driver to be written in user space.
2241 *****************************************************************************/
2242
2243static int mos7840_get_lsr_info(struct moschip_port *mos7840_port,
Al Viro97c49652006-10-09 20:29:03 +01002244 unsigned int __user *value)
Paul B Schroeder3f542972006-08-31 19:41:47 -05002245{
2246 int count;
2247 unsigned int result = 0;
2248
2249 count = mos7840_chars_in_buffer(mos7840_port->port);
2250 if (count == 0) {
2251 dbg("%s -- Empty", __FUNCTION__);
2252 result = TIOCSER_TEMT;
2253 }
2254
2255 if (copy_to_user(value, &result, sizeof(int)))
2256 return -EFAULT;
2257 return 0;
2258}
2259
2260/*****************************************************************************
2261 * mos7840_get_bytes_avail - get number of bytes available
2262 *
2263 * Purpose: Let user call ioctl to get the count of number of bytes available.
2264 *****************************************************************************/
2265
2266static int mos7840_get_bytes_avail(struct moschip_port *mos7840_port,
Al Viro97c49652006-10-09 20:29:03 +01002267 unsigned int __user *value)
Paul B Schroeder3f542972006-08-31 19:41:47 -05002268{
2269 unsigned int result = 0;
2270 struct tty_struct *tty = mos7840_port->port->tty;
2271
2272 if (!tty)
2273 return -ENOIOCTLCMD;
2274
2275 result = tty->read_cnt;
2276
2277 dbg("%s(%d) = %d", __FUNCTION__, mos7840_port->port->number, result);
2278 if (copy_to_user(value, &result, sizeof(int)))
2279 return -EFAULT;
2280
2281 return -ENOIOCTLCMD;
2282}
2283
2284/*****************************************************************************
2285 * mos7840_set_modem_info
2286 * function to set modem info
2287 *****************************************************************************/
2288
2289static int mos7840_set_modem_info(struct moschip_port *mos7840_port,
Al Viro97c49652006-10-09 20:29:03 +01002290 unsigned int cmd, unsigned int __user *value)
Paul B Schroeder3f542972006-08-31 19:41:47 -05002291{
2292 unsigned int mcr;
2293 unsigned int arg;
2294 __u16 Data;
2295 int status;
2296 struct usb_serial_port *port;
2297
2298 if (mos7840_port == NULL)
2299 return -1;
2300
2301 port = (struct usb_serial_port *)mos7840_port->port;
2302 if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
2303 dbg("%s", "Invalid port \n");
2304 return -1;
2305 }
2306
2307 mcr = mos7840_port->shadowMCR;
2308
2309 if (copy_from_user(&arg, value, sizeof(int)))
2310 return -EFAULT;
2311
2312 switch (cmd) {
2313 case TIOCMBIS:
2314 if (arg & TIOCM_RTS)
2315 mcr |= MCR_RTS;
2316 if (arg & TIOCM_DTR)
2317 mcr |= MCR_RTS;
2318 if (arg & TIOCM_LOOP)
2319 mcr |= MCR_LOOPBACK;
2320 break;
2321
2322 case TIOCMBIC:
2323 if (arg & TIOCM_RTS)
2324 mcr &= ~MCR_RTS;
2325 if (arg & TIOCM_DTR)
2326 mcr &= ~MCR_RTS;
2327 if (arg & TIOCM_LOOP)
2328 mcr &= ~MCR_LOOPBACK;
2329 break;
2330
2331 case TIOCMSET:
2332 /* turn off the RTS and DTR and LOOPBACK
2333 * and then only turn on what was asked to */
2334 mcr &= ~(MCR_RTS | MCR_DTR | MCR_LOOPBACK);
2335 mcr |= ((arg & TIOCM_RTS) ? MCR_RTS : 0);
2336 mcr |= ((arg & TIOCM_DTR) ? MCR_DTR : 0);
2337 mcr |= ((arg & TIOCM_LOOP) ? MCR_LOOPBACK : 0);
2338 break;
2339 }
2340
2341 mos7840_port->shadowMCR = mcr;
2342
2343 Data = mos7840_port->shadowMCR;
2344 status = 0;
2345 status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
2346 if (status < 0) {
2347 dbg("setting MODEM_CONTROL_REGISTER Failed\n");
2348 return -1;
2349 }
2350
2351 return 0;
2352}
2353
2354/*****************************************************************************
2355 * mos7840_get_modem_info
2356 * function to get modem info
2357 *****************************************************************************/
2358
2359static int mos7840_get_modem_info(struct moschip_port *mos7840_port,
Al Viro97c49652006-10-09 20:29:03 +01002360 unsigned int __user *value)
Paul B Schroeder3f542972006-08-31 19:41:47 -05002361{
2362 unsigned int result = 0;
2363 __u16 msr;
2364 unsigned int mcr = mos7840_port->shadowMCR;
2365 int status = 0;
2366 status =
2367 mos7840_get_uart_reg(mos7840_port->port, MODEM_STATUS_REGISTER,
2368 &msr);
2369 result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) /* 0x002 */
2370 |((mcr & MCR_RTS) ? TIOCM_RTS : 0) /* 0x004 */
2371 |((msr & MOS7840_MSR_CTS) ? TIOCM_CTS : 0) /* 0x020 */
2372 |((msr & MOS7840_MSR_CD) ? TIOCM_CAR : 0) /* 0x040 */
2373 |((msr & MOS7840_MSR_RI) ? TIOCM_RI : 0) /* 0x080 */
2374 |((msr & MOS7840_MSR_DSR) ? TIOCM_DSR : 0); /* 0x100 */
2375
2376 dbg("%s -- %x", __FUNCTION__, result);
2377
2378 if (copy_to_user(value, &result, sizeof(int)))
2379 return -EFAULT;
2380 return 0;
2381}
2382
2383/*****************************************************************************
2384 * mos7840_get_serial_info
2385 * function to get information about serial port
2386 *****************************************************************************/
2387
2388static int mos7840_get_serial_info(struct moschip_port *mos7840_port,
Al Viro97c49652006-10-09 20:29:03 +01002389 struct serial_struct __user *retinfo)
Paul B Schroeder3f542972006-08-31 19:41:47 -05002390{
2391 struct serial_struct tmp;
2392
2393 if (mos7840_port == NULL)
2394 return -1;
2395
2396 if (!retinfo)
2397 return -EFAULT;
2398
2399 memset(&tmp, 0, sizeof(tmp));
2400
2401 tmp.type = PORT_16550A;
2402 tmp.line = mos7840_port->port->serial->minor;
2403 tmp.port = mos7840_port->port->number;
2404 tmp.irq = 0;
2405 tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
2406 tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE;
2407 tmp.baud_base = 9600;
2408 tmp.close_delay = 5 * HZ;
2409 tmp.closing_wait = 30 * HZ;
2410
2411 if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
2412 return -EFAULT;
2413 return 0;
2414}
2415
2416/*****************************************************************************
2417 * SerialIoctl
2418 * this function handles any ioctl calls to the driver
2419 *****************************************************************************/
2420
2421static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
2422 unsigned int cmd, unsigned long arg)
2423{
Al Viro97c49652006-10-09 20:29:03 +01002424 void __user *argp = (void __user *)arg;
Paul B Schroeder3f542972006-08-31 19:41:47 -05002425 struct moschip_port *mos7840_port;
2426 struct tty_struct *tty;
2427
2428 struct async_icount cnow;
2429 struct async_icount cprev;
2430 struct serial_icounter_struct icount;
2431 int mosret = 0;
2432 int retval;
2433 struct tty_ldisc *ld;
2434
2435 if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
2436 dbg("%s", "Invalid port \n");
2437 return -1;
2438 }
2439
2440 mos7840_port = mos7840_get_port_private(port);
Paul B Schroeder3f542972006-08-31 19:41:47 -05002441
2442 if (mos7840_port == NULL)
2443 return -1;
2444
Adrian Bunkad180272006-10-09 01:16:32 +02002445 tty = mos7840_port->port->tty;
2446
Paul B Schroeder3f542972006-08-31 19:41:47 -05002447 dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);
2448
2449 switch (cmd) {
2450 /* return number of bytes available */
2451
2452 case TIOCINQ:
2453 dbg("%s (%d) TIOCINQ", __FUNCTION__, port->number);
Al Viro97c49652006-10-09 20:29:03 +01002454 return mos7840_get_bytes_avail(mos7840_port, argp);
Paul B Schroeder3f542972006-08-31 19:41:47 -05002455
2456 case TIOCOUTQ:
2457 dbg("%s (%d) TIOCOUTQ", __FUNCTION__, port->number);
2458 return put_user(tty->driver->chars_in_buffer ?
2459 tty->driver->chars_in_buffer(tty) : 0,
2460 (int __user *)arg);
Paul B Schroeder3f542972006-08-31 19:41:47 -05002461
2462 case TCFLSH:
2463 retval = tty_check_change(tty);
2464 if (retval)
2465 return retval;
2466
2467 ld = tty_ldisc_ref(tty);
2468 switch (arg) {
2469 case TCIFLUSH:
2470 if (ld && ld->flush_buffer)
2471 ld->flush_buffer(tty);
2472 break;
2473 case TCIOFLUSH:
2474 if (ld && ld->flush_buffer)
2475 ld->flush_buffer(tty);
2476 /* fall through */
2477 case TCOFLUSH:
2478 if (tty->driver->flush_buffer)
2479 tty->driver->flush_buffer(tty);
2480 break;
2481 default:
2482 tty_ldisc_deref(ld);
2483 return -EINVAL;
2484 }
2485 tty_ldisc_deref(ld);
2486 return 0;
2487
Paul B Schroeder3f542972006-08-31 19:41:47 -05002488 case TIOCSERGETLSR:
2489 dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__, port->number);
Al Viro97c49652006-10-09 20:29:03 +01002490 return mos7840_get_lsr_info(mos7840_port, argp);
Paul B Schroeder3f542972006-08-31 19:41:47 -05002491 return 0;
2492
2493 case TIOCMBIS:
2494 case TIOCMBIC:
2495 case TIOCMSET:
2496 dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __FUNCTION__,
2497 port->number);
2498 mosret =
Al Viro97c49652006-10-09 20:29:03 +01002499 mos7840_set_modem_info(mos7840_port, cmd, argp);
Paul B Schroeder3f542972006-08-31 19:41:47 -05002500 return mosret;
2501
2502 case TIOCMGET:
2503 dbg("%s (%d) TIOCMGET", __FUNCTION__, port->number);
Al Viro97c49652006-10-09 20:29:03 +01002504 return mos7840_get_modem_info(mos7840_port, argp);
Paul B Schroeder3f542972006-08-31 19:41:47 -05002505
2506 case TIOCGSERIAL:
2507 dbg("%s (%d) TIOCGSERIAL", __FUNCTION__, port->number);
Al Viro97c49652006-10-09 20:29:03 +01002508 return mos7840_get_serial_info(mos7840_port, argp);
Paul B Schroeder3f542972006-08-31 19:41:47 -05002509
2510 case TIOCSSERIAL:
2511 dbg("%s (%d) TIOCSSERIAL", __FUNCTION__, port->number);
2512 break;
2513
2514 case TIOCMIWAIT:
2515 dbg("%s (%d) TIOCMIWAIT", __FUNCTION__, port->number);
2516 cprev = mos7840_port->icount;
2517 while (1) {
2518 //interruptible_sleep_on(&mos7840_port->delta_msr_wait);
2519 mos7840_port->delta_msr_cond = 0;
2520 wait_event_interruptible(mos7840_port->delta_msr_wait,
2521 (mos7840_port->
2522 delta_msr_cond == 1));
2523
2524 /* see if a signal did it */
2525 if (signal_pending(current))
2526 return -ERESTARTSYS;
2527 cnow = mos7840_port->icount;
Oliver Neukum0de9a702007-03-16 20:28:28 +01002528 smp_rmb();
Paul B Schroeder3f542972006-08-31 19:41:47 -05002529 if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
2530 cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
2531 return -EIO; /* no change => error */
2532 if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
2533 ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
2534 ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
2535 ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
2536 return 0;
2537 }
2538 cprev = cnow;
2539 }
2540 /* NOTREACHED */
2541 break;
2542
2543 case TIOCGICOUNT:
2544 cnow = mos7840_port->icount;
Oliver Neukum0de9a702007-03-16 20:28:28 +01002545 smp_rmb();
Paul B Schroeder3f542972006-08-31 19:41:47 -05002546 icount.cts = cnow.cts;
2547 icount.dsr = cnow.dsr;
2548 icount.rng = cnow.rng;
2549 icount.dcd = cnow.dcd;
2550 icount.rx = cnow.rx;
2551 icount.tx = cnow.tx;
2552 icount.frame = cnow.frame;
2553 icount.overrun = cnow.overrun;
2554 icount.parity = cnow.parity;
2555 icount.brk = cnow.brk;
2556 icount.buf_overrun = cnow.buf_overrun;
2557
2558 dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__,
2559 port->number, icount.rx, icount.tx);
Al Viro97c49652006-10-09 20:29:03 +01002560 if (copy_to_user(argp, &icount, sizeof(icount)))
Paul B Schroeder3f542972006-08-31 19:41:47 -05002561 return -EFAULT;
2562 return 0;
2563
2564 case TIOCEXBAUD:
2565 return 0;
2566 default:
2567 break;
2568 }
2569
2570 return -ENOIOCTLCMD;
2571}
2572
2573static int mos7840_calc_num_ports(struct usb_serial *serial)
2574{
Oliver Neukum0de9a702007-03-16 20:28:28 +01002575 int mos7840_num_ports = 0;
Paul B Schroeder3f542972006-08-31 19:41:47 -05002576
2577 dbg("numberofendpoints: %d \n",
2578 (int)serial->interface->cur_altsetting->desc.bNumEndpoints);
2579 dbg("numberofendpoints: %d \n",
2580 (int)serial->interface->altsetting->desc.bNumEndpoints);
2581 if (serial->interface->cur_altsetting->desc.bNumEndpoints == 5) {
Oliver Neukum0de9a702007-03-16 20:28:28 +01002582 mos7840_num_ports = serial->num_ports = 2;
Paul B Schroeder3f542972006-08-31 19:41:47 -05002583 } else if (serial->interface->cur_altsetting->desc.bNumEndpoints == 9) {
Oliver Neukum0de9a702007-03-16 20:28:28 +01002584 serial->num_bulk_in = 4;
2585 serial->num_bulk_out = 4;
2586 mos7840_num_ports = serial->num_ports = 4;
Paul B Schroeder3f542972006-08-31 19:41:47 -05002587 }
2588
2589 return mos7840_num_ports;
2590}
2591
2592/****************************************************************************
2593 * mos7840_startup
2594 ****************************************************************************/
2595
2596static int mos7840_startup(struct usb_serial *serial)
2597{
2598 struct moschip_port *mos7840_port;
2599 struct usb_device *dev;
2600 int i, status;
2601
2602 __u16 Data;
2603 dbg("%s \n", " mos7840_startup :entering..........");
2604
2605 if (!serial) {
2606 dbg("%s\n", "Invalid Handler");
2607 return -1;
2608 }
2609
2610 dev = serial->dev;
2611
2612 dbg("%s\n", "Entering...");
2613
2614 /* we set up the pointers to the endpoints in the mos7840_open *
2615 * function, as the structures aren't created yet. */
2616
2617 /* set up port private structures */
2618 for (i = 0; i < serial->num_ports; ++i) {
Burman Yan7ac9da12006-11-22 20:54:38 +02002619 mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
Paul B Schroeder3f542972006-08-31 19:41:47 -05002620 if (mos7840_port == NULL) {
2621 err("%s - Out of memory", __FUNCTION__);
Oliver Neukum0de9a702007-03-16 20:28:28 +01002622 status = -ENOMEM;
2623 i--; /* don't follow NULL pointer cleaning up */
2624 goto error;
Paul B Schroeder3f542972006-08-31 19:41:47 -05002625 }
Paul B Schroeder3f542972006-08-31 19:41:47 -05002626
2627 /* Initialize all port interrupt end point to port 0 int endpoint *
2628 * Our device has only one interrupt end point comman to all port */
2629
2630 mos7840_port->port = serial->port[i];
2631 mos7840_set_port_private(serial->port[i], mos7840_port);
Oliver Neukum0de9a702007-03-16 20:28:28 +01002632 spin_lock_init(&mos7840_port->pool_lock);
Paul B Schroeder3f542972006-08-31 19:41:47 -05002633
2634 mos7840_port->port_num = ((serial->port[i]->number -
2635 (serial->port[i]->serial->minor)) +
2636 1);
2637
2638 if (mos7840_port->port_num == 1) {
2639 mos7840_port->SpRegOffset = 0x0;
2640 mos7840_port->ControlRegOffset = 0x1;
2641 mos7840_port->DcrRegOffset = 0x4;
2642 } else if ((mos7840_port->port_num == 2)
Oliver Neukum0de9a702007-03-16 20:28:28 +01002643 && (serial->num_ports == 4)) {
Paul B Schroeder3f542972006-08-31 19:41:47 -05002644 mos7840_port->SpRegOffset = 0x8;
2645 mos7840_port->ControlRegOffset = 0x9;
2646 mos7840_port->DcrRegOffset = 0x16;
2647 } else if ((mos7840_port->port_num == 2)
Oliver Neukum0de9a702007-03-16 20:28:28 +01002648 && (serial->num_ports == 2)) {
Paul B Schroeder3f542972006-08-31 19:41:47 -05002649 mos7840_port->SpRegOffset = 0xa;
2650 mos7840_port->ControlRegOffset = 0xb;
2651 mos7840_port->DcrRegOffset = 0x19;
2652 } else if ((mos7840_port->port_num == 3)
Oliver Neukum0de9a702007-03-16 20:28:28 +01002653 && (serial->num_ports == 4)) {
Paul B Schroeder3f542972006-08-31 19:41:47 -05002654 mos7840_port->SpRegOffset = 0xa;
2655 mos7840_port->ControlRegOffset = 0xb;
2656 mos7840_port->DcrRegOffset = 0x19;
2657 } else if ((mos7840_port->port_num == 4)
Oliver Neukum0de9a702007-03-16 20:28:28 +01002658 && (serial->num_ports == 4)) {
Paul B Schroeder3f542972006-08-31 19:41:47 -05002659 mos7840_port->SpRegOffset = 0xc;
2660 mos7840_port->ControlRegOffset = 0xd;
2661 mos7840_port->DcrRegOffset = 0x1c;
2662 }
2663 mos7840_dump_serial_port(mos7840_port);
2664
2665 mos7840_set_port_private(serial->port[i], mos7840_port);
2666
2667 //enable rx_disable bit in control register
2668
2669 status =
2670 mos7840_get_reg_sync(serial->port[i],
2671 mos7840_port->ControlRegOffset, &Data);
2672 if (status < 0) {
2673 dbg("Reading ControlReg failed status-0x%x\n", status);
2674 break;
2675 } else
2676 dbg("ControlReg Reading success val is %x, status%d\n",
2677 Data, status);
2678 Data |= 0x08; //setting driver done bit
2679 Data |= 0x04; //sp1_bit to have cts change reflect in modem status reg
2680
2681 //Data |= 0x20; //rx_disable bit
2682 status = 0;
2683 status =
2684 mos7840_set_reg_sync(serial->port[i],
2685 mos7840_port->ControlRegOffset, Data);
2686 if (status < 0) {
2687 dbg("Writing ControlReg failed(rx_disable) status-0x%x\n", status);
2688 break;
2689 } else
2690 dbg("ControlReg Writing success(rx_disable) status%d\n",
2691 status);
2692
2693 //Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 and 0x24 in DCR3
2694 Data = 0x01;
2695 status = 0;
2696 status =
2697 mos7840_set_reg_sync(serial->port[i],
2698 (__u16) (mos7840_port->DcrRegOffset +
2699 0), Data);
2700 if (status < 0) {
2701 dbg("Writing DCR0 failed status-0x%x\n", status);
2702 break;
2703 } else
2704 dbg("DCR0 Writing success status%d\n", status);
2705
2706 Data = 0x05;
2707 status = 0;
2708 status =
2709 mos7840_set_reg_sync(serial->port[i],
2710 (__u16) (mos7840_port->DcrRegOffset +
2711 1), Data);
2712 if (status < 0) {
2713 dbg("Writing DCR1 failed status-0x%x\n", status);
2714 break;
2715 } else
2716 dbg("DCR1 Writing success status%d\n", status);
2717
2718 Data = 0x24;
2719 status = 0;
2720 status =
2721 mos7840_set_reg_sync(serial->port[i],
2722 (__u16) (mos7840_port->DcrRegOffset +
2723 2), Data);
2724 if (status < 0) {
2725 dbg("Writing DCR2 failed status-0x%x\n", status);
2726 break;
2727 } else
2728 dbg("DCR2 Writing success status%d\n", status);
2729
2730 // write values in clkstart0x0 and clkmulti 0x20
2731 Data = 0x0;
2732 status = 0;
2733 status =
2734 mos7840_set_reg_sync(serial->port[i],
2735 CLK_START_VALUE_REGISTER, Data);
2736 if (status < 0) {
2737 dbg("Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status);
2738 break;
2739 } else
2740 dbg("CLK_START_VALUE_REGISTER Writing success status%d\n", status);
2741
2742 Data = 0x20;
Paul B Schroeder3f542972006-08-31 19:41:47 -05002743 status =
2744 mos7840_set_reg_sync(serial->port[i], CLK_MULTI_REGISTER,
2745 Data);
2746 if (status < 0) {
2747 dbg("Writing CLK_MULTI_REGISTER failed status-0x%x\n",
2748 status);
Oliver Neukum0de9a702007-03-16 20:28:28 +01002749 goto error;
Paul B Schroeder3f542972006-08-31 19:41:47 -05002750 } else
2751 dbg("CLK_MULTI_REGISTER Writing success status%d\n",
2752 status);
2753
2754 //write value 0x0 to scratchpad register
2755 Data = 0x00;
Paul B Schroeder3f542972006-08-31 19:41:47 -05002756 status =
2757 mos7840_set_uart_reg(serial->port[i], SCRATCH_PAD_REGISTER,
2758 Data);
2759 if (status < 0) {
2760 dbg("Writing SCRATCH_PAD_REGISTER failed status-0x%x\n",
2761 status);
2762 break;
2763 } else
2764 dbg("SCRATCH_PAD_REGISTER Writing success status%d\n",
2765 status);
2766
2767 //Zero Length flag register
2768 if ((mos7840_port->port_num != 1)
Oliver Neukum0de9a702007-03-16 20:28:28 +01002769 && (serial->num_ports == 2)) {
Paul B Schroeder3f542972006-08-31 19:41:47 -05002770
2771 Data = 0xff;
2772 status = 0;
2773 status = mos7840_set_reg_sync(serial->port[i],
2774 (__u16) (ZLP_REG1 +
2775 ((__u16)
2776 mos7840_port->
2777 port_num)),
2778 Data);
2779 dbg("ZLIP offset%x\n",
2780 (__u16) (ZLP_REG1 +
2781 ((__u16) mos7840_port->port_num)));
2782 if (status < 0) {
2783 dbg("Writing ZLP_REG%d failed status-0x%x\n",
2784 i + 2, status);
2785 break;
2786 } else
2787 dbg("ZLP_REG%d Writing success status%d\n",
2788 i + 2, status);
2789 } else {
2790 Data = 0xff;
2791 status = 0;
2792 status = mos7840_set_reg_sync(serial->port[i],
2793 (__u16) (ZLP_REG1 +
2794 ((__u16)
2795 mos7840_port->
2796 port_num) -
2797 0x1), Data);
2798 dbg("ZLIP offset%x\n",
2799 (__u16) (ZLP_REG1 +
2800 ((__u16) mos7840_port->port_num) - 0x1));
2801 if (status < 0) {
2802 dbg("Writing ZLP_REG%d failed status-0x%x\n",
2803 i + 1, status);
2804 break;
2805 } else
2806 dbg("ZLP_REG%d Writing success status%d\n",
2807 i + 1, status);
2808
2809 }
Oliver Neukum0de9a702007-03-16 20:28:28 +01002810 mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL);
Paul B Schroeder3f542972006-08-31 19:41:47 -05002811 mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL);
Oliver Neukum0de9a702007-03-16 20:28:28 +01002812 mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
2813 if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf || !mos7840_port->dr) {
2814 status = -ENOMEM;
2815 goto error;
2816 }
Paul B Schroeder3f542972006-08-31 19:41:47 -05002817 }
2818
2819 //Zero Length flag enable
2820 Data = 0x0f;
Paul B Schroeder3f542972006-08-31 19:41:47 -05002821 status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data);
2822 if (status < 0) {
2823 dbg("Writing ZLP_REG5 failed status-0x%x\n", status);
2824 return -1;
2825 } else
2826 dbg("ZLP_REG5 Writing success status%d\n", status);
2827
2828 /* setting configuration feature to one */
2829 usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
Al Viro97c49652006-10-09 20:29:03 +01002830 (__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5 * HZ);
Paul B Schroeder3f542972006-08-31 19:41:47 -05002831 return 0;
Oliver Neukum0de9a702007-03-16 20:28:28 +01002832error:
2833 for (/* nothing */; i >= 0; i--) {
2834 mos7840_port = mos7840_get_port_private(serial->port[i]);
2835
2836 kfree(mos7840_port->dr);
2837 kfree(mos7840_port->ctrl_buf);
2838 usb_free_urb(mos7840_port->control_urb);
2839 kfree(mos7840_port);
2840 serial->port[i] = NULL;
2841 }
2842 return status;
Paul B Schroeder3f542972006-08-31 19:41:47 -05002843}
2844
2845/****************************************************************************
2846 * mos7840_shutdown
2847 * This function is called whenever the device is removed from the usb bus.
2848 ****************************************************************************/
2849
2850static void mos7840_shutdown(struct usb_serial *serial)
2851{
2852 int i;
Oliver Neukum0de9a702007-03-16 20:28:28 +01002853 unsigned long flags;
Paul B Schroeder3f542972006-08-31 19:41:47 -05002854 struct moschip_port *mos7840_port;
2855 dbg("%s \n", " shutdown :entering..........");
2856
2857 if (!serial) {
2858 dbg("%s", "Invalid Handler \n");
2859 return;
2860 }
2861
2862 /* check for the ports to be closed,close the ports and disconnect */
2863
2864 /* free private structure allocated for serial port *
2865 * stop reads and writes on all ports */
2866
2867 for (i = 0; i < serial->num_ports; ++i) {
2868 mos7840_port = mos7840_get_port_private(serial->port[i]);
Oliver Neukum0de9a702007-03-16 20:28:28 +01002869 spin_lock_irqsave(&mos7840_port->pool_lock, flags);
2870 mos7840_port->zombie = 1;
2871 spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
Paul B Schroeder3f542972006-08-31 19:41:47 -05002872 usb_kill_urb(mos7840_port->control_urb);
Oliver Neukum0de9a702007-03-16 20:28:28 +01002873 kfree(mos7840_port->ctrl_buf);
2874 kfree(mos7840_port->dr);
Paul B Schroeder3f542972006-08-31 19:41:47 -05002875 kfree(mos7840_port);
2876 mos7840_set_port_private(serial->port[i], NULL);
2877 }
2878
2879 dbg("%s\n", "Thank u :: ");
2880
2881}
2882
Johannes Hölzld9b1b782006-12-17 21:50:24 +01002883static struct usb_driver io_driver = {
2884 .name = "mos7840",
2885 .probe = usb_serial_probe,
2886 .disconnect = usb_serial_disconnect,
2887 .id_table = moschip_id_table_combined,
2888 .no_dynamic_id = 1,
2889};
2890
Paul B Schroeder3f542972006-08-31 19:41:47 -05002891static struct usb_serial_driver moschip7840_4port_device = {
2892 .driver = {
2893 .owner = THIS_MODULE,
2894 .name = "mos7840",
2895 },
2896 .description = DRIVER_DESC,
Johannes Hölzld9b1b782006-12-17 21:50:24 +01002897 .usb_driver = &io_driver,
Paul B Schroeder3f542972006-08-31 19:41:47 -05002898 .id_table = moschip_port_id_table,
2899 .num_interrupt_in = 1, //NUM_DONT_CARE,//1,
2900#ifdef check
2901 .num_bulk_in = 4,
2902 .num_bulk_out = 4,
2903 .num_ports = 4,
2904#endif
2905 .open = mos7840_open,
2906 .close = mos7840_close,
2907 .write = mos7840_write,
2908 .write_room = mos7840_write_room,
2909 .chars_in_buffer = mos7840_chars_in_buffer,
2910 .throttle = mos7840_throttle,
2911 .unthrottle = mos7840_unthrottle,
2912 .calc_num_ports = mos7840_calc_num_ports,
2913#ifdef MCSSerialProbe
2914 .probe = mos7840_serial_probe,
2915#endif
2916 .ioctl = mos7840_ioctl,
2917 .set_termios = mos7840_set_termios,
2918 .break_ctl = mos7840_break,
2919 .tiocmget = mos7840_tiocmget,
2920 .tiocmset = mos7840_tiocmset,
2921 .attach = mos7840_startup,
2922 .shutdown = mos7840_shutdown,
2923 .read_bulk_callback = mos7840_bulk_in_callback,
2924 .read_int_callback = mos7840_interrupt_callback,
2925};
2926
Paul B Schroeder3f542972006-08-31 19:41:47 -05002927/****************************************************************************
2928 * moschip7840_init
2929 * This is called by the module subsystem, or on startup to initialize us
2930 ****************************************************************************/
2931static int __init moschip7840_init(void)
2932{
2933 int retval;
2934
2935 dbg("%s \n", " mos7840_init :entering..........");
2936
2937 /* Register with the usb serial */
2938 retval = usb_serial_register(&moschip7840_4port_device);
2939
2940 if (retval)
2941 goto failed_port_device_register;
2942
2943 dbg("%s\n", "Entring...");
2944 info(DRIVER_DESC " " DRIVER_VERSION);
2945
2946 /* Register with the usb */
2947 retval = usb_register(&io_driver);
2948
2949 if (retval)
2950 goto failed_usb_register;
2951
2952 if (retval == 0) {
2953 dbg("%s\n", "Leaving...");
2954 return 0;
2955 }
2956
2957 failed_usb_register:
2958 usb_serial_deregister(&moschip7840_4port_device);
2959
2960 failed_port_device_register:
2961
2962 return retval;
2963}
2964
2965/****************************************************************************
2966 * moschip7840_exit
2967 * Called when the driver is about to be unloaded.
2968 ****************************************************************************/
2969static void __exit moschip7840_exit(void)
2970{
2971
2972 dbg("%s \n", " mos7840_exit :entering..........");
2973
2974 usb_deregister(&io_driver);
2975
2976 usb_serial_deregister(&moschip7840_4port_device);
2977
2978 dbg("%s\n", "Entring...");
2979}
2980
2981module_init(moschip7840_init);
2982module_exit(moschip7840_exit);
2983
2984/* Module information */
2985MODULE_DESCRIPTION(DRIVER_DESC);
2986MODULE_LICENSE("GPL");
2987
2988module_param(debug, bool, S_IRUGO | S_IWUSR);
2989MODULE_PARM_DESC(debug, "Debug enabled or not");