source: azure_iot_hub_f767zi/trunk/asp_baseplatform/syssvc/serial.c@ 457

Last change on this file since 457 was 457, checked in by coas-nagasima, 4 years ago

ファイルを追加

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