cc65/libsrc/cbm/diskcmd.s

234 lines
6.1 KiB
ArmAsm

;
; Ullrich von Bassewitz, 2002-11-17, 2009-02-22
;
; Handle disk command channels
;
.export isdisk
.export opencmdchannel
.export closecmdchannel
.export readdiskerror
.export writediskcmd
.export writefndiskcmd
.import fncmd, fnlen, fnunit
.importzp tmp1, ptr1
.include "cbm.inc"
.include "filedes.inc"
;--------------------------------------------------------------------------
; isdisk: Return carry clear if the unit number in X is a disk, return
; carry set if not.
.proc isdisk
cpx #FIRST_DRIVE ; Disk unit?
bcc @L1 ; Branch if no disk
cpx #FIRST_DRIVE+MAX_DRIVES
rts
@L1: sec
rts
.endproc
;--------------------------------------------------------------------------
; Open the command channel for the disk unit in X. The function returns an
; error code in A and sets the flags according to the contents of A.
opencmdchannel:
jsr isdisk ; Disk unit?
bcs success
; Is this channel already open?
ldy opentab-FIRST_DRIVE,x
bne isopen
; Open the command channel, Carry is still clear
stx tmp1 ; Save the unit number
txa ; Get unit number
adc #(LFN_OFFS+MAX_FDS-FIRST_DRIVE)
ldy #15 ; Secondary address for cmd channel
jsr SETLFS
lda #0
jsr SETNAM ; No name supplied to OPEN
jsr OPEN
bcs done ; Error, code is in A
; Command channel is open now. Increment the count
ldx tmp1 ; Unit number
ldy opentab-FIRST_DRIVE,x
isopen: iny
tya
sta opentab-FIRST_DRIVE,x
; Done, return success
success:lda #$00
done: cmp #$00 ; Set flags for return code
rts
;--------------------------------------------------------------------------
; closecmdchannel: Decrement the counter for the disk command channel and
; close the channel if the counter drops to zero. The function expects the
; drive number in X and returns an error code in A. The flags for the return
; code are set when the function returns.
closecmdchannel:
jsr isdisk ; Disk unit?
bcs success
; Is this channel really open?
ldy opentab-FIRST_DRIVE,x
beq success ; OOPS! Channel is not open
; Decrement the count and stor it back
dey
tya
sta opentab-FIRST_DRIVE,x
; If the counter is now zero, close the channel. We still have carry clear
; when we come here.
bne success
txa ; Make LFN from drive number
adc #(LFN_OFFS+MAX_FDS-FIRST_DRIVE)
jsr CLOSE
bcs done
bcc success
;--------------------------------------------------------------------------
; readdiskerror: Read a disk error from an already open command channel.
; Returns an error code in A, which may either be the code read from the
; command channel, or another error when accessing the command channel failed.
readdiskerror:
jsr isdisk
bcs success
; Read the command channel. We won't check the status after the channel is
; open, because this seems to be unnecessary in most cases.
txa
clc ; Make LFN from drive number
adc #(LFN_OFFS+MAX_FDS-FIRST_DRIVE)
tax
jsr CHKIN ; Make the command channel input
bcs done ; Bail out with error code in A
jsr BASIN
and #$0F ; Make digit value from PETSCII
sta tmp1
asl a ; * 2
asl a ; * 4, carry clear
adc tmp1 ; * 5
asl a ; * 10
sta tmp1
jsr BASIN
and #$0F ; Make digit value from PETSCII
clc
adc tmp1
; Errors below 20 are not real errors. Fix that
cmp #20+1
bcs @L1
lda #$00
@L1: pha
; Read the remainder of the message and throw it away
@L2: jsr BASIN
cmp #$0D
bne @L2
; Close the input channel
jsr CLRCH
; Restore the error code (will also set the flags) and return
pla
rts
;--------------------------------------------------------------------------
; writefndiskcmd: Write the contents of fncmd to the command channel of the
; drive in fnunit. Returns an error code in A, flags are set according to
; the contents of A.
writefndiskcmd:
lda #<fncmd
sta ptr1
lda #>fncmd
sta ptr1+1
ldx fnlen
inx ; Account for command char in fncmd
txa ; Length of name into A
ldx fnunit ; Unit
; Run directly into writediskcmd
; jmp writediskcmd
;--------------------------------------------------------------------------
; writediskcmd: Gets pointer to data in ptr1, length in A. Writes all data
; to the command channel of the drive in X. Returns an error code in A,
; flags are set according to the contents of A.
writediskcmd:
jsr isdisk
bcs success ; No disk - already done
; Remember the length
sta tmp1
; Write to the command channel.
txa
clc ; Make LFN from drive number
adc #(LFN_OFFS+MAX_FDS-FIRST_DRIVE)
tax
jsr CKOUT ; Make the command channel output
bcs done ; Bail out with error code in A
ldy #$00
@L1: cpy tmp1
bcs @L3
lda (ptr1),y
iny
jsr BSOUT
bcc @L1
@L2: pha
jsr CLRCH
pla
rts
@L3: jsr CLRCH
lda #$00
rts
;--------------------------------------------------------------------------
; Data
.bss
opentab: .res MAX_DRIVES, 0