Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

294 lines
6.1 KiB

#include "insignia.h"
#include "host_def.h"
/*
* SoftPC Revision 3.0
*
* Title : rs232_io.c
*
* Description : RS232 Asynchronous Adaptor BIOS functions.
*
* Notes : None
*
*/
#ifdef SCCSID
static char SccsID[]="@(#)rs232_io.c 1.7 08/03/93 Copyright Insignia Solutions Ltd.";
#endif
#ifdef SEGMENTATION
/*
* The following #include specifies the code segment into which this
* module will by placed by the MPW C compiler on the Mac II running
* MultiFinder.
*/
#include "SOFTPC_BIOS.seg"
#endif
/*
* O/S include files.
*/
#include <stdio.h>
#include TypesH
/*
* SoftPC include files
*/
#include "xt.h"
#include CpuH
#include "sas.h"
#include "ios.h"
#include "bios.h"
#include "trace.h"
#include "rs232.h"
#include "idetect.h"
static word divisors[] = { 1047,768, 384, 192, 96, 48, 24, 12, 6 };
/* workaround for IP32 and Tek43xx compiler bug follows: */
#if defined(IP32) || defined(TK43) || defined(macintosh)
static int port;
#else
static io_addr port;
#endif
static half_word value;
static void return_status()
{
inb(port + (io_addr) RS232_LSR, &value);
setAH(value);
inb(port + (io_addr) RS232_MSR, &value);
setAL(value);
}
void rs232_io()
{
#ifdef BIT_ORDER2
union {
half_word all;
struct {
HALF_WORD_BIT_FIELD word_length:2;
HALF_WORD_BIT_FIELD stop_bit:1;
HALF_WORD_BIT_FIELD parity:2;
HALF_WORD_BIT_FIELD baud_rate:3;
} bit;
} parameters;
#endif
#ifdef BIT_ORDER1
union {
half_word all;
struct {
HALF_WORD_BIT_FIELD baud_rate:3;
HALF_WORD_BIT_FIELD parity:2;
HALF_WORD_BIT_FIELD stop_bit:1;
HALF_WORD_BIT_FIELD word_length:2;
} bit;
} parameters;
#endif
DIVISOR_LATCH divisor_latch;
int j;
half_word timeout;
sys_addr timeout_location;
/* clear com/lpt idle flag */
IDLE_comlpt ();
setIF(1);
/*
* Which adapter?
*/
switch (getDX ())
{
case 0:
port = RS232_COM1_PORT_START;
timeout_location = RS232_COM1_TIMEOUT;
break;
case 1:
port = RS232_COM2_PORT_START;
timeout_location = RS232_COM2_TIMEOUT;
break;
case 2:
port = RS232_COM3_PORT_START;
timeout_location = RS232_COM3_TIMEOUT;
break;
case 3:
port = RS232_COM4_PORT_START;
timeout_location = RS232_COM4_TIMEOUT;
break;
default:
break;
}
/*
* Determine function
*/
switch (getAH ())
{
case 0:
/*
* Initialise the communication port
*/
value = 0x80; /* set DLAB */
outb(port + (io_addr) RS232_LCR, value);
/*
* Set baud rate
*/
parameters.all = getAL();
divisor_latch.all = divisors[parameters.bit.baud_rate];
outb(port + (io_addr) RS232_IER, divisor_latch.byte.MSByte);
outb(port + (io_addr) RS232_TX_RX, divisor_latch.byte.LSByte);
/*
* Set word length, stop bits and parity
*/
parameters.bit.baud_rate = 0;
outb(port + (io_addr) RS232_LCR, parameters.all);
/*
* Disable interrupts
*/
value = 0;
outb(port + (io_addr) RS232_IER, value);
return_status();
break;
case 1:
/*
* Send char over the comms line
*/
/*
* Set DTR and RTS
*/
outb(port + (io_addr) RS232_MCR, 3);
/*
* Real BIOS checks CTS and DSR - we know DSR ok.
* Real BIOS check THRE - we know it's ok.
* We only check CTS - this is supported on a few ports, eg. Macintosh.
*/
/*
* Wait for CTS to go high, or timeout
*/
sas_load(timeout_location, &timeout);
for ( j = 0; j < timeout; j++)
{
inb(port + (io_addr) RS232_MSR, &value);
if(value & 0x10)break; /* CTS High, all is well */
}
if(j < timeout)
{
outb(port + (io_addr) RS232_TX_RX, getAL()); /* Send byte */
inb(port + (io_addr) RS232_LSR, &value);
setAH(value); /* Return Line Status Reg in AH */
}
else
{
setAH(value | 0x80); /* Indicate time out */
}
break;
case 2:
/*
* Receive char over the comms line
*/
/*
* Set DTR
*/
value = 1;
outb(port + (io_addr) RS232_MCR, value);
/*
* Real BIOS checks DSR - we know it's ok.
*/
/*
* Wait for data to appear, or timeout(just an empirical guess)
*/
sas_load(timeout_location, &timeout);
for ( j = 0; j < timeout; j++)
{
inb(port + (io_addr) RS232_LSR, &value);
if ( (value & 1) == 1 )
{
/*
* Data ready go read it
*/
value &= 0x1e; /* keep error bits only */
setAH(value);
inb(port + (io_addr) RS232_TX_RX, &value);
setAL(value);
return;
}
}
/*
* Set timeout
*/
value |= 0x80;
setAH(value);
break;
case 3:
/*
* Return the communication port status
*/
return_status();
break;
case 4:
/*
* EXTENDED (PS/2) Initialise the communication port
*/
value = 0x80; /* set DLAB */
outb(port + (io_addr) RS232_LCR, value);
parameters.bit.word_length = getCH();
parameters.bit.stop_bit = getBL();
parameters.bit.parity = getBH();
parameters.bit.baud_rate = getCL();
/*
Set baud rate
*/
divisor_latch.all = divisors[parameters.bit.baud_rate];
outb(port + (io_addr) RS232_IER, divisor_latch.byte.MSByte);
outb(port + (io_addr) RS232_TX_RX, divisor_latch.byte.LSByte);
/*
* Set word length, stop bits and parity
*/
parameters.bit.baud_rate = 0;
outb(port + (io_addr) RS232_LCR, parameters.all);
/*
* Disable interrupts
*/
value = 0;
outb(port + (io_addr) RS232_IER, value);
return_status();
break;
case 5: /* EXTENDED Comms Port Control */
switch( getAL() )
{
case 0: /* Read modem control register */
inb( port + (io_addr) RS232_MCR, &value);
setBL(value);
break;
case 1: /* Write modem control register */
outb( port + (io_addr) RS232_MCR, getBL());
break;
}
/*
Return the communication port status
*/
return_status();
break;
default:
/*
** Yes both XT and AT BIOS's really do this.
*/
setAH( getAH()-3 );
break;
}
}