Last modified on 10 November 2006, at 13:12

SYMBiFACE II:IDE routines

Revision as of 13:12, 10 November 2006 by 145.254.112.66 (Talk) (added 48bit LBA routine (just for demonstration))

These are the core SYMBiFACE II IDE low level routines of SymbOS, written by Prodatron. They show how to read and write sectors from/to an IDE device.

;==============================================================================
;### IDE-HARDDISC-ROUTINES ####################################################
;==============================================================================

ideprtsta   equ #fd0f           ;Portaddress + #f (Status/Command)
ideprtsdh   equ #fd0e           ;Portaddress + #e (SDH)
ideprtdat   equ #fd08           ;Portaddress + #8 (Data)
ideprterr   equ #fd09           ;Portaddress + #9 (Error)
ideprtdig   equ #fd06           ;Portaddress + #6 (Digital-Output)

;### IDEADR -> set address
;### Input     HL=Track, E=Sector, D=SDH (head, drive, mode), B=number of sectors
;### Output    CF=0 -> ok
;###           CF=1 -> A=error code (...)
;### Destroyed AF,BC
ideadr  call ideadr0
        ret c
        dec c
        out (c),h           ;Track High
        dec c
        out (c),l           ;Track Low
        dec c
        out (c),e           ;Sector
        dec c
        out (c),a           ;number of Sectors
        ret
ideadr0 call iderdy
        ret c
        push bc
        ld bc,ideprtsdh
        out (c),d           ;write SDH-Register
        call iderdy
        jr c,ideadr1
        pop af              ;A=number of sectors
        or a
        ret
ideadr1 pop bc
        ret

;### IDECMD -> Send command
;### Input     A=Command
;### Destroyed BC
idecmd  ld bc,ideprtsta
        out (c),a
        ret

;### IDERDY -> Wait, until IDE-drive is ready for command
;### Output    CF=0 -> ok, CF=1 -> error (A=code)
;### Destroyed AF
iderdy  push bc
        push hl
        ld bc,ideprtsta
        ld hl,256*60
iderdy1 in a,(c)
        and #80
        jr z,iderdy2
        dec l
        jr nz,iderdy1
        call subslp
        dec h
        jr nz,iderdy1
iderdy3 ld a,stoerrabo
        scf
iderdy2 pop hl
        pop bc
        ret

;### IDEDRQ -> wait for "Data Request"
;### Output    BC=Portnumber of the Status Register
;### Destroyed AF
idedrq  ld bc,ideprtsta
idedrq1 in a,(c)
        and #08
        jr z,idedrq1
        ret

;### IDERED -> read 512Bytes
;### Input     HL=destination address
;### Output    HL=address behind destination
;### Destroyed AF,BC
idered  call idedrq
        ld bc,ideprtdat
        ld a,512/32
idered1 ini:inc b:ini:inc b:ini:inc b:ini:inc b:ini:inc b:ini:inc b:ini:inc b:ini:inc b
        ini:inc b:ini:inc b:ini:inc b:ini:inc b:ini:inc b:ini:inc b:ini:inc b:ini:inc b
        ini:inc b:ini:inc b:ini:inc b:ini:inc b:ini:inc b:ini:inc b:ini:inc b:ini:inc b
        ini:inc b:ini:inc b:ini:inc b:ini:inc b:ini:inc b:ini:inc b:ini:inc b:ini:inc b
        dec a
        jr nz,idered1
        ret

;### IDEWRT -> write 512Bytes
;### Input     HL=source address
;### Output    HL=addresse behind source
;### Destroyed AF,BC
idewrt  call idedrq         ;wait for ready
        ld bc,ideprtdat     ;bc=IDE data port
        ld a,512/32
idewrt1 inc b:outi:inc b:outi:inc b:outi:inc b:outi:inc b:outi:inc b:outi:inc b:outi:inc b:outi
        inc b:outi:inc b:outi:inc b:outi:inc b:outi:inc b:outi:inc b:outi:inc b:outi:inc b:outi
        inc b:outi:inc b:outi:inc b:outi:inc b:outi:inc b:outi:inc b:outi:inc b:outi:inc b:outi
        inc b:outi:inc b:outi:inc b:outi:inc b:outi:inc b:outi:inc b:outi:inc b:outi:inc b:outi
        dec a
        jr nz,idewrt1
        ret

;### IDEERR -> check error status
;### Output    CF=0 -> ok (A=0 everthing is fine, A=1 data needed to be corrected),
;###           CF=1 -> error (A=code, 6=error while read/write, 7=error while positioning, 8=abort, 9=unknown)
;### Destroyed BC
ideerr  ld bc,ideprtsta
        in a,(c)
        and 1+4
        ret z               ;CF=0, A=0 -> ok
        cp 4
        ld a,1              ;CF=0, A=1 -> ok, but with data correction
        ret z
        ld bc,ideprterr
        in a,(c)
        ld c,a
        ld b,6
        and 128+64          ;Sector unreadable/BadMarkedSector -> error while read/write
        jr nz,ideerr1
        ld a,c
        inc b
        and 2+16            ;Track0 not found/wrong SectorNum -> error while positioning
        jr nz,ideerr1
        inc b
        bit 2,c             ;Command Aborted -> abort
        jr nz,ideerr1
        inc b               ;everything else -> unknown
ideerr1 ld a,b
        scf
        ret



;### IDE48B -> set 48bit address
;### Eingabe    IX[32-47],HL[16-31],DE[0-15]=Sectornumber, A=SDH, B=Number of Sectors
;### Output     CF=0 -> ok
;###            CF=1 -> A=error code (...)
;### Destroyed  AF,BC,DE
ide48b  push af         ;4
        call iderdy     ;    wait for ready before SDH write
        jr c,ide48b1    ;2
        pop af          ;3
        ld c,a          ;1
        push bc         ;4
        ld bc,ideprtsdh ;3
        or #0f          ;2
        dec a           ;1
        out (c),a       ;4   write SDH Register (low bytes)
        call iderdy     ;    wait for ready after SDH write (maybe this can be skipped)
        jr c,ide48b1    ;2
        dec c           ;1
        out (c),l       ;4      LBA 16-23
        dec c           ;1
        out (c),d       ;4      LBA 08-15
        dec c           ;1
        out (c),e       ;4      LBA 00-07
        ld bc,ideprtsdh ;3
        pop de          ;3
        inc e           ;1
        out (c),a       ;4   write SDH Register (high bytes)
        dec c           ;1
        db #dd:ld a,h   ;2
        out (c),a       ;4      LBA 40-47
        dec c           ;1
        db #dd:ld a,l   ;2
        out (c),a       ;4      LBA 32-39
        dec c           ;1
        out (c),h       ;4      LBA 24-31
        dec c           ;1
        out (c),d       ;4      Sector count
        ret             ;3 -> 79 microseconds
ide48b1 pop bc          ;Return on Error
        ret

See also