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

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

initial

File size: 14.1 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 *
9 * 上記著作権者
10は,以下の (1)〜(4) の条件か,Free Software Foundation
11 * によってå…
12¬è¡¨ã•ã‚Œã¦ã„ã‚‹ GNU General Public License の Version 2 に記
13 * 述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
14 * を改変したものを含む.以下同じ)を使用・複製・改変・再é…
15å¸ƒï¼ˆä»¥ä¸‹ï¼Œ
16 * 利用と呼ぶ)することを無償で許諾する.
17 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
18 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
19 * スコード中に含まれていること.
20 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
21 * 用できる形で再é…
22å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
23å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
24 * 者
25マニュアルなど)に,上記の著作権表示,この利用条件および下記
26 * の無保証規定を掲載すること.
27 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
28 * 用できない形で再é…
29å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®ã„ずれかの条件を満たすこ
30 * と.
31 * (a) 再é…
32å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
33マニュアルなど)に,上記の著
34 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
35 * (b) 再é…
36å¸ƒã®å½¢æ…
37‹ã‚’,別に定める方法によって,TOPPERSプロジェクトに
38 * 報告すること.
39 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
40 * 害からも,上記著作権者
41およびTOPPERSプロジェクトをå…
42è²¬ã™ã‚‹ã“と.
43 *
44 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者
45お
46 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
47 * 含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
48 * 接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
49 *
50 * @(#) $Id: linux_serial.c,v 1.11 2003/12/11 00:36:49 honda Exp $
51 */
52
53#define _LINX_SERIAL_
54
55#include <t_services.h>
56#include <s_services.h>
57#include <signal.h>
58#include <termios.h>
59#include <fcntl.h>
60#include <errno.h>
61#undef __USE_MISC
62#include <unistd.h>
63#include <linux_sigio.h>
64#include "kernel_id.h"
65
66
67/*
68 * シリアルポートの低レベル定義
69 */
70
71typedef struct hardware_serial_port_descripter {
72 char *path; /* UNIX 上でのファイル名 */
73 int fd; /* ファイルディスクリプタ */
74 struct termios current_term; /* 端末制御情
75å ± */
76 struct termios saved_term;
77} HWPORT;
78
79#define NUM_PORT 1
80
81#define RAWPORT1 { 0 }
82
83/*
84 * UNIX レベルのポート初期化/シャットダウン処理
85 *
86 * 現在の実装
87では,端末を使うケースしか考えていない.本来は,open し
88 * たのが端末かどうかで処理を変えるべき.
89 */
90
91Inline void
92hw_port_initialize(HWPORT *p)
93{
94 if (p->path) {
95 p->fd = open(p->path, O_RDWR|O_NDELAY);
96 }
97 else {
98 p->fd = 0; /* 標準å…
99¥å‡ºåŠ›ã‚’使う */
100 }
101 fcntl(p->fd, F_SETOWN, getpid());
102 fcntl(p->fd, F_SETFL, FASYNC|FNDELAY);
103
104
105 tcgetattr(p->fd, &(p->saved_term));
106
107 p->current_term = p->saved_term;
108 p->current_term.c_lflag &= ~(ECHO);
109 p->current_term.c_lflag &= ~(ICANON);
110 p->current_term.c_cc[VMIN] = 1;
111 p->current_term.c_cc[VTIME] = 0;
112
113 tcsetattr(p->fd, TCSAFLUSH, &(p->current_term));
114}
115
116Inline void
117hw_port_terminate(HWPORT *p)
118{
119 tcsetattr(p->fd, TCSAFLUSH, &(p->saved_term));
120 fcntl(p->fd, F_SETFL, 0);
121 if (p->path) {
122 close(p->fd);
123 }
124}
125
126
127/*
128 * シリアルインタフェースドライバ用の SIGIO 通知イベントブロック
129 */
130
131static SIGIOEB serial_sigioeb;
132
133
134/*
135 * シリアルポート管理ブロックの定義
136 */
137
138typedef struct ioctl_descripter {
139 int echo;
140 int input;
141 int newline;
142 int flowc;
143} IOCTL;
144
145#define SERIAL_BUFSZ 256 /* シリアルインタフェース用バッファのサイズ */
146
147#define inc(x) (((x)+1 < SERIAL_BUFSZ) ? (x)+1 : 0)
148#define INC(x) ((x) = inc(x))
149
150
151typedef struct serial_port_control_block {
152 BOOL init_flag; /* 初期化済か? */
153 HWPORT hwport; /* ハードウェア依存情
154å ± */
155 ID in_semid; /* 受信バッファ管理用セマフォの ID */
156 ID out_semid; /* 送信バッファ管理用セマフォの ID */
157
158 int in_read_ptr; /* 受信バッファ読み出しポインタ */
159 int in_write_ptr; /* 受信バッファ書き込みポインタ */
160 int out_read_ptr; /* 送信バッファ読み出しポインタ */
161 int out_write_ptr; /* 送信バッファ書き込みポインタ */
162 UINT ioctl; /* ioctl による設定内
163容 */
164 BOOL send_enabled; /* 送信をイネーブルしてあるか? */
165 BOOL ixon_stopped; /* STOP を受け取った状æ…
166‹ã‹ï¼Ÿ */
167 BOOL ixoff_stopped; /* 相手に STOP を送った状æ…
168‹ã‹ï¼Ÿ */
169 char ixoff_send; /* 相手に START/STOP を送るか? */
170
171 char in_buffer[SERIAL_BUFSZ]; /* 受信バッファエリア */
172 char out_buffer[SERIAL_BUFSZ]; /* 受信バッファエリア */
173} SPCB;
174
175
176#define IN_BUFFER_EMPTY(spcb) \
177 ((spcb)->in_read_ptr == (spcb)->in_write_ptr)
178#define IN_BUFFER_FULL(spcb) \
179 ((spcb)->in_read_ptr == inc((spcb)->in_write_ptr))
180#define OUT_BUFFER_FULL(spcb) \
181 ((spcb)->out_read_ptr == inc((spcb)->out_write_ptr))
182
183/*
184 * モジュール内
185で使う関数
186 */
187static void sigint_handler();
188static BOOL serial_getc(SPCB *spcb, char *c);
189static BOOL serial_putc(SPCB *spcb, char c);
190
191
192/*
193 * シリアルポート管理ブロックの定義と初期化
194 */
195
196static SPCB spcb_table[NUM_PORT] = {
197 {0, RAWPORT1, SEM_SERIAL1_IN, SEM_SERIAL1_OUT }
198};
199
200#define get_spcb(portid) (&(spcb_table[(portid)-1]))
201#define get_spcb_def(portid) get_spcb((portid) ? (portid) : CONSOLE_PORTID)
202
203
204/*
205 * ポートの初期化
206 */
207int
208serial_opn_por(ID portid)
209{
210
211 SPCB *spcb;
212 ER ercd = E_OK;;
213
214 if (!(1 <= portid && portid <= NUM_PORT)) {
215 return(E_PAR);
216 }
217 spcb = get_spcb(portid);
218
219 /*
220 * 複数のタスクが同時に serial_open を呼ぶ状況には対応してい
221 * ない.
222 */
223 if (spcb->init_flag) { /* 初期化済かのチェック */
224 return(E_OK);
225 }
226
227 /*
228 * 変数の初期化
229 */
230 spcb->in_read_ptr = spcb->in_write_ptr = 0;
231 spcb->out_read_ptr = spcb->out_write_ptr = 0;
232 spcb->ixon_stopped = spcb->ixoff_stopped = FALSE;
233 spcb->ixoff_send = 0;
234
235 /*
236 * ハードウェア依存の初期化
237 */
238 hw_port_initialize(&(spcb->hwport));
239
240 /*
241 * プロセスを終了させるシグナルを捕まえる
242 * sigaction()で書き直した方がいいのか?
243 */
244 signal(SIGHUP, sigint_handler);
245 signal(SIGINT, sigint_handler);
246 signal(SIGTERM, sigint_handler);
247
248 spcb->init_flag = TRUE;
249 spcb->send_enabled = FALSE;
250 return(ercd);
251}
252
253/*
254 * ポートのシャットダウン
255 */
256
257ER
258serial_cls_por(ID portid)
259{
260 SPCB *spcb;
261
262 if (!(1 <= portid && portid <= NUM_PORT)) {
263 return(E_PAR); /* ポート番号のチェック */
264 }
265
266 spcb = get_spcb(portid);
267 if (!(spcb->init_flag)) { /* 初期化済かのチェック */
268 return(E_OBJ);
269 }
270
271 /*
272 * ハードウェア依存のシャットダウン処理
273 */
274 syscall(loc_cpu());
275 hw_port_terminate(&(spcb->hwport));
276 syscall(unl_cpu());
277
278 spcb->init_flag = FALSE;
279 return(E_OK);
280}
281
282/*
283 * プロセスを終了させるシグナルに対するハンドラ
284 */
285void
286sigint_handler()
287{
288 SPCB *spcb;
289 int i;
290
291 for (i = 1; i <= NUM_PORT; i++) {
292 spcb = get_spcb(i);
293 if (spcb->init_flag) {
294 hw_port_terminate(&(spcb->hwport));
295 }
296 }
297 exit(0);
298}
299
300/*
301 * フローコントロール関係の定義
302 */
303#define STOP '\023' /* Control-S */
304#define START '\021' /* Control-Q */
305
306#define IXOFF_STOP 64 /* buffer area size to send STOP */
307#define IXOFF_START 128 /* buffer area size to send START */
308
309#define in_buf_area(p) \
310 ((spcb->in_read_ptr >= spcb->in_write_ptr) ? \
311 (spcb->in_read_ptr - spcb->in_write_ptr) : \
312 (spcb->in_read_ptr + SERIAL_BUFSZ - spcb->in_write_ptr))
313/*
314 * ユーティリティルーチン
315 */
316
317Inline BOOL
318read_char(SPCB *spcb, char *c)
319{
320 int n;
321
322 if ((n = read(spcb->hwport.fd, c, 1)) == 1) {
323 return(1);
324 }
325 assert(n < 0 && errno == EWOULDBLOCK);
326 return(0);
327}
328
329Inline BOOL
330write_char(SPCB *spcb, char c)
331{
332 int n;
333
334 if ((n = write(spcb->hwport.fd, &c, 1)) == 1) {
335 return(1);
336 }
337 assert(n < 0 && errno == EWOULDBLOCK);
338 return(0);
339}
340
341/*
342 * シリアルポートからの受信
343 */
344
345static BOOL
346serial_getc(SPCB *spcb, char *c)
347{
348 BOOL buffer_empty;
349
350 syscall(loc_cpu());
351 *c = spcb->in_buffer[spcb->in_read_ptr];
352 if (inc(spcb->in_write_ptr) == spcb->in_read_ptr) {
353 /*
354 * バッファフル状æ…
355‹ãŒè§£é™¤ã•ã‚ŒãŸã‚‰ã€å‰²ã‚Šè¾¼ã¿ãŒå…
356¥ã£ãŸã®ã¨
357 * 同じ振る舞いをさせる。
358 */
359 kill(getpid(), SIGIO);
360 }
361
362 INC(spcb->in_read_ptr);
363
364 if (spcb->ixoff_stopped && (in_buf_area(spcb) > IXOFF_START)) {
365 if (!write_char(spcb, START)) {
366 spcb->ixoff_send = START;
367 }
368 spcb->ixoff_stopped = FALSE;
369 }
370 buffer_empty = IN_BUFFER_EMPTY(spcb);
371 syscall(unl_cpu());
372 return(buffer_empty);
373}
374
375ER_UINT
376serial_rea_dat(ID portid, char *buf, UINT len)
377{
378 SPCB *spcb;
379 BOOL buffer_empty;
380 char c;
381 int i;
382
383
384 if (sns_dpn()) { /* コンテキストのチェック */
385 return(E_CTX);
386 }
387 if (!(0 <= portid && portid <= NUM_PORT)) {
388 return(E_PAR); /* ポート番号のチェック */
389 }
390
391 spcb = get_spcb_def(portid);
392 if (!(spcb->init_flag)) { /* 初期化済かのチェック */
393 return(E_OBJ);
394 }
395 if (len == 0) {
396 return(len);
397 }
398
399
400 syscall(wai_sem(spcb->in_semid));
401 buffer_empty = FALSE;
402 for (i = 0; i < len; i++) {
403 buffer_empty = serial_getc(spcb, &c);
404 if ((spcb->ioctl & IOCTL_ECHO) != 0) {
405 syscall(wai_sem(spcb->out_semid));
406 if (!serial_putc(spcb, c)) {
407 syscall(sig_sem(spcb->out_semid));
408 }
409 }
410 *buf++ = c;
411 if (buffer_empty && i < len - 1) {
412 syscall(wai_sem(spcb->in_semid));
413 }
414 }
415 if (!buffer_empty) {
416 syscall(sig_sem(spcb->in_semid));
417 }
418 return(len);
419}
420
421
422/*
423 * シリアルポートへの送信
424 */
425
426static BOOL
427serial_putc(SPCB *spcb, char c)
428{
429 BOOL buffer_full;
430
431 if (c == '\n' && (spcb->ioctl & IOCTL_CRLF) != 0) {
432 if (serial_putc(spcb, '\r')) {
433 syscall(wai_sem(spcb->out_semid));
434 }
435 }
436
437 syscall(loc_cpu());
438 if (!(spcb->ixon_stopped) && write_char(spcb, c)) {
439 buffer_full = FALSE;
440 }
441 else {
442 spcb->out_buffer[spcb->out_write_ptr] = c;
443 INC(spcb->out_write_ptr);
444 buffer_full = OUT_BUFFER_FULL(spcb);
445 }
446 syscall(unl_cpu());
447 return(buffer_full);
448}
449
450ER_UINT
451serial_wri_dat(ID portid, char *buf, UINT len)
452{
453 SPCB *spcb;
454 BOOL buffer_full;
455 int i;
456
457 if (sns_dpn()) { /* コンテキストのチェック */
458 return(E_CTX);
459 }
460 if (!(0 <= portid && portid <= NUM_PORT)) {
461 return(E_PAR); /* ポート番号のチェック */
462 }
463
464 spcb = get_spcb_def(portid);
465 if (!(spcb->init_flag)) { /* 初期化済かのチェック */
466 return(E_OBJ);
467 }
468
469 syscall(wai_sem(spcb->out_semid));
470 buffer_full = FALSE;
471 for (i = 0; i < len; i++) {
472 buffer_full = serial_putc(spcb, *buf++);
473 if (buffer_full && i < len - 1) {
474 syscall(wai_sem(spcb->out_semid));
475 }
476 }
477 if (!buffer_full) {
478 syscall(sig_sem(spcb->out_semid));
479 }
480 return(len);
481}
482
483/*
484 * シリアルポートの制御
485 */
486
487int
488serial_ctl_por(ID portid, UINT ioctl)
489{
490 SPCB *spcb;
491
492 if (sns_ctx()) { /* コンテキストのチェック */
493 return(E_CTX);
494 }
495 if (!(0 <= portid && portid <= NUM_PORT)) {
496 return(E_PAR); /* ポート番号のチェック */
497 }
498
499 spcb = get_spcb_def(portid);
500 if (!(spcb->init_flag)) { /* 初期化済かのチェック */
501 return(E_OBJ);
502 }
503
504 spcb->ioctl = ioctl;
505 return(E_OK);
506}
507
508
509/*
510 * シリアルポート割込みハンドラ
511 */
512
513static BOOL
514serial_int_handler(ID portid)
515{
516 SPCB *spcb;
517 BOOL flag;
518 char c;
519
520 spcb = get_spcb(portid);
521 flag = 0;
522
523 /*
524 * 1文字受信処理
525 *
526 * まず,バッファフルでない場合に,1文字読んでみる.読めれば,
527 * それに応じた処理を行う.
528 */
529 if (inc(spcb->in_write_ptr) != spcb->in_read_ptr
530 && read_char(spcb, &c)) {
531 if ((spcb->ioctl & IOCTL_FCSND) != 0 && c == STOP) {
532 spcb->ixon_stopped = TRUE;
533 }
534 else if (((spcb->ioctl & IOCTL_FCSND) != 0 || spcb->ixon_stopped)
535 && (c == START || (spcb->ioctl & IOCTL_FCANY) != 0)) {
536 spcb->ixon_stopped = FALSE;
537 }
538 else {
539 spcb->in_buffer[spcb->in_write_ptr] = c;
540 if(spcb->in_read_ptr == spcb->in_write_ptr){
541 syscall(sig_sem(spcb->in_semid));
542 }
543
544 INC(spcb->in_write_ptr);
545
546 if ((spcb->ioctl & IOCTL_FCRCV) != 0 && !(spcb->ixoff_stopped)
547 && (in_buf_area(p) < IXOFF_STOP)) {
548 spcb->ixoff_stopped = TRUE;
549 spcb->ixoff_send = STOP;
550 }
551 }
552 flag = 1;
553 }
554
555 /*
556 * 1文字送信処理
557 */
558 if (spcb->ixoff_send) {
559 if (write_char(spcb, spcb->ixoff_send)) {
560 spcb->ixoff_send = 0;
561 flag = 1;
562 }
563 }
564 else if (!(spcb->ixon_stopped)
565 && spcb->out_read_ptr != spcb->out_write_ptr) {
566 if (write_char(spcb, spcb->out_buffer[spcb->out_read_ptr])) {
567 if(OUT_BUFFER_FULL(spcb)){
568 syscall(sig_sem(spcb->out_semid));
569 }
570 INC(spcb->out_read_ptr);
571 flag = 1;
572 }
573 }
574 return(flag);
575}
576
577
578
579/*
580 * SIGIO コールバックルーチン
581 */
582
583static BOOL
584serial_sigio_callback(VP arg)
585{
586 BOOL flag;
587
588 do {
589// syscall(loc_cpu());
590 flag = serial_int_handler(1);
591// syscall(unl_cpu());
592 } while (flag);
593 return(0);
594}
595
596
597
598/*
599 * シリアルインタフェースドライバの起動
600 */
601
602void
603serial_initialize(VP_INT exinf)
604{
605 serial_sigioeb.callback = serial_sigio_callback;
606 serial_sigioeb.arg = (VP) 0;
607 syscall(enqueue_sigioeb_initialize(&serial_sigioeb));
608}
Note: See TracBrowser for help on using the repository browser.