📄 comm.cpp
字号:
for (; *s;) // for each char in the string
Write(*s++); // write to the output queue
}
/* ******************************************************************** *
*
* Write -- write a block of characters to output queue
*
* ******************************************************************** */
void Comm::Write(char *s, // block of chars to output
int l) // length of block
{
for (; l--;) // for each char in the block
Write(*s++); // write to the output queue
}
/* ******************************************************************** **
*
* IClear -- clear input queue of unread characters
*
* ******************************************************************** */
void Comm::IClear(void)
{
__asm cli // stop interrupts
i_get = i_put = i_buf; // reset buffer pointers
i_count = 0; // ..and queue count
__asm sti // ..and re-enable interrupts
}
/* ******************************************************************** **
*
* OClear -- clear output queue of unsent characters
*
* ******************************************************************** */
void Comm::OClear(void)
{
__asm cli // stop interrupts
o_get = o_put = o_buf; // reset buffer pointers
o_count = 0; // ..and queue count
__asm sti // ..and re-enable interrupts
}
/* ******************************************************************** *
*
* Queue -- put a character into the input queue
*
* ******************************************************************** */
void Comm::Queue(int c, // character to store
int m, // modem status register
int l) // line status register
{
if (flow && (ICount() >= i_stop) && // q. flow control needed?
NOT i_flow) // ..and not already on
RTS(0); // a. yes .. clear RTS line
switch (IFree()) // based on avail queue space
{
case 0: // full input queue
if (i_of) // q. in overflow?
{ // a. yes .. count lost chars
if (*(UINT *) i_last < 65534U) // q. within lost count range?
(*(UINT *) i_last)++; // a. yes .. tally another one
}
else
{
i_of = 1; // set overflow flag
*(UINT *) i_last = 2; // init counter to 2
i_last[2] = 0xff; // ..and set error flag in lsr
}
break; // ..and return to caller
case 1: // almost full
i_last = i_put; // save last saved addr
i_of = 0; // clear overflow flag
default: // from empty to almost full
i_count++; // count characters in queue
*i_put++ = c; // save character in queue
*i_put++ = m; // ..and modem status register
*i_put++ = l; // ..and line status register
if (i_put > i_limit) // q. reach end of buffer?
i_put = i_buf; // a. yes .. set to beginning
}
}
/* ******************************************************************** *
*
* Deque -- get a character from the output queue
*
* ******************************************************************** */
UINT Comm::Deque(void)
{
char c; // work character
if (o_count == 0) // q. output queue empty?
return(-1); // a. yes .. rtn empty handed
c = *o_get++; // get char from output queue
o_count--; // show character being removed
if (o_get > o_limit) // q. reached end of buffer?
o_get = o_buf; // a. yes .. set to beginning
return(c & 0xff); // ..and rtn with char to send
}
/* ******************************************************************** **
*
* ~Comm -- destructor
*
* ******************************************************************** */
Comm::~Comm(void)
{
OUT(MCR, 0); // take down DTR and RTS
DeInstallInt(); // remove interrupt service
delete i_buf; // free input
delete o_buf; // ..and output queues
}
/* ******************************************************************** *
*
* DTR -- cycle DTR modem signal
*
* ******************************************************************** */
void Comm::DTR(long t) // time to hold DTR low
{
OUT(MCR, MCR_DO & ~MCR_DTR); // set off DTR control line
wait_ms(t); // wait a little bit
OUT(MCR, MCR_DO); // ..and restore DTR
}
/* ******************************************************************** *
*
* RTS -- control RTS modem signal
*
* ******************************************************************** */
void Comm::RTS(int f) // RTS enable/disable flag
{
OUT(MCR, MCR_DO - (f ? 0 : MCR_RTS)); // set mcr register
i_flow = NOT f; // ..and set flow ctl'd flag
}
/* ******************************************************************** **
*
* IntRoutine -- communications port interrupt service routine
*
* ******************************************************************** */
void Comm::IntRoutine(void)
{
int c, // output character
cnt, // loop counter
first_cycle; // first cycle flag
char iir, // interrupt id register
lsr; // working line status reg
while (((iir = IN(IIR)) & IIR_PEND) == 0) // while there is work to do
{
switch (iir & IIR_II) // handle each interrupt
{
case IIR_MSI: // modem status interrupt
msr_changed = 1; // set msr changed flag
if ((int_msr = IN(MSR)) & // q. modem status register
MSR_CTS) // ..ready for transmits?
{
if (o_flow || // q. flow controlled?
IN(LSR) & LSR_THRE) // ..or transmitter empty?
{
o_flow = 0; // a. yes .. clear flag
if ((c = Deque()) == -1)// q. output queue empty?
empty_trans = 1; // a. yes .. set flag
else
OUT(THR, c); // else .. put out a character
}
}
continue; // ..and check next interrupt
case IIR_LSI: // line status interrupt
int_lsr = IN(LSR); // read line status register
continue; // ..and check again
case IIR_TBE: // transmitter buffer empty
cnt = fifo ? 15 : 1; // set up output fifo size
first_cycle = 1; // ..and first cycle flag
for (; cnt--;) // loop outputing characters
{
if (flow && // q. flow control enabled
NOT (IN(MSR) & MSR_CTS))// ..and receiver not ready?
{
o_flow = first_cycle; // a. yes .. show flow ctl'd
// ..if nothing went out
break; // ..and check next interrupt
}
if ((c = Deque()) == -1) // q. output queue empty?
{
empty_trans = 1; // a. yes .. set flag
break; // ..and exit this loop
}
OUT(THR, c); // put out another character
first_cycle = 0; // ..and clear flag
}
continue; // ..and check again
case IIR_RBF: // receiver buffer full
while ((lsr = IN(LSR)) & LSR_DR)// while data is available
Queue(IN(RBR), int_msr, // ..get and store
lsr); // ..in the input queue
continue; // check for next interrupt
}
}
__asm mov al, EOI // al = end of interrupt cmd
__asm out I8259, al // send EOI to int controller
}
/* ******************************************************************** *
*
* comm_int() -- communications port interrupt service routine header
*
* ******************************************************************** */
#pragma option -O2-b-e // no global reg allocation
// ..or dead code elimination
void interrupt far comm_int(...)
{
__asm sti // re-enable interrupts
comm->IntRoutine(); // use object's interrupt rtn
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -