serial.c

説明を見る。
00001 /*
00002  *  TOPPERS/ASP Kernel
00003  *      Toyohashi Open Platform for Embedded Real-Time Systems/
00004  *      Advanced Standard Profile Kernel
00005  * 
00006  *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
00007  *                              Toyohashi Univ. of Technology, JAPAN
00008  *  Copyright (C) 2006-2008 by Embedded and Real-Time Systems Laboratory
00009  *              Graduate School of Information Science, Nagoya Univ., JAPAN
00010  * 
00011  *  上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
00012  *  ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
00013  *  変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
00014  *  (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
00015  *      権表示,この利用条件および下記の無保証規定が,そのままの形でソー
00016  *      スコード中に含まれていること.
00017  *  (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
00018  *      用できる形で再配布する場合には,再配布に伴うドキュメント(利用
00019  *      者マニュアルなど)に,上記の著作権表示,この利用条件および下記
00020  *      の無保証規定を掲載すること.
00021  *  (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
00022  *      用できない形で再配布する場合には,次のいずれかの条件を満たすこ
00023  *      と.
00024  *    (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
00025  *        作権表示,この利用条件および下記の無保証規定を掲載すること.
00026  *    (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
00027  *        報告すること.
00028  *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
00029  *      害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
00030  *      また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
00031  *      由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
00032  *      免責すること.
00033  * 
00034  *  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
00035  *  よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
00036  *  に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
00037  *  アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
00038  *  の責任を負わない.
00039  * 
00040  *  @(#) $Id: serial.c 895 2008-04-11 11:23:58Z hiro $
00041  */
00042 
00043 /*
00044  *      シリアルインタフェースドライバ
00045  */
00046 
00047 #include <kernel.h>
00048 #include <t_syslog.h>
00049 #include "target_syssvc.h"
00050 #include "target_serial.h"
00051 #include "serial.h"
00052 #include "kernel_cfg.h"
00053 
00054 /*
00055  *  バッファサイズのデフォルト値とバッファの定義
00056  */
00057 #ifndef SERIAL_RCV_BUFSZ1
00058 #define SERIAL_RCV_BUFSZ1   256         /* ポート1の受信バッファサイズ */
00059 #endif /* SERIAL_RCV_BUFSZ1 */
00060 
00061 #ifndef SERIAL_SND_BUFSZ1
00062 #define SERIAL_SND_BUFSZ1   256         /* ポート1の送信バッファサイズ */
00063 #endif /* SERIAL_SND_BUFSZ1 */
00064 
00065 static char_t   rcv_buffer1[SERIAL_RCV_BUFSZ1];
00066 static char_t   snd_buffer1[SERIAL_SND_BUFSZ1];
00067 
00068 #if TNUM_PORT >= 2                      /* ポート2に関する定義 */
00069 
00070 #ifndef SERIAL_RCV_BUFSZ2
00071 #define SERIAL_RCV_BUFSZ2   256         /* ポート2の受信バッファサイズ */
00072 #endif /* SERIAL_RCV_BUFSZ2 */
00073 
00074 #ifndef SERIAL_SND_BUFSZ2
00075 #define SERIAL_SND_BUFSZ2   256         /* ポート2の送信バッファサイズ */
00076 #endif /* SERIAL_SND_BUFSZ2 */
00077 
00078 static char_t   rcv_buffer2[SERIAL_RCV_BUFSZ2];
00079 static char_t   snd_buffer2[SERIAL_SND_BUFSZ2];
00080 
00081 #endif /* TNUM_PORT >= 2 */
00082 
00083 #if TNUM_PORT >= 3                      /* ポート3に関する定義 */
00084 
00085 #ifndef SERIAL_RCV_BUFSZ3
00086 #define SERIAL_RCV_BUFSZ3   256         /* ポート3の受信バッファサイズ */
00087 #endif /* SERIAL_RCV_BUFSZ3 */
00088 
00089 #ifndef SERIAL_SND_BUFSZ3
00090 #define SERIAL_SND_BUFSZ3   256         /* ポート3の送信バッファサイズ */
00091 #endif /* SERIAL_SND_BUFSZ3 */
00092 
00093 static char_t   rcv_buffer3[SERIAL_RCV_BUFSZ3];
00094 static char_t   snd_buffer3[SERIAL_SND_BUFSZ3];
00095 
00096 #endif /* TNUM_PORT >= 3 */
00097 
00098 /*
00099  *  フロー制御に関連する定数とマクロ
00100  */
00101 #define FC_STOP         '\023'      /* コントロール-S */
00102 #define FC_START        '\021'      /* コントロール-Q */
00103 
00104 #define BUFCNT_STOP(bufsz)      ((bufsz) * 3 / 4)   /* STOPを送る基準文字数 */
00105 #define BUFCNT_START(bufsz)     ((bufsz) / 2)       /* STARTを送る基準文字数 */
00106 
00107 /*
00108  *  シリアルポート初期化ブロック
00109  */
00110 typedef struct serial_port_initialization_block {
00111     ID      rcv_semid;      /* 受信バッファ管理用セマフォのID */
00112     ID      snd_semid;      /* 送信バッファ管理用セマフォのID */
00113     uint_t  rcv_bufsz;      /* 受信バッファサイズ */
00114     char_t  *rcv_buffer;    /* 受信バッファ */
00115     uint_t  snd_bufsz;      /* 送信バッファサイズ */
00116     char_t  *snd_buffer;    /* 送信バッファ */
00117 } SPINIB;
00118 
00119 static const SPINIB spinib_table[TNUM_PORT] = {
00120     { SERIAL_RCV_SEM1, SERIAL_SND_SEM1,
00121       SERIAL_RCV_BUFSZ1, rcv_buffer1,
00122       SERIAL_SND_BUFSZ1, snd_buffer1 },
00123 #if TNUM_PORT >= 2
00124     { SERIAL_RCV_SEM2, SERIAL_SND_SEM2,
00125       SERIAL_RCV_BUFSZ2, rcv_buffer2,
00126       SERIAL_SND_BUFSZ2, snd_buffer2 },
00127 #endif /* TNUM_PORT >= 2 */
00128 #if TNUM_PORT >= 3
00129     { SERIAL_RCV_SEM3, SERIAL_SND_SEM3,
00130       SERIAL_RCV_BUFSZ3, rcv_buffer3,
00131       SERIAL_SND_BUFSZ3, snd_buffer3 },
00132 #endif /* TNUM_PORT >= 3 */
00133 };
00134 
00135 /*
00136  *  シリアルポート管理ブロック
00137  */
00138 typedef struct serial_port_control_block {
00139     const SPINIB *p_spinib;     /* シリアルポート初期化ブロック */
00140     SIOPCB  *p_siopcb;          /* シリアルI/Oポート管理ブロック */
00141     bool_t  openflag;           /* オープン済みフラグ */
00142     bool_t  errorflag;          /* エラーフラグ */
00143     uint_t  ioctl;              /* 動作制御の設定値 */
00144 
00145     uint_t  rcv_read_ptr;       /* 受信バッファ読出しポインタ */
00146     uint_t  rcv_write_ptr;      /* 受信バッファ書込みポインタ */
00147     uint_t  rcv_count;          /* 受信バッファ中の文字数 */
00148     char_t  rcv_fc_chr;         /* 送るべきSTART/STOP */
00149     bool_t  rcv_stopped;        /* STOPを送った状態か? */
00150 
00151     uint_t  snd_read_ptr;       /* 送信バッファ読出しポインタ */
00152     uint_t  snd_write_ptr;      /* 送信バッファ書込みポインタ */
00153     uint_t  snd_count;          /* 送信バッファ中の文字数 */
00154     bool_t  snd_stopped;        /* STOPを受け取った状態か? */
00155 } SPCB;
00156 
00157 static SPCB spcb_table[TNUM_PORT];
00158 
00159 /*
00160  *  シリアルポートIDからシリアルポート管理ブロックを取り出すためのマクロ
00161  */
00162 #define INDEX_PORT(portid)  ((uint_t)((portid) - 1))
00163 #define get_spcb(portid)    (&(spcb_table[INDEX_PORT(portid)]))
00164 
00165 /*
00166  *  ポインタのインクリメント
00167  */
00168 #define INC_PTR(ptr, bufsz)     { if (++(ptr) == (bufsz)) { (ptr) = 0; }}
00169 
00170 /*
00171  *  サービスコール呼出しマクロ
00172  *
00173  *  サービスコール呼出しを含む式expを評価し,返値がエラー(負の値)の場
00174  *  合には,ercにercd_expを評価した値を代入し,error_exitにgotoする.
00175  */
00176 #define SVC(exp, ercd_exp) \
00177                 { if ((exp) < 0) { ercd = (ercd_exp); goto error_exit; }}
00178 
00179 /*
00180  *  E_SYSエラーの生成
00181  */
00182 static ER
00183 gen_ercd_sys(SPCB *p_spcb)
00184 {
00185     p_spcb->errorflag = true;
00186     return(E_SYS);
00187 }
00188 
00189 /*
00190  *  待ちに入るサービスコールからのエラーの変換
00191  */
00192 static ER
00193 gen_ercd_wait(ER rercd, SPCB *p_spcb)
00194 {
00195     switch (MERCD(rercd)) {
00196     case E_RLWAI:
00197     case E_DLT:
00198         return(rercd);
00199     default:
00200         p_spcb->errorflag = true;
00201         return(E_SYS);
00202     }
00203 }
00204 
00205 /*
00206  *  シリアルインタフェースドライバの初期化ルーチン
00207  */
00208 void
00209 serial_initialize(intptr_t exinf)
00210 {
00211     uint_t  i;
00212     SPCB    *p_spcb;
00213 
00214     for (p_spcb = spcb_table, i = 0; i < TNUM_PORT; p_spcb++, i++) {
00215         p_spcb->p_spinib = &(spinib_table[i]);
00216         p_spcb->openflag = false;
00217     }
00218 }
00219 
00220 /*
00221  *  シリアルポートのオープン(サービスコール)
00222  */
00223 ER
00224 serial_opn_por(ID portid)
00225 {
00226     SPCB    *p_spcb;
00227     ER      ercd;
00228 
00229     if (sns_dpn()) {                /* コンテキストのチェック */
00230         return(E_CTX);
00231     }
00232     if (!(1 <= portid && portid <= TNUM_PORT)) {
00233         return(E_ID);               /* ポート番号のチェック */
00234     }
00235     p_spcb = get_spcb(portid);
00236 
00237     SVC(dis_dsp(), gen_ercd_sys(p_spcb));
00238     if (p_spcb->openflag) {         /* オープン済みかのチェック */
00239         ercd = E_OBJ;
00240     }
00241     else {
00242         /*
00243          *  変数の初期化
00244          */
00245         p_spcb->ioctl = (IOCTL_ECHO | IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV);
00246 
00247         p_spcb->rcv_read_ptr = p_spcb->rcv_write_ptr = 0U;
00248         p_spcb->rcv_count = 0U;
00249         p_spcb->rcv_fc_chr = '\0';
00250         p_spcb->rcv_stopped = false;
00251 
00252         p_spcb->snd_read_ptr = p_spcb->snd_write_ptr = 0U;
00253         p_spcb->snd_count = 0U;
00254         p_spcb->snd_stopped = false;
00255 
00256         /*
00257          *  これ以降,割込みを禁止する.
00258          */
00259         if (loc_cpu() < 0) {
00260             ercd = E_SYS;
00261             goto error_exit_enadsp;
00262         }
00263 
00264         /*
00265          *  ハードウェア依存のオープン処理
00266          */
00267         p_spcb->p_siopcb = sio_opn_por(portid, (intptr_t) p_spcb);
00268 
00269         /*
00270          *  受信通知コールバックを許可する.
00271          */
00272         sio_ena_cbr(p_spcb->p_siopcb, SIO_RDY_RCV);
00273         p_spcb->openflag = true;
00274         p_spcb->errorflag = false;
00275 
00276         if (unl_cpu() < 0) {
00277             p_spcb->errorflag = true;
00278             ercd = E_SYS;
00279             goto error_exit_enadsp;
00280         }
00281         ercd = E_OK;
00282     }
00283 
00284   error_exit_enadsp:
00285     SVC(ena_dsp(), gen_ercd_sys(p_spcb));
00286 
00287   error_exit:
00288     return(ercd);
00289 }
00290 
00291 /*
00292  *  シリアルポートのクローズ(サービスコール)
00293  */
00294 ER
00295 serial_cls_por(ID portid)
00296 {
00297     SPCB    *p_spcb;
00298     ER      ercd;
00299     bool_t  eflag = false;
00300 
00301     if (sns_dpn()) {                /* コンテキストのチェック */
00302         return(E_CTX);
00303     }
00304     if (!(1 <= portid && portid <= TNUM_PORT)) {
00305         return(E_ID);               /* ポート番号のチェック */
00306     }
00307     p_spcb = get_spcb(portid);
00308 
00309     SVC(dis_dsp(), gen_ercd_sys(p_spcb));
00310     if (!(p_spcb->openflag)) {      /* オープン済みかのチェック */
00311         ercd = E_OBJ;
00312     }
00313     else {
00314         /*
00315          *  ハードウェア依存のクローズ処理
00316          */
00317         if (loc_cpu() < 0) {
00318             eflag = true;
00319         }
00320         sio_cls_por(p_spcb->p_siopcb);
00321         p_spcb->openflag = false;
00322         if (unl_cpu() < 0) {
00323             eflag = true;
00324         }
00325 
00326         /*
00327          *  セマフォの初期化
00328          */
00329         if (ini_sem(p_spcb->p_spinib->snd_semid) < 0) {
00330             eflag = true;
00331         }
00332         if (ini_sem(p_spcb->p_spinib->rcv_semid) < 0) {
00333             eflag = true;
00334         }
00335 
00336         /*
00337          *  エラーコードの設定
00338          */
00339         if (eflag) {
00340             ercd = gen_ercd_sys(p_spcb);
00341         }
00342         else {
00343             ercd = E_OK;
00344         }
00345     }
00346     SVC(ena_dsp(), gen_ercd_sys(p_spcb));
00347 
00348   error_exit:
00349     return(ercd);
00350 }
00351 
00352 /*
00353  *  シリアルポートへの文字送信
00354  *
00355  *  p_spcbで指定されるシリアルI/Oポートに対して,文字cを送信する.文字
00356  *  を送信レジスタにいれた場合にはtrueを返す.そうでない場合には,送信
00357  *  レジスタが空いたことを通知するコールバック関数を許可し,falseを返す.
00358  *  この関数は,CPUロック状態で呼び出される.
00359  */
00360 Inline bool_t
00361 serial_snd_chr(SPCB *p_spcb, char_t c)
00362 {
00363     if (sio_snd_chr(p_spcb->p_siopcb, c)) {
00364         return(true);
00365     }
00366     else {
00367         sio_ena_cbr(p_spcb->p_siopcb, SIO_RDY_SND);
00368         return(false);
00369     }
00370 }
00371 
00372 /*
00373  *  シリアルポートへの1文字送信
00374  */
00375 static ER_BOOL
00376 serial_wri_chr(SPCB *p_spcb, char_t c)
00377 {
00378     bool_t  buffer_full;
00379     ER      ercd, rercd;
00380 
00381     /*
00382      *  LFの前にCRを送信する.
00383      */
00384     if (c == '\n' && (p_spcb->ioctl & IOCTL_CRLF) != 0U) {
00385         SVC(rercd = serial_wri_chr(p_spcb, '\r'), rercd);
00386         if ((bool_t) rercd) {
00387             SVC(rercd = wai_sem(p_spcb->p_spinib->snd_semid),
00388                                         gen_ercd_wait(rercd, p_spcb));
00389         }
00390     }
00391 
00392     SVC(loc_cpu(), gen_ercd_sys(p_spcb));
00393     if (p_spcb->snd_count == 0U && !(p_spcb->snd_stopped)
00394                                 && serial_snd_chr(p_spcb, c)) {
00395         /*
00396          *  シリアルI/Oデバイスの送信レジスタに文字を入れることに成功し
00397          *  た場合.
00398          */
00399         buffer_full = false;
00400     }
00401     else {
00402         /*
00403          *  送信バッファに文字を入れる.
00404          */
00405         p_spcb->p_spinib->snd_buffer[p_spcb->snd_write_ptr] = c;
00406         INC_PTR(p_spcb->snd_write_ptr, p_spcb->p_spinib->snd_bufsz);
00407         p_spcb->snd_count++;
00408         buffer_full = (p_spcb->snd_count == p_spcb->p_spinib->snd_bufsz);
00409     }
00410 
00411     SVC(unl_cpu(), gen_ercd_sys(p_spcb));
00412     ercd = (ER_BOOL) buffer_full;
00413 
00414   error_exit:
00415     return(ercd);
00416 }
00417 
00418 /*
00419  *  シリアルポートへの文字列送信(サービスコール)
00420  */
00421 ER_UINT
00422 serial_wri_dat(ID portid, char_t *buf, uint_t len)
00423 {
00424     SPCB    *p_spcb;
00425     bool_t  buffer_full;
00426     uint_t  wricnt = 0U;
00427     ER      ercd, rercd;
00428 
00429     if (sns_dpn()) {                /* コンテキストのチェック */
00430         return(E_CTX);
00431     }
00432     if (!(1 <= portid && portid <= TNUM_PORT)) {
00433         return(E_ID);               /* ポート番号のチェック */
00434     }
00435 
00436     p_spcb = get_spcb(portid);
00437     if (!(p_spcb->openflag)) {      /* オープン済みかのチェック */
00438         return(E_OBJ);
00439     }
00440     if (p_spcb->errorflag) {        /* エラー状態かのチェック */
00441         return(E_SYS);
00442     }
00443 
00444     buffer_full = true;             /* ループの1回めはwai_semする */
00445     while (wricnt < len) {
00446         if (buffer_full) {
00447             SVC(rercd = wai_sem(p_spcb->p_spinib->snd_semid),
00448                                         gen_ercd_wait(rercd, p_spcb));
00449         }
00450         SVC(rercd = serial_wri_chr(p_spcb, *buf++), rercd);
00451         wricnt++;
00452         buffer_full = (bool_t) rercd;
00453     }
00454     if (!buffer_full) {
00455         SVC(sig_sem(p_spcb->p_spinib->snd_semid), gen_ercd_sys(p_spcb));
00456     }
00457     ercd = E_OK;
00458 
00459   error_exit:
00460     return(wricnt > 0U ? (ER_UINT) wricnt : ercd);
00461 }
00462 
00463 /*
00464  *  シリアルポートからの1文字受信
00465  */
00466 static bool_t
00467 serial_rea_chr(SPCB *p_spcb, char_t *p_c)
00468 {
00469     bool_t  buffer_empty;
00470     ER      ercd;
00471 
00472     SVC(loc_cpu(), gen_ercd_sys(p_spcb));
00473 
00474     /*
00475      *  受信バッファから文字を取り出す.
00476      */
00477     *p_c = p_spcb->p_spinib->rcv_buffer[p_spcb->rcv_read_ptr];
00478     INC_PTR(p_spcb->rcv_read_ptr, p_spcb->p_spinib->rcv_bufsz);
00479     p_spcb->rcv_count--;
00480     buffer_empty = (p_spcb->rcv_count == 0U);
00481 
00482     /*
00483      *  STARTを送信する.
00484      */
00485     if (p_spcb->rcv_stopped && p_spcb->rcv_count
00486                                 <= BUFCNT_START(p_spcb->p_spinib->rcv_bufsz)) {
00487         if (!serial_snd_chr(p_spcb, FC_START)) {
00488             p_spcb->rcv_fc_chr = FC_START;
00489         }
00490         p_spcb->rcv_stopped = false;
00491     }
00492 
00493     SVC(unl_cpu(), gen_ercd_sys(p_spcb));
00494     ercd = (ER_BOOL) buffer_empty;
00495 
00496   error_exit:
00497     return(ercd);
00498 }
00499 
00500 /*
00501  *  シリアルポートからの文字列受信(サービスコール)
00502  */
00503 ER_UINT
00504 serial_rea_dat(ID portid, char_t *buf, uint_t len)
00505 {
00506     SPCB    *p_spcb;
00507     bool_t  buffer_empty;
00508     uint_t  reacnt = 0U;
00509     char_t  c = '\0';       /* コンパイラの警告を抑止するために初期化する */
00510     ER      ercd, rercd;
00511 
00512     if (sns_dpn()) {                /* コンテキストのチェック */
00513         return(E_CTX);
00514     }
00515     if (!(1 <= portid && portid <= TNUM_PORT)) {
00516         return(E_ID);               /* ポート番号のチェック */
00517     }
00518 
00519     p_spcb = get_spcb(portid);
00520     if (!(p_spcb->openflag)) {      /* オープン済みかのチェック */
00521         return(E_OBJ);
00522     }
00523     if (p_spcb->errorflag) {        /* エラー状態かのチェック */
00524         return(E_SYS);
00525     }
00526 
00527     buffer_empty = true;            /* ループの1回めはwai_semする */
00528     while (reacnt < len) {
00529         if (buffer_empty) {
00530             SVC(rercd = wai_sem(p_spcb->p_spinib->rcv_semid),
00531                                         gen_ercd_wait(rercd, p_spcb));
00532         }
00533         SVC(rercd = serial_rea_chr(p_spcb, &c), rercd);
00534         *buf++ = c;
00535         reacnt++;
00536         buffer_empty = (bool_t) rercd;
00537 
00538         /*
00539          *  エコーバック処理.
00540          */
00541         if ((p_spcb->ioctl & IOCTL_ECHO) != 0U) {
00542             SVC(rercd = wai_sem(p_spcb->p_spinib->snd_semid),
00543                                         gen_ercd_wait(rercd, p_spcb));
00544             SVC(rercd = serial_wri_chr(p_spcb, c), rercd);
00545             if (!((bool_t) rercd)) {
00546                 SVC(sig_sem(p_spcb->p_spinib->snd_semid),
00547                                         gen_ercd_sys(p_spcb));
00548             }
00549         }
00550     }
00551     if (!buffer_empty) {
00552         SVC(sig_sem(p_spcb->p_spinib->rcv_semid), gen_ercd_sys(p_spcb));
00553     }
00554     ercd = E_OK;
00555 
00556   error_exit:
00557     return(reacnt > 0U ? (ER_UINT) reacnt : ercd);
00558 }
00559 
00560 /*
00561  *  シリアルポートの制御(サービスコール)
00562  */
00563 ER
00564 serial_ctl_por(ID portid, uint_t ioctl)
00565 {
00566     SPCB    *p_spcb;
00567 
00568     if (sns_dpn()) {                /* コンテキストのチェック */
00569         return(E_CTX);
00570     }
00571     if (!(1 <= portid && portid <= TNUM_PORT)) {
00572         return(E_ID);               /* ポート番号のチェック */
00573     }
00574 
00575     p_spcb = get_spcb(portid);
00576     if (!(p_spcb->openflag)) {      /* オープン済みかのチェック */
00577         return(E_OBJ);
00578     }
00579     if (p_spcb->errorflag) {        /* エラー状態かのチェック */
00580         return(E_SYS);
00581     }
00582 
00583     p_spcb->ioctl = ioctl;
00584     return(E_OK);
00585 }
00586 
00587 /*
00588  *  シリアルポート状態の参照(サービスコール)
00589  */
00590 ER
00591 serial_ref_por(ID portid, T_SERIAL_RPOR *pk_rpor)
00592 {
00593     SPCB    *p_spcb;
00594 
00595     if (sns_dpn()) {                /* コンテキストのチェック */
00596         return(E_CTX);
00597     }
00598     if (!(1 <= portid && portid <= TNUM_PORT)) {
00599         return(E_ID);               /* ポート番号のチェック */
00600     }
00601 
00602     p_spcb = get_spcb(portid);
00603     if (!(p_spcb->openflag)) {      /* オープン済みかのチェック */
00604         return(E_OBJ);
00605     }
00606     if (p_spcb->errorflag) {        /* エラー状態かのチェック */
00607         return(E_SYS);
00608     }
00609 
00610     pk_rpor->reacnt = p_spcb->rcv_count;
00611     pk_rpor->wricnt = p_spcb->snd_count;
00612     return(E_OK);
00613 }
00614 
00615 /*
00616  *  シリアルポートからの送信可能コールバック
00617  */
00618 void
00619 sio_irdy_snd(intptr_t exinf)
00620 {
00621     SPCB    *p_spcb;
00622 
00623     p_spcb = (SPCB *) exinf;
00624     if (p_spcb->rcv_fc_chr != '\0') {
00625         /*
00626          *  START/STOP を送信する.
00627          */
00628         (void) sio_snd_chr(p_spcb->p_siopcb, p_spcb->rcv_fc_chr);
00629         p_spcb->rcv_fc_chr = '\0';
00630     }
00631     else if (!(p_spcb->snd_stopped) && p_spcb->snd_count > 0U) {
00632         /*
00633          *  送信バッファ中から文字を取り出して送信する.
00634          */
00635         (void) sio_snd_chr(p_spcb->p_siopcb,
00636                     p_spcb->p_spinib->snd_buffer[p_spcb->snd_read_ptr]);
00637         INC_PTR(p_spcb->snd_read_ptr, p_spcb->p_spinib->snd_bufsz);
00638         if (p_spcb->snd_count == p_spcb->p_spinib->snd_bufsz) {
00639             if (isig_sem(p_spcb->p_spinib->snd_semid) < 0) {
00640                 p_spcb->errorflag = true;
00641             }
00642         }
00643         p_spcb->snd_count--;
00644     }
00645     else {
00646         /*
00647          *  送信すべき文字がない場合は,送信可能コールバックを禁止する.
00648          */
00649         sio_dis_cbr(p_spcb->p_siopcb, SIO_RDY_SND);
00650     }
00651 }
00652 
00653 /*
00654  *  シリアルポートからの受信通知コールバック
00655  */
00656 void
00657 sio_irdy_rcv(intptr_t exinf)
00658 {
00659     SPCB    *p_spcb;
00660     char_t  c;
00661 
00662     p_spcb = (SPCB *) exinf;
00663     c = (char_t) sio_rcv_chr(p_spcb->p_siopcb);
00664     if ((p_spcb->ioctl & IOCTL_FCSND) != 0U && c == FC_STOP) {
00665         /*
00666          *  送信を一時停止する.送信中の文字はそのまま送信する.
00667          */
00668         p_spcb->snd_stopped = true;
00669     }
00670     else if (p_spcb->snd_stopped && (c == FC_START
00671                 || (p_spcb->ioctl & IOCTL_FCANY) != 0U)) {
00672         /*
00673          *  送信を再開する.
00674          */
00675         p_spcb->snd_stopped = false;
00676         if (p_spcb->snd_count > 0U) {
00677             c = p_spcb->p_spinib->snd_buffer[p_spcb->snd_read_ptr];
00678             if (serial_snd_chr(p_spcb, c)) {
00679                 INC_PTR(p_spcb->snd_read_ptr, p_spcb->p_spinib->snd_bufsz);
00680                 if (p_spcb->snd_count == p_spcb->p_spinib->snd_bufsz) {
00681                     if (isig_sem(p_spcb->p_spinib->snd_semid) < 0) {
00682                         p_spcb->errorflag = true;
00683                     }
00684                 }
00685                 p_spcb->snd_count--;
00686             }
00687         }
00688     }
00689     else if ((p_spcb->ioctl & IOCTL_FCSND) != 0U && c == FC_START) {
00690         /*
00691          *  送信に対してフロー制御している場合,START は捨てる.
00692          */
00693     }
00694     else if (p_spcb->rcv_count == p_spcb->p_spinib->rcv_bufsz) {
00695         /*
00696          *  バッファフルの場合,受信した文字を捨てる.
00697          */
00698     }
00699     else {
00700         /*
00701          *  受信した文字を受信バッファに入れる.
00702          */
00703         p_spcb->p_spinib->rcv_buffer[p_spcb->rcv_write_ptr] = c;
00704         INC_PTR(p_spcb->rcv_write_ptr, p_spcb->p_spinib->rcv_bufsz);
00705         if (p_spcb->rcv_count == 0U) {
00706             if (isig_sem(p_spcb->p_spinib->rcv_semid) < 0) {
00707                 p_spcb->errorflag = true;
00708             }
00709         }
00710         p_spcb->rcv_count++;
00711 
00712         /*
00713          *  STOPを送信する.
00714          */
00715         if ((p_spcb->ioctl & IOCTL_FCRCV) != 0U && !(p_spcb->rcv_stopped)
00716                         && p_spcb->rcv_count
00717                             >= BUFCNT_STOP(p_spcb->p_spinib->rcv_bufsz)) {
00718             if (!serial_snd_chr(p_spcb, FC_STOP)) {
00719                 p_spcb->rcv_fc_chr = FC_STOP;
00720             }
00721             p_spcb->rcv_stopped = true;
00722         }
00723     }
00724 }
00725 
00726 /*
00727  *  シリアルインタフェースドライバからの未送信文字の取出し
00728  */
00729 bool_t
00730 serial_get_chr(ID portid, char_t *p_c)
00731 {
00732     SPCB    *p_spcb;
00733 
00734     if (1 <= portid && portid <= TNUM_PORT) {   /* ポート番号のチェック */
00735         p_spcb = get_spcb(portid);
00736         if (p_spcb->openflag) {                 /* オープン済みかのチェック */
00737             if (p_spcb->snd_count > 0U) {
00738                 *p_c = p_spcb->p_spinib->snd_buffer[p_spcb->snd_read_ptr];
00739                 INC_PTR(p_spcb->snd_read_ptr, p_spcb->p_spinib->snd_bufsz);
00740                 p_spcb->snd_count--;
00741                 return(true);
00742             }
00743         }
00744     }
00745     return(false);
00746 }

Copyright © 2008 by Kijineko Inc.

ホームページ制作