home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Over 1,000 Doom Levels
/
1000DOOMLevels-3DSharewareGames.bin
/
pc
/
doomfaqs
/
ser4_src
/
port.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-03-19
|
9KB
|
460 lines
// port.c
#include "doomnet.h"
#include "sersetup.h"
void jump_start( void );
void interrupt isr_8250 (void);
void interrupt isr_16550 (void);
union REGS regs;
struct SREGS sregs;
que_t inque, outque;
enum {UART_8250, UART_16550} uart_type;
extern int uart; // io address
extern int irq;
extern unsigned long baud;
int modem_status = -1;
int line_status = -1;
void interrupt (*oldirqvect) (void);
int irqintnum;
extern int comport;
/* showUartErrors() counters. */
extern unsigned long numBreak;
extern unsigned long numFramingError;
extern unsigned long numParityError;
extern unsigned long numOverrunError;
extern unsigned long numTxInterrupts;
extern unsigned long numRxInterrupts;
/*
==============
=
= GetUart
=
==============
*/
void GetUart (void)
{
char far *system_data;
static int ISA_uarts[] = {0x3f8,0x2f8,0x3e8,0x2e8};
static int ISA_IRQs[] = {4,3,4,3};
static int MCA_uarts[] = {0x03f8,0x02f8,0x3220,0x3228};
static int MCA_IRQs[] = {4,3,3,3};
regs.h.ah = 0xc0;
int86x( 0x15, ®s, ®s, &sregs );
if ( regs.x.cflag )
{
if (irq == -1)
irq = ISA_IRQs[ comport-1 ];
if (uart == -1)
uart = ISA_uarts[ comport-1 ];
return;
}
system_data = ( char far *) ( ( (long) sregs.es << 16 ) + regs.x.bx );
if ( system_data[ 5 ] & 0x02 )
{
if (irq == -1)
irq = MCA_IRQs[ comport-1 ];
if (uart == -1)
uart = MCA_uarts[ comport-1 ];
}
else
{
if (irq == -1)
irq = ISA_IRQs[ comport-1 ];
if (uart == -1)
uart = ISA_uarts[ comport-1 ];
}
printf ("Looking for UART at port 0x%x, irq %d...\n\n",uart,irq);
}
/*
===============
=
= InitPort
=
===============
*/
void InitPort (void)
{
int mcr;
int temp;
unsigned long divisor;
//
// init com port settings
//
/*******
regs.x.ax = 0xf3; //f3= 9600 n 8 1
regs.x.dx = comport - 1;
int86 (0x14, ®s, ®s);
*******/
if ((divisor = baud) == 14400)
divisor = 19200;
divisor = CLOCK_FREQUENCY / (16 * divisor); /* Calc. divisor */
OUTPUT( uart + LINE_CONTROL_REGISTER, LCR_DLAB ); /* Enable divisor */
OUTPUT( uart + DIVISOR_LATCH_HIGH, 0 ); /* Set divisor */
OUTPUT( uart + DIVISOR_LATCH_LOW, (unsigned char) divisor);
OUTPUT( uart + LINE_CONTROL_REGISTER, 3 ); /* Set 8,n,1 */
//
// check for a 16550
//
OUTPUT( uart + FIFO_CONTROL_REGISTER, FCR_FIFO_ENABLE + FCR_TRIGGER_04 );
temp = INPUT( uart + INTERRUPT_ID_REGISTER );
if ( ( temp & 0xf8 ) == 0xc0 )
{
uart_type = UART_16550;
printf ("UART is a 16550\n\n");
}
else
{
uart_type = UART_8250;
OUTPUT( uart + FIFO_CONTROL_REGISTER, 0 );
printf ("UART is an 8250\n\n");
}
//
// prepare for interrupts
//
OUTPUT( uart + INTERRUPT_ENABLE_REGISTER, 0 ); /* Turn off interrupts */
mcr = INPUT( uart + MODEM_CONTROL_REGISTER ); /* Get modem status */
mcr |= MCR_OUT2; /* Set GPO 2 */
mcr &= ~MCR_LOOPBACK; /* Turn off loopback test */
mcr |= MCR_DTR; /* Set DTR */
mcr |= MCR_RTS; /* Set RTS */
OUTPUT( uart + MODEM_CONTROL_REGISTER, mcr ); /* Set modem status */
INPUT( uart ); /* Clear Rx interrupts */
INPUT( uart + INTERRUPT_ID_REGISTER ); /* Clear Tx interrupts */
//
// hook the irq vector
//
irqintnum = irq + 8;
oldirqvect = getvect (irqintnum);
if( uart_type == UART_8250 ) /* Use different interrupt routines */
setvect (irqintnum, isr_8250);
else
setvect (irqintnum, isr_16550);
OUTPUT( 0x20 + 1, INPUT( 0x20 + 1 ) & ~(1<<irq) );
CLI();
// enable RX and TX interrupts at the uart
// also enable Line Status interrupts to watch for errors.
OUTPUT( uart + INTERRUPT_ENABLE_REGISTER,
IER_RX_DATA_READY + IER_TX_HOLDING_REGISTER_EMPTY + IER_LINE_STATUS );
// enable interrupts through the interrupt controller
OUTPUT( 0x20, 0xc2 );
STI();
}
/*
=============
=
= ShutdownPort
=
=============
*/
void ShutdownPort ( void )
{
OUTPUT( uart + INTERRUPT_ENABLE_REGISTER, 0 ); /* Turn off interrupts */
OUTPUT( uart + MODEM_CONTROL_REGISTER, 0 ); /* Clear modem status */
OUTPUT( uart + FIFO_CONTROL_REGISTER, 0 ); /* Clear fifo status */
OUTPUT( 0x20 + 1, INPUT( 0x20 + 1 ) | (1<<irq) );
setvect (irqintnum,oldirqvect); /* Return to orig. inter. */
#if 0 /* Leave port as it is. */
*
* regs.x.ax = 0xf3; //f3= 9600 n 8 1
* regs.x.dx = comport - 1;
* int86 (0x14, ®s, ®s);
*
#endif
}
int read_byte( void )
{
int c;
if (inque.size == 0)
return -1;
c = inque.data[inque.tail++];
inque.size--;
if (inque.tail >= QUESIZE)
inque.tail = 0; // wrap around
return c;
}
void write_byte( unsigned char c )
{
outque.data[outque.head++] = c;
outque.size++;
if (outque.head >= QUESIZE)
outque.head = 0; // wrap around
}
void write_bytes( char *buf, int count )
{
if (outque.head + count >= QUESIZE) /* About to wrap around */
{
while (count--)
write_byte (*buf++);
}
else
{
memcpy(outque.data + outque.head, buf, count); /* Write all at once */
outque.head += count;
outque.size += count;
}
}
//==========================================================================
/*
==============
=
= isr_8250
=
==============
*/
void interrupt isr_8250(void)
{
int c;
int count;
while (1)
{
switch( INPUT( uart + INTERRUPT_ID_REGISTER ) & 7 )
{
//
// receive exactly one byte, since this is a UART 8250
//
case IIR_RX_DATA_READY_INTERRUPT :
//I_ColorBlack (0,63,0);
++numRxInterrupts;
c = INPUT( uart + RECEIVE_BUFFER_REGISTER );
inque.data[inque.head++] = c;
inque.size++;
if (inque.head >= QUESIZE)
inque.head = 0; // wrap around
break;
//
// transmit exactly one byte, since this is a UART 8250
//
case IIR_TX_HOLDING_REGISTER_INTERRUPT :
//I_ColorBlack (63,0,0);
++numTxInterrupts;
if (outque.size != 0)
{
c = outque.data[outque.tail++];
outque.size--;
if (outque.tail >= QUESIZE)
outque.tail = 0; // wrap around
OUTPUT( uart + TRANSMIT_HOLDING_REGISTER, c );
}
break;
#if 0 // not enabled
* case IIR_MODEM_STATUS_INTERRUPT :
* modem_status = INPUT( uart + MODEM_STATUS_REGISTER );
* break;
#endif
//
// line status
//
case IIR_LINE_STATUS_INTERRUPT :
line_status = INPUT( uart + LINE_STATUS_REGISTER );
if ( line_status & LSR_OVERRUN_ERROR )
++numOverrunError;
if ( line_status & LSR_PARITY_ERROR )
++numParityError;
if ( line_status & LSR_FRAMING_ERROR )
++numFramingError;
if ( line_status & LSR_BREAK_DETECT )
++numBreak;
break;
//
// done
//
default :
//I_ColorBlack (0,0,0);
OUTPUT( 0x20, 0x20 );
return;
}
}
}
//==========================================================================
/*
==============
=
= isr_16550
=
==============
*/
void interrupt isr_16550(void)
{
int c;
int count;
while (1)
{
switch( INPUT( uart + INTERRUPT_ID_REGISTER ) & 7 )
{
//
// receive
//
case IIR_RX_DATA_READY_INTERRUPT :
//I_ColorBlack (0,63,0);
++numRxInterrupts;
do
{
c = INPUT( uart + RECEIVE_BUFFER_REGISTER );
inque.data[inque.head++] = c;
inque.size++;
if (inque.head >= QUESIZE)
inque.head = 0; // wrap around
} while ( INPUT( uart + LINE_STATUS_REGISTER ) & LSR_DATA_READY );
break;
//
// transmit
//
case IIR_TX_HOLDING_REGISTER_INTERRUPT :
//I_ColorBlack (63,0,0);
++numTxInterrupts;
if (outque.size != 0)
{
count = 16;
do
{
c = outque.data[outque.tail++];
outque.size--;
if (outque.tail >= QUESIZE)
outque.tail = 0; // wrap around
OUTPUT( uart + TRANSMIT_HOLDING_REGISTER, c );
} while (--count && outque.size != 0);
}
break;
#if 0 // not enabled
* case IIR_MODEM_STATUS_INTERRUPT :
* modem_status = INPUT( uart + MODEM_STATUS_REGISTER );
* break;
#endif
//
// line status
//
case IIR_LINE_STATUS_INTERRUPT :
line_status = INPUT( uart + LINE_STATUS_REGISTER );
if ( line_status & LSR_OVERRUN_ERROR )
++numOverrunError;
if ( line_status & LSR_PARITY_ERROR )
++numParityError;
if ( line_status & LSR_FRAMING_ERROR )
++numFramingError;
if ( line_status & LSR_BREAK_DETECT )
++numBreak;
break;
//
// done
//
default :
//I_ColorBlack (0,0,0);
OUTPUT( 0x20, 0x20 );
return;
}
}
}
/*
===============
=
= jump_start
=
= Start up the transmition interrupts by sending the first char
===============
*/
void jump_start( void )
{
int c;
if (outque.size != 0)
{
c = outque.data [outque.tail++];
outque.size--;
if (outque.tail >= QUESIZE)
outque.tail = 0; // wrap around
OUTPUT( uart, c );
}
}