source: anotherchoice/tags/jsp-1.4.4-full-UTF8/systask/serial.c@ 26

Last change on this file since 26 was 26, checked in by ykominami, 10 years ago

initial

File size: 13.7 KB
Line 
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 * Copyright (C) 2006 by Embedded and Real-Time Systems Laboratory
9 * Graduate School of Information Science, Nagoya Univ., JAPAN
10 *
11 * 上記著作権者
12は,以下の (1)〜(4) の条件か,Free Software Foundation
13 * によってå…
14¬è¡¨ã•ã‚Œã¦ã„ã‚‹ GNU General Public License の Version 2 に記
15 * 述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
16 * を改変したものを含む.以下同じ)を使用・複製・改変・再é…
17å¸ƒï¼ˆä»¥ä¸‹ï¼Œ
18 * 利用と呼ぶ)することを無償で許諾する.
19 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
20 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
21 * スコード中に含まれていること.
22 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
23 * 用できる形で再é…
24å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
25å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
26 * 者
27マニュアルなど)に,上記の著作権表示,この利用条件および下記
28 * の無保証規定を掲載すること.
29 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
30 * 用できない形で再é…
31å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®ã„ずれかの条件を満たすこ
32 * と.
33 * (a) 再é…
34å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
35マニュアルなど)に,上記の著
36 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
37 * (b) 再é…
38å¸ƒã®å½¢æ…
39‹ã‚’,別に定める方法によって,TOPPERSプロジェクトに
40 * 報告すること.
41 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
42 * 害からも,上記著作権者
43およびTOPPERSプロジェクトをå…
44è²¬ã™ã‚‹ã“と.
45 *
46 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者
47お
48 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
49 * 含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
50 * 接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
51 *
52 * @(#) $Id: serial.c,v 1.16 2006/02/12 05:26:42 hiro Exp $
53 */
54
55/*
56 * シリアルインタフェースドライバ
57 */
58
59#include <t_services.h>
60#include <serial.h>
61#include <hw_serial.h>
62#include "kernel_id.h"
63
64/*
65 * バッファサイズとフロー制御に関連する定数
66 */
67
68#define SERIAL_BUFSZ 256 /* ドライバのバッファサイズ */
69
70#define FC_STOP '\023' /* コントロール-S */
71#define FC_START '\021' /* コントロール-Q */
72
73#define BUFCNT_STOP (SERIAL_BUFSZ - 64) /* STOPを送る基準文字数 */
74#define BUFCNT_START (SERIAL_BUFSZ - 128) /* STARTを送る基準文字数 */
75
76/*
77 * クローズの際に送信を待
78つ最大時間(msec単位)
79 */
80#define MAX_FLUSH_WAIT 1000
81
82/*
83 * シリアルポート初期化ブロック
84 */
85typedef struct serial_port_initialization_block {
86 ID rcv_semid; /* 受信バッファ管理用セマフォのID */
87 ID snd_semid; /* 送信バッファ管理用セマフォのID */
88} SPINIB;
89
90static const SPINIB spinib_table[TNUM_PORT] = {
91 { SERIAL_RCV_SEM1, SERIAL_SND_SEM1 }
92#if TNUM_PORT >= 2
93 ,{ SERIAL_RCV_SEM2, SERIAL_SND_SEM2 }
94#endif
95#if TNUM_PORT >= 3
96 ,{ SERIAL_RCV_SEM3, SERIAL_SND_SEM3 }
97#endif
98#if TNUM_PORT >= 4
99 ,{ SERIAL_RCV_SEM4, SERIAL_SND_SEM4 }
100#endif
101#if TNUM_PORT >= 5
102 ,{ SERIAL_RCV_SEM5, SERIAL_SND_SEM5 }
103#endif
104};
105
106/*
107 * シリアルポート管理ブロック
108 */
109typedef struct serial_port_control_block {
110 const SPINIB *spinib; /* シリアルポート初期化ブロック */
111 SIOPCB *siopcb; /* シリアルI/Oポート管理ブロック */
112 BOOL openflag; /* オープン済みフラグ */
113 UINT ioctl; /* 動作制御の設定値 */
114
115 UINT rcv_read_ptr; /* 受信バッファ読出しポインタ */
116 UINT rcv_write_ptr; /* 受信バッファ書込みポインタ */
117 UINT rcv_count; /* 受信バッファ中の文字数 */
118 char rcv_fc_chr; /* 送るべき START/STOP */
119 BOOL rcv_stopped; /* STOP を送った状æ…
120‹ã‹ï¼Ÿ */
121
122 UINT snd_read_ptr; /* 送信バッファ読出しポインタ */
123 UINT snd_write_ptr; /* 送信バッファ書込みポインタ */
124 UINT snd_count; /* 送信バッファ中の文字数 */
125 BOOL snd_stopped; /* STOP を受け取った状æ…
126‹ã‹ï¼Ÿ */
127
128 char rcv_buffer[SERIAL_BUFSZ]; /* 受信バッファ */
129 char snd_buffer[SERIAL_BUFSZ]; /* 送信バッファ */
130} SPCB;
131
132static SPCB spcb_table[TNUM_PORT];
133
134/*
135 * シリアルポートIDからシリアルポート管理ブロックを取り出すためのマクロ
136 */
137#define INDEX_PORT(portid) ((UINT)((portid) - 1))
138#define get_spcb(portid) (&(spcb_table[INDEX_PORT(portid)]))
139
140/*
141 * ポインタのインクリメント
142 */
143#define INC_PTR(ptr) { if (++ptr == SERIAL_BUFSZ) ptr = 0; }
144
145/*
146 * シリアルインタフェースドライバの初期化ルーチン
147 */
148void
149serial_initialize(VP_INT exinf)
150{
151 SPCB *spcb;
152 UINT i;
153
154 sio_initialize();
155 for (spcb = spcb_table, i = 0; i < TNUM_PORT; spcb++, i++) {
156 spcb->spinib = &(spinib_table[i]);
157 spcb->openflag = FALSE;
158 }
159}
160
161/*
162 * シリアルポートのオープン
163 */
164ER
165serial_opn_por(ID portid)
166{
167 SPCB *spcb;
168 ER ercd;
169
170 if (sns_ctx()) { /* コンテキストのチェック */
171 return(E_CTX);
172 }
173 if (!(1 <= portid && portid <= TNUM_PORT)) {
174 return(E_ID); /* ポート番号のチェック */
175 }
176 spcb = get_spcb(portid);
177
178 _syscall(loc_cpu());
179 if (spcb->openflag) { /* オープン済みかのチェック */
180 ercd = E_OBJ;
181 }
182 else {
183 /*
184 * 変数の初期化
185 */
186 spcb->ioctl = (IOCTL_ECHO | IOCTL_CRLF
187 | IOCTL_FCSND | IOCTL_FCRCV);
188
189
190 spcb->rcv_read_ptr = spcb->rcv_write_ptr = 0;
191 spcb->rcv_count = 0;
192 spcb->rcv_fc_chr = '\0';
193 spcb->rcv_stopped = FALSE;
194
195 spcb->snd_read_ptr = spcb->snd_write_ptr = 0;
196 spcb->snd_count = 0;
197 spcb->snd_stopped = FALSE;
198
199 /*
200 * ハードウェア依存のオープン処理
201 */
202 spcb->siopcb = sio_opn_por(portid, (VP_INT) spcb);
203
204 /*
205 * 受信通知コールバックを許可する.
206 */
207 sio_ena_cbr(spcb->siopcb, SIO_ERDY_RCV);
208 spcb->openflag = TRUE;
209 ercd = E_OK;
210 }
211 _syscall(unl_cpu());
212 return(ercd);
213}
214
215/*
216 * シリアルポートのクローズ
217 */
218ER
219serial_cls_por(ID portid)
220{
221 SPCB *spcb;
222 ER ercd;
223
224 if (sns_ctx()) { /* コンテキストのチェック */
225 return(E_CTX);
226 }
227 if (!(1 <= portid && portid <= TNUM_PORT)) {
228 return(E_ID); /* ポート番号のチェック */
229 }
230 spcb = get_spcb(portid);
231
232 _syscall(loc_cpu());
233 if (!(spcb->openflag)) { /* オープン済みかのチェック */
234 ercd = E_OBJ;
235 }
236 else {
237 /*
238 * ハードウェア依存のクローズ処理
239 */
240 sio_cls_por(spcb->siopcb);
241 spcb->openflag = FALSE;
242 ercd = E_OK;
243 }
244 _syscall(unl_cpu());
245 return(ercd);
246}
247
248/*
249 * シリアルポートへの文字送信
250 */
251Inline BOOL
252serial_snd_chr(SPCB *spcb, char c)
253{
254 if (sio_snd_chr(spcb->siopcb, c)) {
255 return(TRUE);
256 }
257 else {
258 sio_ena_cbr(spcb->siopcb, SIO_ERDY_SND);
259 return(FALSE);
260 }
261}
262
263/*
264 * シリアルポートへの送信
265 */
266static BOOL
267serial_wri_chr(SPCB *spcb, char c)
268{
269 BOOL buffer_full;
270
271 /*
272 * LF の前に CR を送信する.
273 */
274 if (c == '\n' && (spcb->ioctl & IOCTL_CRLF) != 0) {
275 if (serial_wri_chr(spcb, '\r')) {
276 _syscall(wai_sem(spcb->spinib->snd_semid));
277 }
278 }
279
280 _syscall(loc_cpu());
281 if (spcb->snd_count == 0 && !(spcb->snd_stopped)
282 && serial_snd_chr(spcb, c)) {
283 /*
284 * シリアルI/Oデバイスの送信レジスタに文字をå…
285¥ã‚Œã‚‹ã“
286 * とに成功した場合.
287 */
288 buffer_full = FALSE;
289 }
290 else {
291 /*
292 * 送信バッファに文字をå…
293¥ã‚Œã‚‹ï¼Ž
294 */
295 spcb->snd_buffer[spcb->snd_write_ptr] = c;
296 INC_PTR(spcb->snd_write_ptr);
297 spcb->snd_count++;
298 buffer_full = (spcb->snd_count == SERIAL_BUFSZ);
299 }
300 _syscall(unl_cpu());
301 return(buffer_full);
302}
303
304ER_UINT
305serial_wri_dat(ID portid, char *buf, UINT len)
306{
307 SPCB *spcb;
308 BOOL buffer_full;
309 UINT i;
310
311 if (sns_dpn()) { /* コンテキストのチェック */
312 return(E_CTX);
313 }
314 if (!(1 <= portid && portid <= TNUM_PORT)) {
315 return(E_ID); /* ポート番号のチェック */
316 }
317
318 spcb = get_spcb(portid);
319 if (!(spcb->openflag)) { /* オープン済みかのチェック */
320 return(E_OBJ);
321 }
322
323 buffer_full = TRUE; /* ループの1回めは wai_sem する */
324 for (i = 0; i < len; i++) {
325 if (buffer_full) {
326 _syscall(wai_sem(spcb->spinib->snd_semid));
327 }
328 buffer_full = serial_wri_chr(spcb, *buf++);
329 }
330 if (!buffer_full) {
331 _syscall(sig_sem(spcb->spinib->snd_semid));
332 }
333 return((ER_UINT) len);
334}
335
336/*
337 * シリアルポートからの受信
338 */
339static BOOL
340serial_rea_chr(SPCB *spcb, char *c)
341{
342 BOOL buffer_empty;
343
344 _syscall(loc_cpu());
345
346 /*
347 * 受信バッファから文字を取り出す.
348 */
349 *c = spcb->rcv_buffer[spcb->rcv_read_ptr];
350 INC_PTR(spcb->rcv_read_ptr);
351 spcb->rcv_count--;
352 buffer_empty = (spcb->rcv_count == 0);
353
354 /*
355 * START を送信する.
356 */
357 if (spcb->rcv_stopped && spcb->rcv_count <= BUFCNT_START) {
358 if (!serial_snd_chr(spcb, FC_START)) {
359 spcb->rcv_fc_chr = FC_START;
360 }
361 spcb->rcv_stopped = FALSE;
362 }
363 _syscall(unl_cpu());
364
365 /*
366 * エコーバック処理.
367 */
368 if ((spcb->ioctl & IOCTL_ECHO) != 0) {
369 _syscall(wai_sem(spcb->spinib->snd_semid));
370 if (!serial_wri_chr(spcb, *c)) {
371 _syscall(sig_sem(spcb->spinib->snd_semid));
372 }
373 }
374 return(buffer_empty);
375}
376
377ER_UINT
378serial_rea_dat(ID portid, char *buf, UINT len)
379{
380 SPCB *spcb;
381 BOOL buffer_empty;
382 UINT i;
383
384 if (sns_dpn()) { /* コンテキストのチェック */
385 return(E_CTX);
386 }
387 if (!(1 <= portid && portid <= TNUM_PORT)) {
388 return(E_ID); /* ポート番号のチェック */
389 }
390
391 spcb = get_spcb(portid);
392 if (!(spcb->openflag)) { /* オープン済みかのチェック */
393 return(E_OBJ);
394 }
395
396 buffer_empty = TRUE; /* ループの1回めは wai_sem する */
397 for (i = 0; i < len; i++) {
398 if (buffer_empty) {
399 _syscall(wai_sem(spcb->spinib->rcv_semid));
400 }
401 buffer_empty = serial_rea_chr(spcb, buf++);
402 }
403 if (!buffer_empty) {
404 _syscall(sig_sem(spcb->spinib->rcv_semid));
405 }
406 return((ER_UINT) len);
407}
408
409/*
410 * シリアルポートの制御
411 */
412ER
413serial_ctl_por(ID portid, UINT ioctl)
414{
415 SPCB *spcb;
416
417 if (sns_ctx()) { /* コンテキストのチェック */
418 return(E_CTX);
419 }
420 if (!(1 <= portid && portid <= TNUM_PORT)) {
421 return(E_ID); /* ポート番号のチェック */
422 }
423
424 spcb = get_spcb(portid);
425 if (!(spcb->openflag)) { /* オープン済みかのチェック */
426 return(E_OBJ);
427 }
428
429 spcb->ioctl = ioctl;
430 return(E_OK);
431}
432
433/*
434 * シリアルポート状æ…
435‹ã®å‚ç…
436§
437 */
438ER
439serial_ref_por(ID portid, T_SERIAL_RPOR *pk_rpor)
440{
441 SPCB *spcb;
442
443 if (sns_ctx()) { /* コンテキストのチェック */
444 return(E_CTX);
445 }
446 if (!(1 <= portid && portid <= TNUM_PORT)) {
447 return(E_ID); /* ポート番号のチェック */
448 }
449
450 spcb = get_spcb(portid);
451 if (!(spcb->openflag)) { /* オープン済みかのチェック */
452 return(E_OBJ);
453 }
454
455 pk_rpor->reacnt = spcb->rcv_count;
456 pk_rpor->wricnt = spcb->snd_count;
457 return(E_OK);
458}
459
460/*
461 * シリアルポートからの送信可能コールバック
462 */
463void
464sio_ierdy_snd(VP_INT exinf)
465{
466 SPCB *spcb;
467
468 spcb = (SPCB *) exinf;
469 if (spcb->rcv_fc_chr != '\0') {
470 /*
471 * START/STOP を送信する.
472 */
473 (void) sio_snd_chr(spcb->siopcb, spcb->rcv_fc_chr);
474 spcb->rcv_fc_chr = '\0';
475 }
476 else if (!(spcb->snd_stopped) && spcb->snd_count > 0) {
477 /*
478 * 送信バッファ中から文字を取り出して送信する.
479 */
480 (void) sio_snd_chr(spcb->siopcb,
481 spcb->snd_buffer[spcb->snd_read_ptr]);
482 INC_PTR(spcb->snd_read_ptr);
483 if (spcb->snd_count == SERIAL_BUFSZ) {
484 _syscall(isig_sem(spcb->spinib->snd_semid));
485 }
486 spcb->snd_count--;
487 }
488 else {
489 /*
490 * 送信すべき文字がない場合は,送信可能コールバックを
491 * 禁止する.
492 */
493 sio_dis_cbr(spcb->siopcb, SIO_ERDY_SND);
494 }
495}
496
497/*
498 * シリアルポートからの受信通知コールバック
499 */
500void
501sio_ierdy_rcv(VP_INT exinf)
502{
503 SPCB *spcb;
504 char c;
505
506 spcb = (SPCB *) exinf;
507 c = (char) sio_rcv_chr(spcb->siopcb);
508 if ((spcb->ioctl & IOCTL_FCSND) != 0 && c == FC_STOP) {
509 /*
510 * 送信を一時停止する.送信中の文字はそのまま送信する.
511 */
512 spcb->snd_stopped = TRUE;
513 }
514 else if (spcb->snd_stopped && (c == FC_START
515 || (spcb->ioctl & IOCTL_FCANY) != 0)) {
516 /*
517 * 送信を再開する.
518 */
519 spcb->snd_stopped = FALSE;
520 if (spcb->snd_count > 0) {
521 c = spcb->snd_buffer[spcb->snd_read_ptr];
522 if (serial_snd_chr(spcb, c)) {
523 INC_PTR(spcb->snd_read_ptr);
524 if (spcb->snd_count == SERIAL_BUFSZ) {
525 _syscall(isig_sem(spcb->spinib
526 ->snd_semid));
527 }
528 spcb->snd_count--;
529 }
530 }
531 }
532 else if ((spcb->ioctl & IOCTL_FCSND) != 0 && c == FC_START) {
533 /*
534 * 送信に対してフロー制御している場合,START は捨てる.
535 */
536 }
537 else if (spcb->rcv_count == SERIAL_BUFSZ) {
538 /*
539 * バッファフルの場合,受信した文字を捨てる.
540 */
541 }
542 else {
543 /*
544 * 受信した文字を受信バッファにå…
545¥ã‚Œã‚‹ï¼Ž
546 */
547 spcb->rcv_buffer[spcb->rcv_write_ptr] = c;
548 INC_PTR(spcb->rcv_write_ptr);
549 if (spcb->rcv_count == 0) {
550 _syscall(isig_sem(spcb->spinib->rcv_semid));
551 }
552 spcb->rcv_count++;
553
554 /*
555 * STOP を送信する.
556 */
557 if ((spcb->ioctl & IOCTL_FCRCV) != 0 && !(spcb->rcv_stopped)
558 && (spcb->rcv_count >= BUFCNT_STOP)) {
559 if (!serial_snd_chr(spcb, FC_STOP)) {
560 spcb->rcv_fc_chr = FC_STOP;
561 }
562 spcb->rcv_stopped = TRUE;
563 }
564 }
565}
Note: See TracBrowser for help on using the repository browser.