www.pudn.com > norti2.0 > NOS98.C
/****************************************************************************** * NORTi対応 シルアル入出力ドライバ(PC9801) * * * * File name : nos98.c * * Copyright (c) Miyazaki System Planning Office. 1993-1995 * * * * Compile : cl /c /A? /Ox nos98.c (MS-C 5.1/6.0/7.0) * * tcc -c -m? nos98.c (TC 2.0, TC++ 1.0) * * bcc -c -m? -O2 nos98.c (BC++ 3.x) * * * * 93-04-13 作成 * * 93-05-16 Ver1.13β * * 94-01-05 Ver1.14 * * 95-06-25 Ver1.20 * * 95-09-12 Ver1.21 * ******************************************************************************/ /* CH マクロで、論理チャネル番号を指定できます。例えば、CH=0 と定義すると、 シリアル入出力チャネル0 としてコンパイルされます。 論理チャネル番号の範囲は、0〜4 です。 CH0, CH1, CH2 マクロで、物理チャネル番号を指定できます。 CH0 を定義すると、内蔵チャネル を使うようにコンパイルされます。 CH1 を定義すると、拡張チャネル1 を使うようにコンパイルされます。 CH2 を定義すると、拡張チャネル2 を使うようにコンパイルされます。 */ #include#include #include #include #include #include "norti.h" #include "nosio.h" #include "nos98.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〜3)*/ #ifndef CH #define CH 0 /* 無指定の場合, 論理チャネルは0 */ #endif /* 物理チャネル番号(CH0,CH1,CH2)*/ #ifndef CH0 #ifndef CH1 #ifndef CH2 #if (CH==0) #define CH0 /* 無指定の場合, 論理チャネル0 の物理チャネルは0 */ #elif (CH==1) #define CH1 /* 無指定の場合, 論理チャネル1 の物理チャネルは1 */ #elif (CH==2) #define CH2 /* 無指定の場合, 論理チャネル2 の物理チャネルは2 */ #endif #endif #endif #endif /* CHxに合わせた再定義 */ #ifdef CH0 #define INT_SIO INT_SIO0 #define SIO_DR SIO0_DR #define SIO_CR SIO0_CR #define SIO_MSR SIO0_MSR #define SIO_IER SIO0_IER #endif #ifdef CH1 #define INT_SIO INT_SIO1 #define SIO_DR SIO1_DR #define SIO_CR SIO1_CR #define SIO_MSR SIO1_MSR #define SIO_IER SIO1_IER #endif #ifdef CH2 #define INT_SIO INT_SIO2 #define SIO_DR SIO2_DR #define SIO_CR SIO2_CR #define SIO_MSR SIO2_MSR #define SIO_IER SIO2_IER #endif /* モニタ表示用のVRAMアドレス(EXE286/ハイレゾ未対応)*/ #ifndef VRAM_SIOMON #define VRAM_SIOMON ((0xa0000000L)+(24*80+76)*2) #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 msr, lsr; /* 現在のモデムステータス入力 */ msr = (UB)(~inp(SIO_MSR) & (SIO_CS|SIO_CD)); msr >>= 5; /* 現在のステータス入力 */ /* 受信時のステータスのエラービットとOR */ lsr = (UB)(inp(SIO_CR) & (SIO_DSR|SIO_BD|SIO_FE|SIO_OE|SIO_PE|SIO_TxEMP)); lsr |= SIO[CH].rxsts & (SIO_FE|SIO_OE|SIO_PE); /* 両者をOR */ return (UB)(lsr | msr); } /***************************************************************************** * モニタ表示(内部関数, EXE286/ハイレゾ未対応) * * 画面右下隅に、送受信文字及びステータスを表示する。 * * ・・86・(例) * 」」」ス * EEWwCC DSR,BD,FE,OE,PE,TxEMP,CTS,CD (2桁の16進数) * EWCCCC 受信文字 * WCCCCC 送信文字 ******************************************************************************/ static void near sio_mon(void) { H far *vram; if ((vram = SIO[CH].vram) != NULL) { UB stat; INT i; /* 送受信した文字表示 */ *vram++ = SIO[CH].txchr; *vram++ = SIO[CH].rxchr; /* ステータス表示 */ stat = get_stat(); i = stat >> 4; *vram++ = (H)((i < 10) ? ('0'+ i) : ('A' - 10 + i)); i = stat & 0x0f; *vram = (H)((i < 10) ? ('0'+ i) : ('A' - 10 + i)); } } /***************************************************************************** * モニタ表示クリア(内部関数) * ******************************************************************************/ static void near clr_sio_mon(void) { H far *vram; if ((vram = SIO[CH].vram) != NULL) { *vram++ = ' '; *vram++ = ' '; *vram++ = ' '; *vram = ' '; } } /***************************************************************************** * ポート連続アクセス時の挿入NOP(内部関数) * ******************************************************************************/ static int near nop1(void) { return 0; } static int near nop(int n) { while (n-- >= 0) nop1(); return 0; } /***************************************************************************** * SIOデバイス初期化(内部関数) * ******************************************************************************/ #ifdef CH0 static void near init_sio(UB mode, UW baud) #else static void near init_sio(UB mode) #endif { #ifdef CH0 UH tc; #endif /* ボーレート・ジェネレータ初期化(CH0 のみ) */ #ifdef CH0 outp(I8253_CR, 0xb4); /* カウンタ#2をモード2で使用 */ if (*(B far *)0x500001L & 0x80) /* BIOSワークエリアを参照 */ tc = (UH)(124800L / baud); /* 8MHz系の時定数 */ else tc = (UH)(153600L / baud); /* 10MHz系の時定数 */ outp(I8253_2, tc); /* 時定数下位を設定 */ outp(I8253_2, tc >> 8); /* 時定数上位を設定 */ #endif /* リセット */ outp(SIO_CR, 0x00); /* 0を3回 */ nop(2); outp(SIO_CR, 0x00); nop(2); outp(SIO_CR, 0x00); nop(2); outp(SIO_CR, SIO_IR); nop(2); /* モード設定 */ outp(SIO_CR, mode); nop(2); /* コマンド設定 */ outp(SIO_CR, SIO[CH].cmd[2] = 0); } /***************************************************************************** * SIOへ送信文字を出力(内部関数) * * 出力できた場合 TRUE、出力できなかった場合 FALSE を返す。 ******************************************************************************/ static BOOL near _fastcall tx_chr(UB c) { /* 送信レディでなかったら送信割込み許可 */ if (!(inp(SIO_CR) & SIO_TxRDY)) { #ifdef CH0 outp(SIO_IER, (inp(SIO_IER) & ~(SIO_RxIE|SIO_TxIE|SIO_TEIE)) | (SIO[0].cmd[0] |= SIO_TxIE)); #else outp(SIO_IER, SIO[0].cmd[0] |= SIO_TxIE); #endif 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_CR, SIO[CH].cmd[2] |= SIO_RTS); /* DTR-CTSフロー制御の解除 */ if (SIO[CH].flag & TSF_DTR) outp(SIO_CR, 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)) { sio_mon(); /* モニタ表示 */ 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_CR, SIO[CH].cmd[2] &= ~SIO_RTS); /* RTS OFF */ } /* DTR-CTSフロー制御 */ else if (SIO[CH].flag & TSF_DTR) { if (cnt == DTROFF_LEN) outp(SIO_CR, 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_CR, 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_CR, 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 (inp(SIO_CR) & SIO_RxRDY) { /* 受信文字とステータスを入力 */ SIO[CH].rxchr = (UB)inp(SIO_DR); sts = (UB)inp(SIO_CR); /* 受信エラーならエラーリセット */ if (sts &= (SIO_BD|SIO_FE|SIO_OE|SIO_PE)) outp(SIO_CR, SIO[CH].cmd[2] | SIO_ER); SIO[CH].oldsts = SIO[CH].rxsts; /* 前回の受信ステータス記憶 */ SIO[CH].rxsts = sts; /* 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; /* 送信レディでなくなるまで繰り返し */ while (inp(SIO_CR) & SIO_TxRDY) { /* 受信側から依頼された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); /* 8251 は 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); /* 8251 は TxRDY OFF の反応が遅い! */ } /* 送信割込み許可 */ SIO[CH].cmd[0] |= SIO_TxIE; } /***************************************************************************** * シリアル割込みハンドラ本体(内部関数) * ******************************************************************************/ static void near int_sio(void) { /* 割込み操作 */ #ifdef CH0 outp(SIO_IER, inp(SIO_IER) & ~(SIO_RxIE|SIO_TxIE|SIO_TEIE)); #else outp(SIO_IER, 0); /* 送受信割込み禁止 */ #endif dis_int(INT_SIO); /* シリアル割込み禁止 */ #ifdef CH2 outp(I8259S, 0x20); /* CH2 ではスレーブ8259へEOI */ outp(I8259S, 0x0b); /* スレーブにISRリードコマンド */ if (inp(I8259S) == 0) /* サービス中の割込みなければ */ outp(I8259, 0x20); /* マスタ8259へもEOI */ #else outp(I8259, 0x20); /* CH0, CH1 ではマスタ8259へEOI */ #endif enable(); /* CPU割込み許可 */ /* 受信処理 */ rx_int(); /* 送信処理 */ tx_int(); /* モニタ表示 */ sio_mon(); /* 割込み操作 */ disable(); /* CPU割込み禁止 */ ena_int(INT_SIO); /* シリアル割込み許可 */ #ifdef CH0 outp(SIO_IER, (inp(SIO_IER) & ~(SIO_RxIE|SIO_TxIE|SIO_TEIE)) | SIO[CH].cmd[0]); #else outp(SIO_IER, SIO[CH].cmd[0]); #endif } /***************************************************************************** * シリアル割込みハンドラ * ******************************************************************************/ #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(); /* 割込み終了 */ } /***************************************************************************** * 初期化パラメータ解析(内部関数) * ******************************************************************************/ #ifdef CH0 static BOOL near set_param(const B *s, UB *mode, UW *baud) #else static BOOL near set_param(const B *s, UB *mode) #endif { #ifdef CH0 B c; W b; #endif UB md; /* モード判別 */ md = SIO_X16; 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, "MON") != NULL) SIO[CH].vram = (H far *)VRAM_SIOMON; /* 終端文字指定判別 */ 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; /* ボーレート判別(CH0のみ)*/ /* 3桁以上の数値検索して変換 */ #ifdef CH0 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; } #endif 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; #ifdef CH0 UW baud; #endif /* 制御ブロック初期化 */ if (!init_buf()) return E_NOMEM; /* メモリ不足 */ /* パラメータ解析 */ /* デバイス初期化 */ #ifdef CH0 if (!set_param(param, &mode, &baud)) return E_PAR; init_sio(mode, baud); #else if (!set_param(param, &mode)) return E_PAR; init_sio(mode); #endif /* 割込みハンドラの定義 */ 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); #ifdef CH0 outp(SIO_IER, (inp(SIO_IER) & ~(SIO_RxIE|SIO_TxIE|SIO_TEIE)) | (SIO[CH].cmd[0] = SIO_RxIE)); #else outp(SIO_IER, SIO[CH].cmd[0] = SIO_RxIE); #endif sio_mon(); /* モニタ表示 */ 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); /* シリアル割込み禁止 */ #ifdef CH0 outp(SIO_IER, inp(SIO_IER) & ~(SIO_RxIE|SIO_TxIE|SIO_TEIE)); #else outp(SIO_IER, 0); /* 送受信割込み禁止 */ #endif outp(SIO_CR, 0x00); /* 送受信禁止, DTR/RTS OFF */ clr_sio_mon(); /* モニタ表示消去 */ 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 |TSIO_SBON|TSIO_SBOFF |TSIO_RTSON|TSIO_RTSOFF|TSIO_DTRON|TSIO_DTROFF)) { c = SIO[CH].cmd[2]; if (fncd & TSIO_RXE) c |= SIO_RxE; if (fncd & TSIO_RXD) c &= ~SIO_RxE; if (fncd & TSIO_TXE) c |= SIO_TxE; if (fncd & TSIO_TXD) c &= ~SIO_TxE; if (fncd & TSIO_SBON) c |= SIO_SB; if (fncd & TSIO_SBOFF) c &= ~SIO_SB; 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_CR, SIO[CH].cmd[2] = c); } ena_int(INT_SIO); /* シリアル割込み許可 */ sio_mon(); /* モニタ表示 */ 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 */