OSDN Git Service

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