diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-07-29 15:28:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-07-29 15:28:49 -0400 |
commit | b7ebbb77f183061eb34dd210372d016c04371c26 (patch) | |
tree | 7f7d3519190ef95d3e3bf82048548e1cd3a6404b | |
parent | 7de8b9261d6abbb2bd71aab6a5ac0981696dcd2c (diff) | |
parent | fb29900217bd89370974870d47cab07bad3e5ac4 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6:
staging: udlfb: Add vmalloc.h include
staging: remove aten2011 driver
Staging: android: lowmemorykiller.c: fix it for "oom: move oom_adj value from task_struct to mm_struct"
Staging: serqt_usb2: fix memory leak in error case
Staging: serqt_usb2: add missing calls to tty_kref_put()
-rw-r--r-- | drivers/staging/Kconfig | 2 | ||||
-rw-r--r-- | drivers/staging/Makefile | 1 | ||||
-rw-r--r-- | drivers/staging/android/lowmemorykiller.c | 8 | ||||
-rw-r--r-- | drivers/staging/serqt_usb2/serqt_usb2.c | 20 | ||||
-rw-r--r-- | drivers/staging/uc2322/Kconfig | 10 | ||||
-rw-r--r-- | drivers/staging/uc2322/Makefile | 1 | ||||
-rw-r--r-- | drivers/staging/uc2322/TODO | 7 | ||||
-rw-r--r-- | drivers/staging/uc2322/aten2011.c | 2430 | ||||
-rw-r--r-- | drivers/staging/udlfb/udlfb.c | 1 |
9 files changed, 20 insertions, 2460 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 348bf61a8fec..975ecddbce30 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig | |||
@@ -103,8 +103,6 @@ source "drivers/staging/pohmelfs/Kconfig" | |||
103 | 103 | ||
104 | source "drivers/staging/stlc45xx/Kconfig" | 104 | source "drivers/staging/stlc45xx/Kconfig" |
105 | 105 | ||
106 | source "drivers/staging/uc2322/Kconfig" | ||
107 | |||
108 | source "drivers/staging/b3dfg/Kconfig" | 106 | source "drivers/staging/b3dfg/Kconfig" |
109 | 107 | ||
110 | source "drivers/staging/phison/Kconfig" | 108 | source "drivers/staging/phison/Kconfig" |
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 8d61d7b4debf..2241ae1b21ee 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile | |||
@@ -34,7 +34,6 @@ obj-$(CONFIG_ANDROID) += android/ | |||
34 | obj-$(CONFIG_DST) += dst/ | 34 | obj-$(CONFIG_DST) += dst/ |
35 | obj-$(CONFIG_POHMELFS) += pohmelfs/ | 35 | obj-$(CONFIG_POHMELFS) += pohmelfs/ |
36 | obj-$(CONFIG_STLC45XX) += stlc45xx/ | 36 | obj-$(CONFIG_STLC45XX) += stlc45xx/ |
37 | obj-$(CONFIG_USB_SERIAL_ATEN2011) += uc2322/ | ||
38 | obj-$(CONFIG_B3DFG) += b3dfg/ | 37 | obj-$(CONFIG_B3DFG) += b3dfg/ |
39 | obj-$(CONFIG_IDE_PHISON) += phison/ | 38 | obj-$(CONFIG_IDE_PHISON) += phison/ |
40 | obj-$(CONFIG_PLAN9AUTH) += p9auth/ | 39 | obj-$(CONFIG_PLAN9AUTH) += p9auth/ |
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index fe72240f5a9e..f934393f3959 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c | |||
@@ -96,19 +96,21 @@ static int lowmem_shrink(int nr_to_scan, gfp_t gfp_mask) | |||
96 | 96 | ||
97 | read_lock(&tasklist_lock); | 97 | read_lock(&tasklist_lock); |
98 | for_each_process(p) { | 98 | for_each_process(p) { |
99 | struct mm_struct *mm; | ||
99 | int oom_adj; | 100 | int oom_adj; |
100 | 101 | ||
101 | task_lock(p); | 102 | task_lock(p); |
102 | if (!p->mm) { | 103 | mm = p->mm; |
104 | if (!mm) { | ||
103 | task_unlock(p); | 105 | task_unlock(p); |
104 | continue; | 106 | continue; |
105 | } | 107 | } |
106 | oom_adj = p->oomkilladj; | 108 | oom_adj = mm->oom_adj; |
107 | if (oom_adj < min_adj) { | 109 | if (oom_adj < min_adj) { |
108 | task_unlock(p); | 110 | task_unlock(p); |
109 | continue; | 111 | continue; |
110 | } | 112 | } |
111 | tasksize = get_mm_rss(p->mm); | 113 | tasksize = get_mm_rss(mm); |
112 | task_unlock(p); | 114 | task_unlock(p); |
113 | if (tasksize <= 0) | 115 | if (tasksize <= 0) |
114 | continue; | 116 | continue; |
diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c index a9bd4106beb7..0fdf8c6dc648 100644 --- a/drivers/staging/serqt_usb2/serqt_usb2.c +++ b/drivers/staging/serqt_usb2/serqt_usb2.c | |||
@@ -360,18 +360,18 @@ static void qt_read_bulk_callback(struct urb *urb) | |||
360 | if (port_paranoia_check(port, __func__) != 0) { | 360 | if (port_paranoia_check(port, __func__) != 0) { |
361 | dbg("%s - port_paranoia_check, exiting\n", __func__); | 361 | dbg("%s - port_paranoia_check, exiting\n", __func__); |
362 | qt_port->ReadBulkStopped = 1; | 362 | qt_port->ReadBulkStopped = 1; |
363 | return; | 363 | goto exit; |
364 | } | 364 | } |
365 | 365 | ||
366 | if (!serial) { | 366 | if (!serial) { |
367 | dbg("%s - bad serial pointer, exiting\n", __func__); | 367 | dbg("%s - bad serial pointer, exiting\n", __func__); |
368 | return; | 368 | goto exit; |
369 | } | 369 | } |
370 | if (qt_port->closePending == 1) { | 370 | if (qt_port->closePending == 1) { |
371 | /* Were closing , stop reading */ | 371 | /* Were closing , stop reading */ |
372 | dbg("%s - (qt_port->closepending == 1\n", __func__); | 372 | dbg("%s - (qt_port->closepending == 1\n", __func__); |
373 | qt_port->ReadBulkStopped = 1; | 373 | qt_port->ReadBulkStopped = 1; |
374 | return; | 374 | goto exit; |
375 | } | 375 | } |
376 | 376 | ||
377 | /* | 377 | /* |
@@ -381,7 +381,7 @@ static void qt_read_bulk_callback(struct urb *urb) | |||
381 | */ | 381 | */ |
382 | if (qt_port->RxHolding == 1) { | 382 | if (qt_port->RxHolding == 1) { |
383 | qt_port->ReadBulkStopped = 1; | 383 | qt_port->ReadBulkStopped = 1; |
384 | return; | 384 | goto exit; |
385 | } | 385 | } |
386 | 386 | ||
387 | if (urb->status) { | 387 | if (urb->status) { |
@@ -389,7 +389,7 @@ static void qt_read_bulk_callback(struct urb *urb) | |||
389 | 389 | ||
390 | dbg("%s - nonzero read bulk status received: %d\n", | 390 | dbg("%s - nonzero read bulk status received: %d\n", |
391 | __func__, urb->status); | 391 | __func__, urb->status); |
392 | return; | 392 | goto exit; |
393 | } | 393 | } |
394 | 394 | ||
395 | if (tty && RxCount) { | 395 | if (tty && RxCount) { |
@@ -463,6 +463,8 @@ static void qt_read_bulk_callback(struct urb *urb) | |||
463 | } | 463 | } |
464 | 464 | ||
465 | schedule_work(&port->work); | 465 | schedule_work(&port->work); |
466 | exit: | ||
467 | tty_kref_put(tty); | ||
466 | } | 468 | } |
467 | 469 | ||
468 | /* | 470 | /* |
@@ -736,6 +738,11 @@ static int qt_startup(struct usb_serial *serial) | |||
736 | if (!qt_port) { | 738 | if (!qt_port) { |
737 | dbg("%s: kmalloc for quatech_port (%d) failed!.", | 739 | dbg("%s: kmalloc for quatech_port (%d) failed!.", |
738 | __func__, i); | 740 | __func__, i); |
741 | for(--i; i >= 0; i--) { | ||
742 | port = serial->port[i]; | ||
743 | kfree(usb_get_serial_port_data(port)); | ||
744 | usb_set_serial_port_data(port, NULL); | ||
745 | } | ||
739 | return -ENOMEM; | 746 | return -ENOMEM; |
740 | } | 747 | } |
741 | spin_lock_init(&qt_port->lock); | 748 | spin_lock_init(&qt_port->lock); |
@@ -1041,7 +1048,7 @@ static void qt_block_until_empty(struct tty_struct *tty, | |||
1041 | } | 1048 | } |
1042 | } | 1049 | } |
1043 | 1050 | ||
1044 | static void qt_close( struct usb_serial_port *port) | 1051 | static void qt_close(struct usb_serial_port *port) |
1045 | { | 1052 | { |
1046 | struct usb_serial *serial = port->serial; | 1053 | struct usb_serial *serial = port->serial; |
1047 | struct quatech_port *qt_port; | 1054 | struct quatech_port *qt_port; |
@@ -1068,6 +1075,7 @@ static void qt_close( struct usb_serial_port *port) | |||
1068 | /* wait up to for transmitter to empty */ | 1075 | /* wait up to for transmitter to empty */ |
1069 | if (serial->dev) | 1076 | if (serial->dev) |
1070 | qt_block_until_empty(tty, qt_port); | 1077 | qt_block_until_empty(tty, qt_port); |
1078 | tty_kref_put(tty); | ||
1071 | 1079 | ||
1072 | /* Close uart channel */ | 1080 | /* Close uart channel */ |
1073 | status = qt_close_channel(serial, index); | 1081 | status = qt_close_channel(serial, index); |
diff --git a/drivers/staging/uc2322/Kconfig b/drivers/staging/uc2322/Kconfig deleted file mode 100644 index 2e0c6e79df2b..000000000000 --- a/drivers/staging/uc2322/Kconfig +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | config USB_SERIAL_ATEN2011 | ||
2 | tristate "ATEN 2011 USB to serial device support" | ||
3 | depends on USB_SERIAL | ||
4 | default N | ||
5 | ---help--- | ||
6 | Say Y here if you want to use a ATEN 2011 dual port USB to serial | ||
7 | adapter. | ||
8 | |||
9 | To compile this driver as a module, choose M here: the module will be | ||
10 | called aten2011. | ||
diff --git a/drivers/staging/uc2322/Makefile b/drivers/staging/uc2322/Makefile deleted file mode 100644 index 49c18d6e579f..000000000000 --- a/drivers/staging/uc2322/Makefile +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | obj-$(CONFIG_USB_SERIAL_ATEN2011) += aten2011.o | ||
diff --git a/drivers/staging/uc2322/TODO b/drivers/staging/uc2322/TODO deleted file mode 100644 index c189a64c4185..000000000000 --- a/drivers/staging/uc2322/TODO +++ /dev/null | |||
@@ -1,7 +0,0 @@ | |||
1 | TODO: | ||
2 | - checkpatch.pl cleanups | ||
3 | - remove dead and useless code (auditing the tty ioctls to | ||
4 | verify that they really are correct and needed.) | ||
5 | |||
6 | Please send any patches to Greg Kroah-Hartman <greg@kroah.com> and | ||
7 | Russell Lang <gsview@ghostgum.com.au>. | ||
diff --git a/drivers/staging/uc2322/aten2011.c b/drivers/staging/uc2322/aten2011.c deleted file mode 100644 index 39d0926d1a90..000000000000 --- a/drivers/staging/uc2322/aten2011.c +++ /dev/null | |||
@@ -1,2430 +0,0 @@ | |||
1 | /* | ||
2 | * Aten 2011 USB serial driver for 4 port devices | ||
3 | * | ||
4 | * Copyright (C) 2000 Inside Out Networks | ||
5 | * Copyright (C) 2001-2002, 2009 Greg Kroah-Hartman <greg@kroah.com> | ||
6 | * Copyright (C) 2009 Novell Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/tty.h> | ||
20 | #include <linux/tty_driver.h> | ||
21 | #include <linux/tty_flip.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/serial.h> | ||
24 | #include <linux/uaccess.h> | ||
25 | #include <linux/usb.h> | ||
26 | #include <linux/usb/serial.h> | ||
27 | |||
28 | |||
29 | #define ZLP_REG1 0x3A /* Zero_Flag_Reg1 58 */ | ||
30 | #define ZLP_REG2 0x3B /* Zero_Flag_Reg2 59 */ | ||
31 | #define ZLP_REG3 0x3C /* Zero_Flag_Reg3 60 */ | ||
32 | #define ZLP_REG4 0x3D /* Zero_Flag_Reg4 61 */ | ||
33 | #define ZLP_REG5 0x3E /* Zero_Flag_Reg5 62 */ | ||
34 | |||
35 | /* Interrupt Rotinue Defines */ | ||
36 | #define SERIAL_IIR_RLS 0x06 | ||
37 | #define SERIAL_IIR_RDA 0x04 | ||
38 | #define SERIAL_IIR_CTI 0x0c | ||
39 | #define SERIAL_IIR_THR 0x02 | ||
40 | #define SERIAL_IIR_MS 0x00 | ||
41 | |||
42 | /* Emulation of the bit mask on the LINE STATUS REGISTER. */ | ||
43 | #define SERIAL_LSR_DR 0x0001 | ||
44 | #define SERIAL_LSR_OE 0x0002 | ||
45 | #define SERIAL_LSR_PE 0x0004 | ||
46 | #define SERIAL_LSR_FE 0x0008 | ||
47 | #define SERIAL_LSR_BI 0x0010 | ||
48 | #define SERIAL_LSR_THRE 0x0020 | ||
49 | #define SERIAL_LSR_TEMT 0x0040 | ||
50 | #define SERIAL_LSR_FIFOERR 0x0080 | ||
51 | |||
52 | /* MSR bit defines(place holders) */ | ||
53 | #define ATEN_MSR_DELTA_CTS 0x10 | ||
54 | #define ATEN_MSR_DELTA_DSR 0x20 | ||
55 | #define ATEN_MSR_DELTA_RI 0x40 | ||
56 | #define ATEN_MSR_DELTA_CD 0x80 | ||
57 | |||
58 | /* Serial Port register Address */ | ||
59 | #define RECEIVE_BUFFER_REGISTER ((__u16)(0x00)) | ||
60 | #define TRANSMIT_HOLDING_REGISTER ((__u16)(0x00)) | ||
61 | #define INTERRUPT_ENABLE_REGISTER ((__u16)(0x01)) | ||
62 | #define INTERRUPT_IDENT_REGISTER ((__u16)(0x02)) | ||
63 | #define FIFO_CONTROL_REGISTER ((__u16)(0x02)) | ||
64 | #define LINE_CONTROL_REGISTER ((__u16)(0x03)) | ||
65 | #define MODEM_CONTROL_REGISTER ((__u16)(0x04)) | ||
66 | #define LINE_STATUS_REGISTER ((__u16)(0x05)) | ||
67 | #define MODEM_STATUS_REGISTER ((__u16)(0x06)) | ||
68 | #define SCRATCH_PAD_REGISTER ((__u16)(0x07)) | ||
69 | #define DIVISOR_LATCH_LSB ((__u16)(0x00)) | ||
70 | #define DIVISOR_LATCH_MSB ((__u16)(0x01)) | ||
71 | |||
72 | #define SP1_REGISTER ((__u16)(0x00)) | ||
73 | #define CONTROL1_REGISTER ((__u16)(0x01)) | ||
74 | #define CLK_MULTI_REGISTER ((__u16)(0x02)) | ||
75 | #define CLK_START_VALUE_REGISTER ((__u16)(0x03)) | ||
76 | #define DCR1_REGISTER ((__u16)(0x04)) | ||
77 | #define GPIO_REGISTER ((__u16)(0x07)) | ||
78 | |||
79 | #define SERIAL_LCR_DLAB ((__u16)(0x0080)) | ||
80 | |||
81 | /* | ||
82 | * URB POOL related defines | ||
83 | */ | ||
84 | #define NUM_URBS 16 /* URB Count */ | ||
85 | #define URB_TRANSFER_BUFFER_SIZE 32 /* URB Size */ | ||
86 | |||
87 | #define USB_VENDOR_ID_ATENINTL 0x0557 | ||
88 | #define ATENINTL_DEVICE_ID_2011 0x2011 | ||
89 | #define ATENINTL_DEVICE_ID_7820 0x7820 | ||
90 | |||
91 | static struct usb_device_id id_table[] = { | ||
92 | { USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_2011) }, | ||
93 | { USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_7820) }, | ||
94 | { } /* terminating entry */ | ||
95 | }; | ||
96 | MODULE_DEVICE_TABLE(usb, id_table); | ||
97 | |||
98 | /* This structure holds all of the local port information */ | ||
99 | struct ATENINTL_port { | ||
100 | int port_num; /*Actual port number in the device(1,2,etc)*/ | ||
101 | __u8 bulk_out_endpoint; /* the bulk out endpoint handle */ | ||
102 | unsigned char *bulk_out_buffer; /* buffer used for the bulk out endpoint */ | ||
103 | struct urb *write_urb; /* write URB for this port */ | ||
104 | __u8 bulk_in_endpoint; /* the bulk in endpoint handle */ | ||
105 | unsigned char *bulk_in_buffer; /* the buffer we use for the bulk in endpoint */ | ||
106 | struct urb *read_urb; /* read URB for this port */ | ||
107 | __u8 shadowLCR; /* last LCR value received */ | ||
108 | __u8 shadowMCR; /* last MCR value received */ | ||
109 | char open; | ||
110 | char chaseResponsePending; | ||
111 | wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */ | ||
112 | wait_queue_head_t wait_command; /* for handling sleeping while waiting for command to finish */ | ||
113 | struct async_icount icount; | ||
114 | struct usb_serial_port *port; /* loop back to the owner of this object */ | ||
115 | /*Offsets*/ | ||
116 | __u8 SpRegOffset; | ||
117 | __u8 ControlRegOffset; | ||
118 | __u8 DcrRegOffset; | ||
119 | /* for processing control URBS in interrupt context */ | ||
120 | struct urb *control_urb; | ||
121 | char *ctrl_buf; | ||
122 | int MsrLsr; | ||
123 | |||
124 | struct urb *write_urb_pool[NUM_URBS]; | ||
125 | /* we pass a pointer to this as the arguement sent to cypress_set_termios old_termios */ | ||
126 | struct ktermios tmp_termios; /* stores the old termios settings */ | ||
127 | spinlock_t lock; /* private lock */ | ||
128 | }; | ||
129 | |||
130 | /* This structure holds all of the individual serial device information */ | ||
131 | struct ATENINTL_serial { | ||
132 | __u8 interrupt_in_endpoint; /* the interrupt endpoint handle */ | ||
133 | unsigned char *interrupt_in_buffer; /* the buffer we use for the interrupt endpoint */ | ||
134 | struct urb *interrupt_read_urb; /* our interrupt urb */ | ||
135 | __u8 bulk_in_endpoint; /* the bulk in endpoint handle */ | ||
136 | unsigned char *bulk_in_buffer; /* the buffer we use for the bulk in endpoint */ | ||
137 | struct urb *read_urb; /* our bulk read urb */ | ||
138 | __u8 bulk_out_endpoint; /* the bulk out endpoint handle */ | ||
139 | struct usb_serial *serial; /* loop back to the owner of this object */ | ||
140 | int ATEN2011_spectrum_2or4ports; /* this says the number of ports in the device */ | ||
141 | /* Indicates about the no.of opened ports of an individual USB-serial adapater. */ | ||
142 | unsigned int NoOfOpenPorts; | ||
143 | /* a flag for Status endpoint polling */ | ||
144 | unsigned char status_polling_started; | ||
145 | }; | ||
146 | |||
147 | static void ATEN2011_set_termios(struct tty_struct *tty, | ||
148 | struct usb_serial_port *port, | ||
149 | struct ktermios *old_termios); | ||
150 | static void ATEN2011_change_port_settings(struct tty_struct *tty, | ||
151 | struct ATENINTL_port *ATEN2011_port, | ||
152 | struct ktermios *old_termios); | ||
153 | |||
154 | /************************************* | ||
155 | * Bit definitions for each register * | ||
156 | *************************************/ | ||
157 | #define LCR_BITS_5 0x00 /* 5 bits/char */ | ||
158 | #define LCR_BITS_6 0x01 /* 6 bits/char */ | ||
159 | #define LCR_BITS_7 0x02 /* 7 bits/char */ | ||
160 | #define LCR_BITS_8 0x03 /* 8 bits/char */ | ||
161 | #define LCR_BITS_MASK 0x03 /* Mask for bits/char field */ | ||
162 | |||
163 | #define LCR_STOP_1 0x00 /* 1 stop bit */ | ||
164 | #define LCR_STOP_1_5 0x04 /* 1.5 stop bits (if 5 bits/char) */ | ||
165 | #define LCR_STOP_2 0x04 /* 2 stop bits (if 6-8 bits/char) */ | ||
166 | #define LCR_STOP_MASK 0x04 /* Mask for stop bits field */ | ||
167 | |||
168 | #define LCR_PAR_NONE 0x00 /* No parity */ | ||
169 | #define LCR_PAR_ODD 0x08 /* Odd parity */ | ||
170 | #define LCR_PAR_EVEN 0x18 /* Even parity */ | ||
171 | #define LCR_PAR_MARK 0x28 /* Force parity bit to 1 */ | ||
172 | #define LCR_PAR_SPACE 0x38 /* Force parity bit to 0 */ | ||
173 | #define LCR_PAR_MASK 0x38 /* Mask for parity field */ | ||
174 | |||
175 | #define LCR_SET_BREAK 0x40 /* Set Break condition */ | ||
176 | #define LCR_DL_ENABLE 0x80 /* Enable access to divisor latch */ | ||
177 | |||
178 | #define MCR_DTR 0x01 /* Assert DTR */ | ||
179 | #define MCR_RTS 0x02 /* Assert RTS */ | ||
180 | #define MCR_OUT1 0x04 /* Loopback only: Sets state of RI */ | ||
181 | #define MCR_MASTER_IE 0x08 /* Enable interrupt outputs */ | ||
182 | #define MCR_LOOPBACK 0x10 /* Set internal (digital) loopback mode */ | ||
183 | #define MCR_XON_ANY 0x20 /* Enable any char to exit XOFF mode */ | ||
184 | |||
185 | #define ATEN2011_MSR_CTS 0x10 /* Current state of CTS */ | ||
186 | #define ATEN2011_MSR_DSR 0x20 /* Current state of DSR */ | ||
187 | #define ATEN2011_MSR_RI 0x40 /* Current state of RI */ | ||
188 | #define ATEN2011_MSR_CD 0x80 /* Current state of CD */ | ||
189 | |||
190 | |||
191 | static int debug; | ||
192 | |||
193 | /* | ||
194 | * Version Information | ||
195 | */ | ||
196 | #define DRIVER_VERSION "2.0" | ||
197 | #define DRIVER_DESC "ATENINTL 2011 USB Serial Adapter" | ||
198 | |||
199 | /* | ||
200 | * Defines used for sending commands to port | ||
201 | */ | ||
202 | |||
203 | #define ATEN_WDR_TIMEOUT (50) /* default urb timeout */ | ||
204 | |||
205 | /* Requests */ | ||
206 | #define ATEN_RD_RTYPE 0xC0 | ||
207 | #define ATEN_WR_RTYPE 0x40 | ||
208 | #define ATEN_RDREQ 0x0D | ||
209 | #define ATEN_WRREQ 0x0E | ||
210 | #define ATEN_CTRL_TIMEOUT 500 | ||
211 | #define VENDOR_READ_LENGTH (0x01) | ||
212 | |||
213 | /* set to 1 for RS485 mode and 0 for RS232 mode */ | ||
214 | /* FIXME make this somehow dynamic and not build time specific */ | ||
215 | static int RS485mode; | ||
216 | |||
217 | static int set_reg_sync(struct usb_serial_port *port, __u16 reg, __u16 val) | ||
218 | { | ||
219 | struct usb_device *dev = port->serial->dev; | ||
220 | val = val & 0x00ff; | ||
221 | |||
222 | dbg("%s: is %x, value %x", __func__, reg, val); | ||
223 | |||
224 | return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ATEN_WRREQ, | ||
225 | ATEN_WR_RTYPE, val, reg, NULL, 0, | ||
226 | ATEN_WDR_TIMEOUT); | ||
227 | } | ||
228 | |||
229 | static int get_reg_sync(struct usb_serial_port *port, __u16 reg, __u16 *val) | ||
230 | { | ||
231 | struct usb_device *dev = port->serial->dev; | ||
232 | int ret; | ||
233 | |||
234 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ATEN_RDREQ, | ||
235 | ATEN_RD_RTYPE, 0, reg, val, VENDOR_READ_LENGTH, | ||
236 | ATEN_WDR_TIMEOUT); | ||
237 | dbg("%s: offset is %x, return val %x", __func__, reg, *val); | ||
238 | *val = (*val) & 0x00ff; | ||
239 | return ret; | ||
240 | } | ||
241 | |||
242 | static int set_uart_reg(struct usb_serial_port *port, __u16 reg, __u16 val) | ||
243 | { | ||
244 | struct usb_device *dev = port->serial->dev; | ||
245 | struct ATENINTL_serial *a_serial; | ||
246 | __u16 minor; | ||
247 | |||
248 | a_serial = usb_get_serial_data(port->serial); | ||
249 | minor = port->serial->minor; | ||
250 | if (minor == SERIAL_TTY_NO_MINOR) | ||
251 | minor = 0; | ||
252 | val = val & 0x00ff; | ||
253 | |||
254 | /* | ||
255 | * For the UART control registers, | ||
256 | * the application number need to be Or'ed | ||
257 | */ | ||
258 | if (a_serial->ATEN2011_spectrum_2or4ports == 4) | ||
259 | val |= (((__u16)port->number - minor) + 1) << 8; | ||
260 | else { | ||
261 | if (((__u16) port->number - minor) == 0) | ||
262 | val |= (((__u16)port->number - minor) + 1) << 8; | ||
263 | else | ||
264 | val |= (((__u16)port->number - minor) + 2) << 8; | ||
265 | } | ||
266 | dbg("%s: application number is %x", __func__, val); | ||
267 | |||
268 | return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ATEN_WRREQ, | ||
269 | ATEN_WR_RTYPE, val, reg, NULL, 0, | ||
270 | ATEN_WDR_TIMEOUT); | ||
271 | } | ||
272 | |||
273 | static int get_uart_reg(struct usb_serial_port *port, __u16 reg, __u16 *val) | ||
274 | { | ||
275 | struct usb_device *dev = port->serial->dev; | ||
276 | int ret = 0; | ||
277 | __u16 wval; | ||
278 | struct ATENINTL_serial *a_serial; | ||
279 | __u16 minor = port->serial->minor; | ||
280 | |||
281 | a_serial = usb_get_serial_data(port->serial); | ||
282 | if (minor == SERIAL_TTY_NO_MINOR) | ||
283 | minor = 0; | ||
284 | |||
285 | /* wval is same as application number */ | ||
286 | if (a_serial->ATEN2011_spectrum_2or4ports == 4) | ||
287 | wval = (((__u16)port->number - minor) + 1) << 8; | ||
288 | else { | ||
289 | if (((__u16) port->number - minor) == 0) | ||
290 | wval = (((__u16) port->number - minor) + 1) << 8; | ||
291 | else | ||
292 | wval = (((__u16) port->number - minor) + 2) << 8; | ||
293 | } | ||
294 | dbg("%s: application number is %x", __func__, wval); | ||
295 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ATEN_RDREQ, | ||
296 | ATEN_RD_RTYPE, wval, reg, val, VENDOR_READ_LENGTH, | ||
297 | ATEN_WDR_TIMEOUT); | ||
298 | *val = (*val) & 0x00ff; | ||
299 | return ret; | ||
300 | } | ||
301 | |||
302 | static int handle_newMsr(struct ATENINTL_port *port, __u8 newMsr) | ||
303 | { | ||
304 | struct ATENINTL_port *ATEN2011_port; | ||
305 | struct async_icount *icount; | ||
306 | ATEN2011_port = port; | ||
307 | icount = &ATEN2011_port->icount; | ||
308 | if (newMsr & | ||
309 | (ATEN_MSR_DELTA_CTS | ATEN_MSR_DELTA_DSR | ATEN_MSR_DELTA_RI | | ||
310 | ATEN_MSR_DELTA_CD)) { | ||
311 | icount = &ATEN2011_port->icount; | ||
312 | |||
313 | /* update input line counters */ | ||
314 | if (newMsr & ATEN_MSR_DELTA_CTS) | ||
315 | icount->cts++; | ||
316 | if (newMsr & ATEN_MSR_DELTA_DSR) | ||
317 | icount->dsr++; | ||
318 | if (newMsr & ATEN_MSR_DELTA_CD) | ||
319 | icount->dcd++; | ||
320 | if (newMsr & ATEN_MSR_DELTA_RI) | ||
321 | icount->rng++; | ||
322 | } | ||
323 | |||
324 | return 0; | ||
325 | } | ||
326 | |||
327 | static int handle_newLsr(struct ATENINTL_port *port, __u8 newLsr) | ||
328 | { | ||
329 | struct async_icount *icount; | ||
330 | |||
331 | dbg("%s - %02x", __func__, newLsr); | ||
332 | |||
333 | if (newLsr & SERIAL_LSR_BI) { | ||
334 | /* | ||
335 | * Parity and Framing errors only count if they occur exclusive | ||
336 | * of a break being received. | ||
337 | */ | ||
338 | newLsr &= (__u8) (SERIAL_LSR_OE | SERIAL_LSR_BI); | ||
339 | } | ||
340 | |||
341 | /* update input line counters */ | ||
342 | icount = &port->icount; | ||
343 | if (newLsr & SERIAL_LSR_BI) | ||
344 | icount->brk++; | ||
345 | if (newLsr & SERIAL_LSR_OE) | ||
346 | icount->overrun++; | ||
347 | if (newLsr & SERIAL_LSR_PE) | ||
348 | icount->parity++; | ||
349 | if (newLsr & SERIAL_LSR_FE) | ||
350 | icount->frame++; | ||
351 | |||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | static void ATEN2011_control_callback(struct urb *urb) | ||
356 | { | ||
357 | unsigned char *data; | ||
358 | struct ATENINTL_port *ATEN2011_port; | ||
359 | __u8 regval = 0x0; | ||
360 | |||
361 | switch (urb->status) { | ||
362 | case 0: | ||
363 | /* success */ | ||
364 | break; | ||
365 | case -ECONNRESET: | ||
366 | case -ENOENT: | ||
367 | case -ESHUTDOWN: | ||
368 | /* this urb is terminated, clean up */ | ||
369 | dbg("%s - urb shutting down with status: %d", __func__, | ||
370 | urb->status); | ||
371 | return; | ||
372 | default: | ||
373 | dbg("%s - nonzero urb status received: %d", __func__, | ||
374 | urb->status); | ||
375 | goto exit; | ||
376 | } | ||
377 | |||
378 | ATEN2011_port = (struct ATENINTL_port *)urb->context; | ||
379 | |||
380 | dbg("%s urb buffer size is %d", __func__, urb->actual_length); | ||
381 | dbg("%s ATEN2011_port->MsrLsr is %d port %d", __func__, | ||
382 | ATEN2011_port->MsrLsr, ATEN2011_port->port_num); | ||
383 | data = urb->transfer_buffer; | ||
384 | regval = (__u8) data[0]; | ||
385 | dbg("%s data is %x", __func__, regval); | ||
386 | if (ATEN2011_port->MsrLsr == 0) | ||
387 | handle_newMsr(ATEN2011_port, regval); | ||
388 | else if (ATEN2011_port->MsrLsr == 1) | ||
389 | handle_newLsr(ATEN2011_port, regval); | ||
390 | |||
391 | exit: | ||
392 | return; | ||
393 | } | ||
394 | |||
395 | static int ATEN2011_get_reg(struct ATENINTL_port *ATEN, __u16 Wval, __u16 reg, | ||
396 | __u16 *val) | ||
397 | { | ||
398 | struct usb_device *dev = ATEN->port->serial->dev; | ||
399 | struct usb_ctrlrequest *dr = NULL; | ||
400 | unsigned char *buffer = NULL; | ||
401 | int ret = 0; | ||
402 | buffer = (__u8 *) ATEN->ctrl_buf; | ||
403 | |||
404 | dr = (void *)(buffer + 2); | ||
405 | dr->bRequestType = ATEN_RD_RTYPE; | ||
406 | dr->bRequest = ATEN_RDREQ; | ||
407 | dr->wValue = cpu_to_le16(Wval); | ||
408 | dr->wIndex = cpu_to_le16(reg); | ||
409 | dr->wLength = cpu_to_le16(2); | ||
410 | |||
411 | usb_fill_control_urb(ATEN->control_urb, dev, usb_rcvctrlpipe(dev, 0), | ||
412 | (unsigned char *)dr, buffer, 2, | ||
413 | ATEN2011_control_callback, ATEN); | ||
414 | ATEN->control_urb->transfer_buffer_length = 2; | ||
415 | ret = usb_submit_urb(ATEN->control_urb, GFP_ATOMIC); | ||
416 | return ret; | ||
417 | } | ||
418 | |||
419 | static void ATEN2011_interrupt_callback(struct urb *urb) | ||
420 | { | ||
421 | int result; | ||
422 | int length; | ||
423 | struct ATENINTL_port *ATEN2011_port; | ||
424 | struct ATENINTL_serial *ATEN2011_serial; | ||
425 | struct usb_serial *serial; | ||
426 | __u16 Data; | ||
427 | unsigned char *data; | ||
428 | __u8 sp[5], st; | ||
429 | int i; | ||
430 | __u16 wval; | ||
431 | int minor; | ||
432 | |||
433 | dbg("%s", " : Entering"); | ||
434 | |||
435 | ATEN2011_serial = (struct ATENINTL_serial *)urb->context; | ||
436 | |||
437 | switch (urb->status) { | ||
438 | case 0: | ||
439 | /* success */ | ||
440 | break; | ||
441 | case -ECONNRESET: | ||
442 | case -ENOENT: | ||
443 | case -ESHUTDOWN: | ||
444 | /* this urb is terminated, clean up */ | ||
445 | dbg("%s - urb shutting down with status: %d", __func__, | ||
446 | urb->status); | ||
447 | return; | ||
448 | default: | ||
449 | dbg("%s - nonzero urb status received: %d", __func__, | ||
450 | urb->status); | ||
451 | goto exit; | ||
452 | } | ||
453 | length = urb->actual_length; | ||
454 | data = urb->transfer_buffer; | ||
455 | |||
456 | serial = ATEN2011_serial->serial; | ||
457 | |||
458 | /* ATENINTL get 5 bytes | ||
459 | * Byte 1 IIR Port 1 (port.number is 0) | ||
460 | * Byte 2 IIR Port 2 (port.number is 1) | ||
461 | * Byte 3 IIR Port 3 (port.number is 2) | ||
462 | * Byte 4 IIR Port 4 (port.number is 3) | ||
463 | * Byte 5 FIFO status for both */ | ||
464 | |||
465 | if (length && length > 5) { | ||
466 | dbg("%s", "Wrong data !!!"); | ||
467 | return; | ||
468 | } | ||
469 | |||
470 | /* MATRIX */ | ||
471 | if (ATEN2011_serial->ATEN2011_spectrum_2or4ports == 4) { | ||
472 | sp[0] = (__u8) data[0]; | ||
473 | sp[1] = (__u8) data[1]; | ||
474 | sp[2] = (__u8) data[2]; | ||
475 | sp[3] = (__u8) data[3]; | ||
476 | st = (__u8) data[4]; | ||
477 | } else { | ||
478 | sp[0] = (__u8) data[0]; | ||
479 | sp[1] = (__u8) data[2]; | ||
480 | /* sp[2]=(__u8)data[2]; */ | ||
481 | /* sp[3]=(__u8)data[3]; */ | ||
482 | st = (__u8) data[4]; | ||
483 | |||
484 | } | ||
485 | for (i = 0; i < serial->num_ports; i++) { | ||
486 | ATEN2011_port = usb_get_serial_port_data(serial->port[i]); | ||
487 | minor = serial->minor; | ||
488 | if (minor == SERIAL_TTY_NO_MINOR) | ||
489 | minor = 0; | ||
490 | if ((ATEN2011_serial->ATEN2011_spectrum_2or4ports == 2) | ||
491 | && (i != 0)) | ||
492 | wval = | ||
493 | (((__u16) serial->port[i]->number - | ||
494 | (__u16) (minor)) + 2) << 8; | ||
495 | else | ||
496 | wval = | ||
497 | (((__u16) serial->port[i]->number - | ||
498 | (__u16) (minor)) + 1) << 8; | ||
499 | if (ATEN2011_port->open != 0) { | ||
500 | if (sp[i] & 0x01) { | ||
501 | dbg("SP%d No Interrupt !!!", i); | ||
502 | } else { | ||
503 | switch (sp[i] & 0x0f) { | ||
504 | case SERIAL_IIR_RLS: | ||
505 | dbg("Serial Port %d: Receiver status error or address bit detected in 9-bit mode", i); | ||
506 | ATEN2011_port->MsrLsr = 1; | ||
507 | ATEN2011_get_reg(ATEN2011_port, wval, | ||
508 | LINE_STATUS_REGISTER, | ||
509 | &Data); | ||
510 | break; | ||
511 | case SERIAL_IIR_MS: | ||
512 | dbg("Serial Port %d: Modem status change", i); | ||
513 | ATEN2011_port->MsrLsr = 0; | ||
514 | ATEN2011_get_reg(ATEN2011_port, wval, | ||
515 | MODEM_STATUS_REGISTER, | ||
516 | &Data); | ||
517 | break; | ||
518 | } | ||
519 | } | ||
520 | } | ||
521 | |||
522 | } | ||
523 | exit: | ||
524 | if (ATEN2011_serial->status_polling_started == 0) | ||
525 | return; | ||
526 | |||
527 | result = usb_submit_urb(urb, GFP_ATOMIC); | ||
528 | if (result) { | ||
529 | dev_err(&urb->dev->dev, | ||
530 | "%s - Error %d submitting interrupt urb\n", | ||
531 | __func__, result); | ||
532 | } | ||
533 | |||
534 | return; | ||
535 | } | ||
536 | |||
537 | static void ATEN2011_bulk_in_callback(struct urb *urb) | ||
538 | { | ||
539 | int status; | ||
540 | unsigned char *data; | ||
541 | struct usb_serial *serial; | ||
542 | struct usb_serial_port *port; | ||
543 | struct ATENINTL_serial *ATEN2011_serial; | ||
544 | struct ATENINTL_port *ATEN2011_port; | ||
545 | struct tty_struct *tty; | ||
546 | |||
547 | if (urb->status) { | ||
548 | dbg("nonzero read bulk status received: %d", urb->status); | ||
549 | return; | ||
550 | } | ||
551 | |||
552 | ATEN2011_port = (struct ATENINTL_port *)urb->context; | ||
553 | |||
554 | port = (struct usb_serial_port *)ATEN2011_port->port; | ||
555 | serial = port->serial; | ||
556 | |||
557 | dbg("%s", "Entering..."); | ||
558 | |||
559 | data = urb->transfer_buffer; | ||
560 | ATEN2011_serial = usb_get_serial_data(serial); | ||
561 | |||
562 | if (urb->actual_length) { | ||
563 | tty = tty_port_tty_get(&ATEN2011_port->port->port); | ||
564 | if (tty) { | ||
565 | tty_buffer_request_room(tty, urb->actual_length); | ||
566 | tty_insert_flip_string(tty, data, urb->actual_length); | ||
567 | tty_flip_buffer_push(tty); | ||
568 | tty_kref_put(tty); | ||
569 | } | ||
570 | |||
571 | ATEN2011_port->icount.rx += urb->actual_length; | ||
572 | dbg("ATEN2011_port->icount.rx is %d:", | ||
573 | ATEN2011_port->icount.rx); | ||
574 | } | ||
575 | |||
576 | if (!ATEN2011_port->read_urb) { | ||
577 | dbg("%s", "URB KILLED !!!"); | ||
578 | return; | ||
579 | } | ||
580 | |||
581 | if (ATEN2011_port->read_urb->status != -EINPROGRESS) { | ||
582 | ATEN2011_port->read_urb->dev = serial->dev; | ||
583 | |||
584 | status = usb_submit_urb(ATEN2011_port->read_urb, GFP_ATOMIC); | ||
585 | if (status) | ||
586 | dbg("usb_submit_urb(read bulk) failed, status = %d", status); | ||
587 | } | ||
588 | } | ||
589 | |||
590 | static void ATEN2011_bulk_out_data_callback(struct urb *urb) | ||
591 | { | ||
592 | struct ATENINTL_port *ATEN2011_port; | ||
593 | struct tty_struct *tty; | ||
594 | |||
595 | if (urb->status) { | ||
596 | dbg("nonzero write bulk status received:%d", urb->status); | ||
597 | return; | ||
598 | } | ||
599 | |||
600 | ATEN2011_port = (struct ATENINTL_port *)urb->context; | ||
601 | |||
602 | dbg("%s", "Entering ........."); | ||
603 | |||
604 | tty = tty_port_tty_get(&ATEN2011_port->port->port); | ||
605 | |||
606 | if (tty && ATEN2011_port->open) | ||
607 | /* tell the tty driver that something has changed */ | ||
608 | tty_wakeup(tty); | ||
609 | |||
610 | /* schedule_work(&ATEN2011_port->port->work); */ | ||
611 | tty_kref_put(tty); | ||
612 | |||
613 | } | ||
614 | |||
615 | #ifdef ATENSerialProbe | ||
616 | static int ATEN2011_serial_probe(struct usb_serial *serial, | ||
617 | const struct usb_device_id *id) | ||
618 | { | ||
619 | |||
620 | /*need to implement the mode_reg reading and updating\ | ||
621 | structures usb_serial_ device_type\ | ||
622 | (i.e num_ports, num_bulkin,bulkout etc) */ | ||
623 | /* Also we can update the changes attach */ | ||
624 | return 1; | ||
625 | } | ||
626 | #endif | ||
627 | |||
628 | static int ATEN2011_open(struct tty_struct *tty, struct usb_serial_port *port, | ||
629 | struct file *filp) | ||
630 | { | ||
631 | int response; | ||
632 | int j; | ||
633 | struct usb_serial *serial; | ||
634 | struct urb *urb; | ||
635 | __u16 Data; | ||
636 | int status; | ||
637 | struct ATENINTL_serial *ATEN2011_serial; | ||
638 | struct ATENINTL_port *ATEN2011_port; | ||
639 | struct ktermios tmp_termios; | ||
640 | int minor; | ||
641 | |||
642 | serial = port->serial; | ||
643 | |||
644 | ATEN2011_port = usb_get_serial_port_data(port); | ||
645 | |||
646 | if (ATEN2011_port == NULL) | ||
647 | return -ENODEV; | ||
648 | |||
649 | ATEN2011_serial = usb_get_serial_data(serial); | ||
650 | if (ATEN2011_serial == NULL) | ||
651 | return -ENODEV; | ||
652 | |||
653 | /* increment the number of opened ports counter here */ | ||
654 | ATEN2011_serial->NoOfOpenPorts++; | ||
655 | |||
656 | usb_clear_halt(serial->dev, port->write_urb->pipe); | ||
657 | usb_clear_halt(serial->dev, port->read_urb->pipe); | ||
658 | |||
659 | /* Initialising the write urb pool */ | ||
660 | for (j = 0; j < NUM_URBS; ++j) { | ||
661 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
662 | ATEN2011_port->write_urb_pool[j] = urb; | ||
663 | |||
664 | if (urb == NULL) { | ||
665 | err("No more urbs???"); | ||
666 | continue; | ||
667 | } | ||
668 | |||
669 | urb->transfer_buffer = NULL; | ||
670 | urb->transfer_buffer = | ||
671 | kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); | ||
672 | if (!urb->transfer_buffer) { | ||
673 | err("%s-out of memory for urb buffers.", __func__); | ||
674 | continue; | ||
675 | } | ||
676 | } | ||
677 | |||
678 | /***************************************************************************** | ||
679 | * Initialize ATEN2011 -- Write Init values to corresponding Registers | ||
680 | * | ||
681 | * Register Index | ||
682 | * 1 : IER | ||
683 | * 2 : FCR | ||
684 | * 3 : LCR | ||
685 | * 4 : MCR | ||
686 | * | ||
687 | * 0x08 : SP1/2 Control Reg | ||
688 | *****************************************************************************/ | ||
689 | |||
690 | /* NEED to check the fallowing Block */ | ||
691 | |||
692 | Data = 0x0; | ||
693 | status = get_reg_sync(port, ATEN2011_port->SpRegOffset, &Data); | ||
694 | if (status < 0) { | ||
695 | dbg("Reading Spreg failed"); | ||
696 | return -1; | ||
697 | } | ||
698 | Data |= 0x80; | ||
699 | status = set_reg_sync(port, ATEN2011_port->SpRegOffset, Data); | ||
700 | if (status < 0) { | ||
701 | dbg("writing Spreg failed"); | ||
702 | return -1; | ||
703 | } | ||
704 | |||
705 | Data &= ~0x80; | ||
706 | status = set_reg_sync(port, ATEN2011_port->SpRegOffset, Data); | ||
707 | if (status < 0) { | ||
708 | dbg("writing Spreg failed"); | ||
709 | return -1; | ||
710 | } | ||
711 | |||
712 | /* End of block to be checked */ | ||
713 | /**************************CHECK***************************/ | ||
714 | |||
715 | if (RS485mode == 0) | ||
716 | Data = 0xC0; | ||
717 | else | ||
718 | Data = 0x00; | ||
719 | status = set_uart_reg(port, SCRATCH_PAD_REGISTER, Data); | ||
720 | if (status < 0) { | ||
721 | dbg("Writing SCRATCH_PAD_REGISTER failed status-0x%x", status); | ||
722 | return -1; | ||
723 | } else | ||
724 | dbg("SCRATCH_PAD_REGISTER Writing success status%d", status); | ||
725 | |||
726 | /**************************CHECK***************************/ | ||
727 | |||
728 | Data = 0x0; | ||
729 | status = get_reg_sync(port, ATEN2011_port->ControlRegOffset, &Data); | ||
730 | if (status < 0) { | ||
731 | dbg("Reading Controlreg failed"); | ||
732 | return -1; | ||
733 | } | ||
734 | Data |= 0x08; /* Driver done bit */ | ||
735 | Data |= 0x20; /* rx_disable */ | ||
736 | status = 0; | ||
737 | status = | ||
738 | set_reg_sync(port, ATEN2011_port->ControlRegOffset, Data); | ||
739 | if (status < 0) { | ||
740 | dbg("writing Controlreg failed"); | ||
741 | return -1; | ||
742 | } | ||
743 | /* | ||
744 | * do register settings here | ||
745 | * Set all regs to the device default values. | ||
746 | * First Disable all interrupts. | ||
747 | */ | ||
748 | |||
749 | Data = 0x00; | ||
750 | status = set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); | ||
751 | if (status < 0) { | ||
752 | dbg("disableing interrupts failed"); | ||
753 | return -1; | ||
754 | } | ||
755 | /* Set FIFO_CONTROL_REGISTER to the default value */ | ||
756 | Data = 0x00; | ||
757 | status = set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); | ||
758 | if (status < 0) { | ||
759 | dbg("Writing FIFO_CONTROL_REGISTER failed"); | ||
760 | return -1; | ||
761 | } | ||
762 | |||
763 | Data = 0xcf; /* chk */ | ||
764 | status = set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); | ||
765 | if (status < 0) { | ||
766 | dbg("Writing FIFO_CONTROL_REGISTER failed"); | ||
767 | return -1; | ||
768 | } | ||
769 | |||
770 | Data = 0x03; /* LCR_BITS_8 */ | ||
771 | status = set_uart_reg(port, LINE_CONTROL_REGISTER, Data); | ||
772 | ATEN2011_port->shadowLCR = Data; | ||
773 | |||
774 | Data = 0x0b; /* MCR_DTR|MCR_RTS|MCR_MASTER_IE */ | ||
775 | status = set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); | ||
776 | ATEN2011_port->shadowMCR = Data; | ||
777 | |||
778 | #ifdef Check | ||
779 | Data = 0x00; | ||
780 | status = get_uart_reg(port, LINE_CONTROL_REGISTER, &Data); | ||
781 | ATEN2011_port->shadowLCR = Data; | ||
782 | |||
783 | Data |= SERIAL_LCR_DLAB; /* data latch enable in LCR 0x80 */ | ||
784 | status = set_uart_reg(port, LINE_CONTROL_REGISTER, Data); | ||
785 | |||
786 | Data = 0x0c; | ||
787 | status = set_uart_reg(port, DIVISOR_LATCH_LSB, Data); | ||
788 | |||
789 | Data = 0x0; | ||
790 | status = set_uart_reg(port, DIVISOR_LATCH_MSB, Data); | ||
791 | |||
792 | Data = 0x00; | ||
793 | status = get_uart_reg(port, LINE_CONTROL_REGISTER, &Data); | ||
794 | |||
795 | /* Data = ATEN2011_port->shadowLCR; */ /* data latch disable */ | ||
796 | Data = Data & ~SERIAL_LCR_DLAB; | ||
797 | status = set_uart_reg(port, LINE_CONTROL_REGISTER, Data); | ||
798 | ATEN2011_port->shadowLCR = Data; | ||
799 | #endif | ||
800 | /* clearing Bulkin and Bulkout Fifo */ | ||
801 | Data = 0x0; | ||
802 | status = get_reg_sync(port, ATEN2011_port->SpRegOffset, &Data); | ||
803 | |||
804 | Data = Data | 0x0c; | ||
805 | status = set_reg_sync(port, ATEN2011_port->SpRegOffset, Data); | ||
806 | |||
807 | Data = Data & ~0x0c; | ||
808 | status = set_reg_sync(port, ATEN2011_port->SpRegOffset, Data); | ||
809 | /* Finally enable all interrupts */ | ||
810 | Data = 0x0; | ||
811 | Data = 0x0c; | ||
812 | status = set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); | ||
813 | |||
814 | /* clearing rx_disable */ | ||
815 | Data = 0x0; | ||
816 | status = get_reg_sync(port, ATEN2011_port->ControlRegOffset, &Data); | ||
817 | Data = Data & ~0x20; | ||
818 | status = set_reg_sync(port, ATEN2011_port->ControlRegOffset, Data); | ||
819 | |||
820 | /* rx_negate */ | ||
821 | Data = 0x0; | ||
822 | status = get_reg_sync(port, ATEN2011_port->ControlRegOffset, &Data); | ||
823 | Data = Data | 0x10; | ||
824 | status = 0; | ||
825 | status = set_reg_sync(port, ATEN2011_port->ControlRegOffset, Data); | ||
826 | |||
827 | /* | ||
828 | * Check to see if we've set up our endpoint info yet | ||
829 | * (can't set it up in ATEN2011_startup as the structures | ||
830 | * were not set up at that time.) | ||
831 | */ | ||
832 | if (ATEN2011_serial->NoOfOpenPorts == 1) { | ||
833 | /* start the status polling here */ | ||
834 | ATEN2011_serial->status_polling_started = 1; | ||
835 | /* If not yet set, Set here */ | ||
836 | ATEN2011_serial->interrupt_in_buffer = | ||
837 | serial->port[0]->interrupt_in_buffer; | ||
838 | ATEN2011_serial->interrupt_in_endpoint = | ||
839 | serial->port[0]->interrupt_in_endpointAddress; | ||
840 | ATEN2011_serial->interrupt_read_urb = | ||
841 | serial->port[0]->interrupt_in_urb; | ||
842 | |||
843 | /* set up interrupt urb */ | ||
844 | usb_fill_int_urb(ATEN2011_serial->interrupt_read_urb, | ||
845 | serial->dev, | ||
846 | usb_rcvintpipe(serial->dev, | ||
847 | ATEN2011_serial-> | ||
848 | interrupt_in_endpoint), | ||
849 | ATEN2011_serial->interrupt_in_buffer, | ||
850 | ATEN2011_serial->interrupt_read_urb-> | ||
851 | transfer_buffer_length, | ||
852 | ATEN2011_interrupt_callback, ATEN2011_serial, | ||
853 | ATEN2011_serial->interrupt_read_urb->interval); | ||
854 | |||
855 | /* start interrupt read for ATEN2011 * | ||
856 | * will continue as long as ATEN2011 is connected */ | ||
857 | |||
858 | response = | ||
859 | usb_submit_urb(ATEN2011_serial->interrupt_read_urb, | ||
860 | GFP_KERNEL); | ||
861 | if (response) { | ||
862 | dbg("%s - Error %d submitting interrupt urb", | ||
863 | __func__, response); | ||
864 | } | ||
865 | |||
866 | } | ||
867 | |||
868 | /* | ||
869 | * See if we've set up our endpoint info yet | ||
870 | * (can't set it up in ATEN2011_startup as the | ||
871 | * structures were not set up at that time.) | ||
872 | */ | ||
873 | |||
874 | dbg("port number is %d", port->number); | ||
875 | dbg("serial number is %d", port->serial->minor); | ||
876 | dbg("Bulkin endpoint is %d", port->bulk_in_endpointAddress); | ||
877 | dbg("BulkOut endpoint is %d", port->bulk_out_endpointAddress); | ||
878 | dbg("Interrupt endpoint is %d", | ||
879 | port->interrupt_in_endpointAddress); | ||
880 | dbg("port's number in the device is %d", ATEN2011_port->port_num); | ||
881 | ATEN2011_port->bulk_in_buffer = port->bulk_in_buffer; | ||
882 | ATEN2011_port->bulk_in_endpoint = port->bulk_in_endpointAddress; | ||
883 | ATEN2011_port->read_urb = port->read_urb; | ||
884 | ATEN2011_port->bulk_out_endpoint = port->bulk_out_endpointAddress; | ||
885 | |||
886 | minor = port->serial->minor; | ||
887 | if (minor == SERIAL_TTY_NO_MINOR) | ||
888 | minor = 0; | ||
889 | |||
890 | /* set up our bulk in urb */ | ||
891 | if ((ATEN2011_serial->ATEN2011_spectrum_2or4ports == 2) | ||
892 | && (((__u16) port->number - (__u16) (minor)) != 0)) { | ||
893 | usb_fill_bulk_urb(ATEN2011_port->read_urb, serial->dev, | ||
894 | usb_rcvbulkpipe(serial->dev, | ||
895 | (port-> | ||
896 | bulk_in_endpointAddress + | ||
897 | 2)), port->bulk_in_buffer, | ||
898 | ATEN2011_port->read_urb-> | ||
899 | transfer_buffer_length, | ||
900 | ATEN2011_bulk_in_callback, ATEN2011_port); | ||
901 | } else | ||
902 | usb_fill_bulk_urb(ATEN2011_port->read_urb, | ||
903 | serial->dev, | ||
904 | usb_rcvbulkpipe(serial->dev, | ||
905 | port-> | ||
906 | bulk_in_endpointAddress), | ||
907 | port->bulk_in_buffer, | ||
908 | ATEN2011_port->read_urb-> | ||
909 | transfer_buffer_length, | ||
910 | ATEN2011_bulk_in_callback, ATEN2011_port); | ||
911 | |||
912 | dbg("ATEN2011_open: bulkin endpoint is %d", | ||
913 | port->bulk_in_endpointAddress); | ||
914 | response = usb_submit_urb(ATEN2011_port->read_urb, GFP_KERNEL); | ||
915 | if (response) { | ||
916 | err("%s - Error %d submitting control urb", __func__, | ||
917 | response); | ||
918 | } | ||
919 | |||
920 | /* initialize our wait queues */ | ||
921 | init_waitqueue_head(&ATEN2011_port->wait_chase); | ||
922 | init_waitqueue_head(&ATEN2011_port->wait_command); | ||
923 | |||
924 | /* initialize our icount structure */ | ||
925 | memset(&(ATEN2011_port->icount), 0x00, sizeof(ATEN2011_port->icount)); | ||
926 | |||
927 | /* initialize our port settings */ | ||
928 | ATEN2011_port->shadowMCR = MCR_MASTER_IE; /* Must set to enable ints! */ | ||
929 | ATEN2011_port->chaseResponsePending = 0; | ||
930 | /* send a open port command */ | ||
931 | ATEN2011_port->open = 1; | ||
932 | /* ATEN2011_change_port_settings(ATEN2011_port,old_termios); */ | ||
933 | /* Setup termios */ | ||
934 | ATEN2011_set_termios(tty, port, &tmp_termios); | ||
935 | ATEN2011_port->icount.tx = 0; | ||
936 | ATEN2011_port->icount.rx = 0; | ||
937 | |||
938 | dbg("usb_serial serial:%x ATEN2011_port:%x\nATEN2011_serial:%x usb_serial_port port:%x", | ||
939 | (unsigned int)serial, (unsigned int)ATEN2011_port, | ||
940 | (unsigned int)ATEN2011_serial, (unsigned int)port); | ||
941 | |||
942 | return 0; | ||
943 | |||
944 | } | ||
945 | |||
946 | static int ATEN2011_chars_in_buffer(struct tty_struct *tty) | ||
947 | { | ||
948 | struct usb_serial_port *port = tty->driver_data; | ||
949 | int i; | ||
950 | int chars = 0; | ||
951 | struct ATENINTL_port *ATEN2011_port; | ||
952 | |||
953 | /* dbg("%s"," ATEN2011_chars_in_buffer:entering ..........."); */ | ||
954 | |||
955 | ATEN2011_port = usb_get_serial_port_data(port); | ||
956 | if (ATEN2011_port == NULL) { | ||
957 | dbg("%s", "ATEN2011_break:leaving ..........."); | ||
958 | return -1; | ||
959 | } | ||
960 | |||
961 | for (i = 0; i < NUM_URBS; ++i) | ||
962 | if (ATEN2011_port->write_urb_pool[i]->status == -EINPROGRESS) | ||
963 | chars += URB_TRANSFER_BUFFER_SIZE; | ||
964 | |||
965 | dbg("%s - returns %d", __func__, chars); | ||
966 | return chars; | ||
967 | |||
968 | } | ||
969 | |||
970 | static void ATEN2011_block_until_tx_empty(struct tty_struct *tty, | ||
971 | struct ATENINTL_port *ATEN2011_port) | ||
972 | { | ||
973 | int timeout = HZ / 10; | ||
974 | int wait = 30; | ||
975 | int count; | ||
976 | |||
977 | while (1) { | ||
978 | count = ATEN2011_chars_in_buffer(tty); | ||
979 | |||
980 | /* Check for Buffer status */ | ||
981 | if (count <= 0) | ||
982 | return; | ||
983 | |||
984 | /* Block the thread for a while */ | ||
985 | interruptible_sleep_on_timeout(&ATEN2011_port->wait_chase, | ||
986 | timeout); | ||
987 | |||
988 | /* No activity.. count down section */ | ||
989 | wait--; | ||
990 | if (wait == 0) { | ||
991 | dbg("%s - TIMEOUT", __func__); | ||
992 | return; | ||
993 | } else { | ||
994 | /* Reset timout value back to seconds */ | ||
995 | wait = 30; | ||
996 | } | ||
997 | } | ||
998 | } | ||
999 | |||
1000 | static void ATEN2011_close(struct tty_struct *tty, struct usb_serial_port *port, | ||
1001 | struct file *filp) | ||
1002 | { | ||
1003 | struct usb_serial *serial; | ||
1004 | struct ATENINTL_serial *ATEN2011_serial; | ||
1005 | struct ATENINTL_port *ATEN2011_port; | ||
1006 | int no_urbs; | ||
1007 | __u16 Data; | ||
1008 | |||
1009 | dbg("%s", "ATEN2011_close:entering..."); | ||
1010 | serial = port->serial; | ||
1011 | |||
1012 | /* take the Adpater and port's private data */ | ||
1013 | ATEN2011_serial = usb_get_serial_data(serial); | ||
1014 | ATEN2011_port = usb_get_serial_port_data(port); | ||
1015 | if ((ATEN2011_serial == NULL) || (ATEN2011_port == NULL)) | ||
1016 | return; | ||
1017 | |||
1018 | if (serial->dev) { | ||
1019 | /* flush and block(wait) until tx is empty */ | ||
1020 | ATEN2011_block_until_tx_empty(tty, ATEN2011_port); | ||
1021 | } | ||
1022 | /* kill the ports URB's */ | ||
1023 | for (no_urbs = 0; no_urbs < NUM_URBS; no_urbs++) | ||
1024 | usb_kill_urb(ATEN2011_port->write_urb_pool[no_urbs]); | ||
1025 | /* Freeing Write URBs */ | ||
1026 | for (no_urbs = 0; no_urbs < NUM_URBS; ++no_urbs) { | ||
1027 | kfree(ATEN2011_port->write_urb_pool[no_urbs]->transfer_buffer); | ||
1028 | usb_free_urb(ATEN2011_port->write_urb_pool[no_urbs]); | ||
1029 | } | ||
1030 | /* While closing port, shutdown all bulk read, write * | ||
1031 | * and interrupt read if they exists */ | ||
1032 | if (serial->dev) { | ||
1033 | if (ATEN2011_port->write_urb) { | ||
1034 | dbg("%s", "Shutdown bulk write"); | ||
1035 | usb_kill_urb(ATEN2011_port->write_urb); | ||
1036 | } | ||
1037 | if (ATEN2011_port->read_urb) { | ||
1038 | dbg("%s", "Shutdown bulk read"); | ||
1039 | usb_kill_urb(ATEN2011_port->read_urb); | ||
1040 | } | ||
1041 | if ((&ATEN2011_port->control_urb)) { | ||
1042 | dbg("%s", "Shutdown control read"); | ||
1043 | /* usb_kill_urb (ATEN2011_port->control_urb); */ | ||
1044 | |||
1045 | } | ||
1046 | } | ||
1047 | /* if(ATEN2011_port->ctrl_buf != NULL) */ | ||
1048 | /* kfree(ATEN2011_port->ctrl_buf); */ | ||
1049 | /* decrement the no.of open ports counter of an individual USB-serial adapter. */ | ||
1050 | ATEN2011_serial->NoOfOpenPorts--; | ||
1051 | dbg("NoOfOpenPorts in close%d:in port%d", | ||
1052 | ATEN2011_serial->NoOfOpenPorts, port->number); | ||
1053 | if (ATEN2011_serial->NoOfOpenPorts == 0) { | ||
1054 | /* stop the stus polling here */ | ||
1055 | ATEN2011_serial->status_polling_started = 0; | ||
1056 | if (ATEN2011_serial->interrupt_read_urb) { | ||
1057 | dbg("%s", "Shutdown interrupt_read_urb"); | ||
1058 | /* ATEN2011_serial->interrupt_in_buffer=NULL; */ | ||
1059 | /* usb_kill_urb (ATEN2011_serial->interrupt_read_urb); */ | ||
1060 | } | ||
1061 | } | ||
1062 | if (ATEN2011_port->write_urb) { | ||
1063 | /* if this urb had a transfer buffer already (old tx) free it */ | ||
1064 | kfree(ATEN2011_port->write_urb->transfer_buffer); | ||
1065 | usb_free_urb(ATEN2011_port->write_urb); | ||
1066 | } | ||
1067 | |||
1068 | /* clear the MCR & IER */ | ||
1069 | Data = 0x00; | ||
1070 | set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); | ||
1071 | Data = 0x00; | ||
1072 | set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); | ||
1073 | |||
1074 | ATEN2011_port->open = 0; | ||
1075 | dbg("%s", "Leaving ............"); | ||
1076 | |||
1077 | } | ||
1078 | |||
1079 | static void ATEN2011_block_until_chase_response(struct tty_struct *tty, | ||
1080 | struct ATENINTL_port | ||
1081 | *ATEN2011_port) | ||
1082 | { | ||
1083 | int timeout = 1 * HZ; | ||
1084 | int wait = 10; | ||
1085 | int count; | ||
1086 | |||
1087 | while (1) { | ||
1088 | count = ATEN2011_chars_in_buffer(tty); | ||
1089 | |||
1090 | /* Check for Buffer status */ | ||
1091 | if (count <= 0) { | ||
1092 | ATEN2011_port->chaseResponsePending = 0; | ||
1093 | return; | ||
1094 | } | ||
1095 | |||
1096 | /* Block the thread for a while */ | ||
1097 | interruptible_sleep_on_timeout(&ATEN2011_port->wait_chase, | ||
1098 | timeout); | ||
1099 | /* No activity.. count down section */ | ||
1100 | wait--; | ||
1101 | if (wait == 0) { | ||
1102 | dbg("%s - TIMEOUT", __func__); | ||
1103 | return; | ||
1104 | } else { | ||
1105 | /* Reset timout value back to seconds */ | ||
1106 | wait = 10; | ||
1107 | } | ||
1108 | } | ||
1109 | |||
1110 | } | ||
1111 | |||
1112 | static void ATEN2011_break(struct tty_struct *tty, int break_state) | ||
1113 | { | ||
1114 | struct usb_serial_port *port = tty->driver_data; | ||
1115 | unsigned char data; | ||
1116 | struct usb_serial *serial; | ||
1117 | struct ATENINTL_serial *ATEN2011_serial; | ||
1118 | struct ATENINTL_port *ATEN2011_port; | ||
1119 | |||
1120 | dbg("%s", "Entering ..........."); | ||
1121 | dbg("ATEN2011_break: Start"); | ||
1122 | |||
1123 | serial = port->serial; | ||
1124 | |||
1125 | ATEN2011_serial = usb_get_serial_data(serial); | ||
1126 | ATEN2011_port = usb_get_serial_port_data(port); | ||
1127 | |||
1128 | if ((ATEN2011_serial == NULL) || (ATEN2011_port == NULL)) | ||
1129 | return; | ||
1130 | |||
1131 | /* flush and chase */ | ||
1132 | ATEN2011_port->chaseResponsePending = 1; | ||
1133 | |||
1134 | if (serial->dev) { | ||
1135 | /* flush and block until tx is empty */ | ||
1136 | ATEN2011_block_until_chase_response(tty, ATEN2011_port); | ||
1137 | } | ||
1138 | |||
1139 | if (break_state == -1) | ||
1140 | data = ATEN2011_port->shadowLCR | LCR_SET_BREAK; | ||
1141 | else | ||
1142 | data = ATEN2011_port->shadowLCR & ~LCR_SET_BREAK; | ||
1143 | |||
1144 | ATEN2011_port->shadowLCR = data; | ||
1145 | dbg("ATEN2011_break ATEN2011_port->shadowLCR is %x", | ||
1146 | ATEN2011_port->shadowLCR); | ||
1147 | set_uart_reg(port, LINE_CONTROL_REGISTER, ATEN2011_port->shadowLCR); | ||
1148 | |||
1149 | return; | ||
1150 | } | ||
1151 | |||
1152 | static int ATEN2011_write_room(struct tty_struct *tty) | ||
1153 | { | ||
1154 | struct usb_serial_port *port = tty->driver_data; | ||
1155 | int i; | ||
1156 | int room = 0; | ||
1157 | struct ATENINTL_port *ATEN2011_port; | ||
1158 | |||
1159 | ATEN2011_port = usb_get_serial_port_data(port); | ||
1160 | if (ATEN2011_port == NULL) { | ||
1161 | dbg("%s", "ATEN2011_break:leaving ..........."); | ||
1162 | return -1; | ||
1163 | } | ||
1164 | |||
1165 | for (i = 0; i < NUM_URBS; ++i) | ||
1166 | if (ATEN2011_port->write_urb_pool[i]->status != -EINPROGRESS) | ||
1167 | room += URB_TRANSFER_BUFFER_SIZE; | ||
1168 | |||
1169 | dbg("%s - returns %d", __func__, room); | ||
1170 | return room; | ||
1171 | |||
1172 | } | ||
1173 | |||
1174 | static int ATEN2011_write(struct tty_struct *tty, struct usb_serial_port *port, | ||
1175 | const unsigned char *data, int count) | ||
1176 | { | ||
1177 | int status; | ||
1178 | int i; | ||
1179 | int bytes_sent = 0; | ||
1180 | int transfer_size; | ||
1181 | int minor; | ||
1182 | |||
1183 | struct ATENINTL_port *ATEN2011_port; | ||
1184 | struct usb_serial *serial; | ||
1185 | struct ATENINTL_serial *ATEN2011_serial; | ||
1186 | struct urb *urb; | ||
1187 | const unsigned char *current_position = data; | ||
1188 | unsigned char *data1; | ||
1189 | dbg("%s", "entering ..........."); | ||
1190 | |||
1191 | serial = port->serial; | ||
1192 | |||
1193 | ATEN2011_port = usb_get_serial_port_data(port); | ||
1194 | if (ATEN2011_port == NULL) { | ||
1195 | dbg("%s", "ATEN2011_port is NULL"); | ||
1196 | return -1; | ||
1197 | } | ||
1198 | |||
1199 | ATEN2011_serial = usb_get_serial_data(serial); | ||
1200 | if (ATEN2011_serial == NULL) { | ||
1201 | dbg("%s", "ATEN2011_serial is NULL"); | ||
1202 | return -1; | ||
1203 | } | ||
1204 | |||
1205 | /* try to find a free urb in the list */ | ||
1206 | urb = NULL; | ||
1207 | |||
1208 | for (i = 0; i < NUM_URBS; ++i) { | ||
1209 | if (ATEN2011_port->write_urb_pool[i]->status != -EINPROGRESS) { | ||
1210 | urb = ATEN2011_port->write_urb_pool[i]; | ||
1211 | dbg("URB:%d", i); | ||
1212 | break; | ||
1213 | } | ||
1214 | } | ||
1215 | |||
1216 | if (urb == NULL) { | ||
1217 | dbg("%s - no more free urbs", __func__); | ||
1218 | goto exit; | ||
1219 | } | ||
1220 | |||
1221 | if (urb->transfer_buffer == NULL) { | ||
1222 | urb->transfer_buffer = | ||
1223 | kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); | ||
1224 | |||
1225 | if (urb->transfer_buffer == NULL) { | ||
1226 | err("%s no more kernel memory...", __func__); | ||
1227 | goto exit; | ||
1228 | } | ||
1229 | } | ||
1230 | transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE); | ||
1231 | |||
1232 | memcpy(urb->transfer_buffer, current_position, transfer_size); | ||
1233 | /* usb_serial_debug_data (__FILE__, __func__, transfer_size, urb->transfer_buffer); */ | ||
1234 | |||
1235 | /* fill urb with data and submit */ | ||
1236 | minor = port->serial->minor; | ||
1237 | if (minor == SERIAL_TTY_NO_MINOR) | ||
1238 | minor = 0; | ||
1239 | if ((ATEN2011_serial->ATEN2011_spectrum_2or4ports == 2) | ||
1240 | && (((__u16) port->number - (__u16) (minor)) != 0)) { | ||
1241 | usb_fill_bulk_urb(urb, ATEN2011_serial->serial->dev, | ||
1242 | usb_sndbulkpipe(ATEN2011_serial->serial->dev, | ||
1243 | (port-> | ||
1244 | bulk_out_endpointAddress) + | ||
1245 | 2), urb->transfer_buffer, | ||
1246 | transfer_size, | ||
1247 | ATEN2011_bulk_out_data_callback, | ||
1248 | ATEN2011_port); | ||
1249 | } else | ||
1250 | |||
1251 | usb_fill_bulk_urb(urb, | ||
1252 | ATEN2011_serial->serial->dev, | ||
1253 | usb_sndbulkpipe(ATEN2011_serial->serial->dev, | ||
1254 | port-> | ||
1255 | bulk_out_endpointAddress), | ||
1256 | urb->transfer_buffer, transfer_size, | ||
1257 | ATEN2011_bulk_out_data_callback, | ||
1258 | ATEN2011_port); | ||
1259 | |||
1260 | data1 = urb->transfer_buffer; | ||
1261 | dbg("bulkout endpoint is %d", port->bulk_out_endpointAddress); | ||
1262 | /* for(i=0;i < urb->actual_length;i++) */ | ||
1263 | /* dbg("Data is %c ",data1[i]); */ | ||
1264 | |||
1265 | /* send it down the pipe */ | ||
1266 | status = usb_submit_urb(urb, GFP_ATOMIC); | ||
1267 | |||
1268 | if (status) { | ||
1269 | err("%s - usb_submit_urb(write bulk) failed with status = %d", | ||
1270 | __func__, status); | ||
1271 | bytes_sent = status; | ||
1272 | goto exit; | ||
1273 | } | ||
1274 | bytes_sent = transfer_size; | ||
1275 | ATEN2011_port->icount.tx += transfer_size; | ||
1276 | dbg("ATEN2011_port->icount.tx is %d:", ATEN2011_port->icount.tx); | ||
1277 | |||
1278 | exit: | ||
1279 | return bytes_sent; | ||
1280 | } | ||
1281 | |||
1282 | static void ATEN2011_throttle(struct tty_struct *tty) | ||
1283 | { | ||
1284 | struct usb_serial_port *port = tty->driver_data; | ||
1285 | struct ATENINTL_port *ATEN2011_port; | ||
1286 | int status; | ||
1287 | |||
1288 | dbg("- port %d", port->number); | ||
1289 | |||
1290 | ATEN2011_port = usb_get_serial_port_data(port); | ||
1291 | |||
1292 | if (ATEN2011_port == NULL) | ||
1293 | return; | ||
1294 | |||
1295 | if (!ATEN2011_port->open) { | ||
1296 | dbg("%s", "port not opened"); | ||
1297 | return; | ||
1298 | } | ||
1299 | |||
1300 | dbg("%s", "Entering .......... "); | ||
1301 | |||
1302 | if (!tty) { | ||
1303 | dbg("%s - no tty available", __func__); | ||
1304 | return; | ||
1305 | } | ||
1306 | |||
1307 | /* if we are implementing XON/XOFF, send the stop character */ | ||
1308 | if (I_IXOFF(tty)) { | ||
1309 | unsigned char stop_char = STOP_CHAR(tty); | ||
1310 | status = ATEN2011_write(tty, port, &stop_char, 1); | ||
1311 | if (status <= 0) | ||
1312 | return; | ||
1313 | } | ||
1314 | |||
1315 | /* if we are implementing RTS/CTS, toggle that line */ | ||
1316 | if (tty->termios->c_cflag & CRTSCTS) { | ||
1317 | ATEN2011_port->shadowMCR &= ~MCR_RTS; | ||
1318 | status = set_uart_reg(port, MODEM_CONTROL_REGISTER, | ||
1319 | ATEN2011_port->shadowMCR); | ||
1320 | if (status < 0) | ||
1321 | return; | ||
1322 | } | ||
1323 | |||
1324 | return; | ||
1325 | } | ||
1326 | |||
1327 | static void ATEN2011_unthrottle(struct tty_struct *tty) | ||
1328 | { | ||
1329 | struct usb_serial_port *port = tty->driver_data; | ||
1330 | int status; | ||
1331 | struct ATENINTL_port *ATEN2011_port = usb_get_serial_port_data(port); | ||
1332 | |||
1333 | if (ATEN2011_port == NULL) | ||
1334 | return; | ||
1335 | |||
1336 | if (!ATEN2011_port->open) { | ||
1337 | dbg("%s - port not opened", __func__); | ||
1338 | return; | ||
1339 | } | ||
1340 | |||
1341 | dbg("%s", "Entering .......... "); | ||
1342 | |||
1343 | if (!tty) { | ||
1344 | dbg("%s - no tty available", __func__); | ||
1345 | return; | ||
1346 | } | ||
1347 | |||
1348 | /* if we are implementing XON/XOFF, send the start character */ | ||
1349 | if (I_IXOFF(tty)) { | ||
1350 | unsigned char start_char = START_CHAR(tty); | ||
1351 | status = ATEN2011_write(tty, port, &start_char, 1); | ||
1352 | if (status <= 0) | ||
1353 | return; | ||
1354 | } | ||
1355 | |||
1356 | /* if we are implementing RTS/CTS, toggle that line */ | ||
1357 | if (tty->termios->c_cflag & CRTSCTS) { | ||
1358 | ATEN2011_port->shadowMCR |= MCR_RTS; | ||
1359 | status = set_uart_reg(port, MODEM_CONTROL_REGISTER, | ||
1360 | ATEN2011_port->shadowMCR); | ||
1361 | if (status < 0) | ||
1362 | return; | ||
1363 | } | ||
1364 | |||
1365 | return; | ||
1366 | } | ||
1367 | |||
1368 | static int ATEN2011_tiocmget(struct tty_struct *tty, struct file *file) | ||
1369 | { | ||
1370 | struct usb_serial_port *port = tty->driver_data; | ||
1371 | struct ATENINTL_port *ATEN2011_port; | ||
1372 | unsigned int result; | ||
1373 | __u16 msr; | ||
1374 | __u16 mcr; | ||
1375 | /* unsigned int mcr; */ | ||
1376 | int status = 0; | ||
1377 | ATEN2011_port = usb_get_serial_port_data(port); | ||
1378 | |||
1379 | dbg("%s - port %d", __func__, port->number); | ||
1380 | |||
1381 | if (ATEN2011_port == NULL) | ||
1382 | return -ENODEV; | ||
1383 | |||
1384 | status = get_uart_reg(port, MODEM_STATUS_REGISTER, &msr); | ||
1385 | status = get_uart_reg(port, MODEM_CONTROL_REGISTER, &mcr); | ||
1386 | /* mcr = ATEN2011_port->shadowMCR; */ | ||
1387 | /* COMMENT2: the Fallowing three line are commented for updating only MSR values */ | ||
1388 | result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) | ||
1389 | | ((mcr & MCR_RTS) ? TIOCM_RTS : 0) | ||
1390 | | ((mcr & MCR_LOOPBACK) ? TIOCM_LOOP : 0) | ||
1391 | | ((msr & ATEN2011_MSR_CTS) ? TIOCM_CTS : 0) | ||
1392 | | ((msr & ATEN2011_MSR_CD) ? TIOCM_CAR : 0) | ||
1393 | | ((msr & ATEN2011_MSR_RI) ? TIOCM_RI : 0) | ||
1394 | | ((msr & ATEN2011_MSR_DSR) ? TIOCM_DSR : 0); | ||
1395 | |||
1396 | dbg("%s - 0x%04X", __func__, result); | ||
1397 | |||
1398 | return result; | ||
1399 | } | ||
1400 | |||
1401 | static int ATEN2011_tiocmset(struct tty_struct *tty, struct file *file, | ||
1402 | unsigned int set, unsigned int clear) | ||
1403 | { | ||
1404 | struct usb_serial_port *port = tty->driver_data; | ||
1405 | struct ATENINTL_port *ATEN2011_port; | ||
1406 | unsigned int mcr; | ||
1407 | unsigned int status; | ||
1408 | |||
1409 | dbg("%s - port %d", __func__, port->number); | ||
1410 | |||
1411 | ATEN2011_port = usb_get_serial_port_data(port); | ||
1412 | |||
1413 | if (ATEN2011_port == NULL) | ||
1414 | return -ENODEV; | ||
1415 | |||
1416 | mcr = ATEN2011_port->shadowMCR; | ||
1417 | if (clear & TIOCM_RTS) | ||
1418 | mcr &= ~MCR_RTS; | ||
1419 | if (clear & TIOCM_DTR) | ||
1420 | mcr &= ~MCR_DTR; | ||
1421 | if (clear & TIOCM_LOOP) | ||
1422 | mcr &= ~MCR_LOOPBACK; | ||
1423 | |||
1424 | if (set & TIOCM_RTS) | ||
1425 | mcr |= MCR_RTS; | ||
1426 | if (set & TIOCM_DTR) | ||
1427 | mcr |= MCR_DTR; | ||
1428 | if (set & TIOCM_LOOP) | ||
1429 | mcr |= MCR_LOOPBACK; | ||
1430 | |||
1431 | ATEN2011_port->shadowMCR = mcr; | ||
1432 | |||
1433 | status = set_uart_reg(port, MODEM_CONTROL_REGISTER, mcr); | ||
1434 | if (status < 0) { | ||
1435 | dbg("setting MODEM_CONTROL_REGISTER Failed"); | ||
1436 | return -1; | ||
1437 | } | ||
1438 | |||
1439 | return 0; | ||
1440 | } | ||
1441 | |||
1442 | static void ATEN2011_set_termios(struct tty_struct *tty, | ||
1443 | struct usb_serial_port *port, | ||
1444 | struct ktermios *old_termios) | ||
1445 | { | ||
1446 | int status; | ||
1447 | unsigned int cflag; | ||
1448 | struct usb_serial *serial; | ||
1449 | struct ATENINTL_port *ATEN2011_port; | ||
1450 | |||
1451 | dbg("ATEN2011_set_termios: START"); | ||
1452 | |||
1453 | serial = port->serial; | ||
1454 | |||
1455 | ATEN2011_port = usb_get_serial_port_data(port); | ||
1456 | |||
1457 | if (ATEN2011_port == NULL) | ||
1458 | return; | ||
1459 | |||
1460 | if (!ATEN2011_port->open) { | ||
1461 | dbg("%s - port not opened", __func__); | ||
1462 | return; | ||
1463 | } | ||
1464 | |||
1465 | dbg("%s", "setting termios - "); | ||
1466 | |||
1467 | cflag = tty->termios->c_cflag; | ||
1468 | |||
1469 | dbg("%s - cflag %08x iflag %08x", __func__, | ||
1470 | tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag)); | ||
1471 | |||
1472 | if (old_termios) { | ||
1473 | dbg("%s - old clfag %08x old iflag %08x", __func__, | ||
1474 | old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag)); | ||
1475 | } | ||
1476 | |||
1477 | dbg("%s - port %d", __func__, port->number); | ||
1478 | |||
1479 | /* change the port settings to the new ones specified */ | ||
1480 | |||
1481 | ATEN2011_change_port_settings(tty, ATEN2011_port, old_termios); | ||
1482 | |||
1483 | if (!ATEN2011_port->read_urb) { | ||
1484 | dbg("%s", "URB KILLED !!!!!"); | ||
1485 | return; | ||
1486 | } | ||
1487 | |||
1488 | if (ATEN2011_port->read_urb->status != -EINPROGRESS) { | ||
1489 | ATEN2011_port->read_urb->dev = serial->dev; | ||
1490 | status = usb_submit_urb(ATEN2011_port->read_urb, GFP_ATOMIC); | ||
1491 | if (status) { | ||
1492 | dbg | ||
1493 | (" usb_submit_urb(read bulk) failed, status = %d", | ||
1494 | status); | ||
1495 | } | ||
1496 | } | ||
1497 | return; | ||
1498 | } | ||
1499 | |||
1500 | static int get_lsr_info(struct tty_struct *tty, | ||
1501 | struct ATENINTL_port *ATEN2011_port, | ||
1502 | unsigned int __user *value) | ||
1503 | { | ||
1504 | int count; | ||
1505 | unsigned int result = 0; | ||
1506 | |||
1507 | count = ATEN2011_chars_in_buffer(tty); | ||
1508 | if (count == 0) { | ||
1509 | dbg("%s -- Empty", __func__); | ||
1510 | result = TIOCSER_TEMT; | ||
1511 | } | ||
1512 | |||
1513 | if (copy_to_user(value, &result, sizeof(int))) | ||
1514 | return -EFAULT; | ||
1515 | return 0; | ||
1516 | } | ||
1517 | |||
1518 | static int get_number_bytes_avail(struct tty_struct *tty, | ||
1519 | struct ATENINTL_port *ATEN2011_port, | ||
1520 | unsigned int __user *value) | ||
1521 | { | ||
1522 | unsigned int result = 0; | ||
1523 | |||
1524 | if (!tty) | ||
1525 | return -ENOIOCTLCMD; | ||
1526 | |||
1527 | result = tty->read_cnt; | ||
1528 | |||
1529 | dbg("%s(%d) = %d", __func__, ATEN2011_port->port->number, result); | ||
1530 | if (copy_to_user(value, &result, sizeof(int))) | ||
1531 | return -EFAULT; | ||
1532 | |||
1533 | return -ENOIOCTLCMD; | ||
1534 | } | ||
1535 | |||
1536 | static int set_modem_info(struct ATENINTL_port *ATEN2011_port, unsigned int cmd, | ||
1537 | unsigned int __user *value) | ||
1538 | { | ||
1539 | unsigned int mcr; | ||
1540 | unsigned int arg; | ||
1541 | __u16 Data; | ||
1542 | int status; | ||
1543 | struct usb_serial_port *port; | ||
1544 | |||
1545 | if (ATEN2011_port == NULL) | ||
1546 | return -1; | ||
1547 | |||
1548 | port = (struct usb_serial_port *)ATEN2011_port->port; | ||
1549 | |||
1550 | mcr = ATEN2011_port->shadowMCR; | ||
1551 | |||
1552 | if (copy_from_user(&arg, value, sizeof(int))) | ||
1553 | return -EFAULT; | ||
1554 | |||
1555 | switch (cmd) { | ||
1556 | case TIOCMBIS: | ||
1557 | if (arg & TIOCM_RTS) | ||
1558 | mcr |= MCR_RTS; | ||
1559 | if (arg & TIOCM_DTR) | ||
1560 | mcr |= MCR_RTS; | ||
1561 | if (arg & TIOCM_LOOP) | ||
1562 | mcr |= MCR_LOOPBACK; | ||
1563 | break; | ||
1564 | |||
1565 | case TIOCMBIC: | ||
1566 | if (arg & TIOCM_RTS) | ||
1567 | mcr &= ~MCR_RTS; | ||
1568 | if (arg & TIOCM_DTR) | ||
1569 | mcr &= ~MCR_RTS; | ||
1570 | if (arg & TIOCM_LOOP) | ||
1571 | mcr &= ~MCR_LOOPBACK; | ||
1572 | break; | ||
1573 | |||
1574 | case TIOCMSET: | ||
1575 | /* turn off the RTS and DTR and LOOPBACK | ||
1576 | * and then only turn on what was asked to */ | ||
1577 | mcr &= ~(MCR_RTS | MCR_DTR | MCR_LOOPBACK); | ||
1578 | mcr |= ((arg & TIOCM_RTS) ? MCR_RTS : 0); | ||
1579 | mcr |= ((arg & TIOCM_DTR) ? MCR_DTR : 0); | ||
1580 | mcr |= ((arg & TIOCM_LOOP) ? MCR_LOOPBACK : 0); | ||
1581 | break; | ||
1582 | } | ||
1583 | |||
1584 | ATEN2011_port->shadowMCR = mcr; | ||
1585 | |||
1586 | Data = ATEN2011_port->shadowMCR; | ||
1587 | status = set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); | ||
1588 | if (status < 0) { | ||
1589 | dbg("setting MODEM_CONTROL_REGISTER Failed"); | ||
1590 | return -1; | ||
1591 | } | ||
1592 | |||
1593 | return 0; | ||
1594 | } | ||
1595 | |||
1596 | static int get_modem_info(struct ATENINTL_port *ATEN2011_port, | ||
1597 | unsigned int __user *value) | ||
1598 | { | ||
1599 | unsigned int result = 0; | ||
1600 | __u16 msr; | ||
1601 | unsigned int mcr = ATEN2011_port->shadowMCR; | ||
1602 | int status; | ||
1603 | |||
1604 | status = get_uart_reg(ATEN2011_port->port, MODEM_STATUS_REGISTER, &msr); | ||
1605 | result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) /* 0x002 */ | ||
1606 | |((mcr & MCR_RTS) ? TIOCM_RTS : 0) /* 0x004 */ | ||
1607 | |((msr & ATEN2011_MSR_CTS) ? TIOCM_CTS : 0) /* 0x020 */ | ||
1608 | |((msr & ATEN2011_MSR_CD) ? TIOCM_CAR : 0) /* 0x040 */ | ||
1609 | |((msr & ATEN2011_MSR_RI) ? TIOCM_RI : 0) /* 0x080 */ | ||
1610 | |((msr & ATEN2011_MSR_DSR) ? TIOCM_DSR : 0); /* 0x100 */ | ||
1611 | |||
1612 | dbg("%s -- %x", __func__, result); | ||
1613 | |||
1614 | if (copy_to_user(value, &result, sizeof(int))) | ||
1615 | return -EFAULT; | ||
1616 | return 0; | ||
1617 | } | ||
1618 | |||
1619 | static int get_serial_info(struct ATENINTL_port *ATEN2011_port, | ||
1620 | struct serial_struct __user *retinfo) | ||
1621 | { | ||
1622 | struct serial_struct tmp; | ||
1623 | |||
1624 | if (ATEN2011_port == NULL) | ||
1625 | return -1; | ||
1626 | |||
1627 | if (!retinfo) | ||
1628 | return -EFAULT; | ||
1629 | |||
1630 | memset(&tmp, 0, sizeof(tmp)); | ||
1631 | |||
1632 | tmp.type = PORT_16550A; | ||
1633 | tmp.line = ATEN2011_port->port->serial->minor; | ||
1634 | if (tmp.line == SERIAL_TTY_NO_MINOR) | ||
1635 | tmp.line = 0; | ||
1636 | tmp.port = ATEN2011_port->port->number; | ||
1637 | tmp.irq = 0; | ||
1638 | tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; | ||
1639 | tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE; | ||
1640 | tmp.baud_base = 9600; | ||
1641 | tmp.close_delay = 5 * HZ; | ||
1642 | tmp.closing_wait = 30 * HZ; | ||
1643 | |||
1644 | if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) | ||
1645 | return -EFAULT; | ||
1646 | return 0; | ||
1647 | } | ||
1648 | |||
1649 | static int ATEN2011_ioctl(struct tty_struct *tty, struct file *file, | ||
1650 | unsigned int cmd, unsigned long arg) | ||
1651 | { | ||
1652 | struct usb_serial_port *port = tty->driver_data; | ||
1653 | struct ATENINTL_port *ATEN2011_port; | ||
1654 | struct async_icount cnow; | ||
1655 | struct async_icount cprev; | ||
1656 | struct serial_icounter_struct icount; | ||
1657 | int ATENret = 0; | ||
1658 | unsigned int __user *user_arg = (unsigned int __user *)arg; | ||
1659 | |||
1660 | ATEN2011_port = usb_get_serial_port_data(port); | ||
1661 | |||
1662 | if (ATEN2011_port == NULL) | ||
1663 | return -1; | ||
1664 | |||
1665 | dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd); | ||
1666 | |||
1667 | switch (cmd) { | ||
1668 | /* return number of bytes available */ | ||
1669 | |||
1670 | case TIOCINQ: | ||
1671 | dbg("%s (%d) TIOCINQ", __func__, port->number); | ||
1672 | return get_number_bytes_avail(tty, ATEN2011_port, user_arg); | ||
1673 | break; | ||
1674 | |||
1675 | case TIOCOUTQ: | ||
1676 | dbg("%s (%d) TIOCOUTQ", __func__, port->number); | ||
1677 | return put_user(ATEN2011_chars_in_buffer(tty), user_arg); | ||
1678 | break; | ||
1679 | |||
1680 | case TIOCSERGETLSR: | ||
1681 | dbg("%s (%d) TIOCSERGETLSR", __func__, port->number); | ||
1682 | return get_lsr_info(tty, ATEN2011_port, user_arg); | ||
1683 | return 0; | ||
1684 | |||
1685 | case TIOCMBIS: | ||
1686 | case TIOCMBIC: | ||
1687 | case TIOCMSET: | ||
1688 | dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __func__, | ||
1689 | port->number); | ||
1690 | ATENret = set_modem_info(ATEN2011_port, cmd, user_arg); | ||
1691 | return ATENret; | ||
1692 | |||
1693 | case TIOCMGET: | ||
1694 | dbg("%s (%d) TIOCMGET", __func__, port->number); | ||
1695 | return get_modem_info(ATEN2011_port, user_arg); | ||
1696 | |||
1697 | case TIOCGSERIAL: | ||
1698 | dbg("%s (%d) TIOCGSERIAL", __func__, port->number); | ||
1699 | return get_serial_info(ATEN2011_port, | ||
1700 | (struct serial_struct __user *)arg); | ||
1701 | |||
1702 | case TIOCSSERIAL: | ||
1703 | dbg("%s (%d) TIOCSSERIAL", __func__, port->number); | ||
1704 | break; | ||
1705 | |||
1706 | case TIOCMIWAIT: | ||
1707 | dbg("%s (%d) TIOCMIWAIT", __func__, port->number); | ||
1708 | cprev = ATEN2011_port->icount; | ||
1709 | while (1) { | ||
1710 | /* see if a signal did it */ | ||
1711 | if (signal_pending(current)) | ||
1712 | return -ERESTARTSYS; | ||
1713 | cnow = ATEN2011_port->icount; | ||
1714 | if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && | ||
1715 | cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) | ||
1716 | return -EIO; /* no change => error */ | ||
1717 | if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || | ||
1718 | ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || | ||
1719 | ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || | ||
1720 | ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { | ||
1721 | return 0; | ||
1722 | } | ||
1723 | cprev = cnow; | ||
1724 | } | ||
1725 | /* NOTREACHED */ | ||
1726 | break; | ||
1727 | |||
1728 | case TIOCGICOUNT: | ||
1729 | cnow = ATEN2011_port->icount; | ||
1730 | icount.cts = cnow.cts; | ||
1731 | icount.dsr = cnow.dsr; | ||
1732 | icount.rng = cnow.rng; | ||
1733 | icount.dcd = cnow.dcd; | ||
1734 | icount.rx = cnow.rx; | ||
1735 | icount.tx = cnow.tx; | ||
1736 | icount.frame = cnow.frame; | ||
1737 | icount.overrun = cnow.overrun; | ||
1738 | icount.parity = cnow.parity; | ||
1739 | icount.brk = cnow.brk; | ||
1740 | icount.buf_overrun = cnow.buf_overrun; | ||
1741 | |||
1742 | dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__, | ||
1743 | port->number, icount.rx, icount.tx); | ||
1744 | if (copy_to_user((void __user *)arg, &icount, sizeof(icount))) | ||
1745 | return -EFAULT; | ||
1746 | return 0; | ||
1747 | |||
1748 | default: | ||
1749 | break; | ||
1750 | } | ||
1751 | |||
1752 | return -ENOIOCTLCMD; | ||
1753 | } | ||
1754 | |||
1755 | static int ATEN2011_calc_baud_rate_divisor(int baudRate, int *divisor, | ||
1756 | __u16 *clk_sel_val) | ||
1757 | { | ||
1758 | dbg("%s - %d", __func__, baudRate); | ||
1759 | |||
1760 | if (baudRate <= 115200) { | ||
1761 | *divisor = 115200 / baudRate; | ||
1762 | *clk_sel_val = 0x0; | ||
1763 | } | ||
1764 | if ((baudRate > 115200) && (baudRate <= 230400)) { | ||
1765 | *divisor = 230400 / baudRate; | ||
1766 | *clk_sel_val = 0x10; | ||
1767 | } else if ((baudRate > 230400) && (baudRate <= 403200)) { | ||
1768 | *divisor = 403200 / baudRate; | ||
1769 | *clk_sel_val = 0x20; | ||
1770 | } else if ((baudRate > 403200) && (baudRate <= 460800)) { | ||
1771 | *divisor = 460800 / baudRate; | ||
1772 | *clk_sel_val = 0x30; | ||
1773 | } else if ((baudRate > 460800) && (baudRate <= 806400)) { | ||
1774 | *divisor = 806400 / baudRate; | ||
1775 | *clk_sel_val = 0x40; | ||
1776 | } else if ((baudRate > 806400) && (baudRate <= 921600)) { | ||
1777 | *divisor = 921600 / baudRate; | ||
1778 | *clk_sel_val = 0x50; | ||
1779 | } else if ((baudRate > 921600) && (baudRate <= 1572864)) { | ||
1780 | *divisor = 1572864 / baudRate; | ||
1781 | *clk_sel_val = 0x60; | ||
1782 | } else if ((baudRate > 1572864) && (baudRate <= 3145728)) { | ||
1783 | *divisor = 3145728 / baudRate; | ||
1784 | *clk_sel_val = 0x70; | ||
1785 | } | ||
1786 | return 0; | ||
1787 | } | ||
1788 | |||
1789 | static int ATEN2011_send_cmd_write_baud_rate(struct ATENINTL_port | ||
1790 | *ATEN2011_port, int baudRate) | ||
1791 | { | ||
1792 | int divisor = 0; | ||
1793 | int status; | ||
1794 | __u16 Data; | ||
1795 | unsigned char number; | ||
1796 | __u16 clk_sel_val; | ||
1797 | struct usb_serial_port *port; | ||
1798 | int minor; | ||
1799 | |||
1800 | if (ATEN2011_port == NULL) | ||
1801 | return -1; | ||
1802 | |||
1803 | port = (struct usb_serial_port *)ATEN2011_port->port; | ||
1804 | |||
1805 | dbg("%s", "Entering .......... "); | ||
1806 | |||
1807 | minor = ATEN2011_port->port->serial->minor; | ||
1808 | if (minor == SERIAL_TTY_NO_MINOR) | ||
1809 | minor = 0; | ||
1810 | number = ATEN2011_port->port->number - minor; | ||
1811 | |||
1812 | dbg("%s - port = %d, baud = %d", __func__, | ||
1813 | ATEN2011_port->port->number, baudRate); | ||
1814 | /* reset clk_uart_sel in spregOffset */ | ||
1815 | if (baudRate > 115200) { | ||
1816 | #ifdef HW_flow_control | ||
1817 | /* | ||
1818 | * NOTE: need to see the pther register to modify | ||
1819 | * setting h/w flow control bit to 1; | ||
1820 | */ | ||
1821 | /* Data = ATEN2011_port->shadowMCR; */ | ||
1822 | Data = 0x2b; | ||
1823 | ATEN2011_port->shadowMCR = Data; | ||
1824 | status = set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); | ||
1825 | if (status < 0) { | ||
1826 | dbg("Writing spreg failed in set_serial_baud"); | ||
1827 | return -1; | ||
1828 | } | ||
1829 | #endif | ||
1830 | |||
1831 | } else { | ||
1832 | #ifdef HW_flow_control | ||
1833 | /* setting h/w flow control bit to 0; */ | ||
1834 | /* Data = ATEN2011_port->shadowMCR; */ | ||
1835 | Data = 0xb; | ||
1836 | ATEN2011_port->shadowMCR = Data; | ||
1837 | status = set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); | ||
1838 | if (status < 0) { | ||
1839 | dbg("Writing spreg failed in set_serial_baud"); | ||
1840 | return -1; | ||
1841 | } | ||
1842 | #endif | ||
1843 | |||
1844 | } | ||
1845 | |||
1846 | if (1) /* baudRate <= 115200) */ { | ||
1847 | clk_sel_val = 0x0; | ||
1848 | Data = 0x0; | ||
1849 | status = | ||
1850 | ATEN2011_calc_baud_rate_divisor(baudRate, &divisor, | ||
1851 | &clk_sel_val); | ||
1852 | status = get_reg_sync(port, ATEN2011_port->SpRegOffset, &Data); | ||
1853 | if (status < 0) { | ||
1854 | dbg("reading spreg failed in set_serial_baud"); | ||
1855 | return -1; | ||
1856 | } | ||
1857 | Data = (Data & 0x8f) | clk_sel_val; | ||
1858 | status = set_reg_sync(port, ATEN2011_port->SpRegOffset, Data); | ||
1859 | if (status < 0) { | ||
1860 | dbg("Writing spreg failed in set_serial_baud"); | ||
1861 | return -1; | ||
1862 | } | ||
1863 | /* Calculate the Divisor */ | ||
1864 | |||
1865 | if (status) { | ||
1866 | err("%s - bad baud rate", __func__); | ||
1867 | dbg("%s", "bad baud rate"); | ||
1868 | return status; | ||
1869 | } | ||
1870 | /* Enable access to divisor latch */ | ||
1871 | Data = ATEN2011_port->shadowLCR | SERIAL_LCR_DLAB; | ||
1872 | ATEN2011_port->shadowLCR = Data; | ||
1873 | set_uart_reg(port, LINE_CONTROL_REGISTER, Data); | ||
1874 | |||
1875 | /* Write the divisor */ | ||
1876 | Data = (unsigned char)(divisor & 0xff); | ||
1877 | dbg("set_serial_baud Value to write DLL is %x", Data); | ||
1878 | set_uart_reg(port, DIVISOR_LATCH_LSB, Data); | ||
1879 | |||
1880 | Data = (unsigned char)((divisor & 0xff00) >> 8); | ||
1881 | dbg("set_serial_baud Value to write DLM is %x", Data); | ||
1882 | set_uart_reg(port, DIVISOR_LATCH_MSB, Data); | ||
1883 | |||
1884 | /* Disable access to divisor latch */ | ||
1885 | Data = ATEN2011_port->shadowLCR & ~SERIAL_LCR_DLAB; | ||
1886 | ATEN2011_port->shadowLCR = Data; | ||
1887 | set_uart_reg(port, LINE_CONTROL_REGISTER, Data); | ||
1888 | |||
1889 | } | ||
1890 | |||
1891 | return status; | ||
1892 | } | ||
1893 | |||
1894 | static void ATEN2011_change_port_settings(struct tty_struct *tty, | ||
1895 | struct ATENINTL_port *ATEN2011_port, | ||
1896 | struct ktermios *old_termios) | ||
1897 | { | ||
1898 | int baud; | ||
1899 | unsigned cflag; | ||
1900 | unsigned iflag; | ||
1901 | __u8 lData; | ||
1902 | __u8 lParity; | ||
1903 | __u8 lStop; | ||
1904 | int status; | ||
1905 | __u16 Data; | ||
1906 | struct usb_serial_port *port; | ||
1907 | struct usb_serial *serial; | ||
1908 | |||
1909 | if (ATEN2011_port == NULL) | ||
1910 | return; | ||
1911 | |||
1912 | port = (struct usb_serial_port *)ATEN2011_port->port; | ||
1913 | |||
1914 | serial = port->serial; | ||
1915 | |||
1916 | dbg("%s - port %d", __func__, ATEN2011_port->port->number); | ||
1917 | |||
1918 | if (!ATEN2011_port->open) { | ||
1919 | dbg("%s - port not opened", __func__); | ||
1920 | return; | ||
1921 | } | ||
1922 | |||
1923 | if ((!tty) || (!tty->termios)) { | ||
1924 | dbg("%s - no tty structures", __func__); | ||
1925 | return; | ||
1926 | } | ||
1927 | |||
1928 | dbg("%s", "Entering .......... "); | ||
1929 | |||
1930 | lData = LCR_BITS_8; | ||
1931 | lStop = LCR_STOP_1; | ||
1932 | lParity = LCR_PAR_NONE; | ||
1933 | |||
1934 | cflag = tty->termios->c_cflag; | ||
1935 | iflag = tty->termios->c_iflag; | ||
1936 | |||
1937 | /* Change the number of bits */ | ||
1938 | |||
1939 | /* COMMENT1: the below Line"if(cflag & CSIZE)" is added for the errors we get for serial loop data test i.e serial_loopback.pl -v */ | ||
1940 | /* if(cflag & CSIZE) */ | ||
1941 | { | ||
1942 | switch (cflag & CSIZE) { | ||
1943 | case CS5: | ||
1944 | lData = LCR_BITS_5; | ||
1945 | break; | ||
1946 | |||
1947 | case CS6: | ||
1948 | lData = LCR_BITS_6; | ||
1949 | break; | ||
1950 | |||
1951 | case CS7: | ||
1952 | lData = LCR_BITS_7; | ||
1953 | break; | ||
1954 | default: | ||
1955 | case CS8: | ||
1956 | lData = LCR_BITS_8; | ||
1957 | break; | ||
1958 | } | ||
1959 | } | ||
1960 | /* Change the Parity bit */ | ||
1961 | if (cflag & PARENB) { | ||
1962 | if (cflag & PARODD) { | ||
1963 | lParity = LCR_PAR_ODD; | ||
1964 | dbg("%s - parity = odd", __func__); | ||
1965 | } else { | ||
1966 | lParity = LCR_PAR_EVEN; | ||
1967 | dbg("%s - parity = even", __func__); | ||
1968 | } | ||
1969 | |||
1970 | } else { | ||
1971 | dbg("%s - parity = none", __func__); | ||
1972 | } | ||
1973 | |||
1974 | if (cflag & CMSPAR) | ||
1975 | lParity = lParity | 0x20; | ||
1976 | |||
1977 | /* Change the Stop bit */ | ||
1978 | if (cflag & CSTOPB) { | ||
1979 | lStop = LCR_STOP_2; | ||
1980 | dbg("%s - stop bits = 2", __func__); | ||
1981 | } else { | ||
1982 | lStop = LCR_STOP_1; | ||
1983 | dbg("%s - stop bits = 1", __func__); | ||
1984 | } | ||
1985 | |||
1986 | /* Update the LCR with the correct value */ | ||
1987 | ATEN2011_port->shadowLCR &= | ||
1988 | ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK); | ||
1989 | ATEN2011_port->shadowLCR |= (lData | lParity | lStop); | ||
1990 | |||
1991 | dbg | ||
1992 | ("ATEN2011_change_port_settings ATEN2011_port->shadowLCR is %x", | ||
1993 | ATEN2011_port->shadowLCR); | ||
1994 | /* Disable Interrupts */ | ||
1995 | Data = 0x00; | ||
1996 | set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); | ||
1997 | |||
1998 | Data = 0x00; | ||
1999 | set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); | ||
2000 | |||
2001 | Data = 0xcf; | ||
2002 | set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); | ||
2003 | |||
2004 | /* Send the updated LCR value to the ATEN2011 */ | ||
2005 | Data = ATEN2011_port->shadowLCR; | ||
2006 | |||
2007 | set_uart_reg(port, LINE_CONTROL_REGISTER, Data); | ||
2008 | |||
2009 | Data = 0x00b; | ||
2010 | ATEN2011_port->shadowMCR = Data; | ||
2011 | set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); | ||
2012 | Data = 0x00b; | ||
2013 | set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); | ||
2014 | |||
2015 | /* set up the MCR register and send it to the ATEN2011 */ | ||
2016 | |||
2017 | ATEN2011_port->shadowMCR = MCR_MASTER_IE; | ||
2018 | if (cflag & CBAUD) | ||
2019 | ATEN2011_port->shadowMCR |= (MCR_DTR | MCR_RTS); | ||
2020 | |||
2021 | if (cflag & CRTSCTS) | ||
2022 | ATEN2011_port->shadowMCR |= (MCR_XON_ANY); | ||
2023 | else | ||
2024 | ATEN2011_port->shadowMCR &= ~(MCR_XON_ANY); | ||
2025 | |||
2026 | Data = ATEN2011_port->shadowMCR; | ||
2027 | set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); | ||
2028 | |||
2029 | /* Determine divisor based on baud rate */ | ||
2030 | baud = tty_get_baud_rate(tty); | ||
2031 | |||
2032 | if (!baud) { | ||
2033 | /* pick a default, any default... */ | ||
2034 | dbg("%s", "Picked default baud..."); | ||
2035 | baud = 9600; | ||
2036 | } | ||
2037 | |||
2038 | dbg("%s - baud rate = %d", __func__, baud); | ||
2039 | status = ATEN2011_send_cmd_write_baud_rate(ATEN2011_port, baud); | ||
2040 | |||
2041 | /* Enable Interrupts */ | ||
2042 | Data = 0x0c; | ||
2043 | set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); | ||
2044 | |||
2045 | if (ATEN2011_port->read_urb->status != -EINPROGRESS) { | ||
2046 | ATEN2011_port->read_urb->dev = serial->dev; | ||
2047 | |||
2048 | status = usb_submit_urb(ATEN2011_port->read_urb, GFP_ATOMIC); | ||
2049 | |||
2050 | if (status) { | ||
2051 | dbg | ||
2052 | (" usb_submit_urb(read bulk) failed, status = %d", | ||
2053 | status); | ||
2054 | } | ||
2055 | } | ||
2056 | dbg | ||
2057 | ("ATEN2011_change_port_settings ATEN2011_port->shadowLCR is End %x", | ||
2058 | ATEN2011_port->shadowLCR); | ||
2059 | |||
2060 | return; | ||
2061 | } | ||
2062 | |||
2063 | static int ATEN2011_calc_num_ports(struct usb_serial *serial) | ||
2064 | { | ||
2065 | |||
2066 | __u16 Data = 0x00; | ||
2067 | int ret = 0; | ||
2068 | int ATEN2011_2or4ports; | ||
2069 | ret = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | ||
2070 | ATEN_RDREQ, ATEN_RD_RTYPE, 0, GPIO_REGISTER, | ||
2071 | &Data, VENDOR_READ_LENGTH, ATEN_WDR_TIMEOUT); | ||
2072 | |||
2073 | /* ghostgum: here is where the problem appears to bet */ | ||
2074 | /* Which of the following are needed? */ | ||
2075 | /* Greg used the serial->type->num_ports=2 */ | ||
2076 | /* But the code in the ATEN2011_open relies on serial->num_ports=2 */ | ||
2077 | if ((Data & 0x01) == 0) { | ||
2078 | ATEN2011_2or4ports = 2; | ||
2079 | serial->type->num_ports = 2; | ||
2080 | serial->num_ports = 2; | ||
2081 | } | ||
2082 | /* else if(serial->interface->cur_altsetting->desc.bNumEndpoints == 9) */ | ||
2083 | else { | ||
2084 | ATEN2011_2or4ports = 4; | ||
2085 | serial->type->num_ports = 4; | ||
2086 | serial->num_ports = 4; | ||
2087 | |||
2088 | } | ||
2089 | |||
2090 | return ATEN2011_2or4ports; | ||
2091 | } | ||
2092 | |||
2093 | static int ATEN2011_startup(struct usb_serial *serial) | ||
2094 | { | ||
2095 | struct ATENINTL_serial *ATEN2011_serial; | ||
2096 | struct ATENINTL_port *ATEN2011_port; | ||
2097 | struct usb_device *dev; | ||
2098 | int i, status; | ||
2099 | int minor; | ||
2100 | |||
2101 | __u16 Data; | ||
2102 | dbg("%s", " ATEN2011_startup :entering.........."); | ||
2103 | |||
2104 | if (!serial) { | ||
2105 | dbg("%s", "Invalid Handler"); | ||
2106 | return -1; | ||
2107 | } | ||
2108 | |||
2109 | dev = serial->dev; | ||
2110 | |||
2111 | dbg("%s", "Entering..."); | ||
2112 | |||
2113 | /* create our private serial structure */ | ||
2114 | ATEN2011_serial = kzalloc(sizeof(struct ATENINTL_serial), GFP_KERNEL); | ||
2115 | if (ATEN2011_serial == NULL) { | ||
2116 | err("%s - Out of memory", __func__); | ||
2117 | return -ENOMEM; | ||
2118 | } | ||
2119 | |||
2120 | /* resetting the private structure field values to zero */ | ||
2121 | memset(ATEN2011_serial, 0, sizeof(struct ATENINTL_serial)); | ||
2122 | |||
2123 | ATEN2011_serial->serial = serial; | ||
2124 | /* initilize status polling flag to 0 */ | ||
2125 | ATEN2011_serial->status_polling_started = 0; | ||
2126 | |||
2127 | usb_set_serial_data(serial, ATEN2011_serial); | ||
2128 | ATEN2011_serial->ATEN2011_spectrum_2or4ports = | ||
2129 | ATEN2011_calc_num_ports(serial); | ||
2130 | /* we set up the pointers to the endpoints in the ATEN2011_open * | ||
2131 | * function, as the structures aren't created yet. */ | ||
2132 | |||
2133 | /* set up port private structures */ | ||
2134 | for (i = 0; i < serial->num_ports; ++i) { | ||
2135 | ATEN2011_port = | ||
2136 | kmalloc(sizeof(struct ATENINTL_port), GFP_KERNEL); | ||
2137 | if (ATEN2011_port == NULL) { | ||
2138 | err("%s - Out of memory", __func__); | ||
2139 | usb_set_serial_data(serial, NULL); | ||
2140 | kfree(ATEN2011_serial); | ||
2141 | return -ENOMEM; | ||
2142 | } | ||
2143 | memset(ATEN2011_port, 0, sizeof(struct ATENINTL_port)); | ||
2144 | |||
2145 | /* | ||
2146 | * Initialize all port interrupt end point to port 0 | ||
2147 | * int endpoint. Our device has only one interrupt end point | ||
2148 | * comman to all port | ||
2149 | */ | ||
2150 | /* serial->port[i]->interrupt_in_endpointAddress = serial->port[0]->interrupt_in_endpointAddress; */ | ||
2151 | |||
2152 | ATEN2011_port->port = serial->port[i]; | ||
2153 | usb_set_serial_port_data(serial->port[i], ATEN2011_port); | ||
2154 | |||
2155 | minor = serial->port[i]->serial->minor; | ||
2156 | if (minor == SERIAL_TTY_NO_MINOR) | ||
2157 | minor = 0; | ||
2158 | ATEN2011_port->port_num = | ||
2159 | ((serial->port[i]->number - minor) + 1); | ||
2160 | |||
2161 | if (ATEN2011_port->port_num == 1) { | ||
2162 | ATEN2011_port->SpRegOffset = 0x0; | ||
2163 | ATEN2011_port->ControlRegOffset = 0x1; | ||
2164 | ATEN2011_port->DcrRegOffset = 0x4; | ||
2165 | } else if ((ATEN2011_port->port_num == 2) | ||
2166 | && (ATEN2011_serial->ATEN2011_spectrum_2or4ports == | ||
2167 | 4)) { | ||
2168 | ATEN2011_port->SpRegOffset = 0x8; | ||
2169 | ATEN2011_port->ControlRegOffset = 0x9; | ||
2170 | ATEN2011_port->DcrRegOffset = 0x16; | ||
2171 | } else if ((ATEN2011_port->port_num == 2) | ||
2172 | && (ATEN2011_serial->ATEN2011_spectrum_2or4ports == | ||
2173 | 2)) { | ||
2174 | ATEN2011_port->SpRegOffset = 0xa; | ||
2175 | ATEN2011_port->ControlRegOffset = 0xb; | ||
2176 | ATEN2011_port->DcrRegOffset = 0x19; | ||
2177 | } else if ((ATEN2011_port->port_num == 3) | ||
2178 | && (ATEN2011_serial->ATEN2011_spectrum_2or4ports == | ||
2179 | 4)) { | ||
2180 | ATEN2011_port->SpRegOffset = 0xa; | ||
2181 | ATEN2011_port->ControlRegOffset = 0xb; | ||
2182 | ATEN2011_port->DcrRegOffset = 0x19; | ||
2183 | } else if ((ATEN2011_port->port_num == 4) | ||
2184 | && (ATEN2011_serial->ATEN2011_spectrum_2or4ports == | ||
2185 | 4)) { | ||
2186 | ATEN2011_port->SpRegOffset = 0xc; | ||
2187 | ATEN2011_port->ControlRegOffset = 0xd; | ||
2188 | ATEN2011_port->DcrRegOffset = 0x1c; | ||
2189 | } | ||
2190 | |||
2191 | usb_set_serial_port_data(serial->port[i], ATEN2011_port); | ||
2192 | |||
2193 | /* enable rx_disable bit in control register */ | ||
2194 | |||
2195 | status = get_reg_sync(serial->port[i], | ||
2196 | ATEN2011_port->ControlRegOffset, &Data); | ||
2197 | if (status < 0) { | ||
2198 | dbg("Reading ControlReg failed status-0x%x", | ||
2199 | status); | ||
2200 | break; | ||
2201 | } else | ||
2202 | dbg | ||
2203 | ("ControlReg Reading success val is %x, status%d", | ||
2204 | Data, status); | ||
2205 | Data |= 0x08; /* setting driver done bit */ | ||
2206 | Data |= 0x04; /* sp1_bit to have cts change reflect in modem status reg */ | ||
2207 | |||
2208 | /* Data |= 0x20; */ /* rx_disable bit */ | ||
2209 | status = set_reg_sync(serial->port[i], | ||
2210 | ATEN2011_port->ControlRegOffset, Data); | ||
2211 | if (status < 0) { | ||
2212 | dbg | ||
2213 | ("Writing ControlReg failed(rx_disable) status-0x%x", | ||
2214 | status); | ||
2215 | break; | ||
2216 | } else | ||
2217 | dbg | ||
2218 | ("ControlReg Writing success(rx_disable) status%d", | ||
2219 | status); | ||
2220 | |||
2221 | /* | ||
2222 | * Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 | ||
2223 | * and 0x24 in DCR3 | ||
2224 | */ | ||
2225 | Data = 0x01; | ||
2226 | status = set_reg_sync(serial->port[i], | ||
2227 | (__u16)(ATEN2011_port->DcrRegOffset + 0), | ||
2228 | Data); | ||
2229 | if (status < 0) { | ||
2230 | dbg("Writing DCR0 failed status-0x%x", status); | ||
2231 | break; | ||
2232 | } else | ||
2233 | dbg("DCR0 Writing success status%d", status); | ||
2234 | |||
2235 | Data = 0x05; | ||
2236 | status = set_reg_sync(serial->port[i], | ||
2237 | (__u16)(ATEN2011_port->DcrRegOffset + 1), | ||
2238 | Data); | ||
2239 | if (status < 0) { | ||
2240 | dbg("Writing DCR1 failed status-0x%x", status); | ||
2241 | break; | ||
2242 | } else | ||
2243 | dbg("DCR1 Writing success status%d", status); | ||
2244 | |||
2245 | Data = 0x24; | ||
2246 | status = set_reg_sync(serial->port[i], | ||
2247 | (__u16)(ATEN2011_port->DcrRegOffset + 2), | ||
2248 | Data); | ||
2249 | if (status < 0) { | ||
2250 | dbg("Writing DCR2 failed status-0x%x", status); | ||
2251 | break; | ||
2252 | } else | ||
2253 | dbg("DCR2 Writing success status%d", status); | ||
2254 | |||
2255 | /* write values in clkstart0x0 and clkmulti 0x20 */ | ||
2256 | Data = 0x0; | ||
2257 | status = set_reg_sync(serial->port[i], CLK_START_VALUE_REGISTER, | ||
2258 | Data); | ||
2259 | if (status < 0) { | ||
2260 | dbg | ||
2261 | ("Writing CLK_START_VALUE_REGISTER failed status-0x%x", | ||
2262 | status); | ||
2263 | break; | ||
2264 | } else | ||
2265 | dbg | ||
2266 | ("CLK_START_VALUE_REGISTER Writing success status%d", | ||
2267 | status); | ||
2268 | |||
2269 | Data = 0x20; | ||
2270 | status = set_reg_sync(serial->port[i], CLK_MULTI_REGISTER, | ||
2271 | Data); | ||
2272 | if (status < 0) { | ||
2273 | dbg | ||
2274 | ("Writing CLK_MULTI_REGISTER failed status-0x%x", | ||
2275 | status); | ||
2276 | break; | ||
2277 | } else | ||
2278 | dbg("CLK_MULTI_REGISTER Writing success status%d", | ||
2279 | status); | ||
2280 | |||
2281 | /* Zero Length flag register */ | ||
2282 | if ((ATEN2011_port->port_num != 1) | ||
2283 | && (ATEN2011_serial->ATEN2011_spectrum_2or4ports == 2)) { | ||
2284 | |||
2285 | Data = 0xff; | ||
2286 | status = set_reg_sync(serial->port[i], | ||
2287 | (__u16)(ZLP_REG1 + ((__u16)ATEN2011_port->port_num)), | ||
2288 | Data); | ||
2289 | dbg("ZLIP offset%x", | ||
2290 | (__u16) (ZLP_REG1 + | ||
2291 | ((__u16) ATEN2011_port->port_num))); | ||
2292 | if (status < 0) { | ||
2293 | dbg | ||
2294 | ("Writing ZLP_REG%d failed status-0x%x", | ||
2295 | i + 2, status); | ||
2296 | break; | ||
2297 | } else | ||
2298 | dbg("ZLP_REG%d Writing success status%d", | ||
2299 | i + 2, status); | ||
2300 | } else { | ||
2301 | Data = 0xff; | ||
2302 | status = set_reg_sync(serial->port[i], | ||
2303 | (__u16)(ZLP_REG1 + ((__u16)ATEN2011_port->port_num) - 0x1), | ||
2304 | Data); | ||
2305 | dbg("ZLIP offset%x", | ||
2306 | (__u16) (ZLP_REG1 + | ||
2307 | ((__u16) ATEN2011_port->port_num) - | ||
2308 | 0x1)); | ||
2309 | if (status < 0) { | ||
2310 | dbg | ||
2311 | ("Writing ZLP_REG%d failed status-0x%x", | ||
2312 | i + 1, status); | ||
2313 | break; | ||
2314 | } else | ||
2315 | dbg("ZLP_REG%d Writing success status%d", | ||
2316 | i + 1, status); | ||
2317 | |||
2318 | } | ||
2319 | ATEN2011_port->control_urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
2320 | ATEN2011_port->ctrl_buf = kmalloc(16, GFP_KERNEL); | ||
2321 | |||
2322 | } | ||
2323 | |||
2324 | /* Zero Length flag enable */ | ||
2325 | Data = 0x0f; | ||
2326 | status = set_reg_sync(serial->port[0], ZLP_REG5, Data); | ||
2327 | if (status < 0) { | ||
2328 | dbg("Writing ZLP_REG5 failed status-0x%x", status); | ||
2329 | return -1; | ||
2330 | } else | ||
2331 | dbg("ZLP_REG5 Writing success status%d", status); | ||
2332 | |||
2333 | /* setting configuration feature to one */ | ||
2334 | usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | ||
2335 | (__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5 * HZ); | ||
2336 | return 0; | ||
2337 | } | ||
2338 | |||
2339 | static void ATEN2011_release(struct usb_serial *serial) | ||
2340 | { | ||
2341 | int i; | ||
2342 | struct ATENINTL_port *ATEN2011_port; | ||
2343 | |||
2344 | /* check for the ports to be closed,close the ports and disconnect */ | ||
2345 | |||
2346 | /* free private structure allocated for serial port * | ||
2347 | * stop reads and writes on all ports */ | ||
2348 | |||
2349 | for (i = 0; i < serial->num_ports; ++i) { | ||
2350 | ATEN2011_port = usb_get_serial_port_data(serial->port[i]); | ||
2351 | kfree(ATEN2011_port->ctrl_buf); | ||
2352 | usb_kill_urb(ATEN2011_port->control_urb); | ||
2353 | kfree(ATEN2011_port); | ||
2354 | usb_set_serial_port_data(serial->port[i], NULL); | ||
2355 | } | ||
2356 | |||
2357 | /* free private structure allocated for serial device */ | ||
2358 | |||
2359 | kfree(usb_get_serial_data(serial)); | ||
2360 | usb_set_serial_data(serial, NULL); | ||
2361 | } | ||
2362 | |||
2363 | static struct usb_serial_driver aten_serial_driver = { | ||
2364 | .driver = { | ||
2365 | .owner = THIS_MODULE, | ||
2366 | .name = "aten2011", | ||
2367 | }, | ||
2368 | .description = DRIVER_DESC, | ||
2369 | .id_table = id_table, | ||
2370 | .open = ATEN2011_open, | ||
2371 | .close = ATEN2011_close, | ||
2372 | .write = ATEN2011_write, | ||
2373 | .write_room = ATEN2011_write_room, | ||
2374 | .chars_in_buffer = ATEN2011_chars_in_buffer, | ||
2375 | .throttle = ATEN2011_throttle, | ||
2376 | .unthrottle = ATEN2011_unthrottle, | ||
2377 | .calc_num_ports = ATEN2011_calc_num_ports, | ||
2378 | |||
2379 | .ioctl = ATEN2011_ioctl, | ||
2380 | .set_termios = ATEN2011_set_termios, | ||
2381 | .break_ctl = ATEN2011_break, | ||
2382 | .tiocmget = ATEN2011_tiocmget, | ||
2383 | .tiocmset = ATEN2011_tiocmset, | ||
2384 | .attach = ATEN2011_startup, | ||
2385 | .release = ATEN2011_release, | ||
2386 | .read_bulk_callback = ATEN2011_bulk_in_callback, | ||
2387 | .read_int_callback = ATEN2011_interrupt_callback, | ||
2388 | }; | ||
2389 | |||
2390 | static struct usb_driver aten_driver = { | ||
2391 | .name = "aten2011", | ||
2392 | .probe = usb_serial_probe, | ||
2393 | .disconnect = usb_serial_disconnect, | ||
2394 | .id_table = id_table, | ||
2395 | }; | ||
2396 | |||
2397 | static int __init aten_init(void) | ||
2398 | { | ||
2399 | int retval; | ||
2400 | |||
2401 | /* Register with the usb serial */ | ||
2402 | retval = usb_serial_register(&aten_serial_driver); | ||
2403 | if (retval) | ||
2404 | return retval; | ||
2405 | |||
2406 | printk(KERN_INFO KBUILD_MODNAME ":" | ||
2407 | DRIVER_DESC " " DRIVER_VERSION "\n"); | ||
2408 | |||
2409 | /* Register with the usb */ | ||
2410 | retval = usb_register(&aten_driver); | ||
2411 | if (retval) | ||
2412 | usb_serial_deregister(&aten_serial_driver); | ||
2413 | |||
2414 | return retval; | ||
2415 | } | ||
2416 | |||
2417 | static void __exit aten_exit(void) | ||
2418 | { | ||
2419 | usb_deregister(&aten_driver); | ||
2420 | usb_serial_deregister(&aten_serial_driver); | ||
2421 | } | ||
2422 | |||
2423 | module_init(aten_init); | ||
2424 | module_exit(aten_exit); | ||
2425 | |||
2426 | /* Module information */ | ||
2427 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
2428 | MODULE_LICENSE("GPL"); | ||
2429 | |||
2430 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | ||
diff --git a/drivers/staging/udlfb/udlfb.c b/drivers/staging/udlfb/udlfb.c index 0ab9d15f3439..f5416af1e902 100644 --- a/drivers/staging/udlfb/udlfb.c +++ b/drivers/staging/udlfb/udlfb.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/mm.h> | 21 | #include <linux/mm.h> |
22 | #include <linux/fb.h> | 22 | #include <linux/fb.h> |
23 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
24 | #include <linux/vmalloc.h> | ||
24 | 25 | ||
25 | #include "udlfb.h" | 26 | #include "udlfb.h" |
26 | 27 | ||