unit Comtype;{constants for comport unit}
interface
const
{Parity:}
  pNone = 0;
  pOdd = 8;
  pEven = $18;

  MaxComSpeed = 115200;

{// Values for UART_set_bps_rate()}
  BPS_115200	        =   1;
  BPS_57600		=   2;
  BPS_38400		=   3;
  BPS_19200		=   6;
  BPS_9600		=  12;
  BPS_2400		=  48;
  BPS_1200		=  96;
  BPS_600		= 192;
  BPS_300		= 384;

{// Values for UART_set_line_params()  (can be combined with |)}
  LP_5BITS			= $00;
  LP_6BITS			= $01;
  LP_7BITS			= $02;
  LP_8BITS			= $03;

  LP_1STOP			= $00;
  LP_2STOP			= $04;

  LP_NO_PARITY		        = $00;
  LP_ODD_PARITY	                = $08;
  LP_EVEN_PARITY	        = $18;
  LP_MARK_PARITY	        = $28;
  LP_SPACE_PARITY	        = $38;

{// Values for base addresses}
  BASE_COM1			(*(unsigned far *)= $00400000;
  BASE_COM2			(*(unsigned far *)= $00400002;
  BASE_COM3			(*(unsigned far *)= $00400004;
  BASE_COM4			(*(unsigned far *)= $00400006;

{// Values for the RX FIFO triggerlevel}
  FIFO_1				= $00;
  FIFO_4				= $40;
  FIFO_8				= $80;
  FIFO_14			        = $C0;

{// Values for line status test}
  LS_DR				= $01	;{	// data ready}
  LS_OE				= $02	;{	// overrun error}
  LS_PE				= $04   ;{	// parity error}
  LS_FE				= $08	;{	// framing error}
  LS_BI				= $10	;{	// break indicator}
  LS_THRE			= $20	;{	// transmitter holding register empty}
  LS_TEMT			= $40	;{	// transmitter empty}
  LS_PENDING		        = $80	;{	// error pending in FIFO (16550+ only)}

{// Values for modem status test}
  MS_DELTA_CTS		        = $01;
  MS_DELTA_DSR		        = $02;
  MS_TERI			= $04;
  MS_DELTA_DCD		        = $08;
  MS_CTS			= $10;
  MS_DSR			= $20;
  MS_RI				= $40;
  MS_DCD			= $80;

{// Values for handshaking mode}
  HS_NONE			= $00;
  HS_RTSCTS			= $01;
  HS_XONXOFF		        = $02;

{// Values for errors}
  UE_OK					=  0;{		// OK}
  UE_ERROR				= -1;{		// unspecific error condition}
  UE_BAD_HANDLE		                = -2;{		// given handle has never been defined}
  UE_NO_HANDLES		                = -3;{		// no free handles left (too many ports)}
  UE_NO_FREE_MEMORY	                = -4;{		// not enough free memory for buffers }
  UE_BAD_INBUF_SIZE                     = -5;{		// illegal size given for inbuf      }
  UE_BAD_OUTBUF_SIZE	                = -6;{		// illegal size given for outbuf       }
  UE_BAD_HANDSHAKING	                = -7;{		// illegal handshaking mode specified   }
  UE_BAD_INTLEVEL		        = -8;{		// illegal interrupt level       }
  UE_TIMEOUT			        = -9;{		// any kind of timeout condition appeared}
  UE_BAD_FIFO			        = -10;{	// it's a 16550 (no A), FIFO not enabled          }
  UE_BAD_HANDLER		        = -11;{	// NULL pointer given for handler address}

  UE_USER_BREAK                         = -12;{user wants the port to stop}
{// Values for UART detection routine}
  UD_NONE				= -1;{		//   -1 if no UART is installed at the given base address}
  UD_8250				= 0; {		//    0 - 8250}
  UD_16450				= 1; {		//    1 - 16450}
  UD_16550_NOSCR		        = 2; {		//    2 - 16550 w/o SCR}
  UD_16550				= 3; {		//    3 - 16550}
  UD_16550A_NOSCR		        = 4; {		//    4 - 16550A w/o SCR}
  UD_16550A				= 5; {		//    5 - 16550A}


  CMD8259 = $20;

  {offsets to BaseAddr to acces registers:}
  regReceive = 0; regRBR = 0;{RBR, receive buffer reg., read/only (= r/o)}
  regTransmit = 0; regTHR = 0;{THR, transmit holding reg., w/o}
  regIntrEnable = 1; regIER = 1;{IER, Interrupt Enable reg., enables following events
                             to generate interrupt:}
    ieDataReady = 1; ieDR = 1;{DR, data are in receive buffer}
	ieTransmitRegEmpty = 2; ieTHRE = 2;{wants CPU to transmit something}
    ieStatus = 4;           {if error occurs}
    ieModemStatus = 8;      {if bit in MSR changes}
    {the rest bits if IER should be set to 0}
  regDivLatch = 0; regDL = 0; {Divisor Latch reg., accessed if DLAB in LCR is set,
                            can access as WORD}
  regIntrID = 2; regIIR = 2; {IIR, Interrupt identif. reg., r/o}
    {in the order of lowering priority:}
    iiUART = 1; {if this bit is 0, UART wants you to service the interrupt}

    iiLSR = 6; {LSR changed}
	iiDR = 4;  {Data ready, or FIFO trigger level reached - service by reading RBR}
	iiFIFO = 12; {something is already in FIFO, but nothing was recevied
				  for 4 words time - service by reading RBR}

	iiTHRE = 2; {already serviced by reading IIR}
	iiMSR = 0;  {MSR changed, read it}
	iiFIFOEnabled = $40;

  regFIFOCtrl = 2; regFCR = 2;{FCR, FIFO control registr, w/o}
	fcEnable = 1;
	fcClearReceive  = 2; {clear receiver buffer}
	fcClearTransmit = 4;
	fcDMA = 8;  {dma mode, not avail. in PC}
	{triger level set by bits 7 6:}
	fcTrig1 = 0;           {0 0, 1 char}
	fcTrig4 = $40;         {0 1, 4 chars}
	fcTrig8 = $80;         {1 0, 8 chars}
	fcTrig14 = $C0;        {1 1, 14 chars}

  regLineCtrl = 3; regLCR = 3;{LCR, Line control reg. r/w}
	lcDLAB = $80; DLAB = $80; {DLA access bit, controls what registers
							 at offs 0 and 1 are accessed}

  regModemCtrl = 4; regMCR = 4;{MCR, Modem control reg., r/w}
    mcDTR = 1; DTR = 1;{Data terminal ready}
    mcRTS = 2; RTS = 2;{Request to send}
    mcEnableMulti = 4;      {should be set, used by some multiport boards}
    mcEnable = 8;     {enable UART interrupts, should be set, otherwise
					  no CPU interrupts will be gen. by UART}
    mcLoop = $10;    {loopback testing mode, all outputs disabled}

  regLineStatus = 5; regLSR = 5;{LSR Line status register r/w}
   {for polling or status controling}
   {reset by reading RBR:}
   lsDR = 1; {data ready, something in rec. buffer}
   {reset by reading LSR:}
   lsOE = 2; OE = 2; {overrun, reset by reading LSR, indicates loss of data  }
   lsPE = 4; PE = 4; {parity error}
   lsFE = 8; FE = 8; {framing error, missing stop bit}
   lsBI = $10; BI = $10; {break indicator, break was sent}
   {reset by writing to transmit reg:}
   lsTHRE = $20;     {transmit holding reg. empty}
   {reset by reading LSR:}
   lsTEMT = $40;     {transmitter empty}
   lsFIFOError = $80; {only for 16550, if something is in fifo but received
                      with error}

  regModemStatus = 6; regMSR = 6; {modem status register}
    msDeltaCTS = 1;
    msDeltaDSR = 2;
    msRingHigh = 4; msRIHigh = 4;
    msDeltaDCD = 8;
    msCTS = $10;
    msDSR = $20;
    msRing = $40; msRI = $40;
    msDCD = $80;

  regScratch = 7; regSCR = 7;


{Port errors:}
  erEscPressed = 1; {escape pressed}
  erRBEmpty = 2; {no input data}
{UART id constants:
  //   -1 if no UART is installed
  //    0 - 8250
  //    1 - 16450
  //    2 - 16550 w/o SCR
  //    3 - 16550
  //    4 - 16550A w/o SCR
  //    5 - 16550A
}

  uNone = -1;
  u8250 = 0;
  u16450 = 1;
  u16550wos = 2;
  u16550 = 3;
  u16550Awos = 4;
  u16550A = 5;

{cpXXXX com properties, values are the numbers (not the flags),
  parity is 'N','O','E', 'M','S'}
  cpBPS = 1;
  cpDataBits = 2;
  cpStopBits = 3;
  cpParity = 4;
  cpBreak = 5;
type
  TComProperty = integer;
  PComPort = pointer;
{$IFNDEF WIN32}
function GetUARTType(BA:word):integer;
{$ENDIF}
implementation
{$IFNDEF WIN32}

function GetUARTType(BA:word):integer;
var x,scr,ov:byte;
begin
  GetUARTType := uNone;
  scr := 1;
{
   // This function returns:
  //   -1 if no UART is installed
  //    0 - 8250
  //    1 - 16450
  //    2 - 16550 w/o SCR
  //    3 - 16550
  //    4 - 16550A w/o SCR
  //    5 - 16550A
}

{  // First step: see if the LCR is there}
  ov := Port[BA + regLCR];
  Port[BA+regLCR] := $1B;
  if (Port[BA+regLCR] <> $1B ) then
    exit;
  Port[BA+regLCR] := $03;
  if( Port[BA+regLCR]<>$03 ) then
    exit;
  Port[BA + regLCR] := ov;
{  // Next thing to do is look for the scratch register}
  ov := Port[BA + regSCR];
  Port[BA + regSCR] := $55;
  if (Port[BA+regSCR] <> $55) then
    scr:=0;
  Port[BA+regSCR] := $AA;
  if (Port[BA+ regSCR] <> $AA) then
    scr:=0;
  Port[BA + regSCR] := ov;
{  // Then check if there's a FIFO}
  Port[BA + regFCR] := $01;
  x := Port[BA + regFCR];
  Port[BA+ regFCR] := $00; {// Some old-fashioned software relies on this!}
  if( (x and $80) = 0 ) then begin
    GetUARTType := scr;
    exit;
  end;
  if ((x and $40) = 0) then begin
    GetUARTType := 2+scr;
    exit;
  end;
  GetUARTType := 4+scr;
end;
{$ENDIF}
end.