telegard/tmpcommm.pas

319 lines
7.8 KiB
ObjectPascal

{$A+,B+,E+,F+,I+,L+,N-,O-,R-,S+,V-}
unit tmpcom;
interface
uses crt,dos;
var
tmpcom_BIOS_port_table:array[1..2] of integer absolute $0040:0000;
const
I8088_IMR=$21;
tmpcom_buffer_max=5120;
type
tmpcom_portrec=
record
RTB, { receive / transmit buffers }
IER, { interrupt enable register }
IIR, { interrupt identification register }
LCR, { line control register }
MCR, { modem control register }
LSR, { line status register }
MSR:integer; { modem status register }
end;
var
tmpcom_saveoldvec:pointer;
tmpcom_ports:tmpcom_portrec;
tmpcom_base:integer;
tmpcom_irq,
tmpcom_port:byte;
tmpcom_open_flag:boolean;
tmpcom_buffer:array[0..tmpcom_buffer_max] of byte;
tmpcom_buffer_head,
tmpcom_buffer_tail,
tmpcom_buffer_used:integer;
tmpcom_outcharacter:char;
tmpcom_outgoingnow:boolean;
mpcoder:boolean;
mpcode:array[1..6] of byte;
procedure tmpcom_clear_errors;
procedure tmpcom_setdtr(b:boolean);
procedure tmpcom_closeport(ddtr:boolean);
procedure tmpcom_resetport(comport:byte; baudrate:longint; parity:char;
wordsize,stopbits:byte);
procedure tmpcom_openport(comport:byte; baudrate:longint; parity:char;
wordsize,stopbits:byte);
procedure tmpcom_initvars;
function tmpcom_receive(var c:char):boolean;
procedure tmpcom_sendno(c:char);
procedure tmpcom_send(c:char);
implementation
procedure tmpcom_clear_errors;
var i,j:integer;
begin
inline($FA); { cli }
{ disable baud rate bs... }
i:=port[tmpcom_ports.LCR] and $7F;
port[tmpcom_ports.LCR]:=i;
i:=port[tmpcom_ports.LSR]; { read LSR to reset errors }
i:=port[tmpcom_ports.RTB]; { read RTB in case it contains a chr }
{ enable the IRQ line (3/4) on the 8259 controller }
i:=((port[I8088_IMR]) and ((1 shl tmpcom_irq) xor $00FF));
port[I8088_IMR]:=i;
{ enable data-available interrupt --
transmit-register-empty interrupt is set by tmpcom_send(. }
port[tmpcom_ports.IER]:=$01;
{ enable OUT2, RTS, and DTR }
port[tmpcom_ports.MCR]:=$0B;
inline($FB); { sti }
end;
procedure tmpcom_setdtr(b:boolean);
var bb:byte;
begin
bb:=port[tmpcom_ports.MCR] and $FE;
if (b) then inc(bb);
port[tmpcom_ports.MCR]:=bb;
end;
procedure tmpcom_closeport(ddtr:boolean);
var i,j:integer;
begin
if (tmpcom_open_flag) then begin
inline($FA); { cli }
{ disable the IRQ line (3/4) on the 8259 controller }
i:=((port[I8088_IMR]) or (1 shl tmpcom_irq));
port[I8088_IMR]:=i;
{ disable data-available interrupt (along with all other interrupts) }
port[tmpcom_ports.IER]:=$00;
{ disable OUT2, and DTR if ddtr=TRUE }
i:=((port[tmpcom_ports.MCR]) and ($F7));
port[tmpcom_ports.MCR]:=i;
inline($FB); { sti }
{ reset interrupt vector to original setting }
setintvec(tmpcom_irq+8,tmpcom_saveoldvec);
tmpcom_open_flag:=FALSE;
end;
end;
function iii(i:integer):byte;
var j:integer;
begin
j:=tmpcom_buffer_tail-i;
if (j<0) then inc(j,tmpcom_buffer_max+1);
iii:=tmpcom_buffer[j];
end;
procedure checkmpcode;
var i:integer;
begin
inline($FA);
if ((iii(1)=254) and (iii(2)=253)) then
if ((iii(9)=1) and (iii(10)=2) and (iii(11)=1)) then begin
mpcoder:=TRUE;
for i:=1 to 6 do mpcode[7-i]:=iii(i+2);
tmpcom_buffer_head:=0;
tmpcom_buffer_tail:=tmpcom_buffer_head;
end;
inline($FB);
end;
procedure tmpcom_isr(flags,cs,ip,ax,bx,cx,dx,si,di,ds,es,bp:word); interrupt;
var dxx,i:integer;
bb:byte;
label iisr1,iisr2;
begin
inline($FB);
iisr1:
dxx:=port[tmpcom_ports.IIR];
if (dxx and $01<>$00) then goto iisr2;
case (dxx and $06) of
0:;
2:begin
if (tmpcom_outgoingnow) then begin
i:=port[tmpcom_ports.MSR];
port[tmpcom_ports.RTB]:=ord(tmpcom_outcharacter);
tmpcom_outgoingnow:=FALSE;
end;
port[tmpcom_ports.IER]:=port[tmpcom_ports.IER] and $FD;{ turn off TRE }
end;
4:begin
bb:=port[tmpcom_ports.RTB];
tmpcom_buffer[tmpcom_buffer_head]:=bb;
inc(tmpcom_buffer_head);
if (tmpcom_buffer_head>tmpcom_buffer_max) then
tmpcom_buffer_head:=0;
if (bb=255) then checkmpcode;
end;
6:;
end;
goto iisr1;
iisr2:
port[$20]:=$20;
end;
procedure tmpcom_resetport(comport:byte; baudrate:longint; parity:char;
wordsize,stopbits:byte);
const
tmpcom_num_bauds=10;
tmpcom_baud_table:
array[1..tmpcom_num_bauds] of record baud,bits:word; end
= ((baud:110; bits:$00), (baud:150; bits:$20),
(baud:300; bits:$40), (baud:600; bits:$60),
(baud:1200; bits:$80), (baud:2400; bits:$A0),
(baud:4800; bits:$C0), (baud:9600; bits:$E0),
(baud:19200; bits:$E0), (baud:38400; bits:$E0));
var regs:registers;
comparm,i:integer;
begin
tmpcom_buffer_head:=0;
tmpcom_buffer_tail:=0;
{ set up baud rate bits }
i:=0;
repeat inc(i)
until ((tmpcom_baud_table[i].baud=baudrate) or (i=tmpcom_num_bauds));
comparm:=tmpcom_baud_table[i].bits;
case upcase(parity) of
'E':comparm:=comparm or $18;
'O':comparm:=comparm or $08;
end;
if (wordsize=7) then comparm:=comparm or $02 else comparm:=comparm or $03;
if (stopbits=2) then comparm:=comparm or $04;
regs.ax:=comparm and $00FF;
regs.dx:=tmpcom_port-1; { comport }
intr($14,regs);
end;
procedure tmpcom_openport(comport:byte; baudrate:longint; parity:char;
wordsize,stopbits:byte);
begin
if (tmpcom_open_flag) then tmpcom_closeport(FALSE);
if ((comport=2) and (tmpcom_BIOS_port_table[2]<>0)) then begin
tmpcom_base:=$2f8;
tmpcom_port:=2; tmpcom_irq:=3;
end else begin
tmpcom_base:=$3f8;
tmpcom_port:=1; tmpcom_irq:=4;
end;
with tmpcom_ports do begin
RTB:=tmpcom_base;
IER:=tmpcom_base+$01;
IIR:=tmpcom_base+$02;
LCR:=tmpcom_base+$03;
MCR:=tmpcom_base+$04;
LSR:=tmpcom_base+$05;
MSR:=tmpcom_base+$06;
end;
(* { if the impossible has happened, get the heck outta here... }
if (port[tmpcom_ports.IIR] and $F8<>0) then exit;*)
tmpcom_resetport(comport,baudrate,parity,wordsize,stopbits);
getintvec(tmpcom_irq+8,tmpcom_saveoldvec);
setintvec(tmpcom_irq+8,@tmpcom_isr);
tmpcom_resetport(comport,baudrate,parity,wordsize,stopbits);
tmpcom_clear_errors;
tmpcom_open_flag:=TRUE;
end;
procedure tmpcom_initvars;
begin
tmpcom_base:=$3f8;
tmpcom_irq:=4;
tmpcom_port:=1;
tmpcom_open_flag:=FALSE;
tmpcom_buffer_head:=0;
tmpcom_buffer_tail:=0;
tmpcom_buffer_used:=0;
tmpcom_outcharacter:=#0;
tmpcom_outgoingnow:=FALSE;
end;
function tmpcom_receive(var c:char):boolean;
begin
c:=#0;
if (tmpcom_buffer_head<>tmpcom_buffer_tail) then begin
inline($FA);
c:=chr(tmpcom_buffer[tmpcom_buffer_tail]);
tmpcom_buffer_tail:=(tmpcom_buffer_tail+1) mod (tmpcom_buffer_max+1);
inline($FB);
tmpcom_receive:=TRUE;
end else
tmpcom_receive:=FALSE;
end;
procedure tmpcom_sendno(c:char);
var i:integer;
begin
i:=port[tmpcom_ports.MSR];
while (port[tmpcom_ports.LSR] and $20=0) do ;
port[tmpcom_ports.RTB]:=ord(c);
end;
procedure tmpcom_send(c:char);
var lng:longint;
i:integer;
begin
inline($FB);
lng:=0; while ((tmpcom_outgoingnow) and (lng<500000)) do inc(lng);
if (lng>=500000) then begin
inline($FA); tmpcom_outgoingnow:=FALSE;
{ tmpcom_clear_errors;}
inline($FA); delay(100); inline($FB);
end;
{ enable transmit-register-empty interrupt }
inline($FA);
tmpcom_outcharacter:=c;
tmpcom_outgoingnow:=TRUE;
i:=port[tmpcom_ports.IER];
if (i and $02<>$02) then begin
i:=i or $02;
port[tmpcom_ports.IER]:=i;
end;
inline($FB);
(* inline($FA);
tmpcom_obuffer[tmpcom_obuffer_tail]:=c;
tmpcom_obuffer_tail:=(tmpcom_obuffer_tail+1) mod (tmpcom_obuffer_max+1);
inline($FB);*)
end;
begin
mpcoder:=FALSE;
tmpcom_open_flag:=FALSE;
end.