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