source: asp_wo_cfg/trunk/syssvc/serial.c@ 62

Last change on this file since 62 was 62, checked in by ertl-hiro, 11 years ago

ASP Release 1.9.0 への追従。

  • Property svn:keywords set to Id
File size: 20.7 KB
Line 
1/*
2 * TOPPERS/ASP Kernel
3 * Toyohashi Open Platform for Embedded Real-Time Systems/
4 * Advanced 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-2013 by Embedded and Real-Time Systems Laboratory
9 * Graduate School of Information Science, Nagoya Univ., JAPAN
10 *
11 * 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
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 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
32 * 免責すること.
33 *
34 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
35 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
36 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
37 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
38 * の責任を負わない.
39 *
40 * @(#) $Id: serial.c 62 2013-10-18 15:38:33Z ertl-hiro $
41 */
42
43/*
44 * シリアルインタフェースドライバ
45 */
46
47#include <kernel.h>
48#include <t_syslog.h>
49#include "target_syssvc.h"
50#include "target_serial.h"
51#include "serial.h"
52#include "kernel_cfg.h"
53
54/*
55 * オブジェクトのID
56 */
57#include "kernel_id.h"
58
59/*
60 * バッファサイズのデフォルト値とバッファの定義
61 */
62#ifndef SERIAL_RCV_BUFSZ1
63#define SERIAL_RCV_BUFSZ1 256 /* ポート1の受信バッファサイズ */
64#endif /* SERIAL_RCV_BUFSZ1 */
65
66#ifndef SERIAL_SND_BUFSZ1
67#define SERIAL_SND_BUFSZ1 256 /* ポート1の送信バッファサイズ */
68#endif /* SERIAL_SND_BUFSZ1 */
69
70static char rcv_buffer1[SERIAL_RCV_BUFSZ1];
71static char snd_buffer1[SERIAL_SND_BUFSZ1];
72
73#if TNUM_PORT >= 2 /* ポート2に関する定義 */
74
75#ifndef SERIAL_RCV_BUFSZ2
76#define SERIAL_RCV_BUFSZ2 256 /* ポート2の受信バッファサイズ */
77#endif /* SERIAL_RCV_BUFSZ2 */
78
79#ifndef SERIAL_SND_BUFSZ2
80#define SERIAL_SND_BUFSZ2 256 /* ポート2の送信バッファサイズ */
81#endif /* SERIAL_SND_BUFSZ2 */
82
83static char rcv_buffer2[SERIAL_RCV_BUFSZ2];
84static char snd_buffer2[SERIAL_SND_BUFSZ2];
85
86#endif /* TNUM_PORT >= 2 */
87
88#if TNUM_PORT >= 3 /* ポート3に関する定義 */
89
90#ifndef SERIAL_RCV_BUFSZ3
91#define SERIAL_RCV_BUFSZ3 256 /* ポート3の受信バッファサイズ */
92#endif /* SERIAL_RCV_BUFSZ3 */
93
94#ifndef SERIAL_SND_BUFSZ3
95#define SERIAL_SND_BUFSZ3 256 /* ポート3の送信バッファサイズ */
96#endif /* SERIAL_SND_BUFSZ3 */
97
98static char rcv_buffer3[SERIAL_RCV_BUFSZ3];
99static char snd_buffer3[SERIAL_SND_BUFSZ3];
100
101#endif /* TNUM_PORT >= 3 */
102
103#if TNUM_PORT >= 4 /* ポート4に関する定義 */
104
105#ifndef SERIAL_RCV_BUFSZ4
106#define SERIAL_RCV_BUFSZ4 256 /* ポート4の受信バッファサイズ */
107#endif /* SERIAL_RCV_BUFSZ4 */
108
109#ifndef SERIAL_SND_BUFSZ4
110#define SERIAL_SND_BUFSZ4 256 /* ポート4の送信バッファサイズ */
111#endif /* SERIAL_SND_BUFSZ4 */
112
113static char rcv_buffer4[SERIAL_RCV_BUFSZ4];
114static char snd_buffer4[SERIAL_SND_BUFSZ4];
115
116#endif /* TNUM_PORT >= 4 */
117
118#if TNUM_PORT >= 5
119#error Serial interface driver supports up to 4 ports.
120#endif /* TNUM_PORT >= 5 */
121
122/*
123 * フロー制御に関連する定数とマクロ
124 */
125#define FC_STOP '\023' /* コントロール-S */
126#define FC_START '\021' /* コントロール-Q */
127
128#define BUFCNT_STOP(bufsz) ((bufsz) * 3 / 4) /* STOPを送る基準文字数 */
129#define BUFCNT_START(bufsz) ((bufsz) / 2) /* STARTを送る基準文字数 */
130
131/*
132 * シリアルポート初期化ブロック
133 */
134typedef struct serial_port_initialization_block {
135 ID rcv_semid; /* 受信バッファ管理用セマフォのID */
136 ID snd_semid; /* 送信バッファ管理用セマフォのID */
137 uint_t rcv_bufsz; /* 受信バッファサイズ */
138 char *rcv_buffer; /* 受信バッファ */
139 uint_t snd_bufsz; /* 送信バッファサイズ */
140 char *snd_buffer; /* 送信バッファ */
141} SPINIB;
142
143static const SPINIB spinib_table[TNUM_PORT] = {
144 { SERIAL_RCV_SEM1, SERIAL_SND_SEM1,
145 SERIAL_RCV_BUFSZ1, rcv_buffer1,
146 SERIAL_SND_BUFSZ1, snd_buffer1 },
147#if TNUM_PORT >= 2
148 { SERIAL_RCV_SEM2, SERIAL_SND_SEM2,
149 SERIAL_RCV_BUFSZ2, rcv_buffer2,
150 SERIAL_SND_BUFSZ2, snd_buffer2 },
151#endif /* TNUM_PORT >= 2 */
152#if TNUM_PORT >= 3
153 { SERIAL_RCV_SEM3, SERIAL_SND_SEM3,
154 SERIAL_RCV_BUFSZ3, rcv_buffer3,
155 SERIAL_SND_BUFSZ3, snd_buffer3 },
156#endif /* TNUM_PORT >= 3 */
157#if TNUM_PORT >= 4
158 { SERIAL_RCV_SEM4, SERIAL_SND_SEM4,
159 SERIAL_RCV_BUFSZ4, rcv_buffer4,
160 SERIAL_SND_BUFSZ4, snd_buffer4 },
161#endif /* TNUM_PORT >= 4 */
162};
163
164/*
165 * シリアルポート管理ブロック
166 */
167typedef struct serial_port_control_block {
168 const SPINIB *p_spinib; /* シリアルポート初期化ブロック */
169 SIOPCB *p_siopcb; /* シリアルI/Oポート管理ブロック */
170 bool_t openflag; /* オープン済みフラグ */
171 bool_t errorflag; /* エラーフラグ */
172 uint_t ioctl; /* 動作制御の設定値 */
173
174 uint_t rcv_read_ptr; /* 受信バッファ読出しポインタ */
175 uint_t rcv_write_ptr; /* 受信バッファ書込みポインタ */
176 uint_t rcv_count; /* 受信バッファ中の文字数 */
177 char rcv_fc_chr; /* 送るべきSTART/STOP */
178 bool_t rcv_stopped; /* STOPを送った状態か? */
179
180 uint_t snd_read_ptr; /* 送信バッファ読出しポインタ */
181 uint_t snd_write_ptr; /* 送信バッファ書込みポインタ */
182 uint_t snd_count; /* 送信バッファ中の文字数 */
183 bool_t snd_stopped; /* STOPを受け取った状態か? */
184} SPCB;
185
186static SPCB spcb_table[TNUM_PORT];
187
188/*
189 * シリアルポートIDからシリアルポート管理ブロックを取り出すためのマクロ
190 */
191#define INDEX_PORT(portid) ((uint_t)((portid) - 1))
192#define get_spcb(portid) (&(spcb_table[INDEX_PORT(portid)]))
193
194/*
195 * ポインタのインクリメント
196 */
197#define INC_PTR(ptr, bufsz) do { \
198 if (++(ptr) == (bufsz)) { \
199 (ptr) = 0; \
200 } \
201} while (false)
202
203/*
204 * サービスコール呼出しマクロ
205 *
206 * サービスコール呼出しを含む式expを評価し,返値がエラー(負の値)の場
207 * 合には,ercにercd_expを評価した値を代入し,error_exitにgotoする.
208 */
209#define SVC(exp, ercd_exp) do { \
210 if ((exp) < 0) { \
211 ercd = (ercd_exp); \
212 goto error_exit; \
213 } \
214} while (false)
215
216/*
217 * E_SYSエラーの生成
218 */
219static ER
220gen_ercd_sys(SPCB *p_spcb)
221{
222 p_spcb->errorflag = true;
223 return(E_SYS);
224}
225
226/*
227 * 待ちに入るサービスコールからのエラーの変換
228 */
229static ER
230gen_ercd_wait(ER rercd, SPCB *p_spcb)
231{
232 switch (MERCD(rercd)) {
233 case E_RLWAI:
234 case E_DLT:
235 return(rercd);
236 default:
237 p_spcb->errorflag = true;
238 return(E_SYS);
239 }
240}
241
242/*
243 * シリアルインタフェースドライバの初期化ルーチン
244 */
245void
246serial_initialize(intptr_t exinf)
247{
248 T_CSEM csem;
249 SPCB *p_spcb;
250 uint_t i;
251 ER ercd;
252
253 /*
254 * シリアルI/Oデバイス(SIO)ドライバの初期化
255 */
256 sio_initialize(0);
257
258 /*
259 * シリアルインタフェースドライバの初期化処理(serial.cfg相当の処理)
260 *
261 * CRE_SEM(SERIAL_RCV_SEM1, { TA_TPRI, 0, 1 });
262 * CRE_SEM(SERIAL_SND_SEM1, { TA_TPRI, 1, 1 });
263 */
264 csem.sematr = TA_TPRI;
265 csem.isemcnt = 0;
266 csem.maxsem = 1;
267 ercd = cre_sem(SERIAL_RCV_SEM1, &csem);
268 assert(ercd == E_OK);
269
270 csem.sematr = TA_TPRI;
271 csem.isemcnt = 1;
272 csem.maxsem = 1;
273 ercd = cre_sem(SERIAL_SND_SEM1, &csem);
274 assert(ercd == E_OK);
275
276#if TNUM_PORT >= 2 /* ポート2に関する定義 */
277 /*
278 * CRE_SEM(SERIAL_RCV_SEM2, { TA_TPRI, 0, 1 });
279 * CRE_SEM(SERIAL_SND_SEM2, { TA_TPRI, 1, 1 });
280 */
281 csem.sematr = TA_TPRI;
282 csem.isemcnt = 0;
283 csem.maxsem = 1;
284 ercd = cre_sem(SERIAL_RCV_SEM2, &csem);
285 assert(ercd == E_OK);
286
287 csem.sematr = TA_TPRI;
288 csem.isemcnt = 1;
289 csem.maxsem = 1;
290 ercd = acre_sem(SERIAL_SND_SEM2, &csem);
291 assert(ercd == E_OK);
292#endif /* TNUM_PORT >= 2 */
293
294#if TNUM_PORT >= 3 /* ポート3に関する定義 */
295 /*
296 * CRE_SEM(SERIAL_RCV_SEM3, { TA_TPRI, 0, 1 });
297 * CRE_SEM(SERIAL_SND_SEM3, { TA_TPRI, 1, 1 });
298 */
299 csem.sematr = TA_TPRI;
300 csem.isemcnt = 0;
301 csem.maxsem = 1;
302 ercd = cre_sem(SERIAL_RCV_SEM3, &csem);
303 assert(ercd == E_OK);
304
305 csem.sematr = TA_TPRI;
306 csem.isemcnt = 1;
307 csem.maxsem = 1;
308 ercd = acre_sem(SERIAL_SND_SEM3, &csem);
309 assert(ercd == E_OK);
310#endif /* TNUM_PORT >= 3 */
311
312#if TNUM_PORT >= 4 /* ポート4に関する定義 */
313 /*
314 * CRE_SEM(SERIAL_RCV_SEM4, { TA_TPRI, 0, 1 });
315 * CRE_SEM(SERIAL_SND_SEM4, { TA_TPRI, 1, 1 });
316 */
317 csem.sematr = TA_TPRI;
318 csem.isemcnt = 0;
319 csem.maxsem = 1;
320 ercd = cre_sem(SERIAL_RCV_SEM4, &csem);
321 assert(ercd == E_OK);
322
323 csem.sematr = TA_TPRI;
324 csem.isemcnt = 1;
325 csem.maxsem = 1;
326 ercd = acre_sem(SERIAL_SND_SEM4, &csem);
327 assert(ercd == E_OK);
328#endif /* TNUM_PORT >= 4 */
329
330 /*
331 * シリアルポート管理ブロックの初期化(元のserial_initializeの処理)
332 *
333 * ATT_INI({ TA_NULL, 0, serial_initialize });
334 */
335 for (i = 0; i < TNUM_PORT; i++) {
336 p_spcb = &(spcb_table[i]);
337 p_spcb->p_spinib = &(spinib_table[i]);
338 p_spcb->openflag = false;
339 }
340}
341
342/*
343 * シリアルポートのオープン(サービスコール)
344 */
345ER
346serial_opn_por(ID portid)
347{
348 SPCB *p_spcb;
349 ER ercd;
350
351 if (sns_dpn()) { /* コンテキストのチェック */
352 return(E_CTX);
353 }
354 if (!(1 <= portid && portid <= TNUM_PORT)) {
355 return(E_ID); /* ポート番号のチェック */
356 }
357 p_spcb = get_spcb(portid);
358
359 SVC(dis_dsp(), gen_ercd_sys(p_spcb));
360 if (p_spcb->openflag) { /* オープン済みかのチェック */
361 ercd = E_OBJ;
362 }
363 else {
364 /*
365 * 変数の初期化
366 */
367 p_spcb->ioctl = (IOCTL_ECHO | IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV);
368
369 p_spcb->rcv_read_ptr = 0U;
370 p_spcb->rcv_write_ptr = 0U;
371 p_spcb->rcv_count = 0U;
372 p_spcb->rcv_fc_chr = '\0';
373 p_spcb->rcv_stopped = false;
374
375 p_spcb->snd_read_ptr = 0U;
376 p_spcb->snd_write_ptr = 0U;
377 p_spcb->snd_count = 0U;
378 p_spcb->snd_stopped = false;
379
380 /*
381 * これ以降,割込みを禁止する.
382 */
383 if (loc_cpu() < 0) {
384 ercd = E_SYS;
385 goto error_exit_enadsp;
386 }
387
388 /*
389 * ハードウェア依存のオープン処理
390 */
391 p_spcb->p_siopcb = sio_opn_por(portid, (intptr_t) p_spcb);
392
393 /*
394 * 受信通知コールバックを許可する.
395 */
396 sio_ena_cbr(p_spcb->p_siopcb, SIO_RDY_RCV);
397 p_spcb->openflag = true;
398 p_spcb->errorflag = false;
399
400 if (unl_cpu() < 0) {
401 p_spcb->errorflag = true;
402 ercd = E_SYS;
403 goto error_exit_enadsp;
404 }
405 ercd = E_OK;
406 }
407
408 error_exit_enadsp:
409 SVC(ena_dsp(), gen_ercd_sys(p_spcb));
410
411 error_exit:
412 return(ercd);
413}
414
415/*
416 * シリアルポートのクローズ(サービスコール)
417 */
418ER
419serial_cls_por(ID portid)
420{
421 SPCB *p_spcb;
422 ER ercd;
423 bool_t eflag = false;
424
425 if (sns_dpn()) { /* コンテキストのチェック */
426 return(E_CTX);
427 }
428 if (!(1 <= portid && portid <= TNUM_PORT)) {
429 return(E_ID); /* ポート番号のチェック */
430 }
431 p_spcb = get_spcb(portid);
432
433 SVC(dis_dsp(), gen_ercd_sys(p_spcb));
434 if (!(p_spcb->openflag)) { /* オープン済みかのチェック */
435 ercd = E_OBJ;
436 }
437 else {
438 /*
439 * ハードウェア依存のクローズ処理
440 */
441 if (loc_cpu() < 0) {
442 eflag = true;
443 }
444 sio_cls_por(p_spcb->p_siopcb);
445 p_spcb->openflag = false;
446 if (unl_cpu() < 0) {
447 eflag = true;
448 }
449
450 /*
451 * セマフォの初期化
452 */
453 if (ini_sem(p_spcb->p_spinib->snd_semid) < 0) {
454 eflag = true;
455 }
456 if (ini_sem(p_spcb->p_spinib->rcv_semid) < 0) {
457 eflag = true;
458 }
459
460 /*
461 * エラーコードの設定
462 */
463 if (eflag) {
464 ercd = gen_ercd_sys(p_spcb);
465 }
466 else {
467 ercd = E_OK;
468 }
469 }
470 SVC(ena_dsp(), gen_ercd_sys(p_spcb));
471
472 error_exit:
473 return(ercd);
474}
475
476/*
477 * シリアルポートへの文字送信
478 *
479 * p_spcbで指定されるシリアルI/Oポートに対して,文字cを送信する.文字
480 * を送信レジスタにいれた場合にはtrueを返す.そうでない場合には,送信
481 * レジスタが空いたことを通知するコールバック関数を許可し,falseを返す.
482 * この関数は,CPUロック状態で呼び出される.
483 */
484Inline bool_t
485serial_snd_chr(SPCB *p_spcb, char c)
486{
487 if (sio_snd_chr(p_spcb->p_siopcb, c)) {
488 return(true);
489 }
490 else {
491 sio_ena_cbr(p_spcb->p_siopcb, SIO_RDY_SND);
492 return(false);
493 }
494}
495
496/*
497 * シリアルポートへの1文字送信
498 */
499static ER_BOOL
500serial_wri_chr(SPCB *p_spcb, char c)
501{
502 bool_t buffer_full;
503 ER ercd, rercd;
504
505 /*
506 * LFの前にCRを送信する.
507 */
508 if (c == '\n' && (p_spcb->ioctl & IOCTL_CRLF) != 0U) {
509 /*
510 * 以下のコードは再帰呼出しになっているが,引数cが'\n'の場合に
511 * 引数cを'\r'として呼び出すことから,この再帰呼出しは2回目の
512 * 呼び出しで必ず止まる.
513 */
514 SVC(rercd = serial_wri_chr(p_spcb, '\r'), rercd);
515 if ((bool_t) rercd) {
516 SVC(rercd = wai_sem(p_spcb->p_spinib->snd_semid),
517 gen_ercd_wait(rercd, p_spcb));
518 }
519 }
520
521 SVC(loc_cpu(), gen_ercd_sys(p_spcb));
522 if (p_spcb->snd_count == 0U && !(p_spcb->snd_stopped)
523 && serial_snd_chr(p_spcb, c)) {
524 /*
525 * シリアルI/Oデバイスの送信レジスタに文字を入れることに成功し
526 * た場合.
527 */
528 buffer_full = false;
529 }
530 else {
531 /*
532 * 送信バッファに文字を入れる.
533 */
534 p_spcb->p_spinib->snd_buffer[p_spcb->snd_write_ptr] = c;
535 INC_PTR(p_spcb->snd_write_ptr, p_spcb->p_spinib->snd_bufsz);
536 p_spcb->snd_count++;
537 buffer_full = (p_spcb->snd_count == p_spcb->p_spinib->snd_bufsz);
538 }
539
540 SVC(unl_cpu(), gen_ercd_sys(p_spcb));
541 ercd = (ER_BOOL) buffer_full;
542
543 error_exit:
544 return(ercd);
545}
546
547/*
548 * シリアルポートへの文字列送信(サービスコール)
549 */
550ER_UINT
551serial_wri_dat(ID portid, const char *buf, uint_t len)
552{
553 SPCB *p_spcb;
554 bool_t buffer_full;
555 uint_t wricnt = 0U;
556 ER ercd, rercd;
557
558 if (sns_dpn()) { /* コンテキストのチェック */
559 return(E_CTX);
560 }
561 if (!(1 <= portid && portid <= TNUM_PORT)) {
562 return(E_ID); /* ポート番号のチェック */
563 }
564
565 p_spcb = get_spcb(portid);
566 if (!(p_spcb->openflag)) { /* オープン済みかのチェック */
567 return(E_OBJ);
568 }
569 if (p_spcb->errorflag) { /* エラー状態かのチェック */
570 return(E_SYS);
571 }
572
573 buffer_full = true; /* ループの1回めはwai_semする */
574 while (wricnt < len) {
575 if (buffer_full) {
576 SVC(rercd = wai_sem(p_spcb->p_spinib->snd_semid),
577 gen_ercd_wait(rercd, p_spcb));
578 }
579 SVC(rercd = serial_wri_chr(p_spcb, *buf++), rercd);
580 wricnt++;
581 buffer_full = (bool_t) rercd;
582 }
583 if (!buffer_full) {
584 SVC(sig_sem(p_spcb->p_spinib->snd_semid), gen_ercd_sys(p_spcb));
585 }
586 ercd = E_OK;
587
588 error_exit:
589 return(wricnt > 0U ? (ER_UINT) wricnt : ercd);
590}
591
592/*
593 * シリアルポートからの1文字受信
594 */
595static bool_t
596serial_rea_chr(SPCB *p_spcb, char *p_c)
597{
598 bool_t buffer_empty;
599 ER ercd;
600
601 SVC(loc_cpu(), gen_ercd_sys(p_spcb));
602
603 /*
604 * 受信バッファから文字を取り出す.
605 */
606 *p_c = p_spcb->p_spinib->rcv_buffer[p_spcb->rcv_read_ptr];
607 INC_PTR(p_spcb->rcv_read_ptr, p_spcb->p_spinib->rcv_bufsz);
608 p_spcb->rcv_count--;
609 buffer_empty = (p_spcb->rcv_count == 0U);
610
611 /*
612 * STARTを送信する.
613 */
614 if (p_spcb->rcv_stopped && p_spcb->rcv_count
615 <= BUFCNT_START(p_spcb->p_spinib->rcv_bufsz)) {
616 if (!serial_snd_chr(p_spcb, FC_START)) {
617 p_spcb->rcv_fc_chr = FC_START;
618 }
619 p_spcb->rcv_stopped = false;
620 }
621
622 SVC(unl_cpu(), gen_ercd_sys(p_spcb));
623 ercd = (ER_BOOL) buffer_empty;
624
625 error_exit:
626 return(ercd);
627}
628
629/*
630 * シリアルポートからの文字列受信(サービスコール)
631 */
632ER_UINT
633serial_rea_dat(ID portid, char *buf, uint_t len)
634{
635 SPCB *p_spcb;
636 bool_t buffer_empty;
637 uint_t reacnt = 0U;
638 char c = '\0'; /* コンパイラの警告を抑止するために初期化する */
639 ER ercd, rercd;
640
641 if (sns_dpn()) { /* コンテキストのチェック */
642 return(E_CTX);
643 }
644 if (!(1 <= portid && portid <= TNUM_PORT)) {
645 return(E_ID); /* ポート番号のチェック */
646 }
647
648 p_spcb = get_spcb(portid);
649 if (!(p_spcb->openflag)) { /* オープン済みかのチェック */
650 return(E_OBJ);
651 }
652 if (p_spcb->errorflag) { /* エラー状態かのチェック */
653 return(E_SYS);
654 }
655
656 buffer_empty = true; /* ループの1回めはwai_semする */
657 while (reacnt < len) {
658 if (buffer_empty) {
659 SVC(rercd = wai_sem(p_spcb->p_spinib->rcv_semid),
660 gen_ercd_wait(rercd, p_spcb));
661 }
662 SVC(rercd = serial_rea_chr(p_spcb, &c), rercd);
663 *buf++ = c;
664 reacnt++;
665 buffer_empty = (bool_t) rercd;
666
667 /*
668 * エコーバック処理.
669 */
670 if ((p_spcb->ioctl & IOCTL_ECHO) != 0U) {
671 SVC(rercd = wai_sem(p_spcb->p_spinib->snd_semid),
672 gen_ercd_wait(rercd, p_spcb));
673 SVC(rercd = serial_wri_chr(p_spcb, c), rercd);
674 if (!((bool_t) rercd)) {
675 SVC(sig_sem(p_spcb->p_spinib->snd_semid),
676 gen_ercd_sys(p_spcb));
677 }
678 }
679 }
680 if (!buffer_empty) {
681 SVC(sig_sem(p_spcb->p_spinib->rcv_semid), gen_ercd_sys(p_spcb));
682 }
683 ercd = E_OK;
684
685 error_exit:
686 return(reacnt > 0U ? (ER_UINT) reacnt : ercd);
687}
688
689/*
690 * シリアルポートの制御(サービスコール)
691 */
692ER
693serial_ctl_por(ID portid, uint_t ioctl)
694{
695 SPCB *p_spcb;
696
697 if (sns_dpn()) { /* コンテキストのチェック */
698 return(E_CTX);
699 }
700 if (!(1 <= portid && portid <= TNUM_PORT)) {
701 return(E_ID); /* ポート番号のチェック */
702 }
703
704 p_spcb = get_spcb(portid);
705 if (!(p_spcb->openflag)) { /* オープン済みかのチェック */
706 return(E_OBJ);
707 }
708 if (p_spcb->errorflag) { /* エラー状態かのチェック */
709 return(E_SYS);
710 }
711
712 p_spcb->ioctl = ioctl;
713 return(E_OK);
714}
715
716/*
717 * シリアルポート状態の参照(サービスコール)
718 */
719ER
720serial_ref_por(ID portid, T_SERIAL_RPOR *pk_rpor)
721{
722 SPCB *p_spcb;
723
724 if (sns_dpn()) { /* コンテキストのチェック */
725 return(E_CTX);
726 }
727 if (!(1 <= portid && portid <= TNUM_PORT)) {
728 return(E_ID); /* ポート番号のチェック */
729 }
730
731 p_spcb = get_spcb(portid);
732 if (!(p_spcb->openflag)) { /* オープン済みかのチェック */
733 return(E_OBJ);
734 }
735 if (p_spcb->errorflag) { /* エラー状態かのチェック */
736 return(E_SYS);
737 }
738
739 pk_rpor->reacnt = p_spcb->rcv_count;
740 pk_rpor->wricnt = p_spcb->snd_count;
741 return(E_OK);
742}
743
744/*
745 * シリアルポートからの送信可能コールバック
746 */
747void
748sio_irdy_snd(intptr_t exinf)
749{
750 SPCB *p_spcb;
751
752 p_spcb = (SPCB *) exinf;
753 if (p_spcb->rcv_fc_chr != '\0') {
754 /*
755 * START/STOP を送信する.
756 */
757 (void) sio_snd_chr(p_spcb->p_siopcb, p_spcb->rcv_fc_chr);
758 p_spcb->rcv_fc_chr = '\0';
759 }
760 else if (!(p_spcb->snd_stopped) && p_spcb->snd_count > 0U) {
761 /*
762 * 送信バッファ中から文字を取り出して送信する.
763 */
764 (void) sio_snd_chr(p_spcb->p_siopcb,
765 p_spcb->p_spinib->snd_buffer[p_spcb->snd_read_ptr]);
766 INC_PTR(p_spcb->snd_read_ptr, p_spcb->p_spinib->snd_bufsz);
767 if (p_spcb->snd_count == p_spcb->p_spinib->snd_bufsz) {
768 if (isig_sem(p_spcb->p_spinib->snd_semid) < 0) {
769 p_spcb->errorflag = true;
770 }
771 }
772 p_spcb->snd_count--;
773 }
774 else {
775 /*
776 * 送信すべき文字がない場合は,送信可能コールバックを禁止する.
777 */
778 sio_dis_cbr(p_spcb->p_siopcb, SIO_RDY_SND);
779 }
780}
781
782/*
783 * シリアルポートからの受信通知コールバック
784 */
785void
786sio_irdy_rcv(intptr_t exinf)
787{
788 SPCB *p_spcb;
789 char c;
790
791 p_spcb = (SPCB *) exinf;
792 c = (char) sio_rcv_chr(p_spcb->p_siopcb);
793 if ((p_spcb->ioctl & IOCTL_FCSND) != 0U && c == FC_STOP) {
794 /*
795 * 送信を一時停止する.送信中の文字はそのまま送信する.
796 */
797 p_spcb->snd_stopped = true;
798 }
799 else if (p_spcb->snd_stopped && (c == FC_START
800 || (p_spcb->ioctl & IOCTL_FCANY) != 0U)) {
801 /*
802 * 送信を再開する.
803 */
804 p_spcb->snd_stopped = false;
805 if (p_spcb->snd_count > 0U) {
806 c = p_spcb->p_spinib->snd_buffer[p_spcb->snd_read_ptr];
807 if (serial_snd_chr(p_spcb, c)) {
808 INC_PTR(p_spcb->snd_read_ptr, p_spcb->p_spinib->snd_bufsz);
809 if (p_spcb->snd_count == p_spcb->p_spinib->snd_bufsz) {
810 if (isig_sem(p_spcb->p_spinib->snd_semid) < 0) {
811 p_spcb->errorflag = true;
812 }
813 }
814 p_spcb->snd_count--;
815 }
816 }
817 }
818 else if ((p_spcb->ioctl & IOCTL_FCSND) != 0U && c == FC_START) {
819 /*
820 * 送信に対してフロー制御している場合,START は捨てる.
821 */
822 }
823 else if (p_spcb->rcv_count == p_spcb->p_spinib->rcv_bufsz) {
824 /*
825 * バッファフルの場合,受信した文字を捨てる.
826 */
827 }
828 else {
829 /*
830 * 受信した文字を受信バッファに入れる.
831 */
832 p_spcb->p_spinib->rcv_buffer[p_spcb->rcv_write_ptr] = c;
833 INC_PTR(p_spcb->rcv_write_ptr, p_spcb->p_spinib->rcv_bufsz);
834 if (p_spcb->rcv_count == 0U) {
835 if (isig_sem(p_spcb->p_spinib->rcv_semid) < 0) {
836 p_spcb->errorflag = true;
837 }
838 }
839 p_spcb->rcv_count++;
840
841 /*
842 * STOPを送信する.
843 */
844 if ((p_spcb->ioctl & IOCTL_FCRCV) != 0U && !(p_spcb->rcv_stopped)
845 && p_spcb->rcv_count
846 >= BUFCNT_STOP(p_spcb->p_spinib->rcv_bufsz)) {
847 if (!serial_snd_chr(p_spcb, FC_STOP)) {
848 p_spcb->rcv_fc_chr = FC_STOP;
849 }
850 p_spcb->rcv_stopped = true;
851 }
852 }
853}
854
855/*
856 * シリアルインタフェースドライバからの未送信文字の取出し
857 */
858bool_t
859serial_get_chr(ID portid, char *p_c)
860{
861 SPCB *p_spcb;
862
863 if (1 <= portid && portid <= TNUM_PORT) { /* ポート番号のチェック */
864 p_spcb = get_spcb(portid);
865 if (p_spcb->openflag) { /* オープン済みかのチェック */
866 if (p_spcb->snd_count > 0U) {
867 *p_c = p_spcb->p_spinib->snd_buffer[p_spcb->snd_read_ptr];
868 INC_PTR(p_spcb->snd_read_ptr, p_spcb->p_spinib->snd_bufsz);
869 p_spcb->snd_count--;
870 return(true);
871 }
872 }
873 }
874 return(false);
875}
876
877/*
878 * シリアルインタフェースドライバの終了処理ルーチン
879 */
880void
881serial_terminate(intptr_t exinf)
882{
883 sio_terminate(0);
884}
Note: See TracBrowser for help on using the repository browser.