2 ; Christian Groessler, May-2000
4 ; fd indirection table & helper functions
9 .importzp tmp1,tmp2,tmp3,ptr4,sp
10 .import fd_table,fd_index
21 ; gets fd in ax, decrements usage counter
22 ; return iocb index in X
23 ; return N bit set for invalid fd
24 ; return Z bit set if last user
25 ; all registers destroyed
33 lda fd_index,x ; get index
36 sta fd_index,x ; clear entry
38 asl a ; create index into fd table
42 cmp fd_table+ft_iocb,x ; entry in use?
43 beq inval ; no, return error
44 lda fd_table+ft_usa,x ; get usage counter
45 beq ok_notlast ; 0? (shouldn't happen)
47 sbc #1 ; decr usage counter
52 lda fd_table+ft_iocb,x ; get iocb
57 sta fd_table+ft_iocb,y ; clear table entry
58 lda fd_table+ft_flag,y
59 and #16 ; opened by app?
60 eor #16 ; return set Z if yes
67 .endproc ; fdtoiocb_down
69 inval: ldx #$ff ; sets N
73 ; clear iocb except for ICHID field
74 ; expects X to be index to IOCB (0,$10,$20,etc.)
75 ; all registers destroyed
79 inx ; don't clear ICHID
92 ; return iocb index in A, fd_table index in X
93 ; return N bit set for invalid fd
94 ; all registers destroyed
103 asl a ; create index into fd table
107 cmp fd_table+ft_iocb,x ; entry in use?
108 beq inval ; no, return error
109 lda fd_table+ft_usa,x ; get usage counter
110 beq inval ; 0? should not happen
111 lda fd_table+ft_iocb,x ; get iocb
117 ; no entry parameters
118 ; return ZF = 0/1 for not found/found
119 ; index in X if found
120 ; all registers destroyed
135 inx ; return ZF cleared
138 .endproc ; findfreeiocb
140 ; decrements usage counter for fd
141 ; if 0 reached, it's marked as unused
142 ; get fd index in tmp2
143 ; Y register preserved
148 bcs ret ; invalid index, do nothing
155 asl a ; create index into fd table
159 cmp fd_table+ft_iocb,x ; entry in use?
160 beq ret ; no, do nothing
161 lda fd_table+ft_usa,x ; get usage counter
162 beq ret ; 0? should not happen
164 sbc #1 ; decrement by one
165 sta fd_table+ft_usa,x
167 lda #$ff ; 0, table entry unused now
168 sta fd_table+ft_iocb,x ; clear table entry
171 .endproc ; fddecusage
175 ; called from open() function
176 ; finds a fd to use for an open request
177 ; checks whether it's a device or file (file: characters follow the ':')
178 ; files always get an exclusive slot
179 ; for devices it is checked whether the device is already open, and if yes,
180 ; a link to this open device is returned
182 ; Calling parameters:
183 ; tmp3 - length of filename + 1
184 ; AX - points to filename
185 ; Y - iocb to use (if we need a new open)
187 ; tmp2 - fd num ($ff and C=0 in case of error - no free slot)
188 ; C - 0/1 for no open needed/open should be performed
189 ; all registers preserved!
194 ; ptr4 - 3,4 (backup)
232 ; ptr4 points to filename
242 ; no colon there!? OK, then we use a fresh iocb....
243 ; return error here? no, the subsequent open call should fail
245 do_open_nd: ; do open and don't remember device
250 sta tmp1 ; set flag to return 'open needed' : C = 1
255 cmp fd_table,x ; check ft_iocb field for $ff
256 beq freefnd ; found a free slot
261 cmp #(MAX_FD_VAL*4)+ft_iocb ; end of table reached?
264 ; error: no free slot found
266 stx tmp1 ; return with C = 0
268 stx tmp2 ; iocb: $ff marks error
274 sbc #ft_iocb ; normalize
280 bit tmp1 ; remember device?
282 lda #0 ; no, put 0 in field
286 lda (sp),y ; get device
287 l2: sta fd_table+ft_dev,x ; set device
289 sta fd_table+ft_usa,x ; set usage counter
291 sta fd_table+ft_iocb,x ; set iocb index
293 and #7 ; device number is 3 bits
294 ora #16 ; indicated a fd actively opened by the app
295 sta fd_table+ft_flag,x
297 jsr fdt_to_fdi ; get new index
298 bcs noslot ; no one available
299 ;cmp #$ff ; no one available
300 ;beq noslot ;@@@ cleanup needed
301 sta tmp2 ; return index
304 ; string in "Xn:xxx" format
306 lda (ptr4),y ; get device number
311 sta tmp2 ; save it for speed later here also
312 lda #4 ; max. length if only device + number ("Xn:")
314 bcc do_open_nd ; string is longer -> contains filename
315 bcs check_dev ; handle device only string
317 ; string in "X:xxx" format
318 colon1: lda #3 ; max. length if device only ("X:")
320 bcc do_open_nd ; string is longer -> contains filename
322 ; get device and search it in fd table
325 lda (ptr4),y ; get device id
327 ldx #(MAX_FD_VAL*4) - ft_entrylen
329 cmp fd_table+ft_iocb,x ; is entry valid?
330 beq srch2 ; no, skip this entry
332 cmp fd_table+ft_dev,x
340 ; not found, open new iocb
343 ; helper for branch out of range
346 ; found device in table, check device number (e.g R0 - R3)
347 fnddev: lda fd_table+ft_flag,x
349 cmp tmp2 ; contains devnum
350 bne srch2 ; different device numbers
352 ; found existing open iocb with same device
357 inc fd_table+ft_usa,x ; increment usage counter
358 jsr fdt_to_fdi ; get new index
359 bcs noslot1 ; no one available
360 sta tmp2 ; return index
362 ; clean up and go home
374 lsr a ; set C as needed