diff options
Diffstat (limited to 'drivers/serial/crisv10.c')
| -rw-r--r-- | drivers/serial/crisv10.c | 1293 |
1 files changed, 434 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 | ||
