OSDN Git Service

c20770e06e3f83dc54a3d822178c52210baf3236
[trx-305dsp/dsp.git] / trx305 / kernel / pdic / simple_sio / st16c2550.c
1 /*
2  *  TOPPERS/JSP Kernel
3  *      Toyohashi Open Platform for Embedded Real-Time Systems/
4  *      Just Standard Profile Kernel
5  * 
6  *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
7  *                              Toyohashi Univ. of Technology, JAPAN
8  * 
9  *  上記著作権者は,以下の (1)〜(4) の条件か,Free Software Foundation 
10  *  によって公表されている GNU General Public License の Version 2 に記
11  *  述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
12  *  を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
13  *  利用と呼ぶ)することを無償で許諾する.
14  *  (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
15  *      権表示,この利用条件および下記の無保証規定が,そのままの形でソー
16  *      スコード中に含まれていること.
17  *  (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
18  *      用できる形で再配布する場合には,再配布に伴うドキュメント(利用
19  *      者マニュアルなど)に,上記の著作権表示,この利用条件および下記
20  *      の無保証規定を掲載すること.
21  *  (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
22  *      用できない形で再配布する場合には,次のいずれかの条件を満たすこ
23  *      と.
24  *    (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
25  *        作権表示,この利用条件および下記の無保証規定を掲載すること.
26  *    (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
27  *        報告すること.
28  *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
29  *      害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
30  * 
31  *  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
32  *  よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
33  *  含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
34  *  接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
35  * 
36  *  @(#) $Id: st16c2550.c,v 1.1 2009/01/31 05:27:37 suikan Exp $
37  */
38
39 /*
40  *     ST16C2550 用 簡易SIOドライバ
41  */
42 #include <s_services.h>
43 #include <st16c2550.h>
44  
45 /*
46  * 各レジスタのオフセット
47  */
48 #define ST16C_RHR   0x00   /* H  LCR bit7=0 Read  */
49 #define ST16C_THR   0x00   /* H  LCR bit7=0 Write */
50 #define ST16C_DLL   0x00   /* H  LCR bit7=1       */
51 #define ST16C_IER   0x02   /* H  LCR bit7=0       */
52 #define ST16C_DLM   0x02   /* H  LCR bit7=1       */
53 #define ST16C_ISR   0x04   /* H  Read  */
54 #define ST16C_FCR   0x04   /* H  Write */
55 #define ST16C_LCR   0x06   /* H  */
56 #define ST16C_MCR   0x08   /* H  */
57 #define ST16C_LSR   0x0a   /* H  Read */
58 #define ST16C_MSR   0x0c   /* H  Read */
59 #define ST16C_SPR   0x0e   /* H  */
60
61 #define ISR_TX            0x02       /* 送信割り込み発生 */
62 #define IER_TX            0x02       /* 送信割り込み許可 */
63 #define ISR_RX            0x01       /* 受信割り込み発生 */
64 #define IER_RX            0x01       /* 受信割り込み許可 */
65
66 #define LCR_DL_MODE       0x80       /* Divisor Enable */
67 #define LCR_VAL           0x03       /* 8bit,1stop,Noparity,No break */
68 #define FCR_FIFO_DISABLE  0x00
69
70 #define LSR_RX_DATA_READY 0x01
71 #define LSR_TX_EMPTY      0x20
72
73 #define MCR_INT_ENABLE    0x08
74
75 /*
76  *  115200bpsに設定
77  *  4 = (7372800Hz)/(115200*16)
78  */
79 #define DLM_VAL  0x00
80 #define DLL_VAL  0x04
81
82
83
84
85 /*
86  * シリアルI/Oポート初期化ブロック
87  */
88 const SIOPINIB siopinib_table[TNUM_SIOP] = {
89     {ST16C_CHB, LCR_VAL, DLM_VAL, DLL_VAL, PINTER_PINT7E},
90 #if TNUM_SIOP > 2
91     {ST16C_CHA, LCR_VAL, DLM_VAL, DLL_VAL, PINTER_PINT6E},
92 #endif /* TNUM_SIOP > 2 */    
93 };
94
95 /*
96  *  シリアルI/Oポート初期化ブロックの取出し
97  */
98 #define INDEX_SIOPINIB(siopid)  ((UINT)((siopid) - 1))
99 #define get_siopinib(siopid)  (&(siopinib_table[INDEX_SIOPINIB(siopid)]))
100
101
102 /*
103  *  シリアルI/Oポート管理ブロックのエリア
104  */
105 SIOPCB  siopcb_table[TNUM_SIOP];
106
107 /*
108  *  シリアルI/OポートIDから管理ブロックを取り出すためのマクロ
109  */
110 #define INDEX_SIOP(siopid)  ((UINT)((siopid) - 1))
111 #define get_siopcb(siopid)  (&(siopcb_table[INDEX_SIOP(siopid)]))
112
113 Inline void
114 st16c_write(UW addr, UW offset, UB val)
115 {
116     sil_wrh_mem((VP)(addr + offset),val);
117 }
118
119 Inline UB
120 st16c_read(UW addr, UW offset)
121 {
122     return(sil_reh_mem((VP)(addr + offset)));
123 }
124
125
126 /*
127  * 文字を受信したか?
128  */ 
129 Inline BOOL
130 st16c_getready(SIOPCB *siopcb)
131 {
132     UH status;
133
134     status = st16c_read(siopcb->siopinib->reg_base, ST16C_LSR);
135     
136     return((status & LSR_RX_DATA_READY));
137 }
138
139 /*
140  * 文字を送信できるか?
141  */
142 Inline BOOL
143 st16c_putready(SIOPCB *siopcb)
144 {
145     UH status;
146
147     status = st16c_read(siopcb->siopinib->reg_base, ST16C_LSR);
148     
149     return (status & LSR_TX_EMPTY);
150 }
151
152 /*
153  *  受信した文字の取り出し
154  */
155 Inline UB
156 st16c_getchar(SIOPCB *siopcb)
157 {
158     return(st16c_read(siopcb->siopinib->reg_base,ST16C_RHR));
159 }
160
161 /*
162  *  送信する文字の書き込み
163  */
164 Inline void
165 st16c_putchar(SIOPCB *siopcb, UB c)
166 {
167     st16c_write(siopcb->siopinib->reg_base, ST16C_THR, c);
168 }
169
170 /*
171  *  送信割込み許可
172  */
173 Inline void
174 st16c_enable_send(SIOPCB *siopcb)
175 {
176     st16c_write(siopcb->siopinib->reg_base, ST16C_IER,
177                 (st16c_read(siopcb->siopinib->reg_base,ST16C_IER) | IER_TX));
178 }
179
180 /*
181  *  送信割込み禁止
182  */
183 Inline void
184 st16c_disable_send(SIOPCB *siopcb)
185 {
186     st16c_write(siopcb->siopinib->reg_base, ST16C_IER,
187                 (st16c_read(siopcb->siopinib->reg_base, ST16C_IER) & ~IER_TX));
188                 
189 }
190
191 /*
192  *  受信割込み許可
193  */
194 Inline void
195 st16c_enable_rcv(SIOPCB *siopcb)
196 {
197     st16c_write(siopcb->siopinib->reg_base, ST16C_IER,
198                 (st16c_read(siopcb->siopinib->reg_base,ST16C_IER) | IER_RX));
199 }
200
201 /*
202  *  受信割込み禁止
203  */
204 Inline void
205 st16c_disable_rcv(SIOPCB *siopcb)
206 {
207     st16c_write(siopcb->siopinib->reg_base, ST16C_IER,
208                 (st16c_read(siopcb->siopinib->reg_base, ST16C_IER) & ~IER_RX));
209                 
210 }
211
212
213 /*
214  *  SIOドライバの初期化ルーチン
215  */
216 void
217 st16c2550_initialize()
218 {
219     SIOPCB  *siopcb;
220     UINT    i;
221
222     /*
223      *  シリアルI/Oポート管理ブロックの初期化
224      */
225     for (siopcb = siopcb_table, i = 0; i < TNUM_SIOP; siopcb++, i++) {
226         siopcb->siopinib = &(siopinib_table[i]);
227         siopcb->openflag = FALSE;
228         siopcb->sendflag = FALSE;
229     }
230 }
231
232     
233 /*
234  *
235  */
236 void
237 st16c2550_init_siopinib(const SIOPINIB *siopinib)
238 {
239     /*
240      *  分周比の設定
241      */
242     /* Divisor Enable */
243     st16c_write(siopinib->reg_base, ST16C_LCR,
244                 (st16c_read(siopinib->reg_base, ST16C_LCR) | LCR_DL_MODE));
245     st16c_write(siopinib->reg_base, ST16C_DLL, siopinib->dll_val);
246     st16c_write(siopinib->reg_base, ST16C_DLM, siopinib->dlm_val);
247     /* Divisor Disable */
248     st16c_write(siopinib->reg_base, ST16C_LCR,
249                 (st16c_read(siopinib->reg_base, ST16C_LCR) & ~LCR_DL_MODE));
250
251     /* モード設定 */
252     st16c_write(siopinib->reg_base, ST16C_LCR, siopinib->lcr_val);
253
254     /* FIFO Disable */
255     st16c_write(siopinib->reg_base, ST16C_FCR, FCR_FIFO_DISABLE);
256
257     /* 割込み禁止 */
258     st16c_write(siopinib->reg_base, ST16C_IER, 0x00);
259 }
260
261
262 /*
263  *  カーネル起動時のバーナー出力用の初期化
264  */
265 void
266 st16c2550_init(void)
267 {
268     
269     st16c2550_init_siopinib(get_siopinib(1));
270 #if TNUM_SIOP > 2
271     st16c2550_init_siopinib(get_siopinib(2));    
272 #endif /* TNUM_SIOP > 2 */        
273     
274 }
275
276 /*
277  * オープンしているポートがあるか
278  */
279 BOOL
280 st16c2550_openflag(void)
281 {
282 #if TNUM_SIOP < 2
283     return(siopcb_table[0].openflag);
284 #else /* TNUM_SIOP < 2 */
285     return(siopcb_table[0].openflag || siopcb_table[1].openflag);
286 #endif /* TNUM_SIOP < 2 */
287 }
288
289
290 /*
291  * シリアルI/Oポートのオープン
292  */
293 SIOPCB *
294 st16c2550_opn_por(ID siopid, VP_INT exinf)
295 {
296     SIOPCB      *siopcb;
297     const SIOPINIB  *siopinib;
298
299     siopcb = get_siopcb(siopid);
300     siopinib = siopcb->siopinib;
301     
302     /*
303      * 初期化
304      */
305     st16c2550_init_siopinib(siopcb->siopinib);
306     
307     /* 受信割込み許可 */
308     st16c_write(siopcb->siopinib->reg_base, ST16C_IER, IER_RX);
309     
310     /* 割込み線をイネーブル */
311     st16c_write(siopcb->siopinib->reg_base, ST16C_MCR, MCR_INT_ENABLE);
312
313     siopcb->exinf = exinf;
314     siopcb->getready = siopcb->putready = FALSE;
315     siopcb->openflag = TRUE;
316
317     return(siopcb);
318 }
319
320 /*
321  *  シリアルI/Oポートのクローズ
322  */
323 void
324 st16c2550_cls_por(SIOPCB *siopcb)
325 {
326     /* 割込み禁止 */
327     st16c_write(siopcb->siopinib->reg_base, ST16C_IER, 0x00);   
328     siopcb->openflag = FALSE;
329 }
330
331
332 /*
333  *  シリアルI/Oポートへのポーリングでの出力
334  */
335 void
336 st16c2550_pol_putc(char c, ID siopid)
337 {
338     const SIOPINIB *siopinib;
339     
340     siopinib = get_siopinib(siopid);
341     
342     while((st16c_read(siopinib->reg_base, ST16C_LSR) & LSR_TX_EMPTY)
343           != LSR_TX_EMPTY)
344         ;
345     st16c_write(siopinib->reg_base, ST16C_THR, c);
346 }
347
348
349 /*
350  *  シリアルI/Oポートへの文字送信
351  */
352 BOOL
353 st16c2550_snd_chr(SIOPCB *siopcb, char c)
354 {
355     if (st16c_putready(siopcb)){
356         st16c_putchar(siopcb, c);
357         return(TRUE);
358     }
359     return(FALSE);
360 }
361
362 /*
363  *  シリアルI/Oポートからの文字受信
364  */
365 INT
366 st16c2550_rcv_chr(SIOPCB *siopcb)
367 {
368     if (st16c_getready(siopcb)) {
369         return((INT)(UB) st16c_getchar(siopcb));
370     }
371     return(-1);
372 }
373
374
375
376
377
378 /*
379  *  シリアルI/Oポートからのコールバックの許可
380  */
381 void
382 st16c2550_ena_cbr(SIOPCB *siopcb, UINT cbrtn)
383 {
384
385     switch (cbrtn) {
386         case SIO_ERDY_SND:
387             st16c_enable_send(siopcb);
388             break;
389         case SIO_ERDY_RCV:
390             st16c_enable_rcv(siopcb);
391             break;
392     }
393 }
394
395 /*
396  *  シリアルI/Oポートからのコールバックの禁止
397  */
398 void
399 st16c2550_dis_cbr(SIOPCB *siopcb, UINT cbrtn)
400 {
401     switch (cbrtn) {
402         case SIO_ERDY_SND:
403             st16c_disable_send(siopcb);
404             break;
405         case SIO_ERDY_RCV:
406             st16c_disable_rcv(siopcb);
407             break;
408     }
409 }
410
411 /*
412  *  シリアルI/Oポートに対する割込み処理
413  */
414 static void
415 st16c2550_isr_siop(SIOPCB *siopcb)
416 {
417     if (st16c_getready(siopcb)) {
418         /*
419          *  受信通知コールバックルーチンを呼び出す.
420          */
421         st16c2550_ierdy_rcv(siopcb->exinf);
422     }
423     if (st16c_putready(siopcb)) {
424         /*
425          *  送信可能コールバックルーチンを呼び出す.
426          */
427         st16c2550_ierdy_snd(siopcb->exinf);
428     }
429 }
430
431 /*
432  *  SIOの割込みサービスルーチン
433  */
434 void
435 st16c2550_isr()
436 {
437     st16c2550_isr_siop(&(siopcb_table[0]));
438 }