OpenCores
URL https://opencores.org/ocsvn/rtf65002/rtf65002/trunk

Subversion Repositories rtf65002

[/] [rtf65002/] [trunk/] [software/] [asm/] [DOS.asm] - Blame information for rev 40

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 40 robfinch
;==============================================================================
2
;        __
3
;   \\__/ o\    (C) 2014  Robert Finch, Stratford
4
;    \  __ /    All rights reserved.
5
;     \/_//     robfinch@opencores.org
6
;       ||
7
;
8
;
9
; This source file is free software: you can redistribute it and/or modify
10
; it under the terms of the GNU Lesser General Public License as published
11
; by the Free Software Foundation, either version 3 of the License, or
12
; (at your option) any later version.
13
;
14
; This source file is distributed in the hope that it will be useful,
15
; but WITHOUT ANY WARRANTY; without even the implied warranty of
16
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
; GNU General Public License for more details.
18
;
19
; You should have received a copy of the GNU General Public License
20
; along with this program.  If not, see .
21
;
22
; DOS.asm
23
;       Disk operating system code
24
;==============================================================================
25
;
26
        cpu             rtf65002
27
; 64GB card
28
; 36 address bits
29
; 9 bits for 512 byte block size
30
; 27 bits for block number
31
; 4kB cluster size = 3 bits
32
; 24 bit cluster number
33
; 2MB bitmap of allocated clusters ( contained in 512 clusters)
34
; 512 super bitmap bits
35
;
36
NO_DEV          EQU             -1
37
READING         EQU             'R'
38
WRITING         EQU             'W'
39
DIRTY           EQU             'D'
40
CLEAN           EQU             'C'
41
NORMAL          EQU             0
42
 
43
ONE_SHOT        EQU             1
44
WRITE_IMMED     EQU             2
45
ZUPER_BLOCK     EQU             2       ; write superblock immediately
46
SUPER_BLOCK_NUM         EQU             1       ; should calculate this
47
;
48
; Note that structure offsets are word offsets
49
; The super block always occupies a whole block for simplicity even though
50
; it's mostly unused.
51
;
52
; STRUCT SUPER_BLOCK
53
;
54
s_inodes_count                  EQU             0
55
s_blocks_count                  EQU             1
56
s_r_blocks_count                EQU             2
57
s_free_blocks_count             EQU             3
58
s_free_inodes_count             EQU             4
59
s_first_data_block              EQU             5
60
s_log_block_size                EQU             6
61
s_log_frag_size                 EQU             7
62
s_blocks_per_group              EQU             8
63
s_frags_per_group               EQU             9
64
s_inodes_per_group              EQU             10
65
s_pad                                   EQU             11
66
s_mtime                                 EQU             12
67
s_wtime                                 EQU             14
68
s_mnt_cnt                               EQU             16
69
s_max_mnt_cnt                   EQU             17
70
s_magic                                 EQU             18
71
s_state                                 EQU             19
72
s_errors                                EQU             20
73
s_minor_rev_level               EQU             21
74
s_lastcheck                             EQU             22
75
s_checkinterval                 EQU             24
76
s_creator_os                    EQU             26
77
s_rev_level                             EQU             27
78
s_def_res_uid                   EQU             28
79
s_def_res_gid                   EQU             29
80
s_inode_size                    EQU             31
81
s_volume_name                   EQU             40
82
; In memory management fields
83
s_inodes_per_block              EQU             124
84
s_dev                                   EQU             125
85
s_dirty                                 EQU             126
86
SUPERBUF_SIZE                   EQU             128
87
 
88
; STRUCT INODE
89
;
90
i_mode          EQU             0
91
i_uid           EQU             1
92
i_size          EQU             2
93
i_gid           EQU             3
94
i_atime         EQU             4
95
i_ctime         EQU             6
96
i_mtime         EQU             8
97
i_dtime         EQU             10
98
i_links_count   EQU     12
99
i_blocks        EQU             13
100
i_flags         EQU             14
101
i_osd1          EQU             15
102
INODE_P0        EQU             16
103
INODE_P1        EQU             INODE_P0+1
104
INODE_P2        EQU             INODE_P1+1
105
INODE_P3        EQU             INODE_P2+1
106
INODE_P4        EQU             INODE_P3+1
107
INODE_P5        EQU             INODE_P4+1
108
INODE_P6        EQU             INODE_P5+1
109
INODE_P7        EQU             INODE_P6+1
110
INODE_P8        EQU             INODE_P7+1
111
INODE_P9        EQU             INODE_P8+1
112
INODE_P10       EQU             INODE_P9+1
113
INODE_P11       EQU             INODE_P10+1
114
INODE_IP        EQU             INODE_P11+1             ; indirect pointer
115
INODE_IIP       EQU             INODE_IP+1              ; double indirect pointer
116
INODE_IIIP      EQU             INODE_IIP+1             ; triple indirect pointer
117
i_generation    EQU             31
118
i_file_acl              EQU             32
119
i_dir_acl               EQU             33
120
i_faddr                 EQU             34
121
i_osd2                  EQU             35
122
INODE_DEV       EQU             37
123
INODE_INUM      EQU             38
124
INODE_ICOUNT    EQU     39
125
INODE_DIRTY     EQU             40
126
INODE_SIZE      EQU             41                              ; 41 words
127
 
128
; STRUCT BGDESC
129
;
130
bg_block_bitmap                 EQU             0
131
bg_inode_bitmap                 EQU             1
132
bg_inode_table                  EQU             2
133
bg_free_blocks_count    EQU             3
134
bg_free_inodes_count    EQU             4
135
bg_used_dirs_count              EQU             5
136
bg_reserved                             EQU             6
137
BGDESC_SIZE                             EQU             8
138
bg_dev                                  EQU             9
139
bg_group_num                    EQU             10
140
bg_dirty                                EQU             11
141
BGD_BUFSIZE                             EQU             12
142
 
143
; STRUCT DIRENTRY
144
; Directory entries are 64 bytes
145
; 28 character file name
146
;  4 byte i-node number
147
;
148
DE_NAME                 EQU             0
149
DE_TYPE                 EQU             14
150
DE_INODE                EQU             15
151
DE_SIZE                 EQU             16              ; size in words
152
 
153
; Structure of a disk buffer
154
; The disk buffer contains a number of fields for file system management
155
; followed by a payload area containing disk block contents.
156
;
157
; STRUCT BUF
158
;
159
b_dev                   EQU             0                ; device
160
b_blocknum      EQU             1               ; disk block number
161
b_count         EQU             2               ; reference count
162
b_dirty         EQU             3               ; buffer has been altered
163
b_next          EQU             4               ; next buffer on LRU list
164
b_prev          EQU             5
165
b_hash          EQU             6               ; pointer to hashed buffer
166
b_data          EQU             8               ; beginning of data area
167
BUF_INODE               EQU             8
168
BUF_SIZE                EQU             b_data+256
169
 
170
NR_BUFS                 EQU             8192    ; number of disk buffers in the system (must be a power of 2)
171
NR_BUF_HASH             EQU             1024    ; number of hash chains (must be a power of two)
172
NR_BGD_BUFS             EQU             1024
173
BT_DATA_BLOCK   EQU             0
174
BT_SUPERBLOCK   EQU             1
175
 
176
IAM_BUF_SIZE    EQU             1032    ; 1024 + 8
177
CAM_SUPERMAP_SIZE       EQU             128
178
 
179
; $00000000 super block
180
; $00000001 iam super map (512 bits)
181
; $00000002 inode allocation map (128kB)
182
; $00000102 inode array (1M x 128 byte entries)
183
; $00040102 cam super bitmap bits (512 bits)
184
; $00040103 cluster allocation map (2MB)
185
; $00041103 start of data clusters
186
 
187
; Approximately 12MB (10% of memory) is allowed for the file system variables.
188
; Most of the space 8MB+ is alloted to disk buffers.
189
 
190
DOS_DATA                EQU             0x00300000                                      ; start address of DOS data area
191
super_bufs              EQU             DOS_DATA
192
super_bufs_end  EQU             super_bufs + SUPERBUF_SIZE * 32
193
BGD_bufs                EQU             super_bufs_end
194
BGD_bufs_end    EQU             BGD_bufs + NR_BGD_BUFS * BGD_BUFSIZE    ; 32 kB = 1024 descriptors
195
iam_bufs                EQU             BGD_bufs_end
196
inode_array             EQU             iam_bufs + IAM_BUF_SIZE * 32    ; 129 kB worth
197
inode_array_end EQU             inode_array + INODE_SIZE * 256  ; 41kB worth (256 open files)
198
data_bufs               EQU             0x00320000                      ; room for 8192 buffers
199
data_bufs_end   EQU             data_bufs + BUF_SIZE * NR_BUFS
200
buf_hash                EQU             data_bufs_end
201
buf_hash_end    EQU             buf_hash + NR_BUF_HASH
202
superbuf_dump   EQU             buf_hash_end + 1
203
bufs_in_use             EQU             superbuf_dump + 1
204
blockbuf_dump   EQU             bufs_in_use + 1
205
disk_size               EQU             blockbuf_dump + 1
206
block_size              EQU             disk_size + 1
207
fs_start_block  EQU             block_size + 1
208
bgdt_valid              EQU             fs_start_block + 1
209
front                   EQU             bgdt_valid + 1
210
rear                    EQU             front + 1
211
panicking               EQU             rear + 1
212
fs_active               EQU             panicking + 1
213
DOS_DATA_ENDS   EQU             0x0540000
214
 
215
; number of buffers for the inode allocation map
216
; number of buffers for inode array
217
; Total caching to be 12MB
218
; 9MB reserved for data block caching
219
; 3MB reserved for file management caching
220
 
221
inode_bufs      EQU             DOS_DATA        ; 128B x 256 bufs
222
iam_buf         EQU             0x01FBE800
223
sector_buf      EQU             0x01FBEC00
224
 
225
        org             $FFFFD800
226
 
227
;------------------------------------------------------------------------------
228
; Initialize the file system.
229
;------------------------------------------------------------------------------
230
;
231
init_fs:
232
        stz             bgdt_valid
233
        jsr             init_superbufs
234
        jsr             init_databufs
235
        lda             #'A'
236
        sta             fs_active
237
        lda             #4
238
        ldx             #0                              ; no flags (em =0 native mode)
239
        ldy             #fs_clean
240
        jsr             StartTask
241
        rts
242
 
243
;------------------------------------------------------------------------------
244
; The file system offset is the offset in disk sectors to the start
245
; of the file system. It may be desireable to reserve a number of
246
; disk sectors prior to the actual file system start.
247
;------------------------------------------------------------------------------
248
;
249
get_filesystem_offset:
250
        lda             #2
251
        rts
252
 
253
;------------------------------------------------------------------------------
254
; Initialize super block buffer array.
255
;------------------------------------------------------------------------------
256
;
257
init_superbufs:
258
        pha
259
        phx
260
        ldx             #super_bufs
261
isb1:
262
        lda             #NO_DEV
263
        sta             s_dev,x
264
        lda             #CLEAN
265
        sta             s_dirty,x
266
        add             r2,r2,#SUPERBUF_SIZE
267
        cpx             #super_bufs_end
268
        bltu    isb1
269
        plx
270
        pla
271
        rts
272
 
273
init_databufs:
274
        pha
275
        phx
276
        phy
277
        stz             bufs_in_use
278
        ldx             #data_bufs
279
        stx             front
280
        lda             #data_bufs_end
281
        sub             #BUF_SIZE
282
        sta             rear
283
idb1:
284
        lda             #NO_DEV
285
        sta             b_dev,x
286
        lda             #CLEAN
287
        sta             b_dirty,x
288
        sub             r3,r2,#BUF_SIZE
289
        sty             b_prev,x
290
        add             r3,r2,#BUF_SIZE
291
        sty             b_next,x
292
        sty             b_hash,x
293
        tyx
294
        cpx             #data_bufs_end
295
        bltu    idb1
296
        ldx             front
297
        stz             b_prev,x
298
        stx             buf_hash                        ; buf_hash[0] = front
299
        ldx             rear
300
        stz             b_next,x
301
        ply
302
        plx
303
        pla
304
        rts
305
 
306
;------------------------------------------------------------------------------
307
; Parameters:
308
;       r1 = device
309
; Returns:
310
;       r1 = block size in bytes
311
;------------------------------------------------------------------------------
312
get_block_size:
313
        phx
314
        phy
315
        jsr             get_super
316
        tax
317
        ldy             s_log_block_size,x
318
        lda             #1024
319
        asl             r1,r1,r3
320
        ply
321
        plx
322
        rts
323
 
324
get_log_block_size:
325
        phx
326
        jsr             get_super
327
        tax
328
        lda             s_log_block_size,x
329
        plx
330
        rts
331
 
332
get_inode_size:
333
        phx
334
        jsr             get_super
335
        tax
336
        lda             s_inode_size,x
337
        plx
338
        rts
339
 
340
get_inodes_per_group:
341
        phx
342
        jsr             get_super
343
        tax
344
        lda             s_inodes_per_group,x
345
        plx
346
        rts
347
 
348
; inodes per block does not need to be a power of 2
349
;
350
get_inodes_per_block:
351
        phx
352
        pha
353
        jsr             get_block_size
354
        tax
355
        pla
356
        jsr             get_inode_size
357
        div             r1,r2,r1
358
        plx
359
        rts
360
 
361
get_bgd_per_block:
362
        jsr             get_block_size
363
        lsr             ; BGD size is 32 bytes
364
        lsr
365
        lsr
366
        lsr
367
        lsr
368
        rts
369
 
370
get_bits_per_block:
371
        jsr             get_block_size
372
        asl
373
        asl
374
        asl
375
        rts
376
 
377
get_num_bgd:
378
        phx
379
        jsr             get_super
380
        lda             s_blocks_count,r1
381
        tax
382
        jsr             get_bits_per_block
383
        div             r1,r2,r1
384
        plx
385
        rts
386
 
387
;==============================================================================
388
; INODE code
389
;==============================================================================
390
;------------------------------------------------------------------------------
391
; Free an inode.
392
;
393
; Parameters:
394
;       r1 = device number
395
;       r2 = inode number
396
;------------------------------------------------------------------------------
397
;
398
free_inode:
399
        pha
400
        phx
401
        phy
402
        push    r4
403
        push    r5
404
        push    r7
405
        push    r8
406
        push    r9
407
        ld              r7,r1           ; r7 = device number
408
        jsr             get_inodes_per_group
409
        div             r4,r2,r1        ; r4 = group number of inode
410
        mod             r5,r2,r1        ; r5 = group index
411
        ld              r1,r7
412
        ld              r2,r4
413
        jsr             get_bgdt_entry
414
        ld              r9,r1           ; r9 = pointer to BGDesc
415
        ld              r1,r7
416
        ld              r2,bg_inode_bitmap,r9
417
        jsr             get_block       ; get the bitmap block
418
        ld              r8,r1           ; r8 = bitmap block
419
        ld              r1,r5
420
        bmt             b_data,r8       ; is the inode already free ?
421
        beq             fi1
422
        bmc             b_data,r8
423
        inc             bg_free_inodes_count,r9
424
        lda             #DIRTY
425
        sta             bg_dirty,r9
426
        jsr             get_super
427
        tax
428
        inc             s_free_inodes_count,x
429
        lda             #DIRTY
430
        sta             s_dirty,x
431
        sta             b_dirty,r8
432
        txy
433
        jsr             get_datetime
434
        stx             s_mtime,y
435
        sta             s_mtime+1,y
436
fi1:
437
        pop             r9
438
        pop             r8
439
        pop             r7
440
        pop             r5
441
        pop             r4
442
        ply
443
        plx
444
        pla
445
        rts
446
 
447
;------------------------------------------------------------------------------
448
; Allocate an inode
449
; This is called when a file or directory is created. The routine allocates
450
; an inode on disk, then gets an inode buffer.
451
;
452
; Parameters:
453
;       r1 = device number
454
;       r2 = mode bits
455
; Returns:
456
;       r1 = pointer to inode buffer
457
;------------------------------------------------------------------------------
458
;
459
alloc_inode:
460
        phx
461
        phy
462
        push    r4
463
        push    r7
464
        push    r8
465
        push    r9
466
        push    r10
467
        push    r11
468
; search the super match for a block with available inode
469
        lda             #0                              ; start at bit zero
470
        ld              r7,r1
471
        ld              r8,r2
472
        jsr             get_num_bgd
473
        tay
474
        jsr             get_inodes_per_block
475
        ld              r9,r1
476
        ld              r2,#0                   ; start with group #0
477
alin2:
478
        ld              r1,r7
479
        jsr             get_bgdt_entry
480
        ld              r4,r1
481
        lda             bg_free_inodes_count,r4
482
        bne             alin3
483
        inx
484
        dey
485
        bne             alin2
486
        ld              r1,r7
487
        jsr             dos_msg
488
        db              "Out of inodes on device ",0
489
alin7:
490
        pop             r11
491
        pop             r10
492
        pop             r9
493
        pop             r8
494
        pop             r7
495
        pop             r4
496
        ply
497
        plx
498
        lda             #0
499
        rts
500
alin3:
501
        ld              r1,r7
502
        ld              r10,r2                                  ; r10 = bgd entry number
503
        ldx             bg_inode_bitmap,r4
504
        ldy             #NORMAL
505
        jsr             get_block
506
        tax
507
        ld              r3,r9                                   ; r3 = indoes per block
508
        lda             #0
509
alin5:
510
        bmt             b_data,x
511
        beq             alin4
512
        ina
513
        dey
514
        bne             alin5
515
alin4:
516
        bms             b_data,x                                ; mark inode allocated
517
        ld              r5,r1                                   ; r5 = inode number within block
518
        dec             bg_free_inodes_count,r4
519
        mul             r11,r10,r9
520
        add             r5,r5,r11                                       ; r5 = inode number
521
        lda             #DIRTY
522
        sta             bg_dirty,r4
523
        jsr             get_super                               ; decrement free inode count in superblock
524
        dec             s_free_inodes_count,r1  ; and mark the superblock dirty
525
        tay
526
        lda             #DIRTY
527
        sta             s_dirty,y
528
        jsr             get_datetime
529
        stx             i_mtime,y
530
        sta             i_mtime+1,y
531
        ;
532
        ld              r1,r7                                   ; r1 = device number
533
        ld              r2,r5                                   ; r2 = inode number
534
        jsr             get_inode
535
        cmp             #0
536
        bne             alin6
537
        ld              r1,r7
538
        ld              r2,r5
539
        jsr             free_inode
540
        bra             alin7
541
alin6:
542
        st              r8,i_mode,r1
543
        stz             i_link_count,r1
544
        ; set uid,gid
545
        st              r7,i_dev,r1
546
        jsr             wipe_inode
547
        pop             r11
548
        pop             r10
549
        pop             r9
550
        pop             r8
551
        pop             r7
552
        pop             r4
553
        ply
554
        plx
555
        rts
556
 
557
;------------------------------------------------------------------------------
558
;------------------------------------------------------------------------------
559
;
560
wipe_inode:
561
        pha
562
        phx
563
        phy
564
        tay
565
        stz             i_size,y
566
        jsr             get_datetime
567
        stx             i_mtime,y
568
        sta             i_mtime+1,y
569
        lda             #DIRTY
570
        sta             i_dirty,y
571
        ldx             #15
572
win1:
573
        stz             INODE_P0,y
574
        iny
575
        dex
576
        bne             win1
577
        ply
578
        plx
579
        pla
580
        rts
581
 
582
;------------------------------------------------------------------------------
583
; Get an inode
584
;
585
; There are 256 inode buffers in the system which allows for 256 files
586
; to be open at once.
587
;
588
; Parameters:
589
;       r1 = device
590
;       r2 = inode number
591
; Returns:
592
;       r1 = pointer to inode buffer
593
;------------------------------------------------------------------------------
594
;
595
get_inode:
596
        ; push working registers
597
        push    r4                                              ; r4 = buffer number
598
        push    r5                                              ; r5 points to inode buffer
599
        push    r6
600
        push    r7
601
        ld              r7,#0                                   ; tracks the last free buffer
602
        ; Search the in use inode buffers for the one corresponding
603
        ; to the given device and node number. If found then increment
604
        ; the reference count and return a pointer to the buffer.
605
        ld              r4,#0
606
        ld              r5,#inode_bufs
607
gib4:
608
        ld              r6,INODE_ICOUNT,r5              ; check the count field to see if in use
609
        beq             gib3                                    ; branch if not in use
610
        cmp             INODE_DEV,r5                    ; now check for a matching device
611
        bne             gib5                                    ; branch if no match
612
        cpx             INODE_INUM,r5                   ; now check for matching node number
613
        bne             gib5
614
        inc             INODE_ICOUNT,r5                 ; increment count
615
        ld              r1,r5
616
        pop             r7
617
        pop             r6                                              ; pop working registers
618
        pop             r5
619
        pop             r4
620
        cmp             #0
621
        rts
622
 
623
gib3:
624
        ld              r7,r5                                   ; remember the free inode
625
gib5:
626
        add             r4,#1                                   ; increment buffer number
627
        add             r5,r5,#INODE_SIZE               ; size of an inode in words
628
        cmp             r4,#256                                 ; have we searched all buffers ?
629
        bltu    gib4
630
        cmp             r7,#0                                   ; test if free buffer found
631
        bne             gib6
632
        pop             r7
633
        pop             r6
634
        pop             r5
635
        pop             r4
636
        ld              r1,#0                                   ; no more inode buffers available
637
        rts
638
gib6:
639
        sta             INODE_DEV,r7
640
        stx             INODE_INUM,r7
641
        inc             INODE_ICOUNT,r7                 ; count field =1, was 0
642
        cmp             #NO_DEV                                 ; if there was a device number supplied
643
        beq             gib7                                    ; read the inode from the device
644
        ld              r1,r7
645
        ldx             #READING
646
        jsr             rw_inode
647
gib7:
648
        ld              r1,r7
649
        pop             r7                                              ; restore work registers
650
        pop             r6
651
        pop             r5
652
        pop             r4
653
        cmp             #0
654
        rts
655
 
656
;------------------------------------------------------------------------------
657
; Put inode
658
;
659
; Parameters:
660
;       r1 = pointer to inode buffer
661
;------------------------------------------------------------------------------
662
;
663
put_inode:
664
        cmp             #0                                      ; check for NULL pointer
665
        bne             pi1
666
        rts
667
pi1:
668
        phx
669
        tax
670
        dec             INODE_ICOUNT,x
671
        bne             pi2
672
        ; If the number of links to the inode is zero
673
        ; then deallocate the storage for the inode
674
pi2:
675
        lda             INODE_DIRTY,x
676
        cmp             #DIRTY
677
        bne             pi3
678
        txa                                                     ; acc = inode buffer pointer
679
        ldx             #WRITING
680
        jsr             rw_inode
681
pi3:
682
        plx
683
        rts
684
 
685
;------------------------------------------------------------------------------
686
; Parameters:
687
;       r1 = inode
688
;       r2 = R/W indicator
689
;------------------------------------------------------------------------------
690
rw_inode:
691
        pha
692
        phx
693
        phy
694
        push    r4
695
        push    r5
696
        push    r6
697
        push    r7
698
        ; get the super block for the device
699
        phx
700
        pha
701
        lda             INODE_DEV,r1
702
        jsr             get_inodes_per_group
703
        ld              r5,r1                   ; r4 = inodes per group
704
        pla
705
        ldx             INODE_INUM,r1
706
        div             r6,r2,r5                ; r6 = group number
707
        mod             r7,r2,r5                ; r7 = index into group
708
        lda             INODE_DEV,r1
709
        pha
710
        ld              r2,r6
711
        jsr             get_bgdt_entry
712
        lda             bg_inode_table,r1       ; get block address of inode table
713
        pha
714
        jsr             get_inodes_per_block
715
        div             r6,r7,r1
716
        mod             r8,r7,r1
717
        pla
718
        add             r2,r1,r6
719
        pla
720
        ldy             #NORMAL
721
        jsr             get_block
722
 
723
        ld              r7,r1                           ; r7 = pointer to block buffer
724
        pop             r4                                      ; r4 = inode
725
        add             r5,r1,#BUF_INODE        ; r5 = address of inode data
726
 
727
        mul             r6,r8,#INODE_SIZE
728
        add             r5,r5,r6
729
        pop             r6                                      ; r6 = R/W indicator
730
        cmp             r6,#READING
731
        bne             rwi1
732
        jsr             get_inode_size
733
        dea
734
        ld              r2,r5
735
        ld              r3,r4
736
        mvn
737
        bra             rwi2
738
rwi1:
739
        jsr             get_inode_size
740
        dea
741
        ld              r2,r4
742
        ld              r3,r5
743
        mvn
744
        jsr             get_datetime
745
        stx             INODE_WTIME,r4
746
        sta             INODE_WTIME+1,r4
747
        lda             #DIRTY
748
        sta             b_dirty,r7
749
rwi2:
750
        jsr             get_datetime
751
        stx             INODE_ATIME,r4
752
        sta             INODE_ATIME+1,r4
753
        ld              r1,r7                           ; r1 = pointer to block buffer
754
        ld              r2,#INODE_BLOCK
755
        jsr             put_block
756
        lda             #CLEAN
757
        sta             INODE_DIRTY,r4
758
        pop             r7
759
        pop             r6
760
        pop             r5
761
        pop             r4
762
        ply
763
        plx
764
        pla
765
        rts
766
 
767
;------------------------------------------------------------------------------
768
;------------------------------------------------------------------------------
769
dup_inode:
770
        inc             INODE_ICOUNT,r1
771
        rts
772
 
773
;------------------------------------------------------------------------------
774
; get_bgdt_entry:
775
;       Get block group descriptor from the descriptor table.
776
;
777
; Parameters:
778
;       r1 = device number
779
;       r2 = group number
780
; Returns:
781
;       r1 = pointer to BGD buffer
782
;------------------------------------------------------------------------------
783
;
784
get_bgdt_entry:
785
        push    r5
786
        and             r5,r2,#NR_BGD_BUFS-1            ; r5 = hashed group number
787
        mul             r5,r5,#BGD_BUFSIZE
788
        add             r5,r5,#BGD_bufs         ; r5 = pointer to BGD buffer
789
        cmp             bg_dev,r5
790
        bne             gbe1
791
        cpx             bg_group_num,r5
792
        beq             gbe2
793
gbe1:
794
        push    r4
795
        push    r6
796
        push    r7
797
        push    r8
798
        ld              r6,r1                           ; r6 = device number
799
        ld              r7,r2                           ; r7 = group number
800
        ; does the buffer need to be written to disk ?
801
        ld              r4,bg_dirty,r5
802
        cmp             r4,#CLEAN
803
        beq             gbe3
804
        ; Compute the block number containing the group
805
        jsr             get_bgd_per_block
806
        ld              r2,bg_group_num,r5
807
        div             r8,r2,r1
808
        mod             r4,r2,r1
809
        lda             fs_start_block
810
        ina                                                     ; the next block after the file system start
811
        add             r2,r1,r8                        ; r2 = block number
812
        ld              r1,r6                           ; r1 = device number
813
        jsr             get_block
814
        pha
815
        add             r1,r1,#b_data           ; move to data area
816
        mul             r4,r4,#BGDESC_SIZE
817
        add             r1,r1,r4                        ; r1 = pointer to desired BGD
818
        ; copy BGD to the block
819
        tay
820
        ld              r2,r5
821
        lda             #BGDESC_SIZE-1
822
        mvn
823
        pla
824
        ld              r2,#DIRTY
825
        stx             b_dirty,r1
826
gbe3:
827
        ; Compute the block number containing the group
828
        ld              r1,r6
829
        ld              r2,r7
830
        jsr             get_bgd_per_block
831
        div             r8,r2,r1
832
        mod             r4,r2,r1
833
        lda             fs_start_block
834
        ina                                                     ; the next block after the file system start
835
        add             r2,r1,r8                        ; r2 = block number
836
        ld              r1,r6                           ; r1 = device number
837
        jsr             get_block
838
        add             r1,r1,#b_data           ; move to data area
839
        mul             r4,r4,#BGDESC_SIZE
840
        add             r1,r1,r4                        ; r1 = pointer to desired BGD
841
        ; copy BGD from the block to the buffer
842
        tax
843
        ld              r3,r5
844
        lda             #BGDESC_SIZE-1
845
        mvn
846
        st              r6,bg_dev,r5
847
        st              r7,bg_group_num,r5
848
        lda             #CLEAN
849
        sta             bg_dirty,r5
850
        pop             r8
851
        pop             r7
852
        pop             r6
853
        pop             r4
854
gbe2:
855
        ld              r1,r5
856
        pop             r5
857
        rts
858
 
859
;==============================================================================
860
; Block Caching
861
;==============================================================================
862
 
863
;------------------------------------------------------------------------------
864
; get_block
865
;
866
;       Gets a block from the device. First the block cache is checked for the
867
; block; if found the cached buffer is returned.
868
;       The block number is hashed to determine where to start the search for a
869
; cached buffer.
870
;
871
; Parameters:
872
;       r1 = device
873
;       r2 = block number
874
;       r3 = only searching
875
; Returns:
876
;       r1 = pointer to buffer containing block
877
;------------------------------------------------------------------------------
878
;
879
get_block:
880
        phx
881
        phy
882
        push    r4
883
        push    r5
884
        push    r6
885
        push    r7
886
        push    r8
887
        ld              r4,r1                           ; r4 = device number
888
        ld              r5,r2                           ; r5 = block number
889
        and             r6,r5,#NR_BUF_HASH-1
890
        ldx             buf_hash,r6
891
        cmp             r4,#NO_DEV
892
        beq             gb11
893
gb15:
894
        cmp             r2,r0                           ; while (bp <> NULL) {
895
        beq             gb12
896
        cmp             r4,b_dev,x              ;       if (bp->b_dev == dev) {
897
        bne             gb13
898
        cmp             r5,b_blocknum,x ;               if (bp->b_blocknum==block) {
899
        bne             gb13
900
        cmp             r0,b_count,x            ;                       if (bp->b_count==0)
901
        bne             gb14
902
        inc             bufs_in_use                     ;                               bufs_in_use++
903
gb14:
904
        inc             b_count,x                       ;                       bp->b_count++
905
        txa                                                     ;                       return (bp)
906
gb_ret:
907
        pop             r8
908
        pop             r7
909
        pop             r6
910
        pop             r5
911
        pop             r4
912
        ply
913
        plx
914
        rts
915
gb13:
916
        ldx             b_hash,x                        ;       bp = bp->b_hash
917
        bra             gb15
918
gb11:
919
gb12:
920
        lda             bufs_in_use
921
        cmp             #NR_BUFS
922
        bltu    gb16
923
        jsr             panic
924
        db              "All buffers in use.",0
925
gb16:
926
        inc             bufs_in_use
927
        ldx             front
928
gb18:
929
        cmp             r0,b_count,x
930
        bls             gb17
931
        cmp             r0,b_next,x
932
        beq             gb17
933
        ldx             b_next,x
934
        bra             gb18
935
gb17:
936
        cmp             r2,r0
937
        beq             gb19
938
        cmp             r0,b_count,x
939
        bls             gb20
940
gb19:
941
        jsr             panic
942
        db              "No free buffer.", 0
943
gb20:
944
        ld              r6,b_blocknum,x
945
        and             r6,r6,#NR_BUF_HASH-1
946
        ld              r7,buf_hash,r6
947
        cmp             r7,r2
948
        bne             gb21
949
        ld              r8,b_hash,x
950
        st              r8,buf_hash,r6
951
        bra             gb22
952
gb21:
953
        cmp             r0,b_hash,r7
954
        beq             gb22
955
        cmp             r2,b_hash,r7
956
        bne             gb23
957
        ld              r8,b_hash,x
958
        st              r8,b_hash,r7
959
        bra             gb22
960
gb23:
961
        ld              r7,b_hash,r7
962
        bra             gb21
963
gb22:
964
        ld              r8,b_dirty,x
965
        cmp             r8,#DIRTY
966
        bne             gb24
967
        ld              r8,b_dev,x
968
        cmp             r8,#NO_DEV
969
        beq             gb24
970
        phx
971
        txa
972
        ldx             #WRITING
973
        jsr             rw_block
974
        plx
975
gb24:
976
        st              r4,b_dev,x              ; bp->b_dev = dev
977
        st              r5,b_blocknum,x ; bp->b_blocknum = block
978
        inc             b_count,x                       ; bp->b_count++
979
        ld              r7,buf_hash,r6
980
        st              r7,b_hash,x             ; bp->b_hash = buf_hash[bp->b_blocknr & (NR_b_hash - 1)]
981
        st              r2,buf_hash,r6          ; buf_hash[bp->b_blocknr & (NR_b_hash - 1)] = bp
982
        cmp             r4,#NO_DEV
983
        beq             gb25
984
        cmp             r3,#NORMAL
985
        bne             gb25
986
        phx
987
        txa
988
        ldx             #READING
989
        jsr             rw_block
990
        pla
991
        bra             gb_ret
992
gb25:
993
        txa
994
        bra             gb_ret
995
 
996
;------------------------------------------------------------------------------
997
; put_block
998
;       Put a block back to device
999
;
1000
; Parameters:
1001
;       r1 = pointer to buffer to put
1002
;       r2 = block type
1003
;
1004
;------------------------------------------------------------------------------
1005
;
1006
put_block:
1007
        cmp             #0              ; NULL pointer check
1008
        bne             pb1
1009
pb2:
1010
        rts
1011
pb1:
1012
        pha
1013
        phx
1014
        push    r4
1015
        push    r5
1016
        push    r7
1017
        push    r8
1018
        ld              r4,r1
1019
        ld              r5,r2
1020
        dec             b_count,r1      ; if buf count > 0 then buffer is still in use
1021
        bne             pb2
1022
        dec             bufs_in_use
1023
        tax
1024
        ld              r7,b_next,x
1025
        ld              r8,b_prev,x
1026
        beq             pb3
1027
        st              r7,b_next,r8    ; prev_ptr->b_next = next_ptr
1028
        bra             pb4
1029
pb3:
1030
        st              r7,front                ; front = next_ptr
1031
pb4:
1032
        cmp             r7,r0
1033
        beq             pb5
1034
        st              r8,b_next,r7
1035
        bra             pb6
1036
pb5:
1037
        st              r8,rear
1038
pb6:
1039
        bit             r5,#ONE_SHOT
1040
        beq             pb7
1041
        stz             b_prev,x
1042
        lda             front
1043
        sta             b_next,x
1044
        bne             bp8
1045
        stx             rear
1046
        bra             bp9
1047
bp8:
1048
        stx             b_prev,r1               ; front->b_prev = bp
1049
bp9:
1050
        stx             front                   ; front = bp
1051
        bra             bp10
1052
pb7:
1053
        stz             b_next,x                ; bp->b_next = NULL
1054
        lda             rear
1055
        sta             b_prev,x                ; bp->b_prev = rear
1056
        bne             bp11
1057
        stx             front                   ; front = bp
1058
        bra             bp12
1059
bp11:
1060
        stx             b_next,r1               ; rear->b_next = bp
1061
bp12:
1062
        stx             rear                    ; read = bp
1063
bp10:
1064
        cmp             r0,b_dev,x
1065
        beq             bp13
1066
        lda             #DIRTY
1067
        cmp             b_dirty,x
1068
        bne             bp13
1069
        bit             r5,#WRITE_IMMED
1070
        beq             bp13
1071
        phx
1072
        txa
1073
        ldx             #WRITING
1074
        jsr             rw_block
1075
        plx
1076
bp13:
1077
        cmp             r5,#ZUPER_BLOCK
1078
        bne             bp14
1079
        lda             #NO_DEV
1080
        sta             b_dev,x
1081
bp14:
1082
        pop             r8
1083
        pop             r7
1084
        pop             r5
1085
        pop             r4
1086
        plx
1087
        pla
1088
        rts
1089
 
1090
;------------------------------------------------------------------------------
1091
; block_to_sector:
1092
;       Convert a block number to a sector number.
1093
;
1094
; Parameters:
1095
;       r1 = block number
1096
; Returns:
1097
;       r1 = sector number
1098
;------------------------------------------------------------------------------
1099
block_to_sector:
1100
        phx
1101
        pha
1102
        jsr             get_log_block_size
1103
        tax
1104
        pla
1105
        inx
1106
        asl             r1,r1,r2
1107
        plx
1108
        rts
1109
 
1110
;------------------------------------------------------------------------------
1111
; rw_block:
1112
; ToDo: add error handling
1113
;
1114
; Parameters:
1115
;       r1 = pointer to buffer to operate on
1116
;       r2 = R/W flag
1117
;------------------------------------------------------------------------------
1118
;
1119
rw_block:
1120
        phx
1121
        phy
1122
        push    r4
1123
        push    r5
1124
        pha
1125
        ld              r5,r1                           ; r5 = pointer to data buffer
1126
        add             r5,r5,#b_data
1127
        ldy             b_dev,r1
1128
        cpy             #NO_DEV
1129
        beq             rwb1
1130
        ldy             b_blocknum,r1           ; y = block number
1131
        ld              r4,#1                           ; r4 = # of blocks
1132
        lda             b_dev,r1                        ; device number
1133
        cpx             #READING
1134
        bne             rwb2
1135
        ldx             #11                                     ; read blocks opcode
1136
        bra             rwb1
1137
rwb2:
1138
        ldx             #12                                     ; write blocks opcode
1139
rwb1:
1140
        jsr             DeviceOp
1141
        pla
1142
        ldy             #CLEAN
1143
        sty             b_dirty,r1
1144
        pop             r5
1145
        pop             r4
1146
        ply
1147
        plx
1148
        rts
1149
 
1150
;------------------------------------------------------------------------------
1151
; invalidate_dev
1152
;       Cycle through all the block buffers and mark the buffers for the
1153
; matching device as free.
1154
;
1155
; Parameters:
1156
;       r1 = device number
1157
;------------------------------------------------------------------------------
1158
;
1159
invalidate_dev:
1160
        phx
1161
        phy
1162
        push    r4
1163
        ldy             #NR_BUFS
1164
        ldx             #data_bufs
1165
id2:
1166
        ld              r4,b_dev,x
1167
        cmp             r4,r1
1168
        bne             id1
1169
        ld              r4,#NO_DEV
1170
        st              r4,b_dev,x
1171
id1:
1172
        add             r2,r2,#BUF_SIZE
1173
        dey
1174
        bne             id2
1175
 
1176
; invalidate the superblock
1177
;       ldy             #32
1178
;       ldx             #super_bufs
1179
id3:
1180
;       ld              r4,s_dev,x
1181
;       cmp             r4,r1
1182
;       bne             id4
1183
;       ld              r4,#NO_DEV
1184
;       st              r4,s_dev,x
1185
id4:
1186
;       add             r2,r2,#SUPERBUF_SIZE
1187
;       dey
1188
;       bne             id3
1189
 
1190
        pop             r4
1191
        ply
1192
        plx
1193
        rts
1194
 
1195
;==============================================================================
1196
; SUPERBLOCK code
1197
;==============================================================================
1198
 
1199
;------------------------------------------------------------------------------
1200
; get_super:
1201
;       Get the super block.
1202
; There is a super block for each device. Superblocks have their own buffer
1203
; cache.
1204
;
1205
; Parameters:
1206
;       r1 = device number
1207
; Returns:
1208
;       r1 = pointer to superblock buffer
1209
;------------------------------------------------------------------------------
1210
;
1211
get_super:
1212
        phx
1213
        phy
1214
        push    r4
1215
        ; first search the superbuf array to see if the block is already
1216
        ; memory resident
1217
        ldy             #0
1218
        ldx             #super_bufs
1219
gs2:
1220
        ld              r4,s_dev,x
1221
        cmp             r1,r4                                   ; device number match ?
1222
        beq             gs1                                             ; yes, found superblock buffer for device
1223
        cmp             r4,#NO_DEV
1224
        bne             gs4
1225
        txy                                                             ; record empty buffer
1226
gs4:
1227
        add             r2,r2,#SUPERBUF_SIZE
1228
        cpx             #super_bufs_end
1229
        blo             gs2
1230
        cpy             #0
1231
        beq             gs5
1232
        tyx
1233
        sta             s_dev,x
1234
        bra             gs3
1235
gs5:
1236
        ; Here we couldn't find the device superblock cached and there wasn't a slot free.
1237
        ; So dump one from memory and load cache
1238
        inc             superbuf_dump                   ; "randomizer" for dump select
1239
        ldx             superbuf_dump
1240
        and             r2,r2,#31                               ; 32 buffers
1241
        mul             r2,r2,#SUPERBUF_SIZE
1242
        add             r2,r2,#super_bufs
1243
        ; if the superblock is dirty, then write it out
1244
        ldy             s_dirty,x
1245
        cpy             #DIRTY
1246
        bne             gs3
1247
        jsr             write_super
1248
gs3:
1249
        sta             s_dev,x
1250
        jsr             read_super
1251
gs1:
1252
        txa
1253
        pop             r4
1254
        ply
1255
        plx
1256
        rts
1257
 
1258
;------------------------------------------------------------------------------
1259
; read_super:
1260
;       Read the superblock from disk. Only a single sector is read.
1261
;
1262
; Parameters:
1263
;       r1 = pointer to superblock buffer
1264
;------------------------------------------------------------------------------
1265
;
1266
read_super:
1267
        pha
1268
        phx
1269
        phy
1270
        ldy             s_dev,r1                        ; save device number in .Y
1271
        pha
1272
        jsr             get_filesystem_offset
1273
        tax
1274
        pla
1275
        pha
1276
        asl                                                     ; convert pointer to byte pointer
1277
        asl
1278
        jsr             SDReadSector
1279
        plx
1280
        lda             #CLEAN                          ; mark superblock clean
1281
        sta             s_dirty,x
1282
        sty             s_dev,x                         ; restore device number
1283
        ply
1284
        plx
1285
        pla
1286
        rts
1287
 
1288
;------------------------------------------------------------------------------
1289
; Parameters:
1290
;       r1 = pointer to superblock buffer
1291
;------------------------------------------------------------------------------
1292
write_super:
1293
        pha
1294
        phx
1295
        phy
1296
        push    r4
1297
        ld              r4,r1
1298
        ldy             s_dev,r1                        ; save device number in .Y
1299
        jsr             get_datetime
1300
        stx             s_wtime,r4
1301
        sta             s_wtime+1,r4
1302
        pop             r4
1303
        pha
1304
        jsr             get_filesystem_offset
1305
        tax
1306
        pla
1307
        pha
1308
        asl                                                     ; convert pointer to byte pointer
1309
        asl
1310
        jsr             SDWriteSector
1311
        plx
1312
        lda             #CLEAN
1313
        sta             s_dirty,x
1314
        sty             s_dev,x                         ; restore device number
1315
        ply
1316
        plx
1317
        pla
1318
        rts
1319
 
1320
;==============================================================================
1321
; Utility functions
1322
;==============================================================================
1323
 
1324
;------------------------------------------------------------------------------
1325
; get_datetime:
1326
;       Get the date and time.
1327
; Returns:
1328
;       r1 = date
1329
;       r2 = time
1330
;------------------------------------------------------------------------------
1331
get_datetime:
1332
        php
1333
        sei
1334
        stz             DATETIME_SNAPSHOT       ; take a snapshot of the running date/time
1335
        lda             DATETIME_DATE
1336
        ldx             DATETIME_TIME
1337
        plp
1338
        rts
1339
 
1340
;------------------------------------------------------------------------------
1341
; panic
1342
;       Display a filesystem panic message and abort.
1343
;
1344
; Parameters:
1345
;       r1 = numeric constant
1346
;       inline string
1347
;------------------------------------------------------------------------------
1348
;
1349
panic:
1350
        pha
1351
        lda             panicking
1352
        beq             pan1
1353
        pla
1354
        rts
1355
pan1:
1356
        ina
1357
        sta             panicking       ; panicking = TRUE;
1358
        jsr             dos_msg
1359
        db              "File system panic: ", 0
1360
        ply
1361
        plx                                             ; pull return address from stack
1362
pan2:
1363
        lb              r1,0,x
1364
        beq             pan3
1365
        jsr             DisplayChar
1366
        inx
1367
        bra             pan2
1368
pan3:
1369
        inx
1370
        phx
1371
        tya
1372
        cmp             #NO_NUM
1373
        beq             pan4
1374
        ldx             #5
1375
        jsr             PRTNUM
1376
pan4:
1377
        jsr             CRLF
1378
        jsr             do_sync
1379
        jsr             sys_abort
1380
        ;
1381
pan5:                                           ; we should not get back to here after the sys_abort()
1382
        bra             pan5
1383
 
1384
;------------------------------------------------------------------------------
1385
; Display a message on the screen
1386
; Parameters:
1387
;       inline string
1388
;------------------------------------------------------------------------------
1389
;
1390
dos_msg:
1391
        plx                     ; get return address
1392
dm2:
1393
        lb              r1,0,x
1394
        beq             dm1
1395
        jsr             DisplayChar
1396
        inx
1397
        bra             dm2
1398
dm1:
1399
        inx
1400
        phx
1401
        rts
1402
 
1403
;==============================================================================
1404
;==============================================================================
1405
;------------------------------------------------------------------------------
1406
; File system CLEAN task
1407
;------------------------------------------------------------------------------
1408
fs_clean:
1409
fsc4:
1410
        lda             #100                    ; sleep for 1s
1411
        jsr             Sleep
1412
fsc3:
1413
        lda             fs_active               ; is the file system active ?
1414
        cmp             #'A'
1415
        bne             fsc4
1416
        ldx             #data_bufs
1417
fsc2:
1418
        lda             b_dev,x                 ; is the buffer in use ?
1419
        cmp             #NO_DEV
1420
        beq             fsc1                    ; if not, goto next buffer
1421
        sei
1422
        lda             b_dirty,x               ; is the buffer dirty ?
1423
        cmp             #CLEAN
1424
        beq             fsc1                    ; if not, goto next buffer
1425
        ; Found a dirty buffer
1426
        phx
1427
        txa
1428
        ldx             #WRITING                ; write the dirty buffer out to disk
1429
        jsr             rw_block
1430
        plx
1431
        lda             #CLEAN                  ; mark the buffer as clean
1432
        sta             b_dirty,x
1433
fsc1:                                           ; iterate to the next buffer
1434
        cli
1435
        add             r2,r2,#BUF_SIZE
1436
        cpx             #data_bufs_end
1437
        bltu    fsc2
1438
        bra             fsc3
1439
 
1440
 
1441
;==============================================================================
1442
; DOS commands
1443
;==============================================================================
1444
 
1445
;------------------------------------------------------------------------------
1446
; MKFS - make file system
1447
;------------------------------------------------------------------------------
1448
;
1449
;numb_block_group_sectors:
1450
        ; nbg = ((disk size in bytes /
1451
        ;       (blocks  per block group * block size)) * block group descriptor size ) / block size + 1
1452
 
1453
        jsr             SDInit
1454
        lda             #1024
1455
        sta             block_size
1456
        jsr             SDReadPart
1457
        jsr             get_super
1458
        tax
1459
        ;       blocks_count = disk size * 512 / block size
1460
        jsr             get_log_block_size
1461
        tax
1462
        inx
1463
        lda             disk_size               ; disk size in sectors
1464
        lsr             r1,r1,r2                ; r1 = disk size in blocks
1465
        sta             s_block_count,x
1466
        sta             s_free_blocks_count,x
1467
        ; # files = block count * block size / 2048 (average file size)
1468
        lda             disk_size
1469
        lsr
1470
        lsr
1471
        sta             s_inodes_count,x
1472
        sta             s_free_inodes_count,x
1473
        stz             s_log_block_size,x      ; 0=1kB
1474
        lda             #8192
1475
        sta             s_blocks_per_group,x
1476
        sta             s_inodes_per_group,x
1477
        lda             #$EF54EF54
1478
        sta             s_magic,x
1479
        stz             s_errors,x
1480
        jsr             get_filesystem_offset
1481
        jsr             SDWriteSector           ; put_block
1482
 
1483
        lda             disk_size
1484
        div             r1,r1,#16384                    ; 8388608/512
1485
        div             r1,r1,#32                               ; divide by size of block group descriptot
1486
        add             r1,#1                                   ; round up
1487
        add             r4,r1,#2                                ; boot block + superblock
1488
        ; acc = number of blocks for descriptor table
1489
        tay
1490
        st              r4,bg_block_bitmap,
1491
        rts
1492
 
1493
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.