;
; ATAREAD.ASM - We try to do a disk read.
;

    cli

; Save old int 76h vector
    
    xor ax,ax
    mov es,ax
    es: 
    mov ax,[01d8]
    mov old76ofs,ax
    es:
    mov ax,[01da]
    mov old76seg,ax

; Take over INT 76h (hard disk interface)

    mov ax,offset new76
    es:
    mov [01d8],ax
    mov ax,cs
    es:
    mov [01da],ax

    sti                 ; enable interrupts
    
    mov ax,ds           ; set es...
    mov es,ax           ; ...back to ds

    mov al,0A0h          ; setup al to write to drive/head register... 
                        ; ...selecting drive 0 (0A0h)  (drive 1 = 0B0h)
    mov dx,01F6h        ; dx = drive/head register port
    out dx,al           ; drive number set (AND HEAD 0 IS SET HERE)
                        
    mov dx,01F2         ; dx = sector count register
    mov al,100          ; 100 sectors to read
    out dx,al           ; send al to port dx
    
    inc dx              ; next port (sector number)
    mov al,01           ; al = sector 1
    out dx,al           ; send al to port dx

    inc dx              ; next port (cylinder low)
    xor al,al           ; al = cyl 0 (low)
    out dx,al           ; send al to port dx

    inc dx              ; next port (cylinder high)
    xor al,al           ; al = cyl 0 (high)
    out dx,al           ; send al to port dx

    mov word internal_di,0600h
    mov byte seccnt,0   ; 0 sectors read

    mov al,021h         ; al = READ SECTOR W/O RETRY command
    mov dx,01F7h        ; dx = command register port
    out dx,al           ; Command away!!
    
    xor ax,ax
theloop:       
    inc ax
    mov si,offset reading
    call prints
    cmp byte seccnt,100
    jne theloop         ; wait for the next sector


    ; Ok,now we restore int vector
    cli
    xor ax,ax
    mov es,ax
    mov ax,old76ofs
    es:
    mov [01d8],ax
    mov ax,old76seg
    es:
    mov [01da],ax
    sti
    
;    mov si,0600h
;    xor cx,cx
;    call printmsg

    int 20h              ; outta here!

; *** ISR ISR ISR ISR ISR ***
; Our int 76h ISR
new76:
    cs:
    mov old_ds,ds
    cs:
    mov old_ax,ax
    mov ax,cs
    mov ds,ax
    mov old_bx,bx
    mov old_cx,cx
    mov old_dx,dx
    mov old_bp,bp
    mov old_di,di
    mov old_si,si
    mov old_es,es
    
    mov ax,cs
    mov es,ax

    mov [0500h],ax   ; save our counter
    inc byte seccnt
    mov di,internal_di    

    ; First ack the int
    mov al,20h
    out 0A0h,al         ; nonspecific EOI to PIC 2
    jcxz next           ; breathing room 
next: 
    jcxz next2
next2:
    out 20h,al          ; nonspecific EOI to PIC 1    

    mov dx,01F7h        ; dx = status register port
    in al,dx            ; read in status register (clears interrupt)
    
    test al,01      
    jnz diskerror       ; there was an error

    cld                 ; make sure we go forward
    mov cx,100h         ; 200h bytes to transfer (512)
    mov dx,01F0h        ; dx = data register port 
    rep insw            ; read data!                 
    
idone:
    mov internal_di,di
    mov es,old_es
    mov si,old_si
    mov di,old_di
    mov bp,old_bp
    mov dx,old_dx
    mov cx,old_cx
    mov bx,old_bx
    mov ax,old_ds
    mov ds,ax
    cs:
    mov ax,old_ax
    
    iret

diskerror:
    sti
    mov si,offset dskerr
    call prints
    jmp idone

; end new76

printmsg:
        lodsb                    ; String [si] to al
        inc cx
        cmp cx,51201              
        je loc_ret
        cmp al,7 
        je printmsg
        mov  ah,0Eh
        mov  bx,7
        int  10h            ; Video display   ah=functn 0Eh
                        ;  write char al, teletype mode
        jmp  short printmsg      ; (0152)
loc_ret:    ret
; end printmsg

prints:
    lodsb                    ; String [si] to al
    or   al,al               ; Zero ?
    jz   ps_done            ; Jump if zero
    mov  ah,0Eh
    mov  bx,7
    int  10h                 ; Do the int        
    jmp  short prints      

ps_done:
    ret
; end print_msg

dskerr db 'Disk read error.',0Ah,0Dh,00h
reading db 'reading...',00h

old76ofs dw ?
old76seg dw ?
seccnt db ?

internal_di dw ?

old_ax dw ?
old_bx dw ?
old_cx dw ?
old_dx dw ?
old_bp dw ?
old_di dw ?
old_si dw ?
old_ds dw ?
old_es dw ?

