source: asp3_wo_tecs/trunk/syssvc/serial.c@ 302

Last change on this file since 302 was 302, checked in by ertl-honda, 7 years ago

TECSレスのASP3の開発のため以下のtrunkからコピー
http://dev.toppers.jp/svn/asp3/branches/WO_TECS-3.C.0

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