📄 commdrv.c
字号:
/* RS232 Device Driver (2 channel v0.6) */
/* Copyright 1991, 1992, R.A. Burgess */
/* Copyright 1993, The D-Group & R.A. Burgess */
#define U32 unsigned long
#define S32 long
#define U16 unsigned int
#define S16 int
#define U8 unsigned char
#define S8 char
#define TRUE 1
#define FALSE 0
#include "commdrv.h"
/* MMURTL OS Prototypes */
extern far U32 AllocExch(U32 *pExchRet);
extern far U32 InitDevDr(U32 dDevNum,
S8 *pDCBs,
U32 nDevices,
U32 dfReplace);
extern far U32 AllocOSPage(U32 nPages, U8 **ppMemRet);
extern far U32 DeAllocPage(U8 *pOrigMem, U32 nPages);
extern far U32 UnMaskIRQ(U32 IRQNum);
extern far U32 MaskIRQ(U32 IRQNum);
extern far U32 SetIRQVector(U32 IRQNum, S8 *pIRQ);
extern far U32 EndOfIRQ(U32 IRQNum);
extern far U32 SendMsg(U32 Exch, U32 msg1, U32 msg2);
extern far U32 ISendMsg(U32 Exch, U32 msg1, U32 msg2);
extern far U32 WaitMsg(U32 Exch, S8 *pMsgRet);
extern far U32 CheckMsg(U32 Exch, S8 *pMsgRet);
extern far U32 GetTimerTick(U32 *pTickRet);
extern far U32 Alarm(U32 Exch, U32 count);
extern far U32 KillAlarm(U32 Exch);
extern far U32 Sleep(U32 count);
extern far void MicroDelay(U32 us15count);
extern far void OutByte(U8 Byte, U16 wPort);
extern far U8 InByte(U16 wPort);
extern far void CopyData(U8 *pSource, U8 *pDestination, U32 dBytes);
extern far long GetJobNum(long *pJobNumRet);
/* local prototypes */
U32 comdev_stat(U32 dDevice,
S8 *pStatRet,
U32 dStatusMax,
U32 *pdStatusRet);
S32 comdev_init(U32 dDevice,
S8 *pInitData,
U32 sdInitData);
U32 comdev_op(U32 dDevice,
U32 dOpNum,
U32 dLBA,
U32 dnBlocks,
U8 *pData);
#define CmdReadRec 1 /* Read one or more bytes */
#define CmdWriteRec 2 /* Write one or more bytes */
#define CmdOpenC 10 /* Open Comm Channel */
#define CmdCloseC 11 /* Close Comm Channel */
#define CmdDiscardRcv 12
#define CmdSetRTO 13
#define CmdSetXTO 14
#define CmdSetDTR 15 /* Set DTR (On) */
#define CmdSetRTS 16 /* Set CTS (On) */
#define CmdReSetDTR 17 /* Set DTR (On) */
#define CmdReSetRTS 18 /* Set CTS (On) */
#define CmdBreak 19
#define CmdGetDC 20
#define CmdGetDSR 21
#define CmdGetCTS 22
#define CmdGetRI 23
#define CmdReadB 31
#define CmdWriteB 32
/* The following definitions are used to identify, set
and reset signal line condition and functions.
*/
#define CTS 0x10 /* Clear To Send */
#define DSR 0x20 /* Data Set Ready */
#define RI 0x40 /* Ring Indicator */
#define CD 0x80 /* Carrier Detect */
#define DTR 0x01 /* Data Terminal Ready */
#define RTS 0x02 /* Request To Send */
#define OUT2 0x08 /* Not used */
/* values from IIR register */
#define MDMSTAT 0x00
#define NOINT 0x01
#define TXEMPTY 0x02
#define RVCDATA 0x04
#define RCVSTAT 0x06
/* For errors returned from Comms calls see COMMDRV.H */
#define SSENDBUF 4096 /* 1 Page Send Buf Default */
#define SRECVBUF 4096 /* 1 Page Recv Buf Default */
U32 recv_timeout[2] = 1; /* 10ms intervals */
U32 xmit_timeout[2] = 10; /* 10ms intervals */
/* variables for ISRs */
U8 stat_byte[2];
U8 mstat_byte[2];
U8 int_id[2];
U8 fExpectInt[2];
U32 recv_error[2]; /* NON-ZERO = an error has occurred */
U8 *pSendBuf[2]; /* pointers to Xmit bufs */
U32 head_send[2]; /* Next char to send */
U32 tail_send[2]; /* Where next char goes in buf */
U32 cSendBuf[2]; /* Count of bytes in buf */
U32 sSendBuf[2]; /* Size of buffer (allocated) */
U8 *pRecvBuf[2]; /* pointers to Recv bufs */
U32 head_recv[2]; /* Next char from chip */
U32 tail_recv[2]; /* Next char to read for caller */
U32 cRecvBuf[2]; /* Count of bytes in buf */
U32 sRecvBuf[2]; /* Size of buffer (allocated) */
U8 control_byte[2] = 0;
/* array of registers from port base for each channel */
U16 THR[2]; /* Transmitter Holding Register */
U16 IER[2]; /* Interrupt Enable Register */
U16 IIR[2]; /* Interrupt Id Register */
U16 LCR[2]; /* Line Control Register */
U16 MCR[2]; /* Modem Control Register */
U16 LSR[2]; /* Line Status Register */
U16 MSR[2]; /* Modem Status Register */
U16 DLAB_LO[2]; /* same address as THR */
U16 DLAB_HI[2]; /* same address as IER */
/* Complete description of Register bits follows:
THR -- TX data, RX data, Divisor Latch LSB
IER -- Interrupt Enable, Divisor Latch MSB
7 6 5 4 3 2 1 0
| | | | | | | \_ Data Available
| | | | | | \___ Xmit Holding Reg Empty
| | | | | \_____ Receiver Line Status
| | | | \_______ Modem Status
\ _ _ _\_________ = Always 0
IIR -- Interrupt Identification Register
7 6 5 4 3 2 1 0
| | | | | \_\_\___ 001 = no interrupt
| | | | | 110 = rcvr status
| | | | | 100 = rcvd data
| | | | | 010 = THR empty
| | | | | 000 = Modem status
\ _ _ _ _\_______ = Always 0
LCR -- Line Control Register
7 6 5 4 3 2 1 0
| | | | | | | \_ Word Length Select Bit 0.
| | | | | | \___ Word Length Select Bit 1.
| | | | | \_____ Number Stop Bits (0=1, 1=2)
| | | | \_______ Parity Enable
| | | \_________ Even Parity Select
| | \___________ Stick Parity
| \_____________ Set Break
\_______________ Divisor Latch Access Bit
MCR -- Modem Control Register
7 6 5 4 3 2 1 0
| | | | | | | \_ Data Terminal Ready
| | | | | | \___ Request to Send
| | | | | \_____ Out 1
| | | | \_______ Out 2 (= 1 to enable ints.)
| | | \_________ Loop
\ _ _\___________ = Always 0
LSR -- Line Status Register
7 6 5 4 3 2 1 0
| | | | | | | \_ Data Ready
| | | | | | \___ Overrun Error
| | | | | \_____ Parity Error
| | | | \_______ Framing Error
| | | \_________ Break interrupt
| | \___________ Transmitter Holding Reg Empty
| \_____________ Transmitter Shift Reg Empty
\_______________ = 0
MSR -- Modem Status Register
7 6 5 4 3 2 1 0
| | | | | | | \_ Delta Clear to Send
| | | | | | \___ Delta Data Set Ready
| | | | | \_____ Trailing Edge Ring Indicator
| | | | \_______ Delta Rx Line Signal Detect
| | | \_________ Clear to Send
| | \___________ Data Set Ready
| \_____________ Ring Indicator
\_______________ Receive Line Signal Detect
*/
/* Record for 64 byte status and init record */
/* This structure is peculiar to the comms driver */
#define sStatus 64
struct statRecC comstat[2];
struct statRecC *pCS;
struct dcbtype {
S8 Name[12];
S8 sbName;
S8 type;
S16 nBPB;
U32 last_erc;
U32 nBlocks;
S8 *pDevOp;
S8 *pDevInit;
S8 *pDevSt;
S8 fDevReent;
S8 fSingleUser;
S16 wJob;
U32 OS1;
U32 OS2;
U32 OS3;
U32 OS4;
U32 OS5;
U32 OS6;
};
struct dcbtype comdcb[2]; /* Two RS-232 ports */
/* THE COMMS INTERRUPT FUNCTION PROTOTYPES */
void interrupt comISR0(void);
void interrupt comISR1(void);
/* -------------------------------------------------- */
/* -------------------------------------------------- */
/* -------------------------------------------------- */
/*********************************************************
This is called ONCE to initialize the 2 default
coms channels with the OS device driver interface.
It sets up defaults for both channels to 9600, 8N1.
*********************************************************/
U32 coms_setup(void)
{
U32 erc;
/* first we set up the 2 DCBs in anticipation of calling InitDevDr */
comdcb[0].Name[0] = 'C';
comdcb[0].Name[1] = 'O';
comdcb[0].Name[2] = 'M';
comdcb[0].Name[2] = '1';
comdcb[0].sbName = 4;
comdcb[0].type = 2; /* Sequential */
comdcb[0].nBPB = 1; /* 1 byte per block */
comdcb[0].nBlocks = 0; /* 0 for Sequential devices */
comdcb[0].pDevOp = &comdev_op;
comdcb[0].pDevInit = &comdev_init;
comdcb[0].pDevSt = &comdev_stat;
comdcb[1].Name[0] = 'C';
comdcb[1].Name[1] = 'O';
comdcb[1].Name[2] = 'M';
comdcb[1].Name[2] = '2';
comdcb[1].sbName = 4;
comdcb[1].type = 2; /* Sequential */
comdcb[1].nBPB = 1; /* 1 byte per block */
comdcb[1].nBlocks = 0; /* 0 for Sequential devices */
comdcb[1].pDevOp = &comdev_op;
comdcb[1].pDevInit = &comdev_init;
comdcb[1].pDevSt = &comdev_stat;
/* Set default comms params in stat records */
comstat[0].Baudrate = 9600;
comstat[0].parity = 0; /* none */
comstat[0].databits = 8;
comstat[0].stopbits = 1;
comstat[0].XTimeOut = 100;
comstat[0].RTimeOut = 2;
comstat[0].IOBase = 0x3F8;
comstat[0].IRQNum = 4;
comstat[0].XBufSize = 4096;
comstat[0].RBufSize = 4096;
sSendBuf[0] = 4096;
sRecvBuf[0] = 4096;
comstat[1].Baudrate = 9600;
comstat[1].parity = 0; /* none */
comstat[1].databits = 8;
comstat[1].stopbits = 1;
comstat[1].XTimeOut = 100;
comstat[1].RTimeOut = 2;
comstat[1].IOBase = 0x2F8;
comstat[1].IRQNum = 3;
comstat[1].XBufSize = 4096;
comstat[1].RBufSize = 4096;
sSendBuf[1] = 4096;
sRecvBuf[1] = 4096;
MaskIRQ(4);
MaskIRQ(3);
SetIRQVector(4, &comISR0); /* COM1 */
SetIRQVector(3, &comISR1); /* COM2 */
return(erc = InitDevDr(5, &comdcb, 2, 1));
}
/*********************************************************
This does the grunt work for each of the two ISRs
*********************************************************/
void handleISR(U32 i) /* i is the device */
{
U8 *pRBuf, *pXBuf;
pRBuf = pRecvBuf[i];
pXBuf = pSendBuf[i];
while (TRUE) {
int_id[i] = InByte (IIR[i]); /* Get ID Byte from IIR */
switch (int_id[i]) {
case RCVSTAT:
stat_byte[i] = InByte(LSR[i]); /* clear error conditions */
break;
case RVCDATA:
if (cRecvBuf[i] == sRecvBuf[i]) { /* Overflow!! */
recv_error[i] = ErcRcvBufOvr; /* Do not put in buf */
InByte (THR[i]); /* trash the byte */
}
else {
#asm
CLI
#endasm
pRBuf[head_recv[i]] =
InByte (THR[i]); /* Get the byte */
++cRecvBuf[i];
if (++head_recv[i] == SRECVBUF)
head_recv[i] = 0;
#asm
STI
#endasm
recv_error[i] = 0;
}
break;
case TXEMPTY:
#asm
CLI
#endasm
if (cSendBuf[i]) {
OutByte(pXBuf[tail_send[i]], THR[i]); /* Send the byte */
if (++tail_send[i] == sSendBuf[i])
tail_send[i] = 0;
--cSendBuf[i];
fExpectInt[i] = TRUE;
}
else
fExpectInt[i] = FALSE;
#asm
STI
#endasm
break;
case MDMSTAT:
mstat_byte[i] = InByte (MSR[i]); /* Get Modem Status */
break;
case NOINT:
stat_byte[i] = InByte(LSR[i]); /* clear error conditions */
default:
return;
}
}
}
void interrupt comISR0(void)
{
; /* ; needed if asm is first in function */
#asm
STI
#endasm
handleISR(0);
EndOfIRQ(4);
return;
}
void interrupt comISR1(void)
{
; /* ; needed if asm is first in function */
#asm
STI
#endasm
handleISR(1);
EndOfIRQ(3);
return;
}
/********************************************/
long ReadByteC(U32 device, unsigned char *pByteRet)
{
U32 counter;
U8 *pRBuf;
pRBuf = pRecvBuf[device];
if (recv_error[device]) return (recv_error[device]);
if (cRecvBuf[device]) {
*pByteRet = pRBuf[tail_recv[device]];
if (++tail_recv[device] == sRecvBuf[device])
tail_recv[device] = 0;
--cRecvBuf[device];
return (0);
}
counter = comstat[device].RTimeOut; /* set up for timeout */
while (counter--) {
Sleep(1);
if (cRecvBuf[device]) {
*pByteRet = pRBuf[tail_recv[device]];
if (++tail_recv[device] == sRecvBuf[device])
tail_recv[device] = 0;
--cRecvBuf[device];
return (0);
}
}
return (ErcRecvTimeout);
}
/********************************************/
long ReadRecordC(U32 device,
unsigned char *pDataRet,
unsigned int sDataMax,
unsigned int *pcbRet)
{
int erc, cb;
erc = 0;
cb = 0;
while ((cb < sDataMax) && (!erc)) {
erc = ReadByteC(device, pDataRet++);
if (!erc) ++cb;
}
*pcbRet = cb; /* tell em how many bytes */
return (erc);
}
/********************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -