]> rtime.felk.cvut.cz Git - sysless.git/blob - arch/m68k/generic/drivers/qsm_rs232.c
2f05bd1b458660e460116c0f0126276a0063feca
[sysless.git] / arch / m68k / generic / drivers / qsm_rs232.c
1 /*******************************************************************
2   Components for embedded applications builded for
3   laboratory and medical instruments firmware  
4  
5   qsm_rs232.c - 683xx QSM module RS-232 communication implementation
6  
7   Copyright (C) 2001-2003 by Pavel Pisa pisa@cmp.felk.cvut.cz
8             (C) 2001-2003 by PiKRON Ltd. http://www.pikron.com
9
10  *******************************************************************/
11
12 #include <types.h>
13 #include <system_def.h>
14 #include <sim.h>
15 #include <qsm.h>
16 #include <periph/qsm_rs232.h>
17
18 #define QSM_CHAR_XON  0x11
19 #define QSM_CHAR_XOFF 0x13
20
21 #define QSM_RS232_RTS_PEM (1<<0)
22 #define QSM_RS232_CTS_PEM (1<<1)
23
24 #define qsm_rs232_rts_true() \
25         atomic_set_mask_b(QSM_RS232_RTS_PEM,SIM_PORTE0)
26 #define qsm_rs232_rts_false()  \
27         atomic_clear_mask_b(QSM_RS232_RTS_PEM,SIM_PORTE0)
28 #define qsm_rs232_cts()       (!(*SIM_PORTE0&QSM_RS232_CTS_PEM))
29
30 int qsm_rs232_baud=9600;
31 int qsm_rs232_mode=QSM_RS232_MODEA;
32 int qsm_rs232_flowc=1;
33 #define QSM_RSFLC_HW  0x1
34 #define QSM_RSFLC_XON 0x2
35
36 typedef volatile struct{
37   uint8_t *buf_beg;
38   uint8_t *buf_end;
39   uint8_t *ip;
40   uint8_t *op;
41 } qsm_que_t;
42
43 #define QSM_RS232_BUF_LEN    (80*8)
44 #define QSM_RS232_BUF_FULLTG (84)
45
46 qsm_que_t qsm_rs232_que_in;     /* input qureue */
47 uint8_t qsm_rs232_buf_in[QSM_RS232_BUF_LEN];
48
49 qsm_que_t qsm_rs232_que_out;    /* output queue */
50 uint8_t qsm_rs232_buf_out[QSM_RS232_BUF_LEN];
51
52 short qsm_rs232_flags;
53 #define QSM_RSFL_ROR   0x1
54 #define QSM_RSFL_RFE   0x2
55 #define QSM_RSFL_RPE   0x4
56 #define QSM_RSFL_SXOFF 0x10
57 #define QSM_RSFL_SXON  0x20
58 #define QSM_RSFL_TFCDI 0x40
59 #define QSM_RSFL_RFCDI 0x80
60 #define QSM_RSFL_TIP   0x100
61 #define QSM_RSFL_TWCTS 0x200
62
63 int qsm_rs232_irq_cnt;
64
65
66 /* put character c into queue, if full return -1 */
67 int qsm_que_put(qsm_que_t *q, int c)
68 {
69   uint8_t *p;
70   p=q->ip;
71   *(p++)=c;
72   if(p==q->buf_end) p=q->buf_beg;
73   if(p==q->op) return -1;
74   q->ip=p;
75   return c;
76 }
77
78 /* get character from queue, if empty return -1 */
79 int qsm_que_get(qsm_que_t *q)
80 {
81   uint8_t *p;
82   int  c;
83   p=q->op;
84   if(p==q->ip) return -1;
85   c=*(p++);
86   if(p==q->buf_end) p=q->buf_beg;
87   q->op=p;
88   return c;
89 }
90
91 int qsm_que_freecnt(qsm_que_t *q)
92 {
93   uint8_t *ip=q->ip,*op=q->op;
94   return op-ip-1+(op<=ip?q->buf_end-q->buf_beg:0);
95 }
96
97 int qsm_que_incnt(qsm_que_t *q)
98 {
99   uint8_t *ip=q->ip,*op=q->op;
100   return ip-op+(ip<op?q->buf_end-q->buf_beg:0);
101 }
102
103 #ifdef WITH_GDBSTUB
104 void putDebugChar(int ch)      /* write a single character      */
105 {
106   while(!(*QSM_SCSR&QSM_TDRE)) ;
107   *QSM_SCDR=ch;
108 }
109
110 int getDebugChar(void)         /* read and return a single char */
111 {
112   while(!(*QSM_SCSR&QSM_RDRF)) ;
113   return *QSM_SCDR;
114 }
115
116 extern void qsm_rs232_gdb_isr();
117
118 __asm__ (
119   ".even\n\t"
120   "qsm_rs232_gdb_isr:\n\t"
121   /* emulate vector 31 SIGINT - unix signal number 2 */
122   "movew #0x7c,%sp@(6)\n\t"
123   "subl  #4,%sp\n\t"
124   "movel %a0,%sp@-\n\t"
125   "movec %vbr,%a0\n\t"
126   /* redirect to the vector 31 */
127   "movel %a0@(0x7c),%a0\n\t"
128   "movel %a0,%sp@(4)\n\t"
129   "movel %sp@+,%a0\n\t"
130   "rts\n\t"
131 );
132
133 void qsm_used4gdbdirect(void)
134 {
135   void **vbr;
136   /* only receive interrupt is used */
137   atomic_clear_mask_w(QSM_TIE|QSM_ILIE,QSM_SCCR1);
138   __get_vbr(vbr);
139   vbr[ISR_QSM_INTV]=qsm_rs232_gdb_isr;
140 }
141
142 #endif /* WITH_GDBSTUB */
143
144
145 void qsm_rs232_isr(int intno, void *dev_id, struct pt_regs *regs)
146 {
147   union{
148     uint32_t srdr;
149     struct{
150       uint16_t sr;
151       uint16_t dr;
152     } s;
153   } scsrdr;
154   short val;
155   
156   qsm_rs232_irq_cnt++;
157   scsrdr.srdr=*(volatile uint32_t*)QSM_SCSR;
158   if(scsrdr.s.sr&QSM_RDRF){
159     /* character received */
160     do{
161      #ifdef WITH_GDBSTUB
162       if((qsm_break2gdb&&(scsrdr.s.dr==0x3))||qsm_used4gdbonly){
163         /* ctrl+c received or GDB-only set */
164         /* initiate exception 31 equal to */
165         /* SIGINT - unix signal number 2 */;    
166         regs->vector=4*31; /* emulated SIGINT vector */
167         irq_redirect2vector(31,regs);
168         break;
169       }
170      #endif /* WITH_GDBSTUB */
171       if(scsrdr.s.sr&(QSM_OR|QSM_FE|QSM_PE)){
172         if(scsrdr.s.sr&QSM_OR)qsm_rs232_flags|=QSM_RSFL_ROR;
173         if(scsrdr.s.sr&QSM_FE)qsm_rs232_flags|=QSM_RSFL_RFE;      
174         if(scsrdr.s.sr&QSM_PE)qsm_rs232_flags|=QSM_RSFL_RPE;
175         break;
176       }
177       if(qsm_rs232_flowc&QSM_RSFLC_XON){
178         if(scsrdr.s.dr==QSM_CHAR_XON){
179           qsm_rs232_flags&=~QSM_RSFL_TFCDI;
180           break;
181         }else if(scsrdr.s.dr==QSM_CHAR_XOFF){
182           qsm_rs232_flags|=QSM_RSFL_TFCDI;
183           break;
184         }
185       }
186       if(qsm_que_put(&qsm_rs232_que_in,scsrdr.s.dr)<0)
187         qsm_rs232_flags|=QSM_RSFL_ROR;
188       if((!(qsm_rs232_flags&QSM_RSFL_RFCDI))&&
189          (qsm_que_freecnt(&qsm_rs232_que_in)<=QSM_RS232_BUF_FULLTG)){
190         qsm_rs232_flags|=QSM_RSFL_RFCDI;
191         if(qsm_rs232_flowc&QSM_RSFLC_XON){
192           qsm_rs232_flags&=~QSM_RSFL_SXON;
193           qsm_rs232_flags|=QSM_RSFL_SXOFF;
194         }
195         if(qsm_rs232_flowc&QSM_RSFLC_HW)  qsm_rs232_rts_false();
196       }
197     }while(0);
198   }
199   
200   if(scsrdr.s.sr&QSM_TDRE){
201     atomic_clear_mask_w(QSM_TIE,QSM_SCCR1);
202    #ifdef WITH_GDBSTUB
203     if(qsm_used4gdbonly) {
204       return;
205     }
206    #endif /* WITH_GDBSTUB*/
207     qsm_rs232_flags&=~QSM_RSFL_TIP;
208     if(!(qsm_rs232_flowc&QSM_RSFLC_HW)||qsm_rs232_cts()){
209       qsm_rs232_flowc&=~QSM_RSFL_TWCTS;
210       if(qsm_rs232_flags&(QSM_RSFL_SXON|QSM_RSFL_SXOFF)){
211         val=qsm_rs232_flags&QSM_RSFL_SXON?QSM_CHAR_XON:QSM_CHAR_XOFF;
212         qsm_rs232_flags&=~(QSM_RSFL_SXON|QSM_RSFL_SXOFF);
213         qsm_rs232_flags|=QSM_RSFL_TIP;
214         *QSM_SCDR=val;
215         atomic_set_mask_w(QSM_TIE,QSM_SCCR1);
216       }else{
217         if(!(qsm_rs232_flags&QSM_RSFL_TFCDI)){
218           if((val=qsm_que_get(&qsm_rs232_que_out))>=0){
219             qsm_rs232_flags|=QSM_RSFL_TIP;
220             *QSM_SCDR=val;
221             atomic_set_mask_w(QSM_TIE,QSM_SCCR1);
222           }
223         }
224       }
225     }else
226       qsm_rs232_flowc|=QSM_RSFL_TWCTS;
227   }
228 }
229
230 int qsm_rs232_sendch(int c)
231 {
232   if(qsm_que_put(&qsm_rs232_que_out,c)<0){ 
233     if((qsm_rs232_flags&QSM_RSFL_TWCTS)&&qsm_rs232_cts())
234       atomic_set_mask_w(QSM_TIE,QSM_SCCR1);
235     c=-1;
236   }
237   if(qsm_rs232_flags&QSM_RSFL_TIP) return c;
238   if(qsm_rs232_flags&QSM_RSFL_TFCDI) return c;
239   if((qsm_rs232_flowc&QSM_RSFLC_HW)&&!qsm_rs232_cts()){
240     __memory_barrier();
241     qsm_rs232_flags|=QSM_RSFL_TWCTS;
242     __memory_barrier();
243     return c;
244   }
245   atomic_set_mask_w(QSM_TIE,QSM_SCCR1);
246   return c;
247 }
248
249 int qsm_rs232_recch()
250 {
251   int val;
252   if((qsm_rs232_flags&QSM_RSFL_TWCTS)&&qsm_rs232_cts())
253     atomic_set_mask_w(QSM_TIE,QSM_SCCR1);
254   val=qsm_que_get(&qsm_rs232_que_in);
255   if(qsm_rs232_flags&QSM_RSFL_RFCDI)
256   {
257     if(qsm_que_freecnt(&qsm_rs232_que_in)>=QSM_RS232_BUF_FULLTG+8)
258     {
259       if(qsm_rs232_flowc&QSM_RSFLC_HW)
260         qsm_rs232_rts_true();
261       __memory_barrier();
262       qsm_rs232_flags&=~QSM_RSFL_RFCDI;
263       __memory_barrier();
264     }
265   }
266   return val;
267 }
268
269 int qsm_rs232_sendstr(const char *s)
270 {
271   int cnt=0;
272   while(*s)
273   {
274     if(qsm_rs232_sendch((unsigned char)(*(s++)))<0) break;
275     cnt++;
276   }
277   return cnt;
278 }
279
280
281 /*  
282   unsigned flags;
283   save_and_cli(flags);
284
285   restore_flags(flags);
286 */
287
288 irq_handler_t qsm_rs232_handler={
289   handler: qsm_rs232_isr,
290   flags:   0,
291   dev_id:  0,
292   devname: "qsm_rs232",
293   next:    0
294 };
295
296
297 int qsm_rs232_setmode(int baud, int mode, int flowc)
298 {
299   if(baud==-1) baud=qsm_rs232_baud;
300   if(mode==-1) mode=qsm_rs232_mode;
301   if(flowc==-1) flowc=qsm_rs232_flowc;
302   
303   atomic_clear_mask_w(QSM_RIE|QSM_TIE|QSM_TCIE|QSM_ILIE,QSM_SCCR1);
304   __memory_barrier();
305   qsm_used4gdbonly=0;
306   qsm_rs232_baud=baud;
307   baud*=32;
308   *QSM_SCCR0=(cpu_sys_hz+baud/2)/baud;  /* SCBR */
309   qsm_rs232_mode=mode;
310   *QSM_SCCR1=mode;
311   qsm_rs232_flowc=flowc;
312   qsm_rs232_flags=0;
313
314   *QSM_PORTQS|=0x80;
315   *QSM_DDRQS|=0x80;
316   *QSM_PQSPAR|=0x80;
317   
318   qsm_rs232_que_in.buf_beg=qsm_rs232_buf_in;
319   qsm_rs232_que_in.buf_end=qsm_rs232_que_in.buf_beg+sizeof(qsm_rs232_buf_in);
320   qsm_rs232_que_in.ip=qsm_rs232_que_in.buf_beg;
321   qsm_rs232_que_in.op=qsm_rs232_que_in.buf_beg;
322
323   qsm_rs232_que_out.buf_beg=qsm_rs232_buf_out;
324   qsm_rs232_que_out.buf_end=qsm_rs232_que_out.buf_beg+sizeof(qsm_rs232_buf_out);
325   qsm_rs232_que_out.ip=qsm_rs232_que_out.buf_beg;
326   qsm_rs232_que_out.op=qsm_rs232_que_out.buf_beg;
327
328   if(qsm_rs232_flowc&QSM_RSFLC_HW){
329    *SIM_DDRE|=QSM_RS232_RTS_PEM;   
330    *SIM_DDRE&=~QSM_RS232_CTS_PEM;
331    *SIM_PEPAR&=~(QSM_RS232_CTS_PEM|QSM_RS232_RTS_PEM);
332    qsm_rs232_rts_true();
333   }
334
335   __memory_barrier();
336   *QSM_CR&=~(QSM_STOP|(QSM_IARB^ISR_QSM_IARB));
337   *QSM_CR|=ISR_QSM_IARB;
338   *QSM_QILR&=~QSM_ILSCI;
339   *QSM_QIVR=ISR_QSM_INTV;
340   *QSM_QILR|=ISR_QSM_ILSCI;
341   qsm_rs232_irq_cnt=0;
342   if(test_irq_handler(ISR_QSM_INTV,&qsm_rs232_handler)==0)
343     add_irq_handler(ISR_QSM_INTV,&qsm_rs232_handler);
344
345   atomic_set_mask_w(QSM_RIE,QSM_SCCR1);
346   return 1;
347 }
348