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