SYMBiFACE II:IDE routines
From CPCWiki - THE Amstrad CPC encyclopedia!
Revision as of 12: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