;
; 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1987,1988
; LICENSED MATERIALS - PROPERTY OF IBM
; REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
;
;
; $Header:as.asm 12.0$
; $ACIS:as.asm 12.0$
;
;***********************************************
;
;    Assembler routines for use by the PC Code 
;
;

        TITLE   AS.ASM
        .286c

DEBUG  EQU  1
RBDOS  EQU  1
RB     EQU  0

STACKSIZE EQU 200
LARGESTACK EQU 400
ABIOSSIZE EQU 2200

INCLUDE ASMROUTS.EQU


_TEXT   SEGMENT  BYTE PUBLIC 'CODE'
_TEXT   ENDS

_DATA   SEGMENT WORD PUBLIC 'DATA'
_DATA   ENDS

CONST   SEGMENT  WORD PUBLIC 'CONST'
CONST   ENDS

STACK   SEGMENT  WORD PUBLIC 'STACK'
	db	4048 DUP (0)
STACK   ENDS


_BSS    SEGMENT  WORD PUBLIC 'BSS'
_BSS    ENDS

DGROUP  GROUP   CONST,  _BSS,   _DATA
        ASSUME  CS: _TEXT, DS: DGROUP, SS: DGROUP, ES: DGROUP

_DATA   SEGMENT
        extrn   _cbcbptr:dword         ; Far pointer to cbcb
        extrn   _msstatus:word         ; Status Byte in mouse.c
        extrn   _msx:word              ; X data
        extrn   _msy:word              ; Y data
        extrn   _biosint15seg:word     ; Segment of BIOS int 15 function
        extrn   _biosint15off:word     ; Offset
        extrn   _biosint1cseg:word     ; Segment of BIOS int 1c function
        extrn   _biosint1coff:word     ; Offset (system clock 0x1c)
        extrn   _ubcode_addr:dword     ; Seg & Off of UB FCI code
_DATA   ENDS

_DATA   SEGMENT
         ORG $+LARGESTACK
kbsp     dw     0
         dw     0                       ; Save old stack during interrupt
         dw     0
         ORG $+LARGESTACK
mssp     dw     0
         dw     0                       ; Save old stack during interrupt
         dw     0
         ORG $+LARGESTACK
syssp    dw     0
         dw     0                       ; Save old stack during interrupt
         dw     0
         ORG $+ABIOSSIZE
hdirqsp  dw     0
         dw     0                       ; Save old stack during interrupt
         dw     0
         ORG $+ABIOSSIZE
fdirqsp  dw     0
         dw     0                       ; Save old stack during interrupt
         dw     0
         ORG $+STACKSIZE
irq1sp   dw     0
         dw     0                       ; Save old stack during interrupt
         dw     0
         ORG $+STACKSIZE
irq2sp   dw     0
         dw     0                       ; Save old stack during interrupt
         dw     0
         ORG $+STACKSIZE
irq3sp   dw     0
         dw     0                       ; Save old stack during interrupt
         dw     0
         ORG $+STACKSIZE
irq4sp   dw     0
         dw     0                       ; Save old stack during interrupt
         dw     0
         ORG $+STACKSIZE
irq5sp   dw     0
         dw     0                       ; Save old stack during interrupt
         dw     0
         ORG $+STACKSIZE
irq6sp   dw     0
         dw     0                       ; Save old stack during interrupt
         dw     0
         ORG $+STACKSIZE
irq7sp   dw     0
         dw     0                       ; Save old stack during interrupt
         dw     0
         ORG $+STACKSIZE
irq8sp   dw     0
         dw     0                       ; Save old stack during interrupt
         dw     0
         ORG $+STACKSIZE
irq9sp   dw     0
         dw     0                       ; Save old stack during interrupt
         dw     0
         ORG $+STACKSIZE
irq10sp  dw     0
         dw     0                       ; Save old stack during interrupt
         dw     0
         ORG $+STACKSIZE
irq11sp  dw     0
         dw     0                       ; Save old stack during interrupt
         dw     0
         ORG $+STACKSIZE
irq12sp  dw     0
         dw     0                       ; Save old stack during interrupt
         dw     0
         ORG $+STACKSIZE
irq13sp  dw     0
         dw     0                       ; Save old stack during interrupt
         dw     0
         ORG $+STACKSIZE
irq14sp  dw     0
         dw     0                       ; Save old stack during interrupt
         dw     0
         ORG $+STACKSIZE
irq15sp  dw     0
         dw     0                       ; Save old stack during interrupt
         dw     0
membuf   dw     0
bxsave   dw     0
axsave   dw     0
; int 26 disk packet for dos 4.0
DISK_PACKET	LABEL	BYTE
RBA	dw	0
RBA2	dw	0
COUNT	dw	0
ADDR	dw	0
ADDR2	dw	0
_DATA    ENDS



FUNCTION MACRO   FUNCT
FUNCT    PROC    NEAR
         ENDM

IFSTRAY MACRO   STRAYEXIT
        mov     DX,MAST_8259
        mov     AL,0BH
        out     DX,AL
        jmp     SHORT $+2
        nop
        in      AL,DX
        or      AL,AL
        jz      STRAYEXIT
        ENDM

CHANGESTK MACRO  NEWSP
        pushf
        cli
        push    DGROUP                 ; Address our Data
        pop     DS
        mov     bxsave, BX
        mov     axsave, AX
        lea     BX, NEWSP              ; Get address of new SP
        mov     [BX+2], SP             ; Save the old SP and SS at the top
        mov     AX, SS
        mov     [BX+4], AX
        mov     AX, DS
        mov     SS, AX                 ; Set up interrupt stack
        mov     SP, BX
        mov     BX, bxsave
        mov     AX, axsave
        popf
        ENDM

RESTORESTK MACRO  NEWSP
        pushf
        cli
        lea     BX, NEWSP         ; Restore callers stack
        mov     SP, [BX+2]
        mov     AX, [BX+4]
        mov     SS, AX
        popf
        ENDM



ROMPLVL3 MACRO  IRQPOLL
        xor     AX, AX
        push    AX		  ; push cbcb (zero)
        push    AX		  ; push quereq
        mov     AX, 0ffh          ; Tell _rompint3 it is being called from
        push    AX                ; interrupt level.
        mov     AL, IRQPOLL       ; This is the interrupt level
        push    AX
        mov     AX, 3             ; from lvl 3
        push    AX                ; interrupt level.
        call    _rompint3
        add     sp, 10		  ; 5 words of args
        ENDM


ROMPLVL4 MACRO  IRQPOLL
        xor     AX, AX
        push    AX		  ; push cbcb (zero)
        mov     AX, 0ffh          ; 
        push    AX		  ; push quereq
        push    AX                ; called from interrupt level.
        mov     AL, IRQPOLL       ; This is the interrupt level
        push    AX
        mov     AX, 4             ; from lvl 4
        push    AX                ; interrupt level.
        call    _rompint4
        add     sp, 10		  ; 5 words of args
        ENDM

LOADALL MACRO
	db	0fh,05h 	   ; loadall instruction
	ENDM

SMSW	MACRO	P1
       IFIDN	<&P1>,<AX>
	DB	00FH,001H,0E0H
       ELSE
	DB	00FH
L1	LABEL	BYTE
	SHL	&P1,1
L2	LABEL	BYTE
	ORG	OFFSET CS:L1
	DB	001H
	ORG	OFFSET CS:L2
       ENDIF
	ENDM


PARAM1  EQU 4                      ; Small model
PARAM2  EQU   PARAM1 + 2
PARAM3  EQU   PARAM1 + 4
PARAM4  EQU   PARAM1 + 6
PARAM5  EQU   PARAM1 + 8
PARAM6  EQU   PARAM1 + 10
PARAM7  EQU   PARAM1 + 12
PARAM8  EQU   PARAM1 + 14
PARAM9  EQU   PARAM1 + 16
portk	equ   92h
a20bit	equ   02h



_TEXT   SEGMENT

        extrn   _cbcbreq:near
        extrn   _sysclock:near
        extrn   _rompint3:near
        extrn   _rompint4:near
        extrn   _kbintr:near
	extrn	_kbd_int:near
        extrn   _mouseint:near
	extrn	_hdint:near
	extrn	_fdint:near
	extrn	_asy3:near
	extrn	_asy4:near


        PUBLIC  _blockmove,_extmem
        PUBLIC  _spl,_splx
        PUBLIC  _exchw,_exchl

        PUBLIC  _i_trap
        PUBLIC  _i_ign
        PUBLIC  _i_nmi
        PUBLIC  _i_d0

        PUBLIC  _msint
        PUBLIC  _kbd_intercept
	PUBLIC	_sysirq
	PUBLIC	_hdirq
	PUBLIC	_fdirq
        PUBLIC  _irq1
        PUBLIC  _irq2
        PUBLIC  _irq3
        PUBLIC  _irq4
	PUBLIC	_irq3asy
	PUBLIC	_irq4asy
        PUBLIC  _irq5
        PUBLIC  _irq6
        PUBLIC  _irq7
        PUBLIC  _irq8
        PUBLIC  _irq9
        PUBLIC  _irq10
        PUBLIC  _irq11
        PUBLIC  _irq12
        PUBLIC  _irq13
        PUBLIC  _irq14
        PUBLIC  _irq15
        PUBLIC  _rreboot
        PUBLIC  _int13
	PUBLIC	_int26
	PUBLIC	_rbputc
	PUBLIC	_rblpchar
        public  _int10
        public  _rbgetchar
        public  _eoi_master
        public  _eoi_slave
        public  _sti
        public  _cli
        public  _fci
        public  _wait
	PUBLIC  _loadall
	PUBLIC  _getss
	PUBLIC  _getcs
	public	_bldspt
	public	_bldsit
	public	_initfft
	public  _outpw

FUNCTION _outpw
        push BP
        mov  BP,SP
        push DX

        mov  DX,[BP+PARAM1]             ; Get port
        mov  AX,[BP+PARAM2]             ; Get value
	out  DX,AX

	pop  DX
	pop  BP
	ret
_outpw	endp

FUNCTION _sti
         sti
         ret
_sti     ENDP

FUNCTION _cli
         cli
         ret
_cli     ENDP

FUNCTION _spl
        pushf                         ; Get the flags reg
        pop     AX                    ; into AX

        and     AX, 0200H             ; Interrupt flag only
        cli                           ; Turn off processor interrupts
        ret                           ; AX is returned to caller
_spl  ENDP

FUNCTION _wait
        sti
        wait
_wait ENDP

FUNCTION _splx

        push BP
        mov  BP,SP
        push BX

        mov  AX,[BP+PARAM1]             ; Get the paramater


        and  AX, 0200H                  ; remove any bad bits
        pushf                           ; get the current flag
        pop  BX                         ; into BX
        or   AX, BX                     ; Add our flag to it
        push AX                         ; and set the new state
        popf                            ;

        pop  BX
        mov  SP,BP
        pop  BP
        RET

_splx   ENDP


FUNCTION _rreboot
         INT    19H                     ; do a bios reboot
_rreboot ENDP

;*********************************************************
; blockmove(gdt, length) - Do a BIOS block move function
; struct DESC gdt;       Address of descriptor table
; short  len;            Number of 16-bit words to move
;
;
;

FUNCTION _blockmove
           push BP
           mov  BP,SP
           push ES
           push SI
           push CX

           mov  SI,[BP+PARAM1]    ; Offset of struct DESC
           mov  AX,[BP+PARAM2]    ; Segment of struct DESC
           mov  ES,AX
           mov  CX,[BP+PARAM3]    ; len
           mov  AH,87H            ; Block Move BIOS function
           INT  15H               ; Call BIOS
           mov  AL,AH
           mov  AH,0
           jnc  nocarry
           mov  ah,80h
nocarry:
           pop  CX
           pop  SI
           pop  ES
           mov  SP,BP
           pop  BP
           ret
_blockmove ENDP

;********************************************************
; The following 3 routines are to start abios 
;                    initalization
; bldspt(pointer)	build system paramter table
;  char far * pointer;
; bldsit(pointer) 	build system init table
;  char far * pointer;
; initfft(init_routine,anchor_seg,logical,count)
;	int	(*init_routine)();
;	short	anchor_seg;
;	short	logical,count;
;*********************************************************
FUNCTION _bldspt
	push	BP
	mov	BP,SP
	push	ES
	push	DI
	push	DS

	mov	DI,[BP+PARAM1]	; FP_OFF(pointer)
	mov	AX,[BP+PARAM2]  ; FP_SEG(pointer)
	mov	ES,AX
	xor	AX,AX		; Set RAM extension to 0
	mov	DS,AX		;  (for now..)
	mov	AH,04H		; build system paramter table
	int	15H		; call bios
	
	mov  AL,AH
	mov  AH,0
	jnc  nocarr1
	mov  ah,80h
nocarr1:
	pop	DS
	pop	DI
	pop	ES
	mov	SP,BP
	pop	BP
	ret
_bldspt	ENDP

FUNCTION _bldsit
	push	BP
	mov	BP,SP
	push	ES
	push	DI
	push	DS

	mov	DI,[BP+PARAM1]	; FP_OFF(pointer)
	mov	AX,[BP+PARAM2]  ; FP_SEG(pointer)
	mov	ES,AX
	xor	AX,AX		; Set RAM extension to 0
	mov	DS,AX		;  (for now..)
	mov	AH,05H		; build system init table
	int	15H		; call bios
	
	mov  AL,AH
	mov  AH,0
	jnc  nocarr2
	mov  ah,80h
nocarr2:
	pop	DS
	pop	DI
	pop	ES
	mov	SP,BP
	pop	BP
	ret
_bldsit	ENDP

FUNCTION _initfft
	push	BP
	mov	BP,SP
	push	CX
	push	DX
	push	DS

	mov	AX,[BP+PARAM3]	; Anchor segment
	mov	DS,AX
	mov	DX,[BP+PARAM4]	; starting logical device
	mov	CX,[BP+PARAM5]	; number of logical devices
	call	DWORD PTR PARAM1[BP] ; call the init routine

	xor	ah,ah
	pop	DS
	pop	DX
	pop	CX
	mov	SP,BP
	pop	BP
	ret
_initfft ENDP

;*********************************************************
; loadall(length) - Do a data transfer from pc to extented
;		    memory and vice versa
; short  len;	    Number of 16-bit words to move
;*********************************************************
FUNCTION  _loadall

	enter	0,0

	push	ds			; save ds
	push	es			; save es
	pusha				; save all registers
	pushf				; save flags

	xor	ax,ax			; clear ax
	mov	ds,ax			; set ds to segment 0

	mov	si,82ah 		; offset of bp in loadall area
	mov	word ptr [si],bp	; set bp
	mov	word ptr [si+2],sp	; set sp

	in	al,portk		; read port k
	or	al,a20bit		; enable a20 line
	jmp	$+2
	out	portk,al

	mov	si,806h 		; offset of msw in loadall area
	SMSW	ax			; get machine status word
	mov	word ptr [si],ax
	mov	si,818h 		; offset of flags in loadall area
	cli				; disable interrupts
	pushf				; get flags
	pop	ax
	mov	word ptr [si],ax
	mov	word ptr [si+2],offset movedata  ; set ip to movedata
	mov	cx,word ptr [bp+param1] ; get length
	mov	si,832h 		; offset of cx in loadall area
	mov	word ptr [si],cx	; save length

	LOADALL 			; do loadall

movedata:
	xor	si,si			; clear counter
	xor	di,di
	cld				; forward direction
	rep	movsw

	in	al,portk		; read pork k
	and	al,not a20bit		; disable a20 line
	jmp	$+2
	out	portk,al

	popf				; restore flags
	popa				; restore registers
	pop	es			; restore es and ds
	pop	ds

	xor	ax,ax			; no errors
	leave
	ret
_loadall	ENDP


;*********************************************************
; getcs() - Return the current code segment
;*********************************************************
FUNCTION  _getcs
	mov	ax,cs			; return cs in ax
	ret
_getcs	ENDP


;*********************************************************
; getss() - Return the current stack segment
;*********************************************************
FUNCTION  _getss
	mov	ax,ss			; return ss in ax
	ret
_getss	ENDP


;*********************************************************
; extmem() - Return the amount of extended memory installed in the PC
;
;
;
;
;

FUNCTION _extmem
        mov  AH,88H                     ; memory
        int  15H
        ret
_extmem ENDP

;*********************************************************
;
; long exchl(val)   - swap bytes within the lower and upper half
;      long val;      of a long, then swap the upper and lower
;                     words
;
; Returns long values in AX DX
;
;

FUNCTION _exchl
        push    BP
        mov     BP,SP
        mov     AX,[BP+PARAM1]
        mov     DX,[BP+PARAM2]
        xchg    AL,AH
        xchg    DL,DH
        xchg    AX,DX
        mov     SP,BP
        pop     BP
        ret
_exchl  ENDP

FUNCTION _exchw
        PUSH    BP
        MOV     BP,SP

        MOV     AX,[BP+PARAM1]
        XCHG    AL,AH

        MOV     SP,BP
        POP     BP
        RET
_exchw  ENDP


;*************************************************************************
;        INTERRUPT HANDLERS
;*************************************************************************





dead    proc
dloop:  sti
        nop
        jmp     dloop
dead    endp


_i_d0   PROC    FAR                     ; INTS 0
	IRET
        call    dead
_i_d0   ENDP

_i_trap PROC    FAR                     ; INTS 4
	IRET
        call    dead
_i_trap ENDP

_i_ign  PROC    FAR                     ; for INTS 1,3,5,6,7
	IRET
        call    dead                    ; This handler ignores the call
_i_ign  ENDP                            ; and does a dummy return

_i_nmi  PROC    FAR                     ; NMI handler
        call    dead
_i_nmi  ENDP                            ; This handler should determine
                                        ; what's causing the problem

;***********************************************************************
;
; _msint - Mouse interrupt from BIOS. This routine is called from BIOS
;          after the BIOS code has captured all of the data from the
;          mouse. The BIOS performs the following function:
;
;
;       Data from the mouse is sent to the PS/2 via an interrupt.
;       This interrupt is on level 4 of the slave interrupt controller
;       (vector 0x74).  When one of these interrupts occurs the BIOS
;       code will:
;
;          1. Make sure the data is from the mouse
;          2. Get the data package size
;          3. Input data till all packets are recieved. An EOI is
;             sent at the end of each byte received (except for the
;             last one)
;          4. If last byte, push all the data on the stack.
;          5. Call us (far call)
;          6. Issue an EOI when we return
;          7. IRET
;
;      Our interrupt handler gets the data off of the stack, then sets
;      up the enviroment to call the mouseint() function.

_msint  PROC  far
        ASSUME SS:NOTHING

        ; Save callers registers

        push    BP                      ; Set up a frame pointer so that
                                        ; we can get the data off of the
                                        ; callers stack.
        mov     BP, SP                  ; BP Points to Callers SP
        push    DS                      ; Save Callers Registers
        push    ES
        pusha

        ;
        ; Address our Data Segment
        ;

        mov     AX, DGROUP              ; Set up addressability to our
        mov     DS, AX                  ; data.
        mov     DX, AX                  ; We put this in SS later on.

        ;
        ; Get the mouse data off of the callers stack
        ;

        mov     AX, [BP+12]             ; Status byte from mouse
        mov     _msstatus, AX
        mov     AX, [BP+10]             ; X data
        mov     _msx, AX
        mov     AX, SS:[BP+8]           ; Y data
        mov     _msy, AX
        ;
        ; Set Up A Local Stack
        ;
        ASSUME SS:DGROUP
        pushf
        cli
        lea     BX, mssp               ; Get address of new SP
        mov     [BX+2], SP             ; Save the old SP and SS
        mov     AX, SS
        mov     [BX+4], AX
        mov     SS, DX                 ; Put our data SEG in SS
        mov     SP, BX                 ; New SP (interrupt stack)
        popf
        ;
        ; And Away we Gooooooo
        ;
        xor     AX, AX
        push    AX                     ; From interrupt level
        push    AX                     ; No status
        call    _mouseint              ; Pass it to C function
        add     SP, 4                  ; Adjust stack
        ;
        ; Restore Callers Registers and Stack
        ;
        RESTORESTK mssp
        popa
        pop     ES
        pop     DS
        mov     SP, BP
        pop     BP
        ret                           ; To BIOS (he/she does the IRET )
_msint  ENDP

;***********************************************************************
; _kbd_intercept:
;
;        - Keyboard intercept. This routine is called from BIOS
;          after the BIOS code has processed a keyboard interrupt (irq1).
;
;          To install this routine we must replace the system services
;          routine (int 0x15) with our handler, then watch for the
;          call from the BIOS int 9 routine (keyboard interrupt handler)
;          where AH=0x4f. We then grab the scan code and pass it to
;          the "C" interrupt handler.


_kbd_intercept PROC far

        ; Check the function number

        cmp     AH, 4fH                 ; Is it the Kbd Intercept call
        jnz     passiton                ; No, call original bios routine.

        ;
        ; Process a keyboard intercept call
        ;

        PUSH    DS
        PUSH    ES
        PUSHA
        ;
        ; Address our data segment, and set up an interrupt stack
        ;
        CHANGESTK  kbsp
        ;
        ; Pass the scan code off to the "C" interrupt handler
        ;
        push  AX
        call _kbintr
        add  SP, 2
        ;
        ; Restore callers registers and stack, then reset the carry flag
        ; so that BIOS ignores the scan code.
        ;
        RESTORESTK kbsp
        POPA
        POP    ES
        pop    DS
        clc                             ; Tell BIOS to ignore this key
        ret    2                        ; Return (throw away callers flags)

        ;
        ; Pass all other requests off to original BIOS code
        ;

passiton:
        push    DS                      ; Callers DS

        push    DGROUP                  ; Address Our data
        pop     DS
        push    BP
	mov	BP,SP

        push    _biosint15seg           ; Put BIOS entry point onto
        push    _biosint15off           ; the stack.
        mov     DS,word ptr [BP+2]      ; Restore callers DS
        mov     BP,word ptr [BP+0]      ; and BP
        ret     4                       ; Enter original BIOS INT 15 code
_kbd_intercept ENDP

_sysirq PROC FAR                        ; system clock interupt
        I_START

        CHANGESTK  syssp

        call    _sysclock                ; CALL THE system clock routine

        RESTORESTK   syssp
	cli				 ; undo I_START code
	popa
	pop	es
; NOTE: to finish undoint I_START we should issue a pop DS, but
; the first instruction that we would issue in the next section
; would be a push DS, so we don't bother
; now call the old routine at this location.
        push    DGROUP                  ; Address Our data
        pop     DS
        push    BP
        mov     BP,SP
        push    _biosint1cseg           ; Put BIOS entry point onto
        push    _biosint1coff           ; the stack.
        mov     DS,word ptr [BP+2]      ; Restore callers DS
        mov     BP,word ptr [BP+0]      ; and BP
        ret     4                       ; Enter original BIOS INT 15 code
_sysirq ENDP


_hdirq   PROC FAR                        ; CASCADE FROM 2ND 8259
        I_START                         ; SAVE ALL REGISTERS
        CHANGESTK  hdirqsp
 ;       IFSTRAY hdstray

	mov	ax,1
	push	ax
	call	_hdint
	pop	ax

hdstray:

        RESTORESTK hdirqsp
        I_EXIT                          ; RESTORE THE REGS AND EXIT
_hdirq   ENDP

_fdirq   PROC FAR                        ; CASCADE FROM 2ND 8259
        I_START                         ; SAVE ALL REGISTERS
        CHANGESTK  fdirqsp
 ;       IFSTRAY fdstray

	mov	ax,1
	push	ax
	call	_fdint
	pop	ax

fdstray:

        RESTORESTK fdirqsp
        I_EXIT                          ; RESTORE THE REGS AND EXIT
_fdirq   ENDP

_irq1   PROC FAR                        ; CASCADE FROM 2ND 8259
        I_START                         ; SAVE ALL REGISTERS
        CHANGESTK  irq1sp
        IFSTRAY irq1stray

	call _kbd_int			; call C code to process
irq1stray:

        RESTORESTK irq1sp
        I_EXIT                          ; RESTORE THE REGS AND EXIT
_irq1   ENDP

_irq2   PROC FAR                        ; CASCADE FROM 2ND 8259
        I_START                         ; SAVE ALL REGISTERS
        CHANGESTK  irq2sp
        IFSTRAY irq2stray
        ROMPLVL3 POLL_2
irq2stray:
        RESTORESTK irq2sp
        I_EXIT                          ; RESTORE THE REGS AND EXIT
_irq2   ENDP


_irq3   PROC FAR
        I_START                         ; SAVE ALL REGISTERS
        CHANGESTK  irq3sp
        IFSTRAY irq3stray


        ROMPLVL3 POLL_3

irq3stray:
        RESTORESTK irq3sp
        I_EXIT                          ; RESTORE THE REGS AND EXIT
_irq3   ENDP

_irq3asy   PROC FAR
        I_START                         ; SAVE ALL REGISTERS
        CHANGESTK  irq3sp
        IFSTRAY irq3asystray


        call	_asy3			; call the C routine 

irq3asystray:
        RESTORESTK irq3sp
        I_EXIT                          ; RESTORE THE REGS AND EXIT
_irq3asy   ENDP


_irq4   PROC FAR
        I_START                         ; SAVE ALL REGISTERS
        CHANGESTK  irq4sp
        IFSTRAY irq4stray

        ROMPLVL3 POLL_4

irq4stray:
        RESTORESTK irq4sp
        I_EXIT                          ; RESTORE THE REGS AND EXIT
_irq4   ENDP


_irq4asy   PROC FAR
        I_START                         ; SAVE ALL REGISTERS
        CHANGESTK  irq4sp
        IFSTRAY irq4asystray

        call	_asy4			; call the C routine 

irq4asystray:
        RESTORESTK irq4sp
        I_EXIT                          ; RESTORE THE REGS AND EXIT
_irq4asy   ENDP


_irq5   PROC FAR
        I_START                         ; SAVE ALL REGISTERS
        CHANGESTK  irq5sp
        IFSTRAY irq5stray
        ROMPLVL3 POLL_5
irq5stray:
        RESTORESTK  irq5sp
        I_EXIT                          ; RESTORE THE REGS AND EXIT
_irq5   ENDP


_irq6   PROC FAR
        I_START                         ; SAVE ALL REGISTERS
        CHANGESTK  irq6sp
        IFSTRAY irq6stray
        ROMPLVL3 POLL_6
irq6stray:
        RESTORESTK irq6sp
        I_EXIT                          ; RESTORE THE REGS AND EXIT
_irq6   ENDP


_irq7   PROC FAR                        ; *******CBCB INTERRUPT*********
        I_START

        CHANGESTK  irq7sp
        IFSTRAY irq7stray

        call    _cbcbreq                ; CALL THE CBCBREQ FUNCTION

irq7stray:
        RESTORESTK   irq7sp
        I_EXIT
_irq7   ENDP



_irq8   PROC FAR
        I_START                         ; SAVE ALL REGISTERS
        CHANGESTK  irq8sp
        IFSTRAY irq8stray
        ROMPLVL4 POLL_0
irq8stray:
        RESTORESTK irq8sp
        I_EXIT                          ; RESTORE THE REGS AND EXIT
_irq8   ENDP


_irq9   PROC FAR
        I_START                         ; SAVE ALL REGISTERS
        CHANGESTK  irq9sp
        IFSTRAY irq9stray
        ROMPLVL4 POLL_1
irq9stray:
        RESTORESTK irq9sp
        I_EXIT                          ; RESTORE THE REGS AND EXIT
_irq9   ENDP

_irq10  PROC FAR
        I_START                         ; SAVE ALL REGISTERS
        CHANGESTK  irq10sp
        IFSTRAY irq10stray
        ROMPLVL4 POLL_2
irq10stray:
        RESTORESTK  irq10sp
        I_EXIT                          ; RESTORE THE REGS AND EXIT
_irq10  ENDP

_irq11  PROC FAR
        I_START                         ; SAVE ALL REGISTERS
        CHANGESTK  irq11sp
        IFSTRAY irq11stray
        ROMPLVL4 POLL_3
irq11stray:
        RESTORESTK  irq11sp
        I_EXIT                          ; RESTORE THE REGS AND EXIT
_irq11  ENDP

_irq12  PROC FAR
        I_START                         ; SAVE ALL REGISTERS
        CHANGESTK  irq12sp
        IFSTRAY irq12stray
        ROMPLVL4 POLL_4
irq12stray:
        RESTORESTK  irq12sp
        I_EXIT                          ; RESTORE THE REGS AND EXIT
_irq12  ENDP

_irq13  PROC FAR
        I_START                         ; SAVE ALL REGISTERS
        CHANGESTK  irq13sp
        IFSTRAY irq13stray
        ROMPLVL4 POLL_5
irq13stray:
        RESTORESTK  irq13sp
        I_EXIT                          ; RESTORE THE REGS AND EXIT
_irq13  ENDP

_irq14  PROC FAR
        I_START                         ; SAVE ALL REGISTERS
        CHANGESTK  irq14sp
        IFSTRAY irq14stray
        ROMPLVL4 POLL_6
irq14stray:
        RESTORESTK  irq14sp
        I_EXIT                          ; RESTORE THE REGS AND EXIT
_irq14  ENDP

_irq15  PROC FAR

        I_START                         ; SAVE ALL REGISTERS
        CHANGESTK  irq15sp
        IFSTRAY irq15stray
        ROMPLVL4 POLL_7
irq15stray:
        RESTORESTK irq15sp
        I_EXIT                          ; RESTORE THE REGS AND EXIT
_irq15  ENDP

FUNCTION _int26
        push    bp
        mov     bp,sp

        push    si
        push    di

	push	ds
	;
	; only dos 4 can address sectors more than 32 Meg out.
	;
	mov	ax,PARAM4[bp]	; top half of sector number
	or	ax,ax
	jnz	use_dos_4

	;
	; The sector we want is close enough to use old style int26.
	;  (try this first, we may not be running under DOS 4.0).
	;
	mov	ax,PARAM1[bp]
	mov	cx,PARAM2[bp]
	mov	dx,PARAM3[bp]
	lds	bx,PARAM5[bp]
        int     26h
	pop	cx
	jnc	done
	cmp	ax,0207H	; the sector resides on a >32Meg partition?
	stc			; the cmp could have cleared the carry..
	jnz	done		; is a real error.
	mov	ax,PARAM4[BP]
use_dos_4:
	pop	ds		; restore ds register
	;
	; For one reason or an other we must user DOS 4.0 style int26.
	;  if we are not running under DOS 4.0 this will fail.
	;
	push	ds
	mov	RBA2,ax
	mov	ax,PARAM3[bp]
	mov	RBA,ax
	mov	ax,PARAM2[bp]
	mov	COUNT,ax
	mov	ax,PARAM5[bp]
	mov	ADDR,ax
	mov	ax,PARAM6[bp]
	mov	ADDR2,ax
	mov	cx,-1
	mov	ax,PARAM1[bp]
	lea	bx,DISK_PACKET
	int	26h
	pop	cx

done:
	mov	al,ah		; Don't clobber the carry flag
	mov	ah,0		; Don't clobber the carry flag (no xor or sub..)
	jnc	no_err_26
	mov	ah,80h
no_err_26:
	pop	ds
	pop	di
	pop	si
	pop	bp
	ret
_int26  endp

FUNCTION _int13
        push    bp
        mov     bp,sp

        push    si
        push    di

        mov     bx,[bp+PARAM7]
        mov     dx,[bp+PARAM8]
        mov     es,dx
        mov     ax,[bp+PARAM4] ;track
        mov     ch,al
        ror     ah,1
        ror     ah,1
        mov     cl,ah
        or      cl,[bp+PARAM5]  ;sector
        mov     dh,[bp+PARAM3]  ;head
        mov     dl,[bp+PARAM2]  ;drive
        mov     ah,[bp+PARAM1]  ;op
        mov     al,[bp+PARAM6]  ;num

        int     13h
        mov     al,ah
        mov     ah,0
        jnc     noerr
        mov     ah,80h
noerr:

        pop     di

        pop     si
        mov     sp,bp
        pop     bp
        ret
_int13  endp


;*****************************************************************

; int10 - Do A BIOS Video Interrupt
;
;  Paramaters PARAM1 : struct bios_int  *   - Defined in biosreq.c
;
;  Note: We had to write our own routine for this one (insted of using
;        int86x) because some int 10 calls require us to change BP
;
;


FUNCTION _int10
        push    BP
        mov     BP, SP
        push    DS
        push    ES
        pusha

        mov     BX, [bp+PARAM1]
        mov     AX, [BX + 6]
        mov     CX, [BX + 10]
        mov     DX, [BX + 12]
        mov     SI, [BX + 14]
        mov     DI, [BX + 16]
        mov     BP, [BX + 18]
        mov     ES, [BX + 22]
        mov     bxsave, BX
        mov     BX, [BX + 8]

        int     10H

        push    BX                          ; Save return value for BX
        mov     BX, bxsave                  ; Get structure pointer back
        jnc     int10nc                     ; Is the carry flag set ?
        mov     [BX + 20], 8000H            ;   Yes Set the cflag field

int10nc:
        mov     [BX + 6], AX                ; Return AX
        pop     AX                          ; Get BX off stack
        mov     [BX + 8], AX               ; Return BX
        mov     [BX + 10], CX               ; Return CX
        mov     [BX + 12], DX               ; Return DX


        popa
        pop     ES
        pop     DS
        mov     SP, BP
        pop     BP
        ret
_int10  ENDP


FUNCTION _eoi_master
        push    BP
        mov     BP, SP
        push    AX
        mov     AX, [BP+PARAM1]

        pushf
        cli
        out     MAST_8259, AL
        jmp     $+2
        popf

        pop     AX
        mov     SP, BP
        pop     BP
        ret
_eoi_master ENDP


FUNCTION _eoi_slave
        push    BP
        mov     BP, SP
        push    AX
        mov     AX, [BP+PARAM1]

        pushf
        cli
        out     SLAVE_8259, AL          ; Acknowledge irq on slave chip
        mov     AL, IRQ2EOI             ; Specific EOI for IRQ2

        out     MAST_8259, AL           ; Acknowledge irq on master
        jmp     $+2

        popf

        pop     AX
        mov     SP, BP
        pop     BP
        ret
_eoi_slave ENDP


;------------------------------------------------------------------------------;
;                                                                              ;
;       rbputc()      Display One Character                                  ;
;                                                                              ;
;                                                                              ;
;       Output  None                                                           ;
;                                                                              ;
;------------------------------------------------------------------------------;

FUNCTION _rbputc

                push    BP
                mov     BP, SP
                push    BX


                mov     AL, [bp+PARAM1]      ;Char to write


                mov     AH,0Eh
                mov     BX,7
                int     10h             ;Output char to display in TTY mode


                pop     BX
                mov     SP, BP
                pop     BP
                ret
_rbputc      endp

FUNCTION _rblpchar

                push    BP
                mov     BP, SP
                push    DX


                mov     AL, [bp+PARAM1]      ;Char to write


                mov     AH,00h
                mov     DX,00h
                int     17h             ;Output char to printer


                pop     DX
                mov     SP, BP
                pop     BP
                ret
_rblpchar      endp
;------------------------------------------------------------------------------;
;                                                                              ;
;      rbgetchar()     Get One Character                                       ;
;                                                                              ;
;                                                                              ;
;       Output  AL -  Char, AH Cleared                                         ;
;                                                                              ;
;------------------------------------------------------------------------------;

FUNCTION _rbgetchar

                mov     AH, 0           ; Read a char
                int     16h             ; Bios KB routine

                ret
_rbgetchar      endp


;/* Glue for UB code */

FUNCTION _fci
                push    BP
                mov     BP, SP
               push    BX
                push    ES

                push    WORD PTR [bp+6] ;off
                push    WORD PTR [bp+4] ;seg
                pop     ES
                pop     BX
                CALL    _ubcode_addr

                pop     ES
                pop     BX
                mov     SP, BP
                pop     BP
                ret
_fci            endp

	PUBLIC	_farmemcpy

;*********************************************************
;
; farmemcpy(addr1,addr2,count) - fast copy, copies count bytes from
;					addr1 to addr2 (far pointers)
;	char	far *addr1,far *addr2;
;	unsigned	count;
;
_farmemcpy	PROC	near
		push	BP
		mov	BP,SP
		push	SI
		push	DI
		mov	bx,DS
		lDS	SI,[BP+PARAM1]	;addr1 (source = DS:[SI])
		lES	DI,[BP+PARAM3]	;addr2 (dest = ES:[DI])
		mov	CX,[BP+PARAM5]	; count ( = CX);
		cld			; clear the direction flag
		clc
		ror	cx,1
		rep	movsw
		jnc	copy_done
		movsb
copy_done:
		mov	DS,BX
		pop	DI
		pop	SI
		pop	BP
		ret
_farmemcpy	ENDP

_TEXT   ENDS
        END


