SYMBiFACE II:IDE routines

From CPCWiki - THE Amstrad CPC encyclopedia!
Revision as of 19:31, 12 November 2006 by Prodatron (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

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
;### Input      IX[32-47],HL[16-31],DE[0-15]=Sectornumber, A=SDH, B=Number of Sectors
;###            (you should reset the upper 8bits of the sector count register first)
;### Output     CF=0 -> ok
;###            CF=1 -> A=error code (...)
;### Destroyed  AF,BC,DE
ide48b  push af         ;4
        call iderdy     ;    wait for ready before first SDH write
        jr c,ide48b1    ;2
        pop af          ;3
        or #0f          ;2
        ld c,a          ;1
        push bc         ;4
        ld bc,ideprtsdh ;3
        and #f0         ;2
        out (c),a       ;4   write SDH Register (low bytes)
        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
        dec c           ;1
        pop de          ;3
        out (c),d       ;4      Sector count
        ld bc,ideprtsdh ;3
        out (c),e       ;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
        ret             ;3 -> 77 microseconds
ide48b1 pop bc          ;Return on Error
        ret

See also