]> cloudbase.mooo.com Git - avrcpm.git/blame_incremental - avr/dsk_fsys.asm
* FAT buffer on ATmega328
[avrcpm.git] / avr / dsk_fsys.asm
... / ...
CommitLineData
1; Filesystem functions for the Interaction with BIOS and Disks
2;
3; Copyright (C) 2010 Frank Zoll
4;
5; This file is part of avrcpm.
6;
7; avrcpm is free software: you can redistribute it and/or modify it
8; under the terms of the GNU General Public License as published by
9; the Free Software Foundation, either version 3 of the License, or
10; (at your option) any later version.
11;
12; avrcpm is distributed in the hope that it will be useful,
13; but WITHOUT ANY WARRANTY; without even the implied warranty of
14; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15; GNU General Public License for more details.
16;
17; You should have received a copy of the GNU General Public License
18; along with avrcpm. If not, see <http://www.gnu.org/licenses/>.
19;
20; $Id$
21;
22
23
24; ---------------- Defines for the Filesystem Interface -------
25
26;*****************************************************
27;* Disk-Manager constants *
28;*****************************************************
29
30; Fields in the parttabl
31
32 .equ MAXDISKS = 8 ;Max number of Disks (partitions)
33 .equ PARTENTRY_SIZE = 9 ;Size of a Partitiontableentry
34
35 .equ PTAB_TYPE = 0
36 .equ PTAB_START = 1
37 .equ PTAB_SIZE = 5
38 .equ PTAB_SPT = 7
39 .equ PTAB_BSH = 8
40
41 .equ dskType_None = 0 << 4
42 .equ dskType_CPM = 1 << 4
43 .equ dskType_FAT = 2 << 4
44; .equ dskType_RAM = 3 << 4
45 .equ dskType_MASK = 0xf << 4
46
47;*****************************************************
48;* CP/M to host disk constants *
49;*****************************************************
50; .equ blksize = 1024 ;CP/M allocation size
51; .equ CPMSPT = 26 ;
52
53 .equ HOSTSIZE = 512 ;host disk sector size
54 .equ HOSTBLK = HOSTSIZE/128 ;CP/M sects/host buff
55 .equ SECMSK = HOSTBLK-1 ;sector mask
56 .equ SECSHF = log2(HOSTBLK) ;sector shift
57
58;*****************************************************
59;* BDOS constants on entry to write *
60;*****************************************************
61 .equ WRALL = 0 ;write to allocated
62 .equ WRDIR = 1 ;write to directory
63 .equ WRUAL = 2 ;write to unallocated
64 .equ WRTMSK= 3 ;write type mask
65
66;----------------------------------------------- Start of Data Segment
67
68 .dseg
69
70fsys_vars:
71
72; The following 3 variables are copied from DRAM.
73; Don't change order.
74
75biosdrvtbl: .byte 2 ;
76biosdirbuf: .byte 2 ;
77biosenddat: .byte 2 ;
78
79ndisks: .byte 1 ;Number of CP/M disks
80 .equ o_ndisks = ndisks-fsys_vars
81
82; The following 5 variables are accessed from 8080/z80 via the
83; virtual port interface. Don't change order.
84
85biospar_base:
86bcbadr: .byte 2 ;adr of BiosControlBlock
87seekdsk: .byte 1 ;seek disk number
88seektrk: .byte 2 ;seek track number
89seeksec: .byte 2 ;seek sector number
90dmaadr: .byte 2 ;last dma address
91 .equ o_bcbadr = bcbadr-fsys_vars
92 .equ o_seekdsk = seekdsk-fsys_vars
93 .equ o_seektrk = seektrk-fsys_vars
94 .equ o_seeksec = seeksec-fsys_vars
95 .equ o_dmaadr = dmaadr-fsys_vars
96
97hdrsize: .byte 1 ;Image header size (offset)
98cpmspt: .byte 1 ;CP/M sectors per track
99secpblk: .byte 1 ;sectors per block (alloc size)
100unacnt: .byte 1 ;unalloc rec cnt
101unadsk: .byte 1 ;last unalloc disk
102unalba: .byte 2 ;last unalloc disk block
103 .equ o_hdrsize = hdrsize-fsys_vars
104 .equ o_cpmspt = cpmspt-fsys_vars
105 .equ o_secpblk = secpblk-fsys_vars
106 .equ o_unacnt = unacnt-fsys_vars
107 .equ o_unadsk = unadsk-fsys_vars
108 .equ o_unalba = unalba-fsys_vars
109
110erflag: .byte 1 ;error reporting
111wrtype: .byte 1 ;write operation type
112 .equ o_erflag = erflag-fsys_vars
113 .equ o_wrtype = wrtype-fsys_vars
114
115hostdsk: .byte 1 ;host disk number
116hostlba: .byte 2 ;host sector number (relative to partition start)
117 .equ o_hostdsk = hostdsk-fsys_vars
118 .equ o_hostlba = hostlba-fsys_vars
119
120hostparttbl: .byte PARTENTRY_SIZE*MAXDISKS ;host partition table (type, start sector, sector count)
121hostparttbltop:
122hostbuf: .byte HOSTSIZE ;host buffer (from/to SD-card)
123
124
125; ------------------------------- Start of Code Segment
126 .cseg
127
128;---------------------------------------------------------------------
129
130.if DSKSEL_DEBUG
131
132dbg_prdrvtbl:
133 push xh
134 push xl
135 push temp3
136 push temp2
137 push temp
138 printnewline
139 printstring "drvtbl ("
140 ldsw x,biosdrvtbl
141 movw temp,x
142 lcall printhexw
143 printstring "): "
144 ldi temp3,16
145dbg_pcpel:
146 lcall dram_readw_pp
147 lcall printhexw
148 printstring " "
149 dec temp3
150 brne dbg_pcpel
151 pop temp
152 pop temp2
153 pop temp3
154 pop xl
155 pop xh
156 ret
157
158dbg_print_biosd:
159 printnewline
160 lds temp,bcbadr
161 lds temp2,bcbadr+1
162 lcall printhexw
163 printstring " "
164 lds temp,biosdrvtbl
165 lds temp2,biosdrvtbl+1
166 lcall printhexw
167 printstring " "
168 lds temp,biosdirbuf
169 lds temp2,biosdirbuf+1
170 lcall printhexw
171 printstring " "
172 lds temp,biosenddat
173 lds temp2,biosenddat+1
174 lcall printhexw
175 printstring " "
176 ret
177.endif
178
179; ====================================================================
180; ====================================================================
181; Function: Get a Pointer to a Partitiontable entry
182; ====================================================================
183; Parameters
184; --------------------------------------------------------------------
185; Registers : [w] z Pointer to the Partitionentry
186; [r] zl Number of Diskentry to Read
187; [w] r0 scratch
188; [w] r1 "
189; --------------------------------------------------------------------
190; Description:
191; ====================================================================
192dsk_getpartentry:
193
194 ldi zh,PARTENTRY_SIZE
195 mul zh,zl
196 ldiw z,hostparttbl
197 add zl,r0
198 adc zh,r1
199 ret
200
201; ====================================================================
202; ====================================================================
203; Function: Virtual Port Interface
204; ====================================================================
205; Parameters
206; --------------------------------------------------------------------
207; Registers :
208; Variables :
209;
210; --------------------------------------------------------------------
211; Description:
212; ====================================================================
213
214dsk_param_getadr:
215 ldiw z,biospar_base
216 add zl,temp3
217 adc zh,_0
218 ret
219
220dsk_param_set:
221 rcall dsk_param_getadr
222 st z,temp
223 cpi temp3,bcbadr+1-biospar_base
224 breq SetBCB
225 ret
226
227dsk_param_get:
228 cpi temp3,seekdsk-biospar_base
229 breq dskDiskCheck
230 rcall dsk_param_getadr
231 ld temp,z
232 ret
233
234SetBCB:
235 lds xl,bcbadr
236 mov xh,temp
237 ldiw z,biosdrvtbl
238 ldi temp3,6
239sbcb_l:
240 rcall dram_read_pp
241 st z+,temp
242 dec temp3
243 brne sbcb_l
244
245; rcall dbg_print_biosd
246 rcall dpb_drvtblclear
247; rcall dbg_prdrvtbl
248
249 ret
250
251; ====================================================================
252; Function: Check if disk exists
253; ====================================================================
254; Parameters
255; --------------------------------------------------------------------
256; Registers :
257; Variables :
258; return 0, if selected disk not exist.
259; return !0, if disk exist
260; --------------------------------------------------------------------
261; Description:
262; ====================================================================
263dskDiskCheck:
264 lds temp2,ndisks
265 lds temp,seekdsk
266.if DSKSEL_DEBUG
267 printnewline
268 printstring "DiskCheck: "
269 lcall printhexw
270.endif
271 cpi temp,RAMDISKNR
272 brsh dsk_dchrd ;maybe ramdisk
273
274 tst temp2 ;0 disks?
275 brne dsk_dchpart1
276
277; No disks yet, need to init
278
279 rcall dpb_drvtblclear
280.if 0
281 ldi temp2,0x40
282 ldi temp,1
283 lcall clockput
284.endif
285 rcall mgr_init_partitions ;disk chanched?
286 push temp
287.if 0
288 ldi temp2,0x40
289 ldi temp,2
290 lcall clockput
291; sbrs temp,7
292; rjmp dsk_dchpart0
293
294 lcall mgr_prnt_parttbl
295 printnewline
296.endif
297
298; rcall dbg_prdrvtbl
299 pop temp2
300dsk_dchpart0:
301 cbr temp2,0x80
302 lds temp,seekdsk
303
304; Check if selected disk # is less then # of disks.
305
306dsk_dchpart1:
307 cp temp,temp2
308 brsh dsk_dch_err
309
310.if DSKSEL_DEBUG
311 printnewline
312 printstring "Select: "
313 lcall printhex
314.endif
315 rcall dpb_drvtbl_entry_get
316 or temp,temp2 ;if !0, drive is allready initialized
317 brne dsk_dchend
318 lds temp3,seekdsk
319 mov temp,temp3
320 rcall dpb_biosdph_get
321dsk_dchend:
322
323.if DSKSEL_DEBUG
324 push temp
325 lds temp,seekdsk
326 rcall dpb_drvtbl_entry_get
327
328 printstring ", "
329 lcall printhexw
330 pop temp
331.endif
332
333 ret
334
335dsk_dch_err:
336 ldi temp,0 ;error return
337 ret
338
339; Check RAMDISK
340
341dsk_dchrd:
342#if RAMDISKCNT
343 cpi temp,RAMDISKNR+RAMDISKCNT
344 brsh dsk_dchrd_err
345
346 ldi temp,0xff ;return ok
347 ret
348#endif
349dsk_dchrd_err:
350 ldi temp,0 ;error return
351 ret
352
353
354; ====================================================================
355; Function: Return status of last disk i/o function
356; ====================================================================
357; Parameters
358; --------------------------------------------------------------------
359; Registers :
360; Variables :
361; --------------------------------------------------------------------
362; Description:
363; ====================================================================
364
365dskErrorRet:
366 lds temp,erflag
367 ret
368
369
370; ====================================================================
371; ====================================================================
372
373
374
375str_CPM_Disk:
376 .db 10,"<CPM_Disk>",0
377
378; DPBs for varios fixed formats
379; dpb data starts at 2. byte
380
381dpbdat_avrcpm: ;(dpb243)
382 .db 0x00,0x1A ;sector offset, low(spt)
383 .db 0x00,0x03 ;high (spt), block shift
384 .db 0x07,0x00 ;bock mask, extent mask
385 .db 0xF2,0x00 ;disk size - 1,
386 .db 0x3F,0x00 ;dir max
387 .db 0xC0,0x00 ;alloc0, alloc1
388 .db 0x10,0x00 ;chk size
389 .db 0x02,0x00 ;offset
390
391dpbdat_myz80: ;
392 .db 0x02,0x80 ;sector offset, low(spt)
393 .db 0x00,0x05 ;high (spt), block shift
394 .db 0x1F,0x01 ;bock mask, extent mask
395 .db 0xFF,0x07 ;disk size - 1,
396 .db 0xFF,0x03 ;dir max
397 .db 0xFF,0x00 ;alloc0, alloc1
398 .db 0x00,0x01 ;chk size
399 .db 0x00,0x00 ;offset
400
401dpbdat_simhd: ;
402 .db 0x00,0x20 ;sector offset, low(spt)
403 .db 0x00,0x05 ;high (spt), block shift
404 .db 0x1F,0x01 ;bock mask, extent mask
405 .db 0xF9,0x07 ;disk size - 1,
406 .db 0xFF,0x03 ;dir max
407 .db 0xFF,0x00 ;alloc0, alloc1
408 .db 0x00,0x01 ;chk size
409 .db 0x06,0x00 ;offset
410
411#if 0
412;rd1016
413 .db 0x20,0x00 ;spt
414 .db 0x04,0x0F ;block shift, bock mask
415 .db 0x00,0xFB ;extent mask, low(disk size -1),
416 .db 0x01,0xBF ;high(disk size -1), low(dir max)
417 .db 0x00,0xE0 ;high(dir max), alloc0
418 .db 0x00,0x30 ;alloc1, low(chk size)
419 .db 0x00,0x02 ;high(chk size), low(offset)
420 .db 0x00,0x00 ;high(offset), fill
421;rd9192s
422 .db 0x20,0x00 ;spt
423 .db 0x05,0x1F ;block shift, bock mask
424 .db 0x01,0xFD ;extent mask, low(disk size -1),
425 .db 0x07,0xFF ;high(disk size -1), low(dir max)
426 .db 0x01,0xF0 ;high(dir max), alloc0
427 .db 0x00,0x80 ;alloc1, low(chk size)
428 .db 0x00,0x02 ;high(chk size), low(offset)
429 .db 0x00,0x00 ;high(offset), fill
430#endif
431
432
433
434; ====================================================================
435; Function: get drive table entry pointer for drive # in temp
436; ====================================================================
437; Parameters
438; --------------------------------------------------------------------
439; Registers :
440; Variables :
441;
442; --------------------------------------------------------------------
443; Description:
444; ====================================================================
445
446dpb_drvtbl_entry_p:
447
448 ldsw x,biosdrvtbl
449 lsl temp ;drive #
450 add xl,temp
451 adc xh,_0
452 ret
453
454
455; ====================================================================
456; Function: get drive table entry for drive # in temp
457; ====================================================================
458; Parameters
459; --------------------------------------------------------------------
460; Registers :
461; Variables :
462;
463; --------------------------------------------------------------------
464; Description:
465; ====================================================================
466
467dpb_drvtbl_entry_get:
468
469 rcall dpb_drvtbl_entry_p
470 ljmp dram_readw_pp
471
472
473; ====================================================================
474; Function: Clear drive table (entries 0 to 7)
475; ====================================================================
476; Parameters
477; --------------------------------------------------------------------
478; Registers :
479; Variables :
480;
481; --------------------------------------------------------------------
482; Description:
483; ====================================================================
484
485;
486
487dpb_drvtblclear:
488 ldsw x,biosdrvtbl
489 sbiw x,0
490 breq dpb_drvi_ex
491
492dpb_drvi_1:
493 ldi temp3,8
494dpb_drvi_lp:
495 ldi temp,0
496 ldi temp2,0
497 rcall dram_writew_pp
498 dec temp3
499 brne dpb_drvi_lp
500
501 lds temp,biosenddat
502 lds temp2,biosenddat+1
503 cp temp,_0
504 cpc temp2,_0
505 breq dpb_drvi_ex
506
507 rcall heap_init
508dpb_drvi_ex:
509 clr temp
510 ret
511
512; ====================================================================
513; Function: Test disk format: avrcpmhd
514; ====================================================================
515; Parameters
516; --------------------------------------------------------------------
517; Registers : temp drive #
518;
519; --------------------------------------------------------------------
520; Description: Not implemented yet.
521; ====================================================================
522
523dsk_tst_avrcpmhd:
524 clr temp ; Test, return 'not found' for now.
525 ret
526
527
528; ====================================================================
529; Function: Test disk format: YAZE
530; ====================================================================
531; Parameters
532; --------------------------------------------------------------------
533; Registers : temp drive #
534;
535; --------------------------------------------------------------------
536; Description: From the YAZE Doc:
537;
538; The new disk header occupies the first 128 BYTES of the file and has the
539; new format:
540;
541; 0 - 9 <CPM_Disk>
542; 10 - 15 a null-terminated ascii comment (may be empty)
543; new 16 version (0 = yaze-1.06/1.10, 1 = yaze-ag-2.xx)
544; 17 - 31 a null-terminated ascii comment (may be empty)
545; 32 - 33 sectors per track
546; 34 block shift factor
547; 35 block mask
548; 36 extent mask
549; 37 - 38 disk size max
550; 39 - 40 directory max
551; 41 al0
552; 42 al1
553; 43 - 44 check size (always zero)
554; 45 - 46 track offset
555; new 47 psh (used if version=1 and CP/M 3.1 is running)
556; new 48 phm ( " " " " " " " " " )
557; 49 - 127 unused (zeros)
558; ====================================================================
559
560
561dsk_tst_yaze:
562
563 ldiw y,hostbuf
564 ldiw z,str_CPM_Disk*2
565 lpm temp2,z+ ; get length
566 lcall strncmp_p
567 brne dsk_tyze_not
568
569 ldiw z,hostbuf+31
570 clt ;dpb in RAM
571 ldi temp,1 ;1 sector header size
572 st z,temp
573
574 ori temp,0xff
575 ret
576
577dsk_tyze_not:
578 clr temp ;Not a YAZE disk image.
579 ret
580
581; ====================================================================
582; Function: Test disk format: MyZ80
583; ====================================================================
584; Parameters
585; --------------------------------------------------------------------
586; Registers : temp drive #
587;
588; --------------------------------------------------------------------
589; Description: Test, if first 2 Sectors are filled with 0xE5,
590; and Size = 8192KB + 256Bytes.
591; ====================================================================
592
593dsk_tst_myz80:
594
595 mov zl,temp3
596 rcall dsk_getpartentry ;get partition entry
597 ldd temp,z+PTAB_SIZE
598 ldd temp2,z+PTAB_SIZE+1 ;check, if size is 16385 phys. sectors
599 cpi temp,low(16385)
600 ldi temp,high(16385)
601 cpc temp2,temp
602 brne dsk_tmyz80_not ;wrong size
603
604 ldiw z,hostbuf
605 ldi temp2,0
606
607dsk_tmyz80_loop:
608 ld temp,z+
609 cpi temp,0xE5
610 brne dsk_tmyz80_not
611 dec temp2
612 brne dsk_tmyz80_loop
613
614 ldiw z,dpbdat_myz80*2
615 set
616 ori temp,0xff
617 ret
618
619dsk_tmyz80_not:
620 clr temp ;Not a MyZ80 hard disk image.
621 ret
622
623; ====================================================================
624; Function: Test disk format: simhd, simh altair 8800 hard disk format
625; ====================================================================
626; Parameters
627; --------------------------------------------------------------------
628; Registers : temp drive #
629;
630; --------------------------------------------------------------------
631; Description: Test, if Size = 8192 KB and
632; first 6 tracks are filled with 0xE5.
633; Actually, only the first phys. sector is tested, since
634; the other 47 sectors are not in memory at this time.
635; ====================================================================
636
637dsk_tst_simhd:
638
639 mov zl,temp3
640 rcall dsk_getpartentry ;get partition entry
641 ldd temp,z+PTAB_SIZE
642 ldd temp2,z+PTAB_SIZE+1 ;check, if size is 16384 phys. sectors
643 cpi temp,low(16384)
644 ldi temp,high(16384)
645 cpc temp2,temp
646 brne dsk_tsimhd_not ;wrong size
647
648 ldiw y,hostbuf+128-10
649 ldiw z,str_CPM_Disk*2
650 lpm temp2,z+ ; get length
651 lcall strncmp_p
652 breq dsk_tsimhd_found
653
654 ldiw z,hostbuf
655 ldi temp2,high(512)
656 clr _tmp0 ;low(512)
657dsk_tsimhd_loop:
658 ld temp,z+
659 cpi temp,0xE5
660 brne dsk_tsimhd_not
661 add _tmp0,_255
662 adc temp2,_255
663 brne dsk_tsimhd_loop
664
665dsk_tsimhd_found:
666 ldiw z,dpbdat_simhd*2
667 set
668 ori temp,0xff
669 ret
670
671dsk_tsimhd_not:
672 clr temp ;Not a simhd hard disk image.
673 ret
674
675; ====================================================================
676; Function:
677; ====================================================================
678; Parameters
679; --------------------------------------------------------------------
680; Registers : temp3 drive #
681;
682; --------------------------------------------------------------------
683; Description:
684; ====================================================================
685
686dsk_format_get:
687
688; Get first sector (512 byte) of current drive into hostbuf.
689
690 ldi temp,0
691 ldi temp2,0 ;
692 rcall dsk_readhost_lba
693
694; Test for variable format avrcpmhd.
695
696 rcall dsk_tst_avrcpmhd
697 brne dsk_imgt_done
698
699; Test for YAZE formats.
700
701 rcall dsk_tst_yaze
702 brne dsk_imgt_done
703
704; Test for simhd format.
705
706 rcall dsk_tst_simhd
707 brne dsk_imgt_done
708
709; Test for MyZ80 format.
710
711 rcall dsk_tst_myz80
712 brne dsk_imgt_done
713
714; No special image found. Use avrcpm.
715
716 ldiw z,dpbdat_avrcpm*2
717 set
718 ori temp,0xff
719
720dsk_imgt_done:
721 ret
722
723; ====================================================================
724; Function: Add CP/M image format data to partition table data
725; ====================================================================
726; Parameters
727; --------------------------------------------------------------------
728; Registers : temp3 drive #
729;
730; --------------------------------------------------------------------
731; Description:
732; ====================================================================
733
734dpb_imgdata_get:
735
736; Test for known CP/M formats
737
738 rcall dsk_format_get
739 breq dpb_imgd_err ;no known format detected
740
741dpb_imgd_0:
742 brtc dpb_imgd_variable
743dpb_imgd_fixed:
744 lpm temp, z+ ;image header
745 lpm yl,z+ ;low(SPT)
746 lpm yh,z+ ;high(SPT)
747 lpm temp2,z+ ;BSH
748 rjmp dpb_imgd_common
749
750dpb_imgd_variable:
751 ld temp, z+ ;image header
752 ld yl,z+ ;low(SPT)
753 ld yh,z+ ;high(SPT)
754 ld temp2,z+ ;BSH
755
756dpb_imgd_common:
757 mov zl,temp3
758 rcall dsk_getpartentry ;get partition entry
759 std z+PTAB_SPT,yl
760 tst yh ;more then 256 sectors per track?
761 brne dsk_imgprp_err ;todo: support 16 bit sector numbers
762
763 andi temp2,0x0f
764 swap temp2
765 std z+PTAB_BSH,temp2
766
767 andi temp,~dskType_MASK
768 ldd temp2,z+PTAB_TYPE
769 andi temp2,dskType_MASK
770 or temp,temp2
771 std z+PTAB_TYPE,temp
772
773 ori temp,255
774 ret
775
776dsk_imgprp_err:
777 printnewline
778 ldi temp,'A'
779 add temp,temp3
780 lcall uartputc
781 printstring ": Format not supported: Too much sectors per track! "
782 printnewline
783
784dpb_imgd_err:
785 clr temp
786 ret
787
788; ====================================================================
789; Function:
790; ====================================================================
791; Parameters
792; --------------------------------------------------------------------
793; Registers : temp drive #
794;
795; return !0 if ok
796; 0 on error
797; --------------------------------------------------------------------
798; Description: Init CP/M data structures
799;
800; -----------------------------------------------------------------
801; DPH: | XLT | | | |DIRBUF | DPB | CSV | ALV |
802; -----------------------------------------------------------------
803;offset: 0 2 4 6 8 10 12 14
804;
805; -------------------------------------------------------------
806; DPB: | SPT |BSH|BLM|EXM| DSM | DRM |AL0|AL1| CKS | OFF |
807; -------------------------------------------------------------
808;offset: 0 2 3 4 5 7 9 10 11 13
809; ====================================================================
810
811dpb_biosdph_get:
812 mov temp3,temp ;save disk #
813
814 rcall dsk_format_get
815 brne dpb_di_0
816 rjmp dpb_di_err
817
818dpb_di_0:
819
820; get mem for DPH
821
822 ldi temp, low (16)
823 ldi temp2,high(16)
824 rcall heap_get ;returns ptr to dph mem
825 brne dpb_di_1
826 rjmp dpb_di_err ;
827dpb_di_1:
828 movw x,temp
829 movw y,temp ;save dph pointer
830 ldi temp,0
831 ldi temp2,0
832 rcall dram_writew_pp ;XLT
833 adiw x,6
834 lds temp,biosdirbuf
835 lds temp2,biosdirbuf+1
836 rcall dram_writew_pp ;DIRBUF
837
838; get mem for DPB
839
840 ldi temp, low (15)
841 ldi temp2,high(15)
842 rcall heap_get
843 breq dpb_di_err_p1
844 movw x,temp
845
846 adiw z,1 ;skip sector offset byte
847 push temp3
848 ldi temp3,15
849dpb_dicpl:
850 brtc PC+2 ;
851 lpm temp,z+
852 brts PC+2 ;
853 ld temp,z+
854 rcall dram_write_pp
855 dec temp3
856 brne dpb_dicpl
857 pop temp3
858 sbiw x,15
859 sbiw z,15
860 movw temp,x
861 movw x,y
862 adiw x,10
863 rcall dram_writew_pp ;DPB
864
865 brtc dpb_dicks_variable
866dpb_dicks_fixed:
867 adiw z,5
868 lpm _tmp0,z+ ;dsm
869 lpm _tmp1,z+
870 adiw z,11-5-2
871 lpm temp,z+ ;cks
872 lpm temp2,z+
873 rjmp dpb_dicks_common
874dpb_dicks_variable:
875 ldd _tmp0,z+5 ;dsm
876 ldd _tmp1,z+5+1
877 ldd temp,z+11 ;cks
878 ldd temp2,z+11+1
879
880; get mem for dir check vector
881
882dpb_dicks_common:
883 cp temp,_0
884 cpc temp2,_0
885 breq dpb_dicks0
886 rcall heap_get
887 breq dpb_di_err_p1
888dpb_dicks0:
889 rcall dram_writew_pp ;CSV
890
891; get mem for alloc vector
892
893 movw temp,_tmp0
894 subi temp, low (-8)
895 sbci temp2,high(-8)
896 lsr temp2
897 ror temp
898 lsr temp2
899 ror temp
900 lsr temp2
901 ror temp ;(dsm+1+7)/8
902 rcall heap_get
903 breq dpb_di_err_p1
904 rcall dram_writew_pp ;ALV
905
906; success, insert DPH into drvtbl
907
908 mov temp,temp3
909 rcall dpb_drvtbl_entry_p
910 movw temp,y
911 rcall dram_writew_pp
912
913 ori temp,0xff ;return ok
914 ret
915
916; error, free mem
917
918dpb_di_err_p1:
919 movw temp,y
920 rcall heap_release
921dpb_di_err:
922 eor temp,temp ;return 0 (+ Z-flag)
923 ret
924
925; ====================================================================
926; Function:
927; ====================================================================
928; Parameters
929; --------------------------------------------------------------------
930; Registers :
931;
932; --------------------------------------------------------------------
933; Description:
934; ====================================================================
935
936dsk_setdrvparam:
937 ldd temp2,z+PTAB_TYPE
938 andi temp2,~dskType_MASK ;Lower nibble is image header size
939 std y+o_hdrsize,temp2
940 ldd temp2,z+PTAB_SPT
941 std y+o_cpmspt,temp2 ;CP/M sectors per track
942 ldd temp2,z+PTAB_BSH
943 swap temp2
944 andi temp2,0x0f
945 clr _tmp0
946 inc _tmp0
947dsk_sdrvpl:
948 lsl _tmp0
949 dec temp2
950 brne dsk_sdrvpl
951 std y+o_secpblk,_tmp0 ;Sectors per block
952 ret
953
954
955; ====================================================================
956; Function: Does a Disk interaction
957; ====================================================================
958; Parameters
959; --------------------------------------------------------------------
960; Registers :
961; Variables :
962;
963; --------------------------------------------------------------------
964; Description:
965; ====================================================================
966
967dskDoIt:
968
969 ldiw y,fsys_vars
970 std y+o_erflag,_0
971
972.if DISK_DEBUG
973 push temp
974 sbrc temp,HOME_FUNC
975 rjmp dskdbghome
976 sbrc temp,BOOT_FUNC
977 rjmp dskdbgboot
978.if DISK_DEBUG > 1
979 sbrc temp,READ_FUNC
980 rjmp dskdbgread
981 sbrc temp,WRITE_FUNC
982 rjmp dskdbgwrite
983.endif
984 rjmp dskdbge
985
986dskdbgread:
987 printnewline
988 printstring "dsk RD: "
989 rjmp dskdbg1
990dskdbgwrite:
991 printnewline
992 printstring "dsk WR: "
993 rjmp dskdbg1
994dskdbghome:
995 printnewline
996 printstring " HOME: "
997 rjmp dskdbg1
998dskdbgboot:
999 printnewline
1000 printstring " BOOT: "
1001dskdbg1:
1002 ldd temp,y+o_seekdsk
1003 subi temp,-('A')
1004 rcall uartputc
1005 printstring ": trk "
1006 ldd temp2,y+o_seektrk+1
1007 ldd temp,y+o_seektrk
1008 lcall printhexw
1009 printstring ", sec "
1010 ldd temp,y+o_seeksec
1011 lcall printhex
1012 printstring ", dma "
1013 ldd temp2,y+o_dmaadr+1
1014 ldd temp,y+o_dmaadr
1015 lcall printhexw
1016dskdbge:
1017 pop temp
1018.endif
1019
1020 ;See what has to be done.
1021 sbrc temp,READ_FUNC
1022 rjmp dsk_readwrite
1023 sbrc temp,WRITE_FUNC
1024 rjmp dsk_readwrite
1025 sbrc temp,HOME_FUNC
1026 rjmp dsk_home
1027 sbrc temp,BOOT_FUNC
1028 rjmp dsk_boot
1029
1030 printstring "DISK I/O: Invalid Function code: "
1031 lcall printhex
1032 ljmp haltinv
1033
1034dsk_boot:
1035 std y+o_ndisks,_0 ;no active partitions
1036dsk_inval_hostbuf:
1037 cbi flags,hostact ;host buffer inactive
1038 std y+o_unacnt,_0 ;clear unalloc count
1039 ret
1040
1041dsk_home:
1042 sbis flags,hostwrt ;check for pending write
1043 cbi flags,hostact ;clear host active flag
1044 ret
1045
1046
1047
1048
1049dsk_readwrite:
1050
1051; RAM disk?
1052
1053 ldd zl,y+o_seekdsk
1054#if RAMDISKCNT
1055 cpi zl,RAMDISKNR
1056 brlt dsk_rw_noramdisk
1057 sbrc temp,WRITE_FUNC
1058 rjmp rdsk_write
1059 rjmp rdsk_read
1060dsk_rw_noramdisk:
1061#endif
1062 rcall dsk_getpartentry ;Get Paritiontableentry
1063 ld temp2,z ;Get Partitiontype
1064 andi temp2,dskType_MASK
1065
1066; Isn't it a Disk ?
1067
1068 cpi temp2,dskType_None
1069 brne PC+2
1070 ret ;return error
1071
1072; It must be a FAT16-Imagefile or CP/M Partition.
1073
1074 sbrc temp,WRITE_FUNC
1075 rjmp dsk_write
1076
1077 sbi flags,readop ;Set read operation flag
1078 sbi flags,rsflag ;must read data
1079 std y+o_unacnt,_0
1080 ldi temp,WRUAL ;write type
1081 std y+o_wrtype,temp ;treat as unalloc
1082 rjmp dsk_rw
1083
1084dsk_write:
1085 cbi flags,readop ;Not a read operation
1086 andi temp,WRTMSK
1087 std y+o_wrtype,temp ;save write type
1088dsk_rw:
1089 rcall dsk_setdrvparam ;todo: do this only if needed (disk change)
1090
1091; Convert track/sector to an LBA address (in 128byte blocks)
1092
1093 ldd xl,y+o_seeksec ;
1094 ldi xh,0 ;
1095 ldi temp2,0 ;
1096 ldd temp,y+o_hdrsize ;add image header size
1097 add xl,temp ;
1098 adc xh,_0 ;
1099 ldd temp,y+o_cpmspt ;
1100 ldd _tmp0,y+o_seektrk ;
1101 mul temp,_tmp0 ;
1102 add xl,r0 ;
1103 adc xh,r1 ;
1104 ldd _tmp0,y+o_seektrk+1 ;
1105 mul temp,_tmp0 ;
1106 add xh,r0 ;temp2:xh:xl := sec + trk * SectorsPerTrack
1107 adc temp2,r1 ;
1108 mov temp3,xl
1109 andi temp3,SECMSK ;mask buffer number
1110
1111; Convert from CP/M LBA blocks to host LBA blocks
1112
1113 ldi temp,SECSHF
1114dsk_sh1:
1115 lsr temp2
1116 ror xh
1117 ror xl
1118 dec temp
1119 brne dsk_sh1
1120 ;todo: temp2 should be 0 here.
1121 ;xh:xl = host block to seek
1122;
1123 sbic flags,readop
1124 rjmp dsk_rwoper ;to perform the read
1125
1126; Write operation
1127
1128 cbi flags,rsflag ;rsflag = 0
1129 ldd temp,y+o_wrtype ;
1130 cpi temp,WRUAL ;write unallocated?
1131 brne dsk_chkuna ;check for unalloc
1132
1133; write to unallocated, set parameters
1134
1135 ldd temp,y+o_secpblk ;next unalloc recs (blocksize/128)
1136 cpi temp3,0 ;cpm sector on phys. sector boundary?
1137 breq dsk_una1
1138 sbi flags,rsflag ; no, rsflag = 1
1139 subi temp,HOSTBLK ;don't write
1140 ldd _tmp0,y+o_hdrsize ; in next bock
1141 add temp,_tmp0 ; if there is a header
1142dsk_una1:
1143 std y+o_unacnt,temp
1144 ldd temp,y+o_seekdsk ;disk to seek
1145 std y+o_unadsk,temp ;unadsk = sekdsk
1146 std y+o_unalba, xl ;unalba = seeklba (== hostlba)
1147 std y+o_unalba+1,xh
1148
1149; check for write to unallocated sector
1150
1151dsk_chkuna:
1152
1153 ldd temp,y+o_unacnt ;any unalloc remain?
1154 tst temp
1155 breq dsk_alloc ;skip if not
1156
1157; more unallocated records remain
1158
1159 dec temp ;unacnt = unacnt-1
1160 std y+o_unacnt,temp
1161 ldd temp,y+o_seekdsk ;same disk?
1162 ldd temp2,y+o_unadsk
1163 cp temp,temp2 ;seekdsk = unadsk?
1164 brne dsk_alloc ;skip if not
1165
1166; disks are the same
1167
1168 ldd _tmp0,y+o_unalba
1169 ldd _tmp1,y+o_unalba+1
1170 cp _tmp0,xl ;seeklba = unalba?
1171 cpc _tmp1,xh
1172 brne dsk_alloc ;skip if not
1173
1174; block address is the same
1175; move to next sector for future ref
1176
1177 mov temp,temp3
1178 inc temp ;next part
1179 andi temp,SECMSK
1180 brne dsk_noovf ;skip if no overflow
1181
1182; overflow to next block
1183
1184 sub _tmp0,_255 ;unalba = unalba+1
1185 sbc _tmp1,_255
1186 std y+o_unalba, _tmp0
1187 std y+o_unalba+1,_tmp1
1188
1189dsk_noovf:
1190 rjmp dsk_rwoper ;to perform the write
1191
1192; not an unallocated record, requires pre-read
1193
1194dsk_alloc:
1195 std y+o_unacnt,_0 ;unacnt = 0
1196 sbi flags,rsflag ;rsflag = 1
1197
1198
1199; Enter here to perform the read/write
1200
1201dsk_rwoper:
1202
1203.if DISK_DEBUG > 1
1204 printstring ", flags|wtyp "
1205 in temp,flags
1206 cbr temp,WRTMSK
1207 ldd _tmp0,y+o_wrtype
1208 or temp,_tmp0
1209 lcall printhex
1210 printstring ", buf "
1211 mov temp,temp3
1212 lcall printhex
1213.endif
1214
1215 push temp3
1216 movw temp,x
1217 ldd temp3,y+o_seekdsk
1218 rcall dsk_rw_hostbuf
1219 pop temp ;get back buffer number (which part of hostbuf)
1220 ldiw y,fsys_vars
1221
1222; copy data to or from buffer
1223
1224 ldiw z,hostbuf
1225 ldi temp3,128
1226 mul temp,temp3
1227 add zl,r0 ;offset in hostbuf
1228 adc zh,r1
1229
1230 ldd xl,y+o_dmaadr
1231 ldd xh,y+o_dmaadr+1
1232 sbic flags,readop ;which way?
1233 rjmp dsk_rmove ;skip if read
1234
1235; mark write operation
1236 sbi flags,hostwrt ;hostwrt = 1
1237dsk_wmove:
1238 mem_read
1239 st z+,temp
1240 adiw xl,1
1241 dec temp3
1242 brne dsk_wmove
1243 rjmp dsk_rwmfin
1244
1245dsk_rmove:
1246 ld temp,z+
1247 mem_write
1248 adiw xl,1
1249 dec temp3
1250 brne dsk_rmove
1251
1252dsk_rwmfin:
1253; data has been moved to/from host buffer
1254 ldd temp,y+o_wrtype ;write type
1255 cpi temp,WRDIR ;to directory?
1256 breq dsk_wdir
1257 ret ;no further processing
1258
1259; clear host buffer for directory write
1260dsk_wdir:
1261 ldd temp,y+o_erflag
1262 tst temp ;errors?
1263 breq dsk_wdir1
1264 ret ;skip if so
1265
1266dsk_wdir1:
1267 rcall dsk_writehost ;clear host buff
1268 cbi flags,hostwrt ;buffer written
1269 ret
1270
1271; ====================================================================
1272; Function:
1273; ====================================================================
1274; Parameters
1275; --------------------------------------------------------------------
1276; Registers : temp2:temp block to read (lba)
1277; temp3 disk #
1278;
1279; --------------------------------------------------------------------
1280; Description:
1281; ====================================================================
1282
1283dsk_readhost_lba:
1284
1285.if HOSTRW_DEBUG
1286 printnewline
1287 printstring "Readhost LBA"
1288.endif
1289 sbi flags,rsflag ;must read data
1290 rcall dsk_rw_hostbuf
1291 lds temp,erflag ;returns 0, if ok
1292 tst temp
1293 ret
1294
1295; ====================================================================
1296; Function: Get physical disk sector in hostbuf.
1297; ====================================================================
1298; Parameters
1299; --------------------------------------------------------------------
1300; Registers : temp2:temp host block to read/write (lba)
1301; temp3 disk #
1302;
1303; --------------------------------------------------------------------
1304; Description:
1305; ====================================================================
1306dsk_rw_hostbuf:
1307 ldiw y,fsys_vars
1308 ;xh:xl = host block to seek
1309 std y+o_erflag,_0 ;no errors (yet)
1310
1311; active host sector?
1312
1313 in _tmp0,flags ;host active flag
1314 sbi flags,hostact ;always becomes 1
1315 sbrs _tmp0,hostact ;was it already?
1316 rjmp dsk_filhst ;fill host if not
1317
1318; host buffer active, same as seek buffer?
1319
1320 ldd _tmp0,y+o_hostdsk ;same disk?
1321 cp temp3,_tmp0 ;seekdsk = hostdsk?
1322 brne dsk_nomatch
1323
1324; same disk, same block?
1325
1326 ldd _tmp0,y+o_hostlba
1327 cp temp, _tmp0
1328 ldd _tmp0,y+o_hostlba+1
1329 cpc temp2,_tmp0
1330 breq dsk_match
1331
1332dsk_nomatch:
1333 ;proper disk, but not correct sector
1334 sbis flags,hostwrt ;host written?
1335 rjmp dsk_filhst
1336 push temp3
1337 push temp2
1338 push temp
1339 rcall dsk_writehost ;clear host buff
1340 pop temp
1341 pop temp2
1342 pop temp3
1343
1344; may have to fill the host buffer
1345dsk_filhst:
1346 ldiw y,fsys_vars
1347 std y+o_hostlba,temp
1348 std y+o_hostlba+1,temp2
1349 std y+o_hostdsk,temp3
1350
1351 sbic flags,rsflag ;need to read?
1352 rcall dsk_readhost ;yes, if 1
1353 cbi flags,hostwrt ;no pending write
1354
1355dsk_match:
1356 ret
1357
1358; ====================================================================
1359; Function: Does a Disk write operation
1360; ====================================================================
1361; Parameters
1362; --------------------------------------------------------------------
1363; Registers : none
1364; Variables : [r] seekdsk Number of Disk to Read
1365; [r] seeksec Sector to read
1366; [r] seektrk Track to read
1367; --------------------------------------------------------------------
1368; Description:
1369; ====================================================================
1370
1371dsk_writehost:
1372
1373.if HOSTRW_DEBUG
1374.if DISK_DEBUG == 0
1375 printnewline
1376 printstring "Host write: "
1377.else
1378 printstring ", hst WR "
1379.endif
1380.endif
1381
1382 rcall dsk_hostparam
1383 breq dsk_hstwr_err
1384
1385 ldiw z,hostbuf
1386 rcall mmcWriteSect
1387 tst temp
1388 brne dsk_hstwr_err
1389
1390dsk_hstwr_ok:
1391 sts erflag,_0
1392 ret
1393
1394dsk_hstwr_err:
1395 sts erflag,_255
1396 ret
1397
1398; ====================================================================
1399; Function: Does a Disk read operation
1400; ====================================================================
1401; Parameters
1402; --------------------------------------------------------------------
1403; Registers : none
1404; Variables : [r] seekdsk Number of Disk to Read
1405; [r] seeksec Sector to read
1406; [r] seektrk Track to read
1407; --------------------------------------------------------------------
1408; Description:
1409; ====================================================================
1410
1411dsk_readhost:
1412
1413.if HOSTRW_DEBUG
1414.if DISK_DEBUG == 0
1415 printnewline
1416 printstring "Host read: "
1417.else
1418 printstring ", hst RD "
1419.endif
1420.endif
1421
1422 rcall dsk_hostparam
1423 breq dsk_hstrd_err
1424
1425 ldiw z,hostbuf
1426 rcall mmcReadSect
1427 tst temp
1428 brne dsk_hstrd_err
1429
1430dsk_hstrd_ok:
1431 sts erflag,_0
1432 ret
1433
1434dsk_hstrd_err:
1435 sts erflag,_255
1436 ret
1437
1438; ====================================================================
1439; Function: Does a Disk write operation
1440; ====================================================================
1441; Parameters
1442; --------------------------------------------------------------------
1443; Registers : none
1444; Variables : [r] seekdsk Number of Disk to Read
1445; [r] seeksec Sector to read
1446; [r] seektrk Track to read
1447; hostdsk = host disk #, (partition #)
1448; hostlba = host block #, relative to partition start
1449; Read/Write "hostsize" bytes to/from hostbuf
1450; --------------------------------------------------------------------
1451; Description:
1452; ====================================================================
1453
1454dsk_hostparam:
1455
1456 lds zl,hostdsk
1457
1458.if HOSTRW_DEBUG
1459 mov temp,zl
1460 subi temp,-('A')
1461 lcall uartputc
1462.endif
1463 rcall dsk_getpartentry
1464 lds xl,hostlba ; get sector to access
1465 lds xh,hostlba+1
1466
1467.if HOSTRW_DEBUG
1468 printstring ": lba "
1469 push r15
1470 push r14
1471 clr r14
1472 clr r15
1473 movw temp,x
1474 lcall print_ultoa
1475 pop r14
1476 pop r15
1477.endif
1478
1479 ldd _tmp0,z+PTAB_SIZE ; get disksize
1480 ldd _tmp1,z+PTAB_SIZE+1
1481
1482 cp xl,_tmp0 ; check given sector against disksize
1483 cpc xh,_tmp1
1484 brcc dsk_hst_param_err
1485
1486 ldd temp,z+PTAB_TYPE
1487 andi temp,dskType_MASK
1488
1489#if FAT16_SUPPORT
1490; Is it a FAT16 Diskimage ?
1491 cpi temp,dskType_FAT
1492 brne dsk_hstpar_nofat
1493 rcall fat_lba_to_phys
1494 rjmp dsk_hstpar_gotit
1495dsk_hstpar_nofat:
1496#endif
1497#if CPMDSK_SUPPORT
1498; Is it a CP/M Partition ?
1499 cpi temp,dskType_CPM
1500 brne dsk_hstpar_nocpm
1501 rcall cpm_lba_to_phys
1502 rjmp dsk_hstpar_gotit
1503dsk_hstpar_nocpm:
1504#endif
1505; Disktype not supported
1506 rjmp dsk_hst_param_err
1507
1508dsk_hstpar_gotit:
1509
1510.if HOSTRW_DEBUG
1511 printstring ", abs "
1512 push r15
1513 push r14
1514 push temp2
1515 push temp
1516 movw temp,x
1517 movw r14,y
1518 lcall print_ultoa
1519 pop temp
1520 pop temp2
1521 pop r14
1522 pop r15
1523.endif
1524
1525 ori temp,255
1526 ret
1527
1528dsk_hst_param_err:
1529
1530.if HOSTRW_DEBUG
1531 printstring ", max: "
1532 push r15
1533 push r14
1534 push temp2
1535 push temp
1536 movw temp,_tmp0
1537 clr r14
1538 clr r15
1539 lcall print_ultoa
1540 pop temp
1541 pop temp2
1542 pop r14
1543 pop r15
1544 printstring " "
1545.endif
1546
1547 clr temp
1548 ret
1549
1550; --------------------------------------------------------------------
1551; vim:set ts=8 noet nowrap
1552