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.