1;
2; Ullrich von Bassewitz, 2002-11-17, 2009-02-22
3;
4; Handle disk command channels
5;
6
7        .export         isdisk
8        .export         opencmdchannel
9        .export         closecmdchannel
10        .export         readdiskerror
11        .export         writediskcmd
12        .export         writefndiskcmd
13
14        .import         fncmd, fnlen, fnunit
15        .importzp       tmp1, ptr1
16
17        .include        "cbm.inc"
18        .include        "filedes.inc"
19
20;--------------------------------------------------------------------------
21; isdisk: Return carry clear if the unit number in X is a disk, return
22; carry set if not.
23
24.proc   isdisk
25
26        cpx     #FIRST_DRIVE    ; Disk unit?
27        bcc     @L1             ; Branch if no disk
28        cpx     #FIRST_DRIVE+MAX_DRIVES
29        rts
30
31@L1:    sec
32        rts
33
34.endproc
35
36;--------------------------------------------------------------------------
37; Open the command channel for the disk unit in X. The function returns an
38; error code in A and sets the flags according to the contents of A.
39
40opencmdchannel:
41
42        jsr     isdisk          ; Disk unit?
43        bcs     success
44
45; Is this channel already open?
46
47        ldy     opentab-FIRST_DRIVE,x
48        bne     isopen
49
50; Open the command channel, Carry is still clear
51
52        stx     tmp1            ; Save the unit number
53        txa                     ; Get unit number
54        adc     #(LFN_OFFS+MAX_FDS-FIRST_DRIVE)
55        ldy     #15             ; Secondary address for cmd channel
56        jsr     SETLFS
57
58        lda     #0
59        jsr     SETNAM          ; No name supplied to OPEN
60
61        jsr     OPEN
62        bcs     done            ; Error, code is in A
63
64; Command channel is open now. Increment the count
65
66        ldx     tmp1            ; Unit number
67        ldy     opentab-FIRST_DRIVE,x
68isopen: iny
69        tya
70        sta     opentab-FIRST_DRIVE,x
71
72; Done, return success
73
74success:lda     #$00
75done:   cmp     #$00            ; Set flags for return code
76        rts
77
78
79;--------------------------------------------------------------------------
80; closecmdchannel: Decrement the counter for the disk command channel and
81; close the channel if the counter drops to zero. The function expects the
82; drive number in X and returns an error code in A. The flags for the return
83; code are set when the function returns.
84
85closecmdchannel:
86
87        jsr     isdisk          ; Disk unit?
88        bcs     success
89
90; Is this channel really open?
91
92        ldy     opentab-FIRST_DRIVE,x
93        beq     success         ; OOPS! Channel is not open
94
95; Decrement the count and stor it back
96
97        dey
98        tya
99        sta     opentab-FIRST_DRIVE,x
100
101; If the counter is now zero, close the channel. We still have carry clear
102; when we come here.
103
104        bne     success
105        txa                     ; Make LFN from drive number
106        adc     #(LFN_OFFS+MAX_FDS-FIRST_DRIVE)
107        jsr     CLOSE
108        bcs     done
109        bcc     success
110
111;--------------------------------------------------------------------------
112; readdiskerror: Read a disk error from an already open command channel.
113; Returns an error code in A, which may either be the code read from the
114; command channel, or another error when accessing the command channel failed.
115
116readdiskerror:
117
118        jsr     isdisk
119        bcs     success
120
121; Read the command channel. We won't check the status after the channel is
122; open, because this seems to be unnecessary in most cases.
123
124        txa
125        clc                     ; Make LFN from drive number
126        adc     #(LFN_OFFS+MAX_FDS-FIRST_DRIVE)
127        tax
128        jsr     CHKIN           ; Make the command channel input
129        bcs     done            ; Bail out with error code in A
130
131        jsr     BASIN
132        and     #$0F            ; Make digit value from PETSCII
133        sta     tmp1
134        asl     a               ; * 2
135        asl     a               ; * 4, carry clear
136        adc     tmp1            ; * 5
137        asl     a               ; * 10
138        sta     tmp1
139
140        jsr     BASIN
141        and     #$0F            ; Make digit value from PETSCII
142        clc
143        adc     tmp1
144
145; Errors below 20 are not real errors. Fix that
146
147        cmp     #20+1
148        bcs     @L1
149        lda     #$00
150@L1:    pha
151
152; Read the remainder of the message and throw it away
153
154@L2:    jsr     BASIN
155        cmp     #$0D
156        bne     @L2
157
158; Close the input channel
159
160        jsr     CLRCH
161
162; Restore the error code (will also set the flags) and return
163
164        pla
165        rts
166
167;--------------------------------------------------------------------------
168; writefndiskcmd: Write the contents of fncmd to the command channel of the
169; drive in fnunit. Returns an error code in A, flags are set according to
170; the contents of A.
171
172writefndiskcmd:
173        lda     #<fncmd
174        sta     ptr1
175        lda     #>fncmd
176        sta     ptr1+1
177
178        ldx     fnlen
179        inx                     ; Account for command char in fncmd
180        txa                     ; Length of name into A
181        ldx     fnunit          ; Unit
182
183; Run directly into writediskcmd
184
185;       jmp     writediskcmd
186
187;--------------------------------------------------------------------------
188; writediskcmd: Gets pointer to data in ptr1, length in A. Writes all data
189; to the command channel of the drive in X. Returns an error code in A,
190; flags are set according to the contents of A.
191
192writediskcmd:
193
194        jsr     isdisk
195        bcs     success         ; No disk - already done
196
197; Remember the length
198
199        sta     tmp1
200
201; Write to the command channel.
202
203        txa
204        clc                     ; Make LFN from drive number
205        adc     #(LFN_OFFS+MAX_FDS-FIRST_DRIVE)
206        tax
207        jsr     CKOUT           ; Make the command channel output
208        bcs     done            ; Bail out with error code in A
209
210        ldy     #$00
211@L1:    cpy     tmp1
212        bcs     @L3
213        lda     (ptr1),y
214        iny
215        jsr     BSOUT
216        bcc     @L1
217
218@L2:    pha
219        jsr     CLRCH
220        pla
221        rts
222
223@L3:    jsr     CLRCH
224        lda     #$00
225        rts
226
227
228;--------------------------------------------------------------------------
229; Data
230
231.bss
232
233opentab:        .res    MAX_DRIVES, 0
234