2 ; Christian Groessler, May-2000
4 ; fd indirection table & helper functions
9 .importzp tmp1,tmp2,tmp3,ptr4,sp
10 .import fd_table,fd_index
19 ; gets fd in ax, decrements usage counter
20 ; return iocb index in X
21 ; return N bit set for invalid fd
22 ; return Z bit set if last user
23 ; all registers destroyed
31 lda fd_index,x ; get index
34 sta fd_index,x ; clear entry
36 asl a ; create index into fd table
40 cmp fd_table+ft_iocb,x ; entry in use?
41 beq inval ; no, return error
42 lda fd_table+ft_usa,x ; get usage counter
43 beq ok_notlast ; 0? (shouldn't happen)
45 sbc #1 ; decr usage counter
50 lda fd_table+ft_iocb,x ; get iocb
55 sta fd_table+ft_iocb,y ; clear table entry
56 lda fd_table+ft_flag,y
57 and #16 ; opened by app?
58 eor #16 ; return set Z if yes
65 .endproc ; fdtoiocb_down
67 inval: ldx #$ff ; sets N
71 ; clear iocb except for ICHID field
72 ; expects X to be index to IOCB (0,$10,$20,etc.)
73 ; all registers destroyed
77 inx ; don't clear ICHID
89 ; decrements usage counter for fd
90 ; if 0 reached, it's marked as unused
91 ; get fd index in tmp2
92 ; Y register preserved
97 bcs ret ; invalid index, do nothing
104 asl a ; create index into fd table
108 cmp fd_table+ft_iocb,x ; entry in use?
109 beq ret ; no, do nothing
110 lda fd_table+ft_usa,x ; get usage counter
111 beq ret ; 0? should not happen
113 sbc #1 ; decrement by one
114 sta fd_table+ft_usa,x
116 lda #$ff ; 0, table entry unused now
117 sta fd_table+ft_iocb,x ; clear table entry
120 .endproc ; fddecusage
125 ; called from open() function
126 ; finds a fd to use for an open request
127 ; checks whether it's a device or file (file: characters follow the ':')
128 ; files always get an exclusive slot
129 ; for devices it is checked whether the device is already open, and if yes,
130 ; a link to this open device is returned
132 ; Calling parameters:
133 ; tmp3 - length of filename + 1
134 ; AX - points to filename
135 ; Y - iocb to use (if we need a new open)
137 ; tmp2 - fd num ($ff and C=0 in case of error - no free slot)
138 ; C - 0/1 for no open needed/open should be performed
139 ; all registers preserved!
178 ; ptr4 points to filename
188 ; no colon there!? OK, then we use a fresh iocb....
189 ; return error here? no, the subsequent open call should fail
191 do_open_nd: ; do open and don't remember device
196 sta tmp1 ; set flag to return 'open needed' : C = 1
201 cmp fd_table,x ; check ft_iocb field for $ff
202 beq freefnd ; found a free slot
207 cmp #(MAX_FD_VAL*4)+ft_iocb ; end of table reached?
210 ; error: no free slot found
212 stx tmp1 ; return with C = 0
214 stx tmp2 ; iocb: $ff marks error
220 sbc #ft_iocb ; normalize
226 bit tmp1 ; remember device?
228 lda #0 ; no, put 0 in field
232 lda (sp),y ; get device
233 l2: sta fd_table+ft_dev,x ; set device
235 sta fd_table+ft_usa,x ; set usage counter
237 sta fd_table+ft_iocb,x ; set iocb index
239 and #7 ; device number is 3 bits
240 ora #16 ; indicated a fd actively opened by the app
241 sta fd_table+ft_flag,x
243 jsr fdt_to_fdi ; get new index
244 noslot1:bcs noslot ; no one available (noslot1: helper label for branch out of range)
245 ;cmp #$ff ; no one available
246 ;beq noslot ;@@@ cleanup needed
247 sta tmp2 ; return index
250 ; string in "Xn:xxx" format
252 lda (ptr4),y ; get device number
257 sta tmp2 ; save it for speed later here also
258 lda #4 ; max. length if only device + number ("Xn:")
260 bcc do_open_nd ; string is longer -> contains filename
261 bcs check_dev ; handle device only string
263 ; string in "X:xxx" format
264 colon1: lda #3 ; max. length if device only ("X:")
266 bcc do_open_nd ; string is longer -> contains filename
268 ; get device and search it in fd table
271 lda (ptr4),y ; get device id
273 ldx #(MAX_FD_VAL*4) - ft_entrylen
275 cmp fd_table+ft_iocb,x ; is entry valid?
276 beq srch2 ; no, skip this entry
278 cmp fd_table+ft_dev,x
286 ; not found, open new iocb
289 ; found device in table, check device number (e.g R0 - R3)
290 fnddev: lda fd_table+ft_flag,x
292 cmp tmp2 ; contains devnum
293 bne srch2 ; different device numbers
295 ; found existing open iocb with same device
300 inc fd_table+ft_usa,x ; increment usage counter
301 jsr fdt_to_fdi ; get new index
302 bcs noslot1 ; no one available
303 sta tmp2 ; return index
305 ; clean up and go home
317 lsr a ; set C as needed