; Disk drivers for Tube Flex - 6809 Flex running in an Acorn Tube environment ; =========================================================================== ; Accesses single density disk, single or double sided, ten sectors per track. ; Double sided disks either have logical sectors 11+ or logical tracks 80+. ; ; The physical sectors can be numbered as per whatever base sector number you ; chose - set SEC0 to match. Flex uses logical sector numbers counting from ; 1, and most Flex systems number physical sectors counting from 1. ; ; v0.00 04-Feb-2015 JGH: Initial version, plain single density only ; v0.01 06-Feb-2015 JGH: Optimised DISKACCESS slightly. ; OSWORD: EQU $FFF1 ; MOS call for disk access MAXDRV: EQU 1 ; Valid drives are 0-1 SEC0: EQU $01 ; First physical sector number ORG $DE00 BEGIN: JMP >READ JMP >WRITE JMP >VERIFY JMP >RESTOR JMP >SELECT ; aka DRIVE JMP >CHECK ; aka CHKRDY JMP >CHECK ; aka QUICK JMP >INIT JMP >WINIT JMP >SEEK ; -------------------------------- ; INIT, WINIT - Initialise drivers ; -------------------------------- ; On entry, nothing ; On exit, all may be destroyed ; INIT: WINIT: RTS ; ---------------------------- ; CHECK - Check if drive ready ; ---------------------------- ; On entry, X =>FCB ; (3,X)= drive number ; On exit, A,X = may be destroyed ; B = result ; EQ+CC=drive ready, NE+CS=drive not ready ; CHECK: LDA 3,X ; Get drive number CMPA #MAXDRV ; Valid drive? BLS CHKOK ; Return good status LDB #$80 ; Error, not ready ORCC #$01 ; Set Carry flag RTS CHKOK: CLRB ; Result=0 - ok ANDCC #$FE ; Clear carry=Ok RTS ; ----------------------- ; SELECT - Select a drive ; ----------------------- ; On entry, X =>FCB ; (3,X)= drive number ; On exit, A,X = may be destroyed ; B = result, $0F if nonexistent drive ; EQ+CC=no error, NE+CS=error ; SELECT: LDA 3,X ; Get drive number CMPA #MAXDRV ; Valid drive number? BLS SELOK LDB #$0F ; Error, drive not present ORCC #$01 ; Set Carry flag RTS SELOK: STA CURDRV CLRB ; Result=0 - ok ANDCC #$FE ; Clear carry=Ok RTS ; -------------------------------------------------------- ; SEEK - Seek to specified track and side on current drive ; -------------------------------------------------------- ; On entry, D =disk address (A=track, B=sector) ; On exit, X =preserved so callable by READ/WRITE ; A =may be destroyed ; B =result ; EQ+CC=no error, NE+CS=error ; SEEKRD: SEEKWR: SEEK: PSHS X LDX #0 ; Side 0 CMPB #10 BLS SEEK1 ; sector<11 - side 0 LDX #2 ; sector>10 - side 1 SUBB #10 ; Reduce sector number SEEK1: CMPA #80 BCS SEEK2 ; track<80 - side 0 LDX #2 ; track>79 - side 1 SUBA #80 ; Reduce track number SEEK2: DECB ; Convert to logical sector number ADDB #SEC0 ; Add first physical sector number STD DSKTRK ; Store track+sector EXG D,X ORB CURDRV ; Get drive+side STB DSKDRV ; Store drive+side PULS X LDB #$00 ; Result=Ok ANDCC #$FE ; Clear carry=Ok RTS ; -------------------------------------------- ; RESTORE - Seek to track 0 on specified drive ; -------------------------------------------- ; On entry, X =>FCB ; (3,X)= drive number ; On exit, A,X = may be destroyed ; B = result ; EQ+CC=no error, NE+CS=error ; RESTOR: BSR SELECT ; Select drive BNE RESTERR ; Error, return LDA #$00 STA DSKTRK ; Select track 0 LDB #$69 ; $69=seek BRA DISKACCESS RESTERR: RTS ; ------------------------------ ; READ - Read a sector from disk ; ------------------------------ ; On entry, X =>destination in memory ; D = disk address (A=track, B=sector) ; On exit, A,X = may be destroyed ; B = result ; EQ+CC=no error, NE+CS=error ; READ: BSR SEEKRD ; Seek sector and side BNE RESTERR LDB #$53 ; $53=read BRA DISKACCESS ; Do disk access call ; ------------------------------ ; WRITE - Read a sector from disk ; ------------------------------ ; On entry, X =>source in memory ; D = disk address (A=track, B=sector) ; On exit, A,X = may be destroyed ; B = result ; EQ+CC=no error, NE+CS=error ; WRITE: BSR SEEKWR ; Seek sector and side BNE RESTERR LDB #$4B ; $4B=write BRA DISKACCESS ; Do disk access call ; ----------------------------------- ; VERIFY - Verify sector just written ; ----------------------------------- ; On entry, no parameters ; On exit, A,X = may be destroyed ; B = result ; EQ+CC=no error, NE+CS=error ; VERIFY: LDB #0 ; Do nothing and return 'ok' ANDCC #$FE ; Clear Carry/error flag RTS ; --------------------------------------- ; DISKACCESS - Call MOS to do disk access ; --------------------------------------- ; On entry, B=command ; X=address ; control block drive/track/sector set up by SEEK ; On exit, A,X = may be destroyed ; B = result ; EQ+CC=no error, NE+CS=error ; ;DSKACCA: ; TFR A,B DISKACCESS: LDA #$03 ; Three parameters STD DSKCMD-1 ; Store length and command TFR X,D ; D=address EXG A,B ; Swap to little-endian STD DSKADD+0 LDD #0 STD DSKADD+2 LDD #$211E ; 1x256-byte sector and 'not present' STD DSKNUM DSKRETRY: LDX #DISKCTRL ; Point to control block LDA #$7F ; $7F=disk access JSR OSWORD ; MOS disk access call LDB DSKRES ; Get result CMPB #$10 BEQ DSKRETRY ; For 3.5" drives, ignore Not Ready ; Translate OSWORD 7F result into 1770 result ; OSWRD7F 1770 ; 01 busy ; 02 data request ; 20 deleted data read ; 00 ok 00 ; 02 ok 00 ; 04 ok 00 ; 06 unused 00 ; 08 clock error 04 data lost ; 0A late DMA 04 ; 0C ID CRC error 08 CRC error ; 0E data CRC error 08 CRC error ; 10 drive not ready 80 not ready ; 12 write protected 40 write protected ; 14 track 0 not found 10 not found ; 16 write error 04 data lost ; 18 sector not found 10 not found ; 1A unused 80 ; 1C unused 80 ; 1E drive not present 0F not present LSRB ; Divide OSWORD result by two ANDB #$0F ; Drop other flags CLRA ; D=$00xx TFR D,X ; X=OSWORD result/2 LDB DSKCONV,X ; Get byte from translation table ANDCC #$FE ; Clear Carry/error flag BEQ DSKACCOK ; Result=0, return EQ+CC ORCC #$01 ; Result<>0, return NE+CS DSKACCOK: RTS DSKCONV: FCB $00, $00, $00, $00, $04, $04, $08, $08 FCB $80, $40, $10, $04, $10, $80, $80, $0F CURDRV: FCB 0 ; Current drive DISKCTRL: DSKDRV: FCB 0 ; Drive DSKADD: FDB 0 ; Address low - nb, little-endian! FDB 0 ; Address high FCB $03 ; 3 parameters DSKCMD: FCB $53 ; Command DSKTRK: FCB 0 ; Track DSKSEC: FCB 0 ; Sector DSKNUM: FCB $21 ; 1x256byte sector DSKRES: FCB $1E ; Preload result with 'drive not present' ; Module limit: $E000