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