aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/char/n_r3964.c2097
1 files changed, 981 insertions, 1116 deletions
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
index dc6d41841457..fab1b7d42858 100644
--- a/drivers/char/n_r3964.c
+++ b/drivers/char/n_r3964.c
@@ -60,62 +60,56 @@
60#include <linux/slab.h> 60#include <linux/slab.h>
61#include <linux/tty.h> 61#include <linux/tty.h>
62#include <linux/errno.h> 62#include <linux/errno.h>
63#include <linux/string.h> /* used in new tty drivers */ 63#include <linux/string.h> /* used in new tty drivers */
64#include <linux/signal.h> /* used in new tty drivers */ 64#include <linux/signal.h> /* used in new tty drivers */
65#include <linux/ioctl.h> 65#include <linux/ioctl.h>
66#include <linux/n_r3964.h> 66#include <linux/n_r3964.h>
67#include <linux/poll.h> 67#include <linux/poll.h>
68#include <linux/init.h> 68#include <linux/init.h>
69#include <asm/uaccess.h> 69#include <asm/uaccess.h>
70 70
71 71/*#define DEBUG_QUEUE*/
72//#define DEBUG_QUEUE
73 72
74/* Log successful handshake and protocol operations */ 73/* Log successful handshake and protocol operations */
75//#define DEBUG_PROTO_S 74/*#define DEBUG_PROTO_S*/
76 75
77/* Log handshake and protocol errors: */ 76/* Log handshake and protocol errors: */
78//#define DEBUG_PROTO_E 77/*#define DEBUG_PROTO_E*/
79 78
80/* Log Linediscipline operations (open, close, read, write...): */ 79/* Log Linediscipline operations (open, close, read, write...): */
81//#define DEBUG_LDISC 80/*#define DEBUG_LDISC*/
82 81
83/* Log module and memory operations (init, cleanup; kmalloc, kfree): */ 82/* Log module and memory operations (init, cleanup; kmalloc, kfree): */
84//#define DEBUG_MODUL 83/*#define DEBUG_MODUL*/
85 84
86/* Macro helpers for debug output: */ 85/* Macro helpers for debug output: */
87#define TRACE(format, args...) printk("r3964: " format "\n" , ## args); 86#define TRACE(format, args...) printk("r3964: " format "\n" , ## args)
88 87
89#ifdef DEBUG_MODUL 88#ifdef DEBUG_MODUL
90#define TRACE_M(format, args...) printk("r3964: " format "\n" , ## args); 89#define TRACE_M(format, args...) printk("r3964: " format "\n" , ## args)
91#else 90#else
92#define TRACE_M(fmt, arg...) /**/ 91#define TRACE_M(fmt, arg...) do {} while (0)
93#endif 92#endif
94
95#ifdef DEBUG_PROTO_S 93#ifdef DEBUG_PROTO_S
96#define TRACE_PS(format, args...) printk("r3964: " format "\n" , ## args); 94#define TRACE_PS(format, args...) printk("r3964: " format "\n" , ## args)
97#else 95#else
98#define TRACE_PS(fmt, arg...) /**/ 96#define TRACE_PS(fmt, arg...) do {} while (0)
99#endif 97#endif
100
101#ifdef DEBUG_PROTO_E 98#ifdef DEBUG_PROTO_E
102#define TRACE_PE(format, args...) printk("r3964: " format "\n" , ## args); 99#define TRACE_PE(format, args...) printk("r3964: " format "\n" , ## args)
103#else 100#else
104#define TRACE_PE(fmt, arg...) /**/ 101#define TRACE_PE(fmt, arg...) do {} while (0)
105#endif 102#endif
106
107#ifdef DEBUG_LDISC 103#ifdef DEBUG_LDISC
108#define TRACE_L(format, args...) printk("r3964: " format "\n" , ## args); 104#define TRACE_L(format, args...) printk("r3964: " format "\n" , ## args)
109#else 105#else
110#define TRACE_L(fmt, arg...) /**/ 106#define TRACE_L(fmt, arg...) do {} while (0)
111#endif 107#endif
112
113#ifdef DEBUG_QUEUE 108#ifdef DEBUG_QUEUE
114#define TRACE_Q(format, args...) printk("r3964: " format "\n" , ## args); 109#define TRACE_Q(format, args...) printk("r3964: " format "\n" , ## args)
115#else 110#else
116#define TRACE_Q(fmt, arg...) /**/ 111#define TRACE_Q(fmt, arg...) do {} while (0)
117#endif 112#endif
118
119static void add_tx_queue(struct r3964_info *, struct r3964_block_header *); 113static void add_tx_queue(struct r3964_info *, struct r3964_block_header *);
120static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code); 114static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code);
121static void put_char(struct r3964_info *pInfo, unsigned char ch); 115static void put_char(struct r3964_info *pInfo, unsigned char ch);
@@ -126,937 +120,830 @@ static void receive_char(struct r3964_info *pInfo, const unsigned char c);
126static void receive_error(struct r3964_info *pInfo, const char flag); 120static void receive_error(struct r3964_info *pInfo, const char flag);
127static void on_timeout(unsigned long priv); 121static void on_timeout(unsigned long priv);
128static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg); 122static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg);
129static int read_telegram(struct r3964_info *pInfo, struct pid *pid, unsigned char __user *buf); 123static int read_telegram(struct r3964_info *pInfo, struct pid *pid,
124 unsigned char __user * buf);
130static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg, 125static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg,
131 int error_code, struct r3964_block_header *pBlock); 126 int error_code, struct r3964_block_header *pBlock);
132static struct r3964_message* remove_msg(struct r3964_info *pInfo, 127static struct r3964_message *remove_msg(struct r3964_info *pInfo,
133 struct r3964_client_info *pClient); 128 struct r3964_client_info *pClient);
134static void remove_client_block(struct r3964_info *pInfo, 129static void remove_client_block(struct r3964_info *pInfo,
135 struct r3964_client_info *pClient); 130 struct r3964_client_info *pClient);
136 131
137static int r3964_open(struct tty_struct *tty); 132static int r3964_open(struct tty_struct *tty);
138static void r3964_close(struct tty_struct *tty); 133static void r3964_close(struct tty_struct *tty);
139static ssize_t r3964_read(struct tty_struct *tty, struct file *file, 134static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
140 unsigned char __user *buf, size_t nr); 135 unsigned char __user * buf, size_t nr);
141static ssize_t r3964_write(struct tty_struct * tty, struct file * file, 136static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
142 const unsigned char * buf, size_t nr); 137 const unsigned char *buf, size_t nr);
143static int r3964_ioctl(struct tty_struct * tty, struct file * file, 138static int r3964_ioctl(struct tty_struct *tty, struct file *file,
144 unsigned int cmd, unsigned long arg); 139 unsigned int cmd, unsigned long arg);
145static void r3964_set_termios(struct tty_struct *tty, struct ktermios * old); 140static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old);
146static unsigned int r3964_poll(struct tty_struct * tty, struct file * file, 141static unsigned int r3964_poll(struct tty_struct *tty, struct file *file,
147 struct poll_table_struct *wait); 142 struct poll_table_struct *wait);
148static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, 143static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
149 char *fp, int count); 144 char *fp, int count);
150 145
151static struct tty_ldisc tty_ldisc_N_R3964 = { 146static struct tty_ldisc tty_ldisc_N_R3964 = {
152 .owner = THIS_MODULE, 147 .owner = THIS_MODULE,
153 .magic = TTY_LDISC_MAGIC, 148 .magic = TTY_LDISC_MAGIC,
154 .name = "R3964", 149 .name = "R3964",
155 .open = r3964_open, 150 .open = r3964_open,
156 .close = r3964_close, 151 .close = r3964_close,
157 .read = r3964_read, 152 .read = r3964_read,
158 .write = r3964_write, 153 .write = r3964_write,
159 .ioctl = r3964_ioctl, 154 .ioctl = r3964_ioctl,
160 .set_termios = r3964_set_termios, 155 .set_termios = r3964_set_termios,
161 .poll = r3964_poll, 156 .poll = r3964_poll,
162 .receive_buf = r3964_receive_buf, 157 .receive_buf = r3964_receive_buf,
163}; 158};
164 159
165
166
167static void dump_block(const unsigned char *block, unsigned int length) 160static void dump_block(const unsigned char *block, unsigned int length)
168{ 161{
169 unsigned int i,j; 162 unsigned int i, j;
170 char linebuf[16*3+1]; 163 char linebuf[16 * 3 + 1];
171 164
172 for(i=0;i<length;i+=16) 165 for (i = 0; i < length; i += 16) {
173 { 166 for (j = 0; (j < 16) && (j + i < length); j++) {
174 for(j=0;(j<16) && (j+i<length);j++) 167 sprintf(linebuf + 3 * j, "%02x ", block[i + j]);
175 { 168 }
176 sprintf(linebuf+3*j,"%02x ",block[i+j]); 169 linebuf[3 * j] = '\0';
177 } 170 TRACE_PS("%s", linebuf);
178 linebuf[3*j]='\0'; 171 }
179 TRACE_PS("%s",linebuf);
180 }
181} 172}
182 173
183
184
185
186/************************************************************* 174/*************************************************************
187 * Driver initialisation 175 * Driver initialisation
188 *************************************************************/ 176 *************************************************************/
189 177
190
191/************************************************************* 178/*************************************************************
192 * Module support routines 179 * Module support routines
193 *************************************************************/ 180 *************************************************************/
194 181
195static void __exit r3964_exit(void) 182static void __exit r3964_exit(void)
196{ 183{
197 int status; 184 int status;
198 185
199 TRACE_M ("cleanup_module()"); 186 TRACE_M("cleanup_module()");
200 187
201 status=tty_unregister_ldisc(N_R3964); 188 status = tty_unregister_ldisc(N_R3964);
202 189
203 if(status!=0) 190 if (status != 0) {
204 { 191 printk(KERN_ERR "r3964: error unregistering linediscipline: "
205 printk(KERN_ERR "r3964: error unregistering linediscipline: %d\n", status); 192 "%d\n", status);
206 } 193 } else {
207 else 194 TRACE_L("linediscipline successfully unregistered");
208 { 195 }
209 TRACE_L("linediscipline successfully unregistered");
210 }
211
212} 196}
213 197
214static int __init r3964_init(void) 198static int __init r3964_init(void)
215{ 199{
216 int status; 200 int status;
217 201
218 printk ("r3964: Philips r3964 Driver $Revision: 1.10 $\n"); 202 printk("r3964: Philips r3964 Driver $Revision: 1.10 $\n");
219 203
220 /* 204 /*
221 * Register the tty line discipline 205 * Register the tty line discipline
222 */ 206 */
223 207
224 status = tty_register_ldisc (N_R3964, &tty_ldisc_N_R3964); 208 status = tty_register_ldisc(N_R3964, &tty_ldisc_N_R3964);
225 if (status == 0) 209 if (status == 0) {
226 { 210 TRACE_L("line discipline %d registered", N_R3964);
227 TRACE_L("line discipline %d registered", N_R3964); 211 TRACE_L("flags=%x num=%x", tty_ldisc_N_R3964.flags,
228 TRACE_L("flags=%x num=%x", tty_ldisc_N_R3964.flags, 212 tty_ldisc_N_R3964.num);
229 tty_ldisc_N_R3964.num); 213 TRACE_L("open=%p", tty_ldisc_N_R3964.open);
230 TRACE_L("open=%p", tty_ldisc_N_R3964.open); 214 TRACE_L("tty_ldisc_N_R3964 = %p", &tty_ldisc_N_R3964);
231 TRACE_L("tty_ldisc_N_R3964 = %p", &tty_ldisc_N_R3964); 215 } else {
232 } 216 printk(KERN_ERR "r3964: error registering line discipline: "
233 else 217 "%d\n", status);
234 { 218 }
235 printk (KERN_ERR "r3964: error registering line discipline: %d\n", status); 219 return status;
236 }
237 return status;
238} 220}
239 221
240module_init(r3964_init); 222module_init(r3964_init);
241module_exit(r3964_exit); 223module_exit(r3964_exit);
242 224
243
244/************************************************************* 225/*************************************************************
245 * Protocol implementation routines 226 * Protocol implementation routines
246 *************************************************************/ 227 *************************************************************/
247 228
248static void add_tx_queue(struct r3964_info *pInfo, struct r3964_block_header *pHeader) 229static void add_tx_queue(struct r3964_info *pInfo,
230 struct r3964_block_header *pHeader)
249{ 231{
250 unsigned long flags; 232 unsigned long flags;
251 233
252 spin_lock_irqsave(&pInfo->lock, flags); 234 spin_lock_irqsave(&pInfo->lock, flags);
253 235
254 pHeader->next = NULL; 236 pHeader->next = NULL;
255 237
256 if(pInfo->tx_last == NULL) 238 if (pInfo->tx_last == NULL) {
257 { 239 pInfo->tx_first = pInfo->tx_last = pHeader;
258 pInfo->tx_first = pInfo->tx_last = pHeader; 240 } else {
259 } 241 pInfo->tx_last->next = pHeader;
260 else 242 pInfo->tx_last = pHeader;
261 { 243 }
262 pInfo->tx_last->next = pHeader; 244
263 pInfo->tx_last = pHeader; 245 spin_unlock_irqrestore(&pInfo->lock, flags);
264 } 246
265 247 TRACE_Q("add_tx_queue %p, length %d, tx_first = %p",
266 spin_unlock_irqrestore(&pInfo->lock, flags); 248 pHeader, pHeader->length, pInfo->tx_first);
267
268 TRACE_Q("add_tx_queue %p, length %d, tx_first = %p",
269 pHeader, pHeader->length, pInfo->tx_first );
270} 249}
271 250
272static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code) 251static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code)
273{ 252{
274 struct r3964_block_header *pHeader; 253 struct r3964_block_header *pHeader;
275 unsigned long flags; 254 unsigned long flags;
276#ifdef DEBUG_QUEUE 255#ifdef DEBUG_QUEUE
277 struct r3964_block_header *pDump; 256 struct r3964_block_header *pDump;
278#endif 257#endif
279
280 pHeader = pInfo->tx_first;
281 258
282 if(pHeader==NULL) 259 pHeader = pInfo->tx_first;
283 return; 260
261 if (pHeader == NULL)
262 return;
284 263
285#ifdef DEBUG_QUEUE 264#ifdef DEBUG_QUEUE
286 printk("r3964: remove_from_tx_queue: %p, length %u - ", 265 printk("r3964: remove_from_tx_queue: %p, length %u - ",
287 pHeader, pHeader->length ); 266 pHeader, pHeader->length);
288 for(pDump=pHeader;pDump;pDump=pDump->next) 267 for (pDump = pHeader; pDump; pDump = pDump->next)
289 printk("%p ", pDump); 268 printk("%p ", pDump);
290 printk("\n"); 269 printk("\n");
291#endif 270#endif
292 271
272 if (pHeader->owner) {
273 if (error_code) {
274 add_msg(pHeader->owner, R3964_MSG_ACK, 0,
275 error_code, NULL);
276 } else {
277 add_msg(pHeader->owner, R3964_MSG_ACK, pHeader->length,
278 error_code, NULL);
279 }
280 wake_up_interruptible(&pInfo->read_wait);
281 }
282
283 spin_lock_irqsave(&pInfo->lock, flags);
284
285 pInfo->tx_first = pHeader->next;
286 if (pInfo->tx_first == NULL) {
287 pInfo->tx_last = NULL;
288 }
289
290 spin_unlock_irqrestore(&pInfo->lock, flags);
291
292 kfree(pHeader);
293 TRACE_M("remove_from_tx_queue - kfree %p", pHeader);
293 294
294 if(pHeader->owner) 295 TRACE_Q("remove_from_tx_queue: tx_first = %p, tx_last = %p",
295 { 296 pInfo->tx_first, pInfo->tx_last);
296 if(error_code)
297 {
298 add_msg(pHeader->owner, R3964_MSG_ACK, 0,
299 error_code, NULL);
300 }
301 else
302 {
303 add_msg(pHeader->owner, R3964_MSG_ACK, pHeader->length,
304 error_code, NULL);
305 }
306 wake_up_interruptible (&pInfo->read_wait);
307 }
308
309 spin_lock_irqsave(&pInfo->lock, flags);
310
311 pInfo->tx_first = pHeader->next;
312 if(pInfo->tx_first==NULL)
313 {
314 pInfo->tx_last = NULL;
315 }
316
317 spin_unlock_irqrestore(&pInfo->lock, flags);
318
319 kfree(pHeader);
320 TRACE_M("remove_from_tx_queue - kfree %p",pHeader);
321
322 TRACE_Q("remove_from_tx_queue: tx_first = %p, tx_last = %p",
323 pInfo->tx_first, pInfo->tx_last );
324} 297}
325 298
326static void add_rx_queue(struct r3964_info *pInfo, struct r3964_block_header *pHeader) 299static void add_rx_queue(struct r3964_info *pInfo,
300 struct r3964_block_header *pHeader)
327{ 301{
328 unsigned long flags; 302 unsigned long flags;
329 303
330 spin_lock_irqsave(&pInfo->lock, flags); 304 spin_lock_irqsave(&pInfo->lock, flags);
331 305
332 pHeader->next = NULL; 306 pHeader->next = NULL;
333 307
334 if(pInfo->rx_last == NULL) 308 if (pInfo->rx_last == NULL) {
335 { 309 pInfo->rx_first = pInfo->rx_last = pHeader;
336 pInfo->rx_first = pInfo->rx_last = pHeader; 310 } else {
337 } 311 pInfo->rx_last->next = pHeader;
338 else 312 pInfo->rx_last = pHeader;
339 { 313 }
340 pInfo->rx_last->next = pHeader; 314 pInfo->blocks_in_rx_queue++;
341 pInfo->rx_last = pHeader; 315
342 } 316 spin_unlock_irqrestore(&pInfo->lock, flags);
343 pInfo->blocks_in_rx_queue++; 317
344 318 TRACE_Q("add_rx_queue: %p, length = %d, rx_first = %p, count = %d",
345 spin_unlock_irqrestore(&pInfo->lock, flags); 319 pHeader, pHeader->length,
346 320 pInfo->rx_first, pInfo->blocks_in_rx_queue);
347 TRACE_Q("add_rx_queue: %p, length = %d, rx_first = %p, count = %d",
348 pHeader, pHeader->length,
349 pInfo->rx_first, pInfo->blocks_in_rx_queue);
350} 321}
351 322
352static void remove_from_rx_queue(struct r3964_info *pInfo, 323static void remove_from_rx_queue(struct r3964_info *pInfo,
353 struct r3964_block_header *pHeader) 324 struct r3964_block_header *pHeader)
354{ 325{
355 unsigned long flags; 326 unsigned long flags;
356 struct r3964_block_header *pFind; 327 struct r3964_block_header *pFind;
357 328
358 if(pHeader==NULL) 329 if (pHeader == NULL)
359 return; 330 return;
360 331
361 TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d", 332 TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d",
362 pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue ); 333 pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue);
363 TRACE_Q("remove_from_rx_queue: %p, length %u", 334 TRACE_Q("remove_from_rx_queue: %p, length %u",
364 pHeader, pHeader->length ); 335 pHeader, pHeader->length);
365 336
366 spin_lock_irqsave(&pInfo->lock, flags); 337 spin_lock_irqsave(&pInfo->lock, flags);
367 338
368 if(pInfo->rx_first == pHeader) 339 if (pInfo->rx_first == pHeader) {
369 { 340 /* Remove the first block in the linked list: */
370 /* Remove the first block in the linked list: */ 341 pInfo->rx_first = pHeader->next;
371 pInfo->rx_first = pHeader->next; 342
372 343 if (pInfo->rx_first == NULL) {
373 if(pInfo->rx_first==NULL) 344 pInfo->rx_last = NULL;
374 { 345 }
375 pInfo->rx_last = NULL; 346 pInfo->blocks_in_rx_queue--;
376 } 347 } else {
377 pInfo->blocks_in_rx_queue--; 348 /* Find block to remove: */
378 } 349 for (pFind = pInfo->rx_first; pFind; pFind = pFind->next) {
379 else 350 if (pFind->next == pHeader) {
380 { 351 /* Got it. */
381 /* Find block to remove: */ 352 pFind->next = pHeader->next;
382 for(pFind=pInfo->rx_first; pFind; pFind=pFind->next) 353 pInfo->blocks_in_rx_queue--;
383 { 354 if (pFind->next == NULL) {
384 if(pFind->next == pHeader) 355 /* Oh, removed the last one! */
385 { 356 pInfo->rx_last = pFind;
386 /* Got it. */ 357 }
387 pFind->next = pHeader->next; 358 break;
388 pInfo->blocks_in_rx_queue--; 359 }
389 if(pFind->next==NULL) 360 }
390 { 361 }
391 /* Oh, removed the last one! */ 362
392 pInfo->rx_last = pFind; 363 spin_unlock_irqrestore(&pInfo->lock, flags);
393 } 364
394 break; 365 kfree(pHeader);
395 } 366 TRACE_M("remove_from_rx_queue - kfree %p", pHeader);
396 } 367
397 } 368 TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d",
398 369 pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue);
399 spin_unlock_irqrestore(&pInfo->lock, flags);
400
401 kfree(pHeader);
402 TRACE_M("remove_from_rx_queue - kfree %p",pHeader);
403
404 TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d",
405 pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue );
406} 370}
407 371
408static void put_char(struct r3964_info *pInfo, unsigned char ch) 372static void put_char(struct r3964_info *pInfo, unsigned char ch)
409{ 373{
410 struct tty_struct *tty = pInfo->tty; 374 struct tty_struct *tty = pInfo->tty;
411 375
412 if(tty==NULL) 376 if (tty == NULL)
413 return; 377 return;
414 378
415 if(tty->driver->put_char) 379 if (tty->driver->put_char) {
416 { 380 tty->driver->put_char(tty, ch);
417 tty->driver->put_char(tty, ch); 381 }
418 } 382 pInfo->bcc ^= ch;
419 pInfo->bcc ^= ch;
420} 383}
421 384
422static void flush(struct r3964_info *pInfo) 385static void flush(struct r3964_info *pInfo)
423{ 386{
424 struct tty_struct *tty = pInfo->tty; 387 struct tty_struct *tty = pInfo->tty;
425 388
426 if(tty==NULL) 389 if (tty == NULL)
427 return; 390 return;
428 391
429 if(tty->driver->flush_chars) 392 if (tty->driver->flush_chars) {
430 { 393 tty->driver->flush_chars(tty);
431 tty->driver->flush_chars(tty); 394 }
432 }
433} 395}
434 396
435static void trigger_transmit(struct r3964_info *pInfo) 397static void trigger_transmit(struct r3964_info *pInfo)
436{ 398{
437 unsigned long flags; 399 unsigned long flags;
438
439 400
440 spin_lock_irqsave(&pInfo->lock, flags); 401 spin_lock_irqsave(&pInfo->lock, flags);
441 402
442 if((pInfo->state == R3964_IDLE) && (pInfo->tx_first!=NULL)) 403 if ((pInfo->state == R3964_IDLE) && (pInfo->tx_first != NULL)) {
443 { 404 pInfo->state = R3964_TX_REQUEST;
444 pInfo->state = R3964_TX_REQUEST; 405 pInfo->nRetry = 0;
445 pInfo->nRetry=0; 406 pInfo->flags &= ~R3964_ERROR;
446 pInfo->flags &= ~R3964_ERROR; 407 mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ);
447 mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ);
448 408
449 spin_unlock_irqrestore(&pInfo->lock, flags); 409 spin_unlock_irqrestore(&pInfo->lock, flags);
450 410
451 TRACE_PS("trigger_transmit - sent STX"); 411 TRACE_PS("trigger_transmit - sent STX");
452 412
453 put_char(pInfo, STX); 413 put_char(pInfo, STX);
454 flush(pInfo); 414 flush(pInfo);
455 415
456 pInfo->bcc = 0; 416 pInfo->bcc = 0;
457 } 417 } else {
458 else 418 spin_unlock_irqrestore(&pInfo->lock, flags);
459 { 419 }
460 spin_unlock_irqrestore(&pInfo->lock, flags);
461 }
462} 420}
463 421
464static void retry_transmit(struct r3964_info *pInfo) 422static void retry_transmit(struct r3964_info *pInfo)
465{ 423{
466 if(pInfo->nRetry<R3964_MAX_RETRIES) 424 if (pInfo->nRetry < R3964_MAX_RETRIES) {
467 { 425 TRACE_PE("transmission failed. Retry #%d", pInfo->nRetry);
468 TRACE_PE("transmission failed. Retry #%d", 426 pInfo->bcc = 0;
469 pInfo->nRetry); 427 put_char(pInfo, STX);
470 pInfo->bcc = 0; 428 flush(pInfo);
471 put_char(pInfo, STX); 429 pInfo->state = R3964_TX_REQUEST;
472 flush(pInfo); 430 pInfo->nRetry++;
473 pInfo->state = R3964_TX_REQUEST; 431 mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ);
474 pInfo->nRetry++; 432 } else {
475 mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ); 433 TRACE_PE("transmission failed after %d retries",
476 } 434 R3964_MAX_RETRIES);
477 else 435
478 { 436 remove_from_tx_queue(pInfo, R3964_TX_FAIL);
479 TRACE_PE("transmission failed after %d retries", 437
480 R3964_MAX_RETRIES); 438 put_char(pInfo, NAK);
481 439 flush(pInfo);
482 remove_from_tx_queue(pInfo, R3964_TX_FAIL); 440 pInfo->state = R3964_IDLE;
483 441
484 put_char(pInfo, NAK); 442 trigger_transmit(pInfo);
485 flush(pInfo); 443 }
486 pInfo->state = R3964_IDLE;
487
488 trigger_transmit(pInfo);
489 }
490} 444}
491 445
492
493static void transmit_block(struct r3964_info *pInfo) 446static void transmit_block(struct r3964_info *pInfo)
494{ 447{
495 struct tty_struct *tty = pInfo->tty; 448 struct tty_struct *tty = pInfo->tty;
496 struct r3964_block_header *pBlock = pInfo->tx_first; 449 struct r3964_block_header *pBlock = pInfo->tx_first;
497 int room=0; 450 int room = 0;
498 451
499 if((tty==NULL) || (pBlock==NULL)) 452 if ((tty == NULL) || (pBlock == NULL)) {
500 { 453 return;
501 return; 454 }
502 } 455
503 456 if (tty->driver->write_room)
504 if(tty->driver->write_room) 457 room = tty->driver->write_room(tty);
505 room=tty->driver->write_room(tty); 458
506 459 TRACE_PS("transmit_block %p, room %d, length %d",
507 TRACE_PS("transmit_block %p, room %d, length %d", 460 pBlock, room, pBlock->length);
508 pBlock, room, pBlock->length); 461
509 462 while (pInfo->tx_position < pBlock->length) {
510 while(pInfo->tx_position < pBlock->length) 463 if (room < 2)
511 { 464 break;
512 if(room<2) 465
513 break; 466 if (pBlock->data[pInfo->tx_position] == DLE) {
514 467 /* send additional DLE char: */
515 if(pBlock->data[pInfo->tx_position]==DLE) 468 put_char(pInfo, DLE);
516 { 469 }
517 /* send additional DLE char: */ 470 put_char(pInfo, pBlock->data[pInfo->tx_position++]);
518 put_char(pInfo, DLE); 471
519 } 472 room--;
520 put_char(pInfo, pBlock->data[pInfo->tx_position++]); 473 }
521 474
522 room--; 475 if ((pInfo->tx_position == pBlock->length) && (room >= 3)) {
523 } 476 put_char(pInfo, DLE);
524 477 put_char(pInfo, ETX);
525 if((pInfo->tx_position == pBlock->length) && (room>=3)) 478 if (pInfo->flags & R3964_BCC) {
526 { 479 put_char(pInfo, pInfo->bcc);
527 put_char(pInfo, DLE); 480 }
528 put_char(pInfo, ETX); 481 pInfo->state = R3964_WAIT_FOR_TX_ACK;
529 if(pInfo->flags & R3964_BCC) 482 mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ);
530 { 483 }
531 put_char(pInfo, pInfo->bcc); 484 flush(pInfo);
532 }
533 pInfo->state = R3964_WAIT_FOR_TX_ACK;
534 mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ);
535 }
536 flush(pInfo);
537} 485}
538 486
539static void on_receive_block(struct r3964_info *pInfo) 487static void on_receive_block(struct r3964_info *pInfo)
540{ 488{
541 unsigned int length; 489 unsigned int length;
542 struct r3964_client_info *pClient; 490 struct r3964_client_info *pClient;
543 struct r3964_block_header *pBlock; 491 struct r3964_block_header *pBlock;
544 492
545 length=pInfo->rx_position; 493 length = pInfo->rx_position;
546 494
547 /* compare byte checksum characters: */ 495 /* compare byte checksum characters: */
548 if(pInfo->flags & R3964_BCC) 496 if (pInfo->flags & R3964_BCC) {
549 { 497 if (pInfo->bcc != pInfo->last_rx) {
550 if(pInfo->bcc!=pInfo->last_rx) 498 TRACE_PE("checksum error - got %x but expected %x",
551 { 499 pInfo->last_rx, pInfo->bcc);
552 TRACE_PE("checksum error - got %x but expected %x", 500 pInfo->flags |= R3964_CHECKSUM;
553 pInfo->last_rx, pInfo->bcc); 501 }
554 pInfo->flags |= R3964_CHECKSUM; 502 }
555 } 503
556 } 504 /* check for errors (parity, overrun,...): */
557 505 if (pInfo->flags & R3964_ERROR) {
558 /* check for errors (parity, overrun,...): */ 506 TRACE_PE("on_receive_block - transmission failed error %x",
559 if(pInfo->flags & R3964_ERROR) 507 pInfo->flags & R3964_ERROR);
560 { 508
561 TRACE_PE("on_receive_block - transmission failed error %x", 509 put_char(pInfo, NAK);
562 pInfo->flags & R3964_ERROR); 510 flush(pInfo);
563 511 if (pInfo->nRetry < R3964_MAX_RETRIES) {
564 put_char(pInfo, NAK); 512 pInfo->state = R3964_WAIT_FOR_RX_REPEAT;
565 flush(pInfo); 513 pInfo->nRetry++;
566 if(pInfo->nRetry<R3964_MAX_RETRIES) 514 mod_timer(&pInfo->tmr, jiffies + R3964_TO_RX_PANIC);
567 { 515 } else {
568 pInfo->state=R3964_WAIT_FOR_RX_REPEAT; 516 TRACE_PE("on_receive_block - failed after max retries");
569 pInfo->nRetry++; 517 pInfo->state = R3964_IDLE;
570 mod_timer(&pInfo->tmr, jiffies + R3964_TO_RX_PANIC); 518 }
571 } 519 return;
572 else 520 }
573 { 521
574 TRACE_PE("on_receive_block - failed after max retries"); 522 /* received block; submit DLE: */
575 pInfo->state=R3964_IDLE; 523 put_char(pInfo, DLE);
576 } 524 flush(pInfo);
577 return; 525 del_timer_sync(&pInfo->tmr);
578 } 526 TRACE_PS(" rx success: got %d chars", length);
579 527
580 528 /* prepare struct r3964_block_header: */
581 /* received block; submit DLE: */ 529 pBlock = kmalloc(length + sizeof(struct r3964_block_header),
582 put_char(pInfo, DLE); 530 GFP_KERNEL);
583 flush(pInfo); 531 TRACE_M("on_receive_block - kmalloc %p", pBlock);
584 del_timer_sync(&pInfo->tmr); 532
585 TRACE_PS(" rx success: got %d chars", length); 533 if (pBlock == NULL)
586 534 return;
587 /* prepare struct r3964_block_header: */ 535
588 pBlock = kmalloc(length+sizeof(struct r3964_block_header), GFP_KERNEL); 536 pBlock->length = length;
589 TRACE_M("on_receive_block - kmalloc %p",pBlock); 537 pBlock->data = ((unsigned char *)pBlock) +
590 538 sizeof(struct r3964_block_header);
591 if(pBlock==NULL) 539 pBlock->locks = 0;
592 return; 540 pBlock->next = NULL;
593 541 pBlock->owner = NULL;
594 pBlock->length = length; 542
595 pBlock->data = ((unsigned char*)pBlock)+sizeof(struct r3964_block_header); 543 memcpy(pBlock->data, pInfo->rx_buf, length);
596 pBlock->locks = 0; 544
597 pBlock->next = NULL; 545 /* queue block into rx_queue: */
598 pBlock->owner = NULL; 546 add_rx_queue(pInfo, pBlock);
599 547
600 memcpy(pBlock->data, pInfo->rx_buf, length); 548 /* notify attached client processes: */
601 549 for (pClient = pInfo->firstClient; pClient; pClient = pClient->next) {
602 /* queue block into rx_queue: */ 550 if (pClient->sig_flags & R3964_SIG_DATA) {
603 add_rx_queue(pInfo, pBlock); 551 add_msg(pClient, R3964_MSG_DATA, length, R3964_OK,
604 552 pBlock);
605 /* notify attached client processes: */ 553 }
606 for(pClient=pInfo->firstClient; pClient; pClient=pClient->next) 554 }
607 { 555 wake_up_interruptible(&pInfo->read_wait);
608 if(pClient->sig_flags & R3964_SIG_DATA)
609 {
610 add_msg(pClient, R3964_MSG_DATA, length, R3964_OK, pBlock);
611 }
612 }
613 wake_up_interruptible (&pInfo->read_wait);
614
615 pInfo->state = R3964_IDLE;
616
617 trigger_transmit(pInfo);
618}
619 556
557 pInfo->state = R3964_IDLE;
558
559 trigger_transmit(pInfo);
560}
620 561
621static void receive_char(struct r3964_info *pInfo, const unsigned char c) 562static void receive_char(struct r3964_info *pInfo, const unsigned char c)
622{ 563{
623 switch(pInfo->state) 564 switch (pInfo->state) {
624 { 565 case R3964_TX_REQUEST:
625 case R3964_TX_REQUEST: 566 if (c == DLE) {
626 if(c==DLE) 567 TRACE_PS("TX_REQUEST - got DLE");
627 { 568
628 TRACE_PS("TX_REQUEST - got DLE"); 569 pInfo->state = R3964_TRANSMITTING;
629 570 pInfo->tx_position = 0;
630 pInfo->state = R3964_TRANSMITTING; 571
631 pInfo->tx_position = 0; 572 transmit_block(pInfo);
632 573 } else if (c == STX) {
633 transmit_block(pInfo); 574 if (pInfo->nRetry == 0) {
634 } 575 TRACE_PE("TX_REQUEST - init conflict");
635 else if(c==STX) 576 if (pInfo->priority == R3964_SLAVE) {
636 { 577 goto start_receiving;
637 if(pInfo->nRetry==0) 578 }
638 { 579 } else {
639 TRACE_PE("TX_REQUEST - init conflict"); 580 TRACE_PE("TX_REQUEST - secondary init "
640 if(pInfo->priority == R3964_SLAVE) 581 "conflict!? Switching to SLAVE mode "
641 { 582 "for next rx.");
642 goto start_receiving; 583 goto start_receiving;
643 } 584 }
644 } 585 } else {
645 else 586 TRACE_PE("TX_REQUEST - char != DLE: %x", c);
646 { 587 retry_transmit(pInfo);
647 TRACE_PE("TX_REQUEST - secondary init conflict!?" 588 }
648 " Switching to SLAVE mode for next rx."); 589 break;
649 goto start_receiving; 590 case R3964_TRANSMITTING:
650 } 591 if (c == NAK) {
651 } 592 TRACE_PE("TRANSMITTING - got NAK");
652 else 593 retry_transmit(pInfo);
653 { 594 } else {
654 TRACE_PE("TX_REQUEST - char != DLE: %x", c); 595 TRACE_PE("TRANSMITTING - got invalid char");
655 retry_transmit(pInfo); 596
656 } 597 pInfo->state = R3964_WAIT_ZVZ_BEFORE_TX_RETRY;
657 break; 598 mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ);
658 case R3964_TRANSMITTING: 599 }
659 if(c==NAK) 600 break;
660 { 601 case R3964_WAIT_FOR_TX_ACK:
661 TRACE_PE("TRANSMITTING - got NAK"); 602 if (c == DLE) {
662 retry_transmit(pInfo); 603 TRACE_PS("WAIT_FOR_TX_ACK - got DLE");
663 } 604 remove_from_tx_queue(pInfo, R3964_OK);
664 else 605
665 { 606 pInfo->state = R3964_IDLE;
666 TRACE_PE("TRANSMITTING - got invalid char"); 607 trigger_transmit(pInfo);
667 608 } else {
668 pInfo->state = R3964_WAIT_ZVZ_BEFORE_TX_RETRY; 609 retry_transmit(pInfo);
669 mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); 610 }
670 } 611 break;
671 break; 612 case R3964_WAIT_FOR_RX_REPEAT:
672 case R3964_WAIT_FOR_TX_ACK: 613 /* FALLTROUGH */
673 if(c==DLE) 614 case R3964_IDLE:
674 { 615 if (c == STX) {
675 TRACE_PS("WAIT_FOR_TX_ACK - got DLE"); 616 /* Prevent rx_queue from overflow: */
676 remove_from_tx_queue(pInfo, R3964_OK); 617 if (pInfo->blocks_in_rx_queue >=
677 618 R3964_MAX_BLOCKS_IN_RX_QUEUE) {
678 pInfo->state = R3964_IDLE; 619 TRACE_PE("IDLE - got STX but no space in "
679 trigger_transmit(pInfo); 620 "rx_queue!");
680 } 621 pInfo->state = R3964_WAIT_FOR_RX_BUF;
681 else 622 mod_timer(&pInfo->tmr,
682 { 623 jiffies + R3964_TO_NO_BUF);
683 retry_transmit(pInfo); 624 break;
684 } 625 }
685 break;
686 case R3964_WAIT_FOR_RX_REPEAT:
687 /* FALLTROUGH */
688 case R3964_IDLE:
689 if(c==STX)
690 {
691 /* Prevent rx_queue from overflow: */
692 if(pInfo->blocks_in_rx_queue >= R3964_MAX_BLOCKS_IN_RX_QUEUE)
693 {
694 TRACE_PE("IDLE - got STX but no space in rx_queue!");
695 pInfo->state=R3964_WAIT_FOR_RX_BUF;
696 mod_timer(&pInfo->tmr, jiffies + R3964_TO_NO_BUF);
697 break;
698 }
699start_receiving: 626start_receiving:
700 /* Ok, start receiving: */ 627 /* Ok, start receiving: */
701 TRACE_PS("IDLE - got STX"); 628 TRACE_PS("IDLE - got STX");
702 pInfo->rx_position = 0; 629 pInfo->rx_position = 0;
703 pInfo->last_rx = 0; 630 pInfo->last_rx = 0;
704 pInfo->flags &= ~R3964_ERROR; 631 pInfo->flags &= ~R3964_ERROR;
705 pInfo->state=R3964_RECEIVING; 632 pInfo->state = R3964_RECEIVING;
706 mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); 633 mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ);
707 pInfo->nRetry = 0; 634 pInfo->nRetry = 0;
708 put_char(pInfo, DLE); 635 put_char(pInfo, DLE);
709 flush(pInfo); 636 flush(pInfo);
710 pInfo->bcc = 0; 637 pInfo->bcc = 0;
711 } 638 }
712 break; 639 break;
713 case R3964_RECEIVING: 640 case R3964_RECEIVING:
714 if(pInfo->rx_position < RX_BUF_SIZE) 641 if (pInfo->rx_position < RX_BUF_SIZE) {
715 { 642 pInfo->bcc ^= c;
716 pInfo->bcc ^= c; 643
717 644 if (c == DLE) {
718 if(c==DLE) 645 if (pInfo->last_rx == DLE) {
719 { 646 pInfo->last_rx = 0;
720 if(pInfo->last_rx==DLE) 647 goto char_to_buf;
721 { 648 }
722 pInfo->last_rx = 0; 649 pInfo->last_rx = DLE;
723 goto char_to_buf; 650 break;
724 } 651 } else if ((c == ETX) && (pInfo->last_rx == DLE)) {
725 pInfo->last_rx = DLE; 652 if (pInfo->flags & R3964_BCC) {
726 break; 653 pInfo->state = R3964_WAIT_FOR_BCC;
727 } 654 mod_timer(&pInfo->tmr,
728 else if((c==ETX) && (pInfo->last_rx==DLE)) 655 jiffies + R3964_TO_ZVZ);
729 { 656 } else {
730 if(pInfo->flags & R3964_BCC) 657 on_receive_block(pInfo);
731 { 658 }
732 pInfo->state = R3964_WAIT_FOR_BCC; 659 } else {
733 mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); 660 pInfo->last_rx = c;
734 }
735 else
736 {
737 on_receive_block(pInfo);
738 }
739 }
740 else
741 {
742 pInfo->last_rx = c;
743char_to_buf: 661char_to_buf:
744 pInfo->rx_buf[pInfo->rx_position++] = c; 662 pInfo->rx_buf[pInfo->rx_position++] = c;
745 mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); 663 mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ);
746 } 664 }
747 } 665 }
748 /* else: overflow-msg? BUF_SIZE>MTU; should not happen? */ 666 /* else: overflow-msg? BUF_SIZE>MTU; should not happen? */
749 break; 667 break;
750 case R3964_WAIT_FOR_BCC: 668 case R3964_WAIT_FOR_BCC:
751 pInfo->last_rx = c; 669 pInfo->last_rx = c;
752 on_receive_block(pInfo); 670 on_receive_block(pInfo);
753 break; 671 break;
754 } 672 }
755} 673}
756 674
757static void receive_error(struct r3964_info *pInfo, const char flag) 675static void receive_error(struct r3964_info *pInfo, const char flag)
758{ 676{
759 switch (flag) 677 switch (flag) {
760 { 678 case TTY_NORMAL:
761 case TTY_NORMAL: 679 break;
762 break; 680 case TTY_BREAK:
763 case TTY_BREAK: 681 TRACE_PE("received break");
764 TRACE_PE("received break") 682 pInfo->flags |= R3964_BREAK;
765 pInfo->flags |= R3964_BREAK; 683 break;
766 break; 684 case TTY_PARITY:
767 case TTY_PARITY: 685 TRACE_PE("parity error");
768 TRACE_PE("parity error") 686 pInfo->flags |= R3964_PARITY;
769 pInfo->flags |= R3964_PARITY; 687 break;
770 break; 688 case TTY_FRAME:
771 case TTY_FRAME: 689 TRACE_PE("frame error");
772 TRACE_PE("frame error") 690 pInfo->flags |= R3964_FRAME;
773 pInfo->flags |= R3964_FRAME; 691 break;
774 break; 692 case TTY_OVERRUN:
775 case TTY_OVERRUN: 693 TRACE_PE("frame overrun");
776 TRACE_PE("frame overrun") 694 pInfo->flags |= R3964_OVERRUN;
777 pInfo->flags |= R3964_OVERRUN; 695 break;
778 break; 696 default:
779 default: 697 TRACE_PE("receive_error - unknown flag %d", flag);
780 TRACE_PE("receive_error - unknown flag %d", flag); 698 pInfo->flags |= R3964_UNKNOWN;
781 pInfo->flags |= R3964_UNKNOWN; 699 break;
782 break; 700 }
783 }
784} 701}
785 702
786static void on_timeout(unsigned long priv) 703static void on_timeout(unsigned long priv)
787{ 704{
788 struct r3964_info *pInfo = (void *)priv; 705 struct r3964_info *pInfo = (void *)priv;
789 706
790 switch(pInfo->state) 707 switch (pInfo->state) {
791 { 708 case R3964_TX_REQUEST:
792 case R3964_TX_REQUEST: 709 TRACE_PE("TX_REQUEST - timeout");
793 TRACE_PE("TX_REQUEST - timeout"); 710 retry_transmit(pInfo);
794 retry_transmit(pInfo); 711 break;
795 break; 712 case R3964_WAIT_ZVZ_BEFORE_TX_RETRY:
796 case R3964_WAIT_ZVZ_BEFORE_TX_RETRY: 713 put_char(pInfo, NAK);
797 put_char(pInfo, NAK); 714 flush(pInfo);
798 flush(pInfo); 715 retry_transmit(pInfo);
799 retry_transmit(pInfo); 716 break;
800 break; 717 case R3964_WAIT_FOR_TX_ACK:
801 case R3964_WAIT_FOR_TX_ACK: 718 TRACE_PE("WAIT_FOR_TX_ACK - timeout");
802 TRACE_PE("WAIT_FOR_TX_ACK - timeout"); 719 retry_transmit(pInfo);
803 retry_transmit(pInfo); 720 break;
804 break; 721 case R3964_WAIT_FOR_RX_BUF:
805 case R3964_WAIT_FOR_RX_BUF: 722 TRACE_PE("WAIT_FOR_RX_BUF - timeout");
806 TRACE_PE("WAIT_FOR_RX_BUF - timeout"); 723 put_char(pInfo, NAK);
807 put_char(pInfo, NAK); 724 flush(pInfo);
808 flush(pInfo); 725 pInfo->state = R3964_IDLE;
809 pInfo->state=R3964_IDLE; 726 break;
810 break; 727 case R3964_RECEIVING:
811 case R3964_RECEIVING: 728 TRACE_PE("RECEIVING - timeout after %d chars",
812 TRACE_PE("RECEIVING - timeout after %d chars", 729 pInfo->rx_position);
813 pInfo->rx_position); 730 put_char(pInfo, NAK);
814 put_char(pInfo, NAK); 731 flush(pInfo);
815 flush(pInfo); 732 pInfo->state = R3964_IDLE;
816 pInfo->state=R3964_IDLE; 733 break;
817 break; 734 case R3964_WAIT_FOR_RX_REPEAT:
818 case R3964_WAIT_FOR_RX_REPEAT: 735 TRACE_PE("WAIT_FOR_RX_REPEAT - timeout");
819 TRACE_PE("WAIT_FOR_RX_REPEAT - timeout"); 736 pInfo->state = R3964_IDLE;
820 pInfo->state=R3964_IDLE; 737 break;
821 break; 738 case R3964_WAIT_FOR_BCC:
822 case R3964_WAIT_FOR_BCC: 739 TRACE_PE("WAIT_FOR_BCC - timeout");
823 TRACE_PE("WAIT_FOR_BCC - timeout"); 740 put_char(pInfo, NAK);
824 put_char(pInfo, NAK); 741 flush(pInfo);
825 flush(pInfo); 742 pInfo->state = R3964_IDLE;
826 pInfo->state=R3964_IDLE; 743 break;
827 break; 744 }
828 }
829} 745}
830 746
831static struct r3964_client_info *findClient( 747static struct r3964_client_info *findClient(struct r3964_info *pInfo,
832 struct r3964_info *pInfo, struct pid *pid) 748 struct pid *pid)
833{ 749{
834 struct r3964_client_info *pClient; 750 struct r3964_client_info *pClient;
835 751
836 for(pClient=pInfo->firstClient; pClient; pClient=pClient->next) 752 for (pClient = pInfo->firstClient; pClient; pClient = pClient->next) {
837 { 753 if (pClient->pid == pid) {
838 if(pClient->pid == pid) 754 return pClient;
839 { 755 }
840 return pClient; 756 }
841 } 757 return NULL;
842 }
843 return NULL;
844} 758}
845 759
846static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg) 760static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg)
847{ 761{
848 struct r3964_client_info *pClient; 762 struct r3964_client_info *pClient;
849 struct r3964_client_info **ppClient; 763 struct r3964_client_info **ppClient;
850 struct r3964_message *pMsg; 764 struct r3964_message *pMsg;
851 765
852 if((arg & R3964_SIG_ALL)==0) 766 if ((arg & R3964_SIG_ALL) == 0) {
853 { 767 /* Remove client from client list */
854 /* Remove client from client list */ 768 for (ppClient = &pInfo->firstClient; *ppClient;
855 for(ppClient=&pInfo->firstClient; *ppClient; ppClient=&(*ppClient)->next) 769 ppClient = &(*ppClient)->next) {
856 { 770 pClient = *ppClient;
857 pClient = *ppClient; 771
858 772 if (pClient->pid == pid) {
859 if(pClient->pid == pid) 773 TRACE_PS("removing client %d from client list",
860 { 774 pid_nr(pid));
861 TRACE_PS("removing client %d from client list", pid_nr(pid)); 775 *ppClient = pClient->next;
862 *ppClient = pClient->next; 776 while (pClient->msg_count) {
863 while(pClient->msg_count) 777 pMsg = remove_msg(pInfo, pClient);
864 { 778 if (pMsg) {
865 pMsg=remove_msg(pInfo, pClient); 779 kfree(pMsg);
866 if(pMsg) 780 TRACE_M("enable_signals - msg "
867 { 781 "kfree %p", pMsg);
868 kfree(pMsg); 782 }
869 TRACE_M("enable_signals - msg kfree %p",pMsg); 783 }
870 } 784 put_pid(pClient->pid);
871 } 785 kfree(pClient);
872 put_pid(pClient->pid); 786 TRACE_M("enable_signals - kfree %p", pClient);
873 kfree(pClient); 787 return 0;
874 TRACE_M("enable_signals - kfree %p",pClient); 788 }
875 return 0; 789 }
876 } 790 return -EINVAL;
877 } 791 } else {
878 return -EINVAL; 792 pClient = findClient(pInfo, pid);
879 } 793 if (pClient) {
880 else 794 /* update signal options */
881 { 795 pClient->sig_flags = arg;
882 pClient=findClient(pInfo, pid); 796 } else {
883 if(pClient) 797 /* add client to client list */
884 { 798 pClient = kmalloc(sizeof(struct r3964_client_info),
885 /* update signal options */ 799 GFP_KERNEL);
886 pClient->sig_flags=arg; 800 TRACE_M("enable_signals - kmalloc %p", pClient);
887 } 801 if (pClient == NULL)
888 else 802 return -ENOMEM;
889 { 803
890 /* add client to client list */ 804 TRACE_PS("add client %d to client list", pid_nr(pid));
891 pClient=kmalloc(sizeof(struct r3964_client_info), GFP_KERNEL); 805 spin_lock_init(&pClient->lock);
892 TRACE_M("enable_signals - kmalloc %p",pClient); 806 pClient->sig_flags = arg;
893 if(pClient==NULL) 807 pClient->pid = get_pid(pid);
894 return -ENOMEM; 808 pClient->next = pInfo->firstClient;
895 809 pClient->first_msg = NULL;
896 TRACE_PS("add client %d to client list", pid_nr(pid)); 810 pClient->last_msg = NULL;
897 spin_lock_init(&pClient->lock); 811 pClient->next_block_to_read = NULL;
898 pClient->sig_flags=arg; 812 pClient->msg_count = 0;
899 pClient->pid = get_pid(pid); 813 pInfo->firstClient = pClient;
900 pClient->next=pInfo->firstClient; 814 }
901 pClient->first_msg = NULL; 815 }
902 pClient->last_msg = NULL; 816
903 pClient->next_block_to_read = NULL; 817 return 0;
904 pClient->msg_count = 0;
905 pInfo->firstClient=pClient;
906 }
907 }
908
909 return 0;
910} 818}
911 819
912static int read_telegram(struct r3964_info *pInfo, struct pid *pid, unsigned char __user *buf) 820static int read_telegram(struct r3964_info *pInfo, struct pid *pid,
821 unsigned char __user * buf)
913{ 822{
914 struct r3964_client_info *pClient; 823 struct r3964_client_info *pClient;
915 struct r3964_block_header *block; 824 struct r3964_block_header *block;
916 825
917 if(!buf) 826 if (!buf) {
918 { 827 return -EINVAL;
919 return -EINVAL; 828 }
920 } 829
921 830 pClient = findClient(pInfo, pid);
922 pClient=findClient(pInfo,pid); 831 if (pClient == NULL) {
923 if(pClient==NULL) 832 return -EINVAL;
924 { 833 }
925 return -EINVAL; 834
926 } 835 block = pClient->next_block_to_read;
927 836 if (!block) {
928 block=pClient->next_block_to_read; 837 return 0;
929 if(!block) 838 } else {
930 { 839 if (copy_to_user(buf, block->data, block->length))
931 return 0; 840 return -EFAULT;
932 } 841
933 else 842 remove_client_block(pInfo, pClient);
934 { 843 return block->length;
935 if (copy_to_user (buf, block->data, block->length)) 844 }
936 return -EFAULT; 845
937 846 return -EINVAL;
938 remove_client_block(pInfo, pClient);
939 return block->length;
940 }
941
942 return -EINVAL;
943} 847}
944 848
945static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg, 849static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg,
946 int error_code, struct r3964_block_header *pBlock) 850 int error_code, struct r3964_block_header *pBlock)
947{ 851{
948 struct r3964_message *pMsg; 852 struct r3964_message *pMsg;
949 unsigned long flags; 853 unsigned long flags;
950 854
951 if(pClient->msg_count<R3964_MAX_MSG_COUNT-1) 855 if (pClient->msg_count < R3964_MAX_MSG_COUNT - 1) {
952 {
953queue_the_message: 856queue_the_message:
954 857
955 pMsg = kmalloc(sizeof(struct r3964_message), 858 pMsg = kmalloc(sizeof(struct r3964_message),
956 error_code?GFP_ATOMIC:GFP_KERNEL); 859 error_code ? GFP_ATOMIC : GFP_KERNEL);
957 TRACE_M("add_msg - kmalloc %p",pMsg); 860 TRACE_M("add_msg - kmalloc %p", pMsg);
958 if(pMsg==NULL) { 861 if (pMsg == NULL) {
959 return; 862 return;
960 } 863 }
961 864
962 spin_lock_irqsave(&pClient->lock, flags); 865 spin_lock_irqsave(&pClient->lock, flags);
963 866
964 pMsg->msg_id = msg_id; 867 pMsg->msg_id = msg_id;
965 pMsg->arg = arg; 868 pMsg->arg = arg;
966 pMsg->error_code = error_code; 869 pMsg->error_code = error_code;
967 pMsg->block = pBlock; 870 pMsg->block = pBlock;
968 pMsg->next = NULL; 871 pMsg->next = NULL;
969 872
970 if(pClient->last_msg==NULL) 873 if (pClient->last_msg == NULL) {
971 { 874 pClient->first_msg = pClient->last_msg = pMsg;
972 pClient->first_msg=pClient->last_msg=pMsg; 875 } else {
973 } 876 pClient->last_msg->next = pMsg;
974 else 877 pClient->last_msg = pMsg;
975 { 878 }
976 pClient->last_msg->next = pMsg; 879
977 pClient->last_msg=pMsg; 880 pClient->msg_count++;
978 } 881
979 882 if (pBlock != NULL) {
980 pClient->msg_count++; 883 pBlock->locks++;
981 884 }
982 if(pBlock!=NULL) 885 spin_unlock_irqrestore(&pClient->lock, flags);
983 { 886 } else {
984 pBlock->locks++; 887 if ((pClient->last_msg->msg_id == R3964_MSG_ACK)
985 } 888 && (pClient->last_msg->error_code == R3964_OVERFLOW)) {
986 spin_unlock_irqrestore(&pClient->lock, flags); 889 pClient->last_msg->arg++;
987 } 890 TRACE_PE("add_msg - inc prev OVERFLOW-msg");
988 else 891 } else {
989 { 892 msg_id = R3964_MSG_ACK;
990 if((pClient->last_msg->msg_id == R3964_MSG_ACK) 893 arg = 0;
991 && (pClient->last_msg->error_code==R3964_OVERFLOW)) 894 error_code = R3964_OVERFLOW;
992 { 895 pBlock = NULL;
993 pClient->last_msg->arg++; 896 TRACE_PE("add_msg - queue OVERFLOW-msg");
994 TRACE_PE("add_msg - inc prev OVERFLOW-msg"); 897 goto queue_the_message;
995 } 898 }
996 else 899 }
997 { 900 /* Send SIGIO signal to client process: */
998 msg_id = R3964_MSG_ACK; 901 if (pClient->sig_flags & R3964_USE_SIGIO) {
999 arg = 0; 902 kill_pid(pClient->pid, SIGIO, 1);
1000 error_code = R3964_OVERFLOW; 903 }
1001 pBlock = NULL;
1002 TRACE_PE("add_msg - queue OVERFLOW-msg");
1003 goto queue_the_message;
1004 }
1005 }
1006 /* Send SIGIO signal to client process: */
1007 if(pClient->sig_flags & R3964_USE_SIGIO)
1008 {
1009 kill_pid(pClient->pid, SIGIO, 1);
1010 }
1011} 904}
1012 905
1013static struct r3964_message *remove_msg(struct r3964_info *pInfo, 906static struct r3964_message *remove_msg(struct r3964_info *pInfo,
1014 struct r3964_client_info *pClient) 907 struct r3964_client_info *pClient)
1015{ 908{
1016 struct r3964_message *pMsg=NULL; 909 struct r3964_message *pMsg = NULL;
1017 unsigned long flags; 910 unsigned long flags;
1018 911
1019 if(pClient->first_msg) 912 if (pClient->first_msg) {
1020 { 913 spin_lock_irqsave(&pClient->lock, flags);
1021 spin_lock_irqsave(&pClient->lock, flags); 914
1022 915 pMsg = pClient->first_msg;
1023 pMsg = pClient->first_msg; 916 pClient->first_msg = pMsg->next;
1024 pClient->first_msg = pMsg->next; 917 if (pClient->first_msg == NULL) {
1025 if(pClient->first_msg==NULL) 918 pClient->last_msg = NULL;
1026 { 919 }
1027 pClient->last_msg = NULL; 920
1028 } 921 pClient->msg_count--;
1029 922 if (pMsg->block) {
1030 pClient->msg_count--; 923 remove_client_block(pInfo, pClient);
1031 if(pMsg->block) 924 pClient->next_block_to_read = pMsg->block;
1032 { 925 }
1033 remove_client_block(pInfo, pClient); 926 spin_unlock_irqrestore(&pClient->lock, flags);
1034 pClient->next_block_to_read = pMsg->block; 927 }
1035 } 928 return pMsg;
1036 spin_unlock_irqrestore(&pClient->lock, flags);
1037 }
1038 return pMsg;
1039} 929}
1040 930
1041static void remove_client_block(struct r3964_info *pInfo, 931static void remove_client_block(struct r3964_info *pInfo,
1042 struct r3964_client_info *pClient) 932 struct r3964_client_info *pClient)
1043{ 933{
1044 struct r3964_block_header *block; 934 struct r3964_block_header *block;
1045 935
1046 TRACE_PS("remove_client_block PID %d", pid_nr(pClient->pid)); 936 TRACE_PS("remove_client_block PID %d", pid_nr(pClient->pid));
1047
1048 block=pClient->next_block_to_read;
1049 if(block)
1050 {
1051 block->locks--;
1052 if(block->locks==0)
1053 {
1054 remove_from_rx_queue(pInfo, block);
1055 }
1056 }
1057 pClient->next_block_to_read = NULL;
1058}
1059 937
938 block = pClient->next_block_to_read;
939 if (block) {
940 block->locks--;
941 if (block->locks == 0) {
942 remove_from_rx_queue(pInfo, block);
943 }
944 }
945 pClient->next_block_to_read = NULL;
946}
1060 947
1061/************************************************************* 948/*************************************************************
1062 * Line discipline routines 949 * Line discipline routines
@@ -1064,342 +951,320 @@ static void remove_client_block(struct r3964_info *pInfo,
1064 951
1065static int r3964_open(struct tty_struct *tty) 952static int r3964_open(struct tty_struct *tty)
1066{ 953{
1067 struct r3964_info *pInfo; 954 struct r3964_info *pInfo;
1068 955
1069 TRACE_L("open"); 956 TRACE_L("open");
1070 TRACE_L("tty=%p, PID=%d, disc_data=%p", 957 TRACE_L("tty=%p, PID=%d, disc_data=%p",
1071 tty, current->pid, tty->disc_data); 958 tty, current->pid, tty->disc_data);
1072 959
1073 pInfo=kmalloc(sizeof(struct r3964_info), GFP_KERNEL); 960 pInfo = kmalloc(sizeof(struct r3964_info), GFP_KERNEL);
1074 TRACE_M("r3964_open - info kmalloc %p",pInfo); 961 TRACE_M("r3964_open - info kmalloc %p", pInfo);
1075 962
1076 if(!pInfo) 963 if (!pInfo) {
1077 { 964 printk(KERN_ERR "r3964: failed to alloc info structure\n");
1078 printk(KERN_ERR "r3964: failed to alloc info structure\n"); 965 return -ENOMEM;
1079 return -ENOMEM; 966 }
1080 } 967
1081 968 pInfo->rx_buf = kmalloc(RX_BUF_SIZE, GFP_KERNEL);
1082 pInfo->rx_buf = kmalloc(RX_BUF_SIZE, GFP_KERNEL); 969 TRACE_M("r3964_open - rx_buf kmalloc %p", pInfo->rx_buf);
1083 TRACE_M("r3964_open - rx_buf kmalloc %p",pInfo->rx_buf); 970
1084 971 if (!pInfo->rx_buf) {
1085 if(!pInfo->rx_buf) 972 printk(KERN_ERR "r3964: failed to alloc receive buffer\n");
1086 { 973 kfree(pInfo);
1087 printk(KERN_ERR "r3964: failed to alloc receive buffer\n"); 974 TRACE_M("r3964_open - info kfree %p", pInfo);
1088 kfree(pInfo); 975 return -ENOMEM;
1089 TRACE_M("r3964_open - info kfree %p",pInfo); 976 }
1090 return -ENOMEM; 977
1091 } 978 pInfo->tx_buf = kmalloc(TX_BUF_SIZE, GFP_KERNEL);
1092 979 TRACE_M("r3964_open - tx_buf kmalloc %p", pInfo->tx_buf);
1093 pInfo->tx_buf = kmalloc(TX_BUF_SIZE, GFP_KERNEL); 980
1094 TRACE_M("r3964_open - tx_buf kmalloc %p",pInfo->tx_buf); 981 if (!pInfo->tx_buf) {
1095 982 printk(KERN_ERR "r3964: failed to alloc transmit buffer\n");
1096 if(!pInfo->tx_buf) 983 kfree(pInfo->rx_buf);
1097 { 984 TRACE_M("r3964_open - rx_buf kfree %p", pInfo->rx_buf);
1098 printk(KERN_ERR "r3964: failed to alloc transmit buffer\n"); 985 kfree(pInfo);
1099 kfree(pInfo->rx_buf); 986 TRACE_M("r3964_open - info kfree %p", pInfo);
1100 TRACE_M("r3964_open - rx_buf kfree %p",pInfo->rx_buf); 987 return -ENOMEM;
1101 kfree(pInfo); 988 }
1102 TRACE_M("r3964_open - info kfree %p",pInfo); 989
1103 return -ENOMEM; 990 spin_lock_init(&pInfo->lock);
1104 } 991 pInfo->tty = tty;
1105 992 init_waitqueue_head(&pInfo->read_wait);
1106 spin_lock_init(&pInfo->lock); 993 pInfo->priority = R3964_MASTER;
1107 pInfo->tty = tty; 994 pInfo->rx_first = pInfo->rx_last = NULL;
1108 init_waitqueue_head (&pInfo->read_wait); 995 pInfo->tx_first = pInfo->tx_last = NULL;
1109 pInfo->priority = R3964_MASTER; 996 pInfo->rx_position = 0;
1110 pInfo->rx_first = pInfo->rx_last = NULL; 997 pInfo->tx_position = 0;
1111 pInfo->tx_first = pInfo->tx_last = NULL; 998 pInfo->last_rx = 0;
1112 pInfo->rx_position = 0; 999 pInfo->blocks_in_rx_queue = 0;
1113 pInfo->tx_position = 0; 1000 pInfo->firstClient = NULL;
1114 pInfo->last_rx = 0; 1001 pInfo->state = R3964_IDLE;
1115 pInfo->blocks_in_rx_queue = 0; 1002 pInfo->flags = R3964_DEBUG;
1116 pInfo->firstClient=NULL; 1003 pInfo->nRetry = 0;
1117 pInfo->state=R3964_IDLE; 1004
1118 pInfo->flags = R3964_DEBUG; 1005 tty->disc_data = pInfo;
1119 pInfo->nRetry = 0; 1006 tty->receive_room = 65536;
1120 1007
1121 tty->disc_data = pInfo; 1008 init_timer(&pInfo->tmr);
1122 tty->receive_room = 65536; 1009 pInfo->tmr.data = (unsigned long)pInfo;
1123 1010 pInfo->tmr.function = on_timeout;
1124 init_timer(&pInfo->tmr); 1011
1125 pInfo->tmr.data = (unsigned long)pInfo; 1012 return 0;
1126 pInfo->tmr.function = on_timeout;
1127
1128 return 0;
1129} 1013}
1130 1014
1131static void r3964_close(struct tty_struct *tty) 1015static void r3964_close(struct tty_struct *tty)
1132{ 1016{
1133 struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; 1017 struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data;
1134 struct r3964_client_info *pClient, *pNext; 1018 struct r3964_client_info *pClient, *pNext;
1135 struct r3964_message *pMsg; 1019 struct r3964_message *pMsg;
1136 struct r3964_block_header *pHeader, *pNextHeader; 1020 struct r3964_block_header *pHeader, *pNextHeader;
1137 unsigned long flags; 1021 unsigned long flags;
1138 1022
1139 TRACE_L("close"); 1023 TRACE_L("close");
1140 1024
1141 /* 1025 /*
1142 * Make sure that our task queue isn't activated. If it 1026 * Make sure that our task queue isn't activated. If it
1143 * is, take it out of the linked list. 1027 * is, take it out of the linked list.
1144 */ 1028 */
1145 del_timer_sync(&pInfo->tmr); 1029 del_timer_sync(&pInfo->tmr);
1146 1030
1147 /* Remove client-structs and message queues: */ 1031 /* Remove client-structs and message queues: */
1148 pClient=pInfo->firstClient; 1032 pClient = pInfo->firstClient;
1149 while(pClient) 1033 while (pClient) {
1150 { 1034 pNext = pClient->next;
1151 pNext=pClient->next; 1035 while (pClient->msg_count) {
1152 while(pClient->msg_count) 1036 pMsg = remove_msg(pInfo, pClient);
1153 { 1037 if (pMsg) {
1154 pMsg=remove_msg(pInfo, pClient); 1038 kfree(pMsg);
1155 if(pMsg) 1039 TRACE_M("r3964_close - msg kfree %p", pMsg);
1156 { 1040 }
1157 kfree(pMsg); 1041 }
1158 TRACE_M("r3964_close - msg kfree %p",pMsg); 1042 put_pid(pClient->pid);
1159 } 1043 kfree(pClient);
1160 } 1044 TRACE_M("r3964_close - client kfree %p", pClient);
1161 put_pid(pClient->pid); 1045 pClient = pNext;
1162 kfree(pClient); 1046 }
1163 TRACE_M("r3964_close - client kfree %p",pClient); 1047 /* Remove jobs from tx_queue: */
1164 pClient=pNext; 1048 spin_lock_irqsave(&pInfo->lock, flags);
1165 } 1049 pHeader = pInfo->tx_first;
1166 /* Remove jobs from tx_queue: */ 1050 pInfo->tx_first = pInfo->tx_last = NULL;
1167 spin_lock_irqsave(&pInfo->lock, flags);
1168 pHeader=pInfo->tx_first;
1169 pInfo->tx_first=pInfo->tx_last=NULL;
1170 spin_unlock_irqrestore(&pInfo->lock, flags); 1051 spin_unlock_irqrestore(&pInfo->lock, flags);
1171 1052
1172 while(pHeader) 1053 while (pHeader) {
1173 { 1054 pNextHeader = pHeader->next;
1174 pNextHeader=pHeader->next; 1055 kfree(pHeader);
1175 kfree(pHeader); 1056 pHeader = pNextHeader;
1176 pHeader=pNextHeader;
1177 } 1057 }
1178 1058
1179 /* Free buffers: */ 1059 /* Free buffers: */
1180 wake_up_interruptible(&pInfo->read_wait); 1060 wake_up_interruptible(&pInfo->read_wait);
1181 kfree(pInfo->rx_buf); 1061 kfree(pInfo->rx_buf);
1182 TRACE_M("r3964_close - rx_buf kfree %p",pInfo->rx_buf); 1062 TRACE_M("r3964_close - rx_buf kfree %p", pInfo->rx_buf);
1183 kfree(pInfo->tx_buf); 1063 kfree(pInfo->tx_buf);
1184 TRACE_M("r3964_close - tx_buf kfree %p",pInfo->tx_buf); 1064 TRACE_M("r3964_close - tx_buf kfree %p", pInfo->tx_buf);
1185 kfree(pInfo); 1065 kfree(pInfo);
1186 TRACE_M("r3964_close - info kfree %p",pInfo); 1066 TRACE_M("r3964_close - info kfree %p", pInfo);
1187} 1067}
1188 1068
1189static ssize_t r3964_read(struct tty_struct *tty, struct file *file, 1069static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
1190 unsigned char __user *buf, size_t nr) 1070 unsigned char __user * buf, size_t nr)
1191{ 1071{
1192 struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; 1072 struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data;
1193 struct r3964_client_info *pClient; 1073 struct r3964_client_info *pClient;
1194 struct r3964_message *pMsg; 1074 struct r3964_message *pMsg;
1195 struct r3964_client_message theMsg; 1075 struct r3964_client_message theMsg;
1196 DECLARE_WAITQUEUE (wait, current); 1076 DECLARE_WAITQUEUE(wait, current);
1197 1077
1198 int count; 1078 int count;
1199 1079
1200 TRACE_L("read()"); 1080 TRACE_L("read()");
1201 1081
1202 pClient=findClient(pInfo, task_pid(current)); 1082 pClient = findClient(pInfo, task_pid(current));
1203 if(pClient) 1083 if (pClient) {
1204 { 1084 pMsg = remove_msg(pInfo, pClient);
1205 pMsg = remove_msg(pInfo, pClient); 1085 if (pMsg == NULL) {
1206 if(pMsg==NULL) 1086 /* no messages available. */
1207 { 1087 if (file->f_flags & O_NONBLOCK) {
1208 /* no messages available. */ 1088 return -EAGAIN;
1209 if (file->f_flags & O_NONBLOCK) 1089 }
1210 { 1090 /* block until there is a message: */
1211 return -EAGAIN; 1091 add_wait_queue(&pInfo->read_wait, &wait);
1212 }
1213 /* block until there is a message: */
1214 add_wait_queue(&pInfo->read_wait, &wait);
1215repeat: 1092repeat:
1216 current->state = TASK_INTERRUPTIBLE; 1093 current->state = TASK_INTERRUPTIBLE;
1217 pMsg = remove_msg(pInfo, pClient); 1094 pMsg = remove_msg(pInfo, pClient);
1218 if (!pMsg && !signal_pending(current)) 1095 if (!pMsg && !signal_pending(current)) {
1219 { 1096 schedule();
1220 schedule(); 1097 goto repeat;
1221 goto repeat; 1098 }
1222 } 1099 current->state = TASK_RUNNING;
1223 current->state = TASK_RUNNING; 1100 remove_wait_queue(&pInfo->read_wait, &wait);
1224 remove_wait_queue(&pInfo->read_wait, &wait); 1101 }
1225 } 1102
1226 1103 /* If we still haven't got a message, we must have been signalled */
1227 /* If we still haven't got a message, we must have been signalled */ 1104
1228 1105 if (!pMsg)
1229 if (!pMsg) return -EINTR; 1106 return -EINTR;
1230 1107
1231 /* deliver msg to client process: */ 1108 /* deliver msg to client process: */
1232 theMsg.msg_id = pMsg->msg_id; 1109 theMsg.msg_id = pMsg->msg_id;
1233 theMsg.arg = pMsg->arg; 1110 theMsg.arg = pMsg->arg;
1234 theMsg.error_code = pMsg->error_code; 1111 theMsg.error_code = pMsg->error_code;
1235 count = sizeof(struct r3964_client_message); 1112 count = sizeof(struct r3964_client_message);
1236 1113
1237 kfree(pMsg); 1114 kfree(pMsg);
1238 TRACE_M("r3964_read - msg kfree %p",pMsg); 1115 TRACE_M("r3964_read - msg kfree %p", pMsg);
1239 1116
1240 if (copy_to_user(buf,&theMsg, count)) 1117 if (copy_to_user(buf, &theMsg, count))
1241 return -EFAULT; 1118 return -EFAULT;
1242 1119
1243 TRACE_PS("read - return %d", count); 1120 TRACE_PS("read - return %d", count);
1244 return count; 1121 return count;
1245 } 1122 }
1246 return -EPERM; 1123 return -EPERM;
1247} 1124}
1248 1125
1249static ssize_t r3964_write(struct tty_struct * tty, struct file * file, 1126static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
1250 const unsigned char *data, size_t count) 1127 const unsigned char *data, size_t count)
1251{ 1128{
1252 struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; 1129 struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data;
1253 struct r3964_block_header *pHeader; 1130 struct r3964_block_header *pHeader;
1254 struct r3964_client_info *pClient; 1131 struct r3964_client_info *pClient;
1255 unsigned char *new_data; 1132 unsigned char *new_data;
1256 1133
1257 TRACE_L("write request, %d characters", count); 1134 TRACE_L("write request, %d characters", count);
1258/* 1135/*
1259 * Verify the pointers 1136 * Verify the pointers
1260 */ 1137 */
1261 1138
1262 if(!pInfo) 1139 if (!pInfo)
1263 return -EIO; 1140 return -EIO;
1264 1141
1265/* 1142/*
1266 * Ensure that the caller does not wish to send too much. 1143 * Ensure that the caller does not wish to send too much.
1267 */ 1144 */
1268 if (count > R3964_MTU) 1145 if (count > R3964_MTU) {
1269 { 1146 if (pInfo->flags & R3964_DEBUG) {
1270 if (pInfo->flags & R3964_DEBUG) 1147 TRACE_L(KERN_WARNING "r3964_write: truncating user "
1271 { 1148 "packet from %u to mtu %d", count, R3964_MTU);
1272 TRACE_L (KERN_WARNING 1149 }
1273 "r3964_write: truncating user packet " 1150 count = R3964_MTU;
1274 "from %u to mtu %d", count, R3964_MTU); 1151 }
1275 }
1276 count = R3964_MTU;
1277 }
1278/* 1152/*
1279 * Allocate a buffer for the data and copy it from the buffer with header prepended 1153 * Allocate a buffer for the data and copy it from the buffer with header prepended
1280 */ 1154 */
1281 new_data = kmalloc (count+sizeof(struct r3964_block_header), GFP_KERNEL); 1155 new_data = kmalloc(count + sizeof(struct r3964_block_header),
1282 TRACE_M("r3964_write - kmalloc %p",new_data); 1156 GFP_KERNEL);
1283 if (new_data == NULL) { 1157 TRACE_M("r3964_write - kmalloc %p", new_data);
1284 if (pInfo->flags & R3964_DEBUG) 1158 if (new_data == NULL) {
1285 { 1159 if (pInfo->flags & R3964_DEBUG) {
1286 printk (KERN_ERR 1160 printk(KERN_ERR "r3964_write: no memory\n");
1287 "r3964_write: no memory\n"); 1161 }
1288 } 1162 return -ENOSPC;
1289 return -ENOSPC; 1163 }
1290 } 1164
1291 1165 pHeader = (struct r3964_block_header *)new_data;
1292 pHeader = (struct r3964_block_header *)new_data; 1166 pHeader->data = new_data + sizeof(struct r3964_block_header);
1293 pHeader->data = new_data + sizeof(struct r3964_block_header); 1167 pHeader->length = count;
1294 pHeader->length = count; 1168 pHeader->locks = 0;
1295 pHeader->locks = 0; 1169 pHeader->owner = NULL;
1296 pHeader->owner = NULL; 1170
1297 1171 pClient = findClient(pInfo, task_pid(current));
1298 pClient=findClient(pInfo, task_pid(current)); 1172 if (pClient) {
1299 if(pClient) 1173 pHeader->owner = pClient;
1300 { 1174 }
1301 pHeader->owner = pClient; 1175
1302 } 1176 memcpy(pHeader->data, data, count); /* We already verified this */
1303 1177
1304 memcpy(pHeader->data, data, count); /* We already verified this */ 1178 if (pInfo->flags & R3964_DEBUG) {
1305 1179 dump_block(pHeader->data, count);
1306 if(pInfo->flags & R3964_DEBUG) 1180 }
1307 {
1308 dump_block(pHeader->data, count);
1309 }
1310 1181
1311/* 1182/*
1312 * Add buffer to transmit-queue: 1183 * Add buffer to transmit-queue:
1313 */ 1184 */
1314 add_tx_queue(pInfo, pHeader); 1185 add_tx_queue(pInfo, pHeader);
1315 trigger_transmit(pInfo); 1186 trigger_transmit(pInfo);
1316 1187
1317 return 0; 1188 return 0;
1318} 1189}
1319 1190
1320static int r3964_ioctl(struct tty_struct * tty, struct file * file, 1191static int r3964_ioctl(struct tty_struct *tty, struct file *file,
1321 unsigned int cmd, unsigned long arg) 1192 unsigned int cmd, unsigned long arg)
1322{ 1193{
1323 struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; 1194 struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data;
1324 if(pInfo==NULL) 1195 if (pInfo == NULL)
1325 return -EINVAL; 1196 return -EINVAL;
1326 switch(cmd) 1197 switch (cmd) {
1327 { 1198 case R3964_ENABLE_SIGNALS:
1328 case R3964_ENABLE_SIGNALS: 1199 return enable_signals(pInfo, task_pid(current), arg);
1329 return enable_signals(pInfo, task_pid(current), arg); 1200 case R3964_SETPRIORITY:
1330 case R3964_SETPRIORITY: 1201 if (arg < R3964_MASTER || arg > R3964_SLAVE)
1331 if(arg<R3964_MASTER || arg>R3964_SLAVE) 1202 return -EINVAL;
1332 return -EINVAL; 1203 pInfo->priority = arg & 0xff;
1333 pInfo->priority = arg & 0xff; 1204 return 0;
1334 return 0; 1205 case R3964_USE_BCC:
1335 case R3964_USE_BCC: 1206 if (arg)
1336 if(arg) 1207 pInfo->flags |= R3964_BCC;
1337 pInfo->flags |= R3964_BCC; 1208 else
1338 else 1209 pInfo->flags &= ~R3964_BCC;
1339 pInfo->flags &= ~R3964_BCC; 1210 return 0;
1340 return 0; 1211 case R3964_READ_TELEGRAM:
1341 case R3964_READ_TELEGRAM: 1212 return read_telegram(pInfo, task_pid(current),
1342 return read_telegram(pInfo, task_pid(current), (unsigned char __user *)arg); 1213 (unsigned char __user *)arg);
1343 default: 1214 default:
1344 return -ENOIOCTLCMD; 1215 return -ENOIOCTLCMD;
1345 } 1216 }
1346} 1217}
1347 1218
1348static void r3964_set_termios(struct tty_struct *tty, struct ktermios * old) 1219static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old)
1349{ 1220{
1350 TRACE_L("set_termios"); 1221 TRACE_L("set_termios");
1351} 1222}
1352 1223
1353/* Called without the kernel lock held - fine */ 1224/* Called without the kernel lock held - fine */
1354static unsigned int r3964_poll(struct tty_struct * tty, struct file * file, 1225static unsigned int r3964_poll(struct tty_struct *tty, struct file *file,
1355 struct poll_table_struct *wait) 1226 struct poll_table_struct *wait)
1356{ 1227{
1357 struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; 1228 struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data;
1358 struct r3964_client_info *pClient; 1229 struct r3964_client_info *pClient;
1359 struct r3964_message *pMsg=NULL; 1230 struct r3964_message *pMsg = NULL;
1360 unsigned long flags; 1231 unsigned long flags;
1361 int result = POLLOUT; 1232 int result = POLLOUT;
1362 1233
1363 TRACE_L("POLL"); 1234 TRACE_L("POLL");
1364 1235
1365 pClient=findClient(pInfo, task_pid(current)); 1236 pClient = findClient(pInfo, task_pid(current));
1366 if(pClient) 1237 if (pClient) {
1367 { 1238 poll_wait(file, &pInfo->read_wait, wait);
1368 poll_wait(file, &pInfo->read_wait, wait); 1239 spin_lock_irqsave(&pInfo->lock, flags);
1369 spin_lock_irqsave(&pInfo->lock, flags); 1240 pMsg = pClient->first_msg;
1370 pMsg=pClient->first_msg; 1241 spin_unlock_irqrestore(&pInfo->lock, flags);
1371 spin_unlock_irqrestore(&pInfo->lock, flags); 1242 if (pMsg)
1372 if(pMsg) 1243 result |= POLLIN | POLLRDNORM;
1373 result |= POLLIN | POLLRDNORM; 1244 } else {
1374 } 1245 result = -EINVAL;
1375 else 1246 }
1376 { 1247 return result;
1377 result = -EINVAL;
1378 }
1379 return result;
1380} 1248}
1381 1249
1382static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, 1250static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
1383 char *fp, int count) 1251 char *fp, int count)
1384{ 1252{
1385 struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; 1253 struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data;
1386 const unsigned char *p; 1254 const unsigned char *p;
1387 char *f, flags = 0; 1255 char *f, flags = 0;
1388 int i; 1256 int i;
1389 1257
1390 for (i=count, p = cp, f = fp; i; i--, p++) { 1258 for (i = count, p = cp, f = fp; i; i--, p++) {
1391 if (f) 1259 if (f)
1392 flags = *f++; 1260 flags = *f++;
1393 if(flags==TTY_NORMAL) 1261 if (flags == TTY_NORMAL) {
1394 { 1262 receive_char(pInfo, *p);
1395 receive_char(pInfo, *p); 1263 } else {
1396 } 1264 receive_error(pInfo, flags);
1397 else 1265 }
1398 { 1266
1399 receive_error(pInfo, flags); 1267 }
1400 }
1401
1402 }
1403} 1268}
1404 1269
1405MODULE_LICENSE("GPL"); 1270MODULE_LICENSE("GPL");