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_ti.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_ti.c')
-rw-r--r-- | drivers/usb/serial/io_ti.c | 3091 |
1 files changed, 3091 insertions, 0 deletions
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c new file mode 100644 index 000000000000..6c96fdaec36e --- /dev/null +++ b/drivers/usb/serial/io_ti.c | |||
@@ -0,0 +1,3091 @@ | |||
1 | /* | ||
2 | * Edgeport USB Serial Converter driver | ||
3 | * | ||
4 | * Copyright (C) 2000-2002 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 | * EP/1 EP/2 EP/4 EP/21 EP/22 EP/221 EP/42 EP/421 WATCHPORT | ||
14 | * | ||
15 | * For questions or problems with this driver, contact Inside Out | ||
16 | * Networks technical support, or Peter Berger <pberger@brimson.com>, | ||
17 | * or Al Borchers <alborchers@steinerpoint.com>. | ||
18 | * | ||
19 | * Version history: | ||
20 | * | ||
21 | * July 11, 2002 Removed 4 port device structure since all TI UMP | ||
22 | * chips have only 2 ports | ||
23 | * David Iacovelli (davidi@ionetworks.com) | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #include <linux/config.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/jiffies.h> | ||
30 | #include <linux/errno.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/slab.h> | ||
33 | #include <linux/tty.h> | ||
34 | #include <linux/tty_driver.h> | ||
35 | #include <linux/tty_flip.h> | ||
36 | #include <linux/module.h> | ||
37 | #include <linux/spinlock.h> | ||
38 | #include <linux/serial.h> | ||
39 | #include <linux/ioctl.h> | ||
40 | #include <asm/uaccess.h> | ||
41 | #include <asm/semaphore.h> | ||
42 | #include <linux/usb.h> | ||
43 | |||
44 | #include "usb-serial.h" | ||
45 | #include "io_16654.h" | ||
46 | #include "io_usbvend.h" | ||
47 | #include "io_ti.h" | ||
48 | |||
49 | /* | ||
50 | * Version Information | ||
51 | */ | ||
52 | #define DRIVER_VERSION "v0.7" | ||
53 | #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli" | ||
54 | #define DRIVER_DESC "Edgeport USB Serial Driver" | ||
55 | |||
56 | |||
57 | /* firmware image code */ | ||
58 | #define IMAGE_VERSION_NAME PagableOperationalCodeImageVersion | ||
59 | #define IMAGE_ARRAY_NAME PagableOperationalCodeImage | ||
60 | #define IMAGE_SIZE PagableOperationalCodeSize | ||
61 | #include "io_fw_down3.h" /* Define array OperationalCodeImage[] */ | ||
62 | |||
63 | #define EPROM_PAGE_SIZE 64 | ||
64 | |||
65 | |||
66 | struct edgeport_uart_buf_desc { | ||
67 | __u32 count; // Number of bytes currently in buffer | ||
68 | }; | ||
69 | |||
70 | /* different hardware types */ | ||
71 | #define HARDWARE_TYPE_930 0 | ||
72 | #define HARDWARE_TYPE_TIUMP 1 | ||
73 | |||
74 | // IOCTL_PRIVATE_TI_GET_MODE Definitions | ||
75 | #define TI_MODE_CONFIGURING 0 // Device has not entered start device | ||
76 | #define TI_MODE_BOOT 1 // Staying in boot mode | ||
77 | #define TI_MODE_DOWNLOAD 2 // Made it to download mode | ||
78 | #define TI_MODE_TRANSITIONING 3 // Currently in boot mode but transitioning to download mode | ||
79 | |||
80 | /* read urb state */ | ||
81 | #define EDGE_READ_URB_RUNNING 0 | ||
82 | #define EDGE_READ_URB_STOPPING 1 | ||
83 | #define EDGE_READ_URB_STOPPED 2 | ||
84 | |||
85 | #define EDGE_LOW_LATENCY 1 | ||
86 | #define EDGE_CLOSING_WAIT 4000 /* in .01 sec */ | ||
87 | |||
88 | #define EDGE_OUT_BUF_SIZE 1024 | ||
89 | |||
90 | |||
91 | /* Product information read from the Edgeport */ | ||
92 | struct product_info | ||
93 | { | ||
94 | int TiMode; // Current TI Mode | ||
95 | __u8 hardware_type; // Type of hardware | ||
96 | } __attribute__((packed)); | ||
97 | |||
98 | /* circular buffer */ | ||
99 | struct edge_buf { | ||
100 | unsigned int buf_size; | ||
101 | char *buf_buf; | ||
102 | char *buf_get; | ||
103 | char *buf_put; | ||
104 | }; | ||
105 | |||
106 | struct edgeport_port { | ||
107 | __u16 uart_base; | ||
108 | __u16 dma_address; | ||
109 | __u8 shadow_msr; | ||
110 | __u8 shadow_mcr; | ||
111 | __u8 shadow_lsr; | ||
112 | __u8 lsr_mask; | ||
113 | __u32 ump_read_timeout; /* Number of miliseconds the UMP will | ||
114 | wait without data before completing | ||
115 | a read short */ | ||
116 | int baud_rate; | ||
117 | int close_pending; | ||
118 | int lsr_event; | ||
119 | struct edgeport_uart_buf_desc tx; | ||
120 | struct async_icount icount; | ||
121 | wait_queue_head_t delta_msr_wait; /* for handling sleeping while | ||
122 | waiting for msr change to | ||
123 | happen */ | ||
124 | struct edgeport_serial *edge_serial; | ||
125 | struct usb_serial_port *port; | ||
126 | __u8 bUartMode; /* Port type, 0: RS232, etc. */ | ||
127 | spinlock_t ep_lock; | ||
128 | int ep_read_urb_state; | ||
129 | int ep_write_urb_in_use; | ||
130 | struct edge_buf *ep_out_buf; | ||
131 | }; | ||
132 | |||
133 | struct edgeport_serial { | ||
134 | struct product_info product_info; | ||
135 | u8 TI_I2C_Type; // Type of I2C in UMP | ||
136 | u8 TiReadI2C; // Set to TRUE if we have read the I2c in Boot Mode | ||
137 | struct semaphore es_sem; | ||
138 | int num_ports_open; | ||
139 | struct usb_serial *serial; | ||
140 | }; | ||
141 | |||
142 | |||
143 | /* Devices that this driver supports */ | ||
144 | static struct usb_device_id edgeport_1port_id_table [] = { | ||
145 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_1) }, | ||
146 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_TI3410_EDGEPORT_1) }, | ||
147 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_TI3410_EDGEPORT_1I) }, | ||
148 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_PROXIMITY) }, | ||
149 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_MOTION) }, | ||
150 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_MOISTURE) }, | ||
151 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_TEMPERATURE) }, | ||
152 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_HUMIDITY) }, | ||
153 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_POWER) }, | ||
154 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_LIGHT) }, | ||
155 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_RADIATION) }, | ||
156 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_DISTANCE) }, | ||
157 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_ACCELERATION) }, | ||
158 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_PROX_DIST) }, | ||
159 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_PLUS_PWR_HP4CD) }, | ||
160 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_PLUS_PWR_PCI) }, | ||
161 | { } | ||
162 | }; | ||
163 | |||
164 | static struct usb_device_id edgeport_2port_id_table [] = { | ||
165 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2) }, | ||
166 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2C) }, | ||
167 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2I) }, | ||
168 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421) }, | ||
169 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21) }, | ||
170 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_42) }, | ||
171 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4) }, | ||
172 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4I) }, | ||
173 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22I) }, | ||
174 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_221C) }, | ||
175 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22C) }, | ||
176 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21C) }, | ||
177 | // The 4-port shows up as two 2-port devices | ||
178 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4S) }, | ||
179 | { } | ||
180 | }; | ||
181 | |||
182 | /* Devices that this driver supports */ | ||
183 | static struct usb_device_id id_table_combined [] = { | ||
184 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_1) }, | ||
185 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_TI3410_EDGEPORT_1) }, | ||
186 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_TI3410_EDGEPORT_1I) }, | ||
187 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_PROXIMITY) }, | ||
188 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_MOTION) }, | ||
189 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_MOISTURE) }, | ||
190 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_TEMPERATURE) }, | ||
191 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_HUMIDITY) }, | ||
192 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_POWER) }, | ||
193 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_LIGHT) }, | ||
194 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_RADIATION) }, | ||
195 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_DISTANCE) }, | ||
196 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_ACCELERATION) }, | ||
197 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_PROX_DIST) }, | ||
198 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_PLUS_PWR_HP4CD) }, | ||
199 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_PLUS_PWR_PCI) }, | ||
200 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2) }, | ||
201 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2C) }, | ||
202 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2I) }, | ||
203 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421) }, | ||
204 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21) }, | ||
205 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_42) }, | ||
206 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4) }, | ||
207 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4I) }, | ||
208 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22I) }, | ||
209 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_221C) }, | ||
210 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22C) }, | ||
211 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21C) }, | ||
212 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4S) }, | ||
213 | { } | ||
214 | }; | ||
215 | |||
216 | MODULE_DEVICE_TABLE (usb, id_table_combined); | ||
217 | |||
218 | static struct usb_driver io_driver = { | ||
219 | .owner = THIS_MODULE, | ||
220 | .name = "io_ti", | ||
221 | .probe = usb_serial_probe, | ||
222 | .disconnect = usb_serial_disconnect, | ||
223 | .id_table = id_table_combined, | ||
224 | }; | ||
225 | |||
226 | |||
227 | static struct EDGE_FIRMWARE_VERSION_INFO OperationalCodeImageVersion; | ||
228 | |||
229 | static int debug; | ||
230 | |||
231 | static int TIStayInBootMode = 0; | ||
232 | static int low_latency = EDGE_LOW_LATENCY; | ||
233 | static int closing_wait = EDGE_CLOSING_WAIT; | ||
234 | static int ignore_cpu_rev = 0; | ||
235 | |||
236 | |||
237 | static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length); | ||
238 | |||
239 | static void stop_read(struct edgeport_port *edge_port); | ||
240 | static int restart_read(struct edgeport_port *edge_port); | ||
241 | |||
242 | static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios); | ||
243 | static void edge_send(struct usb_serial_port *port); | ||
244 | |||
245 | /* circular buffer */ | ||
246 | static struct edge_buf *edge_buf_alloc(unsigned int size); | ||
247 | static void edge_buf_free(struct edge_buf *eb); | ||
248 | static void edge_buf_clear(struct edge_buf *eb); | ||
249 | static unsigned int edge_buf_data_avail(struct edge_buf *eb); | ||
250 | static unsigned int edge_buf_space_avail(struct edge_buf *eb); | ||
251 | static unsigned int edge_buf_put(struct edge_buf *eb, const char *buf, | ||
252 | unsigned int count); | ||
253 | static unsigned int edge_buf_get(struct edge_buf *eb, char *buf, | ||
254 | unsigned int count); | ||
255 | |||
256 | |||
257 | static int TIReadVendorRequestSync (struct usb_device *dev, | ||
258 | __u8 request, | ||
259 | __u16 value, | ||
260 | __u16 index, | ||
261 | u8 *data, | ||
262 | int size) | ||
263 | { | ||
264 | int status; | ||
265 | |||
266 | status = usb_control_msg (dev, | ||
267 | usb_rcvctrlpipe(dev, 0), | ||
268 | request, | ||
269 | (USB_TYPE_VENDOR | | ||
270 | USB_RECIP_DEVICE | | ||
271 | USB_DIR_IN), | ||
272 | value, | ||
273 | index, | ||
274 | data, | ||
275 | size, | ||
276 | 1000); | ||
277 | if (status < 0) | ||
278 | return status; | ||
279 | if (status != size) { | ||
280 | dbg ("%s - wanted to write %d, but only wrote %d", | ||
281 | __FUNCTION__, size, status); | ||
282 | return -ECOMM; | ||
283 | } | ||
284 | return 0; | ||
285 | } | ||
286 | |||
287 | static int TISendVendorRequestSync (struct usb_device *dev, | ||
288 | __u8 request, | ||
289 | __u16 value, | ||
290 | __u16 index, | ||
291 | u8 *data, | ||
292 | int size) | ||
293 | { | ||
294 | int status; | ||
295 | |||
296 | status = usb_control_msg (dev, | ||
297 | usb_sndctrlpipe(dev, 0), | ||
298 | request, | ||
299 | (USB_TYPE_VENDOR | | ||
300 | USB_RECIP_DEVICE | | ||
301 | USB_DIR_OUT), | ||
302 | value, | ||
303 | index, | ||
304 | data, | ||
305 | size, | ||
306 | 1000); | ||
307 | if (status < 0) | ||
308 | return status; | ||
309 | if (status != size) { | ||
310 | dbg ("%s - wanted to write %d, but only wrote %d", | ||
311 | __FUNCTION__, size, status); | ||
312 | return -ECOMM; | ||
313 | } | ||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | static int TIWriteCommandSync (struct usb_device *dev, __u8 command, | ||
318 | __u8 moduleid, __u16 value, u8 *data, | ||
319 | int size) | ||
320 | { | ||
321 | return TISendVendorRequestSync (dev, | ||
322 | command, // Request | ||
323 | value, // wValue | ||
324 | moduleid, // wIndex | ||
325 | data, // TransferBuffer | ||
326 | size); // TransferBufferLength | ||
327 | |||
328 | } | ||
329 | |||
330 | /* clear tx/rx buffers and fifo in TI UMP */ | ||
331 | static int TIPurgeDataSync (struct usb_serial_port *port, __u16 mask) | ||
332 | { | ||
333 | int port_number = port->number - port->serial->minor; | ||
334 | |||
335 | dbg ("%s - port %d, mask %x", __FUNCTION__, port_number, mask); | ||
336 | |||
337 | return TIWriteCommandSync (port->serial->dev, | ||
338 | UMPC_PURGE_PORT, | ||
339 | (__u8)(UMPM_UART1_PORT + port_number), | ||
340 | mask, | ||
341 | NULL, | ||
342 | 0); | ||
343 | } | ||
344 | |||
345 | /** | ||
346 | * TIReadDownloadMemory - Read edgeport memory from TI chip | ||
347 | * @dev: usb device pointer | ||
348 | * @start_address: Device CPU address at which to read | ||
349 | * @length: Length of above data | ||
350 | * @address_type: Can read both XDATA and I2C | ||
351 | * @buffer: pointer to input data buffer | ||
352 | */ | ||
353 | static int TIReadDownloadMemory(struct usb_device *dev, int start_address, | ||
354 | int length, __u8 address_type, __u8 *buffer) | ||
355 | { | ||
356 | int status = 0; | ||
357 | __u8 read_length; | ||
358 | __be16 be_start_address; | ||
359 | |||
360 | dbg ("%s - @ %x for %d", __FUNCTION__, start_address, length); | ||
361 | |||
362 | /* Read in blocks of 64 bytes | ||
363 | * (TI firmware can't handle more than 64 byte reads) | ||
364 | */ | ||
365 | while (length) { | ||
366 | if (length > 64) | ||
367 | read_length= 64; | ||
368 | else | ||
369 | read_length = (__u8)length; | ||
370 | |||
371 | if (read_length > 1) { | ||
372 | dbg ("%s - @ %x for %d", __FUNCTION__, | ||
373 | start_address, read_length); | ||
374 | } | ||
375 | be_start_address = cpu_to_be16 (start_address); | ||
376 | status = TIReadVendorRequestSync (dev, | ||
377 | UMPC_MEMORY_READ, // Request | ||
378 | (__u16)address_type, // wValue (Address type) | ||
379 | (__force __u16)be_start_address, // wIndex (Address to read) | ||
380 | buffer, // TransferBuffer | ||
381 | read_length); // TransferBufferLength | ||
382 | |||
383 | if (status) { | ||
384 | dbg ("%s - ERROR %x", __FUNCTION__, status); | ||
385 | return status; | ||
386 | } | ||
387 | |||
388 | if (read_length > 1) { | ||
389 | usb_serial_debug_data(debug, &dev->dev, __FUNCTION__, | ||
390 | read_length, buffer); | ||
391 | } | ||
392 | |||
393 | /* Update pointers/length */ | ||
394 | start_address += read_length; | ||
395 | buffer += read_length; | ||
396 | length -= read_length; | ||
397 | } | ||
398 | |||
399 | return status; | ||
400 | } | ||
401 | |||
402 | static int TIReadRam (struct usb_device *dev, int start_address, int length, __u8 *buffer) | ||
403 | { | ||
404 | return TIReadDownloadMemory (dev, | ||
405 | start_address, | ||
406 | length, | ||
407 | DTK_ADDR_SPACE_XDATA, | ||
408 | buffer); | ||
409 | } | ||
410 | |||
411 | /* Read edgeport memory to a given block */ | ||
412 | static int TIReadBootMemory (struct edgeport_serial *serial, int start_address, int length, __u8 * buffer) | ||
413 | { | ||
414 | int status = 0; | ||
415 | int i; | ||
416 | |||
417 | for (i=0; i< length; i++) { | ||
418 | status = TIReadVendorRequestSync (serial->serial->dev, | ||
419 | UMPC_MEMORY_READ, // Request | ||
420 | serial->TI_I2C_Type, // wValue (Address type) | ||
421 | (__u16)(start_address+i), // wIndex | ||
422 | &buffer[i], // TransferBuffer | ||
423 | 0x01); // TransferBufferLength | ||
424 | if (status) { | ||
425 | dbg ("%s - ERROR %x", __FUNCTION__, status); | ||
426 | return status; | ||
427 | } | ||
428 | } | ||
429 | |||
430 | dbg ("%s - start_address = %x, length = %d", __FUNCTION__, start_address, length); | ||
431 | usb_serial_debug_data(debug, &serial->serial->dev->dev, __FUNCTION__, length, buffer); | ||
432 | |||
433 | serial->TiReadI2C = 1; | ||
434 | |||
435 | return status; | ||
436 | } | ||
437 | |||
438 | /* Write given block to TI EPROM memory */ | ||
439 | static int TIWriteBootMemory (struct edgeport_serial *serial, int start_address, int length, __u8 *buffer) | ||
440 | { | ||
441 | int status = 0; | ||
442 | int i; | ||
443 | __u8 temp; | ||
444 | |||
445 | /* Must do a read before write */ | ||
446 | if (!serial->TiReadI2C) { | ||
447 | status = TIReadBootMemory(serial, 0, 1, &temp); | ||
448 | if (status) | ||
449 | return status; | ||
450 | } | ||
451 | |||
452 | for (i=0; i < length; ++i) { | ||
453 | status = TISendVendorRequestSync (serial->serial->dev, | ||
454 | UMPC_MEMORY_WRITE, // Request | ||
455 | buffer[i], // wValue | ||
456 | (__u16)(i+start_address), // wIndex | ||
457 | NULL, // TransferBuffer | ||
458 | 0); // TransferBufferLength | ||
459 | if (status) | ||
460 | return status; | ||
461 | } | ||
462 | |||
463 | dbg ("%s - start_sddr = %x, length = %d", __FUNCTION__, start_address, length); | ||
464 | usb_serial_debug_data(debug, &serial->serial->dev->dev, __FUNCTION__, length, buffer); | ||
465 | |||
466 | return status; | ||
467 | } | ||
468 | |||
469 | |||
470 | /* Write edgeport I2C memory to TI chip */ | ||
471 | static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address, int length, __u8 address_type, __u8 *buffer) | ||
472 | { | ||
473 | int status = 0; | ||
474 | int write_length; | ||
475 | __be16 be_start_address; | ||
476 | |||
477 | /* We can only send a maximum of 1 aligned byte page at a time */ | ||
478 | |||
479 | /* calulate the number of bytes left in the first page */ | ||
480 | write_length = EPROM_PAGE_SIZE - (start_address & (EPROM_PAGE_SIZE - 1)); | ||
481 | |||
482 | if (write_length > length) | ||
483 | write_length = length; | ||
484 | |||
485 | dbg ("%s - BytesInFirstPage Addr = %x, length = %d", __FUNCTION__, start_address, write_length); | ||
486 | usb_serial_debug_data(debug, &serial->serial->dev->dev, __FUNCTION__, write_length, buffer); | ||
487 | |||
488 | /* Write first page */ | ||
489 | be_start_address = cpu_to_be16 (start_address); | ||
490 | status = TISendVendorRequestSync (serial->serial->dev, | ||
491 | UMPC_MEMORY_WRITE, // Request | ||
492 | (__u16)address_type, // wValue | ||
493 | (__force __u16)be_start_address, // wIndex | ||
494 | buffer, // TransferBuffer | ||
495 | write_length); | ||
496 | if (status) { | ||
497 | dbg ("%s - ERROR %d", __FUNCTION__, status); | ||
498 | return status; | ||
499 | } | ||
500 | |||
501 | length -= write_length; | ||
502 | start_address += write_length; | ||
503 | buffer += write_length; | ||
504 | |||
505 | /* We should be aligned now -- can write max page size bytes at a time */ | ||
506 | while (length) { | ||
507 | if (length > EPROM_PAGE_SIZE) | ||
508 | write_length = EPROM_PAGE_SIZE; | ||
509 | else | ||
510 | write_length = length; | ||
511 | |||
512 | dbg ("%s - Page Write Addr = %x, length = %d", __FUNCTION__, start_address, write_length); | ||
513 | usb_serial_debug_data(debug, &serial->serial->dev->dev, __FUNCTION__, write_length, buffer); | ||
514 | |||
515 | /* Write next page */ | ||
516 | be_start_address = cpu_to_be16 (start_address); | ||
517 | status = TISendVendorRequestSync (serial->serial->dev, | ||
518 | UMPC_MEMORY_WRITE, // Request | ||
519 | (__u16)address_type, // wValue | ||
520 | (__force __u16)be_start_address, // wIndex | ||
521 | buffer, // TransferBuffer | ||
522 | write_length); // TransferBufferLength | ||
523 | if (status) { | ||
524 | dev_err (&serial->serial->dev->dev, "%s - ERROR %d\n", __FUNCTION__, status); | ||
525 | return status; | ||
526 | } | ||
527 | |||
528 | length -= write_length; | ||
529 | start_address += write_length; | ||
530 | buffer += write_length; | ||
531 | } | ||
532 | return status; | ||
533 | } | ||
534 | |||
535 | /* Examine the UMP DMA registers and LSR | ||
536 | * | ||
537 | * Check the MSBit of the X and Y DMA byte count registers. | ||
538 | * A zero in this bit indicates that the TX DMA buffers are empty | ||
539 | * then check the TX Empty bit in the UART. | ||
540 | */ | ||
541 | static int TIIsTxActive (struct edgeport_port *port) | ||
542 | { | ||
543 | int status; | ||
544 | struct out_endpoint_desc_block *oedb; | ||
545 | __u8 *lsr; | ||
546 | int bytes_left = 0; | ||
547 | |||
548 | oedb = kmalloc (sizeof (* oedb), GFP_KERNEL); | ||
549 | if (!oedb) { | ||
550 | dev_err (&port->port->dev, "%s - out of memory\n", __FUNCTION__); | ||
551 | return -ENOMEM; | ||
552 | } | ||
553 | |||
554 | lsr = kmalloc (1, GFP_KERNEL); /* Sigh, that's right, just one byte, | ||
555 | as not all platforms can do DMA | ||
556 | from stack */ | ||
557 | if (!lsr) { | ||
558 | kfree(oedb); | ||
559 | return -ENOMEM; | ||
560 | } | ||
561 | /* Read the DMA Count Registers */ | ||
562 | status = TIReadRam (port->port->serial->dev, | ||
563 | port->dma_address, | ||
564 | sizeof( *oedb), | ||
565 | (void *)oedb); | ||
566 | |||
567 | if (status) | ||
568 | goto exit_is_tx_active; | ||
569 | |||
570 | dbg ("%s - XByteCount 0x%X", __FUNCTION__, oedb->XByteCount); | ||
571 | |||
572 | /* and the LSR */ | ||
573 | status = TIReadRam (port->port->serial->dev, | ||
574 | port->uart_base + UMPMEM_OFFS_UART_LSR, | ||
575 | 1, | ||
576 | lsr); | ||
577 | |||
578 | if (status) | ||
579 | goto exit_is_tx_active; | ||
580 | dbg ("%s - LSR = 0x%X", __FUNCTION__, *lsr); | ||
581 | |||
582 | /* If either buffer has data or we are transmitting then return TRUE */ | ||
583 | if ((oedb->XByteCount & 0x80 ) != 0 ) | ||
584 | bytes_left += 64; | ||
585 | |||
586 | if ((*lsr & UMP_UART_LSR_TX_MASK ) == 0 ) | ||
587 | bytes_left += 1; | ||
588 | |||
589 | /* We return Not Active if we get any kind of error */ | ||
590 | exit_is_tx_active: | ||
591 | dbg ("%s - return %d", __FUNCTION__, bytes_left ); | ||
592 | |||
593 | kfree(lsr); | ||
594 | kfree(oedb); | ||
595 | return bytes_left; | ||
596 | } | ||
597 | |||
598 | static void TIChasePort(struct edgeport_port *port, unsigned long timeout, int flush) | ||
599 | { | ||
600 | int baud_rate; | ||
601 | struct tty_struct *tty = port->port->tty; | ||
602 | wait_queue_t wait; | ||
603 | unsigned long flags; | ||
604 | |||
605 | if (!timeout) | ||
606 | timeout = (HZ*EDGE_CLOSING_WAIT)/100; | ||
607 | |||
608 | /* wait for data to drain from the buffer */ | ||
609 | spin_lock_irqsave(&port->ep_lock, flags); | ||
610 | init_waitqueue_entry(&wait, current); | ||
611 | add_wait_queue(&tty->write_wait, &wait); | ||
612 | for (;;) { | ||
613 | set_current_state(TASK_INTERRUPTIBLE); | ||
614 | if (edge_buf_data_avail(port->ep_out_buf) == 0 | ||
615 | || timeout == 0 || signal_pending(current) | ||
616 | || !usb_get_intfdata(port->port->serial->interface)) /* disconnect */ | ||
617 | break; | ||
618 | spin_unlock_irqrestore(&port->ep_lock, flags); | ||
619 | timeout = schedule_timeout(timeout); | ||
620 | spin_lock_irqsave(&port->ep_lock, flags); | ||
621 | } | ||
622 | set_current_state(TASK_RUNNING); | ||
623 | remove_wait_queue(&tty->write_wait, &wait); | ||
624 | if (flush) | ||
625 | edge_buf_clear(port->ep_out_buf); | ||
626 | spin_unlock_irqrestore(&port->ep_lock, flags); | ||
627 | |||
628 | /* wait for data to drain from the device */ | ||
629 | timeout += jiffies; | ||
630 | while ((long)(jiffies - timeout) < 0 && !signal_pending(current) | ||
631 | && usb_get_intfdata(port->port->serial->interface)) { /* not disconnected */ | ||
632 | if (!TIIsTxActive(port)) | ||
633 | break; | ||
634 | msleep(10); | ||
635 | } | ||
636 | |||
637 | /* disconnected */ | ||
638 | if (!usb_get_intfdata(port->port->serial->interface)) | ||
639 | return; | ||
640 | |||
641 | /* wait one more character time, based on baud rate */ | ||
642 | /* (TIIsTxActive doesn't seem to wait for the last byte) */ | ||
643 | if ((baud_rate=port->baud_rate) == 0) | ||
644 | baud_rate = 50; | ||
645 | msleep(max(1,(10000+baud_rate-1)/baud_rate)); | ||
646 | } | ||
647 | |||
648 | static int TIChooseConfiguration (struct usb_device *dev) | ||
649 | { | ||
650 | // There may be multiple configurations on this device, in which case | ||
651 | // we would need to read and parse all of them to find out which one | ||
652 | // we want. However, we just support one config at this point, | ||
653 | // configuration # 1, which is Config Descriptor 0. | ||
654 | |||
655 | dbg ("%s - Number of Interfaces = %d", __FUNCTION__, dev->config->desc.bNumInterfaces); | ||
656 | dbg ("%s - MAX Power = %d", __FUNCTION__, dev->config->desc.bMaxPower*2); | ||
657 | |||
658 | if (dev->config->desc.bNumInterfaces != 1) { | ||
659 | dev_err (&dev->dev, "%s - bNumInterfaces is not 1, ERROR!\n", __FUNCTION__); | ||
660 | return -ENODEV; | ||
661 | } | ||
662 | |||
663 | return 0; | ||
664 | } | ||
665 | |||
666 | static int TIReadRom (struct edgeport_serial *serial, int start_address, int length, __u8 *buffer) | ||
667 | { | ||
668 | int status; | ||
669 | |||
670 | if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) { | ||
671 | status = TIReadDownloadMemory (serial->serial->dev, | ||
672 | start_address, | ||
673 | length, | ||
674 | serial->TI_I2C_Type, | ||
675 | buffer); | ||
676 | } else { | ||
677 | status = TIReadBootMemory (serial, | ||
678 | start_address, | ||
679 | length, | ||
680 | buffer); | ||
681 | } | ||
682 | |||
683 | return status; | ||
684 | } | ||
685 | |||
686 | static int TIWriteRom (struct edgeport_serial *serial, int start_address, int length, __u8 *buffer) | ||
687 | { | ||
688 | if (serial->product_info.TiMode == TI_MODE_BOOT) | ||
689 | return TIWriteBootMemory (serial, | ||
690 | start_address, | ||
691 | length, | ||
692 | buffer); | ||
693 | |||
694 | if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) | ||
695 | return TIWriteDownloadI2C (serial, | ||
696 | start_address, | ||
697 | length, | ||
698 | serial->TI_I2C_Type, | ||
699 | buffer); | ||
700 | |||
701 | return -EINVAL; | ||
702 | } | ||
703 | |||
704 | |||
705 | |||
706 | /* Read a descriptor header from I2C based on type */ | ||
707 | static int TIGetDescriptorAddress (struct edgeport_serial *serial, int desc_type, struct ti_i2c_desc *rom_desc) | ||
708 | { | ||
709 | int start_address; | ||
710 | int status; | ||
711 | |||
712 | /* Search for requested descriptor in I2C */ | ||
713 | start_address = 2; | ||
714 | do { | ||
715 | status = TIReadRom (serial, | ||
716 | start_address, | ||
717 | sizeof(struct ti_i2c_desc), | ||
718 | (__u8 *)rom_desc ); | ||
719 | if (status) | ||
720 | return 0; | ||
721 | |||
722 | if (rom_desc->Type == desc_type) | ||
723 | return start_address; | ||
724 | |||
725 | start_address = start_address + sizeof(struct ti_i2c_desc) + rom_desc->Size; | ||
726 | |||
727 | } while ((start_address < TI_MAX_I2C_SIZE) && rom_desc->Type); | ||
728 | |||
729 | return 0; | ||
730 | } | ||
731 | |||
732 | /* Validate descriptor checksum */ | ||
733 | static int ValidChecksum(struct ti_i2c_desc *rom_desc, __u8 *buffer) | ||
734 | { | ||
735 | __u16 i; | ||
736 | __u8 cs = 0; | ||
737 | |||
738 | for (i=0; i < rom_desc->Size; i++) { | ||
739 | cs = (__u8)(cs + buffer[i]); | ||
740 | } | ||
741 | if (cs != rom_desc->CheckSum) { | ||
742 | dbg ("%s - Mismatch %x - %x", __FUNCTION__, rom_desc->CheckSum, cs); | ||
743 | return -EINVAL; | ||
744 | } | ||
745 | return 0; | ||
746 | } | ||
747 | |||
748 | /* Make sure that the I2C image is good */ | ||
749 | static int TiValidateI2cImage (struct edgeport_serial *serial) | ||
750 | { | ||
751 | struct device *dev = &serial->serial->dev->dev; | ||
752 | int status = 0; | ||
753 | struct ti_i2c_desc *rom_desc; | ||
754 | int start_address = 2; | ||
755 | __u8 *buffer; | ||
756 | __u16 ttype; | ||
757 | |||
758 | rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL); | ||
759 | if (!rom_desc) { | ||
760 | dev_err (dev, "%s - out of memory\n", __FUNCTION__); | ||
761 | return -ENOMEM; | ||
762 | } | ||
763 | buffer = kmalloc (TI_MAX_I2C_SIZE, GFP_KERNEL); | ||
764 | if (!buffer) { | ||
765 | dev_err (dev, "%s - out of memory when allocating buffer\n", __FUNCTION__); | ||
766 | kfree (rom_desc); | ||
767 | return -ENOMEM; | ||
768 | } | ||
769 | |||
770 | // Read the first byte (Signature0) must be 0x52 or 0x10 | ||
771 | status = TIReadRom (serial, 0, 1, buffer); | ||
772 | if (status) | ||
773 | goto ExitTiValidateI2cImage; | ||
774 | |||
775 | if (*buffer != UMP5152 && *buffer != UMP3410) { | ||
776 | dev_err (dev, "%s - invalid buffer signature\n", __FUNCTION__); | ||
777 | status = -ENODEV; | ||
778 | goto ExitTiValidateI2cImage; | ||
779 | } | ||
780 | |||
781 | do { | ||
782 | // Validate the I2C | ||
783 | status = TIReadRom (serial, | ||
784 | start_address, | ||
785 | sizeof(struct ti_i2c_desc), | ||
786 | (__u8 *)rom_desc); | ||
787 | if (status) | ||
788 | break; | ||
789 | |||
790 | if ((start_address + sizeof(struct ti_i2c_desc) + rom_desc->Size) > TI_MAX_I2C_SIZE) { | ||
791 | status = -ENODEV; | ||
792 | dbg ("%s - structure too big, erroring out.", __FUNCTION__); | ||
793 | break; | ||
794 | } | ||
795 | |||
796 | dbg ("%s Type = 0x%x", __FUNCTION__, rom_desc->Type); | ||
797 | |||
798 | // Skip type 2 record | ||
799 | ttype = rom_desc->Type & 0x0f; | ||
800 | if ( ttype != I2C_DESC_TYPE_FIRMWARE_BASIC | ||
801 | && ttype != I2C_DESC_TYPE_FIRMWARE_AUTO ) { | ||
802 | // Read the descriptor data | ||
803 | status = TIReadRom(serial, | ||
804 | start_address+sizeof(struct ti_i2c_desc), | ||
805 | rom_desc->Size, | ||
806 | buffer); | ||
807 | if (status) | ||
808 | break; | ||
809 | |||
810 | status = ValidChecksum(rom_desc, buffer); | ||
811 | if (status) | ||
812 | break; | ||
813 | } | ||
814 | start_address = start_address + sizeof(struct ti_i2c_desc) + rom_desc->Size; | ||
815 | |||
816 | } while ((rom_desc->Type != I2C_DESC_TYPE_ION) && (start_address < TI_MAX_I2C_SIZE)); | ||
817 | |||
818 | if ((rom_desc->Type != I2C_DESC_TYPE_ION) || (start_address > TI_MAX_I2C_SIZE)) | ||
819 | status = -ENODEV; | ||
820 | |||
821 | ExitTiValidateI2cImage: | ||
822 | kfree (buffer); | ||
823 | kfree (rom_desc); | ||
824 | return status; | ||
825 | } | ||
826 | |||
827 | static int TIReadManufDescriptor (struct edgeport_serial *serial, __u8 *buffer) | ||
828 | { | ||
829 | int status; | ||
830 | int start_address; | ||
831 | struct ti_i2c_desc *rom_desc; | ||
832 | struct edge_ti_manuf_descriptor *desc; | ||
833 | |||
834 | rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL); | ||
835 | if (!rom_desc) { | ||
836 | dev_err (&serial->serial->dev->dev, "%s - out of memory\n", __FUNCTION__); | ||
837 | return -ENOMEM; | ||
838 | } | ||
839 | start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_ION, rom_desc); | ||
840 | |||
841 | if (!start_address) { | ||
842 | dbg ("%s - Edge Descriptor not found in I2C", __FUNCTION__); | ||
843 | status = -ENODEV; | ||
844 | goto exit; | ||
845 | } | ||
846 | |||
847 | // Read the descriptor data | ||
848 | status = TIReadRom (serial, | ||
849 | start_address+sizeof(struct ti_i2c_desc), | ||
850 | rom_desc->Size, | ||
851 | buffer); | ||
852 | if (status) | ||
853 | goto exit; | ||
854 | |||
855 | status = ValidChecksum(rom_desc, buffer); | ||
856 | |||
857 | desc = (struct edge_ti_manuf_descriptor *)buffer; | ||
858 | dbg ( "%s - IonConfig 0x%x", __FUNCTION__, desc->IonConfig ); | ||
859 | dbg ( "%s - Version %d", __FUNCTION__, desc->Version ); | ||
860 | dbg ( "%s - Cpu/Board 0x%x", __FUNCTION__, desc->CpuRev_BoardRev ); | ||
861 | dbg ( "%s - NumPorts %d", __FUNCTION__, desc->NumPorts ); | ||
862 | dbg ( "%s - NumVirtualPorts %d", __FUNCTION__, desc->NumVirtualPorts ); | ||
863 | dbg ( "%s - TotalPorts %d", __FUNCTION__, desc->TotalPorts ); | ||
864 | |||
865 | exit: | ||
866 | kfree (rom_desc); | ||
867 | return status; | ||
868 | } | ||
869 | |||
870 | /* Build firmware header used for firmware update */ | ||
871 | static int BuildI2CFirmwareHeader (__u8 *header, struct device *dev) | ||
872 | { | ||
873 | __u8 *buffer; | ||
874 | int buffer_size; | ||
875 | int i; | ||
876 | __u8 cs = 0; | ||
877 | struct ti_i2c_desc *i2c_header; | ||
878 | struct ti_i2c_image_header *img_header; | ||
879 | struct ti_i2c_firmware_rec *firmware_rec; | ||
880 | |||
881 | // In order to update the I2C firmware we must change the type 2 record to type 0xF2. | ||
882 | // This will force the UMP to come up in Boot Mode. Then while in boot mode, the driver | ||
883 | // will download the latest firmware (padded to 15.5k) into the UMP ram. | ||
884 | // And finally when the device comes back up in download mode the driver will cause | ||
885 | // the new firmware to be copied from the UMP Ram to I2C and the firmware will update | ||
886 | // the record type from 0xf2 to 0x02. | ||
887 | |||
888 | // Allocate a 15.5k buffer + 2 bytes for version number (Firmware Record) | ||
889 | buffer_size = (((1024 * 16) - 512 )+ sizeof(struct ti_i2c_firmware_rec)); | ||
890 | |||
891 | buffer = kmalloc (buffer_size, GFP_KERNEL); | ||
892 | if (!buffer) { | ||
893 | dev_err (dev, "%s - out of memory\n", __FUNCTION__); | ||
894 | return -ENOMEM; | ||
895 | } | ||
896 | |||
897 | // Set entire image of 0xffs | ||
898 | memset (buffer, 0xff, buffer_size); | ||
899 | |||
900 | // Copy version number into firmware record | ||
901 | firmware_rec = (struct ti_i2c_firmware_rec *)buffer; | ||
902 | |||
903 | firmware_rec->Ver_Major = OperationalCodeImageVersion.MajorVersion; | ||
904 | firmware_rec->Ver_Minor = OperationalCodeImageVersion.MinorVersion; | ||
905 | |||
906 | // Pointer to fw_down memory image | ||
907 | img_header = (struct ti_i2c_image_header *)&PagableOperationalCodeImage[0]; | ||
908 | |||
909 | memcpy (buffer + sizeof(struct ti_i2c_firmware_rec), | ||
910 | &PagableOperationalCodeImage[sizeof(struct ti_i2c_image_header)], | ||
911 | le16_to_cpu(img_header->Length)); | ||
912 | |||
913 | for (i=0; i < buffer_size; i++) { | ||
914 | cs = (__u8)(cs + buffer[i]); | ||
915 | } | ||
916 | |||
917 | kfree (buffer); | ||
918 | |||
919 | // Build new header | ||
920 | i2c_header = (struct ti_i2c_desc *)header; | ||
921 | firmware_rec = (struct ti_i2c_firmware_rec*)i2c_header->Data; | ||
922 | |||
923 | i2c_header->Type = I2C_DESC_TYPE_FIRMWARE_BLANK; | ||
924 | i2c_header->Size = (__u16)buffer_size; | ||
925 | i2c_header->CheckSum = cs; | ||
926 | firmware_rec->Ver_Major = OperationalCodeImageVersion.MajorVersion; | ||
927 | firmware_rec->Ver_Minor = OperationalCodeImageVersion.MinorVersion; | ||
928 | |||
929 | return 0; | ||
930 | } | ||
931 | |||
932 | /* Try to figure out what type of I2c we have */ | ||
933 | static int TIGetI2cTypeInBootMode (struct edgeport_serial *serial) | ||
934 | { | ||
935 | int status; | ||
936 | __u8 data; | ||
937 | |||
938 | // Try to read type 2 | ||
939 | status = TIReadVendorRequestSync (serial->serial->dev, | ||
940 | UMPC_MEMORY_READ, // Request | ||
941 | DTK_ADDR_SPACE_I2C_TYPE_II, // wValue (Address type) | ||
942 | 0, // wIndex | ||
943 | &data, // TransferBuffer | ||
944 | 0x01); // TransferBufferLength | ||
945 | if (status) | ||
946 | dbg ("%s - read 2 status error = %d", __FUNCTION__, status); | ||
947 | else | ||
948 | dbg ("%s - read 2 data = 0x%x", __FUNCTION__, data); | ||
949 | if ((!status) && (data == UMP5152 || data == UMP3410)) { | ||
950 | dbg ("%s - ROM_TYPE_II", __FUNCTION__); | ||
951 | serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II; | ||
952 | return 0; | ||
953 | } | ||
954 | |||
955 | // Try to read type 3 | ||
956 | status = TIReadVendorRequestSync (serial->serial->dev, | ||
957 | UMPC_MEMORY_READ, // Request | ||
958 | DTK_ADDR_SPACE_I2C_TYPE_III, // wValue (Address type) | ||
959 | 0, // wIndex | ||
960 | &data, // TransferBuffer | ||
961 | 0x01); // TransferBufferLength | ||
962 | if (status) | ||
963 | dbg ("%s - read 3 status error = %d", __FUNCTION__, status); | ||
964 | else | ||
965 | dbg ("%s - read 2 data = 0x%x", __FUNCTION__, data); | ||
966 | if ((!status) && (data == UMP5152 || data == UMP3410)) { | ||
967 | dbg ("%s - ROM_TYPE_III", __FUNCTION__); | ||
968 | serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_III; | ||
969 | return 0; | ||
970 | } | ||
971 | |||
972 | dbg ("%s - Unknown", __FUNCTION__); | ||
973 | serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II; | ||
974 | return -ENODEV; | ||
975 | } | ||
976 | |||
977 | static int TISendBulkTransferSync (struct usb_serial *serial, void *buffer, int length, int *num_sent) | ||
978 | { | ||
979 | int status; | ||
980 | |||
981 | status = usb_bulk_msg (serial->dev, | ||
982 | usb_sndbulkpipe(serial->dev, | ||
983 | serial->port[0]->bulk_out_endpointAddress), | ||
984 | buffer, | ||
985 | length, | ||
986 | num_sent, | ||
987 | 1000); | ||
988 | return status; | ||
989 | } | ||
990 | |||
991 | /* Download given firmware image to the device (IN BOOT MODE) */ | ||
992 | static int TIDownloadCodeImage (struct edgeport_serial *serial, __u8 *image, int image_length) | ||
993 | { | ||
994 | int status = 0; | ||
995 | int pos; | ||
996 | int transfer; | ||
997 | int done; | ||
998 | |||
999 | // Transfer firmware image | ||
1000 | for (pos = 0; pos < image_length; ) { | ||
1001 | // Read the next buffer from file | ||
1002 | transfer = image_length - pos; | ||
1003 | if (transfer > EDGE_FW_BULK_MAX_PACKET_SIZE) | ||
1004 | transfer = EDGE_FW_BULK_MAX_PACKET_SIZE; | ||
1005 | |||
1006 | // Transfer data | ||
1007 | status = TISendBulkTransferSync (serial->serial, &image[pos], transfer, &done); | ||
1008 | if (status) | ||
1009 | break; | ||
1010 | // Advance buffer pointer | ||
1011 | pos += done; | ||
1012 | } | ||
1013 | |||
1014 | return status; | ||
1015 | } | ||
1016 | |||
1017 | // FIXME!!! | ||
1018 | static int TIConfigureBootDevice (struct usb_device *dev) | ||
1019 | { | ||
1020 | return 0; | ||
1021 | } | ||
1022 | |||
1023 | /** | ||
1024 | * DownloadTIFirmware - Download run-time operating firmware to the TI5052 | ||
1025 | * | ||
1026 | * This routine downloads the main operating code into the TI5052, using the | ||
1027 | * boot code already burned into E2PROM or ROM. | ||
1028 | */ | ||
1029 | static int TIDownloadFirmware (struct edgeport_serial *serial) | ||
1030 | { | ||
1031 | struct device *dev = &serial->serial->dev->dev; | ||
1032 | int status = 0; | ||
1033 | int start_address; | ||
1034 | struct edge_ti_manuf_descriptor *ti_manuf_desc; | ||
1035 | struct usb_interface_descriptor *interface; | ||
1036 | int download_cur_ver; | ||
1037 | int download_new_ver; | ||
1038 | |||
1039 | /* This routine is entered by both the BOOT mode and the Download mode | ||
1040 | * We can determine which code is running by the reading the config | ||
1041 | * descriptor and if we have only one bulk pipe it is in boot mode | ||
1042 | */ | ||
1043 | serial->product_info.hardware_type = HARDWARE_TYPE_TIUMP; | ||
1044 | |||
1045 | /* Default to type 2 i2c */ | ||
1046 | serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II; | ||
1047 | |||
1048 | status = TIChooseConfiguration (serial->serial->dev); | ||
1049 | if (status) | ||
1050 | return status; | ||
1051 | |||
1052 | interface = &serial->serial->interface->cur_altsetting->desc; | ||
1053 | if (!interface) { | ||
1054 | dev_err (dev, "%s - no interface set, error!\n", __FUNCTION__); | ||
1055 | return -ENODEV; | ||
1056 | } | ||
1057 | |||
1058 | // Setup initial mode -- the default mode 0 is TI_MODE_CONFIGURING | ||
1059 | // if we have more than one endpoint we are definitely in download mode | ||
1060 | if (interface->bNumEndpoints > 1) | ||
1061 | serial->product_info.TiMode = TI_MODE_DOWNLOAD; | ||
1062 | else | ||
1063 | // Otherwise we will remain in configuring mode | ||
1064 | serial->product_info.TiMode = TI_MODE_CONFIGURING; | ||
1065 | |||
1066 | // Save Download Version Number | ||
1067 | OperationalCodeImageVersion.MajorVersion = PagableOperationalCodeImageVersion.MajorVersion; | ||
1068 | OperationalCodeImageVersion.MinorVersion = PagableOperationalCodeImageVersion.MinorVersion; | ||
1069 | OperationalCodeImageVersion.BuildNumber = PagableOperationalCodeImageVersion.BuildNumber; | ||
1070 | |||
1071 | /********************************************************************/ | ||
1072 | /* Download Mode */ | ||
1073 | /********************************************************************/ | ||
1074 | if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) { | ||
1075 | struct ti_i2c_desc *rom_desc; | ||
1076 | |||
1077 | dbg ("%s - <<<<<<<<<<<<<<<RUNNING IN DOWNLOAD MODE>>>>>>>>>>", __FUNCTION__); | ||
1078 | |||
1079 | status = TiValidateI2cImage (serial); | ||
1080 | if (status) { | ||
1081 | dbg ("%s - <<<<<<<<<<<<<<<DOWNLOAD MODE -- BAD I2C >>>>>>>>>>", | ||
1082 | __FUNCTION__); | ||
1083 | return status; | ||
1084 | } | ||
1085 | |||
1086 | /* Validate Hardware version number | ||
1087 | * Read Manufacturing Descriptor from TI Based Edgeport | ||
1088 | */ | ||
1089 | ti_manuf_desc = kmalloc (sizeof (*ti_manuf_desc), GFP_KERNEL); | ||
1090 | if (!ti_manuf_desc) { | ||
1091 | dev_err (dev, "%s - out of memory.\n", __FUNCTION__); | ||
1092 | return -ENOMEM; | ||
1093 | } | ||
1094 | status = TIReadManufDescriptor (serial, (__u8 *)ti_manuf_desc); | ||
1095 | if (status) { | ||
1096 | kfree (ti_manuf_desc); | ||
1097 | return status; | ||
1098 | } | ||
1099 | |||
1100 | // Check version number of ION descriptor | ||
1101 | if (!ignore_cpu_rev && TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev) < 2) { | ||
1102 | dbg ( "%s - Wrong CPU Rev %d (Must be 2)", __FUNCTION__, | ||
1103 | TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev)); | ||
1104 | kfree (ti_manuf_desc); | ||
1105 | return -EINVAL; | ||
1106 | } | ||
1107 | |||
1108 | rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL); | ||
1109 | if (!rom_desc) { | ||
1110 | dev_err (dev, "%s - out of memory.\n", __FUNCTION__); | ||
1111 | kfree (ti_manuf_desc); | ||
1112 | return -ENOMEM; | ||
1113 | } | ||
1114 | |||
1115 | // Search for type 2 record (firmware record) | ||
1116 | if ((start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_FIRMWARE_BASIC, rom_desc)) != 0) { | ||
1117 | struct ti_i2c_firmware_rec *firmware_version; | ||
1118 | __u8 record; | ||
1119 | |||
1120 | dbg ("%s - Found Type FIRMWARE (Type 2) record", __FUNCTION__); | ||
1121 | |||
1122 | firmware_version = kmalloc (sizeof (*firmware_version), GFP_KERNEL); | ||
1123 | if (!firmware_version) { | ||
1124 | dev_err (dev, "%s - out of memory.\n", __FUNCTION__); | ||
1125 | kfree (rom_desc); | ||
1126 | kfree (ti_manuf_desc); | ||
1127 | return -ENOMEM; | ||
1128 | } | ||
1129 | |||
1130 | // Validate version number | ||
1131 | // Read the descriptor data | ||
1132 | status = TIReadRom (serial, | ||
1133 | start_address+sizeof(struct ti_i2c_desc), | ||
1134 | sizeof(struct ti_i2c_firmware_rec), | ||
1135 | (__u8 *)firmware_version); | ||
1136 | if (status) { | ||
1137 | kfree (firmware_version); | ||
1138 | kfree (rom_desc); | ||
1139 | kfree (ti_manuf_desc); | ||
1140 | return status; | ||
1141 | } | ||
1142 | |||
1143 | // Check version number of download with current version in I2c | ||
1144 | download_cur_ver = (firmware_version->Ver_Major << 8) + | ||
1145 | (firmware_version->Ver_Minor); | ||
1146 | download_new_ver = (OperationalCodeImageVersion.MajorVersion << 8) + | ||
1147 | (OperationalCodeImageVersion.MinorVersion); | ||
1148 | |||
1149 | dbg ("%s - >>>Firmware Versions Device %d.%d Driver %d.%d", | ||
1150 | __FUNCTION__, | ||
1151 | firmware_version->Ver_Major, | ||
1152 | firmware_version->Ver_Minor, | ||
1153 | OperationalCodeImageVersion.MajorVersion, | ||
1154 | OperationalCodeImageVersion.MinorVersion); | ||
1155 | |||
1156 | // Check if we have an old version in the I2C and update if necessary | ||
1157 | if (download_cur_ver != download_new_ver) { | ||
1158 | dbg ("%s - Update I2C Download from %d.%d to %d.%d", | ||
1159 | __FUNCTION__, | ||
1160 | firmware_version->Ver_Major, | ||
1161 | firmware_version->Ver_Minor, | ||
1162 | OperationalCodeImageVersion.MajorVersion, | ||
1163 | OperationalCodeImageVersion.MinorVersion); | ||
1164 | |||
1165 | // In order to update the I2C firmware we must change the type 2 record to type 0xF2. | ||
1166 | // This will force the UMP to come up in Boot Mode. Then while in boot mode, the driver | ||
1167 | // will download the latest firmware (padded to 15.5k) into the UMP ram. | ||
1168 | // And finally when the device comes back up in download mode the driver will cause | ||
1169 | // the new firmware to be copied from the UMP Ram to I2C and the firmware will update | ||
1170 | // the record type from 0xf2 to 0x02. | ||
1171 | |||
1172 | record = I2C_DESC_TYPE_FIRMWARE_BLANK; | ||
1173 | |||
1174 | // Change the I2C Firmware record type to 0xf2 to trigger an update | ||
1175 | status = TIWriteRom (serial, | ||
1176 | start_address, | ||
1177 | sizeof(record), | ||
1178 | &record); | ||
1179 | if (status) { | ||
1180 | kfree (firmware_version); | ||
1181 | kfree (rom_desc); | ||
1182 | kfree (ti_manuf_desc); | ||
1183 | return status; | ||
1184 | } | ||
1185 | |||
1186 | // verify the write -- must do this in order for write to | ||
1187 | // complete before we do the hardware reset | ||
1188 | status = TIReadRom (serial, | ||
1189 | start_address, | ||
1190 | sizeof(record), | ||
1191 | &record); | ||
1192 | |||
1193 | if (status) { | ||
1194 | kfree (firmware_version); | ||
1195 | kfree (rom_desc); | ||
1196 | kfree (ti_manuf_desc); | ||
1197 | return status; | ||
1198 | } | ||
1199 | |||
1200 | if (record != I2C_DESC_TYPE_FIRMWARE_BLANK) { | ||
1201 | dev_err (dev, "%s - error resetting device\n", __FUNCTION__); | ||
1202 | kfree (firmware_version); | ||
1203 | kfree (rom_desc); | ||
1204 | kfree (ti_manuf_desc); | ||
1205 | return -ENODEV; | ||
1206 | } | ||
1207 | |||
1208 | dbg ("%s - HARDWARE RESET", __FUNCTION__); | ||
1209 | |||
1210 | // Reset UMP -- Back to BOOT MODE | ||
1211 | status = TISendVendorRequestSync (serial->serial->dev, | ||
1212 | UMPC_HARDWARE_RESET, // Request | ||
1213 | 0, // wValue | ||
1214 | 0, // wIndex | ||
1215 | NULL, // TransferBuffer | ||
1216 | 0); // TransferBufferLength | ||
1217 | |||
1218 | dbg ( "%s - HARDWARE RESET return %d", __FUNCTION__, status); | ||
1219 | |||
1220 | /* return an error on purpose. */ | ||
1221 | kfree (firmware_version); | ||
1222 | kfree (rom_desc); | ||
1223 | kfree (ti_manuf_desc); | ||
1224 | return -ENODEV; | ||
1225 | } | ||
1226 | kfree (firmware_version); | ||
1227 | } | ||
1228 | // Search for type 0xF2 record (firmware blank record) | ||
1229 | else if ((start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_FIRMWARE_BLANK, rom_desc)) != 0) { | ||
1230 | #define HEADER_SIZE (sizeof(struct ti_i2c_desc) + sizeof(struct ti_i2c_firmware_rec)) | ||
1231 | __u8 *header; | ||
1232 | __u8 *vheader; | ||
1233 | |||
1234 | header = kmalloc (HEADER_SIZE, GFP_KERNEL); | ||
1235 | if (!header) { | ||
1236 | dev_err (dev, "%s - out of memory.\n", __FUNCTION__); | ||
1237 | kfree (rom_desc); | ||
1238 | kfree (ti_manuf_desc); | ||
1239 | return -ENOMEM; | ||
1240 | } | ||
1241 | |||
1242 | vheader = kmalloc (HEADER_SIZE, GFP_KERNEL); | ||
1243 | if (!vheader) { | ||
1244 | dev_err (dev, "%s - out of memory.\n", __FUNCTION__); | ||
1245 | kfree (header); | ||
1246 | kfree (rom_desc); | ||
1247 | kfree (ti_manuf_desc); | ||
1248 | return -ENOMEM; | ||
1249 | } | ||
1250 | |||
1251 | dbg ("%s - Found Type BLANK FIRMWARE (Type F2) record", __FUNCTION__); | ||
1252 | |||
1253 | // In order to update the I2C firmware we must change the type 2 record to type 0xF2. | ||
1254 | // This will force the UMP to come up in Boot Mode. Then while in boot mode, the driver | ||
1255 | // will download the latest firmware (padded to 15.5k) into the UMP ram. | ||
1256 | // And finally when the device comes back up in download mode the driver will cause | ||
1257 | // the new firmware to be copied from the UMP Ram to I2C and the firmware will update | ||
1258 | // the record type from 0xf2 to 0x02. | ||
1259 | status = BuildI2CFirmwareHeader(header, dev); | ||
1260 | if (status) { | ||
1261 | kfree (vheader); | ||
1262 | kfree (header); | ||
1263 | kfree (rom_desc); | ||
1264 | kfree (ti_manuf_desc); | ||
1265 | return status; | ||
1266 | } | ||
1267 | |||
1268 | // Update I2C with type 0xf2 record with correct size and checksum | ||
1269 | status = TIWriteRom (serial, | ||
1270 | start_address, | ||
1271 | HEADER_SIZE, | ||
1272 | header); | ||
1273 | if (status) { | ||
1274 | kfree (vheader); | ||
1275 | kfree (header); | ||
1276 | kfree (rom_desc); | ||
1277 | kfree (ti_manuf_desc); | ||
1278 | return status; | ||
1279 | } | ||
1280 | |||
1281 | // verify the write -- must do this in order for write to | ||
1282 | // complete before we do the hardware reset | ||
1283 | status = TIReadRom (serial, | ||
1284 | start_address, | ||
1285 | HEADER_SIZE, | ||
1286 | vheader); | ||
1287 | |||
1288 | if (status) { | ||
1289 | dbg ("%s - can't read header back", __FUNCTION__); | ||
1290 | kfree (vheader); | ||
1291 | kfree (header); | ||
1292 | kfree (rom_desc); | ||
1293 | kfree (ti_manuf_desc); | ||
1294 | return status; | ||
1295 | } | ||
1296 | if (memcmp(vheader, header, HEADER_SIZE)) { | ||
1297 | dbg ("%s - write download record failed", __FUNCTION__); | ||
1298 | kfree (vheader); | ||
1299 | kfree (header); | ||
1300 | kfree (rom_desc); | ||
1301 | kfree (ti_manuf_desc); | ||
1302 | return status; | ||
1303 | } | ||
1304 | |||
1305 | kfree (vheader); | ||
1306 | kfree (header); | ||
1307 | |||
1308 | dbg ("%s - Start firmware update", __FUNCTION__); | ||
1309 | |||
1310 | // Tell firmware to copy download image into I2C | ||
1311 | status = TISendVendorRequestSync (serial->serial->dev, | ||
1312 | UMPC_COPY_DNLD_TO_I2C, // Request | ||
1313 | 0, // wValue | ||
1314 | 0, // wIndex | ||
1315 | NULL, // TransferBuffer | ||
1316 | 0); // TransferBufferLength | ||
1317 | |||
1318 | dbg ("%s - Update complete 0x%x", __FUNCTION__, status); | ||
1319 | if (status) { | ||
1320 | dev_err (dev, "%s - UMPC_COPY_DNLD_TO_I2C failed\n", __FUNCTION__); | ||
1321 | kfree (rom_desc); | ||
1322 | kfree (ti_manuf_desc); | ||
1323 | return status; | ||
1324 | } | ||
1325 | } | ||
1326 | |||
1327 | // The device is running the download code | ||
1328 | kfree (rom_desc); | ||
1329 | kfree (ti_manuf_desc); | ||
1330 | return 0; | ||
1331 | } | ||
1332 | |||
1333 | /********************************************************************/ | ||
1334 | /* Boot Mode */ | ||
1335 | /********************************************************************/ | ||
1336 | dbg ("%s - <<<<<<<<<<<<<<<RUNNING IN BOOT MODE>>>>>>>>>>>>>>>", | ||
1337 | __FUNCTION__); | ||
1338 | |||
1339 | // Configure the TI device so we can use the BULK pipes for download | ||
1340 | status = TIConfigureBootDevice (serial->serial->dev); | ||
1341 | if (status) | ||
1342 | return status; | ||
1343 | |||
1344 | if (le16_to_cpu(serial->serial->dev->descriptor.idVendor) != USB_VENDOR_ID_ION) { | ||
1345 | dbg ("%s - VID = 0x%x", __FUNCTION__, | ||
1346 | le16_to_cpu(serial->serial->dev->descriptor.idVendor)); | ||
1347 | serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II; | ||
1348 | goto StayInBootMode; | ||
1349 | } | ||
1350 | |||
1351 | // We have an ION device (I2c Must be programmed) | ||
1352 | // Determine I2C image type | ||
1353 | if (TIGetI2cTypeInBootMode(serial)) { | ||
1354 | goto StayInBootMode; | ||
1355 | } | ||
1356 | |||
1357 | // Registry variable set? | ||
1358 | if (TIStayInBootMode) { | ||
1359 | dbg ("%s - TIStayInBootMode", __FUNCTION__); | ||
1360 | goto StayInBootMode; | ||
1361 | } | ||
1362 | |||
1363 | // Check for ION Vendor ID and that the I2C is valid | ||
1364 | if (!TiValidateI2cImage(serial)) { | ||
1365 | struct ti_i2c_image_header *header; | ||
1366 | int i; | ||
1367 | __u8 cs = 0; | ||
1368 | __u8 *buffer; | ||
1369 | int buffer_size; | ||
1370 | |||
1371 | /* Validate Hardware version number | ||
1372 | * Read Manufacturing Descriptor from TI Based Edgeport | ||
1373 | */ | ||
1374 | ti_manuf_desc = kmalloc (sizeof (*ti_manuf_desc), GFP_KERNEL); | ||
1375 | if (!ti_manuf_desc) { | ||
1376 | dev_err (dev, "%s - out of memory.\n", __FUNCTION__); | ||
1377 | return -ENOMEM; | ||
1378 | } | ||
1379 | status = TIReadManufDescriptor (serial, (__u8 *)ti_manuf_desc); | ||
1380 | if (status) { | ||
1381 | kfree (ti_manuf_desc); | ||
1382 | goto StayInBootMode; | ||
1383 | } | ||
1384 | |||
1385 | // Check for version 2 | ||
1386 | if (!ignore_cpu_rev && TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev) < 2) { | ||
1387 | dbg ("%s - Wrong CPU Rev %d (Must be 2)", __FUNCTION__, | ||
1388 | TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev)); | ||
1389 | kfree (ti_manuf_desc); | ||
1390 | goto StayInBootMode; | ||
1391 | } | ||
1392 | |||
1393 | kfree (ti_manuf_desc); | ||
1394 | |||
1395 | // In order to update the I2C firmware we must change the type 2 record to type 0xF2. | ||
1396 | // This will force the UMP to come up in Boot Mode. Then while in boot mode, the driver | ||
1397 | // will download the latest firmware (padded to 15.5k) into the UMP ram. | ||
1398 | // And finally when the device comes back up in download mode the driver will cause | ||
1399 | // the new firmware to be copied from the UMP Ram to I2C and the firmware will update | ||
1400 | // the record type from 0xf2 to 0x02. | ||
1401 | |||
1402 | /* | ||
1403 | * Do we really have to copy the whole firmware image, | ||
1404 | * or could we do this in place! | ||
1405 | */ | ||
1406 | |||
1407 | // Allocate a 15.5k buffer + 3 byte header | ||
1408 | buffer_size = (((1024 * 16) - 512) + sizeof(struct ti_i2c_image_header)); | ||
1409 | buffer = kmalloc (buffer_size, GFP_KERNEL); | ||
1410 | if (!buffer) { | ||
1411 | dev_err (dev, "%s - out of memory\n", __FUNCTION__); | ||
1412 | return -ENOMEM; | ||
1413 | } | ||
1414 | |||
1415 | // Initialize the buffer to 0xff (pad the buffer) | ||
1416 | memset (buffer, 0xff, buffer_size); | ||
1417 | |||
1418 | memcpy (buffer, &PagableOperationalCodeImage[0], PagableOperationalCodeSize); | ||
1419 | |||
1420 | for(i = sizeof(struct ti_i2c_image_header); i < buffer_size; i++) { | ||
1421 | cs = (__u8)(cs + buffer[i]); | ||
1422 | } | ||
1423 | |||
1424 | header = (struct ti_i2c_image_header *)buffer; | ||
1425 | |||
1426 | // update length and checksum after padding | ||
1427 | header->Length = cpu_to_le16((__u16)(buffer_size - sizeof(struct ti_i2c_image_header))); | ||
1428 | header->CheckSum = cs; | ||
1429 | |||
1430 | // Download the operational code | ||
1431 | dbg ("%s - Downloading operational code image (TI UMP)", __FUNCTION__); | ||
1432 | status = TIDownloadCodeImage (serial, buffer, buffer_size); | ||
1433 | |||
1434 | kfree (buffer); | ||
1435 | |||
1436 | if (status) { | ||
1437 | dbg ("%s - Error downloading operational code image", __FUNCTION__); | ||
1438 | return status; | ||
1439 | } | ||
1440 | |||
1441 | // Device will reboot | ||
1442 | serial->product_info.TiMode = TI_MODE_TRANSITIONING; | ||
1443 | |||
1444 | dbg ("%s - Download successful -- Device rebooting...", __FUNCTION__); | ||
1445 | |||
1446 | /* return an error on purpose */ | ||
1447 | return -ENODEV; | ||
1448 | } | ||
1449 | |||
1450 | StayInBootMode: | ||
1451 | // Eprom is invalid or blank stay in boot mode | ||
1452 | dbg ("%s - <<<<<<<<<<<<<<<STAYING IN BOOT MODE>>>>>>>>>>>>", __FUNCTION__); | ||
1453 | serial->product_info.TiMode = TI_MODE_BOOT; | ||
1454 | |||
1455 | return 0; | ||
1456 | } | ||
1457 | |||
1458 | |||
1459 | static int TISetDtr (struct edgeport_port *port) | ||
1460 | { | ||
1461 | int port_number = port->port->number - port->port->serial->minor; | ||
1462 | |||
1463 | dbg ("%s", __FUNCTION__); | ||
1464 | port->shadow_mcr |= MCR_DTR; | ||
1465 | |||
1466 | return TIWriteCommandSync (port->port->serial->dev, | ||
1467 | UMPC_SET_CLR_DTR, | ||
1468 | (__u8)(UMPM_UART1_PORT + port_number), | ||
1469 | 1, /* set */ | ||
1470 | NULL, | ||
1471 | 0); | ||
1472 | } | ||
1473 | |||
1474 | static int TIClearDtr (struct edgeport_port *port) | ||
1475 | { | ||
1476 | int port_number = port->port->number - port->port->serial->minor; | ||
1477 | |||
1478 | dbg ("%s", __FUNCTION__); | ||
1479 | port->shadow_mcr &= ~MCR_DTR; | ||
1480 | |||
1481 | return TIWriteCommandSync (port->port->serial->dev, | ||
1482 | UMPC_SET_CLR_DTR, | ||
1483 | (__u8)(UMPM_UART1_PORT + port_number), | ||
1484 | 0, /* clear */ | ||
1485 | NULL, | ||
1486 | 0); | ||
1487 | } | ||
1488 | |||
1489 | static int TISetRts (struct edgeport_port *port) | ||
1490 | { | ||
1491 | int port_number = port->port->number - port->port->serial->minor; | ||
1492 | |||
1493 | dbg ("%s", __FUNCTION__); | ||
1494 | port->shadow_mcr |= MCR_RTS; | ||
1495 | |||
1496 | return TIWriteCommandSync (port->port->serial->dev, | ||
1497 | UMPC_SET_CLR_RTS, | ||
1498 | (__u8)(UMPM_UART1_PORT + port_number), | ||
1499 | 1, /* set */ | ||
1500 | NULL, | ||
1501 | 0); | ||
1502 | } | ||
1503 | |||
1504 | static int TIClearRts (struct edgeport_port *port) | ||
1505 | { | ||
1506 | int port_number = port->port->number - port->port->serial->minor; | ||
1507 | |||
1508 | dbg ("%s", __FUNCTION__); | ||
1509 | port->shadow_mcr &= ~MCR_RTS; | ||
1510 | |||
1511 | return TIWriteCommandSync (port->port->serial->dev, | ||
1512 | UMPC_SET_CLR_RTS, | ||
1513 | (__u8)(UMPM_UART1_PORT + port_number), | ||
1514 | 0, /* clear */ | ||
1515 | NULL, | ||
1516 | 0); | ||
1517 | } | ||
1518 | |||
1519 | static int TISetLoopBack (struct edgeport_port *port) | ||
1520 | { | ||
1521 | int port_number = port->port->number - port->port->serial->minor; | ||
1522 | |||
1523 | dbg ("%s", __FUNCTION__); | ||
1524 | |||
1525 | return TIWriteCommandSync (port->port->serial->dev, | ||
1526 | UMPC_SET_CLR_LOOPBACK, | ||
1527 | (__u8)(UMPM_UART1_PORT + port_number), | ||
1528 | 1, /* set */ | ||
1529 | NULL, | ||
1530 | 0); | ||
1531 | } | ||
1532 | |||
1533 | static int TIClearLoopBack (struct edgeport_port *port) | ||
1534 | { | ||
1535 | int port_number = port->port->number - port->port->serial->minor; | ||
1536 | |||
1537 | dbg ("%s", __FUNCTION__); | ||
1538 | |||
1539 | return TIWriteCommandSync (port->port->serial->dev, | ||
1540 | UMPC_SET_CLR_LOOPBACK, | ||
1541 | (__u8)(UMPM_UART1_PORT + port_number), | ||
1542 | 0, /* clear */ | ||
1543 | NULL, | ||
1544 | 0); | ||
1545 | } | ||
1546 | |||
1547 | static int TISetBreak (struct edgeport_port *port) | ||
1548 | { | ||
1549 | int port_number = port->port->number - port->port->serial->minor; | ||
1550 | |||
1551 | dbg ("%s", __FUNCTION__); | ||
1552 | |||
1553 | return TIWriteCommandSync (port->port->serial->dev, | ||
1554 | UMPC_SET_CLR_BREAK, | ||
1555 | (__u8)(UMPM_UART1_PORT + port_number), | ||
1556 | 1, /* set */ | ||
1557 | NULL, | ||
1558 | 0); | ||
1559 | } | ||
1560 | |||
1561 | static int TIClearBreak (struct edgeport_port *port) | ||
1562 | { | ||
1563 | int port_number = port->port->number - port->port->serial->minor; | ||
1564 | |||
1565 | dbg ("%s", __FUNCTION__); | ||
1566 | |||
1567 | return TIWriteCommandSync (port->port->serial->dev, | ||
1568 | UMPC_SET_CLR_BREAK, | ||
1569 | (__u8)(UMPM_UART1_PORT + port_number), | ||
1570 | 0, /* clear */ | ||
1571 | NULL, | ||
1572 | 0); | ||
1573 | } | ||
1574 | |||
1575 | static int TIRestoreMCR (struct edgeport_port *port, __u8 mcr) | ||
1576 | { | ||
1577 | int status = 0; | ||
1578 | |||
1579 | dbg ("%s - %x", __FUNCTION__, mcr); | ||
1580 | |||
1581 | if (mcr & MCR_DTR) | ||
1582 | status = TISetDtr (port); | ||
1583 | else | ||
1584 | status = TIClearDtr (port); | ||
1585 | |||
1586 | if (status) | ||
1587 | return status; | ||
1588 | |||
1589 | if (mcr & MCR_RTS) | ||
1590 | status = TISetRts (port); | ||
1591 | else | ||
1592 | status = TIClearRts (port); | ||
1593 | |||
1594 | if (status) | ||
1595 | return status; | ||
1596 | |||
1597 | if (mcr & MCR_LOOPBACK) | ||
1598 | status = TISetLoopBack (port); | ||
1599 | else | ||
1600 | status = TIClearLoopBack (port); | ||
1601 | |||
1602 | return status; | ||
1603 | } | ||
1604 | |||
1605 | |||
1606 | |||
1607 | /* Convert TI LSR to standard UART flags */ | ||
1608 | static __u8 MapLineStatus (__u8 ti_lsr) | ||
1609 | { | ||
1610 | __u8 lsr = 0; | ||
1611 | |||
1612 | #define MAP_FLAG(flagUmp, flagUart) \ | ||
1613 | if (ti_lsr & flagUmp) \ | ||
1614 | lsr |= flagUart; | ||
1615 | |||
1616 | MAP_FLAG(UMP_UART_LSR_OV_MASK, LSR_OVER_ERR) /* overrun */ | ||
1617 | MAP_FLAG(UMP_UART_LSR_PE_MASK, LSR_PAR_ERR) /* parity error */ | ||
1618 | MAP_FLAG(UMP_UART_LSR_FE_MASK, LSR_FRM_ERR) /* framing error */ | ||
1619 | MAP_FLAG(UMP_UART_LSR_BR_MASK, LSR_BREAK) /* break detected */ | ||
1620 | MAP_FLAG(UMP_UART_LSR_RX_MASK, LSR_RX_AVAIL) /* receive data available */ | ||
1621 | MAP_FLAG(UMP_UART_LSR_TX_MASK, LSR_TX_EMPTY) /* transmit holding register empty */ | ||
1622 | |||
1623 | #undef MAP_FLAG | ||
1624 | |||
1625 | return lsr; | ||
1626 | } | ||
1627 | |||
1628 | static void handle_new_msr (struct edgeport_port *edge_port, __u8 msr) | ||
1629 | { | ||
1630 | struct async_icount *icount; | ||
1631 | struct tty_struct *tty; | ||
1632 | |||
1633 | dbg ("%s - %02x", __FUNCTION__, msr); | ||
1634 | |||
1635 | if (msr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR | EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) { | ||
1636 | icount = &edge_port->icount; | ||
1637 | |||
1638 | /* update input line counters */ | ||
1639 | if (msr & EDGEPORT_MSR_DELTA_CTS) | ||
1640 | icount->cts++; | ||
1641 | if (msr & EDGEPORT_MSR_DELTA_DSR) | ||
1642 | icount->dsr++; | ||
1643 | if (msr & EDGEPORT_MSR_DELTA_CD) | ||
1644 | icount->dcd++; | ||
1645 | if (msr & EDGEPORT_MSR_DELTA_RI) | ||
1646 | icount->rng++; | ||
1647 | wake_up_interruptible (&edge_port->delta_msr_wait); | ||
1648 | } | ||
1649 | |||
1650 | /* Save the new modem status */ | ||
1651 | edge_port->shadow_msr = msr & 0xf0; | ||
1652 | |||
1653 | tty = edge_port->port->tty; | ||
1654 | /* handle CTS flow control */ | ||
1655 | if (tty && C_CRTSCTS(tty)) { | ||
1656 | if (msr & EDGEPORT_MSR_CTS) { | ||
1657 | tty->hw_stopped = 0; | ||
1658 | tty_wakeup(tty); | ||
1659 | } else { | ||
1660 | tty->hw_stopped = 1; | ||
1661 | } | ||
1662 | } | ||
1663 | |||
1664 | return; | ||
1665 | } | ||
1666 | |||
1667 | static void handle_new_lsr (struct edgeport_port *edge_port, int lsr_data, __u8 lsr, __u8 data) | ||
1668 | { | ||
1669 | struct async_icount *icount; | ||
1670 | __u8 new_lsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK)); | ||
1671 | |||
1672 | dbg ("%s - %02x", __FUNCTION__, new_lsr); | ||
1673 | |||
1674 | edge_port->shadow_lsr = lsr; | ||
1675 | |||
1676 | if (new_lsr & LSR_BREAK) { | ||
1677 | /* | ||
1678 | * Parity and Framing errors only count if they | ||
1679 | * occur exclusive of a break being received. | ||
1680 | */ | ||
1681 | new_lsr &= (__u8)(LSR_OVER_ERR | LSR_BREAK); | ||
1682 | } | ||
1683 | |||
1684 | /* Place LSR data byte into Rx buffer */ | ||
1685 | if (lsr_data && edge_port->port->tty) | ||
1686 | edge_tty_recv(&edge_port->port->dev, edge_port->port->tty, &data, 1); | ||
1687 | |||
1688 | /* update input line counters */ | ||
1689 | icount = &edge_port->icount; | ||
1690 | if (new_lsr & LSR_BREAK) | ||
1691 | icount->brk++; | ||
1692 | if (new_lsr & LSR_OVER_ERR) | ||
1693 | icount->overrun++; | ||
1694 | if (new_lsr & LSR_PAR_ERR) | ||
1695 | icount->parity++; | ||
1696 | if (new_lsr & LSR_FRM_ERR) | ||
1697 | icount->frame++; | ||
1698 | } | ||
1699 | |||
1700 | |||
1701 | static void edge_interrupt_callback (struct urb *urb, struct pt_regs *regs) | ||
1702 | { | ||
1703 | struct edgeport_serial *edge_serial = (struct edgeport_serial *)urb->context; | ||
1704 | struct usb_serial_port *port; | ||
1705 | struct edgeport_port *edge_port; | ||
1706 | unsigned char *data = urb->transfer_buffer; | ||
1707 | int length = urb->actual_length; | ||
1708 | int port_number; | ||
1709 | int function; | ||
1710 | int status; | ||
1711 | __u8 lsr; | ||
1712 | __u8 msr; | ||
1713 | |||
1714 | dbg("%s", __FUNCTION__); | ||
1715 | |||
1716 | switch (urb->status) { | ||
1717 | case 0: | ||
1718 | /* success */ | ||
1719 | break; | ||
1720 | case -ECONNRESET: | ||
1721 | case -ENOENT: | ||
1722 | case -ESHUTDOWN: | ||
1723 | /* this urb is terminated, clean up */ | ||
1724 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
1725 | return; | ||
1726 | default: | ||
1727 | dev_err(&urb->dev->dev, "%s - nonzero urb status received: %d\n", __FUNCTION__, urb->status); | ||
1728 | goto exit; | ||
1729 | } | ||
1730 | |||
1731 | if (!length) { | ||
1732 | dbg ("%s - no data in urb", __FUNCTION__); | ||
1733 | goto exit; | ||
1734 | } | ||
1735 | |||
1736 | usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __FUNCTION__, length, data); | ||
1737 | |||
1738 | if (length != 2) { | ||
1739 | dbg ("%s - expecting packet of size 2, got %d", __FUNCTION__, length); | ||
1740 | goto exit; | ||
1741 | } | ||
1742 | |||
1743 | port_number = TIUMP_GET_PORT_FROM_CODE (data[0]); | ||
1744 | function = TIUMP_GET_FUNC_FROM_CODE (data[0]); | ||
1745 | dbg ("%s - port_number %d, function %d, info 0x%x", | ||
1746 | __FUNCTION__, port_number, function, data[1]); | ||
1747 | port = edge_serial->serial->port[port_number]; | ||
1748 | edge_port = usb_get_serial_port_data(port); | ||
1749 | if (!edge_port) { | ||
1750 | dbg ("%s - edge_port not found", __FUNCTION__); | ||
1751 | return; | ||
1752 | } | ||
1753 | switch (function) { | ||
1754 | case TIUMP_INTERRUPT_CODE_LSR: | ||
1755 | lsr = MapLineStatus(data[1]); | ||
1756 | if (lsr & UMP_UART_LSR_DATA_MASK) { | ||
1757 | /* Save the LSR event for bulk read completion routine */ | ||
1758 | dbg ("%s - LSR Event Port %u LSR Status = %02x", | ||
1759 | __FUNCTION__, port_number, lsr); | ||
1760 | edge_port->lsr_event = 1; | ||
1761 | edge_port->lsr_mask = lsr; | ||
1762 | } else { | ||
1763 | dbg ("%s - ===== Port %d LSR Status = %02x ======", | ||
1764 | __FUNCTION__, port_number, lsr); | ||
1765 | handle_new_lsr (edge_port, 0, lsr, 0); | ||
1766 | } | ||
1767 | break; | ||
1768 | |||
1769 | case TIUMP_INTERRUPT_CODE_MSR: // MSR | ||
1770 | /* Copy MSR from UMP */ | ||
1771 | msr = data[1]; | ||
1772 | dbg ("%s - ===== Port %u MSR Status = %02x ======\n", | ||
1773 | __FUNCTION__, port_number, msr); | ||
1774 | handle_new_msr (edge_port, msr); | ||
1775 | break; | ||
1776 | |||
1777 | default: | ||
1778 | dev_err (&urb->dev->dev, "%s - Unknown Interrupt code from UMP %x\n", | ||
1779 | __FUNCTION__, data[1]); | ||
1780 | break; | ||
1781 | |||
1782 | } | ||
1783 | |||
1784 | exit: | ||
1785 | status = usb_submit_urb (urb, GFP_ATOMIC); | ||
1786 | if (status) | ||
1787 | dev_err (&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n", | ||
1788 | __FUNCTION__, status); | ||
1789 | } | ||
1790 | |||
1791 | static void edge_bulk_in_callback (struct urb *urb, struct pt_regs *regs) | ||
1792 | { | ||
1793 | struct edgeport_port *edge_port = (struct edgeport_port *)urb->context; | ||
1794 | unsigned char *data = urb->transfer_buffer; | ||
1795 | struct tty_struct *tty; | ||
1796 | int status = 0; | ||
1797 | int port_number; | ||
1798 | |||
1799 | dbg("%s", __FUNCTION__); | ||
1800 | |||
1801 | switch (urb->status) { | ||
1802 | case 0: | ||
1803 | /* success */ | ||
1804 | break; | ||
1805 | case -ECONNRESET: | ||
1806 | case -ENOENT: | ||
1807 | case -ESHUTDOWN: | ||
1808 | /* this urb is terminated, clean up */ | ||
1809 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
1810 | return; | ||
1811 | default: | ||
1812 | dev_err (&urb->dev->dev,"%s - nonzero read bulk status received: %d\n", | ||
1813 | __FUNCTION__, urb->status ); | ||
1814 | } | ||
1815 | |||
1816 | if (urb->status == -EPIPE) | ||
1817 | goto exit; | ||
1818 | |||
1819 | if (urb->status) { | ||
1820 | dev_err(&urb->dev->dev,"%s - stopping read!\n", __FUNCTION__); | ||
1821 | return; | ||
1822 | } | ||
1823 | |||
1824 | port_number = edge_port->port->number - edge_port->port->serial->minor; | ||
1825 | |||
1826 | if (edge_port->lsr_event) { | ||
1827 | edge_port->lsr_event = 0; | ||
1828 | dbg ("%s ===== Port %u LSR Status = %02x, Data = %02x ======", | ||
1829 | __FUNCTION__, port_number, edge_port->lsr_mask, *data); | ||
1830 | handle_new_lsr (edge_port, 1, edge_port->lsr_mask, *data); | ||
1831 | /* Adjust buffer length/pointer */ | ||
1832 | --urb->actual_length; | ||
1833 | ++data; | ||
1834 | } | ||
1835 | |||
1836 | tty = edge_port->port->tty; | ||
1837 | if (tty && urb->actual_length) { | ||
1838 | usb_serial_debug_data(debug, &edge_port->port->dev, __FUNCTION__, urb->actual_length, data); | ||
1839 | |||
1840 | if (edge_port->close_pending) { | ||
1841 | dbg ("%s - close is pending, dropping data on the floor.", __FUNCTION__); | ||
1842 | } else { | ||
1843 | edge_tty_recv(&edge_port->port->dev, tty, data, urb->actual_length); | ||
1844 | } | ||
1845 | edge_port->icount.rx += urb->actual_length; | ||
1846 | } | ||
1847 | |||
1848 | exit: | ||
1849 | /* continue read unless stopped */ | ||
1850 | spin_lock(&edge_port->ep_lock); | ||
1851 | if (edge_port->ep_read_urb_state == EDGE_READ_URB_RUNNING) { | ||
1852 | urb->dev = edge_port->port->serial->dev; | ||
1853 | status = usb_submit_urb(urb, GFP_ATOMIC); | ||
1854 | } else if (edge_port->ep_read_urb_state == EDGE_READ_URB_STOPPING) { | ||
1855 | edge_port->ep_read_urb_state = EDGE_READ_URB_STOPPED; | ||
1856 | } | ||
1857 | spin_unlock(&edge_port->ep_lock); | ||
1858 | if (status) | ||
1859 | dev_err (&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n", | ||
1860 | __FUNCTION__, status); | ||
1861 | } | ||
1862 | |||
1863 | static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length) | ||
1864 | { | ||
1865 | int cnt; | ||
1866 | |||
1867 | do { | ||
1868 | if (tty->flip.count >= TTY_FLIPBUF_SIZE) { | ||
1869 | tty_flip_buffer_push(tty); | ||
1870 | if (tty->flip.count >= TTY_FLIPBUF_SIZE) { | ||
1871 | dev_err(dev, "%s - dropping data, %d bytes lost\n", | ||
1872 | __FUNCTION__, length); | ||
1873 | return; | ||
1874 | } | ||
1875 | } | ||
1876 | cnt = min(length, TTY_FLIPBUF_SIZE - tty->flip.count); | ||
1877 | memcpy(tty->flip.char_buf_ptr, data, cnt); | ||
1878 | memset(tty->flip.flag_buf_ptr, 0, cnt); | ||
1879 | tty->flip.char_buf_ptr += cnt; | ||
1880 | tty->flip.flag_buf_ptr += cnt; | ||
1881 | tty->flip.count += cnt; | ||
1882 | data += cnt; | ||
1883 | length -= cnt; | ||
1884 | } while (length > 0); | ||
1885 | |||
1886 | tty_flip_buffer_push(tty); | ||
1887 | } | ||
1888 | |||
1889 | static void edge_bulk_out_callback (struct urb *urb, struct pt_regs *regs) | ||
1890 | { | ||
1891 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | ||
1892 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | ||
1893 | |||
1894 | dbg ("%s - port %d", __FUNCTION__, port->number); | ||
1895 | |||
1896 | edge_port->ep_write_urb_in_use = 0; | ||
1897 | |||
1898 | switch (urb->status) { | ||
1899 | case 0: | ||
1900 | /* success */ | ||
1901 | break; | ||
1902 | case -ECONNRESET: | ||
1903 | case -ENOENT: | ||
1904 | case -ESHUTDOWN: | ||
1905 | /* this urb is terminated, clean up */ | ||
1906 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
1907 | return; | ||
1908 | default: | ||
1909 | dev_err (&urb->dev->dev,"%s - nonzero write bulk status received: %d\n", | ||
1910 | __FUNCTION__, urb->status); | ||
1911 | } | ||
1912 | |||
1913 | /* send any buffered data */ | ||
1914 | edge_send(port); | ||
1915 | } | ||
1916 | |||
1917 | static int edge_open (struct usb_serial_port *port, struct file * filp) | ||
1918 | { | ||
1919 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | ||
1920 | struct edgeport_serial *edge_serial; | ||
1921 | struct usb_device *dev; | ||
1922 | struct urb *urb; | ||
1923 | int port_number; | ||
1924 | int status; | ||
1925 | u16 open_settings; | ||
1926 | u8 transaction_timeout; | ||
1927 | |||
1928 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
1929 | |||
1930 | if (edge_port == NULL) | ||
1931 | return -ENODEV; | ||
1932 | |||
1933 | if (port->tty) | ||
1934 | port->tty->low_latency = low_latency; | ||
1935 | |||
1936 | port_number = port->number - port->serial->minor; | ||
1937 | switch (port_number) { | ||
1938 | case 0: | ||
1939 | edge_port->uart_base = UMPMEM_BASE_UART1; | ||
1940 | edge_port->dma_address = UMPD_OEDB1_ADDRESS; | ||
1941 | break; | ||
1942 | case 1: | ||
1943 | edge_port->uart_base = UMPMEM_BASE_UART2; | ||
1944 | edge_port->dma_address = UMPD_OEDB2_ADDRESS; | ||
1945 | break; | ||
1946 | default: | ||
1947 | dev_err (&port->dev, "Unknown port number!!!\n"); | ||
1948 | return -ENODEV; | ||
1949 | } | ||
1950 | |||
1951 | dbg ("%s - port_number = %d, uart_base = %04x, dma_address = %04x", | ||
1952 | __FUNCTION__, port_number, edge_port->uart_base, edge_port->dma_address); | ||
1953 | |||
1954 | dev = port->serial->dev; | ||
1955 | |||
1956 | memset (&(edge_port->icount), 0x00, sizeof(edge_port->icount)); | ||
1957 | init_waitqueue_head (&edge_port->delta_msr_wait); | ||
1958 | |||
1959 | /* turn off loopback */ | ||
1960 | status = TIClearLoopBack (edge_port); | ||
1961 | if (status) { | ||
1962 | dev_err(&port->dev,"%s - cannot send clear loopback command, %d\n", | ||
1963 | __FUNCTION__, status); | ||
1964 | return status; | ||
1965 | } | ||
1966 | |||
1967 | /* set up the port settings */ | ||
1968 | edge_set_termios (port, NULL); | ||
1969 | |||
1970 | /* open up the port */ | ||
1971 | |||
1972 | /* milliseconds to timeout for DMA transfer */ | ||
1973 | transaction_timeout = 2; | ||
1974 | |||
1975 | edge_port->ump_read_timeout = max (20, ((transaction_timeout * 3) / 2) ); | ||
1976 | |||
1977 | // milliseconds to timeout for DMA transfer | ||
1978 | open_settings = (u8)(UMP_DMA_MODE_CONTINOUS | | ||
1979 | UMP_PIPE_TRANS_TIMEOUT_ENA | | ||
1980 | (transaction_timeout << 2)); | ||
1981 | |||
1982 | dbg ("%s - Sending UMPC_OPEN_PORT", __FUNCTION__); | ||
1983 | |||
1984 | /* Tell TI to open and start the port */ | ||
1985 | status = TIWriteCommandSync (dev, | ||
1986 | UMPC_OPEN_PORT, | ||
1987 | (u8)(UMPM_UART1_PORT + port_number), | ||
1988 | open_settings, | ||
1989 | NULL, | ||
1990 | 0); | ||
1991 | if (status) { | ||
1992 | dev_err(&port->dev,"%s - cannot send open command, %d\n", __FUNCTION__, status); | ||
1993 | return status; | ||
1994 | } | ||
1995 | |||
1996 | /* Start the DMA? */ | ||
1997 | status = TIWriteCommandSync (dev, | ||
1998 | UMPC_START_PORT, | ||
1999 | (u8)(UMPM_UART1_PORT + port_number), | ||
2000 | 0, | ||
2001 | NULL, | ||
2002 | 0); | ||
2003 | if (status) { | ||
2004 | dev_err(&port->dev,"%s - cannot send start DMA command, %d\n", __FUNCTION__, status); | ||
2005 | return status; | ||
2006 | } | ||
2007 | |||
2008 | /* Clear TX and RX buffers in UMP */ | ||
2009 | status = TIPurgeDataSync (port, UMP_PORT_DIR_OUT | UMP_PORT_DIR_IN); | ||
2010 | if (status) { | ||
2011 | dev_err(&port->dev,"%s - cannot send clear buffers command, %d\n", __FUNCTION__, status); | ||
2012 | return status; | ||
2013 | } | ||
2014 | |||
2015 | /* Read Initial MSR */ | ||
2016 | status = TIReadVendorRequestSync (dev, | ||
2017 | UMPC_READ_MSR, // Request | ||
2018 | 0, // wValue | ||
2019 | (__u16)(UMPM_UART1_PORT + port_number), // wIndex (Address) | ||
2020 | &edge_port->shadow_msr, // TransferBuffer | ||
2021 | 1); // TransferBufferLength | ||
2022 | if (status) { | ||
2023 | dev_err(&port->dev,"%s - cannot send read MSR command, %d\n", __FUNCTION__, status); | ||
2024 | return status; | ||
2025 | } | ||
2026 | |||
2027 | dbg ("ShadowMSR 0x%X", edge_port->shadow_msr); | ||
2028 | |||
2029 | /* Set Initial MCR */ | ||
2030 | edge_port->shadow_mcr = MCR_RTS | MCR_DTR; | ||
2031 | dbg ("ShadowMCR 0x%X", edge_port->shadow_mcr); | ||
2032 | |||
2033 | edge_serial = edge_port->edge_serial; | ||
2034 | if (down_interruptible(&edge_serial->es_sem)) | ||
2035 | return -ERESTARTSYS; | ||
2036 | if (edge_serial->num_ports_open == 0) { | ||
2037 | /* we are the first port to be opened, let's post the interrupt urb */ | ||
2038 | urb = edge_serial->serial->port[0]->interrupt_in_urb; | ||
2039 | if (!urb) { | ||
2040 | dev_err (&port->dev, "%s - no interrupt urb present, exiting\n", __FUNCTION__); | ||
2041 | status = -EINVAL; | ||
2042 | goto up_es_sem; | ||
2043 | } | ||
2044 | urb->complete = edge_interrupt_callback; | ||
2045 | urb->context = edge_serial; | ||
2046 | urb->dev = dev; | ||
2047 | status = usb_submit_urb (urb, GFP_KERNEL); | ||
2048 | if (status) { | ||
2049 | dev_err (&port->dev, "%s - usb_submit_urb failed with value %d\n", __FUNCTION__, status); | ||
2050 | goto up_es_sem; | ||
2051 | } | ||
2052 | } | ||
2053 | |||
2054 | /* | ||
2055 | * reset the data toggle on the bulk endpoints to work around bug in | ||
2056 | * host controllers where things get out of sync some times | ||
2057 | */ | ||
2058 | usb_clear_halt (dev, port->write_urb->pipe); | ||
2059 | usb_clear_halt (dev, port->read_urb->pipe); | ||
2060 | |||
2061 | /* start up our bulk read urb */ | ||
2062 | urb = port->read_urb; | ||
2063 | if (!urb) { | ||
2064 | dev_err (&port->dev, "%s - no read urb present, exiting\n", __FUNCTION__); | ||
2065 | status = -EINVAL; | ||
2066 | goto unlink_int_urb; | ||
2067 | } | ||
2068 | edge_port->ep_read_urb_state = EDGE_READ_URB_RUNNING; | ||
2069 | urb->complete = edge_bulk_in_callback; | ||
2070 | urb->context = edge_port; | ||
2071 | urb->dev = dev; | ||
2072 | status = usb_submit_urb (urb, GFP_KERNEL); | ||
2073 | if (status) { | ||
2074 | dev_err (&port->dev, "%s - read bulk usb_submit_urb failed with value %d\n", __FUNCTION__, status); | ||
2075 | goto unlink_int_urb; | ||
2076 | } | ||
2077 | |||
2078 | ++edge_serial->num_ports_open; | ||
2079 | |||
2080 | dbg("%s - exited", __FUNCTION__); | ||
2081 | |||
2082 | goto up_es_sem; | ||
2083 | |||
2084 | unlink_int_urb: | ||
2085 | if (edge_port->edge_serial->num_ports_open == 0) | ||
2086 | usb_kill_urb(port->serial->port[0]->interrupt_in_urb); | ||
2087 | up_es_sem: | ||
2088 | up(&edge_serial->es_sem); | ||
2089 | return status; | ||
2090 | } | ||
2091 | |||
2092 | static void edge_close (struct usb_serial_port *port, struct file *filp) | ||
2093 | { | ||
2094 | struct edgeport_serial *edge_serial; | ||
2095 | struct edgeport_port *edge_port; | ||
2096 | int port_number; | ||
2097 | int status; | ||
2098 | |||
2099 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
2100 | |||
2101 | edge_serial = usb_get_serial_data(port->serial); | ||
2102 | edge_port = usb_get_serial_port_data(port); | ||
2103 | if ((edge_serial == NULL) || (edge_port == NULL)) | ||
2104 | return; | ||
2105 | |||
2106 | /* The bulkreadcompletion routine will check | ||
2107 | * this flag and dump add read data */ | ||
2108 | edge_port->close_pending = 1; | ||
2109 | |||
2110 | /* chase the port close and flush */ | ||
2111 | TIChasePort (edge_port, (HZ*closing_wait)/100, 1); | ||
2112 | |||
2113 | usb_kill_urb(port->read_urb); | ||
2114 | usb_kill_urb(port->write_urb); | ||
2115 | edge_port->ep_write_urb_in_use = 0; | ||
2116 | |||
2117 | /* assuming we can still talk to the device, | ||
2118 | * send a close port command to it */ | ||
2119 | dbg("%s - send umpc_close_port", __FUNCTION__); | ||
2120 | port_number = port->number - port->serial->minor; | ||
2121 | status = TIWriteCommandSync (port->serial->dev, | ||
2122 | UMPC_CLOSE_PORT, | ||
2123 | (__u8)(UMPM_UART1_PORT + port_number), | ||
2124 | 0, | ||
2125 | NULL, | ||
2126 | 0); | ||
2127 | down(&edge_serial->es_sem); | ||
2128 | --edge_port->edge_serial->num_ports_open; | ||
2129 | if (edge_port->edge_serial->num_ports_open <= 0) { | ||
2130 | /* last port is now closed, let's shut down our interrupt urb */ | ||
2131 | usb_kill_urb(port->serial->port[0]->interrupt_in_urb); | ||
2132 | edge_port->edge_serial->num_ports_open = 0; | ||
2133 | } | ||
2134 | up(&edge_serial->es_sem); | ||
2135 | edge_port->close_pending = 0; | ||
2136 | |||
2137 | dbg("%s - exited", __FUNCTION__); | ||
2138 | } | ||
2139 | |||
2140 | static int edge_write (struct usb_serial_port *port, const unsigned char *data, int count) | ||
2141 | { | ||
2142 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | ||
2143 | unsigned long flags; | ||
2144 | |||
2145 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
2146 | |||
2147 | if (count == 0) { | ||
2148 | dbg("%s - write request of 0 bytes", __FUNCTION__); | ||
2149 | return 0; | ||
2150 | } | ||
2151 | |||
2152 | if (edge_port == NULL) | ||
2153 | return -ENODEV; | ||
2154 | if (edge_port->close_pending == 1) | ||
2155 | return -ENODEV; | ||
2156 | |||
2157 | spin_lock_irqsave(&edge_port->ep_lock, flags); | ||
2158 | count = edge_buf_put(edge_port->ep_out_buf, data, count); | ||
2159 | spin_unlock_irqrestore(&edge_port->ep_lock, flags); | ||
2160 | |||
2161 | edge_send(port); | ||
2162 | |||
2163 | return count; | ||
2164 | } | ||
2165 | |||
2166 | static void edge_send(struct usb_serial_port *port) | ||
2167 | { | ||
2168 | int count, result; | ||
2169 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | ||
2170 | struct tty_struct *tty = port->tty; | ||
2171 | unsigned long flags; | ||
2172 | |||
2173 | |||
2174 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
2175 | |||
2176 | spin_lock_irqsave(&edge_port->ep_lock, flags); | ||
2177 | |||
2178 | if (edge_port->ep_write_urb_in_use) { | ||
2179 | spin_unlock_irqrestore(&edge_port->ep_lock, flags); | ||
2180 | return; | ||
2181 | } | ||
2182 | |||
2183 | count = edge_buf_get(edge_port->ep_out_buf, | ||
2184 | port->write_urb->transfer_buffer, | ||
2185 | port->bulk_out_size); | ||
2186 | |||
2187 | if (count == 0) { | ||
2188 | spin_unlock_irqrestore(&edge_port->ep_lock, flags); | ||
2189 | return; | ||
2190 | } | ||
2191 | |||
2192 | edge_port->ep_write_urb_in_use = 1; | ||
2193 | |||
2194 | spin_unlock_irqrestore(&edge_port->ep_lock, flags); | ||
2195 | |||
2196 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, port->write_urb->transfer_buffer); | ||
2197 | |||
2198 | /* set up our urb */ | ||
2199 | usb_fill_bulk_urb (port->write_urb, port->serial->dev, | ||
2200 | usb_sndbulkpipe (port->serial->dev, | ||
2201 | port->bulk_out_endpointAddress), | ||
2202 | port->write_urb->transfer_buffer, count, | ||
2203 | edge_bulk_out_callback, | ||
2204 | port); | ||
2205 | |||
2206 | /* send the data out the bulk port */ | ||
2207 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); | ||
2208 | if (result) { | ||
2209 | dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result); | ||
2210 | edge_port->ep_write_urb_in_use = 0; | ||
2211 | // TODO: reschedule edge_send | ||
2212 | } else { | ||
2213 | edge_port->icount.tx += count; | ||
2214 | } | ||
2215 | |||
2216 | /* wakeup any process waiting for writes to complete */ | ||
2217 | /* there is now more room in the buffer for new writes */ | ||
2218 | if (tty) { | ||
2219 | /* let the tty driver wakeup if it has a special write_wakeup function */ | ||
2220 | tty_wakeup(tty); | ||
2221 | } | ||
2222 | } | ||
2223 | |||
2224 | static int edge_write_room (struct usb_serial_port *port) | ||
2225 | { | ||
2226 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | ||
2227 | int room = 0; | ||
2228 | unsigned long flags; | ||
2229 | |||
2230 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
2231 | |||
2232 | if (edge_port == NULL) | ||
2233 | return -ENODEV; | ||
2234 | if (edge_port->close_pending == 1) | ||
2235 | return -ENODEV; | ||
2236 | |||
2237 | spin_lock_irqsave(&edge_port->ep_lock, flags); | ||
2238 | room = edge_buf_space_avail(edge_port->ep_out_buf); | ||
2239 | spin_unlock_irqrestore(&edge_port->ep_lock, flags); | ||
2240 | |||
2241 | dbg("%s - returns %d", __FUNCTION__, room); | ||
2242 | return room; | ||
2243 | } | ||
2244 | |||
2245 | static int edge_chars_in_buffer (struct usb_serial_port *port) | ||
2246 | { | ||
2247 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | ||
2248 | int chars = 0; | ||
2249 | unsigned long flags; | ||
2250 | |||
2251 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
2252 | |||
2253 | if (edge_port == NULL) | ||
2254 | return -ENODEV; | ||
2255 | if (edge_port->close_pending == 1) | ||
2256 | return -ENODEV; | ||
2257 | |||
2258 | spin_lock_irqsave(&edge_port->ep_lock, flags); | ||
2259 | chars = edge_buf_data_avail(edge_port->ep_out_buf); | ||
2260 | spin_unlock_irqrestore(&edge_port->ep_lock, flags); | ||
2261 | |||
2262 | dbg ("%s - returns %d", __FUNCTION__, chars); | ||
2263 | return chars; | ||
2264 | } | ||
2265 | |||
2266 | static void edge_throttle (struct usb_serial_port *port) | ||
2267 | { | ||
2268 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | ||
2269 | struct tty_struct *tty; | ||
2270 | int status; | ||
2271 | |||
2272 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
2273 | |||
2274 | if (edge_port == NULL) | ||
2275 | return; | ||
2276 | |||
2277 | tty = port->tty; | ||
2278 | if (!tty) { | ||
2279 | dbg ("%s - no tty available", __FUNCTION__); | ||
2280 | return; | ||
2281 | } | ||
2282 | |||
2283 | /* if we are implementing XON/XOFF, send the stop character */ | ||
2284 | if (I_IXOFF(tty)) { | ||
2285 | unsigned char stop_char = STOP_CHAR(tty); | ||
2286 | status = edge_write (port, &stop_char, 1); | ||
2287 | if (status <= 0) { | ||
2288 | dev_err(&port->dev, "%s - failed to write stop character, %d\n", __FUNCTION__, status); | ||
2289 | } | ||
2290 | } | ||
2291 | |||
2292 | /* if we are implementing RTS/CTS, stop reads */ | ||
2293 | /* and the Edgeport will clear the RTS line */ | ||
2294 | if (C_CRTSCTS(tty)) | ||
2295 | stop_read(edge_port); | ||
2296 | |||
2297 | } | ||
2298 | |||
2299 | static void edge_unthrottle (struct usb_serial_port *port) | ||
2300 | { | ||
2301 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | ||
2302 | struct tty_struct *tty; | ||
2303 | int status; | ||
2304 | |||
2305 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
2306 | |||
2307 | if (edge_port == NULL) | ||
2308 | return; | ||
2309 | |||
2310 | tty = port->tty; | ||
2311 | if (!tty) { | ||
2312 | dbg ("%s - no tty available", __FUNCTION__); | ||
2313 | return; | ||
2314 | } | ||
2315 | |||
2316 | /* if we are implementing XON/XOFF, send the start character */ | ||
2317 | if (I_IXOFF(tty)) { | ||
2318 | unsigned char start_char = START_CHAR(tty); | ||
2319 | status = edge_write (port, &start_char, 1); | ||
2320 | if (status <= 0) { | ||
2321 | dev_err(&port->dev, "%s - failed to write start character, %d\n", __FUNCTION__, status); | ||
2322 | } | ||
2323 | } | ||
2324 | |||
2325 | /* if we are implementing RTS/CTS, restart reads */ | ||
2326 | /* are the Edgeport will assert the RTS line */ | ||
2327 | if (C_CRTSCTS(tty)) { | ||
2328 | status = restart_read(edge_port); | ||
2329 | if (status) | ||
2330 | dev_err(&port->dev, "%s - read bulk usb_submit_urb failed with value %d\n", __FUNCTION__, status); | ||
2331 | } | ||
2332 | |||
2333 | } | ||
2334 | |||
2335 | static void stop_read(struct edgeport_port *edge_port) | ||
2336 | { | ||
2337 | unsigned long flags; | ||
2338 | |||
2339 | spin_lock_irqsave(&edge_port->ep_lock, flags); | ||
2340 | |||
2341 | if (edge_port->ep_read_urb_state == EDGE_READ_URB_RUNNING) | ||
2342 | edge_port->ep_read_urb_state = EDGE_READ_URB_STOPPING; | ||
2343 | edge_port->shadow_mcr &= ~MCR_RTS; | ||
2344 | |||
2345 | spin_unlock_irqrestore(&edge_port->ep_lock, flags); | ||
2346 | } | ||
2347 | |||
2348 | static int restart_read(struct edgeport_port *edge_port) | ||
2349 | { | ||
2350 | struct urb *urb; | ||
2351 | int status = 0; | ||
2352 | unsigned long flags; | ||
2353 | |||
2354 | spin_lock_irqsave(&edge_port->ep_lock, flags); | ||
2355 | |||
2356 | if (edge_port->ep_read_urb_state == EDGE_READ_URB_STOPPED) { | ||
2357 | urb = edge_port->port->read_urb; | ||
2358 | urb->complete = edge_bulk_in_callback; | ||
2359 | urb->context = edge_port; | ||
2360 | urb->dev = edge_port->port->serial->dev; | ||
2361 | status = usb_submit_urb(urb, GFP_KERNEL); | ||
2362 | } | ||
2363 | edge_port->ep_read_urb_state = EDGE_READ_URB_RUNNING; | ||
2364 | edge_port->shadow_mcr |= MCR_RTS; | ||
2365 | |||
2366 | spin_unlock_irqrestore(&edge_port->ep_lock, flags); | ||
2367 | |||
2368 | return status; | ||
2369 | } | ||
2370 | |||
2371 | static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios) | ||
2372 | { | ||
2373 | struct ump_uart_config *config; | ||
2374 | struct tty_struct *tty; | ||
2375 | int baud; | ||
2376 | unsigned cflag; | ||
2377 | int status; | ||
2378 | int port_number = edge_port->port->number - edge_port->port->serial->minor; | ||
2379 | |||
2380 | dbg("%s - port %d", __FUNCTION__, edge_port->port->number); | ||
2381 | |||
2382 | tty = edge_port->port->tty; | ||
2383 | if ((!tty) || | ||
2384 | (!tty->termios)) { | ||
2385 | dbg("%s - no tty structures", __FUNCTION__); | ||
2386 | return; | ||
2387 | } | ||
2388 | |||
2389 | config = kmalloc (sizeof (*config), GFP_KERNEL); | ||
2390 | if (!config) { | ||
2391 | dev_err (&edge_port->port->dev, "%s - out of memory\n", __FUNCTION__); | ||
2392 | return; | ||
2393 | } | ||
2394 | |||
2395 | cflag = tty->termios->c_cflag; | ||
2396 | |||
2397 | config->wFlags = 0; | ||
2398 | |||
2399 | /* These flags must be set */ | ||
2400 | config->wFlags |= UMP_MASK_UART_FLAGS_RECEIVE_MS_INT; | ||
2401 | config->wFlags |= UMP_MASK_UART_FLAGS_AUTO_START_ON_ERR; | ||
2402 | config->bUartMode = (__u8)(edge_port->bUartMode); | ||
2403 | |||
2404 | switch (cflag & CSIZE) { | ||
2405 | case CS5: | ||
2406 | config->bDataBits = UMP_UART_CHAR5BITS; | ||
2407 | dbg ("%s - data bits = 5", __FUNCTION__); | ||
2408 | break; | ||
2409 | case CS6: | ||
2410 | config->bDataBits = UMP_UART_CHAR6BITS; | ||
2411 | dbg ("%s - data bits = 6", __FUNCTION__); | ||
2412 | break; | ||
2413 | case CS7: | ||
2414 | config->bDataBits = UMP_UART_CHAR7BITS; | ||
2415 | dbg ("%s - data bits = 7", __FUNCTION__); | ||
2416 | break; | ||
2417 | default: | ||
2418 | case CS8: | ||
2419 | config->bDataBits = UMP_UART_CHAR8BITS; | ||
2420 | dbg ("%s - data bits = 8", __FUNCTION__); | ||
2421 | break; | ||
2422 | } | ||
2423 | |||
2424 | if (cflag & PARENB) { | ||
2425 | if (cflag & PARODD) { | ||
2426 | config->wFlags |= UMP_MASK_UART_FLAGS_PARITY; | ||
2427 | config->bParity = UMP_UART_ODDPARITY; | ||
2428 | dbg("%s - parity = odd", __FUNCTION__); | ||
2429 | } else { | ||
2430 | config->wFlags |= UMP_MASK_UART_FLAGS_PARITY; | ||
2431 | config->bParity = UMP_UART_EVENPARITY; | ||
2432 | dbg("%s - parity = even", __FUNCTION__); | ||
2433 | } | ||
2434 | } else { | ||
2435 | config->bParity = UMP_UART_NOPARITY; | ||
2436 | dbg("%s - parity = none", __FUNCTION__); | ||
2437 | } | ||
2438 | |||
2439 | if (cflag & CSTOPB) { | ||
2440 | config->bStopBits = UMP_UART_STOPBIT2; | ||
2441 | dbg("%s - stop bits = 2", __FUNCTION__); | ||
2442 | } else { | ||
2443 | config->bStopBits = UMP_UART_STOPBIT1; | ||
2444 | dbg("%s - stop bits = 1", __FUNCTION__); | ||
2445 | } | ||
2446 | |||
2447 | /* figure out the flow control settings */ | ||
2448 | if (cflag & CRTSCTS) { | ||
2449 | config->wFlags |= UMP_MASK_UART_FLAGS_OUT_X_CTS_FLOW; | ||
2450 | config->wFlags |= UMP_MASK_UART_FLAGS_RTS_FLOW; | ||
2451 | dbg("%s - RTS/CTS is enabled", __FUNCTION__); | ||
2452 | } else { | ||
2453 | dbg("%s - RTS/CTS is disabled", __FUNCTION__); | ||
2454 | tty->hw_stopped = 0; | ||
2455 | restart_read(edge_port); | ||
2456 | } | ||
2457 | |||
2458 | /* if we are implementing XON/XOFF, set the start and stop character in the device */ | ||
2459 | if (I_IXOFF(tty) || I_IXON(tty)) { | ||
2460 | config->cXon = START_CHAR(tty); | ||
2461 | config->cXoff = STOP_CHAR(tty); | ||
2462 | |||
2463 | /* if we are implementing INBOUND XON/XOFF */ | ||
2464 | if (I_IXOFF(tty)) { | ||
2465 | config->wFlags |= UMP_MASK_UART_FLAGS_IN_X; | ||
2466 | dbg ("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", | ||
2467 | __FUNCTION__, config->cXon, config->cXoff); | ||
2468 | } else { | ||
2469 | dbg ("%s - INBOUND XON/XOFF is disabled", __FUNCTION__); | ||
2470 | } | ||
2471 | |||
2472 | /* if we are implementing OUTBOUND XON/XOFF */ | ||
2473 | if (I_IXON(tty)) { | ||
2474 | config->wFlags |= UMP_MASK_UART_FLAGS_OUT_X; | ||
2475 | dbg ("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", | ||
2476 | __FUNCTION__, config->cXon, config->cXoff); | ||
2477 | } else { | ||
2478 | dbg ("%s - OUTBOUND XON/XOFF is disabled", __FUNCTION__); | ||
2479 | } | ||
2480 | } | ||
2481 | |||
2482 | /* Round the baud rate */ | ||
2483 | baud = tty_get_baud_rate(tty); | ||
2484 | if (!baud) { | ||
2485 | /* pick a default, any default... */ | ||
2486 | baud = 9600; | ||
2487 | } | ||
2488 | edge_port->baud_rate = baud; | ||
2489 | config->wBaudRate = (__u16)((461550L + baud/2) / baud); | ||
2490 | |||
2491 | dbg ("%s - baud rate = %d, wBaudRate = %d", __FUNCTION__, baud, config->wBaudRate); | ||
2492 | |||
2493 | dbg ("wBaudRate: %d", (int)(461550L / config->wBaudRate)); | ||
2494 | dbg ("wFlags: 0x%x", config->wFlags); | ||
2495 | dbg ("bDataBits: %d", config->bDataBits); | ||
2496 | dbg ("bParity: %d", config->bParity); | ||
2497 | dbg ("bStopBits: %d", config->bStopBits); | ||
2498 | dbg ("cXon: %d", config->cXon); | ||
2499 | dbg ("cXoff: %d", config->cXoff); | ||
2500 | dbg ("bUartMode: %d", config->bUartMode); | ||
2501 | |||
2502 | /* move the word values into big endian mode */ | ||
2503 | cpu_to_be16s (&config->wFlags); | ||
2504 | cpu_to_be16s (&config->wBaudRate); | ||
2505 | |||
2506 | status = TIWriteCommandSync (edge_port->port->serial->dev, | ||
2507 | UMPC_SET_CONFIG, | ||
2508 | (__u8)(UMPM_UART1_PORT + port_number), | ||
2509 | 0, | ||
2510 | (__u8 *)config, | ||
2511 | sizeof(*config)); | ||
2512 | if (status) { | ||
2513 | dbg ("%s - error %d when trying to write config to device", | ||
2514 | __FUNCTION__, status); | ||
2515 | } | ||
2516 | |||
2517 | kfree (config); | ||
2518 | |||
2519 | return; | ||
2520 | } | ||
2521 | |||
2522 | static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios) | ||
2523 | { | ||
2524 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | ||
2525 | struct tty_struct *tty = port->tty; | ||
2526 | unsigned int cflag; | ||
2527 | |||
2528 | if (!port->tty || !port->tty->termios) { | ||
2529 | dbg ("%s - no tty or termios", __FUNCTION__); | ||
2530 | return; | ||
2531 | } | ||
2532 | |||
2533 | cflag = tty->termios->c_cflag; | ||
2534 | /* check that they really want us to change something */ | ||
2535 | if (old_termios) { | ||
2536 | if (cflag == old_termios->c_cflag && | ||
2537 | tty->termios->c_iflag == old_termios->c_iflag) { | ||
2538 | dbg ("%s - nothing to change", __FUNCTION__); | ||
2539 | return; | ||
2540 | } | ||
2541 | } | ||
2542 | |||
2543 | dbg("%s - clfag %08x iflag %08x", __FUNCTION__, | ||
2544 | tty->termios->c_cflag, tty->termios->c_iflag); | ||
2545 | if (old_termios) { | ||
2546 | dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__, | ||
2547 | old_termios->c_cflag, old_termios->c_iflag); | ||
2548 | } | ||
2549 | |||
2550 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
2551 | |||
2552 | if (edge_port == NULL) | ||
2553 | return; | ||
2554 | |||
2555 | /* change the port settings to the new ones specified */ | ||
2556 | change_port_settings (edge_port, old_termios); | ||
2557 | |||
2558 | return; | ||
2559 | } | ||
2560 | |||
2561 | static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear) | ||
2562 | { | ||
2563 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | ||
2564 | unsigned int mcr; | ||
2565 | |||
2566 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
2567 | |||
2568 | mcr = edge_port->shadow_mcr; | ||
2569 | if (set & TIOCM_RTS) | ||
2570 | mcr |= MCR_RTS; | ||
2571 | if (set & TIOCM_DTR) | ||
2572 | mcr |= MCR_DTR; | ||
2573 | if (set & TIOCM_LOOP) | ||
2574 | mcr |= MCR_LOOPBACK; | ||
2575 | |||
2576 | if (clear & TIOCM_RTS) | ||
2577 | mcr &= ~MCR_RTS; | ||
2578 | if (clear & TIOCM_DTR) | ||
2579 | mcr &= ~MCR_DTR; | ||
2580 | if (clear & TIOCM_LOOP) | ||
2581 | mcr &= ~MCR_LOOPBACK; | ||
2582 | |||
2583 | edge_port->shadow_mcr = mcr; | ||
2584 | |||
2585 | TIRestoreMCR (edge_port, mcr); | ||
2586 | |||
2587 | return 0; | ||
2588 | } | ||
2589 | |||
2590 | static int edge_tiocmget(struct usb_serial_port *port, struct file *file) | ||
2591 | { | ||
2592 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | ||
2593 | unsigned int result = 0; | ||
2594 | unsigned int msr; | ||
2595 | unsigned int mcr; | ||
2596 | |||
2597 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
2598 | |||
2599 | msr = edge_port->shadow_msr; | ||
2600 | mcr = edge_port->shadow_mcr; | ||
2601 | result = ((mcr & MCR_DTR) ? TIOCM_DTR: 0) /* 0x002 */ | ||
2602 | | ((mcr & MCR_RTS) ? TIOCM_RTS: 0) /* 0x004 */ | ||
2603 | | ((msr & EDGEPORT_MSR_CTS) ? TIOCM_CTS: 0) /* 0x020 */ | ||
2604 | | ((msr & EDGEPORT_MSR_CD) ? TIOCM_CAR: 0) /* 0x040 */ | ||
2605 | | ((msr & EDGEPORT_MSR_RI) ? TIOCM_RI: 0) /* 0x080 */ | ||
2606 | | ((msr & EDGEPORT_MSR_DSR) ? TIOCM_DSR: 0); /* 0x100 */ | ||
2607 | |||
2608 | |||
2609 | dbg("%s -- %x", __FUNCTION__, result); | ||
2610 | |||
2611 | return result; | ||
2612 | } | ||
2613 | |||
2614 | static int get_serial_info (struct edgeport_port *edge_port, struct serial_struct __user *retinfo) | ||
2615 | { | ||
2616 | struct serial_struct tmp; | ||
2617 | |||
2618 | if (!retinfo) | ||
2619 | return -EFAULT; | ||
2620 | |||
2621 | memset(&tmp, 0, sizeof(tmp)); | ||
2622 | |||
2623 | tmp.type = PORT_16550A; | ||
2624 | tmp.line = edge_port->port->serial->minor; | ||
2625 | tmp.port = edge_port->port->number; | ||
2626 | tmp.irq = 0; | ||
2627 | tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; | ||
2628 | tmp.xmit_fifo_size = edge_port->port->bulk_out_size; | ||
2629 | tmp.baud_base = 9600; | ||
2630 | tmp.close_delay = 5*HZ; | ||
2631 | tmp.closing_wait = closing_wait; | ||
2632 | // tmp.custom_divisor = state->custom_divisor; | ||
2633 | // tmp.hub6 = state->hub6; | ||
2634 | // tmp.io_type = state->io_type; | ||
2635 | |||
2636 | |||
2637 | if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) | ||
2638 | return -EFAULT; | ||
2639 | return 0; | ||
2640 | } | ||
2641 | |||
2642 | static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg) | ||
2643 | { | ||
2644 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | ||
2645 | struct async_icount cnow; | ||
2646 | struct async_icount cprev; | ||
2647 | |||
2648 | dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd); | ||
2649 | |||
2650 | switch (cmd) { | ||
2651 | case TIOCINQ: | ||
2652 | dbg("%s - (%d) TIOCINQ", __FUNCTION__, port->number); | ||
2653 | // return get_number_bytes_avail(edge_port, (unsigned int *) arg); | ||
2654 | break; | ||
2655 | |||
2656 | case TIOCSERGETLSR: | ||
2657 | dbg("%s - (%d) TIOCSERGETLSR", __FUNCTION__, port->number); | ||
2658 | // return get_lsr_info(edge_port, (unsigned int *) arg); | ||
2659 | break; | ||
2660 | |||
2661 | case TIOCGSERIAL: | ||
2662 | dbg("%s - (%d) TIOCGSERIAL", __FUNCTION__, port->number); | ||
2663 | return get_serial_info(edge_port, (struct serial_struct __user *) arg); | ||
2664 | break; | ||
2665 | |||
2666 | case TIOCSSERIAL: | ||
2667 | dbg("%s - (%d) TIOCSSERIAL", __FUNCTION__, port->number); | ||
2668 | break; | ||
2669 | |||
2670 | case TIOCMIWAIT: | ||
2671 | dbg("%s - (%d) TIOCMIWAIT", __FUNCTION__, port->number); | ||
2672 | cprev = edge_port->icount; | ||
2673 | while (1) { | ||
2674 | interruptible_sleep_on(&edge_port->delta_msr_wait); | ||
2675 | /* see if a signal did it */ | ||
2676 | if (signal_pending(current)) | ||
2677 | return -ERESTARTSYS; | ||
2678 | cnow = edge_port->icount; | ||
2679 | if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && | ||
2680 | cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) | ||
2681 | return -EIO; /* no change => error */ | ||
2682 | if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || | ||
2683 | ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || | ||
2684 | ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || | ||
2685 | ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { | ||
2686 | return 0; | ||
2687 | } | ||
2688 | cprev = cnow; | ||
2689 | } | ||
2690 | /* not reached */ | ||
2691 | break; | ||
2692 | |||
2693 | case TIOCGICOUNT: | ||
2694 | dbg ("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__, | ||
2695 | port->number, edge_port->icount.rx, edge_port->icount.tx); | ||
2696 | if (copy_to_user((void __user *)arg, &edge_port->icount, sizeof(edge_port->icount))) | ||
2697 | return -EFAULT; | ||
2698 | return 0; | ||
2699 | } | ||
2700 | |||
2701 | return -ENOIOCTLCMD; | ||
2702 | } | ||
2703 | |||
2704 | static void edge_break (struct usb_serial_port *port, int break_state) | ||
2705 | { | ||
2706 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | ||
2707 | int status; | ||
2708 | |||
2709 | dbg ("%s - state = %d", __FUNCTION__, break_state); | ||
2710 | |||
2711 | /* chase the port close */ | ||
2712 | TIChasePort (edge_port, 0, 0); | ||
2713 | |||
2714 | if (break_state == -1) { | ||
2715 | status = TISetBreak (edge_port); | ||
2716 | } else { | ||
2717 | status = TIClearBreak (edge_port); | ||
2718 | } | ||
2719 | if (status) { | ||
2720 | dbg ("%s - error %d sending break set/clear command.", | ||
2721 | __FUNCTION__, status); | ||
2722 | } | ||
2723 | } | ||
2724 | |||
2725 | static int edge_startup (struct usb_serial *serial) | ||
2726 | { | ||
2727 | struct edgeport_serial *edge_serial; | ||
2728 | struct edgeport_port *edge_port; | ||
2729 | struct usb_device *dev; | ||
2730 | int status; | ||
2731 | int i; | ||
2732 | |||
2733 | dev = serial->dev; | ||
2734 | |||
2735 | /* create our private serial structure */ | ||
2736 | edge_serial = kmalloc (sizeof(struct edgeport_serial), GFP_KERNEL); | ||
2737 | if (edge_serial == NULL) { | ||
2738 | dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__); | ||
2739 | return -ENOMEM; | ||
2740 | } | ||
2741 | memset (edge_serial, 0, sizeof(struct edgeport_serial)); | ||
2742 | sema_init(&edge_serial->es_sem, 1); | ||
2743 | edge_serial->serial = serial; | ||
2744 | usb_set_serial_data(serial, edge_serial); | ||
2745 | |||
2746 | status = TIDownloadFirmware (edge_serial); | ||
2747 | if (status) { | ||
2748 | kfree (edge_serial); | ||
2749 | return status; | ||
2750 | } | ||
2751 | |||
2752 | /* set up our port private structures */ | ||
2753 | for (i = 0; i < serial->num_ports; ++i) { | ||
2754 | edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL); | ||
2755 | if (edge_port == NULL) { | ||
2756 | dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__); | ||
2757 | goto cleanup; | ||
2758 | } | ||
2759 | memset (edge_port, 0, sizeof(struct edgeport_port)); | ||
2760 | spin_lock_init(&edge_port->ep_lock); | ||
2761 | edge_port->ep_out_buf = edge_buf_alloc(EDGE_OUT_BUF_SIZE); | ||
2762 | if (edge_port->ep_out_buf == NULL) { | ||
2763 | dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__); | ||
2764 | kfree(edge_port); | ||
2765 | goto cleanup; | ||
2766 | } | ||
2767 | edge_port->port = serial->port[i]; | ||
2768 | edge_port->edge_serial = edge_serial; | ||
2769 | usb_set_serial_port_data(serial->port[i], edge_port); | ||
2770 | edge_port->bUartMode = 0; /* Default is RS232 */ | ||
2771 | } | ||
2772 | |||
2773 | return 0; | ||
2774 | |||
2775 | cleanup: | ||
2776 | for (--i; i>=0; --i) { | ||
2777 | edge_port = usb_get_serial_port_data(serial->port[i]); | ||
2778 | edge_buf_free(edge_port->ep_out_buf); | ||
2779 | kfree(edge_port); | ||
2780 | usb_set_serial_port_data(serial->port[i], NULL); | ||
2781 | } | ||
2782 | kfree (edge_serial); | ||
2783 | usb_set_serial_data(serial, NULL); | ||
2784 | return -ENOMEM; | ||
2785 | } | ||
2786 | |||
2787 | static void edge_shutdown (struct usb_serial *serial) | ||
2788 | { | ||
2789 | int i; | ||
2790 | struct edgeport_port *edge_port; | ||
2791 | |||
2792 | dbg ("%s", __FUNCTION__); | ||
2793 | |||
2794 | for (i=0; i < serial->num_ports; ++i) { | ||
2795 | edge_port = usb_get_serial_port_data(serial->port[i]); | ||
2796 | if (edge_port) { | ||
2797 | edge_buf_free(edge_port->ep_out_buf); | ||
2798 | kfree(edge_port); | ||
2799 | } | ||
2800 | usb_set_serial_port_data(serial->port[i], NULL); | ||
2801 | } | ||
2802 | kfree (usb_get_serial_data(serial)); | ||
2803 | usb_set_serial_data(serial, NULL); | ||
2804 | } | ||
2805 | |||
2806 | |||
2807 | /* Circular Buffer */ | ||
2808 | |||
2809 | /* | ||
2810 | * edge_buf_alloc | ||
2811 | * | ||
2812 | * Allocate a circular buffer and all associated memory. | ||
2813 | */ | ||
2814 | |||
2815 | static struct edge_buf *edge_buf_alloc(unsigned int size) | ||
2816 | { | ||
2817 | struct edge_buf *eb; | ||
2818 | |||
2819 | |||
2820 | if (size == 0) | ||
2821 | return NULL; | ||
2822 | |||
2823 | eb = (struct edge_buf *)kmalloc(sizeof(struct edge_buf), GFP_KERNEL); | ||
2824 | if (eb == NULL) | ||
2825 | return NULL; | ||
2826 | |||
2827 | eb->buf_buf = kmalloc(size, GFP_KERNEL); | ||
2828 | if (eb->buf_buf == NULL) { | ||
2829 | kfree(eb); | ||
2830 | return NULL; | ||
2831 | } | ||
2832 | |||
2833 | eb->buf_size = size; | ||
2834 | eb->buf_get = eb->buf_put = eb->buf_buf; | ||
2835 | |||
2836 | return eb; | ||
2837 | } | ||
2838 | |||
2839 | |||
2840 | /* | ||
2841 | * edge_buf_free | ||
2842 | * | ||
2843 | * Free the buffer and all associated memory. | ||
2844 | */ | ||
2845 | |||
2846 | void edge_buf_free(struct edge_buf *eb) | ||
2847 | { | ||
2848 | if (eb != NULL) { | ||
2849 | if (eb->buf_buf != NULL) | ||
2850 | kfree(eb->buf_buf); | ||
2851 | kfree(eb); | ||
2852 | } | ||
2853 | } | ||
2854 | |||
2855 | |||
2856 | /* | ||
2857 | * edge_buf_clear | ||
2858 | * | ||
2859 | * Clear out all data in the circular buffer. | ||
2860 | */ | ||
2861 | |||
2862 | static void edge_buf_clear(struct edge_buf *eb) | ||
2863 | { | ||
2864 | if (eb != NULL) | ||
2865 | eb->buf_get = eb->buf_put; | ||
2866 | /* equivalent to a get of all data available */ | ||
2867 | } | ||
2868 | |||
2869 | |||
2870 | /* | ||
2871 | * edge_buf_data_avail | ||
2872 | * | ||
2873 | * Return the number of bytes of data available in the circular | ||
2874 | * buffer. | ||
2875 | */ | ||
2876 | |||
2877 | static unsigned int edge_buf_data_avail(struct edge_buf *eb) | ||
2878 | { | ||
2879 | if (eb != NULL) | ||
2880 | return ((eb->buf_size + eb->buf_put - eb->buf_get) % eb->buf_size); | ||
2881 | else | ||
2882 | return 0; | ||
2883 | } | ||
2884 | |||
2885 | |||
2886 | /* | ||
2887 | * edge_buf_space_avail | ||
2888 | * | ||
2889 | * Return the number of bytes of space available in the circular | ||
2890 | * buffer. | ||
2891 | */ | ||
2892 | |||
2893 | static unsigned int edge_buf_space_avail(struct edge_buf *eb) | ||
2894 | { | ||
2895 | if (eb != NULL) | ||
2896 | return ((eb->buf_size + eb->buf_get - eb->buf_put - 1) % eb->buf_size); | ||
2897 | else | ||
2898 | return 0; | ||
2899 | } | ||
2900 | |||
2901 | |||
2902 | /* | ||
2903 | * edge_buf_put | ||
2904 | * | ||
2905 | * Copy data data from a user buffer and put it into the circular buffer. | ||
2906 | * Restrict to the amount of space available. | ||
2907 | * | ||
2908 | * Return the number of bytes copied. | ||
2909 | */ | ||
2910 | |||
2911 | static unsigned int edge_buf_put(struct edge_buf *eb, const char *buf, | ||
2912 | unsigned int count) | ||
2913 | { | ||
2914 | unsigned int len; | ||
2915 | |||
2916 | |||
2917 | if (eb == NULL) | ||
2918 | return 0; | ||
2919 | |||
2920 | len = edge_buf_space_avail(eb); | ||
2921 | if (count > len) | ||
2922 | count = len; | ||
2923 | |||
2924 | if (count == 0) | ||
2925 | return 0; | ||
2926 | |||
2927 | len = eb->buf_buf + eb->buf_size - eb->buf_put; | ||
2928 | if (count > len) { | ||
2929 | memcpy(eb->buf_put, buf, len); | ||
2930 | memcpy(eb->buf_buf, buf+len, count - len); | ||
2931 | eb->buf_put = eb->buf_buf + count - len; | ||
2932 | } else { | ||
2933 | memcpy(eb->buf_put, buf, count); | ||
2934 | if (count < len) | ||
2935 | eb->buf_put += count; | ||
2936 | else /* count == len */ | ||
2937 | eb->buf_put = eb->buf_buf; | ||
2938 | } | ||
2939 | |||
2940 | return count; | ||
2941 | } | ||
2942 | |||
2943 | |||
2944 | /* | ||
2945 | * edge_buf_get | ||
2946 | * | ||
2947 | * Get data from the circular buffer and copy to the given buffer. | ||
2948 | * Restrict to the amount of data available. | ||
2949 | * | ||
2950 | * Return the number of bytes copied. | ||
2951 | */ | ||
2952 | |||
2953 | static unsigned int edge_buf_get(struct edge_buf *eb, char *buf, | ||
2954 | unsigned int count) | ||
2955 | { | ||
2956 | unsigned int len; | ||
2957 | |||
2958 | |||
2959 | if (eb == NULL) | ||
2960 | return 0; | ||
2961 | |||
2962 | len = edge_buf_data_avail(eb); | ||
2963 | if (count > len) | ||
2964 | count = len; | ||
2965 | |||
2966 | if (count == 0) | ||
2967 | return 0; | ||
2968 | |||
2969 | len = eb->buf_buf + eb->buf_size - eb->buf_get; | ||
2970 | if (count > len) { | ||
2971 | memcpy(buf, eb->buf_get, len); | ||
2972 | memcpy(buf+len, eb->buf_buf, count - len); | ||
2973 | eb->buf_get = eb->buf_buf + count - len; | ||
2974 | } else { | ||
2975 | memcpy(buf, eb->buf_get, count); | ||
2976 | if (count < len) | ||
2977 | eb->buf_get += count; | ||
2978 | else /* count == len */ | ||
2979 | eb->buf_get = eb->buf_buf; | ||
2980 | } | ||
2981 | |||
2982 | return count; | ||
2983 | } | ||
2984 | |||
2985 | |||
2986 | static struct usb_serial_device_type edgeport_1port_device = { | ||
2987 | .owner = THIS_MODULE, | ||
2988 | .name = "Edgeport TI 1 port adapter", | ||
2989 | .short_name = "edgeport_ti_1", | ||
2990 | .id_table = edgeport_1port_id_table, | ||
2991 | .num_interrupt_in = 1, | ||
2992 | .num_bulk_in = 1, | ||
2993 | .num_bulk_out = 1, | ||
2994 | .num_ports = 1, | ||
2995 | .open = edge_open, | ||
2996 | .close = edge_close, | ||
2997 | .throttle = edge_throttle, | ||
2998 | .unthrottle = edge_unthrottle, | ||
2999 | .attach = edge_startup, | ||
3000 | .shutdown = edge_shutdown, | ||
3001 | .ioctl = edge_ioctl, | ||
3002 | .set_termios = edge_set_termios, | ||
3003 | .tiocmget = edge_tiocmget, | ||
3004 | .tiocmset = edge_tiocmset, | ||
3005 | .write = edge_write, | ||
3006 | .write_room = edge_write_room, | ||
3007 | .chars_in_buffer = edge_chars_in_buffer, | ||
3008 | .break_ctl = edge_break, | ||
3009 | .read_int_callback = edge_interrupt_callback, | ||
3010 | .read_bulk_callback = edge_bulk_in_callback, | ||
3011 | .write_bulk_callback = edge_bulk_out_callback, | ||
3012 | }; | ||
3013 | |||
3014 | static struct usb_serial_device_type edgeport_2port_device = { | ||
3015 | .owner = THIS_MODULE, | ||
3016 | .name = "Edgeport TI 2 port adapter", | ||
3017 | .short_name = "edgeport_ti_2", | ||
3018 | .id_table = edgeport_2port_id_table, | ||
3019 | .num_interrupt_in = 1, | ||
3020 | .num_bulk_in = 2, | ||
3021 | .num_bulk_out = 2, | ||
3022 | .num_ports = 2, | ||
3023 | .open = edge_open, | ||
3024 | .close = edge_close, | ||
3025 | .throttle = edge_throttle, | ||
3026 | .unthrottle = edge_unthrottle, | ||
3027 | .attach = edge_startup, | ||
3028 | .shutdown = edge_shutdown, | ||
3029 | .ioctl = edge_ioctl, | ||
3030 | .set_termios = edge_set_termios, | ||
3031 | .tiocmget = edge_tiocmget, | ||
3032 | .tiocmset = edge_tiocmset, | ||
3033 | .write = edge_write, | ||
3034 | .write_room = edge_write_room, | ||
3035 | .chars_in_buffer = edge_chars_in_buffer, | ||
3036 | .break_ctl = edge_break, | ||
3037 | .read_int_callback = edge_interrupt_callback, | ||
3038 | .read_bulk_callback = edge_bulk_in_callback, | ||
3039 | .write_bulk_callback = edge_bulk_out_callback, | ||
3040 | }; | ||
3041 | |||
3042 | |||
3043 | static int __init edgeport_init(void) | ||
3044 | { | ||
3045 | int retval; | ||
3046 | retval = usb_serial_register(&edgeport_1port_device); | ||
3047 | if (retval) | ||
3048 | goto failed_1port_device_register; | ||
3049 | retval = usb_serial_register(&edgeport_2port_device); | ||
3050 | if (retval) | ||
3051 | goto failed_2port_device_register; | ||
3052 | retval = usb_register(&io_driver); | ||
3053 | if (retval) | ||
3054 | goto failed_usb_register; | ||
3055 | info(DRIVER_DESC " " DRIVER_VERSION); | ||
3056 | return 0; | ||
3057 | failed_usb_register: | ||
3058 | usb_serial_deregister(&edgeport_2port_device); | ||
3059 | failed_2port_device_register: | ||
3060 | usb_serial_deregister(&edgeport_1port_device); | ||
3061 | failed_1port_device_register: | ||
3062 | return retval; | ||
3063 | } | ||
3064 | |||
3065 | static void __exit edgeport_exit (void) | ||
3066 | { | ||
3067 | usb_deregister (&io_driver); | ||
3068 | usb_serial_deregister (&edgeport_1port_device); | ||
3069 | usb_serial_deregister (&edgeport_2port_device); | ||
3070 | } | ||
3071 | |||
3072 | module_init(edgeport_init); | ||
3073 | module_exit(edgeport_exit); | ||
3074 | |||
3075 | /* Module information */ | ||
3076 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
3077 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
3078 | MODULE_LICENSE("GPL"); | ||
3079 | |||
3080 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
3081 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | ||
3082 | |||
3083 | module_param(low_latency, bool, S_IRUGO | S_IWUSR); | ||
3084 | MODULE_PARM_DESC(low_latency, "Low latency enabled or not"); | ||
3085 | |||
3086 | module_param(closing_wait, int, S_IRUGO | S_IWUSR); | ||
3087 | MODULE_PARM_DESC(closing_wait, "Maximum wait for data to drain, in .01 secs"); | ||
3088 | |||
3089 | module_param(ignore_cpu_rev, bool, S_IRUGO | S_IWUSR); | ||
3090 | MODULE_PARM_DESC(ignore_cpu_rev, "Ignore the cpu revision when connecting to a device"); | ||
3091 | |||