217 lines
7.7 KiB
NASM
217 lines
7.7 KiB
NASM
|
;**
|
||
|
;** bimo.asm:
|
||
|
;** Interrupt handlers for real- and protected-mode INT 0xC, or 0x0B
|
||
|
;** if the -2 command-line option is used. See the bimodal.c example
|
||
|
;** program for details.
|
||
|
;**
|
||
|
|
||
|
.286
|
||
|
|
||
|
_TEXT16 SEGMENT BYTE PUBLIC 'CODE'
|
||
|
ASSUME cs:_TEXT16
|
||
|
|
||
|
;**
|
||
|
;** The real-mode interrupt handler is in a 16-bit code segment
|
||
|
;** so that the assembler will generate the right code.
|
||
|
;**
|
||
|
;** We will copy this code to a 16-bit segment in low memory
|
||
|
;** and install it as a real mode interrupt handler before it
|
||
|
;** gets executed. (There's no distinction between code and
|
||
|
;** data in real mode.)
|
||
|
;**
|
||
|
;** Since the handler doesn't get executed before it gets copied,
|
||
|
;** putting it in this segment makes the C code simpler.
|
||
|
;**
|
||
|
;** The buffer into which we will store the data being sent
|
||
|
;** to us is also in this segment, for simplicity. (It's
|
||
|
;** possible to read and write code segments in real mode.)
|
||
|
;** We will lay out this segment using fixed offsets, so that
|
||
|
;** we can omit the data in the executable file. The symbolic
|
||
|
;** offsets are only used to reference the segment BEFORE
|
||
|
;** it has been copied low.
|
||
|
;**
|
||
|
;** Both the real mode and protected mode handlers will store
|
||
|
;** their data in this same buffer (that is, in the copy in
|
||
|
;** low memory).
|
||
|
;**
|
||
|
;** OFFSET LENGTH CONTENTS
|
||
|
;**
|
||
|
;** 0 <128 Real mode interrupt handler
|
||
|
;** 128 4 Next available slot in buffer
|
||
|
;** 132 1024 Data receive buffer
|
||
|
;** 132+1024 1 Overflow indicator
|
||
|
;**
|
||
|
|
||
|
maxbuf EQU 1024
|
||
|
|
||
|
PUBLIC rmhandler_, _com_port_low
|
||
|
rmhandler_:
|
||
|
push ds
|
||
|
push bx
|
||
|
mov bx, 0B800h
|
||
|
mov ds, bx ; DS = 0xB800
|
||
|
sub bx, bx ; BX = 0
|
||
|
mov WORD PTR [bx], 0720h ; Clear 2 character cells
|
||
|
mov WORD PTR [bx+2], 0720h
|
||
|
|
||
|
push cx
|
||
|
push ax
|
||
|
mov cx, 10h
|
||
|
rmdelay:
|
||
|
mov ax, 1
|
||
|
mul cl
|
||
|
loop rmdelay ; RM delay loop (flicker makes
|
||
|
pop ax ; screen effects understandable)
|
||
|
pop cx
|
||
|
|
||
|
mov BYTE PTR [bx],'R' ; Write 'R' to memory map
|
||
|
|
||
|
db 0BBh ; mov bx,...
|
||
|
_com_port_low DW ? ; com port base address
|
||
|
push ax
|
||
|
push dx
|
||
|
lea dx, [bx+2] ; int id register
|
||
|
in al, dx ; Read ports so interrupts
|
||
|
mov dx, bx ; can continue to be
|
||
|
in al, dx ; generated; get data in AL
|
||
|
|
||
|
mov bx, cs:[128] ; get buffer index
|
||
|
mov cs:[132+bx], al ; store data
|
||
|
inc bx ; increment count, which
|
||
|
cmp bx, maxbuf+1 ; can overflow by one,
|
||
|
jl no_ov1 ; resetting it to zero
|
||
|
sub bx, bx ; on an overflow so we
|
||
|
no_ov1: ; don't clobber memory --
|
||
|
mov cs:[128], bx ; and store new value
|
||
|
|
||
|
mov dx,020h
|
||
|
mov al,dl
|
||
|
out dx,al ; Send EOI
|
||
|
pop dx
|
||
|
pop ax
|
||
|
pop bx
|
||
|
pop ds
|
||
|
iret
|
||
|
ASSUME cs:NOTHING
|
||
|
|
||
|
; These variables only exist in the real mode copy of this segment
|
||
|
; (the one which actually gets executed)
|
||
|
;
|
||
|
; ORG 128
|
||
|
;next DD 0
|
||
|
;databuf DB maxbuf dup(0)
|
||
|
;overflow DB 0
|
||
|
|
||
|
_TEXT16 ENDS
|
||
|
|
||
|
.386p
|
||
|
|
||
|
_DATA SEGMENT DWORD PUBLIC 'DATA'
|
||
|
EXTRN _com_port:WORD
|
||
|
EXTRN _com_id:BYTE
|
||
|
EXTRN _lowmem_seg:WORD
|
||
|
EXTRN _pm_count:DWORD
|
||
|
_DATA ENDS
|
||
|
|
||
|
_TEXT SEGMENT BYTE PUBLIC 'CODE'
|
||
|
ASSUME cs:_TEXT, ds:_DATA
|
||
|
|
||
|
PUBLIC com_init_
|
||
|
com_init_:
|
||
|
mov ax,0F3h ; 9600,n,8,1
|
||
|
mov dl,[_com_id]
|
||
|
sub dh,dh
|
||
|
dec dx ; 0 = COM1, 1 = COM2
|
||
|
int 14h ; Initialize device
|
||
|
mov bx,[_com_port] ; Base of port space
|
||
|
lea dx,[bx+5] ; line status register
|
||
|
in al,dx
|
||
|
lea dx,[bx+4] ; modem control register
|
||
|
in al,dx
|
||
|
or al,8 ; enable OUT2 interrupt
|
||
|
out dx,al
|
||
|
lea dx,[bx+2] ; int id register
|
||
|
in al,dx
|
||
|
mov dx,bx ; data receive register
|
||
|
in al,dx
|
||
|
mov dl,NOT 10h ; mask for IRQ4
|
||
|
cmp [_com_id],1
|
||
|
je maskit
|
||
|
mov dl,NOT 8h ; mask for IRQ3
|
||
|
maskit:
|
||
|
in al,21h ; interrupt mask register
|
||
|
and al,dl ; force IRQ unmasked
|
||
|
out 21h,al
|
||
|
lea dx,[bx+1] ; int enable register
|
||
|
mov al,1
|
||
|
out dx,al ; enable received-data int
|
||
|
ret
|
||
|
|
||
|
ASSUME ds:NOTHING
|
||
|
|
||
|
;**
|
||
|
;** The protected-mode interrupt handler is in a 32-bit code
|
||
|
;** segment. Even so, we have to be sure to force an IRETD
|
||
|
;** at the end of the handler, because MASM doesn't generate
|
||
|
;** one. This handler will be called on a 32-bit stack by
|
||
|
;** DOS/4GW.
|
||
|
;**
|
||
|
|
||
|
PUBLIC pmhandler_
|
||
|
pmhandler_:
|
||
|
push ds
|
||
|
push ebx
|
||
|
mov bx,_DATA
|
||
|
mov ds,bx
|
||
|
|
||
|
ASSUME ds:_DATA
|
||
|
|
||
|
mov ebx,0B8000h ; DS:EBX = flat:0B8000h
|
||
|
mov DWORD PTR [ebx],07200720h ; Clear 2 character cells
|
||
|
|
||
|
push eax
|
||
|
push ecx
|
||
|
mov ecx, 10h
|
||
|
pmdelay:
|
||
|
mov ax, 1
|
||
|
mul cl
|
||
|
loop pmdelay ; PM delay loop (for clarity
|
||
|
pop ecx ; of display only)
|
||
|
|
||
|
mov BYTE PTR [ebx+2],'P' ; Write 'P' to memory map
|
||
|
|
||
|
push edx
|
||
|
mov bx,[_com_port]
|
||
|
lea dx,[bx+2]
|
||
|
in al,dx ; Read ports so interrupts
|
||
|
mov dx,bx ; can continue to be
|
||
|
in al,dx ; generated
|
||
|
|
||
|
inc [_pm_count] ; Count interrupts handled in PM
|
||
|
mov bx, [_lowmem_seg]
|
||
|
mov ds, bx ; Get DS addressability to buffer
|
||
|
|
||
|
ASSUME ds:NOTHING
|
||
|
|
||
|
mov ebx, ds:[128] ; get buffer index
|
||
|
mov ds:[132+ebx], al ; store data
|
||
|
inc ebx ; increment count, which
|
||
|
cmp ebx, maxbuf+1 ; can overflow by one,
|
||
|
jl no_ov2 ; resetting it to zero
|
||
|
sub ebx, ebx ; on an overflow so we
|
||
|
no_ov2: ; don't clobber memory --
|
||
|
mov ds:[128], ebx ; and store new value
|
||
|
|
||
|
mov dx,020h
|
||
|
mov al,dl
|
||
|
out dx,al ; Send EOI
|
||
|
pop edx
|
||
|
pop eax
|
||
|
pop ebx
|
||
|
pop ds
|
||
|
iretd
|
||
|
|
||
|
_TEXT ENDS
|
||
|
|
||
|
END
|