www.pudn.com > norti2.0 > NOSIBM.C
/****************************************************************************** * NORTi対応 シルアル入出力ドライバ(IBM-PC) * * * * File name : nosibm.c * * Copyright (c) Miyazaki System Planning Office. 1994-1995 * * * * Compile : cl /c /A? /Ox nosibm.c (MS-C 5.1/6.0/7.0) * * tcc -c -m? nosibm.c (TC 2.0, TC++ 1.0) * * bcc -c -m? -O2 nosibm.c (BC++ 3.x) * * * * 94-09-27 作成 * * 95-06-25 Ver1.20 * * 95-09-12 Ver1.21 * ******************************************************************************/ /* CH マクロで、論理チャネル番号を指定できます。例えば、CH=0 と定義すると、 シリアル入出力チャネル0 としてコンパイルされます。 論理チャネル番号の範囲は、0〜4 です。 無指定の場合のデフォルトは、CH=0 です。 CH1, CH2 マクロで、物理チャネル番号を指定できます。 CH1 を定義すると、チャネル1(COM1)を使うようにコンパイルされます。 CH2 を定義すると、チャネル2(COM2)を使うようにコンパイルされます。 無指定の場合のデフォルトは、CH=0 が CH1、CH=1 が CH2 です。 I/O アドレスは、03F8H, 02F8H に固定です。 割込みベクタは、0CH, 0BH に固定です。 */ #include#include #include #include #include #include "norti.h" #include "nosio.h" #include "nosibm.h" /* 処理系の差異の調整 */ #ifdef M_I86 /* MS-C の場合 */ #define enable _enable /* 関数名変更 */ #define disable _disable #pragma check_stack(off) /* スタックチェックなし */ #endif #ifndef _MSC_VER /* MS-C 6.0, BORLAND-C 以外では */ #ifndef __BORLANDC__ #define _fastcall pascal /* _fastcall 指定を pascal に変更 */ #endif #endif /* 論理チャネル番号(CH=0〜4)*/ #ifndef CH #define CH 0 /* 無指定の場合, 論理チャネルは0 */ #endif /* 物理チャネル番号(CH1,CH2)*/ #ifndef CH1 #ifndef CH2 #if (CH==0) #define CH1 /* 無指定の場合, 論理チャネル0 の物理チャネルは1 */ #elif (CH==1) #define CH2 /* 無指定の場合, 論理チャネル1 の物理チャネルは2 */ #endif #endif #endif /* CHxに合わせた再定義 */ #ifdef CH1 #define INT_SIO INT_SIO1 #define SIO_DR SIO1_DR #define SIO_IER SIO1_IER #define SIO_IIR SIO1_IIR #define SIO_LCR SIO1_LCR #define SIO_MCR SIO1_MCR #define SIO_MSR SIO1_MSR #define SIO_LSR SIO1_LSR #endif #ifdef CH2 #define INT_SIO INT_SIO2 #define SIO_DR SIO2_DR #define SIO_IER SIO2_IER #define SIO_IIR SIO2_IIR #define SIO_LCR SIO2_LCR #define SIO_MCR SIO2_MCR #define SIO_MSR SIO2_MSR #define SIO_LSR SIO2_LSR #endif /* 送受信バッファサイズの定義 */ #ifndef BUFSZ #define BUFSZ 1024 /* 受信バッファ長(10〜Hの上限)*/ #endif #ifndef TXBUFSZ #define TXBUFSZ BUFSZ /* 送信バッファ長(1〜Hの上限)*/ #endif /* フロー制御の定数 */ #define XOFF_LEN (BUFSZ*3/4) /* XOFF送信バッファ長 */ #define XON_LEN (BUFSZ*1/4) /* XON 送信バッファ長 */ #define DTROFF_LEN (BUFSZ-4) /* DTR/RTS信号OFFバッファ長 */ #define DTRON_LEN (BUFSZ-5) /* DTR/RTS信号ON バッファ長 */ /* シリアル入出力制御ブロック */ extern T_SIO SIO[]; /* 制御文字 */ #define XOFF 0x13 /* 送信停止(CTRL-S)*/ #define XON 0x11 /* 送信再開(CTRL-Q)*/ /***************************************************************************** * シリアル入出力制御ブロック初期化(内部関数) * ******************************************************************************/ static BOOL near init_buf(void) { UB *p; /* 制御ブロッククリア */ SIO[CH].ch = CH; /* チャネル番号 */ SIO[CH].flag &= ~TSF_INIT; /* 制御フラグ */ SIO[CH].txchr = 0; /* 送信文字 */ SIO[CH].rxchr = 0; /* 受信文字 */ SIO[CH].rxsts = 0; /* 受信ステータス */ SIO[CH].oldsts = 0; /* 前回の受信ステータス */ SIO[CH].eot = 0; /* 終端文字 */ SIO[CH].eotcnt = 0; /* 終端文字検出カウンタ */ SIO[CH].txtid = 0; /* 送信待ちタスクID */ SIO[CH].rxtid = 0; /* 受信待ちタスクID */ SIO[CH].tetid = 0; /* 送信終了待ちタスクID */ SIO[CH].cmd[0] = 0; /* SIOコマンドバッファ */ SIO[CH].cmd[1] = 0; SIO[CH].cmd[2] = 0; SIO[CH].txcnt = 0; /* 送信バッファ内の文字数 */ SIO[CH].rxcnt = 0; /* 受信バッファ内の文字数 */ /* バッファ確保 */ if (SIO[CH].flag & TSF_INIT) p = SIO[CH].txbuf; else p = malloc(TXBUFSZ+(BUFSZ*2)); if (p == NULL) return FALSE; /* ポインタ類セットアップ */ SIO[CH].txbuf = p; /* 送信バッファ */ SIO[CH].rxbuf = p + TXBUFSZ; /* 受信バッファ */ SIO[CH].txputp = SIO[CH].txbuf; /* 送信バッファ格納ポインタ初期値 */ SIO[CH].txgetp = SIO[CH].txbuf; /* 送信バッファ取得ポインタ初期値 */ SIO[CH].rxputp = SIO[CH].rxbuf; /* 受信バッファ格納ポインタ初期値 */ SIO[CH].rxgetp = SIO[CH].rxbuf; /* 受信バッファ取得ポインタ初期値 */ return TRUE; } /***************************************************************************** * ステータス入力 & 編集(内部関数) * ******************************************************************************/ static UB near get_stat(void) { UB stat, c; /* 現在のモデムステータス入力 */ c = (UB)inp(SIO_MSR); /* モデムステータスビット編集 */ stat = 0; if (c & SIO_CTS) stat |= TSIO_CTS; if (c & SIO_DSR) stat |= TSIO_DSR; if (c & SIO_CD) stat |= TSIO_CD; /* 現在のラインステータス入力 */ c = (UB)inp(SIO_LSR); /* 受信時のステータスのエラービットとOR */ c |= (SIO[CH].rxsts & (SIO_FE|SIO_OE|SIO_PE)); /* ラインステータスビット編集 */ if (c & SIO_PE) /* パリティエラー */ stat |= TSIO_PE; if (c & SIO_OE) /* オーバーランエラー */ stat |= TSIO_OE; if (c & SIO_FE) /* オーバーランエラー */ stat |= TSIO_FE; if (c & SIO_BD) /* ブレーク検出 */ stat |= TSIO_BD; if (c & SIO_TxEMP) /* 送信バッファ空 */ stat |= TSIO_TXEMP; return stat; } /***************************************************************************** * ポート連続アクセス時の挿入NOP(内部関数) * ******************************************************************************/ static int near nop1(void) { return 0; } static int near nop(int n) { while (n-- >= 0) nop1(); return 0; } /***************************************************************************** * SIOデバイス初期化(内部関数) * ******************************************************************************/ static void near init_sio(UB mode, UW baud) { UH tc; /* ラインコントロール・レジスタ設定 */ outp(SIO_LCR, SIO[CH].cmd[1] = mode); /* モデムコントロール・レジスタ・クリア */ outp(SIO_MCR, 0); /* ボーレート分周レジスタ設定 */ outp(SIO_LCR, SIO[CH].cmd[1] |= SIO_DLAB); /* DLAB = 1 */ tc = (UH)(115200L / baud); outp(SIO_DR, (UB)tc); outp(SIO_IER, (UB)(tc >> 8)); outp(SIO_LCR, SIO[CH].cmd[1] &= ~SIO_DLAB); /* DLAB = 0 */ } /***************************************************************************** * SIOへ送信文字を出力(内部関数) * * 出力できた場合 TRUE、出力できなかった場合 FALSE を返す。 ******************************************************************************/ static BOOL near _fastcall tx_chr(UB c) { /* 送信レディでなかったら送信割込み許可 */ if (!(inp(SIO_LSR) & SIO_TxRDY)) { outp(SIO_IER, SIO[CH].cmd[0] |= SIO_TxIE); return FALSE; } /* フロー制御ありなら CTS チェック */ /* CTS OFF なら モデムステータス割込み許可 */ if (SIO[CH].flag & (TSF_RTS|TSF_DTR)) { if (!(inp(SIO_MSR) & SIO_CTS)) { outp(SIO_IER, SIO[CH].cmd[0] |= SIO_MSIE); return FALSE; } } /* 1文字送信 */ outp(SIO_DR, SIO[CH].txchr = c); return TRUE; } /***************************************************************************** * 送信バッファクリア(内部関数) * ******************************************************************************/ static void near clr_txbuf(void) { SIO[CH].txcnt = 0; SIO[CH].txgetp = SIO[CH].txputp; } /***************************************************************************** * 受信バッファクリア(内部関数) * ******************************************************************************/ static void near clr_rxbuf(void) { /* 受信バッファクリア */ SIO[CH].rxsts = 0; SIO[CH].oldsts = 0; SIO[CH].eotcnt = 0; SIO[CH].rxcnt = 0; SIO[CH].rxgetp = SIO[CH].rxputp; /* RTS-CTSフロー制御の解除 */ if (SIO[CH].flag & TSF_RTS) outp(SIO_MCR, SIO[CH].cmd[2] |= SIO_RTS); /* DTR-CTSフロー制御の解除 */ if (SIO[CH].flag & TSF_DTR) outp(SIO_MCR, SIO[CH].cmd[2] |= SIO_DTR); /* XON/OFFフロー制御の解除 */ if (SIO[CH].flag & TSF_TXOFF) { if (tx_chr(XON)) SIO[CH].flag &= ~TSF_TXOFF; else SIO[CH].flag |= TSF_TXREQ; } } /***************************************************************************** * 送信バッファへ1文字格納(内部関数) * * バッファ満杯で格納できなかった場合は、FALSE を返す。 ******************************************************************************/ static BOOL near _fastcall put_txbuf(UB c) { /* 送信バッファ空でXOFF受信していないなら直接出力 */ if (SIO[CH].txcnt == 0 && !(SIO[CH].flag & TSF_RXOFF)) { if (tx_chr(c)) return TRUE; } /* バッファ満杯チェック */ /* バッファ内文字数 + 1 */ if (SIO[CH].txcnt >= TXBUFSZ) return FALSE; SIO[CH].txcnt++; /* バッファへ格納 */ *SIO[CH].txputp = c; /* 格納ポインタを1つ進める */ if (++SIO[CH].txputp >= SIO[CH].txbuf + TXBUFSZ) SIO[CH].txputp = SIO[CH].txbuf; return TRUE; } /***************************************************************************** * 受信バッファへ受信文字/ステータス格納(内部関数) * ******************************************************************************/ static void near put_rxbuf(void) { UH cnt; /* 連続ブレークチェック */ if ((SIO[CH].rxsts & SIO_BD) && (SIO[CH].oldsts & SIO_BD)) return; /* バッファ満杯チェック */ cnt = SIO[CH].rxcnt; if (cnt == BUFSZ) return; if (cnt == BUFSZ - 1) SIO[CH].rxsts |= SIO_RxRDY; /* オーバフローは RxRDY ビットに割り当て */ /* バッファへ格納 */ /* 終端文字検出+1 */ if ((*SIO[CH].rxputp = SIO[CH].rxchr) == SIO[CH].eot) SIO[CH].eotcnt++; *(SIO[CH].rxputp + BUFSZ) = SIO[CH].rxsts; /* 格納ポインタを1つ進める */ if (++SIO[CH].rxputp >= SIO[CH].rxbuf + BUFSZ) SIO[CH].rxputp = SIO[CH].rxbuf; /* バッファ内文字数 + 1 */ SIO[CH].rxcnt = ++cnt; /* RTS-CTSフロー制御 */ if (SIO[CH].flag & TSF_RTS) { if (cnt == DTROFF_LEN) outp(SIO_MCR, SIO[CH].cmd[2] &= ~SIO_RTS); /* RTS OFF */ } /* DTR-CTSフロー制御 */ else if (SIO[CH].flag & TSF_DTR) { if (cnt == DTROFF_LEN) outp(SIO_MCR, SIO[CH].cmd[2] &= ~SIO_DTR); /* DTR OFF */ } /* XON/OFFフロー制御 */ else if ((SIO[CH].flag & (TSF_XON|TSF_TXOFF)) == TSF_XON) { if (cnt == XOFF_LEN) SIO[CH].flag |= TSF_TXREQ; /* 続く送信処理にXOFF送信要求セット */ } } /***************************************************************************** * 受信バッファから1文字取得(内部関数) * * バッファ空で取得できなかった場合は、-1 を返す。 ******************************************************************************/ static INT near _fastcall get_rxbuf(UB *c) { UB sts; /* 受信バッファ空チェック */ if (SIO[CH].rxcnt == 0) return -1; /* 受信バッファから取得 */ /* 終端文字検出数-1 */ sts = *(SIO[CH].rxgetp + BUFSZ); if ((*c = *SIO[CH].rxgetp) == SIO[CH].eot) SIO[CH].eotcnt--; /* 取得ポインタを1つ進める */ if (++SIO[CH].rxgetp >= SIO[CH].rxbuf + BUFSZ) SIO[CH].rxgetp = SIO[CH].rxbuf; /* 受信バッファ内文字数 - 1 */ SIO[CH].rxcnt--; /* RTS-CTSフロー制御 */ if (SIO[CH].flag & TSF_RTS) { if (SIO[CH].rxcnt == DTRON_LEN) outp(SIO_MCR, SIO[CH].cmd[2] |= SIO_RTS); /* RTS ON */ } /* DTR-CTSフロー制御 */ else if (SIO[CH].flag & TSF_DTR) { if (SIO[CH].rxcnt == DTRON_LEN) outp(SIO_MCR, SIO[CH].cmd[2] |= SIO_DTR); /* DTR ON */ } /* XON/OFFフロー制御 */ else if (SIO[CH].flag & TSF_TXOFF) { if (SIO[CH].rxcnt == XON_LEN) { if (tx_chr(XON)) /* XON送信できたら */ SIO[CH].flag &= ~TSF_TXOFF; /* XOFF送信済みクリア */ else /* 送信できなければ */ SIO[CH].flag |= TSF_TXREQ; /* 送信要求セット */ } } return sts; } /***************************************************************************** * シリアル割込みハンドラ受信処理(内部関数) * ******************************************************************************/ static void near rx_int(void) { UB sts; /* 受信レディでなくなるまで繰り返し */ while ((sts = (UB)inp(SIO_LSR)) & SIO_RxRDY) { /* 受信文字入力, ステータス記憶 */ SIO[CH].rxchr = (UB)inp(SIO_DR); SIO[CH].oldsts = SIO[CH].rxsts; SIO[CH].rxsts = (UB)(sts & (SIO_BD|SIO_FE|SIO_OE|SIO_PE)); /* XON/OFFフロー制御有りの場合 */ if (SIO[CH].flag & TSF_XON) { /* XOFF受信なら送信中断させる */ if (SIO[CH].rxchr == XOFF) { SIO[CH].flag |= TSF_RXOFF; continue; } /* XON 受信なら送信再開させる */ if (SIO[CH].rxchr == XON) { SIO[CH].flag &= ~TSF_RXOFF; if (SIO[CH].txtid != 0) iwup_tsk(SIO[CH].txtid); continue; } } /* 受信バッファへ格納 */ put_rxbuf(); /* 受信待ち解除 */ if (SIO[CH].rxtid != 0) iwup_tsk(SIO[CH].rxtid); } } /***************************************************************************** * シリアル割込みハンドラ送信処理(内部関数) * * 送信割込み許可させるなら TRUE を返す。 ******************************************************************************/ static void near tx_int(void) { /* 送信割込みとモデムステータス割込み禁止 */ SIO[CH].cmd[0] &= ~(SIO_TxIE|SIO_MSIE); inp(SIO_MSR); /* モデムステータス割込みリセット */ /* 送信レディでなくなるまで繰り返し */ while (inp(SIO_LSR) & SIO_TxRDY) { /* フロー制御ありなら CTS チェック */ /* CTS OFF なら モデムステータス割込み許可 */ if (SIO[CH].flag & (TSF_RTS|TSF_DTR)) { if (!(inp(SIO_MSR) & SIO_CTS)) { SIO[CH].cmd[0] |= SIO_MSIE; return; } } /* 受信側から依頼されたXON/XOFFの送信 */ if (SIO[CH].flag & TSF_TXREQ) { if (SIO[CH].flag & TSF_TXOFF) { outp(SIO_DR, SIO[CH].txchr = XON); SIO[CH].flag &= ~TSF_TXOFF; } else { outp(SIO_DR, SIO[CH].txchr = XOFF); SIO[CH].flag |= TSF_TXOFF; } SIO[CH].flag &= ~TSF_TXREQ; nop(4); /* 8250 は TxRDY OFF の反応が遅い! */ continue; } /* XOFF受信していたら送信不可 */ if (SIO[CH].flag & TSF_RXOFF) return; /* 送信バッファ空なら送信不可 */ if (SIO[CH].txcnt == 0) { /* 送信終了待ち解除 */ if (SIO[CH].tetid != 0) iwup_tsk(SIO[CH].tetid); return; } /* 送信バッファ内文字数 - 1 */ SIO[CH].txcnt--; /* 送信バッファから取得して出力 */ outp(SIO_DR, SIO[CH].txchr = *SIO[CH].txgetp); /* 取得ポインタを1つ進める */ if (++SIO[CH].txgetp >= SIO[CH].txbuf + TXBUFSZ) SIO[CH].txgetp = SIO[CH].txbuf; /* 送信待ち解除 */ if (SIO[CH].txtid != 0) iwup_tsk(SIO[CH].txtid); else nop(3); /* 8250 は TxRDY OFF の反応が遅い! */ } /* 送信割込み許可 */ SIO[CH].cmd[0] |= SIO_TxIE; } /***************************************************************************** * シリアル割込みハンドラ本体(内部関数) * ******************************************************************************/ static void near int_sio(void) { /* 割込み操作 */ outp(SIO_IER, 0); outp(SIO_MCR, SIO[CH].cmd[2] &= ~SIO_OUT2); dis_int(INT_SIO); /* シリアル割込み禁止 */ outp(I8259, 0x20); /* 割込み終了コマンド発行 */ enable(); /* CPU割込み許可 */ /* 受信処理 */ rx_int(); /* 送信処理 */ tx_int(); /* 割込み操作 */ disable(); /* CPU割込み禁止 */ ena_int(INT_SIO); /* シリアル割込み許可 */ outp(SIO_MCR, SIO[CH].cmd[2] |= SIO_OUT2); outp(SIO_IER, SIO[CH].cmd[0]); } /***************************************************************************** * シリアル割込みハンドラ * ******************************************************************************/ #if (CH==0) INTHDR int_sio0(void) #elif (CH==1) INTHDR int_sio1(void) #elif (CH==2) INTHDR int_sio2(void) #elif (CH==3) INTHDR int_sio3(void) #elif (CH==4) INTHDR int_sio4(void) #endif { ent_int(); /* 割込み開始 */ int_sio(); /* 割込みハンドラ本体 */ ret_int(); /* 割込み終了 */ } /***************************************************************************** * 初期化パラメータ解析(内部関数) * ******************************************************************************/ static BOOL near set_param(const B *s, UB *mode, UW *baud) { B c; W b; UB md; /* モード判別 */ md = 0; if (strstr(s, "PE") != NULL) md |= SIO_EVEN; else if (strstr(s, "PO") != NULL) md |= SIO_ODD; else md |= SIO_NONE; if (strstr(s, "S2") != NULL) md |= SIO_S2; else md |= SIO_S1; /* データ長判別 */ if (strstr(s, "B7") != NULL) md |= SIO_B7; else md |= SIO_B8; *mode = md; /* フロー制御有無判別 */ if (strstr(s, "XON") != NULL) SIO[CH].flag |= TSF_XON; if (strstr(s, "DTR") != NULL) SIO[CH].flag |= TSF_DTR; if (strstr(s, "RTS") != NULL) SIO[CH].flag |= TSF_RTS; /* 終端文字指定判別 */ if (strstr(s, "ETX") != NULL) SIO[CH].eot = 0x03; if (strstr(s, "EOT") != NULL) SIO[CH].eot = 0x04; if (strstr(s, "CR" ) != NULL) SIO[CH].eot = 0x0d; if (strstr(s, "LF" ) != NULL) SIO[CH].eot = 0x0a; /* ボーレート判別 */ /* 3桁以上の数値検索して変換 */ for (;;) { c = *s++; if (c == '\0') { *baud = 9600L; break; } if (c < '0' || c > '9') continue; c = *s++; if (c < '0' || c > '9') continue; c = *s++; if (c < '0' || c > '9') continue; s -= 3; b = 0L; for (;;) { c = *s++; if (c < '0' || c > '9') break; b = b * 10 + (c - '0'); } *baud = b; break; } return TRUE; } /***************************************************************************** * シリアル入出力初期化 * ******************************************************************************/ #if (CH==0) ER cdecl ini_sio0(const B *param) #elif (CH==1) ER cdecl ini_sio1(const B *param) #elif (CH==2) ER cdecl ini_sio2(const B *param) #elif (CH==3) ER cdecl ini_sio3(const B *param) #elif (CH==4) ER cdecl ini_sio4(const B *param) #endif { UB mode; UW baud; /* 制御ブロック初期化 */ if (!init_buf()) return E_NOMEM; /* メモリ不足 */ /* パラメータ解析 */ if (!set_param(param, &mode, &baud)) return E_PAR; /* デバイス初期化 */ init_sio(mode, baud); /* 割込みハンドラの定義 */ if (!(SIO[CH].flag & TSF_INIT)) { #if (CH==0) def_int(INT_SIO, int_sio0); #elif (CH==1) def_int(INT_SIO, int_sio1); #elif (CH==2) def_int(INT_SIO, int_sio2); #elif (CH==3) def_int(INT_SIO, int_sio3); #elif (CH==4) def_int(INT_SIO, int_sio4); #endif } SIO[CH].flag |= TSF_INIT; /* 初期化済みセット */ /* シリアル割込み許可 */ ena_int(INT_SIO); outp(SIO_MCR, SIO[CH].cmd[2] |= SIO_OUT2); return E_OK; } /***************************************************************************** * シリアル入出力終了 * ******************************************************************************/ #if (CH==0) void cdecl ext_sio0(void) #elif (CH==1) void cdecl ext_sio1(void) #elif (CH==2) void cdecl ext_sio2(void) #elif (CH==3) void cdecl ext_sio3(void) #elif (CH==4) void cdecl ext_sio4(void) #endif { if (!(SIO[CH].flag & TSF_INIT)) /* 未初期化なら何もしない */ return; dis_int(INT_SIO); /* シリアル割込み禁止 */ outp(SIO_IER, 0x00); outp(SIO_MCR, 0x00); /* 送受信禁止, DTR/RTS OFF */ free(SIO[CH].txbuf); /* バッファ解放 */ SIO[CH].txbuf = NULL; SIO[CH].flag &= ~TSF_INIT; /* 初期化済みフラグクリア */ def_int(INT_SIO, (INTHDRP)NADR); /* 割込み定義を取り消し */ } /***************************************************************************** * シリアル1文字入力 * ******************************************************************************/ #if (CH==0) ER cdecl get_sio0(UB *c, TMO tmout) #elif (CH==1) ER cdecl get_sio1(UB *c, TMO tmout) #elif (CH==2) ER cdecl get_sio2(UB *c, TMO tmout) #elif (CH==3) ER cdecl get_sio3(UB *c, TMO tmout) #elif (CH==4) ER cdecl get_sio4(UB *c, TMO tmout) #endif { ER err; INT sts; for (;;) { dis_int(INT_SIO); /* シリアル割込み禁止 */ /* 受信バッファから1文字得る */ sts = get_rxbuf(c); if (sts != -1) /* 受信文字あった場合 */ { ena_int(INT_SIO); /* シリアル割込み許可 */ /* 受信エラー判別 */ if (sts & (SIO_RxRDY|SIO_BD|SIO_FE|SIO_OE|SIO_PE)) { if (sts & SIO_RxRDY) err = EV_SIOOVF; else if (sts & SIO_OE) err = EV_SIOORN; else if (sts & SIO_BD) err = EV_SIOBRK; else if (sts & SIO_FE) err = EV_SIOFRM; else /* SIO_PE */ err = EV_SIOPTY; } else err = E_OK; return err; } /* 受信割込み待ち */ SIO[CH].rxtid = vget_tid(); ena_int(INT_SIO); /* シリアル割込み許可 */ err = wai_tsk(tmout); SIO[CH].rxtid = 0; vcan_wup(); /* 複数回 iwup_tsk された場合の対策 */ if (err) return err; /* タイムアウト終了 */ } } /***************************************************************************** * シリアル1文字出力 * ******************************************************************************/ #if (CH==0) ER cdecl put_sio0(UB c, TMO tmout) #elif (CH==1) ER cdecl put_sio1(UB c, TMO tmout) #elif (CH==2) ER cdecl put_sio2(UB c, TMO tmout) #elif (CH==3) ER cdecl put_sio3(UB c, TMO tmout) #elif (CH==4) ER cdecl put_sio4(UB c, TMO tmout) #endif { ER err; for (;;) { dis_int(INT_SIO); /* シリアル割込み禁止 */ /* 送信バッファへ1文字格納 */ if (put_txbuf(c)) /* 送信できた場合 */ { ena_int(INT_SIO); /* シリアル割込み許可 */ return E_OK; /* 正常終了 */ } /* 送信割込み待ち */ SIO[CH].txtid = vget_tid(); ena_int(INT_SIO); /* シリアル割込み許可 */ err = wai_tsk(tmout); SIO[CH].txtid = 0; vcan_wup(); /* 複数回 iwup_tsk された場合の対策 */ if (err) return err; /* タイムアウト終了 */ } } /***************************************************************************** * シリアル入出力制御 * ******************************************************************************/ #if (CH==0) ER cdecl ctl_sio0(UH fncd) #elif (CH==1) ER cdecl ctl_sio1(UH fncd) #elif (CH==2) ER cdecl ctl_sio2(UH fncd) #elif (CH==3) ER cdecl ctl_sio3(UH fncd) #elif (CH==4) ER cdecl ctl_sio4(UH fncd) #endif { UB c; dis_int(INT_SIO); /* シリアル割込み禁止 */ /* バッファクリア */ if (fncd & TSIO_RXCLR) clr_rxbuf(); if (fncd & TSIO_TXCLR) clr_txbuf(); /* コマンド出力 */ if (fncd & (TSIO_RXE|TSIO_RXD)) /* TSIO_TXE,TSIO_TXD 未サポート! */ { c = SIO[CH].cmd[0]; if (fncd & TSIO_RXE) c |= SIO_RxIE; if (fncd & TSIO_RXD) c &= ~SIO_RxIE; outp(SIO_IER, SIO[CH].cmd[0] = c); } if (fncd & (TSIO_SBON|TSIO_SBOFF)) { c = SIO[CH].cmd[1]; if (fncd & TSIO_SBON) c |= SIO_SB; else c &= ~SIO_SB; outp(SIO_LCR, SIO[CH].cmd[1] = c); } if (fncd & (TSIO_RTSON|TSIO_RTSOFF|TSIO_DTRON|TSIO_DTROFF)) { c = SIO[CH].cmd[2]; if (fncd & TSIO_RTSON) c |= SIO_RTS; if (fncd & TSIO_RTSOFF) c &= ~SIO_RTS; if (fncd & TSIO_DTRON) c |= SIO_DTR; if (fncd & TSIO_DTROFF) c &= ~SIO_DTR; outp(SIO_MCR, SIO[CH].cmd[2] = c); } ena_int(INT_SIO); /* シリアル割込み許可 */ return E_OK; } /***************************************************************************** * シリアル入出力状態参照 * ******************************************************************************/ #if (CH==0) ER cdecl ref_sio0(T_SIOS *pk_sios) #elif (CH==1) ER cdecl ref_sio1(T_SIOS *pk_sios) #elif (CH==2) ER cdecl ref_sio2(T_SIOS *pk_sios) #elif (CH==3) ER cdecl ref_sio3(T_SIOS *pk_sios) #elif (CH==4) ER cdecl ref_sio4(T_SIOS *pk_sios) #endif { UB stat; dis_int(INT_SIO); /* シリアル割込み禁止 */ stat = get_stat(); if (SIO[CH].txcnt != 0) stat &= ~TSIO_TXEMP; pk_sios->siostat = stat; pk_sios->rxlen = SIO[CH].rxcnt; pk_sios->frbufsz = (UH)(TXBUFSZ - SIO[CH].txcnt); pk_sios->eotcnt = SIO[CH].eotcnt; ena_int(INT_SIO); /* シリアル割込み許可 */ return E_OK; } /***************************************************************************** * シリアル送信バッファ・フラッシュ * ******************************************************************************/ #if (CH==0) ER cdecl fls_sio0(TMO tmout) #elif (CH==1) ER cdecl fls_sio1(TMO tmout) #elif (CH==2) ER cdecl fls_sio2(TMO tmout) #elif (CH==3) ER cdecl fls_sio3(TMO tmout) #elif (CH==4) ER cdecl fls_sio4(TMO tmout) #endif { ER err; for (;;) { dis_int(INT_SIO); /* シリアル割込み禁止 */ /* 送信バッファ空の場合 */ if (SIO[CH].txcnt == 0) { ena_int(INT_SIO); /* シリアル割込み許可 */ return E_OK; /* 正常終了 */ } /* 送信終了割込み待ち */ SIO[CH].tetid = vget_tid(); ena_int(INT_SIO); /* シリアル割込み許可 */ err = wai_tsk(tmout); SIO[CH].tetid = 0; vcan_wup(); /* 複数回 iwup_tsk された場合の対策 */ if (err) return err; /* タイムアウト終了 */ } } /* end */