diff options
author | Jesper Nilsson <jesper.nilsson@axis.com> | 2007-11-14 20:01:15 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-11-14 21:45:46 -0500 |
commit | 77accbf505a073beecf32e60265697517e203bea (patch) | |
tree | 5323f47dac9e40841502aa0191573b252747dc0b /drivers/serial | |
parent | 4b7e888933b0d71f9534830ae1edc1e23f0fb075 (diff) |
CRISv10 serial driver rewrite
New and improved serial driver for CRISv10, take three, with improvements
suggested by Jiri Slaby.
- Call wait_event_interruptible with a _correct_ and sensible condition.
- Removed superfluous test of info->flags & ASYNC_CLOSING, since that is done
by wait_event_interruptible.
- Moved common code for deregistering DMA and IRQ to deinit_port function.
- Use setup_timer when initializing flush_timer.
- Convert bit-field for uses_dma_in and uses_dma_out to regular bytes.
- Removed CVS tags.
- Removed defines and comments for CRIS_BUF_SIZE and TTY_THRESHOLD_THROTTLE
(no longer used).
- Cleaned up code to pass checkpatch.
- Add crisv10.h header file.
- Merge of CRISv10 from Axis internal CVS.
Signed-off-by: Jesper Nilsson <jesper.nilsson@axis.com>
Reviewed-by: Jiri Slaby <jirislaby@gmail.com>
Cc: Mikael Starvik <starvik@axis.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/crisv10.c | 1293 | ||||
-rw-r--r-- | drivers/serial/crisv10.h | 146 |
2 files changed, 580 insertions, 859 deletions
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index f523cdf4b02b..a4e23cf47906 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c | |||
@@ -1,426 +1,10 @@ | |||
1 | /* $Id: serial.c,v 1.25 2004/09/29 10:33:49 starvik Exp $ | 1 | /* |
2 | * | ||
3 | * Serial port driver for the ETRAX 100LX chip | 2 | * Serial port driver for the ETRAX 100LX chip |
4 | * | 3 | * |
5 | * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Axis Communications AB | 4 | * Copyright (C) 1998-2007 Axis Communications AB |
6 | * | 5 | * |
7 | * Many, many authors. Based once upon a time on serial.c for 16x50. | 6 | * Many, many authors. Based once upon a time on serial.c for 16x50. |
8 | * | 7 | * |
9 | * $Log: serial.c,v $ | ||
10 | * Revision 1.25 2004/09/29 10:33:49 starvik | ||
11 | * Resolved a dealock when printing debug from kernel. | ||
12 | * | ||
13 | * Revision 1.24 2004/08/27 23:25:59 johana | ||
14 | * rs_set_termios() must call change_speed() if c_iflag has changed or | ||
15 | * automatic XOFF handling will be enabled and transmitter will stop | ||
16 | * if 0x13 is received. | ||
17 | * | ||
18 | * Revision 1.23 2004/08/24 06:57:13 starvik | ||
19 | * More whitespace cleanup | ||
20 | * | ||
21 | * Revision 1.22 2004/08/24 06:12:20 starvik | ||
22 | * Whitespace cleanup | ||
23 | * | ||
24 | * Revision 1.20 2004/05/24 12:00:20 starvik | ||
25 | * Big merge of stuff from Linux 2.4 (e.g. manual mode for the serial port). | ||
26 | * | ||
27 | * Revision 1.19 2004/05/17 13:12:15 starvik | ||
28 | * Kernel console hook | ||
29 | * Big merge from Linux 2.4 still pending. | ||
30 | * | ||
31 | * Revision 1.18 2003/10/28 07:18:30 starvik | ||
32 | * Compiles with debug info | ||
33 | * | ||
34 | * Revision 1.17 2003/07/04 08:27:37 starvik | ||
35 | * Merge of Linux 2.5.74 | ||
36 | * | ||
37 | * Revision 1.16 2003/06/13 10:05:19 johana | ||
38 | * Help the user to avoid trouble by: | ||
39 | * Forcing mixed mode for status/control lines if not all pins are used. | ||
40 | * | ||
41 | * Revision 1.15 2003/06/13 09:43:01 johana | ||
42 | * Merged in the following changes from os/linux/arch/cris/drivers/serial.c | ||
43 | * + some minor changes to reduce diff. | ||
44 | * | ||
45 | * Revision 1.49 2003/05/30 11:31:54 johana | ||
46 | * Merged in change-branch--serial9bit that adds CMSPAR support for sticky | ||
47 | * parity (mark/space) | ||
48 | * | ||
49 | * Revision 1.48 2003/05/30 11:03:57 johana | ||
50 | * Implemented rs_send_xchar() by disabling the DMA and writing manually. | ||
51 | * Added e100_disable_txdma_channel() and e100_enable_txdma_channel(). | ||
52 | * Fixed rs_throttle() and rs_unthrottle() to properly call rs_send_xchar | ||
53 | * instead of setting info->x_char and check the CRTSCTS flag before | ||
54 | * controlling the rts pin. | ||
55 | * | ||
56 | * Revision 1.14 2003/04/09 08:12:44 pkj | ||
57 | * Corrected typo changes made upstream. | ||
58 | * | ||
59 | * Revision 1.13 2003/04/09 05:20:47 starvik | ||
60 | * Merge of Linux 2.5.67 | ||
61 | * | ||
62 | * Revision 1.11 2003/01/22 06:48:37 starvik | ||
63 | * Fixed warnings issued by GCC 3.2.1 | ||
64 | * | ||
65 | * Revision 1.9 2002/12/13 09:07:47 starvik | ||
66 | * Alert user that RX_TIMEOUT_TICKS==0 doesn't work | ||
67 | * | ||
68 | * Revision 1.8 2002/12/11 13:13:57 starvik | ||
69 | * Added arch/ to v10 specific includes | ||
70 | * Added fix from Linux 2.4 in serial.c (flush_to_flip_buffer) | ||
71 | * | ||
72 | * Revision 1.7 2002/12/06 07:13:57 starvik | ||
73 | * Corrected work queue stuff | ||
74 | * Removed CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST | ||
75 | * | ||
76 | * Revision 1.6 2002/11/21 07:17:46 starvik | ||
77 | * Change static inline to extern inline where otherwise outlined with gcc-3.2 | ||
78 | * | ||
79 | * Revision 1.5 2002/11/14 15:59:49 starvik | ||
80 | * Linux 2.5 port of the latest serial driver from 2.4. The work queue stuff | ||
81 | * probably doesn't work yet. | ||
82 | * | ||
83 | * Revision 1.42 2002/11/05 09:08:47 johana | ||
84 | * Better implementation of rs_stop() and rs_start() that uses the XOFF | ||
85 | * register to start/stop transmission. | ||
86 | * change_speed() also initilises XOFF register correctly so that | ||
87 | * auto_xoff is enabled when IXON flag is set by user. | ||
88 | * This gives fast XOFF response times. | ||
89 | * | ||
90 | * Revision 1.41 2002/11/04 18:40:57 johana | ||
91 | * Implemented rs_stop() and rs_start(). | ||
92 | * Simple tests using hwtestserial indicates that this should be enough | ||
93 | * to make it work. | ||
94 | * | ||
95 | * Revision 1.40 2002/10/14 05:33:18 starvik | ||
96 | * RS-485 uses fast timers even if SERIAL_FAST_TIMER is disabled | ||
97 | * | ||
98 | * Revision 1.39 2002/09/30 21:00:57 johana | ||
99 | * Support for CONFIG_ETRAX_SERx_DTR_RI_DSR_CD_MIXED where the status and | ||
100 | * control pins can be mixed between PA and PB. | ||
101 | * If no serial port uses MIXED old solution is used | ||
102 | * (saves a few bytes and cycles). | ||
103 | * control_pins struct uses masks instead of bit numbers. | ||
104 | * Corrected dummy values and polarity in line_info() so | ||
105 | * /proc/tty/driver/serial is now correct. | ||
106 | * (the E100_xxx_GET() macros is really active low - perhaps not obvious) | ||
107 | * | ||
108 | * Revision 1.38 2002/08/23 11:01:36 starvik | ||
109 | * Check that serial port is enabled in all interrupt handlers to avoid | ||
110 | * restarts of DMA channels not assigned to serial ports | ||
111 | * | ||
112 | * Revision 1.37 2002/08/13 13:02:37 bjornw | ||
113 | * Removed some warnings because of unused code | ||
114 | * | ||
115 | * Revision 1.36 2002/08/08 12:50:01 starvik | ||
116 | * Serial interrupt is shared with synchronous serial port driver | ||
117 | * | ||
118 | * Revision 1.35 2002/06/03 10:40:49 starvik | ||
119 | * Increased RS-485 RTS toggle timer to 2 characters | ||
120 | * | ||
121 | * Revision 1.34 2002/05/28 18:59:36 johana | ||
122 | * Whitespace and comment fixing to be more like etrax100ser.c 1.71. | ||
123 | * | ||
124 | * Revision 1.33 2002/05/28 17:55:43 johana | ||
125 | * RS-485 uses FAST_TIMER if enabled, and starts a short (one char time) | ||
126 | * timer from tranismit_chars (interrupt context). | ||
127 | * The timer toggles RTS in interrupt context when expired giving minimum | ||
128 | * latencies. | ||
129 | * | ||
130 | * Revision 1.32 2002/05/22 13:58:00 johana | ||
131 | * Renamed rs_write() to raw_write() and made it inline. | ||
132 | * New rs_write() handles RS-485 if configured and enabled | ||
133 | * (moved code from e100_write_rs485()). | ||
134 | * RS-485 ioctl's uses copy_from_user() instead of verify_area(). | ||
135 | * | ||
136 | * Revision 1.31 2002/04/22 11:20:03 johana | ||
137 | * Updated copyright years. | ||
138 | * | ||
139 | * Revision 1.30 2002/04/22 09:39:12 johana | ||
140 | * RS-485 support compiles. | ||
141 | * | ||
142 | * Revision 1.29 2002/01/14 16:10:01 pkj | ||
143 | * Allocate the receive buffers dynamically. The static 4kB buffer was | ||
144 | * too small for the peaks. This means that we can get rid of the extra | ||
145 | * buffer and the copying to it. It also means we require less memory | ||
146 | * under normal operations, but can use more when needed (there is a | ||
147 | * cap at 64kB for safety reasons). If there is no memory available | ||
148 | * we panic(), and die a horrible death... | ||
149 | * | ||
150 | * Revision 1.28 2001/12/18 15:04:53 johana | ||
151 | * Cleaned up write_rs485() - now it works correctly without padding extra | ||
152 | * char. | ||
153 | * Added sane default initialisation of rs485. | ||
154 | * Added #ifdef around dummy variables. | ||
155 | * | ||
156 | * Revision 1.27 2001/11/29 17:00:41 pkj | ||
157 | * 2kB seems to be too small a buffer when using 921600 bps, | ||
158 | * so increase it to 4kB (this was already done for the elinux | ||
159 | * version of the serial driver). | ||
160 | * | ||
161 | * Revision 1.26 2001/11/19 14:20:41 pkj | ||
162 | * Minor changes to comments and unused code. | ||
163 | * | ||
164 | * Revision 1.25 2001/11/12 20:03:43 pkj | ||
165 | * Fixed compiler warnings. | ||
166 | * | ||
167 | * Revision 1.24 2001/11/12 15:10:05 pkj | ||
168 | * Total redesign of the receiving part of the serial driver. | ||
169 | * Uses eight chained descriptors to write to a 4kB buffer. | ||
170 | * This data is then serialised into a 2kB buffer. From there it | ||
171 | * is copied into the TTY's flip buffers when they become available. | ||
172 | * A lot of copying, and the sizes of the buffers might need to be | ||
173 | * tweaked, but all in all it should work better than the previous | ||
174 | * version, without the need to modify the TTY code in any way. | ||
175 | * Also note that erroneous bytes are now correctly marked in the | ||
176 | * flag buffers (instead of always marking the first byte). | ||
177 | * | ||
178 | * Revision 1.23 2001/10/30 17:53:26 pkj | ||
179 | * * Set info->uses_dma to 0 when a port is closed. | ||
180 | * * Mark the timer1 interrupt as a fast one (SA_INTERRUPT). | ||
181 | * * Call start_flush_timer() in start_receive() if | ||
182 | * CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST is defined. | ||
183 | * | ||
184 | * Revision 1.22 2001/10/30 17:44:03 pkj | ||
185 | * Use %lu for received and transmitted counters in line_info(). | ||
186 | * | ||
187 | * Revision 1.21 2001/10/30 17:40:34 pkj | ||
188 | * Clean-up. The only change to functionality is that | ||
189 | * CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS(=5) is used instead of | ||
190 | * MAX_FLUSH_TIME(=8). | ||
191 | * | ||
192 | * Revision 1.20 2001/10/30 15:24:49 johana | ||
193 | * Added char_time stuff from 2.0 driver. | ||
194 | * | ||
195 | * Revision 1.19 2001/10/30 15:23:03 johana | ||
196 | * Merged with 1.13.2 branch + fixed indentation | ||
197 | * and changed CONFIG_ETRAX100_XYS to CONFIG_ETRAX_XYZ | ||
198 | * | ||
199 | * Revision 1.18 2001/09/24 09:27:22 pkj | ||
200 | * Completed ext_baud_table[] in cflag_to_baud() and cflag_to_etrax_baud(). | ||
201 | * | ||
202 | * Revision 1.17 2001/08/24 11:32:49 ronny | ||
203 | * More fixes for the CONFIG_ETRAX_SERIAL_PORT0 define. | ||
204 | * | ||
205 | * Revision 1.16 2001/08/24 07:56:22 ronny | ||
206 | * Added config ifdefs around ser0 irq requests. | ||
207 | * | ||
208 | * Revision 1.15 2001/08/16 09:10:31 bjarne | ||
209 | * serial.c - corrected the initialization of rs_table, the wrong defines | ||
210 | * where used. | ||
211 | * Corrected a test in timed_flush_handler. | ||
212 | * Changed configured to enabled. | ||
213 | * serial.h - Changed configured to enabled. | ||
214 | * | ||
215 | * Revision 1.14 2001/08/15 07:31:23 bjarne | ||
216 | * Introduced two new members to the e100_serial struct. | ||
217 | * configured - Will be set to 1 if the port has been configured in .config | ||
218 | * uses_dma - Should be set to 1 if the port uses DMA. Currently it is set | ||
219 | * to 1 | ||
220 | * when a port is opened. This is used to limit the DMA interrupt | ||
221 | * routines to only manipulate DMA channels actually used by the | ||
222 | * serial driver. | ||
223 | * | ||
224 | * Revision 1.13.2.2 2001/10/17 13:57:13 starvik | ||
225 | * Receiver was broken by the break fixes | ||
226 | * | ||
227 | * Revision 1.13.2.1 2001/07/20 13:57:39 ronny | ||
228 | * Merge with new stuff from etrax100ser.c. Works but haven't checked stuff | ||
229 | * like break handling. | ||
230 | * | ||
231 | * Revision 1.13 2001/05/09 12:40:31 johana | ||
232 | * Use DMA_NBR and IRQ_NBR defines from dma.h and irq.h | ||
233 | * | ||
234 | * Revision 1.12 2001/04/19 12:23:07 bjornw | ||
235 | * CONFIG_RS485 -> CONFIG_ETRAX_RS485 | ||
236 | * | ||
237 | * Revision 1.11 2001/04/05 14:29:48 markusl | ||
238 | * Updated according to review remarks i.e. | ||
239 | * -Use correct types in port structure to avoid compiler warnings | ||
240 | * -Try to use IO_* macros whenever possible | ||
241 | * -Open should never return -EBUSY | ||
242 | * | ||
243 | * Revision 1.10 2001/03/05 13:14:07 bjornw | ||
244 | * Another spelling fix | ||
245 | * | ||
246 | * Revision 1.9 2001/02/23 13:46:38 bjornw | ||
247 | * Spellling check | ||
248 | * | ||
249 | * Revision 1.8 2001/01/23 14:56:35 markusl | ||
250 | * Made use of ser1 optional | ||
251 | * Needed by USB | ||
252 | * | ||
253 | * Revision 1.7 2001/01/19 16:14:48 perf | ||
254 | * Added kernel options for serial ports 234. | ||
255 | * Changed option names from CONFIG_ETRAX100_XYZ to CONFIG_ETRAX_XYZ. | ||
256 | * | ||
257 | * Revision 1.6 2000/11/22 16:36:09 bjornw | ||
258 | * Please marketing by using the correct case when spelling Etrax. | ||
259 | * | ||
260 | * Revision 1.5 2000/11/21 16:43:37 bjornw | ||
261 | * Fixed so it compiles under CONFIG_SVINTO_SIM | ||
262 | * | ||
263 | * Revision 1.4 2000/11/15 17:34:12 bjornw | ||
264 | * Added a timeout timer for flushing input channels. The interrupt-based | ||
265 | * fast flush system should be easy to merge with this later (works the same | ||
266 | * way, only with an irq instead of a system timer_list) | ||
267 | * | ||
268 | * Revision 1.3 2000/11/13 17:19:57 bjornw | ||
269 | * * Incredibly, this almost complete rewrite of serial.c worked (at least | ||
270 | * for output) the first time. | ||
271 | * | ||
272 | * Items worth noticing: | ||
273 | * | ||
274 | * No Etrax100 port 1 workarounds (does only compile on 2.4 anyway now) | ||
275 | * RS485 is not ported (why can't it be done in userspace as on x86 ?) | ||
276 | * Statistics done through async_icount - if any more stats are needed, | ||
277 | * that's the place to put them or in an arch-dep version of it. | ||
278 | * timeout_interrupt and the other fast timeout stuff not ported yet | ||
279 | * There be dragons in this 3k+ line driver | ||
280 | * | ||
281 | * Revision 1.2 2000/11/10 16:50:28 bjornw | ||
282 | * First shot at a 2.4 port, does not compile totally yet | ||
283 | * | ||
284 | * Revision 1.1 2000/11/10 16:47:32 bjornw | ||
285 | * Added verbatim copy of rev 1.49 etrax100ser.c from elinux | ||
286 | * | ||
287 | * Revision 1.49 2000/10/30 15:47:14 tobiasa | ||
288 | * Changed version number. | ||
289 | * | ||
290 | * Revision 1.48 2000/10/25 11:02:43 johana | ||
291 | * Changed %ul to %lu in printf's | ||
292 | * | ||
293 | * Revision 1.47 2000/10/18 15:06:53 pkj | ||
294 | * Compile correctly with CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST and | ||
295 | * CONFIG_ETRAX_SERIAL_PROC_ENTRY together. | ||
296 | * Some clean-up of the /proc/serial file. | ||
297 | * | ||
298 | * Revision 1.46 2000/10/16 12:59:40 johana | ||
299 | * Added CONFIG_ETRAX_SERIAL_PROC_ENTRY for statistics and debug info. | ||
300 | * | ||
301 | * Revision 1.45 2000/10/13 17:10:59 pkj | ||
302 | * Do not flush DMAs while flipping TTY buffers. | ||
303 | * | ||
304 | * Revision 1.44 2000/10/13 16:34:29 pkj | ||
305 | * Added a delay in ser_interrupt() for 2.3ms when an error is detected. | ||
306 | * We do not know why this delay is required yet, but without it the | ||
307 | * irmaflash program does not work (this was the program that needed | ||
308 | * the ser_interrupt() to be needed in the first place). This should not | ||
309 | * affect normal use of the serial ports. | ||
310 | * | ||
311 | * Revision 1.43 2000/10/13 16:30:44 pkj | ||
312 | * New version of the fast flush of serial buffers code. This time | ||
313 | * it is localized to the serial driver and uses a fast timer to | ||
314 | * do the work. | ||
315 | * | ||
316 | * Revision 1.42 2000/10/13 14:54:26 bennyo | ||
317 | * Fix for switching RTS when using rs485 | ||
318 | * | ||
319 | * Revision 1.41 2000/10/12 11:43:44 pkj | ||
320 | * Cleaned up a number of comments. | ||
321 | * | ||
322 | * Revision 1.40 2000/10/10 11:58:39 johana | ||
323 | * Made RS485 support generic for all ports. | ||
324 | * Toggle rts in interrupt if no delay wanted. | ||
325 | * WARNING: No true transmitter empty check?? | ||
326 | * Set d_wait bit when sending data so interrupt is delayed until | ||
327 | * fifo flushed. (Fix tcdrain() problem) | ||
328 | * | ||
329 | * Revision 1.39 2000/10/04 16:08:02 bjornw | ||
330 | * * Use virt_to_phys etc. for DMA addresses | ||
331 | * * Removed CONFIG_FLUSH_DMA_FAST hacks | ||
332 | * * Indentation fix | ||
333 | * | ||
334 | * Revision 1.38 2000/10/02 12:27:10 mattias | ||
335 | * * added variable used when using fast flush on serial dma. | ||
336 | * (CONFIG_FLUSH_DMA_FAST) | ||
337 | * | ||
338 | * Revision 1.37 2000/09/27 09:44:24 pkj | ||
339 | * Uncomment definition of SERIAL_HANDLE_EARLY_ERRORS. | ||
340 | * | ||
341 | * Revision 1.36 2000/09/20 13:12:52 johana | ||
342 | * Support for CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS: | ||
343 | * Number of timer ticks between flush of receive fifo (1 tick = 10ms). | ||
344 | * Try 0-3 for low latency applications. Approx 5 for high load | ||
345 | * applications (e.g. PPP). Maybe this should be more adaptive some day... | ||
346 | * | ||
347 | * Revision 1.35 2000/09/20 10:36:08 johana | ||
348 | * Typo in get_lsr_info() | ||
349 | * | ||
350 | * Revision 1.34 2000/09/20 10:29:59 johana | ||
351 | * Let rs_chars_in_buffer() check fifo content as well. | ||
352 | * get_lsr_info() might work now (not tested). | ||
353 | * Easier to change the port to debug. | ||
354 | * | ||
355 | * Revision 1.33 2000/09/13 07:52:11 torbjore | ||
356 | * Support RS485 | ||
357 | * | ||
358 | * Revision 1.32 2000/08/31 14:45:37 bjornw | ||
359 | * After sending a break we need to reset the transmit DMA channel | ||
360 | * | ||
361 | * Revision 1.31 2000/06/21 12:13:29 johana | ||
362 | * Fixed wait for all chars sent when closing port. | ||
363 | * (Used to always take 1 second!) | ||
364 | * Added shadows for directions of status/ctrl signals. | ||
365 | * | ||
366 | * Revision 1.30 2000/05/29 16:27:55 bjornw | ||
367 | * Simulator ifdef moved a bit | ||
368 | * | ||
369 | * Revision 1.29 2000/05/09 09:40:30 mattias | ||
370 | * * Added description of dma registers used in timeout_interrupt | ||
371 | * * Removed old code | ||
372 | * | ||
373 | * Revision 1.28 2000/05/08 16:38:58 mattias | ||
374 | * * Bugfix for flushing fifo in timeout_interrupt | ||
375 | * Problem occurs when bluetooth stack waits for a small number of bytes | ||
376 | * containing an event acknowledging free buffers in bluetooth HW | ||
377 | * As before, data was stuck in fifo until more data came on uart and | ||
378 | * flushed it up to the stack. | ||
379 | * | ||
380 | * Revision 1.27 2000/05/02 09:52:28 jonasd | ||
381 | * Added fix for peculiar etrax behaviour when eop is forced on an empty | ||
382 | * fifo. This is used when flashing the IRMA chip. Disabled by default. | ||
383 | * | ||
384 | * Revision 1.26 2000/03/29 15:32:02 bjornw | ||
385 | * 2.0.34 updates | ||
386 | * | ||
387 | * Revision 1.25 2000/02/16 16:59:36 bjornw | ||
388 | * * Receive DMA directly into the flip-buffer, eliminating an intermediary | ||
389 | * receive buffer and a memcpy. Will avoid some overruns. | ||
390 | * * Error message on debug port if an overrun or flip buffer overrun occurs. | ||
391 | * * Just use the first byte in the flag flip buffer for errors. | ||
392 | * * Check for timeout on the serial ports only each 5/100 s, not 1/100. | ||
393 | * | ||
394 | * Revision 1.24 2000/02/09 18:02:28 bjornw | ||
395 | * * Clear serial errors (overrun, framing, parity) correctly. Before, the | ||
396 | * receiver would get stuck if an error occurred and we did not restart | ||
397 | * the input DMA. | ||
398 | * * Cosmetics (indentation, some code made into inlines) | ||
399 | * * Some more debug options | ||
400 | * * Actually shut down the serial port (DMA irq, DMA reset, receiver stop) | ||
401 | * when the last open is closed. Corresponding fixes in startup(). | ||
402 | * * rs_close() "tx FIFO wait" code moved into right place, bug & -> && fixed | ||
403 | * and make a special case out of port 1 (R_DMA_CHx_STATUS is broken for that) | ||
404 | * * e100_disable_rx/enable_rx just disables/enables the receiver, not RTS | ||
405 | * | ||
406 | * Revision 1.23 2000/01/24 17:46:19 johana | ||
407 | * Wait for flush of DMA/FIFO when closing port. | ||
408 | * | ||
409 | * Revision 1.22 2000/01/20 18:10:23 johana | ||
410 | * Added TIOCMGET ioctl to return modem status. | ||
411 | * Implemented modem status/control that works with the extra signals | ||
412 | * (DTR, DSR, RI,CD) as well. | ||
413 | * 3 different modes supported: | ||
414 | * ser0 on PB (Bundy), ser1 on PB (Lisa) and ser2 on PA (Bundy) | ||
415 | * Fixed DEF_TX value that caused the serial transmitter pin (txd) to go to 0 when | ||
416 | * closing the last filehandle, NASTY!. | ||
417 | * Added break generation, not tested though! | ||
418 | * Use IRQF_SHARED when request_irq() for ser2 and ser3 (shared with) par0 and par1. | ||
419 | * You can't use them at the same time (yet..), but you can hopefully switch | ||
420 | * between ser2/par0, ser3/par1 with the same kernel config. | ||
421 | * Replaced some magic constants with defines | ||
422 | * | ||
423 | * | ||
424 | */ | 8 | */ |
425 | 9 | ||
426 | static char *serial_version = "$Revision: 1.25 $"; | 10 | static char *serial_version = "$Revision: 1.25 $"; |
@@ -446,6 +30,7 @@ static char *serial_version = "$Revision: 1.25 $"; | |||
446 | 30 | ||
447 | #include <asm/io.h> | 31 | #include <asm/io.h> |
448 | #include <asm/irq.h> | 32 | #include <asm/irq.h> |
33 | #include <asm/dma.h> | ||
449 | #include <asm/system.h> | 34 | #include <asm/system.h> |
450 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
451 | 36 | ||
@@ -454,8 +39,9 @@ static char *serial_version = "$Revision: 1.25 $"; | |||
454 | /* non-arch dependent serial structures are in linux/serial.h */ | 39 | /* non-arch dependent serial structures are in linux/serial.h */ |
455 | #include <linux/serial.h> | 40 | #include <linux/serial.h> |
456 | /* while we keep our own stuff (struct e100_serial) in a local .h file */ | 41 | /* while we keep our own stuff (struct e100_serial) in a local .h file */ |
457 | #include "serial.h" | 42 | #include "crisv10.h" |
458 | #include <asm/fasttimer.h> | 43 | #include <asm/fasttimer.h> |
44 | #include <asm/arch/io_interface_mux.h> | ||
459 | 45 | ||
460 | #ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER | 46 | #ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER |
461 | #ifndef CONFIG_ETRAX_FAST_TIMER | 47 | #ifndef CONFIG_ETRAX_FAST_TIMER |
@@ -504,18 +90,6 @@ struct tty_driver *serial_driver; | |||
504 | from eLinux */ | 90 | from eLinux */ |
505 | #define SERIAL_HANDLE_EARLY_ERRORS | 91 | #define SERIAL_HANDLE_EARLY_ERRORS |
506 | 92 | ||
507 | /* Defined and used in n_tty.c, but we need it here as well */ | ||
508 | #define TTY_THRESHOLD_THROTTLE 128 | ||
509 | |||
510 | /* Due to buffersizes and threshold values, our SERIAL_DESCR_BUF_SIZE | ||
511 | * must not be to high or flow control won't work if we leave it to the tty | ||
512 | * layer so we have our own throttling in flush_to_flip | ||
513 | * TTY_FLIPBUF_SIZE=512, | ||
514 | * TTY_THRESHOLD_THROTTLE/UNTHROTTLE=128 | ||
515 | * BUF_SIZE can't be > 128 | ||
516 | */ | ||
517 | #define CRIS_BUF_SIZE 512 | ||
518 | |||
519 | /* Currently 16 descriptors x 128 bytes = 2048 bytes */ | 93 | /* Currently 16 descriptors x 128 bytes = 2048 bytes */ |
520 | #define SERIAL_DESCR_BUF_SIZE 256 | 94 | #define SERIAL_DESCR_BUF_SIZE 256 |
521 | 95 | ||
@@ -588,13 +162,13 @@ unsigned long timer_data_to_ns(unsigned long timer_data); | |||
588 | static void change_speed(struct e100_serial *info); | 162 | static void change_speed(struct e100_serial *info); |
589 | static void rs_throttle(struct tty_struct * tty); | 163 | static void rs_throttle(struct tty_struct * tty); |
590 | static void rs_wait_until_sent(struct tty_struct *tty, int timeout); | 164 | static void rs_wait_until_sent(struct tty_struct *tty, int timeout); |
591 | static int rs_write(struct tty_struct * tty, int from_user, | 165 | static int rs_write(struct tty_struct *tty, |
592 | const unsigned char *buf, int count); | 166 | const unsigned char *buf, int count); |
593 | #ifdef CONFIG_ETRAX_RS485 | 167 | #ifdef CONFIG_ETRAX_RS485 |
594 | static int e100_write_rs485(struct tty_struct * tty, int from_user, | 168 | static int e100_write_rs485(struct tty_struct *tty, |
595 | const unsigned char *buf, int count); | 169 | const unsigned char *buf, int count); |
596 | #endif | 170 | #endif |
597 | static int get_lsr_info(struct e100_serial * info, unsigned int *value); | 171 | static int get_lsr_info(struct e100_serial *info, unsigned int *value); |
598 | 172 | ||
599 | 173 | ||
600 | #define DEF_BAUD 115200 /* 115.2 kbit/s */ | 174 | #define DEF_BAUD 115200 /* 115.2 kbit/s */ |
@@ -679,20 +253,39 @@ static struct e100_serial rs_table[] = { | |||
679 | .rx_ctrl = DEF_RX, | 253 | .rx_ctrl = DEF_RX, |
680 | .tx_ctrl = DEF_TX, | 254 | .tx_ctrl = DEF_TX, |
681 | .iseteop = 2, | 255 | .iseteop = 2, |
256 | .dma_owner = dma_ser0, | ||
257 | .io_if = if_serial_0, | ||
682 | #ifdef CONFIG_ETRAX_SERIAL_PORT0 | 258 | #ifdef CONFIG_ETRAX_SERIAL_PORT0 |
683 | .enabled = 1, | 259 | .enabled = 1, |
684 | #ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT | 260 | #ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT |
685 | .dma_out_enabled = 1, | 261 | .dma_out_enabled = 1, |
262 | .dma_out_nbr = SER0_TX_DMA_NBR, | ||
263 | .dma_out_irq_nbr = SER0_DMA_TX_IRQ_NBR, | ||
264 | .dma_out_irq_flags = IRQF_DISABLED, | ||
265 | .dma_out_irq_description = "serial 0 dma tr", | ||
686 | #else | 266 | #else |
687 | .dma_out_enabled = 0, | 267 | .dma_out_enabled = 0, |
268 | .dma_out_nbr = UINT_MAX, | ||
269 | .dma_out_irq_nbr = 0, | ||
270 | .dma_out_irq_flags = 0, | ||
271 | .dma_out_irq_description = NULL, | ||
688 | #endif | 272 | #endif |
689 | #ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN | 273 | #ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN |
690 | .dma_in_enabled = 1, | 274 | .dma_in_enabled = 1, |
275 | .dma_in_nbr = SER0_RX_DMA_NBR, | ||
276 | .dma_in_irq_nbr = SER0_DMA_RX_IRQ_NBR, | ||
277 | .dma_in_irq_flags = IRQF_DISABLED, | ||
278 | .dma_in_irq_description = "serial 0 dma rec", | ||
691 | #else | 279 | #else |
692 | .dma_in_enabled = 0 | 280 | .dma_in_enabled = 0, |
281 | .dma_in_nbr = UINT_MAX, | ||
282 | .dma_in_irq_nbr = 0, | ||
283 | .dma_in_irq_flags = 0, | ||
284 | .dma_in_irq_description = NULL, | ||
693 | #endif | 285 | #endif |
694 | #else | 286 | #else |
695 | .enabled = 0, | 287 | .enabled = 0, |
288 | .io_if_description = NULL, | ||
696 | .dma_out_enabled = 0, | 289 | .dma_out_enabled = 0, |
697 | .dma_in_enabled = 0 | 290 | .dma_in_enabled = 0 |
698 | #endif | 291 | #endif |
@@ -714,20 +307,42 @@ static struct e100_serial rs_table[] = { | |||
714 | .rx_ctrl = DEF_RX, | 307 | .rx_ctrl = DEF_RX, |
715 | .tx_ctrl = DEF_TX, | 308 | .tx_ctrl = DEF_TX, |
716 | .iseteop = 3, | 309 | .iseteop = 3, |
310 | .dma_owner = dma_ser1, | ||
311 | .io_if = if_serial_1, | ||
717 | #ifdef CONFIG_ETRAX_SERIAL_PORT1 | 312 | #ifdef CONFIG_ETRAX_SERIAL_PORT1 |
718 | .enabled = 1, | 313 | .enabled = 1, |
314 | .io_if_description = "ser1", | ||
719 | #ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA8_OUT | 315 | #ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA8_OUT |
720 | .dma_out_enabled = 1, | 316 | .dma_out_enabled = 1, |
317 | .dma_out_nbr = SER1_TX_DMA_NBR, | ||
318 | .dma_out_irq_nbr = SER1_DMA_TX_IRQ_NBR, | ||
319 | .dma_out_irq_flags = IRQF_DISABLED, | ||
320 | .dma_out_irq_description = "serial 1 dma tr", | ||
721 | #else | 321 | #else |
722 | .dma_out_enabled = 0, | 322 | .dma_out_enabled = 0, |
323 | .dma_out_nbr = UINT_MAX, | ||
324 | .dma_out_irq_nbr = 0, | ||
325 | .dma_out_irq_flags = 0, | ||
326 | .dma_out_irq_description = NULL, | ||
723 | #endif | 327 | #endif |
724 | #ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA9_IN | 328 | #ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA9_IN |
725 | .dma_in_enabled = 1, | 329 | .dma_in_enabled = 1, |
330 | .dma_in_nbr = SER1_RX_DMA_NBR, | ||
331 | .dma_in_irq_nbr = SER1_DMA_RX_IRQ_NBR, | ||
332 | .dma_in_irq_flags = IRQF_DISABLED, | ||
333 | .dma_in_irq_description = "serial 1 dma rec", | ||
726 | #else | 334 | #else |
727 | .dma_in_enabled = 0 | 335 | .dma_in_enabled = 0, |
336 | .dma_in_enabled = 0, | ||
337 | .dma_in_nbr = UINT_MAX, | ||
338 | .dma_in_irq_nbr = 0, | ||
339 | .dma_in_irq_flags = 0, | ||
340 | .dma_in_irq_description = NULL, | ||
728 | #endif | 341 | #endif |
729 | #else | 342 | #else |
730 | .enabled = 0, | 343 | .enabled = 0, |
344 | .io_if_description = NULL, | ||
345 | .dma_in_irq_nbr = 0, | ||
731 | .dma_out_enabled = 0, | 346 | .dma_out_enabled = 0, |
732 | .dma_in_enabled = 0 | 347 | .dma_in_enabled = 0 |
733 | #endif | 348 | #endif |
@@ -748,20 +363,40 @@ static struct e100_serial rs_table[] = { | |||
748 | .rx_ctrl = DEF_RX, | 363 | .rx_ctrl = DEF_RX, |
749 | .tx_ctrl = DEF_TX, | 364 | .tx_ctrl = DEF_TX, |
750 | .iseteop = 0, | 365 | .iseteop = 0, |
366 | .dma_owner = dma_ser2, | ||
367 | .io_if = if_serial_2, | ||
751 | #ifdef CONFIG_ETRAX_SERIAL_PORT2 | 368 | #ifdef CONFIG_ETRAX_SERIAL_PORT2 |
752 | .enabled = 1, | 369 | .enabled = 1, |
370 | .io_if_description = "ser2", | ||
753 | #ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT | 371 | #ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT |
754 | .dma_out_enabled = 1, | 372 | .dma_out_enabled = 1, |
373 | .dma_out_nbr = SER2_TX_DMA_NBR, | ||
374 | .dma_out_irq_nbr = SER2_DMA_TX_IRQ_NBR, | ||
375 | .dma_out_irq_flags = IRQF_DISABLED, | ||
376 | .dma_out_irq_description = "serial 2 dma tr", | ||
755 | #else | 377 | #else |
756 | .dma_out_enabled = 0, | 378 | .dma_out_enabled = 0, |
379 | .dma_out_nbr = UINT_MAX, | ||
380 | .dma_out_irq_nbr = 0, | ||
381 | .dma_out_irq_flags = 0, | ||
382 | .dma_out_irq_description = NULL, | ||
757 | #endif | 383 | #endif |
758 | #ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN | 384 | #ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN |
759 | .dma_in_enabled = 1, | 385 | .dma_in_enabled = 1, |
386 | .dma_in_nbr = SER2_RX_DMA_NBR, | ||
387 | .dma_in_irq_nbr = SER2_DMA_RX_IRQ_NBR, | ||
388 | .dma_in_irq_flags = IRQF_DISABLED, | ||
389 | .dma_in_irq_description = "serial 2 dma rec", | ||
760 | #else | 390 | #else |
761 | .dma_in_enabled = 0 | 391 | .dma_in_enabled = 0, |
392 | .dma_in_nbr = UINT_MAX, | ||
393 | .dma_in_irq_nbr = 0, | ||
394 | .dma_in_irq_flags = 0, | ||
395 | .dma_in_irq_description = NULL, | ||
762 | #endif | 396 | #endif |
763 | #else | 397 | #else |
764 | .enabled = 0, | 398 | .enabled = 0, |
399 | .io_if_description = NULL, | ||
765 | .dma_out_enabled = 0, | 400 | .dma_out_enabled = 0, |
766 | .dma_in_enabled = 0 | 401 | .dma_in_enabled = 0 |
767 | #endif | 402 | #endif |
@@ -782,20 +417,40 @@ static struct e100_serial rs_table[] = { | |||
782 | .rx_ctrl = DEF_RX, | 417 | .rx_ctrl = DEF_RX, |
783 | .tx_ctrl = DEF_TX, | 418 | .tx_ctrl = DEF_TX, |
784 | .iseteop = 1, | 419 | .iseteop = 1, |
420 | .dma_owner = dma_ser3, | ||
421 | .io_if = if_serial_3, | ||
785 | #ifdef CONFIG_ETRAX_SERIAL_PORT3 | 422 | #ifdef CONFIG_ETRAX_SERIAL_PORT3 |
786 | .enabled = 1, | 423 | .enabled = 1, |
424 | .io_if_description = "ser3", | ||
787 | #ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA4_OUT | 425 | #ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA4_OUT |
788 | .dma_out_enabled = 1, | 426 | .dma_out_enabled = 1, |
427 | .dma_out_nbr = SER3_TX_DMA_NBR, | ||
428 | .dma_out_irq_nbr = SER3_DMA_TX_IRQ_NBR, | ||
429 | .dma_out_irq_flags = IRQF_DISABLED, | ||
430 | .dma_out_irq_description = "serial 3 dma tr", | ||
789 | #else | 431 | #else |
790 | .dma_out_enabled = 0, | 432 | .dma_out_enabled = 0, |
433 | .dma_out_nbr = UINT_MAX, | ||
434 | .dma_out_irq_nbr = 0, | ||
435 | .dma_out_irq_flags = 0, | ||
436 | .dma_out_irq_description = NULL, | ||
791 | #endif | 437 | #endif |
792 | #ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA5_IN | 438 | #ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA5_IN |
793 | .dma_in_enabled = 1, | 439 | .dma_in_enabled = 1, |
440 | .dma_in_nbr = SER3_RX_DMA_NBR, | ||
441 | .dma_in_irq_nbr = SER3_DMA_RX_IRQ_NBR, | ||
442 | .dma_in_irq_flags = IRQF_DISABLED, | ||
443 | .dma_in_irq_description = "serial 3 dma rec", | ||
794 | #else | 444 | #else |
795 | .dma_in_enabled = 0 | 445 | .dma_in_enabled = 0, |
446 | .dma_in_nbr = UINT_MAX, | ||
447 | .dma_in_irq_nbr = 0, | ||
448 | .dma_in_irq_flags = 0, | ||
449 | .dma_in_irq_description = NULL | ||
796 | #endif | 450 | #endif |
797 | #else | 451 | #else |
798 | .enabled = 0, | 452 | .enabled = 0, |
453 | .io_if_description = NULL, | ||
799 | .dma_out_enabled = 0, | 454 | .dma_out_enabled = 0, |
800 | .dma_in_enabled = 0 | 455 | .dma_in_enabled = 0 |
801 | #endif | 456 | #endif |
@@ -1416,12 +1071,11 @@ e100_dtr(struct e100_serial *info, int set) | |||
1416 | { | 1071 | { |
1417 | unsigned long flags; | 1072 | unsigned long flags; |
1418 | 1073 | ||
1419 | save_flags(flags); | 1074 | local_irq_save(flags); |
1420 | cli(); | ||
1421 | *e100_modem_pins[info->line].dtr_shadow &= ~mask; | 1075 | *e100_modem_pins[info->line].dtr_shadow &= ~mask; |
1422 | *e100_modem_pins[info->line].dtr_shadow |= (set ? 0 : mask); | 1076 | *e100_modem_pins[info->line].dtr_shadow |= (set ? 0 : mask); |
1423 | *e100_modem_pins[info->line].dtr_port = *e100_modem_pins[info->line].dtr_shadow; | 1077 | *e100_modem_pins[info->line].dtr_port = *e100_modem_pins[info->line].dtr_shadow; |
1424 | restore_flags(flags); | 1078 | local_irq_restore(flags); |
1425 | } | 1079 | } |
1426 | 1080 | ||
1427 | #ifdef SERIAL_DEBUG_IO | 1081 | #ifdef SERIAL_DEBUG_IO |
@@ -1440,12 +1094,11 @@ e100_rts(struct e100_serial *info, int set) | |||
1440 | { | 1094 | { |
1441 | #ifndef CONFIG_SVINTO_SIM | 1095 | #ifndef CONFIG_SVINTO_SIM |
1442 | unsigned long flags; | 1096 | unsigned long flags; |
1443 | save_flags(flags); | 1097 | local_irq_save(flags); |
1444 | cli(); | ||
1445 | info->rx_ctrl &= ~E100_RTS_MASK; | 1098 | info->rx_ctrl &= ~E100_RTS_MASK; |
1446 | info->rx_ctrl |= (set ? 0 : E100_RTS_MASK); /* RTS is active low */ | 1099 | info->rx_ctrl |= (set ? 0 : E100_RTS_MASK); /* RTS is active low */ |
1447 | info->port[REG_REC_CTRL] = info->rx_ctrl; | 1100 | info->port[REG_REC_CTRL] = info->rx_ctrl; |
1448 | restore_flags(flags); | 1101 | local_irq_restore(flags); |
1449 | #ifdef SERIAL_DEBUG_IO | 1102 | #ifdef SERIAL_DEBUG_IO |
1450 | printk("ser%i rts %i\n", info->line, set); | 1103 | printk("ser%i rts %i\n", info->line, set); |
1451 | #endif | 1104 | #endif |
@@ -1463,12 +1116,11 @@ e100_ri_out(struct e100_serial *info, int set) | |||
1463 | unsigned char mask = e100_modem_pins[info->line].ri_mask; | 1116 | unsigned char mask = e100_modem_pins[info->line].ri_mask; |
1464 | unsigned long flags; | 1117 | unsigned long flags; |
1465 | 1118 | ||
1466 | save_flags(flags); | 1119 | local_irq_save(flags); |
1467 | cli(); | ||
1468 | *e100_modem_pins[info->line].ri_shadow &= ~mask; | 1120 | *e100_modem_pins[info->line].ri_shadow &= ~mask; |
1469 | *e100_modem_pins[info->line].ri_shadow |= (set ? 0 : mask); | 1121 | *e100_modem_pins[info->line].ri_shadow |= (set ? 0 : mask); |
1470 | *e100_modem_pins[info->line].ri_port = *e100_modem_pins[info->line].ri_shadow; | 1122 | *e100_modem_pins[info->line].ri_port = *e100_modem_pins[info->line].ri_shadow; |
1471 | restore_flags(flags); | 1123 | local_irq_restore(flags); |
1472 | } | 1124 | } |
1473 | #endif | 1125 | #endif |
1474 | } | 1126 | } |
@@ -1481,12 +1133,11 @@ e100_cd_out(struct e100_serial *info, int set) | |||
1481 | unsigned char mask = e100_modem_pins[info->line].cd_mask; | 1133 | unsigned char mask = e100_modem_pins[info->line].cd_mask; |
1482 | unsigned long flags; | 1134 | unsigned long flags; |
1483 | 1135 | ||
1484 | save_flags(flags); | 1136 | local_irq_save(flags); |
1485 | cli(); | ||
1486 | *e100_modem_pins[info->line].cd_shadow &= ~mask; | 1137 | *e100_modem_pins[info->line].cd_shadow &= ~mask; |
1487 | *e100_modem_pins[info->line].cd_shadow |= (set ? 0 : mask); | 1138 | *e100_modem_pins[info->line].cd_shadow |= (set ? 0 : mask); |
1488 | *e100_modem_pins[info->line].cd_port = *e100_modem_pins[info->line].cd_shadow; | 1139 | *e100_modem_pins[info->line].cd_port = *e100_modem_pins[info->line].cd_shadow; |
1489 | restore_flags(flags); | 1140 | local_irq_restore(flags); |
1490 | } | 1141 | } |
1491 | #endif | 1142 | #endif |
1492 | } | 1143 | } |
@@ -1560,8 +1211,7 @@ static void e100_disable_txdma_channel(struct e100_serial *info) | |||
1560 | /* Disable output DMA channel for the serial port in question | 1211 | /* Disable output DMA channel for the serial port in question |
1561 | * ( set to something other then serialX) | 1212 | * ( set to something other then serialX) |
1562 | */ | 1213 | */ |
1563 | save_flags(flags); | 1214 | local_irq_save(flags); |
1564 | cli(); | ||
1565 | DFLOW(DEBUG_LOG(info->line, "disable_txdma_channel %i\n", info->line)); | 1215 | DFLOW(DEBUG_LOG(info->line, "disable_txdma_channel %i\n", info->line)); |
1566 | if (info->line == 0) { | 1216 | if (info->line == 0) { |
1567 | if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma6)) == | 1217 | if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma6)) == |
@@ -1589,7 +1239,7 @@ static void e100_disable_txdma_channel(struct e100_serial *info) | |||
1589 | } | 1239 | } |
1590 | } | 1240 | } |
1591 | *R_GEN_CONFIG = genconfig_shadow; | 1241 | *R_GEN_CONFIG = genconfig_shadow; |
1592 | restore_flags(flags); | 1242 | local_irq_restore(flags); |
1593 | } | 1243 | } |
1594 | 1244 | ||
1595 | 1245 | ||
@@ -1597,8 +1247,7 @@ static void e100_enable_txdma_channel(struct e100_serial *info) | |||
1597 | { | 1247 | { |
1598 | unsigned long flags; | 1248 | unsigned long flags; |
1599 | 1249 | ||
1600 | save_flags(flags); | 1250 | local_irq_save(flags); |
1601 | cli(); | ||
1602 | DFLOW(DEBUG_LOG(info->line, "enable_txdma_channel %i\n", info->line)); | 1251 | DFLOW(DEBUG_LOG(info->line, "enable_txdma_channel %i\n", info->line)); |
1603 | /* Enable output DMA channel for the serial port in question */ | 1252 | /* Enable output DMA channel for the serial port in question */ |
1604 | if (info->line == 0) { | 1253 | if (info->line == 0) { |
@@ -1615,7 +1264,7 @@ static void e100_enable_txdma_channel(struct e100_serial *info) | |||
1615 | genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma4, serial3); | 1264 | genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma4, serial3); |
1616 | } | 1265 | } |
1617 | *R_GEN_CONFIG = genconfig_shadow; | 1266 | *R_GEN_CONFIG = genconfig_shadow; |
1618 | restore_flags(flags); | 1267 | local_irq_restore(flags); |
1619 | } | 1268 | } |
1620 | 1269 | ||
1621 | static void e100_disable_rxdma_channel(struct e100_serial *info) | 1270 | static void e100_disable_rxdma_channel(struct e100_serial *info) |
@@ -1625,8 +1274,7 @@ static void e100_disable_rxdma_channel(struct e100_serial *info) | |||
1625 | /* Disable input DMA channel for the serial port in question | 1274 | /* Disable input DMA channel for the serial port in question |
1626 | * ( set to something other then serialX) | 1275 | * ( set to something other then serialX) |
1627 | */ | 1276 | */ |
1628 | save_flags(flags); | 1277 | local_irq_save(flags); |
1629 | cli(); | ||
1630 | if (info->line == 0) { | 1278 | if (info->line == 0) { |
1631 | if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma7)) == | 1279 | if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma7)) == |
1632 | IO_STATE(R_GEN_CONFIG, dma7, serial0)) { | 1280 | IO_STATE(R_GEN_CONFIG, dma7, serial0)) { |
@@ -1653,7 +1301,7 @@ static void e100_disable_rxdma_channel(struct e100_serial *info) | |||
1653 | } | 1301 | } |
1654 | } | 1302 | } |
1655 | *R_GEN_CONFIG = genconfig_shadow; | 1303 | *R_GEN_CONFIG = genconfig_shadow; |
1656 | restore_flags(flags); | 1304 | local_irq_restore(flags); |
1657 | } | 1305 | } |
1658 | 1306 | ||
1659 | 1307 | ||
@@ -1661,8 +1309,7 @@ static void e100_enable_rxdma_channel(struct e100_serial *info) | |||
1661 | { | 1309 | { |
1662 | unsigned long flags; | 1310 | unsigned long flags; |
1663 | 1311 | ||
1664 | save_flags(flags); | 1312 | local_irq_save(flags); |
1665 | cli(); | ||
1666 | /* Enable input DMA channel for the serial port in question */ | 1313 | /* Enable input DMA channel for the serial port in question */ |
1667 | if (info->line == 0) { | 1314 | if (info->line == 0) { |
1668 | genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma7); | 1315 | genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma7); |
@@ -1678,7 +1325,7 @@ static void e100_enable_rxdma_channel(struct e100_serial *info) | |||
1678 | genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma5, serial3); | 1325 | genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma5, serial3); |
1679 | } | 1326 | } |
1680 | *R_GEN_CONFIG = genconfig_shadow; | 1327 | *R_GEN_CONFIG = genconfig_shadow; |
1681 | restore_flags(flags); | 1328 | local_irq_restore(flags); |
1682 | } | 1329 | } |
1683 | 1330 | ||
1684 | #ifdef SERIAL_HANDLE_EARLY_ERRORS | 1331 | #ifdef SERIAL_HANDLE_EARLY_ERRORS |
@@ -1785,7 +1432,7 @@ e100_enable_rs485(struct tty_struct *tty,struct rs485_control *r) | |||
1785 | } | 1432 | } |
1786 | 1433 | ||
1787 | static int | 1434 | static int |
1788 | e100_write_rs485(struct tty_struct *tty, int from_user, | 1435 | e100_write_rs485(struct tty_struct *tty, |
1789 | const unsigned char *buf, int count) | 1436 | const unsigned char *buf, int count) |
1790 | { | 1437 | { |
1791 | struct e100_serial * info = (struct e100_serial *)tty->driver_data; | 1438 | struct e100_serial * info = (struct e100_serial *)tty->driver_data; |
@@ -1798,7 +1445,7 @@ e100_write_rs485(struct tty_struct *tty, int from_user, | |||
1798 | */ | 1445 | */ |
1799 | info->rs485.enabled = 1; | 1446 | info->rs485.enabled = 1; |
1800 | /* rs_write now deals with RS485 if enabled */ | 1447 | /* rs_write now deals with RS485 if enabled */ |
1801 | count = rs_write(tty, from_user, buf, count); | 1448 | count = rs_write(tty, buf, count); |
1802 | info->rs485.enabled = old_enabled; | 1449 | info->rs485.enabled = old_enabled; |
1803 | return count; | 1450 | return count; |
1804 | } | 1451 | } |
@@ -1836,7 +1483,7 @@ rs_stop(struct tty_struct *tty) | |||
1836 | unsigned long flags; | 1483 | unsigned long flags; |
1837 | unsigned long xoff; | 1484 | unsigned long xoff; |
1838 | 1485 | ||
1839 | save_flags(flags); cli(); | 1486 | local_irq_save(flags); |
1840 | DFLOW(DEBUG_LOG(info->line, "XOFF rs_stop xmit %i\n", | 1487 | DFLOW(DEBUG_LOG(info->line, "XOFF rs_stop xmit %i\n", |
1841 | CIRC_CNT(info->xmit.head, | 1488 | CIRC_CNT(info->xmit.head, |
1842 | info->xmit.tail,SERIAL_XMIT_SIZE))); | 1489 | info->xmit.tail,SERIAL_XMIT_SIZE))); |
@@ -1848,7 +1495,7 @@ rs_stop(struct tty_struct *tty) | |||
1848 | } | 1495 | } |
1849 | 1496 | ||
1850 | *((unsigned long *)&info->port[REG_XOFF]) = xoff; | 1497 | *((unsigned long *)&info->port[REG_XOFF]) = xoff; |
1851 | restore_flags(flags); | 1498 | local_irq_restore(flags); |
1852 | } | 1499 | } |
1853 | } | 1500 | } |
1854 | 1501 | ||
@@ -1860,7 +1507,7 @@ rs_start(struct tty_struct *tty) | |||
1860 | unsigned long flags; | 1507 | unsigned long flags; |
1861 | unsigned long xoff; | 1508 | unsigned long xoff; |
1862 | 1509 | ||
1863 | save_flags(flags); cli(); | 1510 | local_irq_save(flags); |
1864 | DFLOW(DEBUG_LOG(info->line, "XOFF rs_start xmit %i\n", | 1511 | DFLOW(DEBUG_LOG(info->line, "XOFF rs_start xmit %i\n", |
1865 | CIRC_CNT(info->xmit.head, | 1512 | CIRC_CNT(info->xmit.head, |
1866 | info->xmit.tail,SERIAL_XMIT_SIZE))); | 1513 | info->xmit.tail,SERIAL_XMIT_SIZE))); |
@@ -1875,7 +1522,7 @@ rs_start(struct tty_struct *tty) | |||
1875 | info->xmit.head != info->xmit.tail && info->xmit.buf) | 1522 | info->xmit.head != info->xmit.tail && info->xmit.buf) |
1876 | e100_enable_serial_tx_ready_irq(info); | 1523 | e100_enable_serial_tx_ready_irq(info); |
1877 | 1524 | ||
1878 | restore_flags(flags); | 1525 | local_irq_restore(flags); |
1879 | } | 1526 | } |
1880 | } | 1527 | } |
1881 | 1528 | ||
@@ -2055,8 +1702,7 @@ static int serial_fast_timer_expired = 0; | |||
2055 | static void flush_timeout_function(unsigned long data); | 1702 | static void flush_timeout_function(unsigned long data); |
2056 | #define START_FLUSH_FAST_TIMER_TIME(info, string, usec) {\ | 1703 | #define START_FLUSH_FAST_TIMER_TIME(info, string, usec) {\ |
2057 | unsigned long timer_flags; \ | 1704 | unsigned long timer_flags; \ |
2058 | save_flags(timer_flags); \ | 1705 | local_irq_save(timer_flags); \ |
2059 | cli(); \ | ||
2060 | if (fast_timers[info->line].function == NULL) { \ | 1706 | if (fast_timers[info->line].function == NULL) { \ |
2061 | serial_fast_timer_started++; \ | 1707 | serial_fast_timer_started++; \ |
2062 | TIMERD(DEBUG_LOG(info->line, "start_timer %i ", info->line)); \ | 1708 | TIMERD(DEBUG_LOG(info->line, "start_timer %i ", info->line)); \ |
@@ -2070,7 +1716,7 @@ static void flush_timeout_function(unsigned long data); | |||
2070 | else { \ | 1716 | else { \ |
2071 | TIMERD(DEBUG_LOG(info->line, "timer %i already running\n", info->line)); \ | 1717 | TIMERD(DEBUG_LOG(info->line, "timer %i already running\n", info->line)); \ |
2072 | } \ | 1718 | } \ |
2073 | restore_flags(timer_flags); \ | 1719 | local_irq_restore(timer_flags); \ |
2074 | } | 1720 | } |
2075 | #define START_FLUSH_FAST_TIMER(info, string) START_FLUSH_FAST_TIMER_TIME(info, string, info->flush_time_usec) | 1721 | #define START_FLUSH_FAST_TIMER(info, string) START_FLUSH_FAST_TIMER_TIME(info, string, info->flush_time_usec) |
2076 | 1722 | ||
@@ -2099,8 +1745,7 @@ append_recv_buffer(struct e100_serial *info, struct etrax_recv_buffer *buffer) | |||
2099 | { | 1745 | { |
2100 | unsigned long flags; | 1746 | unsigned long flags; |
2101 | 1747 | ||
2102 | save_flags(flags); | 1748 | local_irq_save(flags); |
2103 | cli(); | ||
2104 | 1749 | ||
2105 | if (!info->first_recv_buffer) | 1750 | if (!info->first_recv_buffer) |
2106 | info->first_recv_buffer = buffer; | 1751 | info->first_recv_buffer = buffer; |
@@ -2113,7 +1758,7 @@ append_recv_buffer(struct e100_serial *info, struct etrax_recv_buffer *buffer) | |||
2113 | if (info->recv_cnt > info->max_recv_cnt) | 1758 | if (info->recv_cnt > info->max_recv_cnt) |
2114 | info->max_recv_cnt = info->recv_cnt; | 1759 | info->max_recv_cnt = info->recv_cnt; |
2115 | 1760 | ||
2116 | restore_flags(flags); | 1761 | local_irq_restore(flags); |
2117 | } | 1762 | } |
2118 | 1763 | ||
2119 | static int | 1764 | static int |
@@ -2133,11 +1778,7 @@ add_char_and_flag(struct e100_serial *info, unsigned char data, unsigned char fl | |||
2133 | info->icount.rx++; | 1778 | info->icount.rx++; |
2134 | } else { | 1779 | } else { |
2135 | struct tty_struct *tty = info->tty; | 1780 | struct tty_struct *tty = info->tty; |
2136 | *tty->flip.char_buf_ptr = data; | 1781 | tty_insert_flip_char(tty, data, flag); |
2137 | *tty->flip.flag_buf_ptr = flag; | ||
2138 | tty->flip.flag_buf_ptr++; | ||
2139 | tty->flip.char_buf_ptr++; | ||
2140 | tty->flip.count++; | ||
2141 | info->icount.rx++; | 1782 | info->icount.rx++; |
2142 | } | 1783 | } |
2143 | 1784 | ||
@@ -2322,7 +1963,6 @@ start_receive(struct e100_serial *info) | |||
2322 | */ | 1963 | */ |
2323 | return; | 1964 | return; |
2324 | #endif | 1965 | #endif |
2325 | info->tty->flip.count = 0; | ||
2326 | if (info->uses_dma_in) { | 1966 | if (info->uses_dma_in) { |
2327 | /* reset the input dma channel to be sure it works */ | 1967 | /* reset the input dma channel to be sure it works */ |
2328 | 1968 | ||
@@ -2484,32 +2124,20 @@ static void flush_to_flip_buffer(struct e100_serial *info) | |||
2484 | { | 2124 | { |
2485 | struct tty_struct *tty; | 2125 | struct tty_struct *tty; |
2486 | struct etrax_recv_buffer *buffer; | 2126 | struct etrax_recv_buffer *buffer; |
2487 | unsigned int length; | ||
2488 | unsigned long flags; | 2127 | unsigned long flags; |
2489 | int max_flip_size; | ||
2490 | |||
2491 | if (!info->first_recv_buffer) | ||
2492 | return; | ||
2493 | 2128 | ||
2494 | save_flags(flags); | 2129 | local_irq_save(flags); |
2495 | cli(); | 2130 | tty = info->tty; |
2496 | 2131 | ||
2497 | if (!(tty = info->tty)) { | 2132 | if (!tty) { |
2498 | restore_flags(flags); | 2133 | local_irq_restore(flags); |
2499 | return; | 2134 | return; |
2500 | } | 2135 | } |
2501 | 2136 | ||
2502 | while ((buffer = info->first_recv_buffer) != NULL) { | 2137 | while ((buffer = info->first_recv_buffer) != NULL) { |
2503 | unsigned int count = buffer->length; | 2138 | unsigned int count = buffer->length; |
2504 | 2139 | ||
2505 | count = tty_buffer_request_room(tty, count); | 2140 | tty_insert_flip_string(tty, buffer->buffer, count); |
2506 | if (count == 0) /* Throttle ?? */ | ||
2507 | break; | ||
2508 | |||
2509 | if (count > 1) | ||
2510 | tty_insert_flip_strings(tty, buffer->buffer, count - 1); | ||
2511 | tty_insert_flip_char(tty, buffer->buffer[count-1], buffer->error); | ||
2512 | |||
2513 | info->recv_cnt -= count; | 2141 | info->recv_cnt -= count; |
2514 | 2142 | ||
2515 | if (count == buffer->length) { | 2143 | if (count == buffer->length) { |
@@ -2525,18 +2153,9 @@ static void flush_to_flip_buffer(struct e100_serial *info) | |||
2525 | if (!info->first_recv_buffer) | 2153 | if (!info->first_recv_buffer) |
2526 | info->last_recv_buffer = NULL; | 2154 | info->last_recv_buffer = NULL; |
2527 | 2155 | ||
2528 | restore_flags(flags); | 2156 | local_irq_restore(flags); |
2529 | |||
2530 | DFLIP( | ||
2531 | if (1) { | ||
2532 | DEBUG_LOG(info->line, "*** rxtot %i\n", info->icount.rx); | ||
2533 | DEBUG_LOG(info->line, "ldisc %lu\n", tty->ldisc.chars_in_buffer(tty)); | ||
2534 | DEBUG_LOG(info->line, "room %lu\n", tty->ldisc.receive_room(tty)); | ||
2535 | } | ||
2536 | 2157 | ||
2537 | ); | 2158 | /* This includes a check for low-latency */ |
2538 | |||
2539 | /* this includes a check for low-latency */ | ||
2540 | tty_flip_buffer_push(tty); | 2159 | tty_flip_buffer_push(tty); |
2541 | } | 2160 | } |
2542 | 2161 | ||
@@ -2679,21 +2298,7 @@ struct e100_serial * handle_ser_rx_interrupt_no_dma(struct e100_serial *info) | |||
2679 | printk("!NO TTY!\n"); | 2298 | printk("!NO TTY!\n"); |
2680 | return info; | 2299 | return info; |
2681 | } | 2300 | } |
2682 | if (tty->flip.count >= CRIS_BUF_SIZE - TTY_THRESHOLD_THROTTLE) { | 2301 | |
2683 | /* check TTY_THROTTLED first so it indicates our state */ | ||
2684 | if (!test_and_set_bit(TTY_THROTTLED, &tty->flags)) { | ||
2685 | DFLOW(DEBUG_LOG(info->line, "rs_throttle flip.count: %i\n", tty->flip.count)); | ||
2686 | rs_throttle(tty); | ||
2687 | } | ||
2688 | } | ||
2689 | if (tty->flip.count >= CRIS_BUF_SIZE) { | ||
2690 | DEBUG_LOG(info->line, "force FLIP! %i\n", tty->flip.count); | ||
2691 | tty->flip.work.func((void *) tty); | ||
2692 | if (tty->flip.count >= CRIS_BUF_SIZE) { | ||
2693 | DEBUG_LOG(info->line, "FLIP FULL! %i\n", tty->flip.count); | ||
2694 | return info; /* if TTY_DONT_FLIP is set */ | ||
2695 | } | ||
2696 | } | ||
2697 | /* Read data and status at the same time */ | 2302 | /* Read data and status at the same time */ |
2698 | data_read = *((unsigned long *)&info->port[REG_DATA_STATUS32]); | 2303 | data_read = *((unsigned long *)&info->port[REG_DATA_STATUS32]); |
2699 | more_data: | 2304 | more_data: |
@@ -2746,27 +2351,26 @@ more_data: | |||
2746 | DEBUG_LOG(info->line, "EBRK %i\n", info->break_detected_cnt); | 2351 | DEBUG_LOG(info->line, "EBRK %i\n", info->break_detected_cnt); |
2747 | info->errorcode = ERRCODE_INSERT_BREAK; | 2352 | info->errorcode = ERRCODE_INSERT_BREAK; |
2748 | } else { | 2353 | } else { |
2354 | unsigned char data = IO_EXTRACT(R_SERIAL0_READ, | ||
2355 | data_in, data_read); | ||
2356 | char flag = TTY_NORMAL; | ||
2749 | if (info->errorcode == ERRCODE_INSERT_BREAK) { | 2357 | if (info->errorcode == ERRCODE_INSERT_BREAK) { |
2750 | info->icount.brk++; | 2358 | struct tty_struct *tty = info->tty; |
2751 | *tty->flip.char_buf_ptr = 0; | 2359 | tty_insert_flip_char(tty, 0, flag); |
2752 | *tty->flip.flag_buf_ptr = TTY_BREAK; | ||
2753 | tty->flip.flag_buf_ptr++; | ||
2754 | tty->flip.char_buf_ptr++; | ||
2755 | tty->flip.count++; | ||
2756 | info->icount.rx++; | 2360 | info->icount.rx++; |
2757 | } | 2361 | } |
2758 | *tty->flip.char_buf_ptr = IO_EXTRACT(R_SERIAL0_READ, data_in, data_read); | ||
2759 | 2362 | ||
2760 | if (data_read & IO_MASK(R_SERIAL0_READ, par_err)) { | 2363 | if (data_read & IO_MASK(R_SERIAL0_READ, par_err)) { |
2761 | info->icount.parity++; | 2364 | info->icount.parity++; |
2762 | *tty->flip.flag_buf_ptr = TTY_PARITY; | 2365 | flag = TTY_PARITY; |
2763 | } else if (data_read & IO_MASK(R_SERIAL0_READ, overrun)) { | 2366 | } else if (data_read & IO_MASK(R_SERIAL0_READ, overrun)) { |
2764 | info->icount.overrun++; | 2367 | info->icount.overrun++; |
2765 | *tty->flip.flag_buf_ptr = TTY_OVERRUN; | 2368 | flag = TTY_OVERRUN; |
2766 | } else if (data_read & IO_MASK(R_SERIAL0_READ, framing_err)) { | 2369 | } else if (data_read & IO_MASK(R_SERIAL0_READ, framing_err)) { |
2767 | info->icount.frame++; | 2370 | info->icount.frame++; |
2768 | *tty->flip.flag_buf_ptr = TTY_FRAME; | 2371 | flag = TTY_FRAME; |
2769 | } | 2372 | } |
2373 | tty_insert_flip_char(tty, data, flag); | ||
2770 | info->errorcode = 0; | 2374 | info->errorcode = 0; |
2771 | } | 2375 | } |
2772 | info->break_detected_cnt = 0; | 2376 | info->break_detected_cnt = 0; |
@@ -2782,16 +2386,14 @@ more_data: | |||
2782 | log_int(rdpc(), 0, 0); | 2386 | log_int(rdpc(), 0, 0); |
2783 | } | 2387 | } |
2784 | ); | 2388 | ); |
2785 | *tty->flip.char_buf_ptr = IO_EXTRACT(R_SERIAL0_READ, data_in, data_read); | 2389 | tty_insert_flip_char(tty, |
2786 | *tty->flip.flag_buf_ptr = 0; | 2390 | IO_EXTRACT(R_SERIAL0_READ, data_in, data_read), |
2391 | TTY_NORMAL); | ||
2787 | } else { | 2392 | } else { |
2788 | DEBUG_LOG(info->line, "ser_rx int but no data_avail %08lX\n", data_read); | 2393 | DEBUG_LOG(info->line, "ser_rx int but no data_avail %08lX\n", data_read); |
2789 | } | 2394 | } |
2790 | 2395 | ||
2791 | 2396 | ||
2792 | tty->flip.flag_buf_ptr++; | ||
2793 | tty->flip.char_buf_ptr++; | ||
2794 | tty->flip.count++; | ||
2795 | info->icount.rx++; | 2397 | info->icount.rx++; |
2796 | data_read = *((unsigned long *)&info->port[REG_DATA_STATUS32]); | 2398 | data_read = *((unsigned long *)&info->port[REG_DATA_STATUS32]); |
2797 | if (data_read & IO_MASK(R_SERIAL0_READ, data_avail)) { | 2399 | if (data_read & IO_MASK(R_SERIAL0_READ, data_avail)) { |
@@ -2929,7 +2531,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) | |||
2929 | if (info->x_char) { | 2531 | if (info->x_char) { |
2930 | unsigned char rstat; | 2532 | unsigned char rstat; |
2931 | DFLOW(DEBUG_LOG(info->line, "tx_int: xchar 0x%02X\n", info->x_char)); | 2533 | DFLOW(DEBUG_LOG(info->line, "tx_int: xchar 0x%02X\n", info->x_char)); |
2932 | save_flags(flags); cli(); | 2534 | local_irq_save(flags); |
2933 | rstat = info->port[REG_STATUS]; | 2535 | rstat = info->port[REG_STATUS]; |
2934 | DFLOW(DEBUG_LOG(info->line, "stat %x\n", rstat)); | 2536 | DFLOW(DEBUG_LOG(info->line, "stat %x\n", rstat)); |
2935 | 2537 | ||
@@ -2938,7 +2540,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) | |||
2938 | info->x_char = 0; | 2540 | info->x_char = 0; |
2939 | /* We must enable since it is disabled in ser_interrupt */ | 2541 | /* We must enable since it is disabled in ser_interrupt */ |
2940 | e100_enable_serial_tx_ready_irq(info); | 2542 | e100_enable_serial_tx_ready_irq(info); |
2941 | restore_flags(flags); | 2543 | local_irq_restore(flags); |
2942 | return; | 2544 | return; |
2943 | } | 2545 | } |
2944 | if (info->uses_dma_out) { | 2546 | if (info->uses_dma_out) { |
@@ -2946,7 +2548,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) | |||
2946 | int i; | 2548 | int i; |
2947 | /* We only use normal tx interrupt when sending x_char */ | 2549 | /* We only use normal tx interrupt when sending x_char */ |
2948 | DFLOW(DEBUG_LOG(info->line, "tx_int: xchar sent\n", 0)); | 2550 | DFLOW(DEBUG_LOG(info->line, "tx_int: xchar sent\n", 0)); |
2949 | save_flags(flags); cli(); | 2551 | local_irq_save(flags); |
2950 | rstat = info->port[REG_STATUS]; | 2552 | rstat = info->port[REG_STATUS]; |
2951 | DFLOW(DEBUG_LOG(info->line, "stat %x\n", rstat)); | 2553 | DFLOW(DEBUG_LOG(info->line, "stat %x\n", rstat)); |
2952 | e100_disable_serial_tx_ready_irq(info); | 2554 | e100_disable_serial_tx_ready_irq(info); |
@@ -2959,7 +2561,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) | |||
2959 | nop(); | 2561 | nop(); |
2960 | 2562 | ||
2961 | *info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, continue); | 2563 | *info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, continue); |
2962 | restore_flags(flags); | 2564 | local_irq_restore(flags); |
2963 | return; | 2565 | return; |
2964 | } | 2566 | } |
2965 | /* Normal char-by-char interrupt */ | 2567 | /* Normal char-by-char interrupt */ |
@@ -2973,7 +2575,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) | |||
2973 | } | 2575 | } |
2974 | DINTR2(DEBUG_LOG(info->line, "tx_int %c\n", info->xmit.buf[info->xmit.tail])); | 2576 | DINTR2(DEBUG_LOG(info->line, "tx_int %c\n", info->xmit.buf[info->xmit.tail])); |
2975 | /* Send a byte, rs485 timing is critical so turn of ints */ | 2577 | /* Send a byte, rs485 timing is critical so turn of ints */ |
2976 | save_flags(flags); cli(); | 2578 | local_irq_save(flags); |
2977 | info->port[REG_TR_DATA] = info->xmit.buf[info->xmit.tail]; | 2579 | info->port[REG_TR_DATA] = info->xmit.buf[info->xmit.tail]; |
2978 | info->xmit.tail = (info->xmit.tail + 1) & (SERIAL_XMIT_SIZE-1); | 2580 | info->xmit.tail = (info->xmit.tail + 1) & (SERIAL_XMIT_SIZE-1); |
2979 | info->icount.tx++; | 2581 | info->icount.tx++; |
@@ -2997,7 +2599,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) | |||
2997 | /* We must enable since it is disabled in ser_interrupt */ | 2599 | /* We must enable since it is disabled in ser_interrupt */ |
2998 | e100_enable_serial_tx_ready_irq(info); | 2600 | e100_enable_serial_tx_ready_irq(info); |
2999 | } | 2601 | } |
3000 | restore_flags(flags); | 2602 | local_irq_restore(flags); |
3001 | 2603 | ||
3002 | if (CIRC_CNT(info->xmit.head, | 2604 | if (CIRC_CNT(info->xmit.head, |
3003 | info->xmit.tail, | 2605 | info->xmit.tail, |
@@ -3022,7 +2624,7 @@ ser_interrupt(int irq, void *dev_id) | |||
3022 | int handled = 0; | 2624 | int handled = 0; |
3023 | static volatile unsigned long reentered_ready_mask = 0; | 2625 | static volatile unsigned long reentered_ready_mask = 0; |
3024 | 2626 | ||
3025 | save_flags(flags); cli(); | 2627 | local_irq_save(flags); |
3026 | irq_mask1_rd = *R_IRQ_MASK1_RD; | 2628 | irq_mask1_rd = *R_IRQ_MASK1_RD; |
3027 | /* First handle all rx interrupts with ints disabled */ | 2629 | /* First handle all rx interrupts with ints disabled */ |
3028 | info = rs_table; | 2630 | info = rs_table; |
@@ -3067,7 +2669,7 @@ ser_interrupt(int irq, void *dev_id) | |||
3067 | /* Unblock the serial interrupt */ | 2669 | /* Unblock the serial interrupt */ |
3068 | *R_VECT_MASK_SET = IO_STATE(R_VECT_MASK_SET, serial, set); | 2670 | *R_VECT_MASK_SET = IO_STATE(R_VECT_MASK_SET, serial, set); |
3069 | 2671 | ||
3070 | sti(); | 2672 | local_irq_enable(); |
3071 | ready_mask = (1 << (8+1+2*0)); /* ser0 tr_ready */ | 2673 | ready_mask = (1 << (8+1+2*0)); /* ser0 tr_ready */ |
3072 | info = rs_table; | 2674 | info = rs_table; |
3073 | for (i = 0; i < NR_PORTS; i++) { | 2675 | for (i = 0; i < NR_PORTS; i++) { |
@@ -3080,11 +2682,11 @@ ser_interrupt(int irq, void *dev_id) | |||
3080 | ready_mask <<= 2; | 2682 | ready_mask <<= 2; |
3081 | } | 2683 | } |
3082 | /* handle_ser_tx_interrupt enables tr_ready interrupts */ | 2684 | /* handle_ser_tx_interrupt enables tr_ready interrupts */ |
3083 | cli(); | 2685 | local_irq_disable(); |
3084 | /* Handle reentered TX interrupt */ | 2686 | /* Handle reentered TX interrupt */ |
3085 | irq_mask1_rd = reentered_ready_mask; | 2687 | irq_mask1_rd = reentered_ready_mask; |
3086 | } | 2688 | } |
3087 | cli(); | 2689 | local_irq_disable(); |
3088 | tx_started = 0; | 2690 | tx_started = 0; |
3089 | } else { | 2691 | } else { |
3090 | unsigned long ready_mask; | 2692 | unsigned long ready_mask; |
@@ -3100,7 +2702,7 @@ ser_interrupt(int irq, void *dev_id) | |||
3100 | } | 2702 | } |
3101 | } | 2703 | } |
3102 | 2704 | ||
3103 | restore_flags(flags); | 2705 | local_irq_restore(flags); |
3104 | return IRQ_RETVAL(handled); | 2706 | return IRQ_RETVAL(handled); |
3105 | } /* ser_interrupt */ | 2707 | } /* ser_interrupt */ |
3106 | #endif | 2708 | #endif |
@@ -3121,11 +2723,13 @@ ser_interrupt(int irq, void *dev_id) | |||
3121 | * them using rs_sched_event(), and they get done here. | 2723 | * them using rs_sched_event(), and they get done here. |
3122 | */ | 2724 | */ |
3123 | static void | 2725 | static void |
3124 | do_softint(void *private_) | 2726 | do_softint(struct work_struct *work) |
3125 | { | 2727 | { |
3126 | struct e100_serial *info = (struct e100_serial *) private_; | 2728 | struct e100_serial *info; |
3127 | struct tty_struct *tty; | 2729 | struct tty_struct *tty; |
3128 | 2730 | ||
2731 | info = container_of(work, struct e100_serial, work); | ||
2732 | |||
3129 | tty = info->tty; | 2733 | tty = info->tty; |
3130 | if (!tty) | 2734 | if (!tty) |
3131 | return; | 2735 | return; |
@@ -3145,13 +2749,12 @@ startup(struct e100_serial * info) | |||
3145 | if (!xmit_page) | 2749 | if (!xmit_page) |
3146 | return -ENOMEM; | 2750 | return -ENOMEM; |
3147 | 2751 | ||
3148 | save_flags(flags); | 2752 | local_irq_save(flags); |
3149 | cli(); | ||
3150 | 2753 | ||
3151 | /* if it was already initialized, skip this */ | 2754 | /* if it was already initialized, skip this */ |
3152 | 2755 | ||
3153 | if (info->flags & ASYNC_INITIALIZED) { | 2756 | if (info->flags & ASYNC_INITIALIZED) { |
3154 | restore_flags(flags); | 2757 | local_irq_restore(flags); |
3155 | free_page(xmit_page); | 2758 | free_page(xmit_page); |
3156 | return 0; | 2759 | return 0; |
3157 | } | 2760 | } |
@@ -3277,7 +2880,7 @@ startup(struct e100_serial * info) | |||
3277 | 2880 | ||
3278 | info->flags |= ASYNC_INITIALIZED; | 2881 | info->flags |= ASYNC_INITIALIZED; |
3279 | 2882 | ||
3280 | restore_flags(flags); | 2883 | local_irq_restore(flags); |
3281 | return 0; | 2884 | return 0; |
3282 | } | 2885 | } |
3283 | 2886 | ||
@@ -3328,8 +2931,7 @@ shutdown(struct e100_serial * info) | |||
3328 | info->irq); | 2931 | info->irq); |
3329 | #endif | 2932 | #endif |
3330 | 2933 | ||
3331 | save_flags(flags); | 2934 | local_irq_save(flags); |
3332 | cli(); /* Disable interrupts */ | ||
3333 | 2935 | ||
3334 | if (info->xmit.buf) { | 2936 | if (info->xmit.buf) { |
3335 | free_page((unsigned long)info->xmit.buf); | 2937 | free_page((unsigned long)info->xmit.buf); |
@@ -3353,7 +2955,7 @@ shutdown(struct e100_serial * info) | |||
3353 | set_bit(TTY_IO_ERROR, &info->tty->flags); | 2955 | set_bit(TTY_IO_ERROR, &info->tty->flags); |
3354 | 2956 | ||
3355 | info->flags &= ~ASYNC_INITIALIZED; | 2957 | info->flags &= ~ASYNC_INITIALIZED; |
3356 | restore_flags(flags); | 2958 | local_irq_restore(flags); |
3357 | } | 2959 | } |
3358 | 2960 | ||
3359 | 2961 | ||
@@ -3411,7 +3013,6 @@ change_speed(struct e100_serial *info) | |||
3411 | DBAUD(printk("using external baudrate: %lu\n", CONFIG_ETRAX_EXTERN_PB6CLK_FREQ/8)); | 3013 | DBAUD(printk("using external baudrate: %lu\n", CONFIG_ETRAX_EXTERN_PB6CLK_FREQ/8)); |
3412 | info->baud = CONFIG_ETRAX_EXTERN_PB6CLK_FREQ/8; | 3014 | info->baud = CONFIG_ETRAX_EXTERN_PB6CLK_FREQ/8; |
3413 | } | 3015 | } |
3414 | } | ||
3415 | #endif | 3016 | #endif |
3416 | else | 3017 | else |
3417 | { | 3018 | { |
@@ -3445,8 +3046,7 @@ change_speed(struct e100_serial *info) | |||
3445 | 3046 | ||
3446 | #ifndef CONFIG_SVINTO_SIM | 3047 | #ifndef CONFIG_SVINTO_SIM |
3447 | /* start with default settings and then fill in changes */ | 3048 | /* start with default settings and then fill in changes */ |
3448 | save_flags(flags); | 3049 | local_irq_save(flags); |
3449 | cli(); | ||
3450 | /* 8 bit, no/even parity */ | 3050 | /* 8 bit, no/even parity */ |
3451 | info->rx_ctrl &= ~(IO_MASK(R_SERIAL0_REC_CTRL, rec_bitnr) | | 3051 | info->rx_ctrl &= ~(IO_MASK(R_SERIAL0_REC_CTRL, rec_bitnr) | |
3452 | IO_MASK(R_SERIAL0_REC_CTRL, rec_par_en) | | 3052 | IO_MASK(R_SERIAL0_REC_CTRL, rec_par_en) | |
@@ -3510,7 +3110,7 @@ change_speed(struct e100_serial *info) | |||
3510 | } | 3110 | } |
3511 | 3111 | ||
3512 | *((unsigned long *)&info->port[REG_XOFF]) = xoff; | 3112 | *((unsigned long *)&info->port[REG_XOFF]) = xoff; |
3513 | restore_flags(flags); | 3113 | local_irq_restore(flags); |
3514 | #endif /* !CONFIG_SVINTO_SIM */ | 3114 | #endif /* !CONFIG_SVINTO_SIM */ |
3515 | 3115 | ||
3516 | update_char_time(info); | 3116 | update_char_time(info); |
@@ -3538,13 +3138,12 @@ rs_flush_chars(struct tty_struct *tty) | |||
3538 | 3138 | ||
3539 | /* this protection might not exactly be necessary here */ | 3139 | /* this protection might not exactly be necessary here */ |
3540 | 3140 | ||
3541 | save_flags(flags); | 3141 | local_irq_save(flags); |
3542 | cli(); | ||
3543 | start_transmit(info); | 3142 | start_transmit(info); |
3544 | restore_flags(flags); | 3143 | local_irq_restore(flags); |
3545 | } | 3144 | } |
3546 | 3145 | ||
3547 | static int rs_raw_write(struct tty_struct * tty, int from_user, | 3146 | static int rs_raw_write(struct tty_struct *tty, |
3548 | const unsigned char *buf, int count) | 3147 | const unsigned char *buf, int count) |
3549 | { | 3148 | { |
3550 | int c, ret = 0; | 3149 | int c, ret = 0; |
@@ -3567,53 +3166,19 @@ static int rs_raw_write(struct tty_struct * tty, int from_user, | |||
3567 | SIMCOUT(buf, count); | 3166 | SIMCOUT(buf, count); |
3568 | return count; | 3167 | return count; |
3569 | #endif | 3168 | #endif |
3570 | save_flags(flags); | 3169 | local_save_flags(flags); |
3571 | DFLOW(DEBUG_LOG(info->line, "write count %i ", count)); | 3170 | DFLOW(DEBUG_LOG(info->line, "write count %i ", count)); |
3572 | DFLOW(DEBUG_LOG(info->line, "ldisc %i\n", tty->ldisc.chars_in_buffer(tty))); | 3171 | DFLOW(DEBUG_LOG(info->line, "ldisc %i\n", tty->ldisc.chars_in_buffer(tty))); |
3573 | 3172 | ||
3574 | 3173 | ||
3575 | /* the cli/restore_flags pairs below are needed because the | 3174 | /* The local_irq_disable/restore_flags pairs below are needed |
3576 | * DMA interrupt handler moves the info->xmit values. the memcpy | 3175 | * because the DMA interrupt handler moves the info->xmit values. |
3577 | * needs to be in the critical region unfortunately, because we | 3176 | * the memcpy needs to be in the critical region unfortunately, |
3578 | * need to read xmit values, memcpy, write xmit values in one | 3177 | * because we need to read xmit values, memcpy, write xmit values |
3579 | * atomic operation... this could perhaps be avoided by more clever | 3178 | * in one atomic operation... this could perhaps be avoided by |
3580 | * design. | 3179 | * more clever design. |
3581 | */ | 3180 | */ |
3582 | if (from_user) { | 3181 | local_irq_disable(); |
3583 | mutex_lock(&tmp_buf_mutex); | ||
3584 | while (1) { | ||
3585 | int c1; | ||
3586 | c = CIRC_SPACE_TO_END(info->xmit.head, | ||
3587 | info->xmit.tail, | ||
3588 | SERIAL_XMIT_SIZE); | ||
3589 | if (count < c) | ||
3590 | c = count; | ||
3591 | if (c <= 0) | ||
3592 | break; | ||
3593 | |||
3594 | c -= copy_from_user(tmp_buf, buf, c); | ||
3595 | if (!c) { | ||
3596 | if (!ret) | ||
3597 | ret = -EFAULT; | ||
3598 | break; | ||
3599 | } | ||
3600 | cli(); | ||
3601 | c1 = CIRC_SPACE_TO_END(info->xmit.head, | ||
3602 | info->xmit.tail, | ||
3603 | SERIAL_XMIT_SIZE); | ||
3604 | if (c1 < c) | ||
3605 | c = c1; | ||
3606 | memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c); | ||
3607 | info->xmit.head = ((info->xmit.head + c) & | ||
3608 | (SERIAL_XMIT_SIZE-1)); | ||
3609 | restore_flags(flags); | ||
3610 | buf += c; | ||
3611 | count -= c; | ||
3612 | ret += c; | ||
3613 | } | ||
3614 | mutex_unlock(&tmp_buf_mutex); | ||
3615 | } else { | ||
3616 | cli(); | ||
3617 | while (count) { | 3182 | while (count) { |
3618 | c = CIRC_SPACE_TO_END(info->xmit.head, | 3183 | c = CIRC_SPACE_TO_END(info->xmit.head, |
3619 | info->xmit.tail, | 3184 | info->xmit.tail, |
@@ -3631,8 +3196,7 @@ static int rs_raw_write(struct tty_struct * tty, int from_user, | |||
3631 | count -= c; | 3196 | count -= c; |
3632 | ret += c; | 3197 | ret += c; |
3633 | } | 3198 | } |
3634 | restore_flags(flags); | 3199 | local_irq_restore(flags); |
3635 | } | ||
3636 | 3200 | ||
3637 | /* enable transmitter if not running, unless the tty is stopped | 3201 | /* enable transmitter if not running, unless the tty is stopped |
3638 | * this does not need IRQ protection since if tr_running == 0 | 3202 | * this does not need IRQ protection since if tr_running == 0 |
@@ -3651,7 +3215,7 @@ static int rs_raw_write(struct tty_struct * tty, int from_user, | |||
3651 | } /* raw_raw_write() */ | 3215 | } /* raw_raw_write() */ |
3652 | 3216 | ||
3653 | static int | 3217 | static int |
3654 | rs_write(struct tty_struct * tty, int from_user, | 3218 | rs_write(struct tty_struct *tty, |
3655 | const unsigned char *buf, int count) | 3219 | const unsigned char *buf, int count) |
3656 | { | 3220 | { |
3657 | #if defined(CONFIG_ETRAX_RS485) | 3221 | #if defined(CONFIG_ETRAX_RS485) |
@@ -3678,7 +3242,7 @@ rs_write(struct tty_struct * tty, int from_user, | |||
3678 | } | 3242 | } |
3679 | #endif /* CONFIG_ETRAX_RS485 */ | 3243 | #endif /* CONFIG_ETRAX_RS485 */ |
3680 | 3244 | ||
3681 | count = rs_raw_write(tty, from_user, buf, count); | 3245 | count = rs_raw_write(tty, buf, count); |
3682 | 3246 | ||
3683 | #if defined(CONFIG_ETRAX_RS485) | 3247 | #if defined(CONFIG_ETRAX_RS485) |
3684 | if (info->rs485.enabled) | 3248 | if (info->rs485.enabled) |
@@ -3746,10 +3310,9 @@ rs_flush_buffer(struct tty_struct *tty) | |||
3746 | struct e100_serial *info = (struct e100_serial *)tty->driver_data; | 3310 | struct e100_serial *info = (struct e100_serial *)tty->driver_data; |
3747 | unsigned long flags; | 3311 | unsigned long flags; |
3748 | 3312 | ||
3749 | save_flags(flags); | 3313 | local_irq_save(flags); |
3750 | cli(); | ||
3751 | info->xmit.head = info->xmit.tail = 0; | 3314 | info->xmit.head = info->xmit.tail = 0; |
3752 | restore_flags(flags); | 3315 | local_irq_restore(flags); |
3753 | 3316 | ||
3754 | tty_wakeup(tty); | 3317 | tty_wakeup(tty); |
3755 | } | 3318 | } |
@@ -3767,7 +3330,7 @@ static void rs_send_xchar(struct tty_struct *tty, char ch) | |||
3767 | { | 3330 | { |
3768 | struct e100_serial *info = (struct e100_serial *)tty->driver_data; | 3331 | struct e100_serial *info = (struct e100_serial *)tty->driver_data; |
3769 | unsigned long flags; | 3332 | unsigned long flags; |
3770 | save_flags(flags); cli(); | 3333 | local_irq_save(flags); |
3771 | if (info->uses_dma_out) { | 3334 | if (info->uses_dma_out) { |
3772 | /* Put the DMA on hold and disable the channel */ | 3335 | /* Put the DMA on hold and disable the channel */ |
3773 | *info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, hold); | 3336 | *info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, hold); |
@@ -3784,7 +3347,7 @@ static void rs_send_xchar(struct tty_struct *tty, char ch) | |||
3784 | DFLOW(DEBUG_LOG(info->line, "rs_send_xchar 0x%02X\n", ch)); | 3347 | DFLOW(DEBUG_LOG(info->line, "rs_send_xchar 0x%02X\n", ch)); |
3785 | info->x_char = ch; | 3348 | info->x_char = ch; |
3786 | e100_enable_serial_tx_ready_irq(info); | 3349 | e100_enable_serial_tx_ready_irq(info); |
3787 | restore_flags(flags); | 3350 | local_irq_restore(flags); |
3788 | } | 3351 | } |
3789 | 3352 | ||
3790 | /* | 3353 | /* |
@@ -3996,21 +3559,61 @@ char *get_control_state_str(int MLines, char *s) | |||
3996 | } | 3559 | } |
3997 | #endif | 3560 | #endif |
3998 | 3561 | ||
3562 | static void | ||
3563 | rs_break(struct tty_struct *tty, int break_state) | ||
3564 | { | ||
3565 | struct e100_serial *info = (struct e100_serial *)tty->driver_data; | ||
3566 | unsigned long flags; | ||
3567 | |||
3568 | if (!info->port) | ||
3569 | return; | ||
3570 | |||
3571 | local_irq_save(flags); | ||
3572 | if (break_state == -1) { | ||
3573 | /* Go to manual mode and set the txd pin to 0 */ | ||
3574 | /* Clear bit 7 (txd) and 6 (tr_enable) */ | ||
3575 | info->tx_ctrl &= 0x3F; | ||
3576 | } else { | ||
3577 | /* Set bit 7 (txd) and 6 (tr_enable) */ | ||
3578 | info->tx_ctrl |= (0x80 | 0x40); | ||
3579 | } | ||
3580 | info->port[REG_TR_CTRL] = info->tx_ctrl; | ||
3581 | local_irq_restore(flags); | ||
3582 | } | ||
3583 | |||
3999 | static int | 3584 | static int |
4000 | get_modem_info(struct e100_serial * info, unsigned int *value) | 3585 | rs_tiocmset(struct tty_struct *tty, struct file *file, |
3586 | unsigned int set, unsigned int clear) | ||
4001 | { | 3587 | { |
4002 | unsigned int result; | 3588 | struct e100_serial *info = (struct e100_serial *)tty->driver_data; |
4003 | /* Polarity isn't verified */ | ||
4004 | #if 0 /*def SERIAL_DEBUG_IO */ | ||
4005 | 3589 | ||
4006 | printk("get_modem_info: RTS: %i DTR: %i CD: %i RI: %i DSR: %i CTS: %i\n", | 3590 | if (clear & TIOCM_RTS) |
4007 | E100_RTS_GET(info), | 3591 | e100_rts(info, 0); |
4008 | E100_DTR_GET(info), | 3592 | if (clear & TIOCM_DTR) |
4009 | E100_CD_GET(info), | 3593 | e100_dtr(info, 0); |
4010 | E100_RI_GET(info), | 3594 | /* Handle FEMALE behaviour */ |
4011 | E100_DSR_GET(info), | 3595 | if (clear & TIOCM_RI) |
4012 | E100_CTS_GET(info)); | 3596 | e100_ri_out(info, 0); |
4013 | #endif | 3597 | if (clear & TIOCM_CD) |
3598 | e100_cd_out(info, 0); | ||
3599 | |||
3600 | if (set & TIOCM_RTS) | ||
3601 | e100_rts(info, 1); | ||
3602 | if (set & TIOCM_DTR) | ||
3603 | e100_dtr(info, 1); | ||
3604 | /* Handle FEMALE behaviour */ | ||
3605 | if (set & TIOCM_RI) | ||
3606 | e100_ri_out(info, 1); | ||
3607 | if (set & TIOCM_CD) | ||
3608 | e100_cd_out(info, 1); | ||
3609 | return 0; | ||
3610 | } | ||
3611 | |||
3612 | static int | ||
3613 | rs_tiocmget(struct tty_struct *tty, struct file *file) | ||
3614 | { | ||
3615 | struct e100_serial *info = (struct e100_serial *)tty->driver_data; | ||
3616 | unsigned int result; | ||
4014 | 3617 | ||
4015 | result = | 3618 | result = |
4016 | (!E100_RTS_GET(info) ? TIOCM_RTS : 0) | 3619 | (!E100_RTS_GET(info) ? TIOCM_RTS : 0) |
@@ -4021,95 +3624,20 @@ get_modem_info(struct e100_serial * info, unsigned int *value) | |||
4021 | | (!E100_CTS_GET(info) ? TIOCM_CTS : 0); | 3624 | | (!E100_CTS_GET(info) ? TIOCM_CTS : 0); |
4022 | 3625 | ||
4023 | #ifdef SERIAL_DEBUG_IO | 3626 | #ifdef SERIAL_DEBUG_IO |
4024 | printk("e100ser: modem state: %i 0x%08X\n", result, result); | 3627 | printk(KERN_DEBUG "ser%i: modem state: %i 0x%08X\n", |
3628 | info->line, result, result); | ||
4025 | { | 3629 | { |
4026 | char s[100]; | 3630 | char s[100]; |
4027 | 3631 | ||
4028 | get_control_state_str(result, s); | 3632 | get_control_state_str(result, s); |
4029 | printk("state: %s\n", s); | 3633 | printk(KERN_DEBUG "state: %s\n", s); |
4030 | } | 3634 | } |
4031 | #endif | 3635 | #endif |
4032 | if (copy_to_user(value, &result, sizeof(int))) | 3636 | return result; |
4033 | return -EFAULT; | ||
4034 | return 0; | ||
4035 | } | ||
4036 | 3637 | ||
4037 | |||
4038 | static int | ||
4039 | set_modem_info(struct e100_serial * info, unsigned int cmd, | ||
4040 | unsigned int *value) | ||
4041 | { | ||
4042 | unsigned int arg; | ||
4043 | |||
4044 | if (copy_from_user(&arg, value, sizeof(int))) | ||
4045 | return -EFAULT; | ||
4046 | |||
4047 | switch (cmd) { | ||
4048 | case TIOCMBIS: | ||
4049 | if (arg & TIOCM_RTS) { | ||
4050 | e100_rts(info, 1); | ||
4051 | } | ||
4052 | if (arg & TIOCM_DTR) { | ||
4053 | e100_dtr(info, 1); | ||
4054 | } | ||
4055 | /* Handle FEMALE behaviour */ | ||
4056 | if (arg & TIOCM_RI) { | ||
4057 | e100_ri_out(info, 1); | ||
4058 | } | ||
4059 | if (arg & TIOCM_CD) { | ||
4060 | e100_cd_out(info, 1); | ||
4061 | } | ||
4062 | break; | ||
4063 | case TIOCMBIC: | ||
4064 | if (arg & TIOCM_RTS) { | ||
4065 | e100_rts(info, 0); | ||
4066 | } | ||
4067 | if (arg & TIOCM_DTR) { | ||
4068 | e100_dtr(info, 0); | ||
4069 | } | ||
4070 | /* Handle FEMALE behaviour */ | ||
4071 | if (arg & TIOCM_RI) { | ||
4072 | e100_ri_out(info, 0); | ||
4073 | } | ||
4074 | if (arg & TIOCM_CD) { | ||
4075 | e100_cd_out(info, 0); | ||
4076 | } | ||
4077 | break; | ||
4078 | case TIOCMSET: | ||
4079 | e100_rts(info, arg & TIOCM_RTS); | ||
4080 | e100_dtr(info, arg & TIOCM_DTR); | ||
4081 | /* Handle FEMALE behaviour */ | ||
4082 | e100_ri_out(info, arg & TIOCM_RI); | ||
4083 | e100_cd_out(info, arg & TIOCM_CD); | ||
4084 | break; | ||
4085 | default: | ||
4086 | return -EINVAL; | ||
4087 | } | ||
4088 | return 0; | ||
4089 | } | 3638 | } |
4090 | 3639 | ||
4091 | 3640 | ||
4092 | static void | ||
4093 | rs_break(struct tty_struct *tty, int break_state) | ||
4094 | { | ||
4095 | struct e100_serial * info = (struct e100_serial *)tty->driver_data; | ||
4096 | unsigned long flags; | ||
4097 | |||
4098 | if (!info->port) | ||
4099 | return; | ||
4100 | |||
4101 | save_flags(flags); | ||
4102 | cli(); | ||
4103 | if (break_state == -1) { | ||
4104 | /* Go to manual mode and set the txd pin to 0 */ | ||
4105 | info->tx_ctrl &= 0x3F; /* Clear bit 7 (txd) and 6 (tr_enable) */ | ||
4106 | } else { | ||
4107 | info->tx_ctrl |= (0x80 | 0x40); /* Set bit 7 (txd) and 6 (tr_enable) */ | ||
4108 | } | ||
4109 | info->port[REG_TR_CTRL] = info->tx_ctrl; | ||
4110 | restore_flags(flags); | ||
4111 | } | ||
4112 | |||
4113 | static int | 3641 | static int |
4114 | rs_ioctl(struct tty_struct *tty, struct file * file, | 3642 | rs_ioctl(struct tty_struct *tty, struct file * file, |
4115 | unsigned int cmd, unsigned long arg) | 3643 | unsigned int cmd, unsigned long arg) |
@@ -4124,49 +3652,45 @@ rs_ioctl(struct tty_struct *tty, struct file * file, | |||
4124 | } | 3652 | } |
4125 | 3653 | ||
4126 | switch (cmd) { | 3654 | switch (cmd) { |
4127 | case TIOCMGET: | 3655 | case TIOCGSERIAL: |
4128 | return get_modem_info(info, (unsigned int *) arg); | 3656 | return get_serial_info(info, |
4129 | case TIOCMBIS: | 3657 | (struct serial_struct *) arg); |
4130 | case TIOCMBIC: | 3658 | case TIOCSSERIAL: |
4131 | case TIOCMSET: | 3659 | return set_serial_info(info, |
4132 | return set_modem_info(info, cmd, (unsigned int *) arg); | 3660 | (struct serial_struct *) arg); |
4133 | case TIOCGSERIAL: | 3661 | case TIOCSERGETLSR: /* Get line status register */ |
4134 | return get_serial_info(info, | 3662 | return get_lsr_info(info, (unsigned int *) arg); |
4135 | (struct serial_struct *) arg); | 3663 | |
4136 | case TIOCSSERIAL: | 3664 | case TIOCSERGSTRUCT: |
4137 | return set_serial_info(info, | 3665 | if (copy_to_user((struct e100_serial *) arg, |
4138 | (struct serial_struct *) arg); | 3666 | info, sizeof(struct e100_serial))) |
4139 | case TIOCSERGETLSR: /* Get line status register */ | 3667 | return -EFAULT; |
4140 | return get_lsr_info(info, (unsigned int *) arg); | 3668 | return 0; |
4141 | |||
4142 | case TIOCSERGSTRUCT: | ||
4143 | if (copy_to_user((struct e100_serial *) arg, | ||
4144 | info, sizeof(struct e100_serial))) | ||
4145 | return -EFAULT; | ||
4146 | return 0; | ||
4147 | 3669 | ||
4148 | #if defined(CONFIG_ETRAX_RS485) | 3670 | #if defined(CONFIG_ETRAX_RS485) |
4149 | case TIOCSERSETRS485: | 3671 | case TIOCSERSETRS485: |
4150 | { | 3672 | { |
4151 | struct rs485_control rs485ctrl; | 3673 | struct rs485_control rs485ctrl; |
4152 | if (copy_from_user(&rs485ctrl, (struct rs485_control*)arg, sizeof(rs485ctrl))) | 3674 | if (copy_from_user(&rs485ctrl, (struct rs485_control *)arg, |
4153 | return -EFAULT; | 3675 | sizeof(rs485ctrl))) |
3676 | return -EFAULT; | ||
4154 | 3677 | ||
4155 | return e100_enable_rs485(tty, &rs485ctrl); | 3678 | return e100_enable_rs485(tty, &rs485ctrl); |
4156 | } | 3679 | } |
4157 | 3680 | ||
4158 | case TIOCSERWRRS485: | 3681 | case TIOCSERWRRS485: |
4159 | { | 3682 | { |
4160 | struct rs485_write rs485wr; | 3683 | struct rs485_write rs485wr; |
4161 | if (copy_from_user(&rs485wr, (struct rs485_write*)arg, sizeof(rs485wr))) | 3684 | if (copy_from_user(&rs485wr, (struct rs485_write *)arg, |
4162 | return -EFAULT; | 3685 | sizeof(rs485wr))) |
3686 | return -EFAULT; | ||
4163 | 3687 | ||
4164 | return e100_write_rs485(tty, 1, rs485wr.outc, rs485wr.outc_size); | 3688 | return e100_write_rs485(tty, rs485wr.outc, rs485wr.outc_size); |
4165 | } | 3689 | } |
4166 | #endif | 3690 | #endif |
4167 | 3691 | ||
4168 | default: | 3692 | default: |
4169 | return -ENOIOCTLCMD; | 3693 | return -ENOIOCTLCMD; |
4170 | } | 3694 | } |
4171 | return 0; | 3695 | return 0; |
4172 | } | 3696 | } |
@@ -4191,46 +3715,6 @@ rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) | |||
4191 | 3715 | ||
4192 | } | 3716 | } |
4193 | 3717 | ||
4194 | /* In debugport.c - register a console write function that uses the normal | ||
4195 | * serial driver | ||
4196 | */ | ||
4197 | typedef int (*debugport_write_function)(int i, const char *buf, unsigned int len); | ||
4198 | |||
4199 | extern debugport_write_function debug_write_function; | ||
4200 | |||
4201 | static int rs_debug_write_function(int i, const char *buf, unsigned int len) | ||
4202 | { | ||
4203 | int cnt; | ||
4204 | int written = 0; | ||
4205 | struct tty_struct *tty; | ||
4206 | static int recurse_cnt = 0; | ||
4207 | |||
4208 | tty = rs_table[i].tty; | ||
4209 | if (tty) { | ||
4210 | unsigned long flags; | ||
4211 | if (recurse_cnt > 5) /* We skip this debug output */ | ||
4212 | return 1; | ||
4213 | |||
4214 | local_irq_save(flags); | ||
4215 | recurse_cnt++; | ||
4216 | local_irq_restore(flags); | ||
4217 | do { | ||
4218 | cnt = rs_write(tty, 0, buf + written, len); | ||
4219 | if (cnt >= 0) { | ||
4220 | written += cnt; | ||
4221 | buf += cnt; | ||
4222 | len -= cnt; | ||
4223 | } else | ||
4224 | len = cnt; | ||
4225 | } while(len > 0); | ||
4226 | local_irq_save(flags); | ||
4227 | recurse_cnt--; | ||
4228 | local_irq_restore(flags); | ||
4229 | return 1; | ||
4230 | } | ||
4231 | return 0; | ||
4232 | } | ||
4233 | |||
4234 | /* | 3718 | /* |
4235 | * ------------------------------------------------------------ | 3719 | * ------------------------------------------------------------ |
4236 | * rs_close() | 3720 | * rs_close() |
@@ -4252,11 +3736,10 @@ rs_close(struct tty_struct *tty, struct file * filp) | |||
4252 | 3736 | ||
4253 | /* interrupts are disabled for this entire function */ | 3737 | /* interrupts are disabled for this entire function */ |
4254 | 3738 | ||
4255 | save_flags(flags); | 3739 | local_irq_save(flags); |
4256 | cli(); | ||
4257 | 3740 | ||
4258 | if (tty_hung_up_p(filp)) { | 3741 | if (tty_hung_up_p(filp)) { |
4259 | restore_flags(flags); | 3742 | local_irq_restore(flags); |
4260 | return; | 3743 | return; |
4261 | } | 3744 | } |
4262 | 3745 | ||
@@ -4283,7 +3766,7 @@ rs_close(struct tty_struct *tty, struct file * filp) | |||
4283 | info->count = 0; | 3766 | info->count = 0; |
4284 | } | 3767 | } |
4285 | if (info->count) { | 3768 | if (info->count) { |
4286 | restore_flags(flags); | 3769 | local_irq_restore(flags); |
4287 | return; | 3770 | return; |
4288 | } | 3771 | } |
4289 | info->flags |= ASYNC_CLOSING; | 3772 | info->flags |= ASYNC_CLOSING; |
@@ -4337,7 +3820,7 @@ rs_close(struct tty_struct *tty, struct file * filp) | |||
4337 | } | 3820 | } |
4338 | info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | 3821 | info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); |
4339 | wake_up_interruptible(&info->close_wait); | 3822 | wake_up_interruptible(&info->close_wait); |
4340 | restore_flags(flags); | 3823 | local_irq_restore(flags); |
4341 | 3824 | ||
4342 | /* port closed */ | 3825 | /* port closed */ |
4343 | 3826 | ||
@@ -4359,6 +3842,28 @@ rs_close(struct tty_struct *tty, struct file * filp) | |||
4359 | #endif | 3842 | #endif |
4360 | } | 3843 | } |
4361 | #endif | 3844 | #endif |
3845 | |||
3846 | /* | ||
3847 | * Release any allocated DMA irq's. | ||
3848 | */ | ||
3849 | if (info->dma_in_enabled) { | ||
3850 | free_irq(info->dma_in_irq_nbr, info); | ||
3851 | cris_free_dma(info->dma_in_nbr, info->dma_in_irq_description); | ||
3852 | info->uses_dma_in = 0; | ||
3853 | #ifdef SERIAL_DEBUG_OPEN | ||
3854 | printk(KERN_DEBUG "DMA irq '%s' freed\n", | ||
3855 | info->dma_in_irq_description); | ||
3856 | #endif | ||
3857 | } | ||
3858 | if (info->dma_out_enabled) { | ||
3859 | free_irq(info->dma_out_irq_nbr, info); | ||
3860 | cris_free_dma(info->dma_out_nbr, info->dma_out_irq_description); | ||
3861 | info->uses_dma_out = 0; | ||
3862 | #ifdef SERIAL_DEBUG_OPEN | ||
3863 | printk(KERN_DEBUG "DMA irq '%s' freed\n", | ||
3864 | info->dma_out_irq_description); | ||
3865 | #endif | ||
3866 | } | ||
4362 | } | 3867 | } |
4363 | 3868 | ||
4364 | /* | 3869 | /* |
@@ -4433,8 +3938,8 @@ block_til_ready(struct tty_struct *tty, struct file * filp, | |||
4433 | */ | 3938 | */ |
4434 | if (tty_hung_up_p(filp) || | 3939 | if (tty_hung_up_p(filp) || |
4435 | (info->flags & ASYNC_CLOSING)) { | 3940 | (info->flags & ASYNC_CLOSING)) { |
4436 | if (info->flags & ASYNC_CLOSING) | 3941 | wait_event_interruptible(info->close_wait, |
4437 | interruptible_sleep_on(&info->close_wait); | 3942 | !(info->flags & ASYNC_CLOSING)); |
4438 | #ifdef SERIAL_DO_RESTART | 3943 | #ifdef SERIAL_DO_RESTART |
4439 | if (info->flags & ASYNC_HUP_NOTIFY) | 3944 | if (info->flags & ASYNC_HUP_NOTIFY) |
4440 | return -EAGAIN; | 3945 | return -EAGAIN; |
@@ -4472,21 +3977,19 @@ block_til_ready(struct tty_struct *tty, struct file * filp, | |||
4472 | printk("block_til_ready before block: ttyS%d, count = %d\n", | 3977 | printk("block_til_ready before block: ttyS%d, count = %d\n", |
4473 | info->line, info->count); | 3978 | info->line, info->count); |
4474 | #endif | 3979 | #endif |
4475 | save_flags(flags); | 3980 | local_irq_save(flags); |
4476 | cli(); | ||
4477 | if (!tty_hung_up_p(filp)) { | 3981 | if (!tty_hung_up_p(filp)) { |
4478 | extra_count++; | 3982 | extra_count++; |
4479 | info->count--; | 3983 | info->count--; |
4480 | } | 3984 | } |
4481 | restore_flags(flags); | 3985 | local_irq_restore(flags); |
4482 | info->blocked_open++; | 3986 | info->blocked_open++; |
4483 | while (1) { | 3987 | while (1) { |
4484 | save_flags(flags); | 3988 | local_irq_save(flags); |
4485 | cli(); | ||
4486 | /* assert RTS and DTR */ | 3989 | /* assert RTS and DTR */ |
4487 | e100_rts(info, 1); | 3990 | e100_rts(info, 1); |
4488 | e100_dtr(info, 1); | 3991 | e100_dtr(info, 1); |
4489 | restore_flags(flags); | 3992 | local_irq_restore(flags); |
4490 | set_current_state(TASK_INTERRUPTIBLE); | 3993 | set_current_state(TASK_INTERRUPTIBLE); |
4491 | if (tty_hung_up_p(filp) || | 3994 | if (tty_hung_up_p(filp) || |
4492 | !(info->flags & ASYNC_INITIALIZED)) { | 3995 | !(info->flags & ASYNC_INITIALIZED)) { |
@@ -4528,6 +4031,19 @@ block_til_ready(struct tty_struct *tty, struct file * filp, | |||
4528 | return 0; | 4031 | return 0; |
4529 | } | 4032 | } |
4530 | 4033 | ||
4034 | static void | ||
4035 | deinit_port(struct e100_serial *info) | ||
4036 | { | ||
4037 | if (info->dma_out_enabled) { | ||
4038 | cris_free_dma(info->dma_out_nbr, info->dma_out_irq_description); | ||
4039 | free_irq(info->dma_out_irq_nbr, info); | ||
4040 | } | ||
4041 | if (info->dma_in_enabled) { | ||
4042 | cris_free_dma(info->dma_in_nbr, info->dma_in_irq_description); | ||
4043 | free_irq(info->dma_in_irq_nbr, info); | ||
4044 | } | ||
4045 | } | ||
4046 | |||
4531 | /* | 4047 | /* |
4532 | * This routine is called whenever a serial port is opened. | 4048 | * This routine is called whenever a serial port is opened. |
4533 | * It performs the serial-specific initialization for the tty structure. | 4049 | * It performs the serial-specific initialization for the tty structure. |
@@ -4538,9 +4054,9 @@ rs_open(struct tty_struct *tty, struct file * filp) | |||
4538 | struct e100_serial *info; | 4054 | struct e100_serial *info; |
4539 | int retval, line; | 4055 | int retval, line; |
4540 | unsigned long page; | 4056 | unsigned long page; |
4057 | int allocated_resources = 0; | ||
4541 | 4058 | ||
4542 | /* find which port we want to open */ | 4059 | /* find which port we want to open */ |
4543 | |||
4544 | line = tty->index; | 4060 | line = tty->index; |
4545 | 4061 | ||
4546 | if (line < 0 || line >= NR_PORTS) | 4062 | if (line < 0 || line >= NR_PORTS) |
@@ -4580,8 +4096,8 @@ rs_open(struct tty_struct *tty, struct file * filp) | |||
4580 | */ | 4096 | */ |
4581 | if (tty_hung_up_p(filp) || | 4097 | if (tty_hung_up_p(filp) || |
4582 | (info->flags & ASYNC_CLOSING)) { | 4098 | (info->flags & ASYNC_CLOSING)) { |
4583 | if (info->flags & ASYNC_CLOSING) | 4099 | wait_event_interruptible(info->close_wait, |
4584 | interruptible_sleep_on(&info->close_wait); | 4100 | !(info->flags & ASYNC_CLOSING)); |
4585 | #ifdef SERIAL_DO_RESTART | 4101 | #ifdef SERIAL_DO_RESTART |
4586 | return ((info->flags & ASYNC_HUP_NOTIFY) ? | 4102 | return ((info->flags & ASYNC_HUP_NOTIFY) ? |
4587 | -EAGAIN : -ERESTARTSYS); | 4103 | -EAGAIN : -ERESTARTSYS); |
@@ -4591,12 +4107,85 @@ rs_open(struct tty_struct *tty, struct file * filp) | |||
4591 | } | 4107 | } |
4592 | 4108 | ||
4593 | /* | 4109 | /* |
4110 | * If DMA is enabled try to allocate the irq's. | ||
4111 | */ | ||
4112 | if (info->count == 1) { | ||
4113 | allocated_resources = 1; | ||
4114 | if (info->dma_in_enabled) { | ||
4115 | if (request_irq(info->dma_in_irq_nbr, | ||
4116 | rec_interrupt, | ||
4117 | info->dma_in_irq_flags, | ||
4118 | info->dma_in_irq_description, | ||
4119 | info)) { | ||
4120 | printk(KERN_WARNING "DMA irq '%s' busy; " | ||
4121 | "falling back to non-DMA mode\n", | ||
4122 | info->dma_in_irq_description); | ||
4123 | /* Make sure we never try to use DMA in */ | ||
4124 | /* for the port again. */ | ||
4125 | info->dma_in_enabled = 0; | ||
4126 | } else if (cris_request_dma(info->dma_in_nbr, | ||
4127 | info->dma_in_irq_description, | ||
4128 | DMA_VERBOSE_ON_ERROR, | ||
4129 | info->dma_owner)) { | ||
4130 | free_irq(info->dma_in_irq_nbr, info); | ||
4131 | printk(KERN_WARNING "DMA '%s' busy; " | ||
4132 | "falling back to non-DMA mode\n", | ||
4133 | info->dma_in_irq_description); | ||
4134 | /* Make sure we never try to use DMA in */ | ||
4135 | /* for the port again. */ | ||
4136 | info->dma_in_enabled = 0; | ||
4137 | } | ||
4138 | #ifdef SERIAL_DEBUG_OPEN | ||
4139 | else | ||
4140 | printk(KERN_DEBUG "DMA irq '%s' allocated\n", | ||
4141 | info->dma_in_irq_description); | ||
4142 | #endif | ||
4143 | } | ||
4144 | if (info->dma_out_enabled) { | ||
4145 | if (request_irq(info->dma_out_irq_nbr, | ||
4146 | tr_interrupt, | ||
4147 | info->dma_out_irq_flags, | ||
4148 | info->dma_out_irq_description, | ||
4149 | info)) { | ||
4150 | printk(KERN_WARNING "DMA irq '%s' busy; " | ||
4151 | "falling back to non-DMA mode\n", | ||
4152 | info->dma_out_irq_description); | ||
4153 | /* Make sure we never try to use DMA out */ | ||
4154 | /* for the port again. */ | ||
4155 | info->dma_out_enabled = 0; | ||
4156 | } else if (cris_request_dma(info->dma_out_nbr, | ||
4157 | info->dma_out_irq_description, | ||
4158 | DMA_VERBOSE_ON_ERROR, | ||
4159 | info->dma_owner)) { | ||
4160 | free_irq(info->dma_out_irq_nbr, info); | ||
4161 | printk(KERN_WARNING "DMA '%s' busy; " | ||
4162 | "falling back to non-DMA mode\n", | ||
4163 | info->dma_out_irq_description); | ||
4164 | /* Make sure we never try to use DMA out */ | ||
4165 | /* for the port again. */ | ||
4166 | info->dma_out_enabled = 0; | ||
4167 | } | ||
4168 | #ifdef SERIAL_DEBUG_OPEN | ||
4169 | else | ||
4170 | printk(KERN_DEBUG "DMA irq '%s' allocated\n", | ||
4171 | info->dma_out_irq_description); | ||
4172 | #endif | ||
4173 | } | ||
4174 | } | ||
4175 | |||
4176 | /* | ||
4594 | * Start up the serial port | 4177 | * Start up the serial port |
4595 | */ | 4178 | */ |
4596 | 4179 | ||
4597 | retval = startup(info); | 4180 | retval = startup(info); |
4598 | if (retval) | 4181 | if (retval) { |
4182 | if (allocated_resources) | ||
4183 | deinit_port(info); | ||
4184 | |||
4185 | /* FIXME Decrease count info->count here too? */ | ||
4599 | return retval; | 4186 | return retval; |
4187 | } | ||
4188 | |||
4600 | 4189 | ||
4601 | retval = block_til_ready(tty, filp, info); | 4190 | retval = block_til_ready(tty, filp, info); |
4602 | if (retval) { | 4191 | if (retval) { |
@@ -4604,6 +4193,9 @@ rs_open(struct tty_struct *tty, struct file * filp) | |||
4604 | printk("rs_open returning after block_til_ready with %d\n", | 4193 | printk("rs_open returning after block_til_ready with %d\n", |
4605 | retval); | 4194 | retval); |
4606 | #endif | 4195 | #endif |
4196 | if (allocated_resources) | ||
4197 | deinit_port(info); | ||
4198 | |||
4607 | return retval; | 4199 | return retval; |
4608 | } | 4200 | } |
4609 | 4201 | ||
@@ -4793,6 +4385,8 @@ static const struct tty_operations rs_ops = { | |||
4793 | .send_xchar = rs_send_xchar, | 4385 | .send_xchar = rs_send_xchar, |
4794 | .wait_until_sent = rs_wait_until_sent, | 4386 | .wait_until_sent = rs_wait_until_sent, |
4795 | .read_proc = rs_read_proc, | 4387 | .read_proc = rs_read_proc, |
4388 | .tiocmget = rs_tiocmget, | ||
4389 | .tiocmset = rs_tiocmset | ||
4796 | }; | 4390 | }; |
4797 | 4391 | ||
4798 | static int __init | 4392 | static int __init |
@@ -4810,9 +4404,27 @@ rs_init(void) | |||
4810 | /* Setup the timed flush handler system */ | 4404 | /* Setup the timed flush handler system */ |
4811 | 4405 | ||
4812 | #if !defined(CONFIG_ETRAX_SERIAL_FAST_TIMER) | 4406 | #if !defined(CONFIG_ETRAX_SERIAL_FAST_TIMER) |
4813 | init_timer(&flush_timer); | 4407 | setup_timer(&flush_timer, timed_flush_handler, 0); |
4814 | flush_timer.function = timed_flush_handler; | 4408 | mod_timer(&flush_timer, jiffies + 5); |
4815 | mod_timer(&flush_timer, jiffies + CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS); | 4409 | #endif |
4410 | |||
4411 | #if defined(CONFIG_ETRAX_RS485) | ||
4412 | #if defined(CONFIG_ETRAX_RS485_ON_PA) | ||
4413 | if (cris_io_interface_allocate_pins(if_ser0, 'a', rs485_pa_bit, | ||
4414 | rs485_pa_bit)) { | ||
4415 | printk(KERN_CRIT "ETRAX100LX serial: Could not allocate " | ||
4416 | "RS485 pin\n"); | ||
4417 | return -EBUSY; | ||
4418 | } | ||
4419 | #endif | ||
4420 | #if defined(CONFIG_ETRAX_RS485_ON_PORT_G) | ||
4421 | if (cris_io_interface_allocate_pins(if_ser0, 'g', rs485_pa_bit, | ||
4422 | rs485_port_g_bit)) { | ||
4423 | printk(KERN_CRIT "ETRAX100LX serial: Could not allocate " | ||
4424 | "RS485 pin\n"); | ||
4425 | return -EBUSY; | ||
4426 | } | ||
4427 | #endif | ||
4816 | #endif | 4428 | #endif |
4817 | 4429 | ||
4818 | /* Initialize the tty_driver structure */ | 4430 | /* Initialize the tty_driver structure */ |
@@ -4839,6 +4451,16 @@ rs_init(void) | |||
4839 | /* do some initializing for the separate ports */ | 4451 | /* do some initializing for the separate ports */ |
4840 | 4452 | ||
4841 | for (i = 0, info = rs_table; i < NR_PORTS; i++,info++) { | 4453 | for (i = 0, info = rs_table; i < NR_PORTS; i++,info++) { |
4454 | if (info->enabled) { | ||
4455 | if (cris_request_io_interface(info->io_if, | ||
4456 | info->io_if_description)) { | ||
4457 | printk(KERN_CRIT "ETRAX100LX async serial: " | ||
4458 | "Could not allocate IO pins for " | ||
4459 | "%s, port %d\n", | ||
4460 | info->io_if_description, i); | ||
4461 | info->enabled = 0; | ||
4462 | } | ||
4463 | } | ||
4842 | info->uses_dma_in = 0; | 4464 | info->uses_dma_in = 0; |
4843 | info->uses_dma_out = 0; | 4465 | info->uses_dma_out = 0; |
4844 | info->line = i; | 4466 | info->line = i; |
@@ -4872,7 +4494,7 @@ rs_init(void) | |||
4872 | info->rs485.delay_rts_before_send = 0; | 4494 | info->rs485.delay_rts_before_send = 0; |
4873 | info->rs485.enabled = 0; | 4495 | info->rs485.enabled = 0; |
4874 | #endif | 4496 | #endif |
4875 | INIT_WORK(&info->work, do_softint, info); | 4497 | INIT_WORK(&info->work, do_softint); |
4876 | 4498 | ||
4877 | if (info->enabled) { | 4499 | if (info->enabled) { |
4878 | printk(KERN_INFO "%s%d at 0x%x is a builtin UART with DMA\n", | 4500 | printk(KERN_INFO "%s%d at 0x%x is a builtin UART with DMA\n", |
@@ -4890,64 +4512,17 @@ rs_init(void) | |||
4890 | #endif | 4512 | #endif |
4891 | 4513 | ||
4892 | #ifndef CONFIG_SVINTO_SIM | 4514 | #ifndef CONFIG_SVINTO_SIM |
4515 | #ifndef CONFIG_ETRAX_KGDB | ||
4893 | /* Not needed in simulator. May only complicate stuff. */ | 4516 | /* Not needed in simulator. May only complicate stuff. */ |
4894 | /* hook the irq's for DMA channel 6 and 7, serial output and input, and some more... */ | 4517 | /* hook the irq's for DMA channel 6 and 7, serial output and input, and some more... */ |
4895 | 4518 | ||
4896 | if (request_irq(SERIAL_IRQ_NBR, ser_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial ", NULL)) | 4519 | if (request_irq(SERIAL_IRQ_NBR, ser_interrupt, |
4897 | panic("irq8"); | 4520 | IRQF_SHARED | IRQF_DISABLED, "serial ", driver)) |
4898 | 4521 | panic("%s: Failed to request irq8", __FUNCTION__); | |
4899 | #ifdef CONFIG_ETRAX_SERIAL_PORT0 | ||
4900 | #ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT | ||
4901 | if (request_irq(SER0_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_DISABLED, "serial 0 dma tr", NULL)) | ||
4902 | panic("irq22"); | ||
4903 | #endif | ||
4904 | #ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN | ||
4905 | if (request_irq(SER0_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_DISABLED, "serial 0 dma rec", NULL)) | ||
4906 | panic("irq23"); | ||
4907 | #endif | ||
4908 | #endif | ||
4909 | |||
4910 | #ifdef CONFIG_ETRAX_SERIAL_PORT1 | ||
4911 | #ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA8_OUT | ||
4912 | if (request_irq(SER1_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_DISABLED, "serial 1 dma tr", NULL)) | ||
4913 | panic("irq24"); | ||
4914 | #endif | ||
4915 | #ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA9_IN | ||
4916 | if (request_irq(SER1_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_DISABLED, "serial 1 dma rec", NULL)) | ||
4917 | panic("irq25"); | ||
4918 | #endif | ||
4919 | #endif | ||
4920 | #ifdef CONFIG_ETRAX_SERIAL_PORT2 | ||
4921 | /* DMA Shared with par0 (and SCSI0 and ATA) */ | ||
4922 | #ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT | ||
4923 | if (request_irq(SER2_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 2 dma tr", NULL)) | ||
4924 | panic("irq18"); | ||
4925 | #endif | ||
4926 | #ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN | ||
4927 | if (request_irq(SER2_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 2 dma rec", NULL)) | ||
4928 | panic("irq19"); | ||
4929 | #endif | ||
4930 | #endif | ||
4931 | #ifdef CONFIG_ETRAX_SERIAL_PORT3 | ||
4932 | /* DMA Shared with par1 (and SCSI1 and Extern DMA 0) */ | ||
4933 | #ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA4_OUT | ||
4934 | if (request_irq(SER3_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 3 dma tr", NULL)) | ||
4935 | panic("irq20"); | ||
4936 | #endif | ||
4937 | #ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA5_IN | ||
4938 | if (request_irq(SER3_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 3 dma rec", NULL)) | ||
4939 | panic("irq21"); | ||
4940 | #endif | ||
4941 | #endif | ||
4942 | 4522 | ||
4943 | #ifdef CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST | ||
4944 | if (request_irq(TIMER1_IRQ_NBR, timeout_interrupt, IRQF_SHARED | IRQF_DISABLED, | ||
4945 | "fast serial dma timeout", NULL)) { | ||
4946 | printk(KERN_CRIT "err: timer1 irq\n"); | ||
4947 | } | ||
4948 | #endif | 4523 | #endif |
4949 | #endif /* CONFIG_SVINTO_SIM */ | 4524 | #endif /* CONFIG_SVINTO_SIM */ |
4950 | debug_write_function = rs_debug_write_function; | 4525 | |
4951 | return 0; | 4526 | return 0; |
4952 | } | 4527 | } |
4953 | 4528 | ||
diff --git a/drivers/serial/crisv10.h b/drivers/serial/crisv10.h new file mode 100644 index 000000000000..ccd0f32b7372 --- /dev/null +++ b/drivers/serial/crisv10.h | |||
@@ -0,0 +1,146 @@ | |||
1 | /* | ||
2 | * serial.h: Arch-dep definitions for the Etrax100 serial driver. | ||
3 | * | ||
4 | * Copyright (C) 1998-2007 Axis Communications AB | ||
5 | */ | ||
6 | |||
7 | #ifndef _ETRAX_SERIAL_H | ||
8 | #define _ETRAX_SERIAL_H | ||
9 | |||
10 | #include <linux/circ_buf.h> | ||
11 | #include <asm/termios.h> | ||
12 | #include <asm/dma.h> | ||
13 | #include <asm/arch/io_interface_mux.h> | ||
14 | |||
15 | /* Software state per channel */ | ||
16 | |||
17 | #ifdef __KERNEL__ | ||
18 | /* | ||
19 | * This is our internal structure for each serial port's state. | ||
20 | * | ||
21 | * Many fields are paralleled by the structure used by the serial_struct | ||
22 | * structure. | ||
23 | * | ||
24 | * For definitions of the flags field, see tty.h | ||
25 | */ | ||
26 | |||
27 | #define SERIAL_RECV_DESCRIPTORS 8 | ||
28 | |||
29 | struct etrax_recv_buffer { | ||
30 | struct etrax_recv_buffer *next; | ||
31 | unsigned short length; | ||
32 | unsigned char error; | ||
33 | unsigned char pad; | ||
34 | |||
35 | unsigned char buffer[0]; | ||
36 | }; | ||
37 | |||
38 | struct e100_serial { | ||
39 | int baud; | ||
40 | volatile u8 *port; /* R_SERIALx_CTRL */ | ||
41 | u32 irq; /* bitnr in R_IRQ_MASK2 for dmaX_descr */ | ||
42 | |||
43 | /* Output registers */ | ||
44 | volatile u8 *oclrintradr; /* adr to R_DMA_CHx_CLR_INTR */ | ||
45 | volatile u32 *ofirstadr; /* adr to R_DMA_CHx_FIRST */ | ||
46 | volatile u8 *ocmdadr; /* adr to R_DMA_CHx_CMD */ | ||
47 | const volatile u8 *ostatusadr; /* adr to R_DMA_CHx_STATUS */ | ||
48 | |||
49 | /* Input registers */ | ||
50 | volatile u8 *iclrintradr; /* adr to R_DMA_CHx_CLR_INTR */ | ||
51 | volatile u32 *ifirstadr; /* adr to R_DMA_CHx_FIRST */ | ||
52 | volatile u8 *icmdadr; /* adr to R_DMA_CHx_CMD */ | ||
53 | volatile u32 *idescradr; /* adr to R_DMA_CHx_DESCR */ | ||
54 | |||
55 | int flags; /* defined in tty.h */ | ||
56 | |||
57 | u8 rx_ctrl; /* shadow for R_SERIALx_REC_CTRL */ | ||
58 | u8 tx_ctrl; /* shadow for R_SERIALx_TR_CTRL */ | ||
59 | u8 iseteop; /* bit number for R_SET_EOP for the input dma */ | ||
60 | int enabled; /* Set to 1 if the port is enabled in HW config */ | ||
61 | |||
62 | u8 dma_out_enabled; /* Set to 1 if DMA should be used */ | ||
63 | u8 dma_in_enabled; /* Set to 1 if DMA should be used */ | ||
64 | |||
65 | /* end of fields defined in rs_table[] in .c-file */ | ||
66 | int dma_owner; | ||
67 | unsigned int dma_in_nbr; | ||
68 | unsigned int dma_out_nbr; | ||
69 | unsigned int dma_in_irq_nbr; | ||
70 | unsigned int dma_out_irq_nbr; | ||
71 | unsigned long dma_in_irq_flags; | ||
72 | unsigned long dma_out_irq_flags; | ||
73 | char *dma_in_irq_description; | ||
74 | char *dma_out_irq_description; | ||
75 | |||
76 | enum cris_io_interface io_if; | ||
77 | char *io_if_description; | ||
78 | |||
79 | u8 uses_dma_in; /* Set to 1 if DMA is used */ | ||
80 | u8 uses_dma_out; /* Set to 1 if DMA is used */ | ||
81 | u8 forced_eop; /* a fifo eop has been forced */ | ||
82 | int baud_base; /* For special baudrates */ | ||
83 | int custom_divisor; /* For special baudrates */ | ||
84 | struct etrax_dma_descr tr_descr; | ||
85 | struct etrax_dma_descr rec_descr[SERIAL_RECV_DESCRIPTORS]; | ||
86 | int cur_rec_descr; | ||
87 | |||
88 | volatile int tr_running; /* 1 if output is running */ | ||
89 | |||
90 | struct tty_struct *tty; | ||
91 | int read_status_mask; | ||
92 | int ignore_status_mask; | ||
93 | int x_char; /* xon/xoff character */ | ||
94 | int close_delay; | ||
95 | unsigned short closing_wait; | ||
96 | unsigned short closing_wait2; | ||
97 | unsigned long event; | ||
98 | unsigned long last_active; | ||
99 | int line; | ||
100 | int type; /* PORT_ETRAX */ | ||
101 | int count; /* # of fd on device */ | ||
102 | int blocked_open; /* # of blocked opens */ | ||
103 | struct circ_buf xmit; | ||
104 | struct etrax_recv_buffer *first_recv_buffer; | ||
105 | struct etrax_recv_buffer *last_recv_buffer; | ||
106 | unsigned int recv_cnt; | ||
107 | unsigned int max_recv_cnt; | ||
108 | |||
109 | struct work_struct work; | ||
110 | struct async_icount icount; /* error-statistics etc.*/ | ||
111 | struct ktermios normal_termios; | ||
112 | struct ktermios callout_termios; | ||
113 | wait_queue_head_t open_wait; | ||
114 | wait_queue_head_t close_wait; | ||
115 | |||
116 | unsigned long char_time_usec; /* The time for 1 char, in usecs */ | ||
117 | unsigned long flush_time_usec; /* How often we should flush */ | ||
118 | unsigned long last_tx_active_usec; /* Last tx usec in the jiffies */ | ||
119 | unsigned long last_tx_active; /* Last tx time in jiffies */ | ||
120 | unsigned long last_rx_active_usec; /* Last rx usec in the jiffies */ | ||
121 | unsigned long last_rx_active; /* Last rx time in jiffies */ | ||
122 | |||
123 | int break_detected_cnt; | ||
124 | int errorcode; | ||
125 | |||
126 | #ifdef CONFIG_ETRAX_RS485 | ||
127 | struct rs485_control rs485; /* RS-485 support */ | ||
128 | #endif | ||
129 | }; | ||
130 | |||
131 | /* this PORT is not in the standard serial.h. it's not actually used for | ||
132 | * anything since we only have one type of async serial-port anyway in this | ||
133 | * system. | ||
134 | */ | ||
135 | |||
136 | #define PORT_ETRAX 1 | ||
137 | |||
138 | /* | ||
139 | * Events are used to schedule things to happen at timer-interrupt | ||
140 | * time, instead of at rs interrupt time. | ||
141 | */ | ||
142 | #define RS_EVENT_WRITE_WAKEUP 0 | ||
143 | |||
144 | #endif /* __KERNEL__ */ | ||
145 | |||
146 | #endif /* !_ETRAX_SERIAL_H */ | ||