source: UsbWattMeter/trunk/asp_dcre/syssvc/serial.c@ 167

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

MIMEにSJISを設定

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