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