diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/usb/serial/io_edgeport.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/usb/serial/io_edgeport.c')
-rw-r--r-- | drivers/usb/serial/io_edgeport.c | 3113 |
1 files changed, 3113 insertions, 0 deletions
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c new file mode 100644 index 000000000000..e35b5adcd5fe --- /dev/null +++ b/drivers/usb/serial/io_edgeport.c | |||
@@ -0,0 +1,3113 @@ | |||
1 | /* | ||
2 | * Edgeport USB Serial Converter driver | ||
3 | * | ||
4 | * Copyright (C) 2000 Inside Out Networks, All rights reserved. | ||
5 | * Copyright (C) 2001-2002 Greg Kroah-Hartman <greg@kroah.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * Supports the following devices: | ||
13 | * Edgeport/4 | ||
14 | * Edgeport/4t | ||
15 | * Edgeport/2 | ||
16 | * Edgeport/4i | ||
17 | * Edgeport/2i | ||
18 | * Edgeport/421 | ||
19 | * Edgeport/21 | ||
20 | * Rapidport/4 | ||
21 | * Edgeport/8 | ||
22 | * Edgeport/2D8 | ||
23 | * Edgeport/4D8 | ||
24 | * Edgeport/8i | ||
25 | * | ||
26 | * For questions or problems with this driver, contact Inside Out | ||
27 | * Networks technical support, or Peter Berger <pberger@brimson.com>, | ||
28 | * or Al Borchers <alborchers@steinerpoint.com>. | ||
29 | * | ||
30 | * Version history: | ||
31 | * | ||
32 | * 2003_04_03 al borchers | ||
33 | * - fixed a bug (that shows up with dosemu) where the tty struct is | ||
34 | * used in a callback after it has been freed | ||
35 | * | ||
36 | * 2.3 2002_03_08 greg kroah-hartman | ||
37 | * - fixed bug when multiple devices were attached at the same time. | ||
38 | * | ||
39 | * 2.2 2001_11_14 greg kroah-hartman | ||
40 | * - fixed bug in edge_close that kept the port from being used more | ||
41 | * than once. | ||
42 | * - fixed memory leak on device removal. | ||
43 | * - fixed potential double free of memory when command urb submitting | ||
44 | * failed. | ||
45 | * - other small cleanups when the device is removed | ||
46 | * | ||
47 | * 2.1 2001_07_09 greg kroah-hartman | ||
48 | * - added support for TIOCMBIS and TIOCMBIC. | ||
49 | * | ||
50 | * (04/08/2001) gb | ||
51 | * - Identify version on module load. | ||
52 | * | ||
53 | * 2.0 2001_03_05 greg kroah-hartman | ||
54 | * - reworked entire driver to fit properly in with the other usb-serial | ||
55 | * drivers. Occasional oopses still happen, but it's a good start. | ||
56 | * | ||
57 | * 1.2.3 (02/23/2001) greg kroah-hartman | ||
58 | * - changed device table to work properly for 2.4.x final format. | ||
59 | * - fixed problem with dropping data at high data rates. | ||
60 | * | ||
61 | * 1.2.2 (11/27/2000) greg kroah-hartman | ||
62 | * - cleaned up more NTisms. | ||
63 | * - Added device table for 2.4.0-test11 | ||
64 | * | ||
65 | * 1.2.1 (11/08/2000) greg kroah-hartman | ||
66 | * - Started to clean up NTisms. | ||
67 | * - Fixed problem with dev field of urb for kernels >= 2.4.0-test9 | ||
68 | * | ||
69 | * 1.2 (10/17/2000) David Iacovelli | ||
70 | * Remove all EPIC code and GPL source | ||
71 | * Fix RELEVANT_IFLAG macro to include flow control | ||
72 | * changes port configuration changes. | ||
73 | * Fix redefinition of SERIAL_MAGIC | ||
74 | * Change all timeout values to 5 seconds | ||
75 | * Tried to fix the UHCI multiple urb submission, but failed miserably. | ||
76 | * it seems to work fine with OHCI. | ||
77 | * ( Greg take a look at the #if 0 at end of WriteCmdUsb() we must | ||
78 | * find a way to work arount this UHCI bug ) | ||
79 | * | ||
80 | * 1.1 (10/11/2000) David Iacovelli | ||
81 | * Fix XON/XOFF flow control to support both IXON and IXOFF | ||
82 | * | ||
83 | * 0.9.27 (06/30/2000) David Iacovelli | ||
84 | * Added transmit queue and now allocate urb for command writes. | ||
85 | * | ||
86 | * 0.9.26 (06/29/2000) David Iacovelli | ||
87 | * Add support for 80251 based edgeport | ||
88 | * | ||
89 | * 0.9.25 (06/27/2000) David Iacovelli | ||
90 | * Do not close the port if it has multiple opens. | ||
91 | * | ||
92 | * 0.9.24 (05/26/2000) David Iacovelli | ||
93 | * Add IOCTLs to support RXTX and JAVA POS | ||
94 | * and first cut at running BlackBox Demo | ||
95 | * | ||
96 | * 0.9.23 (05/24/2000) David Iacovelli | ||
97 | * Add IOCTLs to support RXTX and JAVA POS | ||
98 | * | ||
99 | * 0.9.22 (05/23/2000) David Iacovelli | ||
100 | * fixed bug in enumeration. If epconfig turns on mapping by | ||
101 | * path after a device is already plugged in, we now update | ||
102 | * the mapping correctly | ||
103 | * | ||
104 | * 0.9.21 (05/16/2000) David Iacovelli | ||
105 | * Added BlockUntilChaseResp() to also wait for txcredits | ||
106 | * Updated the way we allocate and handle write URBs | ||
107 | * Add debug code to dump buffers | ||
108 | * | ||
109 | * 0.9.20 (05/01/2000) David Iacovelli | ||
110 | * change driver to use usb/tts/ | ||
111 | * | ||
112 | * 0.9.19 (05/01/2000) David Iacovelli | ||
113 | * Update code to compile if DEBUG is off | ||
114 | * | ||
115 | * 0.9.18 (04/28/2000) David Iacovelli | ||
116 | * cleanup and test tty_register with devfs | ||
117 | * | ||
118 | * 0.9.17 (04/27/2000) greg kroah-hartman | ||
119 | * changed tty_register around to be like the way it | ||
120 | * was before, but now it works properly with devfs. | ||
121 | * | ||
122 | * 0.9.16 (04/26/2000) david iacovelli | ||
123 | * Fixed bug in GetProductInfo() | ||
124 | * | ||
125 | * 0.9.15 (04/25/2000) david iacovelli | ||
126 | * Updated enumeration | ||
127 | * | ||
128 | * 0.9.14 (04/24/2000) david iacovelli | ||
129 | * Removed all config/status IOCTLS and | ||
130 | * converted to using /proc/edgeport | ||
131 | * still playing with devfs | ||
132 | * | ||
133 | * 0.9.13 (04/24/2000) david iacovelli | ||
134 | * Removed configuration based on ttyUSB0 | ||
135 | * Added support for configuration using /prod/edgeport | ||
136 | * first attempt at using devfs (not working yet!) | ||
137 | * Added IOCTL to GetProductInfo() | ||
138 | * Added support for custom baud rates | ||
139 | * Add support for random port numbers | ||
140 | * | ||
141 | * 0.9.12 (04/18/2000) david iacovelli | ||
142 | * added additional configuration IOCTLs | ||
143 | * use ttyUSB0 for configuration | ||
144 | * | ||
145 | * 0.9.11 (04/17/2000) greg kroah-hartman | ||
146 | * fixed module initialization race conditions. | ||
147 | * made all urbs dynamically allocated. | ||
148 | * made driver devfs compatible. now it only registers the tty device | ||
149 | * when the device is actually plugged in. | ||
150 | * | ||
151 | * 0.9.10 (04/13/2000) greg kroah-hartman | ||
152 | * added proc interface framework. | ||
153 | * | ||
154 | * 0.9.9 (04/13/2000) david iacovelli | ||
155 | * added enumeration code and ioctls to configure the device | ||
156 | * | ||
157 | * 0.9.8 (04/12/2000) david iacovelli | ||
158 | * Change interrupt read start when device is plugged in | ||
159 | * and stop when device is removed | ||
160 | * process interrupt reads when all ports are closed | ||
161 | * (keep value of rxBytesAvail consistent with the edgeport) | ||
162 | * set the USB_BULK_QUEUE flag so that we can shove a bunch | ||
163 | * of urbs at once down the pipe | ||
164 | * | ||
165 | * 0.9.7 (04/10/2000) david iacovelli | ||
166 | * start to add enumeration code. | ||
167 | * generate serial number for epic devices | ||
168 | * add support for kdb | ||
169 | * | ||
170 | * 0.9.6 (03/30/2000) david iacovelli | ||
171 | * add IOCTL to get string, manufacture, and boot descriptors | ||
172 | * | ||
173 | * 0.9.5 (03/14/2000) greg kroah-hartman | ||
174 | * more error checking added to SerialOpen to try to fix UHCI open problem | ||
175 | * | ||
176 | * 0.9.4 (03/09/2000) greg kroah-hartman | ||
177 | * added more error checking to handle oops when data is hanging | ||
178 | * around and tty is abruptly closed. | ||
179 | * | ||
180 | * 0.9.3 (03/09/2000) david iacovelli | ||
181 | * Add epic support for xon/xoff chars | ||
182 | * play with performance | ||
183 | * | ||
184 | * 0.9.2 (03/08/2000) greg kroah-hartman | ||
185 | * changed most "info" calls to "dbg" | ||
186 | * implemented flow control properly in the termios call | ||
187 | * | ||
188 | * 0.9.1 (03/08/2000) david iacovelli | ||
189 | * added EPIC support | ||
190 | * enabled bootloader update | ||
191 | * | ||
192 | * 0.9 (03/08/2000) greg kroah-hartman | ||
193 | * Release to IO networks. | ||
194 | * Integrated changes that David made | ||
195 | * made getting urbs for writing SMP safe | ||
196 | * | ||
197 | * 0.8 (03/07/2000) greg kroah-hartman | ||
198 | * Release to IO networks. | ||
199 | * Fixed problems that were seen in code by David. | ||
200 | * Now both Edgeport/4 and Edgeport/2 works properly. | ||
201 | * Changed most of the functions to use port instead of serial. | ||
202 | * | ||
203 | * 0.7 (02/27/2000) greg kroah-hartman | ||
204 | * Milestone 3 release. | ||
205 | * Release to IO Networks | ||
206 | * ioctl for waiting on line change implemented. | ||
207 | * ioctl for getting statistics implemented. | ||
208 | * multiport support working. | ||
209 | * lsr and msr registers are now handled properly. | ||
210 | * change break now hooked up and working. | ||
211 | * support for all known Edgeport devices. | ||
212 | * | ||
213 | * 0.6 (02/22/2000) greg kroah-hartman | ||
214 | * Release to IO networks. | ||
215 | * CHASE is implemented correctly when port is closed. | ||
216 | * SerialOpen now blocks correctly until port is fully opened. | ||
217 | * | ||
218 | * 0.5 (02/20/2000) greg kroah-hartman | ||
219 | * Release to IO networks. | ||
220 | * Known problems: | ||
221 | * modem status register changes are not sent on to the user | ||
222 | * CHASE is not implemented when the port is closed. | ||
223 | * | ||
224 | * 0.4 (02/16/2000) greg kroah-hartman | ||
225 | * Second cut at the CeBit demo. | ||
226 | * Doesn't leak memory on every write to the port | ||
227 | * Still small leaks on startup. | ||
228 | * Added support for Edgeport/2 and Edgeport/8 | ||
229 | * | ||
230 | * 0.3 (02/15/2000) greg kroah-hartman | ||
231 | * CeBit demo release. | ||
232 | * Force the line settings to 4800, 8, 1, e for the demo. | ||
233 | * Warning! This version leaks memory like crazy! | ||
234 | * | ||
235 | * 0.2 (01/30/2000) greg kroah-hartman | ||
236 | * Milestone 1 release. | ||
237 | * Device is found by USB subsystem, enumerated, fimware is downloaded | ||
238 | * and the descriptors are printed to the debug log, config is set, and | ||
239 | * green light starts to blink. Open port works, and data can be sent | ||
240 | * and received at the default settings of the UART. Loopback connector | ||
241 | * and debug log confirms this. | ||
242 | * | ||
243 | * 0.1 (01/23/2000) greg kroah-hartman | ||
244 | * Initial release to help IO Networks try to set up their test system. | ||
245 | * Edgeport4 is recognized, firmware is downloaded, config is set so | ||
246 | * device blinks green light every 3 sec. Port is bound, but opening, | ||
247 | * closing, and sending data do not work properly. | ||
248 | * | ||
249 | */ | ||
250 | |||
251 | #include <linux/config.h> | ||
252 | #include <linux/kernel.h> | ||
253 | #include <linux/jiffies.h> | ||
254 | #include <linux/errno.h> | ||
255 | #include <linux/init.h> | ||
256 | #include <linux/slab.h> | ||
257 | #include <linux/tty.h> | ||
258 | #include <linux/tty_driver.h> | ||
259 | #include <linux/tty_flip.h> | ||
260 | #include <linux/module.h> | ||
261 | #include <linux/spinlock.h> | ||
262 | #include <linux/serial.h> | ||
263 | #include <linux/ioctl.h> | ||
264 | #include <linux/wait.h> | ||
265 | #include <asm/uaccess.h> | ||
266 | #include <linux/usb.h> | ||
267 | #include "usb-serial.h" | ||
268 | #include "io_edgeport.h" | ||
269 | #include "io_ionsp.h" /* info for the iosp messages */ | ||
270 | #include "io_16654.h" /* 16654 UART defines */ | ||
271 | |||
272 | /* | ||
273 | * Version Information | ||
274 | */ | ||
275 | #define DRIVER_VERSION "v2.7" | ||
276 | #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli" | ||
277 | #define DRIVER_DESC "Edgeport USB Serial Driver" | ||
278 | |||
279 | /* First, the latest boot code - for first generation edgeports */ | ||
280 | #define IMAGE_ARRAY_NAME BootCodeImage_GEN1 | ||
281 | #define IMAGE_VERSION_NAME BootCodeImageVersion_GEN1 | ||
282 | #include "io_fw_boot.h" /* the bootloader firmware to download to a device, if it needs it */ | ||
283 | |||
284 | /* for second generation edgeports */ | ||
285 | #define IMAGE_ARRAY_NAME BootCodeImage_GEN2 | ||
286 | #define IMAGE_VERSION_NAME BootCodeImageVersion_GEN2 | ||
287 | #include "io_fw_boot2.h" /* the bootloader firmware to download to a device, if it needs it */ | ||
288 | |||
289 | /* Then finally the main run-time operational code - for first generation edgeports */ | ||
290 | #define IMAGE_ARRAY_NAME OperationalCodeImage_GEN1 | ||
291 | #define IMAGE_VERSION_NAME OperationalCodeImageVersion_GEN1 | ||
292 | #include "io_fw_down.h" /* Define array OperationalCodeImage[] */ | ||
293 | |||
294 | /* for second generation edgeports */ | ||
295 | #define IMAGE_ARRAY_NAME OperationalCodeImage_GEN2 | ||
296 | #define IMAGE_VERSION_NAME OperationalCodeImageVersion_GEN2 | ||
297 | #include "io_fw_down2.h" /* Define array OperationalCodeImage[] */ | ||
298 | |||
299 | #define MAX_NAME_LEN 64 | ||
300 | |||
301 | #define CHASE_TIMEOUT (5*HZ) /* 5 seconds */ | ||
302 | #define OPEN_TIMEOUT (5*HZ) /* 5 seconds */ | ||
303 | #define COMMAND_TIMEOUT (5*HZ) /* 5 seconds */ | ||
304 | |||
305 | /* receive port state */ | ||
306 | enum RXSTATE { | ||
307 | EXPECT_HDR1 = 0, /* Expect header byte 1 */ | ||
308 | EXPECT_HDR2 = 1, /* Expect header byte 2 */ | ||
309 | EXPECT_DATA = 2, /* Expect 'RxBytesRemaining' data */ | ||
310 | EXPECT_HDR3 = 3, /* Expect header byte 3 (for status hdrs only) */ | ||
311 | }; | ||
312 | |||
313 | |||
314 | /* Transmit Fifo | ||
315 | * This Transmit queue is an extension of the edgeport Rx buffer. | ||
316 | * The maximum amount of data buffered in both the edgeport | ||
317 | * Rx buffer (maxTxCredits) and this buffer will never exceed maxTxCredits. | ||
318 | */ | ||
319 | struct TxFifo { | ||
320 | unsigned int head; /* index to head pointer (write) */ | ||
321 | unsigned int tail; /* index to tail pointer (read) */ | ||
322 | unsigned int count; /* Bytes in queue */ | ||
323 | unsigned int size; /* Max size of queue (equal to Max number of TxCredits) */ | ||
324 | unsigned char *fifo; /* allocated Buffer */ | ||
325 | }; | ||
326 | |||
327 | /* This structure holds all of the local port information */ | ||
328 | struct edgeport_port { | ||
329 | __u16 txCredits; /* our current credits for this port */ | ||
330 | __u16 maxTxCredits; /* the max size of the port */ | ||
331 | |||
332 | struct TxFifo txfifo; /* transmit fifo -- size will be maxTxCredits */ | ||
333 | struct urb *write_urb; /* write URB for this port */ | ||
334 | char write_in_progress; /* TRUE while a write URB is outstanding */ | ||
335 | spinlock_t ep_lock; | ||
336 | |||
337 | __u8 shadowLCR; /* last LCR value received */ | ||
338 | __u8 shadowMCR; /* last MCR value received */ | ||
339 | __u8 shadowMSR; /* last MSR value received */ | ||
340 | __u8 shadowLSR; /* last LSR value received */ | ||
341 | __u8 shadowXonChar; /* last value set as XON char in Edgeport */ | ||
342 | __u8 shadowXoffChar; /* last value set as XOFF char in Edgeport */ | ||
343 | __u8 validDataMask; | ||
344 | __u32 baudRate; | ||
345 | |||
346 | char open; | ||
347 | char openPending; | ||
348 | char commandPending; | ||
349 | char closePending; | ||
350 | char chaseResponsePending; | ||
351 | |||
352 | wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */ | ||
353 | wait_queue_head_t wait_open; /* for handling sleeping while waiting for open to finish */ | ||
354 | wait_queue_head_t wait_command; /* for handling sleeping while waiting for command to finish */ | ||
355 | wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */ | ||
356 | |||
357 | struct async_icount icount; | ||
358 | struct usb_serial_port *port; /* loop back to the owner of this object */ | ||
359 | }; | ||
360 | |||
361 | |||
362 | /* This structure holds all of the individual device information */ | ||
363 | struct edgeport_serial { | ||
364 | char name[MAX_NAME_LEN+1]; /* string name of this device */ | ||
365 | |||
366 | struct edge_manuf_descriptor manuf_descriptor; /* the manufacturer descriptor */ | ||
367 | struct edge_boot_descriptor boot_descriptor; /* the boot firmware descriptor */ | ||
368 | struct edgeport_product_info product_info; /* Product Info */ | ||
369 | |||
370 | __u8 interrupt_in_endpoint; /* the interrupt endpoint handle */ | ||
371 | unsigned char * interrupt_in_buffer; /* the buffer we use for the interrupt endpoint */ | ||
372 | struct urb * interrupt_read_urb; /* our interrupt urb */ | ||
373 | |||
374 | __u8 bulk_in_endpoint; /* the bulk in endpoint handle */ | ||
375 | unsigned char * bulk_in_buffer; /* the buffer we use for the bulk in endpoint */ | ||
376 | struct urb * read_urb; /* our bulk read urb */ | ||
377 | int read_in_progress; | ||
378 | spinlock_t es_lock; | ||
379 | |||
380 | __u8 bulk_out_endpoint; /* the bulk out endpoint handle */ | ||
381 | |||
382 | __s16 rxBytesAvail; /* the number of bytes that we need to read from this device */ | ||
383 | |||
384 | enum RXSTATE rxState; /* the current state of the bulk receive processor */ | ||
385 | __u8 rxHeader1; /* receive header byte 1 */ | ||
386 | __u8 rxHeader2; /* receive header byte 2 */ | ||
387 | __u8 rxHeader3; /* receive header byte 3 */ | ||
388 | __u8 rxPort; /* the port that we are currently receiving data for */ | ||
389 | __u8 rxStatusCode; /* the receive status code */ | ||
390 | __u8 rxStatusParam; /* the receive status paramater */ | ||
391 | __s16 rxBytesRemaining; /* the number of port bytes left to read */ | ||
392 | struct usb_serial *serial; /* loop back to the owner of this object */ | ||
393 | }; | ||
394 | |||
395 | /* baud rate information */ | ||
396 | struct divisor_table_entry { | ||
397 | __u32 BaudRate; | ||
398 | __u16 Divisor; | ||
399 | }; | ||
400 | |||
401 | // | ||
402 | // Define table of divisors for Rev A EdgePort/4 hardware | ||
403 | // These assume a 3.6864MHz crystal, the standard /16, and | ||
404 | // MCR.7 = 0. | ||
405 | // | ||
406 | static struct divisor_table_entry divisor_table[] = { | ||
407 | { 50, 4608}, | ||
408 | { 75, 3072}, | ||
409 | { 110, 2095}, /* 2094.545455 => 230450 => .0217 % over */ | ||
410 | { 134, 1713}, /* 1713.011152 => 230398.5 => .00065% under */ | ||
411 | { 150, 1536}, | ||
412 | { 300, 768}, | ||
413 | { 600, 384}, | ||
414 | { 1200, 192}, | ||
415 | { 1800, 128}, | ||
416 | { 2400, 96}, | ||
417 | { 4800, 48}, | ||
418 | { 7200, 32}, | ||
419 | { 9600, 24}, | ||
420 | { 14400, 16}, | ||
421 | { 19200, 12}, | ||
422 | { 38400, 6}, | ||
423 | { 57600, 4}, | ||
424 | { 115200, 2}, | ||
425 | { 230400, 1}, | ||
426 | }; | ||
427 | |||
428 | /* local variables */ | ||
429 | static int debug; | ||
430 | |||
431 | static int low_latency = 1; /* tty low latency flag, on by default */ | ||
432 | |||
433 | static int CmdUrbs = 0; /* Number of outstanding Command Write Urbs */ | ||
434 | |||
435 | |||
436 | /* local function prototypes */ | ||
437 | |||
438 | /* function prototypes for all URB callbacks */ | ||
439 | static void edge_interrupt_callback (struct urb *urb, struct pt_regs *regs); | ||
440 | static void edge_bulk_in_callback (struct urb *urb, struct pt_regs *regs); | ||
441 | static void edge_bulk_out_data_callback (struct urb *urb, struct pt_regs *regs); | ||
442 | static void edge_bulk_out_cmd_callback (struct urb *urb, struct pt_regs *regs); | ||
443 | |||
444 | /* function prototypes for the usbserial callbacks */ | ||
445 | static int edge_open (struct usb_serial_port *port, struct file *filp); | ||
446 | static void edge_close (struct usb_serial_port *port, struct file *filp); | ||
447 | static int edge_write (struct usb_serial_port *port, const unsigned char *buf, int count); | ||
448 | static int edge_write_room (struct usb_serial_port *port); | ||
449 | static int edge_chars_in_buffer (struct usb_serial_port *port); | ||
450 | static void edge_throttle (struct usb_serial_port *port); | ||
451 | static void edge_unthrottle (struct usb_serial_port *port); | ||
452 | static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios); | ||
453 | static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg); | ||
454 | static void edge_break (struct usb_serial_port *port, int break_state); | ||
455 | static int edge_tiocmget (struct usb_serial_port *port, struct file *file); | ||
456 | static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear); | ||
457 | static int edge_startup (struct usb_serial *serial); | ||
458 | static void edge_shutdown (struct usb_serial *serial); | ||
459 | |||
460 | |||
461 | #include "io_tables.h" /* all of the devices that this driver supports */ | ||
462 | |||
463 | static struct usb_driver io_driver = { | ||
464 | .owner = THIS_MODULE, | ||
465 | .name = "io_edgeport", | ||
466 | .probe = usb_serial_probe, | ||
467 | .disconnect = usb_serial_disconnect, | ||
468 | .id_table = id_table_combined, | ||
469 | }; | ||
470 | |||
471 | /* function prototypes for all of our local functions */ | ||
472 | static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned char *buffer, __u16 bufferLength); | ||
473 | static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2, __u8 byte3); | ||
474 | static void edge_tty_recv (struct device *dev, struct tty_struct *tty, unsigned char *data, int length); | ||
475 | static void handle_new_msr (struct edgeport_port *edge_port, __u8 newMsr); | ||
476 | static void handle_new_lsr (struct edgeport_port *edge_port, __u8 lsrData, __u8 lsr, __u8 data); | ||
477 | static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u8 param); | ||
478 | static int calc_baud_rate_divisor (int baud_rate, int *divisor); | ||
479 | static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRate); | ||
480 | static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios); | ||
481 | static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 regNum, __u8 regValue); | ||
482 | static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer, int writeLength); | ||
483 | static void send_more_port_data (struct edgeport_serial *edge_serial, struct edgeport_port *edge_port); | ||
484 | |||
485 | static int sram_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data); | ||
486 | static int rom_read (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data); | ||
487 | static int rom_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data); | ||
488 | static void get_manufacturing_desc (struct edgeport_serial *edge_serial); | ||
489 | static void get_boot_desc (struct edgeport_serial *edge_serial); | ||
490 | static void load_application_firmware (struct edgeport_serial *edge_serial); | ||
491 | |||
492 | static void unicode_to_ascii (char *string, __le16 *unicode, int unicode_size); | ||
493 | |||
494 | |||
495 | // ************************************************************************ | ||
496 | // ************************************************************************ | ||
497 | // ************************************************************************ | ||
498 | // ************************************************************************ | ||
499 | |||
500 | /************************************************************************ | ||
501 | * * | ||
502 | * update_edgeport_E2PROM() Compare current versions of * | ||
503 | * Boot ROM and Manufacture * | ||
504 | * Descriptors with versions * | ||
505 | * embedded in this driver * | ||
506 | * * | ||
507 | ************************************************************************/ | ||
508 | static void update_edgeport_E2PROM (struct edgeport_serial *edge_serial) | ||
509 | { | ||
510 | __u32 BootCurVer; | ||
511 | __u32 BootNewVer; | ||
512 | __u8 BootMajorVersion; | ||
513 | __u8 BootMinorVersion; | ||
514 | __le16 BootBuildNumber; | ||
515 | __u8 *BootImage; | ||
516 | __u32 BootSize; | ||
517 | struct edge_firmware_image_record *record; | ||
518 | unsigned char *firmware; | ||
519 | int response; | ||
520 | |||
521 | |||
522 | switch (edge_serial->product_info.iDownloadFile) { | ||
523 | case EDGE_DOWNLOAD_FILE_I930: | ||
524 | BootMajorVersion = BootCodeImageVersion_GEN1.MajorVersion; | ||
525 | BootMinorVersion = BootCodeImageVersion_GEN1.MinorVersion; | ||
526 | BootBuildNumber = cpu_to_le16(BootCodeImageVersion_GEN1.BuildNumber); | ||
527 | BootImage = &BootCodeImage_GEN1[0]; | ||
528 | BootSize = sizeof( BootCodeImage_GEN1 ); | ||
529 | break; | ||
530 | |||
531 | case EDGE_DOWNLOAD_FILE_80251: | ||
532 | BootMajorVersion = BootCodeImageVersion_GEN2.MajorVersion; | ||
533 | BootMinorVersion = BootCodeImageVersion_GEN2.MinorVersion; | ||
534 | BootBuildNumber = cpu_to_le16(BootCodeImageVersion_GEN2.BuildNumber); | ||
535 | BootImage = &BootCodeImage_GEN2[0]; | ||
536 | BootSize = sizeof( BootCodeImage_GEN2 ); | ||
537 | break; | ||
538 | |||
539 | default: | ||
540 | return; | ||
541 | } | ||
542 | |||
543 | // Check Boot Image Version | ||
544 | BootCurVer = (edge_serial->boot_descriptor.MajorVersion << 24) + | ||
545 | (edge_serial->boot_descriptor.MinorVersion << 16) + | ||
546 | le16_to_cpu(edge_serial->boot_descriptor.BuildNumber); | ||
547 | |||
548 | BootNewVer = (BootMajorVersion << 24) + | ||
549 | (BootMinorVersion << 16) + | ||
550 | le16_to_cpu(BootBuildNumber); | ||
551 | |||
552 | dbg("Current Boot Image version %d.%d.%d", | ||
553 | edge_serial->boot_descriptor.MajorVersion, | ||
554 | edge_serial->boot_descriptor.MinorVersion, | ||
555 | le16_to_cpu(edge_serial->boot_descriptor.BuildNumber)); | ||
556 | |||
557 | |||
558 | if (BootNewVer > BootCurVer) { | ||
559 | dbg("**Update Boot Image from %d.%d.%d to %d.%d.%d", | ||
560 | edge_serial->boot_descriptor.MajorVersion, | ||
561 | edge_serial->boot_descriptor.MinorVersion, | ||
562 | le16_to_cpu(edge_serial->boot_descriptor.BuildNumber), | ||
563 | BootMajorVersion, | ||
564 | BootMinorVersion, | ||
565 | le16_to_cpu(BootBuildNumber)); | ||
566 | |||
567 | |||
568 | dbg("Downloading new Boot Image"); | ||
569 | |||
570 | firmware = BootImage; | ||
571 | |||
572 | for (;;) { | ||
573 | record = (struct edge_firmware_image_record *)firmware; | ||
574 | response = rom_write (edge_serial->serial, le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), le16_to_cpu(record->Len), &record->Data[0]); | ||
575 | if (response < 0) { | ||
576 | dev_err(&edge_serial->serial->dev->dev, "rom_write failed (%x, %x, %d)\n", le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), le16_to_cpu(record->Len)); | ||
577 | break; | ||
578 | } | ||
579 | firmware += sizeof (struct edge_firmware_image_record) + le16_to_cpu(record->Len); | ||
580 | if (firmware >= &BootImage[BootSize]) { | ||
581 | break; | ||
582 | } | ||
583 | } | ||
584 | } else { | ||
585 | dbg("Boot Image -- already up to date"); | ||
586 | } | ||
587 | } | ||
588 | |||
589 | |||
590 | /************************************************************************ | ||
591 | * * | ||
592 | * Get string descriptor from device * | ||
593 | * * | ||
594 | ************************************************************************/ | ||
595 | static int get_string (struct usb_device *dev, int Id, char *string) | ||
596 | { | ||
597 | struct usb_string_descriptor StringDesc; | ||
598 | struct usb_string_descriptor *pStringDesc; | ||
599 | |||
600 | dbg("%s - USB String ID = %d", __FUNCTION__, Id ); | ||
601 | |||
602 | if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc, sizeof(StringDesc))) { | ||
603 | return 0; | ||
604 | } | ||
605 | |||
606 | pStringDesc = kmalloc (StringDesc.bLength, GFP_KERNEL); | ||
607 | |||
608 | if (!pStringDesc) { | ||
609 | return 0; | ||
610 | } | ||
611 | |||
612 | if (!usb_get_descriptor(dev, USB_DT_STRING, Id, pStringDesc, StringDesc.bLength )) { | ||
613 | kfree(pStringDesc); | ||
614 | return 0; | ||
615 | } | ||
616 | |||
617 | unicode_to_ascii(string, pStringDesc->wData, pStringDesc->bLength/2-1); | ||
618 | |||
619 | kfree(pStringDesc); | ||
620 | return strlen(string); | ||
621 | } | ||
622 | |||
623 | |||
624 | #if 0 | ||
625 | /************************************************************************ | ||
626 | * | ||
627 | * Get string descriptor from device | ||
628 | * | ||
629 | ************************************************************************/ | ||
630 | static int get_string_desc (struct usb_device *dev, int Id, struct usb_string_descriptor **pRetDesc) | ||
631 | { | ||
632 | struct usb_string_descriptor StringDesc; | ||
633 | struct usb_string_descriptor *pStringDesc; | ||
634 | |||
635 | dbg("%s - USB String ID = %d", __FUNCTION__, Id ); | ||
636 | |||
637 | if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc, sizeof(StringDesc))) { | ||
638 | return 0; | ||
639 | } | ||
640 | |||
641 | pStringDesc = kmalloc (StringDesc.bLength, GFP_KERNEL); | ||
642 | |||
643 | if (!pStringDesc) { | ||
644 | return -1; | ||
645 | } | ||
646 | |||
647 | if (!usb_get_descriptor(dev, USB_DT_STRING, Id, pStringDesc, StringDesc.bLength )) { | ||
648 | kfree(pStringDesc); | ||
649 | return -1; | ||
650 | } | ||
651 | |||
652 | *pRetDesc = pStringDesc; | ||
653 | return 0; | ||
654 | } | ||
655 | #endif | ||
656 | |||
657 | static void get_product_info(struct edgeport_serial *edge_serial) | ||
658 | { | ||
659 | struct edgeport_product_info *product_info = &edge_serial->product_info; | ||
660 | |||
661 | memset (product_info, 0, sizeof(struct edgeport_product_info)); | ||
662 | |||
663 | product_info->ProductId = (__u16)(le16_to_cpu(edge_serial->serial->dev->descriptor.idProduct) & ~ION_DEVICE_ID_80251_NETCHIP); | ||
664 | product_info->NumPorts = edge_serial->manuf_descriptor.NumPorts; | ||
665 | product_info->ProdInfoVer = 0; | ||
666 | |||
667 | product_info->RomSize = edge_serial->manuf_descriptor.RomSize; | ||
668 | product_info->RamSize = edge_serial->manuf_descriptor.RamSize; | ||
669 | product_info->CpuRev = edge_serial->manuf_descriptor.CpuRev; | ||
670 | product_info->BoardRev = edge_serial->manuf_descriptor.BoardRev; | ||
671 | |||
672 | product_info->BootMajorVersion = edge_serial->boot_descriptor.MajorVersion; | ||
673 | product_info->BootMinorVersion = edge_serial->boot_descriptor.MinorVersion; | ||
674 | product_info->BootBuildNumber = edge_serial->boot_descriptor.BuildNumber; | ||
675 | |||
676 | memcpy(product_info->ManufactureDescDate, edge_serial->manuf_descriptor.DescDate, sizeof(edge_serial->manuf_descriptor.DescDate)); | ||
677 | |||
678 | // check if this is 2nd generation hardware | ||
679 | if (le16_to_cpu(edge_serial->serial->dev->descriptor.idProduct) & ION_DEVICE_ID_80251_NETCHIP) { | ||
680 | product_info->FirmwareMajorVersion = OperationalCodeImageVersion_GEN2.MajorVersion; | ||
681 | product_info->FirmwareMinorVersion = OperationalCodeImageVersion_GEN2.MinorVersion; | ||
682 | product_info->FirmwareBuildNumber = cpu_to_le16(OperationalCodeImageVersion_GEN2.BuildNumber); | ||
683 | product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_80251; | ||
684 | } else { | ||
685 | product_info->FirmwareMajorVersion = OperationalCodeImageVersion_GEN1.MajorVersion; | ||
686 | product_info->FirmwareMinorVersion = OperationalCodeImageVersion_GEN1.MinorVersion; | ||
687 | product_info->FirmwareBuildNumber = cpu_to_le16(OperationalCodeImageVersion_GEN1.BuildNumber); | ||
688 | product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_I930; | ||
689 | } | ||
690 | |||
691 | // Determine Product type and set appropriate flags | ||
692 | switch (DEVICE_ID_FROM_USB_PRODUCT_ID(product_info->ProductId)) { | ||
693 | case ION_DEVICE_ID_EDGEPORT_COMPATIBLE: | ||
694 | case ION_DEVICE_ID_EDGEPORT_4T: | ||
695 | case ION_DEVICE_ID_EDGEPORT_4: | ||
696 | case ION_DEVICE_ID_EDGEPORT_2: | ||
697 | case ION_DEVICE_ID_EDGEPORT_8_DUAL_CPU: | ||
698 | case ION_DEVICE_ID_EDGEPORT_8: | ||
699 | case ION_DEVICE_ID_EDGEPORT_421: | ||
700 | case ION_DEVICE_ID_EDGEPORT_21: | ||
701 | case ION_DEVICE_ID_EDGEPORT_2_DIN: | ||
702 | case ION_DEVICE_ID_EDGEPORT_4_DIN: | ||
703 | case ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU: | ||
704 | product_info->IsRS232 = 1; | ||
705 | break; | ||
706 | |||
707 | case ION_DEVICE_ID_EDGEPORT_2I: // Edgeport/2 RS422/RS485 | ||
708 | product_info->IsRS422 = 1; | ||
709 | product_info->IsRS485 = 1; | ||
710 | break; | ||
711 | |||
712 | case ION_DEVICE_ID_EDGEPORT_8I: // Edgeport/4 RS422 | ||
713 | case ION_DEVICE_ID_EDGEPORT_4I: // Edgeport/4 RS422 | ||
714 | product_info->IsRS422 = 1; | ||
715 | break; | ||
716 | } | ||
717 | |||
718 | // Dump Product Info structure | ||
719 | dbg("**Product Information:"); | ||
720 | dbg(" ProductId %x", product_info->ProductId ); | ||
721 | dbg(" NumPorts %d", product_info->NumPorts ); | ||
722 | dbg(" ProdInfoVer %d", product_info->ProdInfoVer ); | ||
723 | dbg(" IsServer %d", product_info->IsServer); | ||
724 | dbg(" IsRS232 %d", product_info->IsRS232 ); | ||
725 | dbg(" IsRS422 %d", product_info->IsRS422 ); | ||
726 | dbg(" IsRS485 %d", product_info->IsRS485 ); | ||
727 | dbg(" RomSize %d", product_info->RomSize ); | ||
728 | dbg(" RamSize %d", product_info->RamSize ); | ||
729 | dbg(" CpuRev %x", product_info->CpuRev ); | ||
730 | dbg(" BoardRev %x", product_info->BoardRev); | ||
731 | dbg(" BootMajorVersion %d.%d.%d", product_info->BootMajorVersion, | ||
732 | product_info->BootMinorVersion, | ||
733 | le16_to_cpu(product_info->BootBuildNumber)); | ||
734 | dbg(" FirmwareMajorVersion %d.%d.%d", product_info->FirmwareMajorVersion, | ||
735 | product_info->FirmwareMinorVersion, | ||
736 | le16_to_cpu(product_info->FirmwareBuildNumber)); | ||
737 | dbg(" ManufactureDescDate %d/%d/%d", product_info->ManufactureDescDate[0], | ||
738 | product_info->ManufactureDescDate[1], | ||
739 | product_info->ManufactureDescDate[2]+1900); | ||
740 | dbg(" iDownloadFile 0x%x", product_info->iDownloadFile); | ||
741 | |||
742 | } | ||
743 | |||
744 | |||
745 | /************************************************************************/ | ||
746 | /************************************************************************/ | ||
747 | /* U S B C A L L B A C K F U N C T I O N S */ | ||
748 | /* U S B C A L L B A C K F U N C T I O N S */ | ||
749 | /************************************************************************/ | ||
750 | /************************************************************************/ | ||
751 | |||
752 | /***************************************************************************** | ||
753 | * edge_interrupt_callback | ||
754 | * this is the callback function for when we have received data on the | ||
755 | * interrupt endpoint. | ||
756 | *****************************************************************************/ | ||
757 | static void edge_interrupt_callback (struct urb *urb, struct pt_regs *regs) | ||
758 | { | ||
759 | struct edgeport_serial *edge_serial = (struct edgeport_serial *)urb->context; | ||
760 | struct edgeport_port *edge_port; | ||
761 | struct usb_serial_port *port; | ||
762 | unsigned char *data = urb->transfer_buffer; | ||
763 | int length = urb->actual_length; | ||
764 | int bytes_avail; | ||
765 | int position; | ||
766 | int txCredits; | ||
767 | int portNumber; | ||
768 | int result; | ||
769 | |||
770 | dbg("%s", __FUNCTION__); | ||
771 | |||
772 | switch (urb->status) { | ||
773 | case 0: | ||
774 | /* success */ | ||
775 | break; | ||
776 | case -ECONNRESET: | ||
777 | case -ENOENT: | ||
778 | case -ESHUTDOWN: | ||
779 | /* this urb is terminated, clean up */ | ||
780 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
781 | return; | ||
782 | default: | ||
783 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
784 | goto exit; | ||
785 | } | ||
786 | |||
787 | // process this interrupt-read even if there are no ports open | ||
788 | if (length) { | ||
789 | usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __FUNCTION__, length, data); | ||
790 | |||
791 | if (length > 1) { | ||
792 | bytes_avail = data[0] | (data[1] << 8); | ||
793 | if (bytes_avail) { | ||
794 | spin_lock(&edge_serial->es_lock); | ||
795 | edge_serial->rxBytesAvail += bytes_avail; | ||
796 | dbg("%s - bytes_avail=%d, rxBytesAvail=%d, read_in_progress=%d", __FUNCTION__, bytes_avail, edge_serial->rxBytesAvail, edge_serial->read_in_progress); | ||
797 | |||
798 | if (edge_serial->rxBytesAvail > 0 && | ||
799 | !edge_serial->read_in_progress) { | ||
800 | dbg("%s - posting a read", __FUNCTION__); | ||
801 | edge_serial->read_in_progress = TRUE; | ||
802 | |||
803 | /* we have pending bytes on the bulk in pipe, send a request */ | ||
804 | edge_serial->read_urb->dev = edge_serial->serial->dev; | ||
805 | result = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC); | ||
806 | if (result) { | ||
807 | dev_err(&edge_serial->serial->dev->dev, "%s - usb_submit_urb(read bulk) failed with result = %d\n", __FUNCTION__, result); | ||
808 | edge_serial->read_in_progress = FALSE; | ||
809 | } | ||
810 | } | ||
811 | spin_unlock(&edge_serial->es_lock); | ||
812 | } | ||
813 | } | ||
814 | /* grab the txcredits for the ports if available */ | ||
815 | position = 2; | ||
816 | portNumber = 0; | ||
817 | while ((position < length) && (portNumber < edge_serial->serial->num_ports)) { | ||
818 | txCredits = data[position] | (data[position+1] << 8); | ||
819 | if (txCredits) { | ||
820 | port = edge_serial->serial->port[portNumber]; | ||
821 | edge_port = usb_get_serial_port_data(port); | ||
822 | if (edge_port->open) { | ||
823 | spin_lock(&edge_port->ep_lock); | ||
824 | edge_port->txCredits += txCredits; | ||
825 | spin_unlock(&edge_port->ep_lock); | ||
826 | dbg("%s - txcredits for port%d = %d", __FUNCTION__, portNumber, edge_port->txCredits); | ||
827 | |||
828 | /* tell the tty driver that something has changed */ | ||
829 | if (edge_port->port->tty) | ||
830 | tty_wakeup(edge_port->port->tty); | ||
831 | |||
832 | // Since we have more credit, check if more data can be sent | ||
833 | send_more_port_data(edge_serial, edge_port); | ||
834 | } | ||
835 | } | ||
836 | position += 2; | ||
837 | ++portNumber; | ||
838 | } | ||
839 | } | ||
840 | |||
841 | exit: | ||
842 | result = usb_submit_urb (urb, GFP_ATOMIC); | ||
843 | if (result) { | ||
844 | dev_err(&urb->dev->dev, "%s - Error %d submitting control urb\n", __FUNCTION__, result); | ||
845 | } | ||
846 | } | ||
847 | |||
848 | |||
849 | /***************************************************************************** | ||
850 | * edge_bulk_in_callback | ||
851 | * this is the callback function for when we have received data on the | ||
852 | * bulk in endpoint. | ||
853 | *****************************************************************************/ | ||
854 | static void edge_bulk_in_callback (struct urb *urb, struct pt_regs *regs) | ||
855 | { | ||
856 | struct edgeport_serial *edge_serial = (struct edgeport_serial *)urb->context; | ||
857 | unsigned char *data = urb->transfer_buffer; | ||
858 | int status; | ||
859 | __u16 raw_data_length; | ||
860 | |||
861 | dbg("%s", __FUNCTION__); | ||
862 | |||
863 | if (urb->status) { | ||
864 | dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); | ||
865 | edge_serial->read_in_progress = FALSE; | ||
866 | return; | ||
867 | } | ||
868 | |||
869 | if (urb->actual_length == 0) { | ||
870 | dbg("%s - read bulk callback with no data", __FUNCTION__); | ||
871 | edge_serial->read_in_progress = FALSE; | ||
872 | return; | ||
873 | } | ||
874 | |||
875 | raw_data_length = urb->actual_length; | ||
876 | |||
877 | usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __FUNCTION__, raw_data_length, data); | ||
878 | |||
879 | spin_lock(&edge_serial->es_lock); | ||
880 | |||
881 | /* decrement our rxBytes available by the number that we just got */ | ||
882 | edge_serial->rxBytesAvail -= raw_data_length; | ||
883 | |||
884 | dbg("%s - Received = %d, rxBytesAvail %d", __FUNCTION__, raw_data_length, edge_serial->rxBytesAvail); | ||
885 | |||
886 | process_rcvd_data (edge_serial, data, urb->actual_length); | ||
887 | |||
888 | /* check to see if there's any more data for us to read */ | ||
889 | if (edge_serial->rxBytesAvail > 0) { | ||
890 | dbg("%s - posting a read", __FUNCTION__); | ||
891 | edge_serial->read_urb->dev = edge_serial->serial->dev; | ||
892 | status = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC); | ||
893 | if (status) { | ||
894 | dev_err(&urb->dev->dev, "%s - usb_submit_urb(read bulk) failed, status = %d\n", __FUNCTION__, status); | ||
895 | edge_serial->read_in_progress = FALSE; | ||
896 | } | ||
897 | } else { | ||
898 | edge_serial->read_in_progress = FALSE; | ||
899 | } | ||
900 | |||
901 | spin_unlock(&edge_serial->es_lock); | ||
902 | } | ||
903 | |||
904 | |||
905 | /***************************************************************************** | ||
906 | * edge_bulk_out_data_callback | ||
907 | * this is the callback function for when we have finished sending serial data | ||
908 | * on the bulk out endpoint. | ||
909 | *****************************************************************************/ | ||
910 | static void edge_bulk_out_data_callback (struct urb *urb, struct pt_regs *regs) | ||
911 | { | ||
912 | struct edgeport_port *edge_port = (struct edgeport_port *)urb->context; | ||
913 | struct tty_struct *tty; | ||
914 | |||
915 | dbg("%s", __FUNCTION__); | ||
916 | |||
917 | if (urb->status) { | ||
918 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | ||
919 | } | ||
920 | |||
921 | tty = edge_port->port->tty; | ||
922 | |||
923 | if (tty && edge_port->open) { | ||
924 | /* let the tty driver wakeup if it has a special write_wakeup function */ | ||
925 | tty_wakeup(tty); | ||
926 | } | ||
927 | |||
928 | // Release the Write URB | ||
929 | edge_port->write_in_progress = FALSE; | ||
930 | |||
931 | // Check if more data needs to be sent | ||
932 | send_more_port_data((struct edgeport_serial *)(usb_get_serial_data(edge_port->port->serial)), edge_port); | ||
933 | } | ||
934 | |||
935 | |||
936 | /***************************************************************************** | ||
937 | * BulkOutCmdCallback | ||
938 | * this is the callback function for when we have finished sending a command | ||
939 | * on the bulk out endpoint. | ||
940 | *****************************************************************************/ | ||
941 | static void edge_bulk_out_cmd_callback (struct urb *urb, struct pt_regs *regs) | ||
942 | { | ||
943 | struct edgeport_port *edge_port = (struct edgeport_port *)urb->context; | ||
944 | struct tty_struct *tty; | ||
945 | int status = urb->status; | ||
946 | |||
947 | dbg("%s", __FUNCTION__); | ||
948 | |||
949 | CmdUrbs--; | ||
950 | dbg("%s - FREE URB %p (outstanding %d)", __FUNCTION__, urb, CmdUrbs); | ||
951 | |||
952 | |||
953 | /* clean up the transfer buffer */ | ||
954 | if (urb->transfer_buffer != NULL) { | ||
955 | kfree(urb->transfer_buffer); | ||
956 | } | ||
957 | |||
958 | /* Free the command urb */ | ||
959 | usb_free_urb (urb); | ||
960 | |||
961 | if (status) { | ||
962 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, status); | ||
963 | return; | ||
964 | } | ||
965 | |||
966 | /* Get pointer to tty */ | ||
967 | tty = edge_port->port->tty; | ||
968 | |||
969 | /* tell the tty driver that something has changed */ | ||
970 | if (tty && edge_port->open) | ||
971 | tty_wakeup(tty); | ||
972 | |||
973 | /* we have completed the command */ | ||
974 | edge_port->commandPending = FALSE; | ||
975 | wake_up(&edge_port->wait_command); | ||
976 | } | ||
977 | |||
978 | |||
979 | /***************************************************************************** | ||
980 | * Driver tty interface functions | ||
981 | *****************************************************************************/ | ||
982 | |||
983 | /***************************************************************************** | ||
984 | * SerialOpen | ||
985 | * this function is called by the tty driver when a port is opened | ||
986 | * If successful, we return 0 | ||
987 | * Otherwise we return a negative error number. | ||
988 | *****************************************************************************/ | ||
989 | static int edge_open (struct usb_serial_port *port, struct file * filp) | ||
990 | { | ||
991 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | ||
992 | struct usb_serial *serial; | ||
993 | struct edgeport_serial *edge_serial; | ||
994 | int response; | ||
995 | |||
996 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
997 | |||
998 | if (edge_port == NULL) | ||
999 | return -ENODEV; | ||
1000 | |||
1001 | if (port->tty) | ||
1002 | port->tty->low_latency = low_latency; | ||
1003 | |||
1004 | /* see if we've set up our endpoint info yet (can't set it up in edge_startup | ||
1005 | as the structures were not set up at that time.) */ | ||
1006 | serial = port->serial; | ||
1007 | edge_serial = usb_get_serial_data(serial); | ||
1008 | if (edge_serial == NULL) { | ||
1009 | return -ENODEV; | ||
1010 | } | ||
1011 | if (edge_serial->interrupt_in_buffer == NULL) { | ||
1012 | struct usb_serial_port *port0 = serial->port[0]; | ||
1013 | |||
1014 | /* not set up yet, so do it now */ | ||
1015 | edge_serial->interrupt_in_buffer = port0->interrupt_in_buffer; | ||
1016 | edge_serial->interrupt_in_endpoint = port0->interrupt_in_endpointAddress; | ||
1017 | edge_serial->interrupt_read_urb = port0->interrupt_in_urb; | ||
1018 | edge_serial->bulk_in_buffer = port0->bulk_in_buffer; | ||
1019 | edge_serial->bulk_in_endpoint = port0->bulk_in_endpointAddress; | ||
1020 | edge_serial->read_urb = port0->read_urb; | ||
1021 | edge_serial->bulk_out_endpoint = port0->bulk_out_endpointAddress; | ||
1022 | |||
1023 | /* set up our interrupt urb */ | ||
1024 | usb_fill_int_urb(edge_serial->interrupt_read_urb, | ||
1025 | serial->dev, | ||
1026 | usb_rcvintpipe(serial->dev, | ||
1027 | port0->interrupt_in_endpointAddress), | ||
1028 | port0->interrupt_in_buffer, | ||
1029 | edge_serial->interrupt_read_urb->transfer_buffer_length, | ||
1030 | edge_interrupt_callback, edge_serial, | ||
1031 | edge_serial->interrupt_read_urb->interval); | ||
1032 | |||
1033 | /* set up our bulk in urb */ | ||
1034 | usb_fill_bulk_urb(edge_serial->read_urb, serial->dev, | ||
1035 | usb_rcvbulkpipe(serial->dev, | ||
1036 | port0->bulk_in_endpointAddress), | ||
1037 | port0->bulk_in_buffer, | ||
1038 | edge_serial->read_urb->transfer_buffer_length, | ||
1039 | edge_bulk_in_callback, edge_serial); | ||
1040 | edge_serial->read_in_progress = FALSE; | ||
1041 | |||
1042 | /* start interrupt read for this edgeport | ||
1043 | * this interrupt will continue as long as the edgeport is connected */ | ||
1044 | response = usb_submit_urb (edge_serial->interrupt_read_urb, GFP_KERNEL); | ||
1045 | if (response) { | ||
1046 | dev_err(&port->dev, "%s - Error %d submitting control urb\n", __FUNCTION__, response); | ||
1047 | } | ||
1048 | } | ||
1049 | |||
1050 | /* initialize our wait queues */ | ||
1051 | init_waitqueue_head(&edge_port->wait_open); | ||
1052 | init_waitqueue_head(&edge_port->wait_chase); | ||
1053 | init_waitqueue_head(&edge_port->delta_msr_wait); | ||
1054 | init_waitqueue_head(&edge_port->wait_command); | ||
1055 | |||
1056 | /* initialize our icount structure */ | ||
1057 | memset (&(edge_port->icount), 0x00, sizeof(edge_port->icount)); | ||
1058 | |||
1059 | /* initialize our port settings */ | ||
1060 | edge_port->txCredits = 0; /* Can't send any data yet */ | ||
1061 | edge_port->shadowMCR = MCR_MASTER_IE; /* Must always set this bit to enable ints! */ | ||
1062 | edge_port->chaseResponsePending = FALSE; | ||
1063 | |||
1064 | /* send a open port command */ | ||
1065 | edge_port->openPending = TRUE; | ||
1066 | edge_port->open = FALSE; | ||
1067 | response = send_iosp_ext_cmd (edge_port, IOSP_CMD_OPEN_PORT, 0); | ||
1068 | |||
1069 | if (response < 0) { | ||
1070 | dev_err(&port->dev, "%s - error sending open port command\n", __FUNCTION__); | ||
1071 | edge_port->openPending = FALSE; | ||
1072 | return -ENODEV; | ||
1073 | } | ||
1074 | |||
1075 | /* now wait for the port to be completely opened */ | ||
1076 | wait_event_timeout(edge_port->wait_open, (edge_port->openPending != TRUE), OPEN_TIMEOUT); | ||
1077 | |||
1078 | if (edge_port->open == FALSE) { | ||
1079 | /* open timed out */ | ||
1080 | dbg("%s - open timedout", __FUNCTION__); | ||
1081 | edge_port->openPending = FALSE; | ||
1082 | return -ENODEV; | ||
1083 | } | ||
1084 | |||
1085 | /* create the txfifo */ | ||
1086 | edge_port->txfifo.head = 0; | ||
1087 | edge_port->txfifo.tail = 0; | ||
1088 | edge_port->txfifo.count = 0; | ||
1089 | edge_port->txfifo.size = edge_port->maxTxCredits; | ||
1090 | edge_port->txfifo.fifo = kmalloc (edge_port->maxTxCredits, GFP_KERNEL); | ||
1091 | |||
1092 | if (!edge_port->txfifo.fifo) { | ||
1093 | dbg("%s - no memory", __FUNCTION__); | ||
1094 | edge_close (port, filp); | ||
1095 | return -ENOMEM; | ||
1096 | } | ||
1097 | |||
1098 | /* Allocate a URB for the write */ | ||
1099 | edge_port->write_urb = usb_alloc_urb (0, GFP_KERNEL); | ||
1100 | edge_port->write_in_progress = FALSE; | ||
1101 | |||
1102 | if (!edge_port->write_urb) { | ||
1103 | dbg("%s - no memory", __FUNCTION__); | ||
1104 | edge_close (port, filp); | ||
1105 | return -ENOMEM; | ||
1106 | } | ||
1107 | |||
1108 | dbg("%s(%d) - Initialize TX fifo to %d bytes", __FUNCTION__, port->number, edge_port->maxTxCredits); | ||
1109 | |||
1110 | dbg("%s exited", __FUNCTION__); | ||
1111 | |||
1112 | return 0; | ||
1113 | } | ||
1114 | |||
1115 | |||
1116 | /************************************************************************ | ||
1117 | * | ||
1118 | * block_until_chase_response | ||
1119 | * | ||
1120 | * This function will block the close until one of the following: | ||
1121 | * 1. Response to our Chase comes from Edgeport | ||
1122 | * 2. A timout of 10 seconds without activity has expired | ||
1123 | * (1K of Edgeport data @ 2400 baud ==> 4 sec to empty) | ||
1124 | * | ||
1125 | ************************************************************************/ | ||
1126 | static void block_until_chase_response(struct edgeport_port *edge_port) | ||
1127 | { | ||
1128 | DEFINE_WAIT(wait); | ||
1129 | __u16 lastCredits; | ||
1130 | int timeout = 1*HZ; | ||
1131 | int loop = 10; | ||
1132 | |||
1133 | while (1) { | ||
1134 | // Save Last credits | ||
1135 | lastCredits = edge_port->txCredits; | ||
1136 | |||
1137 | // Did we get our Chase response | ||
1138 | if (edge_port->chaseResponsePending == FALSE) { | ||
1139 | dbg("%s - Got Chase Response", __FUNCTION__); | ||
1140 | |||
1141 | // did we get all of our credit back? | ||
1142 | if (edge_port->txCredits == edge_port->maxTxCredits ) { | ||
1143 | dbg("%s - Got all credits", __FUNCTION__); | ||
1144 | return; | ||
1145 | } | ||
1146 | } | ||
1147 | |||
1148 | // Block the thread for a while | ||
1149 | prepare_to_wait(&edge_port->wait_chase, &wait, TASK_UNINTERRUPTIBLE); | ||
1150 | schedule_timeout(timeout); | ||
1151 | finish_wait(&edge_port->wait_chase, &wait); | ||
1152 | |||
1153 | if (lastCredits == edge_port->txCredits) { | ||
1154 | // No activity.. count down. | ||
1155 | loop--; | ||
1156 | if (loop == 0) { | ||
1157 | edge_port->chaseResponsePending = FALSE; | ||
1158 | dbg("%s - Chase TIMEOUT", __FUNCTION__); | ||
1159 | return; | ||
1160 | } | ||
1161 | } else { | ||
1162 | // Reset timout value back to 10 seconds | ||
1163 | dbg("%s - Last %d, Current %d", __FUNCTION__, lastCredits, edge_port->txCredits); | ||
1164 | loop = 10; | ||
1165 | } | ||
1166 | } | ||
1167 | } | ||
1168 | |||
1169 | |||
1170 | /************************************************************************ | ||
1171 | * | ||
1172 | * block_until_tx_empty | ||
1173 | * | ||
1174 | * This function will block the close until one of the following: | ||
1175 | * 1. TX count are 0 | ||
1176 | * 2. The edgeport has stopped | ||
1177 | * 3. A timout of 3 seconds without activity has expired | ||
1178 | * | ||
1179 | ************************************************************************/ | ||
1180 | static void block_until_tx_empty (struct edgeport_port *edge_port) | ||
1181 | { | ||
1182 | DEFINE_WAIT(wait); | ||
1183 | struct TxFifo *fifo = &edge_port->txfifo; | ||
1184 | __u32 lastCount; | ||
1185 | int timeout = HZ/10; | ||
1186 | int loop = 30; | ||
1187 | |||
1188 | while (1) { | ||
1189 | // Save Last count | ||
1190 | lastCount = fifo->count; | ||
1191 | |||
1192 | // Is the Edgeport Buffer empty? | ||
1193 | if (lastCount == 0) { | ||
1194 | dbg("%s - TX Buffer Empty", __FUNCTION__); | ||
1195 | return; | ||
1196 | } | ||
1197 | |||
1198 | // Block the thread for a while | ||
1199 | prepare_to_wait (&edge_port->wait_chase, &wait, TASK_UNINTERRUPTIBLE); | ||
1200 | schedule_timeout(timeout); | ||
1201 | finish_wait(&edge_port->wait_chase, &wait); | ||
1202 | |||
1203 | dbg("%s wait", __FUNCTION__); | ||
1204 | |||
1205 | if (lastCount == fifo->count) { | ||
1206 | // No activity.. count down. | ||
1207 | loop--; | ||
1208 | if (loop == 0) { | ||
1209 | dbg("%s - TIMEOUT", __FUNCTION__); | ||
1210 | return; | ||
1211 | } | ||
1212 | } else { | ||
1213 | // Reset timout value back to seconds | ||
1214 | loop = 30; | ||
1215 | } | ||
1216 | } | ||
1217 | } | ||
1218 | |||
1219 | |||
1220 | /***************************************************************************** | ||
1221 | * edge_close | ||
1222 | * this function is called by the tty driver when a port is closed | ||
1223 | *****************************************************************************/ | ||
1224 | static void edge_close (struct usb_serial_port *port, struct file * filp) | ||
1225 | { | ||
1226 | struct edgeport_serial *edge_serial; | ||
1227 | struct edgeport_port *edge_port; | ||
1228 | int status; | ||
1229 | |||
1230 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
1231 | |||
1232 | edge_serial = usb_get_serial_data(port->serial); | ||
1233 | edge_port = usb_get_serial_port_data(port); | ||
1234 | if ((edge_serial == NULL) || (edge_port == NULL)) | ||
1235 | return; | ||
1236 | |||
1237 | // block until tx is empty | ||
1238 | block_until_tx_empty(edge_port); | ||
1239 | |||
1240 | edge_port->closePending = TRUE; | ||
1241 | |||
1242 | /* flush and chase */ | ||
1243 | edge_port->chaseResponsePending = TRUE; | ||
1244 | |||
1245 | dbg("%s - Sending IOSP_CMD_CHASE_PORT", __FUNCTION__); | ||
1246 | status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0); | ||
1247 | if (status == 0) { | ||
1248 | // block until chase finished | ||
1249 | block_until_chase_response(edge_port); | ||
1250 | } else { | ||
1251 | edge_port->chaseResponsePending = FALSE; | ||
1252 | } | ||
1253 | |||
1254 | /* close the port */ | ||
1255 | dbg("%s - Sending IOSP_CMD_CLOSE_PORT", __FUNCTION__); | ||
1256 | send_iosp_ext_cmd (edge_port, IOSP_CMD_CLOSE_PORT, 0); | ||
1257 | |||
1258 | //port->close = TRUE; | ||
1259 | edge_port->closePending = FALSE; | ||
1260 | edge_port->open = FALSE; | ||
1261 | edge_port->openPending = FALSE; | ||
1262 | |||
1263 | if (edge_port->write_urb) { | ||
1264 | usb_kill_urb(edge_port->write_urb); | ||
1265 | } | ||
1266 | |||
1267 | if (edge_port->write_urb) { | ||
1268 | /* if this urb had a transfer buffer already (old transfer) free it */ | ||
1269 | if (edge_port->write_urb->transfer_buffer != NULL) { | ||
1270 | kfree(edge_port->write_urb->transfer_buffer); | ||
1271 | } | ||
1272 | usb_free_urb (edge_port->write_urb); | ||
1273 | edge_port->write_urb = NULL; | ||
1274 | } | ||
1275 | if (edge_port->txfifo.fifo) { | ||
1276 | kfree(edge_port->txfifo.fifo); | ||
1277 | edge_port->txfifo.fifo = NULL; | ||
1278 | } | ||
1279 | |||
1280 | dbg("%s exited", __FUNCTION__); | ||
1281 | } | ||
1282 | |||
1283 | /***************************************************************************** | ||
1284 | * SerialWrite | ||
1285 | * this function is called by the tty driver when data should be written to | ||
1286 | * the port. | ||
1287 | * If successful, we return the number of bytes written, otherwise we return | ||
1288 | * a negative error number. | ||
1289 | *****************************************************************************/ | ||
1290 | static int edge_write (struct usb_serial_port *port, const unsigned char *data, int count) | ||
1291 | { | ||
1292 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | ||
1293 | struct TxFifo *fifo; | ||
1294 | int copySize; | ||
1295 | int bytesleft; | ||
1296 | int firsthalf; | ||
1297 | int secondhalf; | ||
1298 | unsigned long flags; | ||
1299 | |||
1300 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
1301 | |||
1302 | if (edge_port == NULL) | ||
1303 | return -ENODEV; | ||
1304 | |||
1305 | // get a pointer to the Tx fifo | ||
1306 | fifo = &edge_port->txfifo; | ||
1307 | |||
1308 | spin_lock_irqsave(&edge_port->ep_lock, flags); | ||
1309 | |||
1310 | // calculate number of bytes to put in fifo | ||
1311 | copySize = min ((unsigned int)count, (edge_port->txCredits - fifo->count)); | ||
1312 | |||
1313 | dbg("%s(%d) of %d byte(s) Fifo room %d -- will copy %d bytes", __FUNCTION__, | ||
1314 | port->number, count, edge_port->txCredits - fifo->count, copySize); | ||
1315 | |||
1316 | /* catch writes of 0 bytes which the tty driver likes to give us, and when txCredits is empty */ | ||
1317 | if (copySize == 0) { | ||
1318 | dbg("%s - copySize = Zero", __FUNCTION__); | ||
1319 | goto finish_write; | ||
1320 | } | ||
1321 | |||
1322 | // queue the data | ||
1323 | // since we can never overflow the buffer we do not have to check for full condition | ||
1324 | |||
1325 | // the copy is done is two parts -- first fill to the end of the buffer | ||
1326 | // then copy the reset from the start of the buffer | ||
1327 | |||
1328 | bytesleft = fifo->size - fifo->head; | ||
1329 | firsthalf = min (bytesleft, copySize); | ||
1330 | dbg("%s - copy %d bytes of %d into fifo ", __FUNCTION__, firsthalf, bytesleft); | ||
1331 | |||
1332 | /* now copy our data */ | ||
1333 | memcpy(&fifo->fifo[fifo->head], data, firsthalf); | ||
1334 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, firsthalf, &fifo->fifo[fifo->head]); | ||
1335 | |||
1336 | // update the index and size | ||
1337 | fifo->head += firsthalf; | ||
1338 | fifo->count += firsthalf; | ||
1339 | |||
1340 | // wrap the index | ||
1341 | if (fifo->head == fifo->size) { | ||
1342 | fifo->head = 0; | ||
1343 | } | ||
1344 | |||
1345 | secondhalf = copySize-firsthalf; | ||
1346 | |||
1347 | if (secondhalf) { | ||
1348 | dbg("%s - copy rest of data %d", __FUNCTION__, secondhalf); | ||
1349 | memcpy(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf); | ||
1350 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, secondhalf, &fifo->fifo[fifo->head]); | ||
1351 | // update the index and size | ||
1352 | fifo->count += secondhalf; | ||
1353 | fifo->head += secondhalf; | ||
1354 | // No need to check for wrap since we can not get to end of fifo in this part | ||
1355 | } | ||
1356 | |||
1357 | finish_write: | ||
1358 | spin_unlock_irqrestore(&edge_port->ep_lock, flags); | ||
1359 | |||
1360 | send_more_port_data((struct edgeport_serial *)usb_get_serial_data(port->serial), edge_port); | ||
1361 | |||
1362 | dbg("%s wrote %d byte(s) TxCredits %d, Fifo %d", __FUNCTION__, copySize, edge_port->txCredits, fifo->count); | ||
1363 | |||
1364 | return copySize; | ||
1365 | } | ||
1366 | |||
1367 | |||
1368 | /************************************************************************ | ||
1369 | * | ||
1370 | * send_more_port_data() | ||
1371 | * | ||
1372 | * This routine attempts to write additional UART transmit data | ||
1373 | * to a port over the USB bulk pipe. It is called (1) when new | ||
1374 | * data has been written to a port's TxBuffer from higher layers | ||
1375 | * (2) when the peripheral sends us additional TxCredits indicating | ||
1376 | * that it can accept more Tx data for a given port; and (3) when | ||
1377 | * a bulk write completes successfully and we want to see if we | ||
1378 | * can transmit more. | ||
1379 | * | ||
1380 | ************************************************************************/ | ||
1381 | static void send_more_port_data(struct edgeport_serial *edge_serial, struct edgeport_port *edge_port) | ||
1382 | { | ||
1383 | struct TxFifo *fifo = &edge_port->txfifo; | ||
1384 | struct urb *urb; | ||
1385 | unsigned char *buffer; | ||
1386 | int status; | ||
1387 | int count; | ||
1388 | int bytesleft; | ||
1389 | int firsthalf; | ||
1390 | int secondhalf; | ||
1391 | unsigned long flags; | ||
1392 | |||
1393 | dbg("%s(%d)", __FUNCTION__, edge_port->port->number); | ||
1394 | |||
1395 | spin_lock_irqsave(&edge_port->ep_lock, flags); | ||
1396 | |||
1397 | if (edge_port->write_in_progress || | ||
1398 | !edge_port->open || | ||
1399 | (fifo->count == 0)) { | ||
1400 | dbg("%s(%d) EXIT - fifo %d, PendingWrite = %d", __FUNCTION__, edge_port->port->number, fifo->count, edge_port->write_in_progress); | ||
1401 | goto exit_send; | ||
1402 | } | ||
1403 | |||
1404 | // since the amount of data in the fifo will always fit into the | ||
1405 | // edgeport buffer we do not need to check the write length | ||
1406 | |||
1407 | // Do we have enough credits for this port to make it worthwhile | ||
1408 | // to bother queueing a write. If it's too small, say a few bytes, | ||
1409 | // it's better to wait for more credits so we can do a larger | ||
1410 | // write. | ||
1411 | if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits,EDGE_FW_BULK_MAX_PACKET_SIZE)) { | ||
1412 | dbg("%s(%d) Not enough credit - fifo %d TxCredit %d", __FUNCTION__, edge_port->port->number, fifo->count, edge_port->txCredits ); | ||
1413 | goto exit_send; | ||
1414 | } | ||
1415 | |||
1416 | // lock this write | ||
1417 | edge_port->write_in_progress = TRUE; | ||
1418 | |||
1419 | // get a pointer to the write_urb | ||
1420 | urb = edge_port->write_urb; | ||
1421 | |||
1422 | /* if this urb had a transfer buffer already (old transfer) free it */ | ||
1423 | if (urb->transfer_buffer != NULL) { | ||
1424 | kfree(urb->transfer_buffer); | ||
1425 | urb->transfer_buffer = NULL; | ||
1426 | } | ||
1427 | |||
1428 | /* build the data header for the buffer and port that we are about to send out */ | ||
1429 | count = fifo->count; | ||
1430 | buffer = kmalloc (count+2, GFP_ATOMIC); | ||
1431 | if (buffer == NULL) { | ||
1432 | dev_err(&edge_port->port->dev, "%s - no more kernel memory...\n", __FUNCTION__); | ||
1433 | edge_port->write_in_progress = FALSE; | ||
1434 | goto exit_send; | ||
1435 | } | ||
1436 | buffer[0] = IOSP_BUILD_DATA_HDR1 (edge_port->port->number - edge_port->port->serial->minor, count); | ||
1437 | buffer[1] = IOSP_BUILD_DATA_HDR2 (edge_port->port->number - edge_port->port->serial->minor, count); | ||
1438 | |||
1439 | /* now copy our data */ | ||
1440 | bytesleft = fifo->size - fifo->tail; | ||
1441 | firsthalf = min (bytesleft, count); | ||
1442 | memcpy(&buffer[2], &fifo->fifo[fifo->tail], firsthalf); | ||
1443 | fifo->tail += firsthalf; | ||
1444 | fifo->count -= firsthalf; | ||
1445 | if (fifo->tail == fifo->size) { | ||
1446 | fifo->tail = 0; | ||
1447 | } | ||
1448 | |||
1449 | secondhalf = count-firsthalf; | ||
1450 | if (secondhalf) { | ||
1451 | memcpy(&buffer[2+firsthalf], &fifo->fifo[fifo->tail], secondhalf); | ||
1452 | fifo->tail += secondhalf; | ||
1453 | fifo->count -= secondhalf; | ||
1454 | } | ||
1455 | |||
1456 | if (count) | ||
1457 | usb_serial_debug_data(debug, &edge_port->port->dev, __FUNCTION__, count, &buffer[2]); | ||
1458 | |||
1459 | /* fill up the urb with all of our data and submit it */ | ||
1460 | usb_fill_bulk_urb (urb, edge_serial->serial->dev, | ||
1461 | usb_sndbulkpipe(edge_serial->serial->dev, edge_serial->bulk_out_endpoint), | ||
1462 | buffer, count+2, edge_bulk_out_data_callback, edge_port); | ||
1463 | |||
1464 | /* decrement the number of credits we have by the number we just sent */ | ||
1465 | edge_port->txCredits -= count; | ||
1466 | edge_port->icount.tx += count; | ||
1467 | |||
1468 | urb->dev = edge_serial->serial->dev; | ||
1469 | status = usb_submit_urb(urb, GFP_ATOMIC); | ||
1470 | if (status) { | ||
1471 | /* something went wrong */ | ||
1472 | dev_err(&edge_port->port->dev, "%s - usb_submit_urb(write bulk) failed, status = %d, data lost\n", __FUNCTION__, status); | ||
1473 | edge_port->write_in_progress = FALSE; | ||
1474 | |||
1475 | /* revert the credits as something bad happened. */ | ||
1476 | edge_port->txCredits += count; | ||
1477 | edge_port->icount.tx -= count; | ||
1478 | } | ||
1479 | dbg("%s wrote %d byte(s) TxCredit %d, Fifo %d", __FUNCTION__, count, edge_port->txCredits, fifo->count); | ||
1480 | |||
1481 | exit_send: | ||
1482 | spin_unlock_irqrestore(&edge_port->ep_lock, flags); | ||
1483 | } | ||
1484 | |||
1485 | |||
1486 | /***************************************************************************** | ||
1487 | * edge_write_room | ||
1488 | * this function is called by the tty driver when it wants to know how many | ||
1489 | * bytes of data we can accept for a specific port. | ||
1490 | * If successful, we return the amount of room that we have for this port | ||
1491 | * (the txCredits), | ||
1492 | * Otherwise we return a negative error number. | ||
1493 | *****************************************************************************/ | ||
1494 | static int edge_write_room (struct usb_serial_port *port) | ||
1495 | { | ||
1496 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | ||
1497 | int room; | ||
1498 | unsigned long flags; | ||
1499 | |||
1500 | dbg("%s", __FUNCTION__); | ||
1501 | |||
1502 | if (edge_port == NULL) | ||
1503 | return -ENODEV; | ||
1504 | if (edge_port->closePending == TRUE) | ||
1505 | return -ENODEV; | ||
1506 | |||
1507 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
1508 | |||
1509 | if (!edge_port->open) { | ||
1510 | dbg("%s - port not opened", __FUNCTION__); | ||
1511 | return -EINVAL; | ||
1512 | } | ||
1513 | |||
1514 | // total of both buffers is still txCredit | ||
1515 | spin_lock_irqsave(&edge_port->ep_lock, flags); | ||
1516 | room = edge_port->txCredits - edge_port->txfifo.count; | ||
1517 | spin_unlock_irqrestore(&edge_port->ep_lock, flags); | ||
1518 | |||
1519 | dbg("%s - returns %d", __FUNCTION__, room); | ||
1520 | return room; | ||
1521 | } | ||
1522 | |||
1523 | |||
1524 | /***************************************************************************** | ||
1525 | * edge_chars_in_buffer | ||
1526 | * this function is called by the tty driver when it wants to know how many | ||
1527 | * bytes of data we currently have outstanding in the port (data that has | ||
1528 | * been written, but hasn't made it out the port yet) | ||
1529 | * If successful, we return the number of bytes left to be written in the | ||
1530 | * system, | ||
1531 | * Otherwise we return a negative error number. | ||
1532 | *****************************************************************************/ | ||
1533 | static int edge_chars_in_buffer (struct usb_serial_port *port) | ||
1534 | { | ||
1535 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | ||
1536 | int num_chars; | ||
1537 | unsigned long flags; | ||
1538 | |||
1539 | dbg("%s", __FUNCTION__); | ||
1540 | |||
1541 | if (edge_port == NULL) | ||
1542 | return -ENODEV; | ||
1543 | if (edge_port->closePending == TRUE) | ||
1544 | return -ENODEV; | ||
1545 | |||
1546 | if (!edge_port->open) { | ||
1547 | dbg("%s - port not opened", __FUNCTION__); | ||
1548 | return -EINVAL; | ||
1549 | } | ||
1550 | |||
1551 | spin_lock_irqsave(&edge_port->ep_lock, flags); | ||
1552 | num_chars = edge_port->maxTxCredits - edge_port->txCredits + edge_port->txfifo.count; | ||
1553 | spin_unlock_irqrestore(&edge_port->ep_lock, flags); | ||
1554 | if (num_chars) { | ||
1555 | dbg("%s(port %d) - returns %d", __FUNCTION__, port->number, num_chars); | ||
1556 | } | ||
1557 | |||
1558 | return num_chars; | ||
1559 | } | ||
1560 | |||
1561 | |||
1562 | /***************************************************************************** | ||
1563 | * SerialThrottle | ||
1564 | * this function is called by the tty driver when it wants to stop the data | ||
1565 | * being read from the port. | ||
1566 | *****************************************************************************/ | ||
1567 | static void edge_throttle (struct usb_serial_port *port) | ||
1568 | { | ||
1569 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | ||
1570 | struct tty_struct *tty; | ||
1571 | int status; | ||
1572 | |||
1573 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
1574 | |||
1575 | if (edge_port == NULL) | ||
1576 | return; | ||
1577 | |||
1578 | if (!edge_port->open) { | ||
1579 | dbg("%s - port not opened", __FUNCTION__); | ||
1580 | return; | ||
1581 | } | ||
1582 | |||
1583 | tty = port->tty; | ||
1584 | if (!tty) { | ||
1585 | dbg ("%s - no tty available", __FUNCTION__); | ||
1586 | return; | ||
1587 | } | ||
1588 | |||
1589 | /* if we are implementing XON/XOFF, send the stop character */ | ||
1590 | if (I_IXOFF(tty)) { | ||
1591 | unsigned char stop_char = STOP_CHAR(tty); | ||
1592 | status = edge_write (port, &stop_char, 1); | ||
1593 | if (status <= 0) { | ||
1594 | return; | ||
1595 | } | ||
1596 | } | ||
1597 | |||
1598 | /* if we are implementing RTS/CTS, toggle that line */ | ||
1599 | if (tty->termios->c_cflag & CRTSCTS) { | ||
1600 | edge_port->shadowMCR &= ~MCR_RTS; | ||
1601 | status = send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR); | ||
1602 | if (status != 0) { | ||
1603 | return; | ||
1604 | } | ||
1605 | } | ||
1606 | |||
1607 | return; | ||
1608 | } | ||
1609 | |||
1610 | |||
1611 | /***************************************************************************** | ||
1612 | * edge_unthrottle | ||
1613 | * this function is called by the tty driver when it wants to resume the data | ||
1614 | * being read from the port (called after SerialThrottle is called) | ||
1615 | *****************************************************************************/ | ||
1616 | static void edge_unthrottle (struct usb_serial_port *port) | ||
1617 | { | ||
1618 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | ||
1619 | struct tty_struct *tty; | ||
1620 | int status; | ||
1621 | |||
1622 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
1623 | |||
1624 | if (edge_port == NULL) | ||
1625 | return; | ||
1626 | |||
1627 | if (!edge_port->open) { | ||
1628 | dbg("%s - port not opened", __FUNCTION__); | ||
1629 | return; | ||
1630 | } | ||
1631 | |||
1632 | tty = port->tty; | ||
1633 | if (!tty) { | ||
1634 | dbg ("%s - no tty available", __FUNCTION__); | ||
1635 | return; | ||
1636 | } | ||
1637 | |||
1638 | /* if we are implementing XON/XOFF, send the start character */ | ||
1639 | if (I_IXOFF(tty)) { | ||
1640 | unsigned char start_char = START_CHAR(tty); | ||
1641 | status = edge_write (port, &start_char, 1); | ||
1642 | if (status <= 0) { | ||
1643 | return; | ||
1644 | } | ||
1645 | } | ||
1646 | |||
1647 | /* if we are implementing RTS/CTS, toggle that line */ | ||
1648 | if (tty->termios->c_cflag & CRTSCTS) { | ||
1649 | edge_port->shadowMCR |= MCR_RTS; | ||
1650 | status = send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR); | ||
1651 | if (status != 0) { | ||
1652 | return; | ||
1653 | } | ||
1654 | } | ||
1655 | |||
1656 | return; | ||
1657 | } | ||
1658 | |||
1659 | |||
1660 | /***************************************************************************** | ||
1661 | * SerialSetTermios | ||
1662 | * this function is called by the tty driver when it wants to change the termios structure | ||
1663 | *****************************************************************************/ | ||
1664 | static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios) | ||
1665 | { | ||
1666 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | ||
1667 | struct tty_struct *tty = port->tty; | ||
1668 | unsigned int cflag; | ||
1669 | |||
1670 | if (!port->tty || !port->tty->termios) { | ||
1671 | dbg ("%s - no tty or termios", __FUNCTION__); | ||
1672 | return; | ||
1673 | } | ||
1674 | |||
1675 | cflag = tty->termios->c_cflag; | ||
1676 | /* check that they really want us to change something */ | ||
1677 | if (old_termios) { | ||
1678 | if (cflag == old_termios->c_cflag && | ||
1679 | tty->termios->c_iflag == old_termios->c_iflag) { | ||
1680 | dbg("%s - nothing to change", __FUNCTION__); | ||
1681 | return; | ||
1682 | } | ||
1683 | } | ||
1684 | |||
1685 | dbg("%s - clfag %08x iflag %08x", __FUNCTION__, | ||
1686 | tty->termios->c_cflag, tty->termios->c_iflag); | ||
1687 | if (old_termios) { | ||
1688 | dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__, | ||
1689 | old_termios->c_cflag, old_termios->c_iflag); | ||
1690 | } | ||
1691 | |||
1692 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
1693 | |||
1694 | if (edge_port == NULL) | ||
1695 | return; | ||
1696 | |||
1697 | if (!edge_port->open) { | ||
1698 | dbg("%s - port not opened", __FUNCTION__); | ||
1699 | return; | ||
1700 | } | ||
1701 | |||
1702 | /* change the port settings to the new ones specified */ | ||
1703 | change_port_settings (edge_port, old_termios); | ||
1704 | |||
1705 | return; | ||
1706 | } | ||
1707 | |||
1708 | |||
1709 | /***************************************************************************** | ||
1710 | * get_lsr_info - get line status register info | ||
1711 | * | ||
1712 | * Purpose: Let user call ioctl() to get info when the UART physically | ||
1713 | * is emptied. On bus types like RS485, the transmitter must | ||
1714 | * release the bus after transmitting. This must be done when | ||
1715 | * the transmit shift register is empty, not be done when the | ||
1716 | * transmit holding register is empty. This functionality | ||
1717 | * allows an RS485 driver to be written in user space. | ||
1718 | *****************************************************************************/ | ||
1719 | static int get_lsr_info(struct edgeport_port *edge_port, unsigned int __user *value) | ||
1720 | { | ||
1721 | unsigned int result = 0; | ||
1722 | unsigned long flags; | ||
1723 | |||
1724 | spin_lock_irqsave(&edge_port->ep_lock, flags); | ||
1725 | if (edge_port->maxTxCredits == edge_port->txCredits && | ||
1726 | edge_port->txfifo.count == 0) { | ||
1727 | dbg("%s -- Empty", __FUNCTION__); | ||
1728 | result = TIOCSER_TEMT; | ||
1729 | } | ||
1730 | spin_unlock_irqrestore(&edge_port->ep_lock, flags); | ||
1731 | |||
1732 | if (copy_to_user(value, &result, sizeof(int))) | ||
1733 | return -EFAULT; | ||
1734 | return 0; | ||
1735 | } | ||
1736 | |||
1737 | static int get_number_bytes_avail(struct edgeport_port *edge_port, unsigned int __user *value) | ||
1738 | { | ||
1739 | unsigned int result = 0; | ||
1740 | struct tty_struct *tty = edge_port->port->tty; | ||
1741 | |||
1742 | if (!tty) | ||
1743 | return -ENOIOCTLCMD; | ||
1744 | |||
1745 | result = tty->read_cnt; | ||
1746 | |||
1747 | dbg("%s(%d) = %d", __FUNCTION__, edge_port->port->number, result); | ||
1748 | if (copy_to_user(value, &result, sizeof(int))) | ||
1749 | return -EFAULT; | ||
1750 | //return 0; | ||
1751 | return -ENOIOCTLCMD; | ||
1752 | } | ||
1753 | |||
1754 | static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear) | ||
1755 | { | ||
1756 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | ||
1757 | unsigned int mcr; | ||
1758 | |||
1759 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
1760 | |||
1761 | mcr = edge_port->shadowMCR; | ||
1762 | if (set & TIOCM_RTS) | ||
1763 | mcr |= MCR_RTS; | ||
1764 | if (set & TIOCM_DTR) | ||
1765 | mcr |= MCR_DTR; | ||
1766 | if (set & TIOCM_LOOP) | ||
1767 | mcr |= MCR_LOOPBACK; | ||
1768 | |||
1769 | if (clear & TIOCM_RTS) | ||
1770 | mcr &= ~MCR_RTS; | ||
1771 | if (clear & TIOCM_DTR) | ||
1772 | mcr &= ~MCR_DTR; | ||
1773 | if (clear & TIOCM_LOOP) | ||
1774 | mcr &= ~MCR_LOOPBACK; | ||
1775 | |||
1776 | edge_port->shadowMCR = mcr; | ||
1777 | |||
1778 | send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR); | ||
1779 | |||
1780 | return 0; | ||
1781 | } | ||
1782 | |||
1783 | static int edge_tiocmget(struct usb_serial_port *port, struct file *file) | ||
1784 | { | ||
1785 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | ||
1786 | unsigned int result = 0; | ||
1787 | unsigned int msr; | ||
1788 | unsigned int mcr; | ||
1789 | |||
1790 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
1791 | |||
1792 | msr = edge_port->shadowMSR; | ||
1793 | mcr = edge_port->shadowMCR; | ||
1794 | result = ((mcr & MCR_DTR) ? TIOCM_DTR: 0) /* 0x002 */ | ||
1795 | | ((mcr & MCR_RTS) ? TIOCM_RTS: 0) /* 0x004 */ | ||
1796 | | ((msr & EDGEPORT_MSR_CTS) ? TIOCM_CTS: 0) /* 0x020 */ | ||
1797 | | ((msr & EDGEPORT_MSR_CD) ? TIOCM_CAR: 0) /* 0x040 */ | ||
1798 | | ((msr & EDGEPORT_MSR_RI) ? TIOCM_RI: 0) /* 0x080 */ | ||
1799 | | ((msr & EDGEPORT_MSR_DSR) ? TIOCM_DSR: 0); /* 0x100 */ | ||
1800 | |||
1801 | |||
1802 | dbg("%s -- %x", __FUNCTION__, result); | ||
1803 | |||
1804 | return result; | ||
1805 | } | ||
1806 | |||
1807 | static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct __user *retinfo) | ||
1808 | { | ||
1809 | struct serial_struct tmp; | ||
1810 | |||
1811 | if (!retinfo) | ||
1812 | return -EFAULT; | ||
1813 | |||
1814 | memset(&tmp, 0, sizeof(tmp)); | ||
1815 | |||
1816 | tmp.type = PORT_16550A; | ||
1817 | tmp.line = edge_port->port->serial->minor; | ||
1818 | tmp.port = edge_port->port->number; | ||
1819 | tmp.irq = 0; | ||
1820 | tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; | ||
1821 | tmp.xmit_fifo_size = edge_port->maxTxCredits; | ||
1822 | tmp.baud_base = 9600; | ||
1823 | tmp.close_delay = 5*HZ; | ||
1824 | tmp.closing_wait = 30*HZ; | ||
1825 | // tmp.custom_divisor = state->custom_divisor; | ||
1826 | // tmp.hub6 = state->hub6; | ||
1827 | // tmp.io_type = state->io_type; | ||
1828 | |||
1829 | if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) | ||
1830 | return -EFAULT; | ||
1831 | return 0; | ||
1832 | } | ||
1833 | |||
1834 | |||
1835 | |||
1836 | /***************************************************************************** | ||
1837 | * SerialIoctl | ||
1838 | * this function handles any ioctl calls to the driver | ||
1839 | *****************************************************************************/ | ||
1840 | static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg) | ||
1841 | { | ||
1842 | DEFINE_WAIT(wait); | ||
1843 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | ||
1844 | struct async_icount cnow; | ||
1845 | struct async_icount cprev; | ||
1846 | struct serial_icounter_struct icount; | ||
1847 | |||
1848 | dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd); | ||
1849 | |||
1850 | switch (cmd) { | ||
1851 | // return number of bytes available | ||
1852 | case TIOCINQ: | ||
1853 | dbg("%s (%d) TIOCINQ", __FUNCTION__, port->number); | ||
1854 | return get_number_bytes_avail(edge_port, (unsigned int __user *) arg); | ||
1855 | break; | ||
1856 | |||
1857 | case TIOCSERGETLSR: | ||
1858 | dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__, port->number); | ||
1859 | return get_lsr_info(edge_port, (unsigned int __user *) arg); | ||
1860 | return 0; | ||
1861 | |||
1862 | case TIOCGSERIAL: | ||
1863 | dbg("%s (%d) TIOCGSERIAL", __FUNCTION__, port->number); | ||
1864 | return get_serial_info(edge_port, (struct serial_struct __user *) arg); | ||
1865 | |||
1866 | case TIOCSSERIAL: | ||
1867 | dbg("%s (%d) TIOCSSERIAL", __FUNCTION__, port->number); | ||
1868 | break; | ||
1869 | |||
1870 | case TIOCMIWAIT: | ||
1871 | dbg("%s (%d) TIOCMIWAIT", __FUNCTION__, port->number); | ||
1872 | cprev = edge_port->icount; | ||
1873 | while (1) { | ||
1874 | prepare_to_wait(&edge_port->delta_msr_wait, &wait, TASK_INTERRUPTIBLE); | ||
1875 | schedule(); | ||
1876 | finish_wait(&edge_port->delta_msr_wait, &wait); | ||
1877 | /* see if a signal did it */ | ||
1878 | if (signal_pending(current)) | ||
1879 | return -ERESTARTSYS; | ||
1880 | cnow = edge_port->icount; | ||
1881 | if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && | ||
1882 | cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) | ||
1883 | return -EIO; /* no change => error */ | ||
1884 | if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || | ||
1885 | ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || | ||
1886 | ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || | ||
1887 | ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { | ||
1888 | return 0; | ||
1889 | } | ||
1890 | cprev = cnow; | ||
1891 | } | ||
1892 | /* NOTREACHED */ | ||
1893 | break; | ||
1894 | |||
1895 | case TIOCGICOUNT: | ||
1896 | cnow = edge_port->icount; | ||
1897 | memset(&icount, 0, sizeof(icount)); | ||
1898 | icount.cts = cnow.cts; | ||
1899 | icount.dsr = cnow.dsr; | ||
1900 | icount.rng = cnow.rng; | ||
1901 | icount.dcd = cnow.dcd; | ||
1902 | icount.rx = cnow.rx; | ||
1903 | icount.tx = cnow.tx; | ||
1904 | icount.frame = cnow.frame; | ||
1905 | icount.overrun = cnow.overrun; | ||
1906 | icount.parity = cnow.parity; | ||
1907 | icount.brk = cnow.brk; | ||
1908 | icount.buf_overrun = cnow.buf_overrun; | ||
1909 | |||
1910 | dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__, port->number, icount.rx, icount.tx ); | ||
1911 | if (copy_to_user((void __user *)arg, &icount, sizeof(icount))) | ||
1912 | return -EFAULT; | ||
1913 | return 0; | ||
1914 | } | ||
1915 | |||
1916 | return -ENOIOCTLCMD; | ||
1917 | } | ||
1918 | |||
1919 | |||
1920 | /***************************************************************************** | ||
1921 | * SerialBreak | ||
1922 | * this function sends a break to the port | ||
1923 | *****************************************************************************/ | ||
1924 | static void edge_break (struct usb_serial_port *port, int break_state) | ||
1925 | { | ||
1926 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | ||
1927 | int status; | ||
1928 | |||
1929 | /* flush and chase */ | ||
1930 | edge_port->chaseResponsePending = TRUE; | ||
1931 | |||
1932 | dbg("%s - Sending IOSP_CMD_CHASE_PORT", __FUNCTION__); | ||
1933 | status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0); | ||
1934 | if (status == 0) { | ||
1935 | // block until chase finished | ||
1936 | block_until_chase_response(edge_port); | ||
1937 | } else { | ||
1938 | edge_port->chaseResponsePending = FALSE; | ||
1939 | } | ||
1940 | |||
1941 | if (break_state == -1) { | ||
1942 | dbg("%s - Sending IOSP_CMD_SET_BREAK", __FUNCTION__); | ||
1943 | status = send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_BREAK, 0); | ||
1944 | } else { | ||
1945 | dbg("%s - Sending IOSP_CMD_CLEAR_BREAK", __FUNCTION__); | ||
1946 | status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CLEAR_BREAK, 0); | ||
1947 | } | ||
1948 | if (status) { | ||
1949 | dbg("%s - error sending break set/clear command.", __FUNCTION__); | ||
1950 | } | ||
1951 | |||
1952 | return; | ||
1953 | } | ||
1954 | |||
1955 | |||
1956 | /***************************************************************************** | ||
1957 | * process_rcvd_data | ||
1958 | * this function handles the data received on the bulk in pipe. | ||
1959 | *****************************************************************************/ | ||
1960 | static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned char * buffer, __u16 bufferLength) | ||
1961 | { | ||
1962 | struct usb_serial_port *port; | ||
1963 | struct edgeport_port *edge_port; | ||
1964 | struct tty_struct *tty; | ||
1965 | __u16 lastBufferLength; | ||
1966 | __u16 rxLen; | ||
1967 | |||
1968 | dbg("%s", __FUNCTION__); | ||
1969 | |||
1970 | lastBufferLength = bufferLength + 1; | ||
1971 | |||
1972 | while (bufferLength > 0) { | ||
1973 | /* failsafe incase we get a message that we don't understand */ | ||
1974 | if (lastBufferLength == bufferLength) { | ||
1975 | dbg("%s - stuck in loop, exiting it.", __FUNCTION__); | ||
1976 | break; | ||
1977 | } | ||
1978 | lastBufferLength = bufferLength; | ||
1979 | |||
1980 | switch (edge_serial->rxState) { | ||
1981 | case EXPECT_HDR1: | ||
1982 | edge_serial->rxHeader1 = *buffer; | ||
1983 | ++buffer; | ||
1984 | --bufferLength; | ||
1985 | |||
1986 | if (bufferLength == 0) { | ||
1987 | edge_serial->rxState = EXPECT_HDR2; | ||
1988 | break; | ||
1989 | } | ||
1990 | /* otherwise, drop on through */ | ||
1991 | |||
1992 | case EXPECT_HDR2: | ||
1993 | edge_serial->rxHeader2 = *buffer; | ||
1994 | ++buffer; | ||
1995 | --bufferLength; | ||
1996 | |||
1997 | dbg("%s - Hdr1=%02X Hdr2=%02X", __FUNCTION__, edge_serial->rxHeader1, edge_serial->rxHeader2); | ||
1998 | |||
1999 | // Process depending on whether this header is | ||
2000 | // data or status | ||
2001 | |||
2002 | if (IS_CMD_STAT_HDR(edge_serial->rxHeader1)) { | ||
2003 | // Decode this status header and goto EXPECT_HDR1 (if we | ||
2004 | // can process the status with only 2 bytes), or goto | ||
2005 | // EXPECT_HDR3 to get the third byte. | ||
2006 | |||
2007 | edge_serial->rxPort = IOSP_GET_HDR_PORT(edge_serial->rxHeader1); | ||
2008 | edge_serial->rxStatusCode = IOSP_GET_STATUS_CODE(edge_serial->rxHeader1); | ||
2009 | |||
2010 | if (!IOSP_STATUS_IS_2BYTE(edge_serial->rxStatusCode)) { | ||
2011 | // This status needs additional bytes. Save what we have | ||
2012 | // and then wait for more data. | ||
2013 | edge_serial->rxStatusParam = edge_serial->rxHeader2; | ||
2014 | |||
2015 | edge_serial->rxState = EXPECT_HDR3; | ||
2016 | break; | ||
2017 | } | ||
2018 | |||
2019 | // We have all the header bytes, process the status now | ||
2020 | process_rcvd_status (edge_serial, edge_serial->rxHeader2, 0); | ||
2021 | edge_serial->rxState = EXPECT_HDR1; | ||
2022 | break; | ||
2023 | } else { | ||
2024 | edge_serial->rxPort = IOSP_GET_HDR_PORT(edge_serial->rxHeader1); | ||
2025 | edge_serial->rxBytesRemaining = IOSP_GET_HDR_DATA_LEN(edge_serial->rxHeader1, edge_serial->rxHeader2); | ||
2026 | |||
2027 | dbg("%s - Data for Port %u Len %u", __FUNCTION__, edge_serial->rxPort, edge_serial->rxBytesRemaining); | ||
2028 | |||
2029 | //ASSERT( DevExt->RxPort < DevExt->NumPorts ); | ||
2030 | //ASSERT( DevExt->RxBytesRemaining < IOSP_MAX_DATA_LENGTH ); | ||
2031 | |||
2032 | if (bufferLength == 0 ) { | ||
2033 | edge_serial->rxState = EXPECT_DATA; | ||
2034 | break; | ||
2035 | } | ||
2036 | // Else, drop through | ||
2037 | } | ||
2038 | |||
2039 | case EXPECT_DATA: // Expect data | ||
2040 | |||
2041 | if (bufferLength < edge_serial->rxBytesRemaining) { | ||
2042 | rxLen = bufferLength; | ||
2043 | edge_serial->rxState = EXPECT_DATA; // Expect data to start next buffer | ||
2044 | } else { | ||
2045 | // BufLen >= RxBytesRemaining | ||
2046 | rxLen = edge_serial->rxBytesRemaining; | ||
2047 | edge_serial->rxState = EXPECT_HDR1; // Start another header next time | ||
2048 | } | ||
2049 | |||
2050 | bufferLength -= rxLen; | ||
2051 | edge_serial->rxBytesRemaining -= rxLen; | ||
2052 | |||
2053 | /* spit this data back into the tty driver if this port is open */ | ||
2054 | if (rxLen) { | ||
2055 | port = edge_serial->serial->port[edge_serial->rxPort]; | ||
2056 | edge_port = usb_get_serial_port_data(port); | ||
2057 | if (edge_port->open) { | ||
2058 | tty = edge_port->port->tty; | ||
2059 | if (tty) { | ||
2060 | dbg("%s - Sending %d bytes to TTY for port %d", __FUNCTION__, rxLen, edge_serial->rxPort); | ||
2061 | edge_tty_recv(&edge_serial->serial->dev->dev, tty, buffer, rxLen); | ||
2062 | } | ||
2063 | edge_port->icount.rx += rxLen; | ||
2064 | } | ||
2065 | buffer += rxLen; | ||
2066 | } | ||
2067 | |||
2068 | break; | ||
2069 | |||
2070 | case EXPECT_HDR3: // Expect 3rd byte of status header | ||
2071 | edge_serial->rxHeader3 = *buffer; | ||
2072 | ++buffer; | ||
2073 | --bufferLength; | ||
2074 | |||
2075 | // We have all the header bytes, process the status now | ||
2076 | process_rcvd_status (edge_serial, edge_serial->rxStatusParam, edge_serial->rxHeader3); | ||
2077 | edge_serial->rxState = EXPECT_HDR1; | ||
2078 | break; | ||
2079 | |||
2080 | } | ||
2081 | } | ||
2082 | } | ||
2083 | |||
2084 | |||
2085 | /***************************************************************************** | ||
2086 | * process_rcvd_status | ||
2087 | * this function handles the any status messages received on the bulk in pipe. | ||
2088 | *****************************************************************************/ | ||
2089 | static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2, __u8 byte3) | ||
2090 | { | ||
2091 | struct usb_serial_port *port; | ||
2092 | struct edgeport_port *edge_port; | ||
2093 | __u8 code = edge_serial->rxStatusCode; | ||
2094 | |||
2095 | /* switch the port pointer to the one being currently talked about */ | ||
2096 | port = edge_serial->serial->port[edge_serial->rxPort]; | ||
2097 | edge_port = usb_get_serial_port_data(port); | ||
2098 | if (edge_port == NULL) { | ||
2099 | dev_err(&edge_serial->serial->dev->dev, "%s - edge_port == NULL for port %d\n", __FUNCTION__, edge_serial->rxPort); | ||
2100 | return; | ||
2101 | } | ||
2102 | |||
2103 | dbg("%s - port %d", __FUNCTION__, edge_serial->rxPort); | ||
2104 | |||
2105 | if (code == IOSP_EXT_STATUS) { | ||
2106 | switch (byte2) { | ||
2107 | case IOSP_EXT_STATUS_CHASE_RSP: | ||
2108 | // we want to do EXT status regardless of port open/closed | ||
2109 | dbg("%s - Port %u EXT CHASE_RSP Data = %02x", __FUNCTION__, edge_serial->rxPort, byte3 ); | ||
2110 | // Currently, the only EXT_STATUS is Chase, so process here instead of one more call | ||
2111 | // to one more subroutine. If/when more EXT_STATUS, there'll be more work to do. | ||
2112 | // Also, we currently clear flag and close the port regardless of content of above's Byte3. | ||
2113 | // We could choose to do something else when Byte3 says Timeout on Chase from Edgeport, | ||
2114 | // like wait longer in block_until_chase_response, but for now we don't. | ||
2115 | edge_port->chaseResponsePending = FALSE; | ||
2116 | wake_up (&edge_port->wait_chase); | ||
2117 | return; | ||
2118 | |||
2119 | case IOSP_EXT_STATUS_RX_CHECK_RSP: | ||
2120 | dbg("%s ========== Port %u CHECK_RSP Sequence = %02x =============\n", __FUNCTION__, edge_serial->rxPort, byte3 ); | ||
2121 | //Port->RxCheckRsp = TRUE; | ||
2122 | return; | ||
2123 | } | ||
2124 | } | ||
2125 | |||
2126 | if (code == IOSP_STATUS_OPEN_RSP) { | ||
2127 | edge_port->txCredits = GET_TX_BUFFER_SIZE(byte3); | ||
2128 | edge_port->maxTxCredits = edge_port->txCredits; | ||
2129 | dbg("%s - Port %u Open Response Inital MSR = %02x TxBufferSize = %d", __FUNCTION__, edge_serial->rxPort, byte2, edge_port->txCredits); | ||
2130 | handle_new_msr (edge_port, byte2); | ||
2131 | |||
2132 | /* send the current line settings to the port so we are in sync with any further termios calls */ | ||
2133 | if (edge_port->port->tty) | ||
2134 | change_port_settings (edge_port, edge_port->port->tty->termios); | ||
2135 | |||
2136 | /* we have completed the open */ | ||
2137 | edge_port->openPending = FALSE; | ||
2138 | edge_port->open = TRUE; | ||
2139 | wake_up(&edge_port->wait_open); | ||
2140 | return; | ||
2141 | } | ||
2142 | |||
2143 | // If port is closed, silently discard all rcvd status. We can | ||
2144 | // have cases where buffered status is received AFTER the close | ||
2145 | // port command is sent to the Edgeport. | ||
2146 | if ((!edge_port->open ) || (edge_port->closePending)) { | ||
2147 | return; | ||
2148 | } | ||
2149 | |||
2150 | switch (code) { | ||
2151 | // Not currently sent by Edgeport | ||
2152 | case IOSP_STATUS_LSR: | ||
2153 | dbg("%s - Port %u LSR Status = %02x", __FUNCTION__, edge_serial->rxPort, byte2); | ||
2154 | handle_new_lsr (edge_port, FALSE, byte2, 0); | ||
2155 | break; | ||
2156 | |||
2157 | case IOSP_STATUS_LSR_DATA: | ||
2158 | dbg("%s - Port %u LSR Status = %02x, Data = %02x", __FUNCTION__, edge_serial->rxPort, byte2, byte3); | ||
2159 | // byte2 is LSR Register | ||
2160 | // byte3 is broken data byte | ||
2161 | handle_new_lsr (edge_port, TRUE, byte2, byte3); | ||
2162 | break; | ||
2163 | // | ||
2164 | // case IOSP_EXT_4_STATUS: | ||
2165 | // dbg("%s - Port %u LSR Status = %02x Data = %02x", __FUNCTION__, edge_serial->rxPort, byte2, byte3); | ||
2166 | // break; | ||
2167 | // | ||
2168 | case IOSP_STATUS_MSR: | ||
2169 | dbg("%s - Port %u MSR Status = %02x", __FUNCTION__, edge_serial->rxPort, byte2); | ||
2170 | |||
2171 | // Process this new modem status and generate appropriate | ||
2172 | // events, etc, based on the new status. This routine | ||
2173 | // also saves the MSR in Port->ShadowMsr. | ||
2174 | handle_new_msr(edge_port, byte2); | ||
2175 | break; | ||
2176 | |||
2177 | default: | ||
2178 | dbg("%s - Unrecognized IOSP status code %u\n", __FUNCTION__, code); | ||
2179 | break; | ||
2180 | } | ||
2181 | |||
2182 | return; | ||
2183 | } | ||
2184 | |||
2185 | |||
2186 | /***************************************************************************** | ||
2187 | * edge_tty_recv | ||
2188 | * this function passes data on to the tty flip buffer | ||
2189 | *****************************************************************************/ | ||
2190 | static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length) | ||
2191 | { | ||
2192 | int cnt; | ||
2193 | |||
2194 | do { | ||
2195 | if (tty->flip.count >= TTY_FLIPBUF_SIZE) { | ||
2196 | tty_flip_buffer_push(tty); | ||
2197 | if (tty->flip.count >= TTY_FLIPBUF_SIZE) { | ||
2198 | dev_err(dev, "%s - dropping data, %d bytes lost\n", | ||
2199 | __FUNCTION__, length); | ||
2200 | return; | ||
2201 | } | ||
2202 | } | ||
2203 | cnt = min(length, TTY_FLIPBUF_SIZE - tty->flip.count); | ||
2204 | memcpy(tty->flip.char_buf_ptr, data, cnt); | ||
2205 | memset(tty->flip.flag_buf_ptr, 0, cnt); | ||
2206 | tty->flip.char_buf_ptr += cnt; | ||
2207 | tty->flip.flag_buf_ptr += cnt; | ||
2208 | tty->flip.count += cnt; | ||
2209 | data += cnt; | ||
2210 | length -= cnt; | ||
2211 | } while (length > 0); | ||
2212 | |||
2213 | tty_flip_buffer_push(tty); | ||
2214 | } | ||
2215 | |||
2216 | |||
2217 | /***************************************************************************** | ||
2218 | * handle_new_msr | ||
2219 | * this function handles any change to the msr register for a port. | ||
2220 | *****************************************************************************/ | ||
2221 | static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr) | ||
2222 | { | ||
2223 | struct async_icount *icount; | ||
2224 | |||
2225 | dbg("%s %02x", __FUNCTION__, newMsr); | ||
2226 | |||
2227 | if (newMsr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR | EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) { | ||
2228 | icount = &edge_port->icount; | ||
2229 | |||
2230 | /* update input line counters */ | ||
2231 | if (newMsr & EDGEPORT_MSR_DELTA_CTS) { | ||
2232 | icount->cts++; | ||
2233 | } | ||
2234 | if (newMsr & EDGEPORT_MSR_DELTA_DSR) { | ||
2235 | icount->dsr++; | ||
2236 | } | ||
2237 | if (newMsr & EDGEPORT_MSR_DELTA_CD) { | ||
2238 | icount->dcd++; | ||
2239 | } | ||
2240 | if (newMsr & EDGEPORT_MSR_DELTA_RI) { | ||
2241 | icount->rng++; | ||
2242 | } | ||
2243 | wake_up_interruptible(&edge_port->delta_msr_wait); | ||
2244 | } | ||
2245 | |||
2246 | /* Save the new modem status */ | ||
2247 | edge_port->shadowMSR = newMsr & 0xf0; | ||
2248 | |||
2249 | return; | ||
2250 | } | ||
2251 | |||
2252 | |||
2253 | /***************************************************************************** | ||
2254 | * handle_new_lsr | ||
2255 | * this function handles any change to the lsr register for a port. | ||
2256 | *****************************************************************************/ | ||
2257 | static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData, __u8 lsr, __u8 data) | ||
2258 | { | ||
2259 | __u8 newLsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK)); | ||
2260 | struct async_icount *icount; | ||
2261 | |||
2262 | dbg("%s - %02x", __FUNCTION__, newLsr); | ||
2263 | |||
2264 | edge_port->shadowLSR = lsr; | ||
2265 | |||
2266 | if (newLsr & LSR_BREAK) { | ||
2267 | // | ||
2268 | // Parity and Framing errors only count if they | ||
2269 | // occur exclusive of a break being | ||
2270 | // received. | ||
2271 | // | ||
2272 | newLsr &= (__u8)(LSR_OVER_ERR | LSR_BREAK); | ||
2273 | } | ||
2274 | |||
2275 | /* Place LSR data byte into Rx buffer */ | ||
2276 | if (lsrData && edge_port->port->tty) | ||
2277 | edge_tty_recv(&edge_port->port->dev, edge_port->port->tty, &data, 1); | ||
2278 | |||
2279 | /* update input line counters */ | ||
2280 | icount = &edge_port->icount; | ||
2281 | if (newLsr & LSR_BREAK) { | ||
2282 | icount->brk++; | ||
2283 | } | ||
2284 | if (newLsr & LSR_OVER_ERR) { | ||
2285 | icount->overrun++; | ||
2286 | } | ||
2287 | if (newLsr & LSR_PAR_ERR) { | ||
2288 | icount->parity++; | ||
2289 | } | ||
2290 | if (newLsr & LSR_FRM_ERR) { | ||
2291 | icount->frame++; | ||
2292 | } | ||
2293 | |||
2294 | return; | ||
2295 | } | ||
2296 | |||
2297 | |||
2298 | /**************************************************************************** | ||
2299 | * sram_write | ||
2300 | * writes a number of bytes to the Edgeport device's sram starting at the | ||
2301 | * given address. | ||
2302 | * If successful returns the number of bytes written, otherwise it returns | ||
2303 | * a negative error number of the problem. | ||
2304 | ****************************************************************************/ | ||
2305 | static int sram_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data) | ||
2306 | { | ||
2307 | int result; | ||
2308 | __u16 current_length; | ||
2309 | unsigned char *transfer_buffer; | ||
2310 | |||
2311 | dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, length); | ||
2312 | |||
2313 | transfer_buffer = kmalloc (64, GFP_KERNEL); | ||
2314 | if (!transfer_buffer) { | ||
2315 | dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 64); | ||
2316 | return -ENOMEM; | ||
2317 | } | ||
2318 | |||
2319 | /* need to split these writes up into 64 byte chunks */ | ||
2320 | result = 0; | ||
2321 | while (length > 0) { | ||
2322 | if (length > 64) { | ||
2323 | current_length = 64; | ||
2324 | } else { | ||
2325 | current_length = length; | ||
2326 | } | ||
2327 | // dbg("%s - writing %x, %x, %d", __FUNCTION__, extAddr, addr, current_length); | ||
2328 | memcpy (transfer_buffer, data, current_length); | ||
2329 | result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), USB_REQUEST_ION_WRITE_RAM, | ||
2330 | 0x40, addr, extAddr, transfer_buffer, current_length, 300); | ||
2331 | if (result < 0) | ||
2332 | break; | ||
2333 | length -= current_length; | ||
2334 | addr += current_length; | ||
2335 | data += current_length; | ||
2336 | } | ||
2337 | |||
2338 | kfree (transfer_buffer); | ||
2339 | return result; | ||
2340 | } | ||
2341 | |||
2342 | |||
2343 | /**************************************************************************** | ||
2344 | * rom_write | ||
2345 | * writes a number of bytes to the Edgeport device's ROM starting at the | ||
2346 | * given address. | ||
2347 | * If successful returns the number of bytes written, otherwise it returns | ||
2348 | * a negative error number of the problem. | ||
2349 | ****************************************************************************/ | ||
2350 | static int rom_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data) | ||
2351 | { | ||
2352 | int result; | ||
2353 | __u16 current_length; | ||
2354 | unsigned char *transfer_buffer; | ||
2355 | |||
2356 | // dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, length); | ||
2357 | |||
2358 | transfer_buffer = kmalloc (64, GFP_KERNEL); | ||
2359 | if (!transfer_buffer) { | ||
2360 | dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 64); | ||
2361 | return -ENOMEM; | ||
2362 | } | ||
2363 | |||
2364 | /* need to split these writes up into 64 byte chunks */ | ||
2365 | result = 0; | ||
2366 | while (length > 0) { | ||
2367 | if (length > 64) { | ||
2368 | current_length = 64; | ||
2369 | } else { | ||
2370 | current_length = length; | ||
2371 | } | ||
2372 | // dbg("%s - writing %x, %x, %d", __FUNCTION__, extAddr, addr, current_length); | ||
2373 | memcpy (transfer_buffer, data, current_length); | ||
2374 | result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), USB_REQUEST_ION_WRITE_ROM, | ||
2375 | 0x40, addr, extAddr, transfer_buffer, current_length, 300); | ||
2376 | if (result < 0) | ||
2377 | break; | ||
2378 | length -= current_length; | ||
2379 | addr += current_length; | ||
2380 | data += current_length; | ||
2381 | } | ||
2382 | |||
2383 | kfree (transfer_buffer); | ||
2384 | return result; | ||
2385 | } | ||
2386 | |||
2387 | |||
2388 | /**************************************************************************** | ||
2389 | * rom_read | ||
2390 | * reads a number of bytes from the Edgeport device starting at the given | ||
2391 | * address. | ||
2392 | * If successful returns the number of bytes read, otherwise it returns | ||
2393 | * a negative error number of the problem. | ||
2394 | ****************************************************************************/ | ||
2395 | static int rom_read (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data) | ||
2396 | { | ||
2397 | int result; | ||
2398 | __u16 current_length; | ||
2399 | unsigned char *transfer_buffer; | ||
2400 | |||
2401 | dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, length); | ||
2402 | |||
2403 | transfer_buffer = kmalloc (64, GFP_KERNEL); | ||
2404 | if (!transfer_buffer) { | ||
2405 | dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 64); | ||
2406 | return -ENOMEM; | ||
2407 | } | ||
2408 | |||
2409 | /* need to split these reads up into 64 byte chunks */ | ||
2410 | result = 0; | ||
2411 | while (length > 0) { | ||
2412 | if (length > 64) { | ||
2413 | current_length = 64; | ||
2414 | } else { | ||
2415 | current_length = length; | ||
2416 | } | ||
2417 | // dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, current_length); | ||
2418 | result = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), USB_REQUEST_ION_READ_ROM, | ||
2419 | 0xC0, addr, extAddr, transfer_buffer, current_length, 300); | ||
2420 | if (result < 0) | ||
2421 | break; | ||
2422 | memcpy (data, transfer_buffer, current_length); | ||
2423 | length -= current_length; | ||
2424 | addr += current_length; | ||
2425 | data += current_length; | ||
2426 | } | ||
2427 | |||
2428 | kfree (transfer_buffer); | ||
2429 | return result; | ||
2430 | } | ||
2431 | |||
2432 | |||
2433 | /**************************************************************************** | ||
2434 | * send_iosp_ext_cmd | ||
2435 | * Is used to send a IOSP message to the Edgeport device | ||
2436 | ****************************************************************************/ | ||
2437 | static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u8 param) | ||
2438 | { | ||
2439 | unsigned char *buffer; | ||
2440 | unsigned char *currentCommand; | ||
2441 | int length = 0; | ||
2442 | int status = 0; | ||
2443 | |||
2444 | dbg("%s - %d, %d", __FUNCTION__, command, param); | ||
2445 | |||
2446 | buffer = kmalloc (10, GFP_ATOMIC); | ||
2447 | if (!buffer) { | ||
2448 | dev_err(&edge_port->port->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 10); | ||
2449 | return -ENOMEM; | ||
2450 | } | ||
2451 | |||
2452 | currentCommand = buffer; | ||
2453 | |||
2454 | MAKE_CMD_EXT_CMD (¤tCommand, &length, | ||
2455 | edge_port->port->number - edge_port->port->serial->minor, | ||
2456 | command, param); | ||
2457 | |||
2458 | status = write_cmd_usb (edge_port, buffer, length); | ||
2459 | if (status) { | ||
2460 | /* something bad happened, let's free up the memory */ | ||
2461 | kfree(buffer); | ||
2462 | } | ||
2463 | |||
2464 | return status; | ||
2465 | } | ||
2466 | |||
2467 | |||
2468 | /***************************************************************************** | ||
2469 | * write_cmd_usb | ||
2470 | * this function writes the given buffer out to the bulk write endpoint. | ||
2471 | *****************************************************************************/ | ||
2472 | static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer, int length) | ||
2473 | { | ||
2474 | struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial); | ||
2475 | int status = 0; | ||
2476 | struct urb *urb; | ||
2477 | int timeout; | ||
2478 | |||
2479 | usb_serial_debug_data(debug, &edge_port->port->dev, __FUNCTION__, length, buffer); | ||
2480 | |||
2481 | /* Allocate our next urb */ | ||
2482 | urb = usb_alloc_urb (0, GFP_ATOMIC); | ||
2483 | if (!urb) | ||
2484 | return -ENOMEM; | ||
2485 | |||
2486 | CmdUrbs++; | ||
2487 | dbg("%s - ALLOCATE URB %p (outstanding %d)", __FUNCTION__, urb, CmdUrbs); | ||
2488 | |||
2489 | usb_fill_bulk_urb (urb, edge_serial->serial->dev, | ||
2490 | usb_sndbulkpipe(edge_serial->serial->dev, edge_serial->bulk_out_endpoint), | ||
2491 | buffer, length, edge_bulk_out_cmd_callback, edge_port); | ||
2492 | |||
2493 | edge_port->commandPending = TRUE; | ||
2494 | status = usb_submit_urb(urb, GFP_ATOMIC); | ||
2495 | |||
2496 | if (status) { | ||
2497 | /* something went wrong */ | ||
2498 | dev_err(&edge_port->port->dev, "%s - usb_submit_urb(write command) failed, status = %d\n", __FUNCTION__, status); | ||
2499 | usb_kill_urb(urb); | ||
2500 | usb_free_urb(urb); | ||
2501 | CmdUrbs--; | ||
2502 | return status; | ||
2503 | } | ||
2504 | |||
2505 | // wait for command to finish | ||
2506 | timeout = COMMAND_TIMEOUT; | ||
2507 | #if 0 | ||
2508 | wait_event (&edge_port->wait_command, (edge_port->commandPending == FALSE)); | ||
2509 | |||
2510 | if (edge_port->commandPending == TRUE) { | ||
2511 | /* command timed out */ | ||
2512 | dbg("%s - command timed out", __FUNCTION__); | ||
2513 | status = -EINVAL; | ||
2514 | } | ||
2515 | #endif | ||
2516 | return status; | ||
2517 | } | ||
2518 | |||
2519 | |||
2520 | /***************************************************************************** | ||
2521 | * send_cmd_write_baud_rate | ||
2522 | * this function sends the proper command to change the baud rate of the | ||
2523 | * specified port. | ||
2524 | *****************************************************************************/ | ||
2525 | static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRate) | ||
2526 | { | ||
2527 | unsigned char *cmdBuffer; | ||
2528 | unsigned char *currCmd; | ||
2529 | int cmdLen = 0; | ||
2530 | int divisor; | ||
2531 | int status; | ||
2532 | unsigned char number = edge_port->port->number - edge_port->port->serial->minor; | ||
2533 | |||
2534 | dbg("%s - port = %d, baud = %d", __FUNCTION__, edge_port->port->number, baudRate); | ||
2535 | |||
2536 | status = calc_baud_rate_divisor (baudRate, &divisor); | ||
2537 | if (status) { | ||
2538 | dev_err(&edge_port->port->dev, "%s - bad baud rate\n", __FUNCTION__); | ||
2539 | return status; | ||
2540 | } | ||
2541 | |||
2542 | // Alloc memory for the string of commands. | ||
2543 | cmdBuffer = kmalloc (0x100, GFP_ATOMIC); | ||
2544 | if (!cmdBuffer) { | ||
2545 | dev_err(&edge_port->port->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 0x100); | ||
2546 | return -ENOMEM; | ||
2547 | } | ||
2548 | currCmd = cmdBuffer; | ||
2549 | |||
2550 | // Enable access to divisor latch | ||
2551 | MAKE_CMD_WRITE_REG( &currCmd, &cmdLen, number, LCR, LCR_DL_ENABLE ); | ||
2552 | |||
2553 | // Write the divisor itself | ||
2554 | MAKE_CMD_WRITE_REG( &currCmd, &cmdLen, number, DLL, LOW8 (divisor) ); | ||
2555 | MAKE_CMD_WRITE_REG( &currCmd, &cmdLen, number, DLM, HIGH8(divisor) ); | ||
2556 | |||
2557 | // Restore original value to disable access to divisor latch | ||
2558 | MAKE_CMD_WRITE_REG( &currCmd, &cmdLen, number, LCR, edge_port->shadowLCR); | ||
2559 | |||
2560 | status = write_cmd_usb(edge_port, cmdBuffer, cmdLen ); | ||
2561 | if (status) { | ||
2562 | /* something bad happened, let's free up the memory */ | ||
2563 | kfree (cmdBuffer); | ||
2564 | } | ||
2565 | |||
2566 | return status; | ||
2567 | } | ||
2568 | |||
2569 | |||
2570 | /***************************************************************************** | ||
2571 | * calc_baud_rate_divisor | ||
2572 | * this function calculates the proper baud rate divisor for the specified | ||
2573 | * baud rate. | ||
2574 | *****************************************************************************/ | ||
2575 | static int calc_baud_rate_divisor (int baudrate, int *divisor) | ||
2576 | { | ||
2577 | int i; | ||
2578 | __u16 custom; | ||
2579 | |||
2580 | |||
2581 | dbg("%s - %d", __FUNCTION__, baudrate); | ||
2582 | |||
2583 | for (i = 0; i < NUM_ENTRIES(divisor_table); i++) { | ||
2584 | if ( divisor_table[i].BaudRate == baudrate ) { | ||
2585 | *divisor = divisor_table[i].Divisor; | ||
2586 | return 0; | ||
2587 | } | ||
2588 | } | ||
2589 | |||
2590 | // We have tried all of the standard baud rates | ||
2591 | // lets try to calculate the divisor for this baud rate | ||
2592 | // Make sure the baud rate is reasonable | ||
2593 | if (baudrate > 50 && baudrate < 230400) { | ||
2594 | // get divisor | ||
2595 | custom = (__u16)((230400L + baudrate/2) / baudrate); | ||
2596 | |||
2597 | *divisor = custom; | ||
2598 | |||
2599 | dbg("%s - Baud %d = %d\n", __FUNCTION__, baudrate, custom); | ||
2600 | return 0; | ||
2601 | } | ||
2602 | |||
2603 | return -1; | ||
2604 | } | ||
2605 | |||
2606 | |||
2607 | /***************************************************************************** | ||
2608 | * send_cmd_write_uart_register | ||
2609 | * this function builds up a uart register message and sends to to the device. | ||
2610 | *****************************************************************************/ | ||
2611 | static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 regNum, __u8 regValue) | ||
2612 | { | ||
2613 | unsigned char *cmdBuffer; | ||
2614 | unsigned char *currCmd; | ||
2615 | unsigned long cmdLen = 0; | ||
2616 | int status; | ||
2617 | |||
2618 | dbg("%s - write to %s register 0x%02x", (regNum == MCR) ? "MCR" : "LCR", __FUNCTION__, regValue); | ||
2619 | |||
2620 | // Alloc memory for the string of commands. | ||
2621 | cmdBuffer = kmalloc (0x10, GFP_ATOMIC); | ||
2622 | if (cmdBuffer == NULL ) { | ||
2623 | return -ENOMEM; | ||
2624 | } | ||
2625 | |||
2626 | currCmd = cmdBuffer; | ||
2627 | |||
2628 | // Build a cmd in the buffer to write the given register | ||
2629 | MAKE_CMD_WRITE_REG (&currCmd, &cmdLen, | ||
2630 | edge_port->port->number - edge_port->port->serial->minor, | ||
2631 | regNum, regValue); | ||
2632 | |||
2633 | status = write_cmd_usb(edge_port, cmdBuffer, cmdLen); | ||
2634 | if (status) { | ||
2635 | /* something bad happened, let's free up the memory */ | ||
2636 | kfree (cmdBuffer); | ||
2637 | } | ||
2638 | |||
2639 | return status; | ||
2640 | } | ||
2641 | |||
2642 | |||
2643 | /***************************************************************************** | ||
2644 | * change_port_settings | ||
2645 | * This routine is called to set the UART on the device to match the specified | ||
2646 | * new settings. | ||
2647 | *****************************************************************************/ | ||
2648 | #ifndef CMSPAR | ||
2649 | #define CMSPAR 0 | ||
2650 | #endif | ||
2651 | static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios) | ||
2652 | { | ||
2653 | struct tty_struct *tty; | ||
2654 | int baud; | ||
2655 | unsigned cflag; | ||
2656 | __u8 mask = 0xff; | ||
2657 | __u8 lData; | ||
2658 | __u8 lParity; | ||
2659 | __u8 lStop; | ||
2660 | __u8 rxFlow; | ||
2661 | __u8 txFlow; | ||
2662 | int status; | ||
2663 | |||
2664 | dbg("%s - port %d", __FUNCTION__, edge_port->port->number); | ||
2665 | |||
2666 | if ((!edge_port->open) && | ||
2667 | (!edge_port->openPending)) { | ||
2668 | dbg("%s - port not opened", __FUNCTION__); | ||
2669 | return; | ||
2670 | } | ||
2671 | |||
2672 | tty = edge_port->port->tty; | ||
2673 | if ((!tty) || | ||
2674 | (!tty->termios)) { | ||
2675 | dbg("%s - no tty structures", __FUNCTION__); | ||
2676 | return; | ||
2677 | } | ||
2678 | |||
2679 | cflag = tty->termios->c_cflag; | ||
2680 | |||
2681 | switch (cflag & CSIZE) { | ||
2682 | case CS5: lData = LCR_BITS_5; mask = 0x1f; dbg("%s - data bits = 5", __FUNCTION__); break; | ||
2683 | case CS6: lData = LCR_BITS_6; mask = 0x3f; dbg("%s - data bits = 6", __FUNCTION__); break; | ||
2684 | case CS7: lData = LCR_BITS_7; mask = 0x7f; dbg("%s - data bits = 7", __FUNCTION__); break; | ||
2685 | default: | ||
2686 | case CS8: lData = LCR_BITS_8; dbg("%s - data bits = 8", __FUNCTION__); break; | ||
2687 | } | ||
2688 | |||
2689 | lParity = LCR_PAR_NONE; | ||
2690 | if (cflag & PARENB) { | ||
2691 | if (cflag & CMSPAR) { | ||
2692 | if (cflag & PARODD) { | ||
2693 | lParity = LCR_PAR_MARK; | ||
2694 | dbg("%s - parity = mark", __FUNCTION__); | ||
2695 | } else { | ||
2696 | lParity = LCR_PAR_SPACE; | ||
2697 | dbg("%s - parity = space", __FUNCTION__); | ||
2698 | } | ||
2699 | } else if (cflag & PARODD) { | ||
2700 | lParity = LCR_PAR_ODD; | ||
2701 | dbg("%s - parity = odd", __FUNCTION__); | ||
2702 | } else { | ||
2703 | lParity = LCR_PAR_EVEN; | ||
2704 | dbg("%s - parity = even", __FUNCTION__); | ||
2705 | } | ||
2706 | } else { | ||
2707 | dbg("%s - parity = none", __FUNCTION__); | ||
2708 | } | ||
2709 | |||
2710 | if (cflag & CSTOPB) { | ||
2711 | lStop = LCR_STOP_2; | ||
2712 | dbg("%s - stop bits = 2", __FUNCTION__); | ||
2713 | } else { | ||
2714 | lStop = LCR_STOP_1; | ||
2715 | dbg("%s - stop bits = 1", __FUNCTION__); | ||
2716 | } | ||
2717 | |||
2718 | /* figure out the flow control settings */ | ||
2719 | rxFlow = txFlow = 0x00; | ||
2720 | if (cflag & CRTSCTS) { | ||
2721 | rxFlow |= IOSP_RX_FLOW_RTS; | ||
2722 | txFlow |= IOSP_TX_FLOW_CTS; | ||
2723 | dbg("%s - RTS/CTS is enabled", __FUNCTION__); | ||
2724 | } else { | ||
2725 | dbg("%s - RTS/CTS is disabled", __FUNCTION__); | ||
2726 | } | ||
2727 | |||
2728 | /* if we are implementing XON/XOFF, set the start and stop character in the device */ | ||
2729 | if (I_IXOFF(tty) || I_IXON(tty)) { | ||
2730 | unsigned char stop_char = STOP_CHAR(tty); | ||
2731 | unsigned char start_char = START_CHAR(tty); | ||
2732 | |||
2733 | send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_XON_CHAR, start_char); | ||
2734 | send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_XOFF_CHAR, stop_char); | ||
2735 | |||
2736 | /* if we are implementing INBOUND XON/XOFF */ | ||
2737 | if (I_IXOFF(tty)) { | ||
2738 | rxFlow |= IOSP_RX_FLOW_XON_XOFF; | ||
2739 | dbg("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", __FUNCTION__, start_char, stop_char); | ||
2740 | } else { | ||
2741 | dbg("%s - INBOUND XON/XOFF is disabled", __FUNCTION__); | ||
2742 | } | ||
2743 | |||
2744 | /* if we are implementing OUTBOUND XON/XOFF */ | ||
2745 | if (I_IXON(tty)) { | ||
2746 | txFlow |= IOSP_TX_FLOW_XON_XOFF; | ||
2747 | dbg("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", __FUNCTION__, start_char, stop_char); | ||
2748 | } else { | ||
2749 | dbg("%s - OUTBOUND XON/XOFF is disabled", __FUNCTION__); | ||
2750 | } | ||
2751 | } | ||
2752 | |||
2753 | /* Set flow control to the configured value */ | ||
2754 | send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_RX_FLOW, rxFlow); | ||
2755 | send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_TX_FLOW, txFlow); | ||
2756 | |||
2757 | |||
2758 | edge_port->shadowLCR &= ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK); | ||
2759 | edge_port->shadowLCR |= (lData | lParity | lStop); | ||
2760 | |||
2761 | edge_port->validDataMask = mask; | ||
2762 | |||
2763 | /* Send the updated LCR value to the EdgePort */ | ||
2764 | status = send_cmd_write_uart_register(edge_port, LCR, edge_port->shadowLCR); | ||
2765 | if (status != 0) { | ||
2766 | return; | ||
2767 | } | ||
2768 | |||
2769 | /* set up the MCR register and send it to the EdgePort */ | ||
2770 | edge_port->shadowMCR = MCR_MASTER_IE; | ||
2771 | if (cflag & CBAUD) { | ||
2772 | edge_port->shadowMCR |= (MCR_DTR | MCR_RTS); | ||
2773 | } | ||
2774 | status = send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR); | ||
2775 | if (status != 0) { | ||
2776 | return; | ||
2777 | } | ||
2778 | |||
2779 | /* Determine divisor based on baud rate */ | ||
2780 | baud = tty_get_baud_rate(tty); | ||
2781 | if (!baud) { | ||
2782 | /* pick a default, any default... */ | ||
2783 | baud = 9600; | ||
2784 | } | ||
2785 | |||
2786 | dbg("%s - baud rate = %d", __FUNCTION__, baud); | ||
2787 | status = send_cmd_write_baud_rate (edge_port, baud); | ||
2788 | |||
2789 | return; | ||
2790 | } | ||
2791 | |||
2792 | |||
2793 | /**************************************************************************** | ||
2794 | * unicode_to_ascii | ||
2795 | * Turns a string from Unicode into ASCII. | ||
2796 | * Doesn't do a good job with any characters that are outside the normal | ||
2797 | * ASCII range, but it's only for debugging... | ||
2798 | * NOTE: expects the unicode in LE format | ||
2799 | ****************************************************************************/ | ||
2800 | static void unicode_to_ascii (char *string, __le16 *unicode, int unicode_size) | ||
2801 | { | ||
2802 | int i; | ||
2803 | |||
2804 | if (unicode_size <= 0) | ||
2805 | return; | ||
2806 | |||
2807 | for (i = 0; i < unicode_size; ++i) | ||
2808 | string[i] = (char)(le16_to_cpu(unicode[i])); | ||
2809 | string[unicode_size] = 0x00; | ||
2810 | } | ||
2811 | |||
2812 | |||
2813 | /**************************************************************************** | ||
2814 | * get_manufacturing_desc | ||
2815 | * reads in the manufacturing descriptor and stores it into the serial | ||
2816 | * structure. | ||
2817 | ****************************************************************************/ | ||
2818 | static void get_manufacturing_desc (struct edgeport_serial *edge_serial) | ||
2819 | { | ||
2820 | int response; | ||
2821 | |||
2822 | dbg("getting manufacturer descriptor"); | ||
2823 | |||
2824 | response = rom_read (edge_serial->serial, (EDGE_MANUF_DESC_ADDR & 0xffff0000) >> 16, | ||
2825 | (__u16)(EDGE_MANUF_DESC_ADDR & 0x0000ffff), EDGE_MANUF_DESC_LEN, | ||
2826 | (__u8 *)(&edge_serial->manuf_descriptor)); | ||
2827 | |||
2828 | if (response < 1) { | ||
2829 | dev_err(&edge_serial->serial->dev->dev, "error in getting manufacturer descriptor\n"); | ||
2830 | } else { | ||
2831 | char string[30]; | ||
2832 | dbg("**Manufacturer Descriptor"); | ||
2833 | dbg(" RomSize: %dK", edge_serial->manuf_descriptor.RomSize); | ||
2834 | dbg(" RamSize: %dK", edge_serial->manuf_descriptor.RamSize); | ||
2835 | dbg(" CpuRev: %d", edge_serial->manuf_descriptor.CpuRev); | ||
2836 | dbg(" BoardRev: %d", edge_serial->manuf_descriptor.BoardRev); | ||
2837 | dbg(" NumPorts: %d", edge_serial->manuf_descriptor.NumPorts); | ||
2838 | dbg(" DescDate: %d/%d/%d", edge_serial->manuf_descriptor.DescDate[0], edge_serial->manuf_descriptor.DescDate[1], edge_serial->manuf_descriptor.DescDate[2]+1900); | ||
2839 | unicode_to_ascii (string, edge_serial->manuf_descriptor.SerialNumber, edge_serial->manuf_descriptor.SerNumLength/2-1); | ||
2840 | dbg(" SerialNumber: %s", string); | ||
2841 | unicode_to_ascii (string, edge_serial->manuf_descriptor.AssemblyNumber, edge_serial->manuf_descriptor.AssemblyNumLength/2-1); | ||
2842 | dbg(" AssemblyNumber: %s", string); | ||
2843 | unicode_to_ascii (string, edge_serial->manuf_descriptor.OemAssyNumber, edge_serial->manuf_descriptor.OemAssyNumLength/2-1); | ||
2844 | dbg(" OemAssyNumber: %s", string); | ||
2845 | dbg(" UartType: %d", edge_serial->manuf_descriptor.UartType); | ||
2846 | dbg(" IonPid: %d", edge_serial->manuf_descriptor.IonPid); | ||
2847 | dbg(" IonConfig: %d", edge_serial->manuf_descriptor.IonConfig); | ||
2848 | } | ||
2849 | } | ||
2850 | |||
2851 | |||
2852 | /**************************************************************************** | ||
2853 | * get_boot_desc | ||
2854 | * reads in the bootloader descriptor and stores it into the serial | ||
2855 | * structure. | ||
2856 | ****************************************************************************/ | ||
2857 | static void get_boot_desc (struct edgeport_serial *edge_serial) | ||
2858 | { | ||
2859 | int response; | ||
2860 | |||
2861 | dbg("getting boot descriptor"); | ||
2862 | |||
2863 | response = rom_read (edge_serial->serial, (EDGE_BOOT_DESC_ADDR & 0xffff0000) >> 16, | ||
2864 | (__u16)(EDGE_BOOT_DESC_ADDR & 0x0000ffff), EDGE_BOOT_DESC_LEN, | ||
2865 | (__u8 *)(&edge_serial->boot_descriptor)); | ||
2866 | |||
2867 | if (response < 1) { | ||
2868 | dev_err(&edge_serial->serial->dev->dev, "error in getting boot descriptor\n"); | ||
2869 | } else { | ||
2870 | dbg("**Boot Descriptor:"); | ||
2871 | dbg(" BootCodeLength: %d", le16_to_cpu(edge_serial->boot_descriptor.BootCodeLength)); | ||
2872 | dbg(" MajorVersion: %d", edge_serial->boot_descriptor.MajorVersion); | ||
2873 | dbg(" MinorVersion: %d", edge_serial->boot_descriptor.MinorVersion); | ||
2874 | dbg(" BuildNumber: %d", le16_to_cpu(edge_serial->boot_descriptor.BuildNumber)); | ||
2875 | dbg(" Capabilities: 0x%x", le16_to_cpu(edge_serial->boot_descriptor.Capabilities)); | ||
2876 | dbg(" UConfig0: %d", edge_serial->boot_descriptor.UConfig0); | ||
2877 | dbg(" UConfig1: %d", edge_serial->boot_descriptor.UConfig1); | ||
2878 | } | ||
2879 | } | ||
2880 | |||
2881 | |||
2882 | /**************************************************************************** | ||
2883 | * load_application_firmware | ||
2884 | * This is called to load the application firmware to the device | ||
2885 | ****************************************************************************/ | ||
2886 | static void load_application_firmware (struct edgeport_serial *edge_serial) | ||
2887 | { | ||
2888 | struct edge_firmware_image_record *record; | ||
2889 | unsigned char *firmware; | ||
2890 | unsigned char *FirmwareImage; | ||
2891 | int ImageSize; | ||
2892 | int response; | ||
2893 | |||
2894 | |||
2895 | switch (edge_serial->product_info.iDownloadFile) { | ||
2896 | case EDGE_DOWNLOAD_FILE_I930: | ||
2897 | dbg("downloading firmware version (930) %d.%d.%d", | ||
2898 | OperationalCodeImageVersion_GEN1.MajorVersion, | ||
2899 | OperationalCodeImageVersion_GEN1.MinorVersion, | ||
2900 | OperationalCodeImageVersion_GEN1.BuildNumber); | ||
2901 | firmware = &OperationalCodeImage_GEN1[0]; | ||
2902 | FirmwareImage = &OperationalCodeImage_GEN1[0]; | ||
2903 | ImageSize = sizeof(OperationalCodeImage_GEN1); | ||
2904 | break; | ||
2905 | |||
2906 | case EDGE_DOWNLOAD_FILE_80251: | ||
2907 | dbg("downloading firmware version (80251) %d.%d.%d", | ||
2908 | OperationalCodeImageVersion_GEN2.MajorVersion, | ||
2909 | OperationalCodeImageVersion_GEN2.MinorVersion, | ||
2910 | OperationalCodeImageVersion_GEN2.BuildNumber); | ||
2911 | firmware = &OperationalCodeImage_GEN2[0]; | ||
2912 | FirmwareImage = &OperationalCodeImage_GEN2[0]; | ||
2913 | ImageSize = sizeof(OperationalCodeImage_GEN2); | ||
2914 | break; | ||
2915 | |||
2916 | case EDGE_DOWNLOAD_FILE_NONE: | ||
2917 | dbg ("No download file specified, skipping download\n"); | ||
2918 | return; | ||
2919 | |||
2920 | default: | ||
2921 | return; | ||
2922 | } | ||
2923 | |||
2924 | |||
2925 | for (;;) { | ||
2926 | record = (struct edge_firmware_image_record *)firmware; | ||
2927 | response = sram_write (edge_serial->serial, le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), le16_to_cpu(record->Len), &record->Data[0]); | ||
2928 | if (response < 0) { | ||
2929 | dev_err(&edge_serial->serial->dev->dev, "sram_write failed (%x, %x, %d)\n", le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), le16_to_cpu(record->Len)); | ||
2930 | break; | ||
2931 | } | ||
2932 | firmware += sizeof (struct edge_firmware_image_record) + le16_to_cpu(record->Len); | ||
2933 | if (firmware >= &FirmwareImage[ImageSize]) { | ||
2934 | break; | ||
2935 | } | ||
2936 | } | ||
2937 | |||
2938 | dbg("sending exec_dl_code"); | ||
2939 | response = usb_control_msg (edge_serial->serial->dev, | ||
2940 | usb_sndctrlpipe(edge_serial->serial->dev, 0), | ||
2941 | USB_REQUEST_ION_EXEC_DL_CODE, | ||
2942 | 0x40, 0x4000, 0x0001, NULL, 0, 3000); | ||
2943 | |||
2944 | return; | ||
2945 | } | ||
2946 | |||
2947 | |||
2948 | /**************************************************************************** | ||
2949 | * edge_startup | ||
2950 | ****************************************************************************/ | ||
2951 | static int edge_startup (struct usb_serial *serial) | ||
2952 | { | ||
2953 | struct edgeport_serial *edge_serial; | ||
2954 | struct edgeport_port *edge_port; | ||
2955 | struct usb_device *dev; | ||
2956 | int i; | ||
2957 | |||
2958 | dev = serial->dev; | ||
2959 | |||
2960 | /* create our private serial structure */ | ||
2961 | edge_serial = kmalloc (sizeof(struct edgeport_serial), GFP_KERNEL); | ||
2962 | if (edge_serial == NULL) { | ||
2963 | dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__); | ||
2964 | return -ENOMEM; | ||
2965 | } | ||
2966 | memset (edge_serial, 0, sizeof(struct edgeport_serial)); | ||
2967 | spin_lock_init(&edge_serial->es_lock); | ||
2968 | edge_serial->serial = serial; | ||
2969 | usb_set_serial_data(serial, edge_serial); | ||
2970 | |||
2971 | /* get the name for the device from the device */ | ||
2972 | if ( (i = get_string(dev, dev->descriptor.iManufacturer, &edge_serial->name[0])) != 0) { | ||
2973 | edge_serial->name[i-1] = ' '; | ||
2974 | } | ||
2975 | |||
2976 | get_string(dev, dev->descriptor.iProduct, &edge_serial->name[i]); | ||
2977 | |||
2978 | dev_info(&serial->dev->dev, "%s detected\n", edge_serial->name); | ||
2979 | |||
2980 | /* get the manufacturing descriptor for this device */ | ||
2981 | get_manufacturing_desc (edge_serial); | ||
2982 | |||
2983 | /* get the boot descriptor */ | ||
2984 | get_boot_desc (edge_serial); | ||
2985 | |||
2986 | get_product_info(edge_serial); | ||
2987 | |||
2988 | /* set the number of ports from the manufacturing description */ | ||
2989 | /* serial->num_ports = serial->product_info.NumPorts; */ | ||
2990 | if (edge_serial->product_info.NumPorts != serial->num_ports) { | ||
2991 | warn("%s - Device Reported %d serial ports vs core " | ||
2992 | "thinking we have %d ports, email greg@kroah.com this info.", | ||
2993 | __FUNCTION__, edge_serial->product_info.NumPorts, | ||
2994 | serial->num_ports); | ||
2995 | } | ||
2996 | |||
2997 | dbg("%s - time 1 %ld", __FUNCTION__, jiffies); | ||
2998 | |||
2999 | /* now load the application firmware into this device */ | ||
3000 | load_application_firmware (edge_serial); | ||
3001 | |||
3002 | dbg("%s - time 2 %ld", __FUNCTION__, jiffies); | ||
3003 | |||
3004 | /* Check current Edgeport EEPROM and update if necessary */ | ||
3005 | update_edgeport_E2PROM (edge_serial); | ||
3006 | |||
3007 | dbg("%s - time 3 %ld", __FUNCTION__, jiffies); | ||
3008 | |||
3009 | /* set the configuration to use #1 */ | ||
3010 | // dbg("set_configuration 1"); | ||
3011 | // usb_set_configuration (dev, 1); | ||
3012 | |||
3013 | /* we set up the pointers to the endpoints in the edge_open function, | ||
3014 | * as the structures aren't created yet. */ | ||
3015 | |||
3016 | /* set up our port private structures */ | ||
3017 | for (i = 0; i < serial->num_ports; ++i) { | ||
3018 | edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL); | ||
3019 | if (edge_port == NULL) { | ||
3020 | dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__); | ||
3021 | usb_set_serial_data(serial, NULL); | ||
3022 | kfree(edge_serial); | ||
3023 | return -ENOMEM; | ||
3024 | } | ||
3025 | memset (edge_port, 0, sizeof(struct edgeport_port)); | ||
3026 | spin_lock_init(&edge_port->ep_lock); | ||
3027 | edge_port->port = serial->port[i]; | ||
3028 | usb_set_serial_port_data(serial->port[i], edge_port); | ||
3029 | } | ||
3030 | |||
3031 | return 0; | ||
3032 | } | ||
3033 | |||
3034 | |||
3035 | /**************************************************************************** | ||
3036 | * edge_shutdown | ||
3037 | * This function is called whenever the device is removed from the usb bus. | ||
3038 | ****************************************************************************/ | ||
3039 | static void edge_shutdown (struct usb_serial *serial) | ||
3040 | { | ||
3041 | int i; | ||
3042 | |||
3043 | dbg("%s", __FUNCTION__); | ||
3044 | |||
3045 | /* stop reads and writes on all ports */ | ||
3046 | for (i=0; i < serial->num_ports; ++i) { | ||
3047 | kfree (usb_get_serial_port_data(serial->port[i])); | ||
3048 | usb_set_serial_port_data(serial->port[i], NULL); | ||
3049 | } | ||
3050 | kfree (usb_get_serial_data(serial)); | ||
3051 | usb_set_serial_data(serial, NULL); | ||
3052 | } | ||
3053 | |||
3054 | |||
3055 | /**************************************************************************** | ||
3056 | * edgeport_init | ||
3057 | * This is called by the module subsystem, or on startup to initialize us | ||
3058 | ****************************************************************************/ | ||
3059 | static int __init edgeport_init(void) | ||
3060 | { | ||
3061 | int retval; | ||
3062 | |||
3063 | retval = usb_serial_register(&edgeport_2port_device); | ||
3064 | if (retval) | ||
3065 | goto failed_2port_device_register; | ||
3066 | retval = usb_serial_register(&edgeport_4port_device); | ||
3067 | if (retval) | ||
3068 | goto failed_4port_device_register; | ||
3069 | retval = usb_serial_register(&edgeport_8port_device); | ||
3070 | if (retval) | ||
3071 | goto failed_8port_device_register; | ||
3072 | retval = usb_register(&io_driver); | ||
3073 | if (retval) | ||
3074 | goto failed_usb_register; | ||
3075 | info(DRIVER_DESC " " DRIVER_VERSION); | ||
3076 | return 0; | ||
3077 | |||
3078 | failed_usb_register: | ||
3079 | usb_serial_deregister(&edgeport_8port_device); | ||
3080 | failed_8port_device_register: | ||
3081 | usb_serial_deregister(&edgeport_4port_device); | ||
3082 | failed_4port_device_register: | ||
3083 | usb_serial_deregister(&edgeport_2port_device); | ||
3084 | failed_2port_device_register: | ||
3085 | return retval; | ||
3086 | } | ||
3087 | |||
3088 | |||
3089 | /**************************************************************************** | ||
3090 | * edgeport_exit | ||
3091 | * Called when the driver is about to be unloaded. | ||
3092 | ****************************************************************************/ | ||
3093 | static void __exit edgeport_exit (void) | ||
3094 | { | ||
3095 | usb_deregister (&io_driver); | ||
3096 | usb_serial_deregister (&edgeport_2port_device); | ||
3097 | usb_serial_deregister (&edgeport_4port_device); | ||
3098 | usb_serial_deregister (&edgeport_8port_device); | ||
3099 | } | ||
3100 | |||
3101 | module_init(edgeport_init); | ||
3102 | module_exit(edgeport_exit); | ||
3103 | |||
3104 | /* Module information */ | ||
3105 | MODULE_AUTHOR( DRIVER_AUTHOR ); | ||
3106 | MODULE_DESCRIPTION( DRIVER_DESC ); | ||
3107 | MODULE_LICENSE("GPL"); | ||
3108 | |||
3109 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
3110 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | ||
3111 | |||
3112 | module_param(low_latency, bool, S_IRUGO | S_IWUSR); | ||
3113 | MODULE_PARM_DESC(low_latency, "Low latency enabled or not"); | ||