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 */