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