diff --git a/libsrc/cbm/Makefile b/libsrc/cbm/Makefile index 1a67ed45c..a77597bfa 100644 --- a/libsrc/cbm/Makefile +++ b/libsrc/cbm/Makefile @@ -44,7 +44,7 @@ S_OBJS = c_acptr.o \ close.o \ ctype.o \ cvline.o \ - diskerror.o \ + diskcmd.o \ filedes.o \ filename.o \ filevars.o \ @@ -57,6 +57,7 @@ S_OBJS = c_acptr.o \ oserror.o \ read.o \ revers.o \ + rwcommon.o \ scratch.o \ sysremove.o \ systime.o \ diff --git a/libsrc/cbm/cbm.inc b/libsrc/cbm/cbm.inc index 4a418e5e1..d0f0aad3c 100644 --- a/libsrc/cbm/cbm.inc +++ b/libsrc/cbm/cbm.inc @@ -51,8 +51,17 @@ IOBASE = $FFF3 ;----------------------------------------------------------------------------- ; Device numbers ; - + CBMDEV_KBD = 0 CBMDEV_DATASETTE= 1 CBMDEV_RS232 = 2 CBMDEV_SCREEN = 3 + +;----------------------------------------------------------------------------- +; Disk stuff +; + +MAX_DRIVES = 24 +FIRST_DRIVE = 8 + + diff --git a/libsrc/cbm/close.s b/libsrc/cbm/close.s index 0bca167bb..c521c0801 100644 --- a/libsrc/cbm/close.s +++ b/libsrc/cbm/close.s @@ -6,8 +6,9 @@ .export _close - .import getdiskerror + .import readdiskerror, closecmdchannel .import __errno, __oserror + .importzp tmp2 .include "errno.inc" .include "cbm.inc" @@ -25,36 +26,40 @@ bne invalidfd cmp #MAX_FDS ; Is it valid? bcs invalidfd ; Jump if no + sta tmp2 ; Save the handle -; Check if the LFN is valid and the file is open for writing +; Check if the file is actually open - adc #LFN_OFFS ; Carry is already clear tax - lda fdtab-LFN_OFFS,x; Get flags for this handle + lda fdtab,x ; Get flags for this handle + and #LFN_OPEN beq notopen ; Valid lfn, close it. The close call is always error free, at least as far ; as the kernal is involved lda #LFN_CLOSED - sta fdtab-LFN_OFFS,x - lda unittab,x - pha ; Push unit for this file - txa + sta fdtab,x + lda tmp2 ; Get the handle + clc + adc #LFN_OFFS ; Make LFN from handle jsr CLOSE - pla -; Read the drive error channel +; Read the drive error channel, then close it - lda unittab,x - tax - jsr getdiskerror - cmp #$00 - bne error + ldy tmp2 ; Get the handle + ldx unittab,y ; Get teh disk for this handle + jsr readdiskerror ; Read the disk error code + pha ; Save it on stack + ldy tmp2 + ldx unittab,y + jsr closecmdchannel ; Close the disk command channel + pla ; Get the error code from the disk + bne error ; Jump if error ; Successful - tax + tax ; Return zero in a/x rts ; Error entry, file descriptor is invalid diff --git a/libsrc/cbm/diskcmd.s b/libsrc/cbm/diskcmd.s new file mode 100644 index 000000000..134622f20 --- /dev/null +++ b/libsrc/cbm/diskcmd.s @@ -0,0 +1,212 @@ +; +; Ullrich von Bassewitz, 17.11.2002 +; +; Handle disk command channels +; + + .export isdisk + .export opencmdchannel + .export closecmdchannel + .export readdiskerror + .export writediskcmd + + .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 + +;-------------------------------------------------------------------------- +; writediskcmd: Gets pointer to data in ptr1, length in A. Writes all data +; to the command channel of the given drive. Returns an error code in A, +; flags are set according to the contents of A. + +writediskcmd: + + jsr isdisk + bcs success + +; 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 diff --git a/libsrc/cbm/diskerror.s b/libsrc/cbm/diskerror.s deleted file mode 100644 index ec0489e9f..000000000 --- a/libsrc/cbm/diskerror.s +++ /dev/null @@ -1,87 +0,0 @@ -; -; Ullrich von Bassewitz, 16.11.2002 -; -; Read the disk error channel -; - - .export readdiskerror, getdiskerror - .import fnunit - .importzp tmp1 - - .include "cbm.inc" - -;-------------------------------------------------------------------------- -; 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. - -.proc readdiskerror - -; Read the command channel. We won't check the status after the channel is -; open, because this seems to be unnecessary in most cases. - - ldx #15 - jsr CHKIN ; Read from LFN 15 - 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 done - lda #0 - -done: rts - -.endproc - - -;-------------------------------------------------------------------------- -; getdiskerror: Open the command channel to a disk unit with id in X. Read -; the error and close it again. 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. - -.proc getdiskerror - - cpx #8 ; Disk unit? - bcc nodisk - - lda #15 ; Command channel - tay ; Secondary address - jsr SETLFS - - lda #$00 - jsr SETNAM ; No name supplied to OPEN - - jsr OPEN - bcs err - - jsr readdiskerror - pha ; Save error code - lda #15 - jsr CLOSE - pla - -err: rts - -nodisk: lda #$00 - rts - -.endproc - - - diff --git a/libsrc/cbm/filedes.inc b/libsrc/cbm/filedes.inc index eb4d7050d..cccd067e9 100644 --- a/libsrc/cbm/filedes.inc +++ b/libsrc/cbm/filedes.inc @@ -14,6 +14,8 @@ LFN_OFFS = 3 ; Start with logical file number 3 LFN_CLOSED = $00 ; LFN is closed LFN_READ = $01 ; Open for reading LFN_WRITE = $02 ; Open for writing +LFN_OPEN = (LFN_READ | LFN_WRITE) +LFN_EOF = $80 ; Read to EOF LFN_STDIN = LFN_OFFS+0 LFN_STDOUT = LFN_OFFS+1 diff --git a/libsrc/cbm/open.s b/libsrc/cbm/open.s index 5d8cb269b..ad902237a 100644 --- a/libsrc/cbm/open.s +++ b/libsrc/cbm/open.s @@ -8,7 +8,7 @@ .import addysp, popax .import scratch, fnparse, fncomplete, fnset - .import getdiskerror + .import opencmdchannel, closecmdchannel, readdiskerror .import __errno, __oserror .import fnunit .importzp sp, tmp2, tmp3 @@ -110,26 +110,18 @@ common: sta tmp3 jsr OPEN bcs error -; Read the error channel +; Open the the drive command channel and read it ldx fnunit - jsr getdiskerror - cmp #0 - beq isopen ; Branch if no error - -; We had an error, close the file - - pha - lda tmp2 - clc - adc #LFN_OFFS - jsr CLOSE - pla - bne error ; Branch always + jsr opencmdchannel + bne closeandexit + ldx fnunit + jsr readdiskerror + bne closeandexit ; Branch on error ; File is open. Mark it as open in the table -isopen: ldx tmp2 + ldx tmp2 lda tmp3 sta fdtab,x lda fnunit @@ -161,7 +153,18 @@ invflags: sta __errno+1 beq errout +; Error entry: Close the file and exit +closeandexit: + pha + lda tmp2 + clc + adc #LFN_OFFS + jsr CLOSE + ldx fnunit + jsr closecmdchannel + pla + bne error ; Branch always .endproc diff --git a/libsrc/cbm/read.s b/libsrc/cbm/read.s index 6c2046900..5a2157b99 100644 --- a/libsrc/cbm/read.s +++ b/libsrc/cbm/read.s @@ -6,10 +6,11 @@ .export _read .constructor initstdin - + + .import rwcommon .import popax .import __errno, __oserror - .importzp ptr1, ptr2, ptr3, tmp1, tmp2 + .importzp ptr1, ptr2, ptr3, tmp1, tmp2, tmp3 .include "errno.inc" .include "fcntl.inc" @@ -39,31 +40,8 @@ .proc _read -; Retrieve count - - jsr popax ; Get count - eor #$FF - sta ptr1 - txa - eor #$FF - sta ptr1+1 ; Remember -count-1 - -; Retrieve buf - - jsr popax - sta ptr2 - stx ptr2+1 - -; Retrieve the handle - - jsr popax - -; Check if we have a valid handle - - cpx #$00 - bne invalidfd - cmp #MAX_FDS ; Is it valid? - bcs invalidfd ; Jump if no + jsr rwcommon ; Pop params, check handle + bcs invalidfd ; Branch if handle not ok ; Check if the LFN is valid and the file is open for writing @@ -73,34 +51,27 @@ and #LFN_READ ; File open for writing? beq notopen +; Check the EOF flag. If it is set, don't read anything + + lda fdtab-LFN_OFFS,x; Get flags for this handle + bmi eof + ; Valid lfn. Make it the input file jsr CHKIN bcs error -; Clear the byte counter - - lda #$00 - sta ptr3 - sta ptr3+1 - -; Read the status to check if we are already at the end of the file - - jsr READST - and #%01000000 - bne done - ; Go looping... - beq deccount ; Branch always + bcc @L3 ; Branch always ; Read the next byte -loop: jsr BASIN +@L0: jsr BASIN sta tmp1 ; Save the input byte jsr READST ; Read the IEEE status - sta tmp2 ; Save it + sta tmp3 ; Save it and #%10111111 ; Check anything but the EOI bit bne error5 ; Assume device not present @@ -121,17 +92,24 @@ loop: jsr BASIN ; Get the status again and check the EOI bit -@L2: lda tmp2 +@L2: lda tmp3 and #%01000000 ; Check for EOI - bne done ; Jump if end of file reached + bne @L4 ; Jump if end of file reached ; Decrement the count -deccount: - inc ptr1 - bne loop +@L3: inc ptr1 + bne @L0 inc ptr1+1 - bne loop + bne @L0 + beq done ; Branch always + +; Set the EOI flag and bail out + +@L4: ldx tmp2 ; Get the handle + lda #LFN_EOF + ora fdtab,x + sta fdtab,x ; Read done, close the input channel @@ -139,7 +117,7 @@ done: jsr CLRCH ; Return the number of chars read - lda ptr3 +eof: lda ptr3 ldx ptr3+1 rts @@ -157,7 +135,7 @@ invalidfd: notopen: lda #3 ; File not open bne error - + ; Error entry, status not ok error5: lda #5 ; Device not present diff --git a/libsrc/cbm/rwcommon.s b/libsrc/cbm/rwcommon.s new file mode 100644 index 000000000..2e124c7b0 --- /dev/null +++ b/libsrc/cbm/rwcommon.s @@ -0,0 +1,47 @@ +; +; Ullrich von Bassewitz, 17.11.2002 +; +; Common stuff for the read/write routines +; + + .export rwcommon + + .import popax + .importzp ptr1, ptr2, ptr3, tmp2 + + .include "filedes.inc" + + +;-------------------------------------------------------------------------- +; rwcommon: Pop the parameters from stack, preprocess them and place them +; into zero page locations. Return carry set if the handle is invalid, +; return carry clear if it is ok. If the carry is clear, the handle is +; returned in A. + +.proc rwcommon + + jsr popax ; Get count + eor #$FF + sta ptr1 + txa + eor #$FF + sta ptr1+1 ; Remember -count-1 + + jsr popax ; Get buf + sta ptr2 + stx ptr2+1 + + lda #$00 + sta ptr3 + sta ptr3+1 ; Clear ptr3 + + jsr popax ; Get the handle + sta tmp2 + cpx #$01 + bcs inv + cmp #MAX_FDS +inv: rts + +.endproc + + diff --git a/libsrc/cbm/scratch.s b/libsrc/cbm/scratch.s index e8ffad9d5..6fd617308 100644 --- a/libsrc/cbm/scratch.s +++ b/libsrc/cbm/scratch.s @@ -5,8 +5,9 @@ ; .export scratch - .import readdiskerror + .import opencmdchannel, closecmdchannel, writediskcmd .import fnunit, fnlen, fncmd + .importzp ptr1 .include "cbm.inc" @@ -18,28 +19,27 @@ .proc scratch - lda #15 ; Command channel - ldx fnunit ; Unit - tay ; Secondary address - jsr SETLFS + ldx fnunit + jsr opencmdchannel + bne done lda #'s' ; Scratch command sta fncmd + + lda #fncmd + sta ptr1+1 + ldx fnlen inx ; Account for "S" txa ; Length of name into A - ldx #fncmd - jsr SETNAM - - jsr OPEN - bcs done - - jsr readdiskerror ; Read the command channel + ldx fnunit ; Unit + jsr writediskcmd pha - lda #15 - jsr CLOSE + ldx fnunit + jsr closecmdchannel pla done: rts diff --git a/libsrc/cbm/write.s b/libsrc/cbm/write.s index dc7bf348c..508deb6b8 100644 --- a/libsrc/cbm/write.s +++ b/libsrc/cbm/write.s @@ -7,9 +7,9 @@ .export _write .constructor initstdout - .import incsp6 + .import rwcommon .import __errno, __oserror - .importzp sp, ptr1, ptr2 + .importzp sp, ptr1, ptr2, ptr3 .include "errno.inc" .include "fcntl.inc" @@ -44,13 +44,8 @@ .proc _write - ldy #4 - lda (sp),y ; Get fd - -; Check if we have a valid handle - - cmp #MAX_FDS ; Is it valid? - bcs invalidfd ; Jump if no + jsr rwcommon ; Pop params, check handle + bcs invalidfd ; Branch if handle not ok ; Check if the LFN is valid and the file is open for writing @@ -64,49 +59,35 @@ jsr CKOUT bcs error - -; Calculate -count-1 for easier looping - - ldy #0 - lda (sp),y - eor #$FF - sta ptr1 - iny - lda (sp),y - eor #$FF - sta ptr1+1 - -; Get the pointer to the data buffer - - iny - lda (sp),y - sta ptr2 - iny - lda (sp),y - sta ptr2+1 - jmp deccount + bcc @L2 ; Read the IEEE488 status -loop: jsr READST +@L0: jsr READST cmp #0 bne error5 +; Output the next character from the buffer + ldy #0 lda (ptr2),y inc ptr2 bne @L1 inc ptr2+1 ; A = *buf++; - @L1: jsr BSOUT +; Count characters written + + inc ptr3 + bne @L2 + inc ptr3+1 + ; Decrement count -deccount: - inc ptr1 - bne loop +@L2: inc ptr1 + bne @L0 inc ptr1+1 - bne loop + bne @L0 ; Wrote all chars, close the output channel @@ -114,12 +95,9 @@ deccount: ; Return the number of chars written - ldy #1 - lda (sp),y - tax - dey - lda (sp),y - jmp incsp6 + lda ptr3 + ldx ptr3+1 + rts ; Error entry, file descriptor is invalid @@ -142,7 +120,7 @@ error5: lda #5 ; Device not present error: sta __oserror errout: lda #$FF tax ; Return -1 - jmp incsp6 + rts .endproc