summaryrefslogtreecommitdiff
path: root/v2.0/source/FAT.ASM
blob: b1a4863f31b643b5b0df820c33958492c5d288ec (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
;
; FAT operations for MSDOS
;

INCLUDE DOSSEG.ASM

CODE    SEGMENT BYTE PUBLIC  'CODE'
        ASSUME  SS:DOSGROUP,CS:DOSGROUP

.xlist
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
.cref
.list

TITLE   FAT - FAT maintenance routines
NAME    FAT

        i_need  CURBUF,DWORD
        i_need  CLUSSPLIT,BYTE
        i_need  CLUSSAVE,WORD
        i_need  CLUSSEC,WORD
        i_need  THISDRV,BYTE
        i_need  DEVCALL,BYTE
        i_need  CALLMED,BYTE
        i_need  CALLRBYT,BYTE
        i_need  BUFFHEAD,DWORD
        i_need  CALLXAD,DWORD
        i_need  CALLBPB,DWORD

SUBTTL UNPACK -- UNPACK FAT ENTRIES
PAGE

ASSUME  SS:DOSGROUP
        procedure   UNPACK,NEAR
ASSUME  DS:DOSGROUP,ES:NOTHING

; Inputs:
;       BX = Cluster number
;       ES:BP = Base of drive parameters
; Outputs:
;       DI = Contents of FAT for given cluster
;       Zero set means DI=0 (free cluster)
; SI Destroyed, No other registers affected. Fatal error if cluster too big.

        CMP     BX,ES:[BP.dpb_max_cluster]
        JA      HURTFAT
        CALL    MAPCLUSTER
ASSUME  DS:NOTHING
        MOV     DI,[DI]
        JNC     HAVCLUS
        PUSH    CX
        MOV     CL,4
        SHR     DI,CL
        POP     CX
        STC
HAVCLUS:
        AND     DI,0FFFH
        PUSH    SS
        POP     DS
        return

HURTFAT:
        PUSH    AX
        MOV     AH,80H          ; Signal Bad FAT to INT int_fatal_abort handler
        MOV     DI,0FFFH        ; In case INT int_fatal_abort returns (it shouldn't)
        invoke  FATAL
        POP     AX              ; Try to ignore bad FAT
        return
UNPACK  ENDP

SUBTTL PACK -- PACK FAT ENTRIES
PAGE
        procedure   PACK,NEAR
ASSUME  DS:DOSGROUP,ES:NOTHING

; Inputs:
;       BX = Cluster number
;       DX = Data
;       ES:BP = Pointer to drive DPB
; Outputs:
;       The data is stored in the FAT at the given cluster.
;       SI,DX,DI all destroyed
;       No other registers affected

        CALL    MAPCLUSTER
ASSUME  DS:NOTHING
        MOV     SI,[DI]
        JNC     ALIGNED
        PUSH    CX
        MOV     CL,4
        SHL     DX,CL
        POP     CX
        AND     SI,0FH
        JMP     SHORT PACKIN
ALIGNED:
        AND     SI,0F000H
PACKIN:
        OR      SI,DX
        MOV     [DI],SI
        LDS     SI,[CURBUF]
        MOV     [SI.BUFDIRTY],1
        CMP     BYTE PTR [CLUSSPLIT],0
        PUSH    SS
        POP     DS
ASSUME  DS:DOSGROUP
        retz
        PUSH    AX
        PUSH    BX
        PUSH    CX
        MOV     AX,[CLUSSAVE]
        MOV     DS,WORD PTR [CURBUF+2]
ASSUME  DS:NOTHING
        ADD     SI,BUFINSIZ
        MOV     [SI],AH
        PUSH    SS
        POP     DS
ASSUME  DS:DOSGROUP
        PUSH    AX
        MOV     DX,[CLUSSEC]
        MOV     SI,1
        XOR     AL,AL
        invoke  GETBUFFRB
        LDS     DI,[CURBUF]
ASSUME  DS:NOTHING
        MOV     [DI.BUFDIRTY],1
        ADD     DI,BUFINSIZ
        DEC     DI
        ADD     DI,ES:[BP.dpb_sector_size]
        POP     AX
        MOV     [DI],AL
        PUSH    SS
        POP     DS
        POP     CX
        POP     BX
        POP     AX
        return
PACK    ENDP

SUBTTL MAPCLUSTER - BUFFER A FAT SECTOR
PAGE
        procedure   MAPCLUSTER,NEAR
ASSUME  DS:DOSGROUP,ES:NOTHING

; Inputs:
;       ES:BP Points to DPB
;       BX Is cluster number
; Function:
;       Get a pointer to the cluster
; Outputs:
;       DS:DI Points to contents of FAT for given cluster
;       DS:SI Points to start of buffer
;       Carry set if cluster data is in high 12 bits of word
; No other registers effected

        MOV     BYTE PTR [CLUSSPLIT],0
        PUSH    AX
        PUSH    BX
        PUSH    CX
        PUSH    DX
        MOV     AX,BX
        SHR     AX,1
        ADD     AX,BX
        XOR     DX,DX
        MOV     CX,ES:[BP.dpb_sector_size]
        DIV     CX              ; AX is FAT sector # DX is sector index
        ADD     AX,ES:[BP.dpb_first_FAT]
        DEC     CX
        PUSH    AX
        PUSH    DX
        PUSH    CX
        MOV     DX,AX
        XOR     AL,AL
        MOV     SI,1
        invoke  GETBUFFRB
        LDS     SI,[CURBUF]
ASSUME  DS:NOTHING
        LEA     DI,[SI.BufInSiz]
        POP     CX
        POP     AX
        POP     DX
        ADD     DI,AX
        CMP     AX,CX
        JNZ     MAPRET
        MOV     AL,[DI]
        PUSH    SS
        POP     DS
ASSUME  DS:DOSGROUP
        INC     BYTE PTR [CLUSSPLIT]
        MOV     BYTE PTR [CLUSSAVE],AL
        MOV     [CLUSSEC],DX
        INC     DX
        XOR     AL,AL
        MOV     SI,1
        invoke  GETBUFFRB
        LDS     SI,[CURBUF]
ASSUME  DS:NOTHING
        LEA     DI,[SI.BufInSiz]
        MOV     AL,[DI]
        PUSH    SS
        POP     DS
ASSUME  DS:DOSGROUP
        MOV     BYTE PTR [CLUSSAVE+1],AL
        MOV     DI,OFFSET DOSGROUP:CLUSSAVE
MAPRET:
        POP     DX
        POP     CX
        POP     BX
        MOV     AX,BX
        SHR     AX,1
        POP     AX
        return
MAPCLUSTER  ENDP

SUBTTL FATREAD -- CHECK DRIVE GET FAT
PAGE
ASSUME  DS:DOSGROUP,ES:NOTHING

        procedure   FAT_operation,NEAR
FATERR:
        AND     DI,STECODE      ; Put error code in DI
        MOV     AH,2            ; While trying to read FAT
        MOV     AL,BYTE PTR [THISDRV]    ; Tell which drive
        invoke  FATAL1

        entry   FATREAD
ASSUME  DS:DOSGROUP,ES:NOTHING

; Function:
;       If disk may have been changed, FAT is read in and buffers are
;       flagged invalid. If not, no action is taken.
; Outputs:
;       ES:BP = Base of drive parameters
; All other registers destroyed

        MOV     AL,BYTE PTR [THISDRV]
        invoke  GETBP
        MOV     AL,DMEDHL
        MOV     AH,ES:[BP.dpb_UNIT]
        MOV     WORD PTR [DEVCALL],AX
        MOV     BYTE PTR [DEVCALL.REQFUNC],DEVMDCH
        MOV     [DEVCALL.REQSTAT],0
        MOV     AL,ES:[BP.dpb_media]
        MOV     BYTE PTR [CALLMED],AL
        PUSH    ES
        PUSH    DS
        MOV     BX,OFFSET DOSGROUP:DEVCALL
        LDS     SI,ES:[BP.dpb_driver_addr]       ; DS:SI Points to device header
ASSUME  DS:NOTHING
        POP     ES                      ; ES:BX Points to call header
        invoke  DEVIOCALL2
        PUSH    SS
        POP     DS
ASSUME  DS:DOSGROUP
        POP     ES                      ; Restore ES:BP
        MOV     DI,[DEVCALL.REQSTAT]
        TEST    DI,STERR
        JNZ     FATERR
        XOR     AH,AH
        XCHG    AH,ES:[BP.dpb_first_access]      ; Reset dpb_first_access
        MOV     AL,BYTE PTR [THISDRV]    ; Use physical unit number
        OR      AH,BYTE PTR [CALLRBYT]
        JS      NEWDSK          ; new disk or first access?
        JZ      CHKBUFFDIRT
        return                  ; If Media not changed
CHKBUFFDIRT:
        INC     AH              ; Here if ?Media..Check buffers
        LDS     DI,[BUFFHEAD]
ASSUME  DS:NOTHING
NBUFFER:                        ; Look for dirty buffers
        CMP     AX,WORD PTR [DI.BUFDRV]
        retz                    ; There is a dirty buffer, assume Media OK
        LDS     DI,[DI.NEXTBUF]
        CMP     DI,-1
        JNZ     NBUFFER
; If no dirty buffers, assume Media changed
NEWDSK:
        invoke  SETVISIT
NXBUFFER:
        MOV     [DI.VISIT],1
        CMP     AL,[DI.BUFDRV]       ; For this drive?
        JNZ     SKPBUFF
        MOV     WORD PTR [DI.BUFDRV],00FFH  ; Free up buffer
        invoke  SCANPLACE
SKPBUFF:
        invoke  SKIPVISIT
        JNZ     NXBUFFER
        LDS     DI,ES:[BP.dpb_driver_addr]
        TEST    [DI.SDEVATT],ISFATBYDEV
        JNZ     GETFREEBUF
        context DS
        MOV     BX,2
        CALL    UNPACK                  ; Read the first FAT sector into  CURBUF
        LDS     DI,[CURBUF]
        JMP     SHORT GOTGETBUF
GETFREEBUF:
ASSUME  DS:NOTHING
        PUSH    ES                      ; Get a free buffer for BIOS to use
        PUSH    BP
        LDS     DI,[BUFFHEAD]
        invoke  BUFWRITE
        POP     BP
        POP     ES
GOTGETBUF:
        ADD     DI,BUFINSIZ
        MOV     WORD PTR [CALLXAD+2],DS
        PUSH    SS
        POP     DS
ASSUME  DS:DOSGROUP
        MOV     WORD PTR [CALLXAD],DI
        MOV     AL,DBPBHL
        MOV     AH,BYTE PTR ES:[BP.dpb_UNIT]
        MOV     WORD PTR [DEVCALL],AX
        MOV     BYTE PTR [DEVCALL.REQFUNC],DEVBPB
        MOV     [DEVCALL.REQSTAT],0
        MOV     AL,BYTE PTR ES:[BP.dpb_media]
        MOV     [CALLMED],AL
        PUSH    ES
        PUSH    DS
        PUSH    WORD PTR ES:[BP.dpb_driver_addr+2]
        PUSH    WORD PTR ES:[BP.dpb_driver_addr]
        MOV     BX,OFFSET DOSGROUP:DEVCALL
        POP     SI
        POP     DS                      ; DS:SI Points to device header
ASSUME  DS:NOTHING
        POP     ES                      ; ES:BX Points to call header
        invoke  DEVIOCALL2
        POP     ES                      ; Restore ES:BP
        PUSH    SS
        POP     DS
ASSUME  DS:DOSGROUP
        MOV     DI,[DEVCALL.REQSTAT]
        TEST    DI,STERR
        JNZ     FATERRJ
        MOV     AL,BYTE PTR ES:[BP.dpb_media]
        LDS     SI,[CALLBPB]
ASSUME  DS:NOTHING
        CMP     AL,BYTE PTR [SI.BPMEDIA]
        JZ      DPBOK
        invoke  $SETDPB
        LDS     DI,[CALLXAD]            ; Get back buffer pointer
        MOV     AL,BYTE PTR ES:[BP.dpb_FAT_count]
        MOV     AH,BYTE PTR ES:[BP.dpb_FAT_size]
        MOV     WORD PTR [DI.BUFWRTCNT-BUFINSIZ],AX   ;Correct buffer info
DPBOK:
        context ds
        MOV     AX,-1
        TEST    ES:[BP.dpb_current_dir],AX
        retz                            ; If root, leave as root
        MOV     ES:[BP.dpb_current_dir],AX    ; Path may be bad, mark invalid
        return

FATERRJ: JMP    FATERR

FAT_operation   ENDP

do_ext

CODE    ENDS
    END