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