2 ; Christian Groessler, May-2000
4 ; fd indirection table & helper functions
9 .importzp tmp1,tmp2,tmp3,ptr4,sp
11 .import fd_table,fd_index
20 ; gets fd in ax, decrements usage counter
21 ; return iocb index in X
22 ; return N bit set for invalid fd
23 ; return Z bit set if last user
24 ; all registers destroyed
32 lda fd_index,x ; get index
35 sta fd_index,x ; clear entry
37 asl a ; create index into fd table
41 cmp fd_table+ft_iocb,x ; entry in use?
42 beq inval ; no, return error
43 lda fd_table+ft_usa,x ; get usage counter
46 sbc #1 ; decr usage counter
51 lda fd_table+ft_iocb,x ; get iocb
57 sta fd_table+ft_iocb,y ; clear table entry
67 inval: ldx #$ff ; sets N
72 ; return iocb index in X
73 ; return N bit set for invalid fd
74 ; all registers destroyed
83 asl a ; create index into fd table
87 cmp fd_table+ft_iocb,x ; entry in use?
88 beq inval ; no, return error
89 lda fd_table+ft_usa,x ; get usage counter
90 beq inval ; 0? should not happen
91 lda fd_table+ft_iocb,x ; get iocb
96 ; decrements usage counter for fd
97 ; if 0 reached, it's marked as unused
98 ; get fd index in tmp2
99 ; Y register preserved
104 bcs ret ; invalid index, do nothing
111 asl a ; create index into fd table
115 cmp fd_table+ft_iocb,x ; entry in use?
116 beq ret ; no, do nothing
117 lda fd_table+ft_usa,x ; get usage counter
118 beq ret ; 0? should not happen
120 sbc #1 ; decrement by one
121 sta fd_table+ft_usa,x
123 lda #$ff ; 0, table entry unused now
124 sta fd_table+ft_iocb,x ; clear table entry
131 ; called from open() function
132 ; finds a fd to use for an open request
133 ; checks whether it's a device or file (file: characters follow the ':')
134 ; files always get an exclusive slot
135 ; for devices it is checked whether the device is already open, and if yes,
136 ; a link to this open device is returned
138 ; Calling parameters:
139 ; tmp3 - length of filename + 1
140 ; AX - points to filename
141 ; Y - iocb to use (if we need a new open)
143 ; tmp2 - fd num ($ff and C=0 in case of error - no free slot)
144 ; C - 0/1 for no open needed/open should be performed
145 ; all registers preserved!
150 ; ptr4 - 3,4 (backup)
188 ; ptr4 points to filename
198 ; no colon there!? OK, then we use a fresh iocb....
199 ; return error here? no, the subsequent open call should fail
201 do_open_nd: ; do open and don't remember device
206 sta tmp1 ; set flag to return 'open needed' : C = 1
212 beq freefnd ; found a free slot
217 cmp #(MAX_FD_VAL*4)+ft_iocb ; end of table reached?
220 ; error: no free slot found
222 stx tmp1 ; return with C = 0
224 stx tmp2 ; iocb: $ff marks error
230 sbc #ft_iocb ; normalize
236 bit tmp1 ; remember device?
238 lda #0 ; no, put 0 in field
242 lda (sp),y ; get device
243 l2: sta fd_table+ft_dev,x ; set device
245 sta fd_table+ft_usa,x ; set usage counter
247 sta fd_table+ft_iocb,x ; set iocb index
250 sta fd_table+ft_flag,x
252 jsr fdt_to_fdi ; get new index
253 bcs noslot ; no one available
254 ;cmp #$ff ; no one available
255 ;beq noslot ;@@@ cleanup needed
256 sta tmp2 ; return index
259 ; string in "Xn:xxx" format
261 lda (ptr4),y ; get device number
266 sta tmp2 ; save it for speed later here also
267 lda #4 ; max. length if only device + number ("Xn:")
269 bcc do_open_nd ; string is longer -> contains filename
270 bcs check_dev ; handle device only string
272 ; string in "X:xxx" format
273 colon1: lda #3 ; max. length if device only ("X:")
275 bcc do_open_nd ; string is longer -> contains filename
277 ; get device and search it in fd table
280 lda (ptr4),y ; get device id
282 ldx #(MAX_FD_VAL*4) - ft_entrylen
284 cmp fd_table+ft_iocb,x ; is entry valid?
285 beq srch2 ; no, skip this entry
287 cmp fd_table+ft_dev,x
295 ; not found, open new iocb
298 ; helper for branch out of range
301 ; found device in table, check device number (e.g R0 - R3)
302 fnddev: lda fd_table+ft_flag,x
304 cmp tmp2 ; contains devnum
305 bne srch2 ; different device numbers
307 ; found existing open iocb with same device
312 inc fd_table+ft_usa,x ; increment usage counter
313 jsr fdt_to_fdi ; get new index
314 bcs noslot1 ; no one available
315 sta tmp2 ; return index
317 ; clean up and go home
329 lsr a ; set C as needed