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