{ I am using a PCCOM 4-port serial card and this unit works with a small test program but when I use it in a larger program (executable approx 48k) I only get some of the characters from the port. The serial card is 16450 based with vector at $02BF.. I have done very little interrupt programming so I don't know if that is the problem. Thanks........ } unit mycom; interface procedure Async_ISR; interrupt; procedure XmitChar(Serial_IOPort:byte;C: char); { Uses variable and constant declarations from} function RemoteReadKey(Serial_IOPort:byte): char; { Uses var and const from above } function RemoteKeyPressed(Serial_IOPort:byte):boolean; { Uses vars and consts from above } procedure InitPort(Serial_IOPort:byte); procedure InitInter; procedure TerminateInter; function COM_BufSize (Serial_IOPort:byte):byte; implementation USES DOS,crt; var COM_mask:byte; COM_Buffer: array [0..3] of array[0 .. 129] of char; { A buffer for input} COM_Temp, { Varible to hold various modem statuses } COM_CommPort: byte; { Comm Port in use } COM_Head : array [0..3] of byte; { Size of the buffer } OldInt0Dh :pointer; OldPIC:byte; const COM_IRQ_Number = $07; COM_IRQ_Vector = $0F; const BaseAddr: array[0 .. 3] of word = ($02A0, $02A8, $02B0, $02B8); Baud=38400; { Speed required } Divisor:word = 115200 div Baud; { or 1843200 / (16 * Baud) } { ^ UART clock speed } procedure Async_ISR; CONST Buf_Pnt:POINTER=@COM_Buffer; begin { WRITE('*'); } asm STI { STI - Disable interrupts } PUSHA PUSH SS MOV CL,00 { Com Port Counter 0 - 3 => COM5 - COM8} @NextVector: MOV DX, 02BFh { WHO WANTED AN INTERRUPT ? } MOV BL,01 SHL BL,CL IN AL,DX TEST AL,BL JNZ @CheckNextVector MOV DX, 02A0h { BASE OF FIRST PORT } MOV AL,08 MUL CL ADD DX,AX { GOT BASE ADDRESS IN DX } @GoBackForMore: ADD DX,02h IN AL,DX { CHECK INTERRUPT ID REGISTER } SUB DX,02h TEST AL,01h { NO IRQ PENDING } JNZ @CheckNextVector AND AL,06h CMP AL,04h { DID WE RECEIVE A CHARACTER } JNZ @CheckMore { NO ? THEN WHAT ELSE } IN AL,DX { READ INPUT FROM PORT } MOV BH,AL { PUT DATA IN BH FOR LATER } LDS SI,Buf_Pnt LES DI,Buf_Pnt MOV AL,130 { SIZE OF BUFFER + 2 for size & tail pointer } MUL CL ADD SI,AX ADD DI,AX { FOUND BUFFER[COM_PORT] } LODSB CMP AL,127 { IF BUFFER FULL IGNORE CHARACTER } JA @CheckForAnotherIRQ INC AL { INC SIZE IF ROOM } STOSB { WRITE BACK TO SIZE COUNTER } LODSB { tail pointer } MOV BL,AL { PUT TAIL POINTER IN BL } INC AL CMP AL,128 JB @WriteTail MOV AL,0 @WriteTail: STOSB MOV AL,BH { GET BACK DATA FROM BH } MOV BH,0 ADD DI,BX { ADD CONTENTS OF TAIL POINTER TO POINTER } STOSB { WRITE DATA TO BUFFER } JMP @CheckForAnotherIRQ @CheckMore: CMP AH,02h { THD EMPTY } JNZ @CheckMore2 { FOR LATER ADDITION OF INTERRUPT SEND ROUTINE } JMP @CheckForAnotherIRQ @CheckMore2: CMP AH,06h { ERROR OR BREAK } JNZ @CheckForAnotherIRQ IN AL,DX { READ FROM PORT TO CLEAR OVERRUNS } ADD DX,05h IN AL,DX { READ LINE STATUS REGISTER } SUB DX,05h @CheckForAnotherIRQ: JMP @GoBackForMore { ANOTHER INTERRUPT ON THIS PORT } @CheckNextVector: INC CL CMP CL,04h JNZ @NextVector MOV DX,0020h MOV AL,20h OUT DX,AL { RESET PIC } POP SS POPA CLI { CLI - Enable interrupts } end; end; procedure XmitChar(Serial_IOPort:byte;C: char); { Uses variable and constant declarations from} begin { the previous example } repeat { write ('.');} until (port[BaseAddr[Serial_IOPort] + $05] and $20 = $20); { Wait for THR } port[BaseAddr[Serial_IOPort]] := Ord(C); { Send character } { textcolor(red); write(ord(c)); write('.'); textcolor(lightgray);} end; function RemoteReadKey(Serial_IOPort:byte): char; { Uses var and const from above } begin if ord(COM_Buffer[Serial_IOPort][0]) > 0 then begin RemoteReadKey := COM_Buffer[Serial_IOPort][COM_Head[Serial_IOPort]+2]; {Get the character } inc(COM_Head[Serial_IOPort]); { Move Head to the nextcharacter } if COM_Head[Serial_IOPort] > 127 then COM_Head[Serial_IOPort] := 0; { Wrap Head around if necessary } dec(COM_Buffer[Serial_IOPort][0]); {Remove the character } end else RemoteReadKey:=chr(0); end; function RemoteKeyPressed(Serial_IOPort:byte): boolean; { Uses vars and consts from above } begin RemoteKeyPressed := ord(COM_Buffer[Serial_IOPort][0]) > 0; { A key was pressed if there is data in} end; { the buffer } procedure InitPort(Serial_IOPort:byte); var COM_tt:byte; begin inline($FB); { STI - Disable interrupts } Port[BaseAddr[Serial_IOPort]+$03]:=Port[BaseAddr[Serial_IOPort]+$03] or 128; { Ready to set Port speed } Port[BaseAddr[Serial_IOPort]]:= Lo(Divisor); Port[BaseAddr[Serial_IOPort]+$01]:= Hi(Divisor); { Set Speed to 38400 } Port[BaseAddr[Serial_IOPort]+$03]:= $03 or $08 or $00; { end set port speed and set 8 - O - 1 } Port[BaseAddr[Serial_IOPort]+$01]:= $01; { set Interrupt enable on Rx Data } COM_tt:=Port[BaseAddr[Serial_IOPort]]; COM_tt:=Port[BaseAddr[Serial_IOPort]+1]; COM_tt:=Port[BaseAddr[Serial_IOPort]+2]; COM_tt:=Port[BaseAddr[Serial_IOPort]+3]; COM_tt:=Port[BaseAddr[Serial_IOPort]+4]; COM_tt:=Port[BaseAddr[Serial_IOPort]+5]; COM_tt:=Port[BaseAddr[Serial_IOPort]+6]; Port[BaseAddr[Serial_IOPort]]:=0; COM_Head[Serial_IOPort]:=0; COM_Buffer[Serial_IOPort][1]:=CHR(0); { tail } COM_Buffer[Serial_IOPort][0]:=chr(0); { size } inline($FA); { CLI - Enable interrupts } end; procedure InitInter; begin InitPort (0); InitPort (1); InitPort (2); InitPort (3); Port[$02BF]:=$ff; GetIntVec(COM_IRQ_vector, OldInt0Dh); SetIntVec(COM_IRQ_vector, @Async_ISR); COM_mask := (1 shl (COM_IRQ_number)) xor $00FF; OldPic:=Port[$21]; Port[$21] := OldPIC and COM_mask; end; procedure TerminateInter; var Serial_IOPort,com_tt:byte; begin { COM_mask := 1 shl (COM_IRQ_number);} SetIntVec(COM_IRQ_vector, OldInt0Dh); for Serial_IOPort := 0 to 3 do begin { set Interrupt enable off } COM_tt:=Port[BaseAddr[Serial_IOPort]]; COM_tt:=Port[BaseAddr[Serial_IOPort]+1]; COM_tt:=Port[BaseAddr[Serial_IOPort]+2]; COM_tt:=Port[BaseAddr[Serial_IOPort]+3]; COM_tt:=Port[BaseAddr[Serial_IOPort]+4]; COM_tt:=Port[BaseAddr[Serial_IOPort]+5]; COM_tt:=Port[BaseAddr[Serial_IOPort]+6]; Port[BaseAddr[Serial_IOPort]]:=0; Port[BaseAddr[Serial_IOPort]+$01]:= $00; Port[$21] := Port[$21] and OldPIC; end; END; function COM_BufSize (Serial_IOPort:byte):byte; begin COM_BufSize:=ord(COM_Buffer[Serial_IOPort][0]); end; end. Com_Buffer Structure: Byte 0 - number of characters in buffer Byte 1 - tail ponter in buffer 2-129 - 128 bytes (the buffer)