; Subroutine to check if an address range is available for allocation
; as shared memory.
; Input:  bx = segment start address
;         di = # of bytes / 16
; Returns with carry set if range is occupied
; All registers saved and restored
;
        public  occupied_chk
occupied_chk:
        push    ax                      ; save registers
        push    bx
        push    cx
        push    dx
        push    si
        push    di
        push    ds
;
; first check if there is any ROM in our range
;
        add     di,bx                   ; end of range to check
        mov     dx,0c000h               ; start of possible ROM area
occ_next2k:
        mov     ds,dx
        xor     si,si
        mov     cx,0aa55h               ; ROM signature
        mov     ax,[si]
        cmp     ax,cx                   ; any signature?
        jne     occ_no_ROM
        mov     ah,[si+2]               ; ROM length in 512 byte blocks
        xor     al,al
        mov     cx,ax
        shr     ax,1
        shr     ax,1
        shr     ax,1
        add     ax,dx                   ; end of ROM
        cmp     ax,bx                   ; does it reach into our area?
        jb      occ_no_ROM
        shl     cx,1                    ; # of bytes to checksum
        xor     ah,ah                   ; clear accumulated checksum
occ_chksum:
        lodsb                           ; get a byte
        add     ah,al                   ; add modulo 100h
        loop    occ_chksum              ; repeat for all bytes
        or      ah,ah                   ; is checksum zero?
        jz      occ_is_ROM              ; -yes, range is occupied
occ_no_ROM:
        add     dx,2048 shr 4           ; next 2k segment
        cmp     dx,di                   ; at end of our range?
        jbe     occ_next2k
;
; no ROM found in our range, check for RAM
;
        mov     ds,bx                   ; point segment at start of range
        sub     di,bx                   ; compute # of bytes
        mov     cl,4
        shl     di,cl
        xor     bx,bx                   ; clear word pointer
        mov     ax,0a5a5h               ; test pattern
        mov     si,05a5ah               ;   and its complement
occ_nextword:
        sti                             ; disable interrupts
        mov     cx,[bx]                 ; save original contents
        mov     dx,[bx+2]               ; save original contents
        mov     [bx],si                 ; put our pattern
        mov     [bx+2],ax               ; drain any capacitive memory
        cmp     [bx],si                 ; is our pattern still there?
        mov     [bx],cx                 ; restore original contents
        mov     [bx+2],dx               ; restore original contents
        cli                             ; enable interrupts
        jne     occ_no_RAM
        sti                             ; disable interrupts
        mov     [bx],ax                 ; put the complement pattern
        mov     [bx+2],si               ; drain capacitive memory
        cmp     [bx],ax                 ; our pattern still there?
        mov     [bx],cx                 ; restore original contents
        mov     [bx+2],dx               ; restore original contents
        sti                             ; enable interrupts
        je      occ_is_RAM              ; -yes, range is occupied
occ_no_RAM:
        add     bx,2                    ; check next word
        cmp     bx,di                   ; at end of range?
        jb      occ_nextword
        clc                             ; clear carry - range is available
        jmp     short occ_return
occ_is_ROM:
occ_is_RAM:
        stc                             ; set carry - range is occupied
occ_return:
        pop     ds                      ; restore registers
        pop     di
        pop     si
        pop     dx
        pop     cx
        pop     bx
        pop     ax
        ret

