]> cloudbase.mooo.com Git - avrcpm.git/blob - avrcpm/avr/dsk_fsys.asm
* Start of dynamic disk size code.
[avrcpm.git] / avrcpm / 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 .equ dskType_None = 0
31 .equ dskType_CPM = 1
32 .equ dskType_FAT = 2
33 ; .equ dskType_RAM = 3
34
35 ;*****************************************************
36 ;* CP/M to host disk constants *
37 ;*****************************************************
38 .equ MAXDISKS = 6 ;Max number of Disks (partitions)
39 .equ PARTENTRY_SIZE = 9 ;Size of a Partitiontableentry
40 .equ blksize = 1024 ;CP/M allocation size
41 .equ hostsize = 512 ;host disk sector size
42 ; .equ hostspt = 20 ;host disk sectors/trk
43 .equ hostblk = hostsize/128 ;CP/M sects/host buff
44 ; .equ CPMSPT = hostblk*hostspt ;CP/M sectors/track
45 .equ CPMSPT = 26 ;
46 .equ SECMSK = hostblk-1 ;sector mask
47 .equ SECSHF = log2(hostblk) ;sector shift
48
49 ;*****************************************************
50 ;* BDOS constants on entry to write *
51 ;*****************************************************
52 .equ WRALL = 0 ;write to allocated
53 .equ WRDIR = 1 ;write to directory
54 .equ WRUAL = 2 ;write to unallocated
55 .equ WRTMSK= 3 ;write type mask
56
57 .equ READ_FUNC = 7
58 .equ WRITE_FUNC = 6
59 .equ BOOT_FUNC = 5
60 .equ HOME_FUNC = 4
61
62 ;----------------------------------------------- Start of Data Segment
63
64 .dseg
65
66 ; The following 3 variables are copied from DRAM.
67 ; Don't change order.
68
69 biosdrvtbl: .byte 2 ;
70 biosdirbuf: .byte 2 ;
71 biosenddat: .byte 2 ;
72
73 ndisks: .byte 1 ;Number of CP/M disks
74
75 ; The following 5 variables are accessed from 8080/z80 via the
76 ; virtual port interface. Don't change order.
77
78 biospar_base:
79 bcbadr: .byte 2 ;adr of BiosControlBlock
80 seekdsk: .byte 1 ;seek disk number
81 seektrk: .byte 2 ;seek track number
82 seeksec: .byte 2 ;seek sector number
83 dmaadr: .byte 2 ;last dma address
84
85 unacnt: .byte 1 ;unalloc rec cnt
86 unadsk: .byte 1 ;last unalloc disk
87 unatrk: .byte 2 ;last unalloc track
88 unasec: .byte 1 ;last unalloc sector
89
90 erflag: .byte 1 ;error reporting
91 wrtype: .byte 1 ;write operation type
92
93 hostbuf: .byte hostsize ;host buffer (from/to SD-card)
94 hostparttbl: .byte PARTENTRY_SIZE*MAXDISKS ;host partition table (type, start sector, sector count)
95 hostparttbltop:
96 hostdsk: .byte 1 ;host disk number
97 hosttype: .byte 1 ;host disk type (same entry as 1 parition entry)
98 hostlba: .byte 3 ;host sector number (relative to partition start)
99
100
101 ; ------------------------------- Start of Code Segment
102 .cseg
103
104 ;---------------------------------------------------------------------
105
106 .if DSKSEL_DEBUG
107
108 dbg_prdrvtbl:
109 push xh
110 push xl
111 push temp3
112 push temp2
113 push temp
114 printnewline
115 printstring "drvtbl ("
116 lds xl,biosdrvtbl
117 lds xh,biosdrvtbl+1
118 movw temp,x
119 rcall printhexw
120 printstring "): "
121 ldi temp3,16
122 dbg_pcpel:
123 rcall dram_readw_pp
124 rcall printhexw
125 printstring " "
126 dec temp3
127 brne dbg_pcpel
128 pop temp
129 pop temp2
130 pop temp3
131 pop xl
132 pop xh
133 ret
134
135 dbg_print_biosd:
136 printnewline
137 lds temp,bcbadr
138 lds temp2,bcbadr+1
139 rcall printhexw
140 printstring " "
141 lds temp,biosdrvtbl
142 lds temp2,biosdrvtbl+1
143 rcall printhexw
144 printstring " "
145 lds temp,biosdirbuf
146 lds temp2,biosdirbuf+1
147 rcall printhexw
148 printstring " "
149 lds temp,biosenddat
150 lds temp2,biosenddat+1
151 rcall printhexw
152 printstring " "
153 ret
154 .endif
155
156 ; ====================================================================
157 ; Function: Get a Pointer to a Partitiontable entry
158 ; ====================================================================
159 ; Parameters
160 ; --------------------------------------------------------------------
161 ; Registers : [w] z Pointer to the Partitionentry
162 ; [r] xl Number of Diskentry to Read
163 ; [w] _tmp0 scratch
164 ; [w] _tmp1 "
165 ; --------------------------------------------------------------------
166 ; Description:
167 ; ====================================================================
168 dsk_getpartentry:
169
170 ldi zl,PARTENTRY_SIZE
171 mul xl,zl
172 ldiw z,hostparttbl
173 add zl,_tmp0
174 add zh,_tmp1
175 ret
176
177 ; ====================================================================
178 ; Function: Virtual Port Interface
179 ; ====================================================================
180 ; Parameters
181 ; --------------------------------------------------------------------
182 ; Registers :
183 ; Variables :
184 ;
185 ; --------------------------------------------------------------------
186 ; Description:
187 ; ====================================================================
188
189 dsk_param_getadr:
190 ldiw z,biospar_base
191 add zl,temp3
192 adc zh,_0
193 ret
194
195 dsk_param_wr:
196 rcall dsk_param_getadr
197 st z,temp
198 cpi temp3,bcbadr+1-seektrk
199 brne dsk_param_wr1
200 std z+1,_0
201 dsk_param_wr1:
202 cpi temp3,bcbadr+1-biospar_base
203 breq SetBCB
204 ret
205
206 dsk_param_rd:
207 cpi temp3,seekdsk-biospar_base
208 breq dskDiskCheck
209 rcall dsk_param_getadr
210 ld temp,z
211 ret
212
213 SetBCB:
214 lds xl,bcbadr
215 mov xh,temp
216 ldiw z,biosdrvtbl
217 ldi temp3,6
218 sbcb_l:
219 rcall dram_read_pp
220 st z+,temp
221 dec temp3
222 brne sbcb_l
223
224 ; rcall dbg_print_biosd
225 rcall dsk_drvtblinit
226 ; rcall dbg_prdrvtbl
227
228 ret
229
230 ; ====================================================================
231 ; Function: Check if disk exists
232 ; ====================================================================
233 ; Parameters
234 ; --------------------------------------------------------------------
235 ; Registers :
236 ; Variables :
237 ; return 0, if selected disk not exist.
238 ; return !0, if disk exist
239 ; --------------------------------------------------------------------
240 ; Description:
241 ; ====================================================================
242 dskDiskCheck:
243 lds temp,ndisks
244 lds temp2,seekdsk
245 .if DSKSEL_DEBUG
246 printnewline
247 printstring "DiskCheck: "
248 rcall printhexw
249 .endif
250 cpi temp2,RAMDISKNR
251 brsh dsk_dchrd ;maybe ramdisk
252
253 ; Check if selected disk # is less then # of disks.
254
255 lds temp,ndisks
256 tst temp ;0 disks?
257 brne dsk_dchpart1
258
259 ; No disks yet, need to init
260
261 rcall mgr_init_partitions ;disk chanched?
262 ; sbrs temp,7
263 ; rjmp dsk_dchpart0
264 push temp
265 rcall dsk_drvtblinit
266 ; rcall dbg_prdrvtbl
267 pop temp
268 dsk_dchpart0:
269 cbr temp,0x80
270 lds temp2,seekdsk
271
272 dsk_dchpart1:
273 cp temp2,temp
274 brsh dsk_dch_err
275
276 .if DSKSEL_DEBUG
277 printnewline
278 printstring "Select: "
279 mov temp,temp2
280 rcall printhex
281 .endif
282 ldsw x,biosdrvtbl
283 lsl temp2 ;drive #
284 add xl,temp2
285 adc xh,_0
286 rcall dram_readw_pp ;get drive table entry
287
288 or temp,temp2 ;if !0, drive is allready initialized
289 brne dsk_dchend
290 lds temp,seekdsk
291 rcall dsk_diskinit
292
293 dsk_dchend:
294 .if DSKSEL_DEBUG
295 push temp
296 ldsw x,biosdrvtbl
297 lds temp,seekdsk
298 lsl temp ;drive #
299 add xl,temp
300 adc xh,_0
301 rcall dram_readw_pp
302 printstring ", "
303 rcall printhexw
304 pop temp
305 .endif
306
307 ret
308
309 dsk_dch_err:
310 ldi temp,0 ;error return
311 ret
312
313 ; Check RAMDISK
314
315 dsk_dchrd:
316 #if RAMDISKCNT
317 cpi temp,RAMDISKNR+RAMDISKCNT
318 brsh dsk_dchrd_err
319
320 ldi temp,0xff ;return ok
321 ret
322 #endif
323 dsk_dchrd_err:
324 ldi temp,0 ;error return
325 ret
326
327
328 ; ====================================================================
329 ; Function: Return status of last disk i/o function
330 ; ====================================================================
331 ; Parameters
332 ; --------------------------------------------------------------------
333 ; Registers :
334 ; Variables :
335 ; --------------------------------------------------------------------
336 ; Description:
337 ; ====================================================================
338 dskErrorRet:
339 lds temp,erflag
340 ret
341
342
343 ; -------------------------------------------------------------------
344
345
346 .dseg
347 tmpdpb: .byte 15
348
349 .cseg
350
351 ; Test DPBs (avrcpm format)
352
353 dpblist:
354 ;dpb243
355 .db 0x1A,0x00 ;spt
356 .db 0x03,0x07 ;block shift, bock mask
357 .db 0x00,0xF2 ;extent mask, low(disk size -1),
358 .db 0x00,0x3F ;high(disk size -1), low(dir max)
359 .db 0x00,0xC0 ;high(dir max), alloc0
360 .db 0x00,0x10 ;alloc1, low(chk size)
361 .db 0x00,0x02 ;high(chk size), low(offset)
362 .db 0x00,0x00 ;high(offset), fill
363 ;dpb243
364 .db 0x1A,0x00 ;spt
365 .db 0x03,0x07 ;block shift, bock mask
366 .db 0x00,0xF2 ;extent mask, low(disk size -1),
367 .db 0x00,0x3F ;high(disk size -1), low(dir max)
368 .db 0x00,0xC0 ;high(dir max), alloc0
369 .db 0x00,0x10 ;alloc1, low(chk size)
370 .db 0x00,0x02 ;high(chk size), low(offset)
371 .db 0x00,0x00 ;high(offset), fill
372 ;dpb243
373 .db 0x1A,0x00 ;spt
374 .db 0x03,0x07 ;block shift, bock mask
375 .db 0x00,0xF2 ;extent mask, low(disk size -1),
376 .db 0x00,0x3F ;high(disk size -1), low(dir max)
377 .db 0x00,0xC0 ;high(dir max), alloc0
378 .db 0x00,0x10 ;alloc1, low(chk size)
379 .db 0x00,0x02 ;high(chk size), low(offset)
380 .db 0x00,0x00 ;high(offset), fill
381 ;dpb243
382 .db 0x1A,0x00 ;spt
383 .db 0x03,0x07 ;block shift, bock mask
384 .db 0x00,0xF2 ;extent mask, low(disk size -1),
385 .db 0x00,0x3F ;high(disk size -1), low(dir max)
386 .db 0x00,0xC0 ;high(dir max), alloc0
387 .db 0x00,0x10 ;alloc1, low(chk size)
388 .db 0x00,0x02 ;high(chk size), low(offset)
389 .db 0x00,0x00 ;high(offset), fill
390 #if 0
391 ;rd1016
392 .db 0x20,0x00 ;spt
393 .db 0x04,0x0F ;block shift, bock mask
394 .db 0x00,0xFB ;extent mask, low(disk size -1),
395 .db 0x01,0xBF ;high(disk size -1), low(dir max)
396 .db 0x00,0xE0 ;high(dir max), alloc0
397 .db 0x00,0x30 ;alloc1, low(chk size)
398 .db 0x00,0x02 ;high(chk size), low(offset)
399 .db 0x00,0x00 ;high(offset), fill
400 ;rd9192s
401 .db 0x20,0x00 ;spt
402 .db 0x05,0x1F ;block shift, bock mask
403 .db 0x01,0xFD ;extent mask, low(disk size -1),
404 .db 0x07,0xFF ;high(disk size -1), low(dir max)
405 .db 0x01,0xF0 ;high(dir max), alloc0
406 .db 0x00,0x80 ;alloc1, low(chk size)
407 .db 0x00,0x02 ;high(chk size), low(offset)
408 .db 0x00,0x00 ;high(offset), fill
409 #endif
410
411 ; Test
412 cpy_dpb:
413 push zh
414 push zl
415 push yh
416 push yl
417 ldiw z,dpblist*2
418 ldi temp2,16
419 mul temp,temp2
420 add zl,_tmp0
421 adc zh,_tmp1
422 ldiw y,tmpdpb
423 cpydpb_l:
424 lpm temp,z+
425 st y+,temp
426 cpi yl,low(tmpdpb + 15)
427 brne cpydpb_l
428 pop yl
429 pop yh
430 pop zl
431 pop zh
432 ret
433
434 ; clear drive table
435 ; for now, only entries 1 - 3 are cleared.
436
437 ; ====================================================================
438 ; Function: Clear drive table
439 ; ====================================================================
440 ; Parameters
441 ; --------------------------------------------------------------------
442 ; Registers :
443 ; Variables :
444 ;
445 ; --------------------------------------------------------------------
446 ; Description:
447 ; ====================================================================
448
449 ; For now, only entries 1 - 3 are cleared.
450
451 dsk_drvtblinit:
452 ldsw x,biosdrvtbl
453 adiw x,2
454 ldi temp3,3
455 dsk_drvi_l:
456 ldi temp,0
457 ldi temp2,0
458 rcall dram_writew_pp
459 dec temp3
460 brne dsk_drvi_l
461
462 lds temp,biosenddat
463 lds temp2,biosenddat+1
464 rcall heap_init
465 clr temp
466 ret
467
468
469 ; ----------------------------------------------------------------------
470 ; Init CP/M data structures
471 ; temp = drive #
472 ;
473 ; return !0 if ok
474 ; 0 on error
475
476
477 dsk_diskinit:
478 mov temp3,temp ;save disk #
479
480
481 ; Test
482 rcall cpy_dpb
483
484
485
486
487 ; get mem for DPH
488 ; -----------------------------------------------------------------
489 ; DPH: | XLT | | | |DIRBUF | DPB | CSV | ALV |
490 ; -----------------------------------------------------------------
491 ;(offset) 0 2 4 6 8 10 12 14
492
493 ldi temp, low (16)
494 ldi temp2,high(16)
495 rcall heap_get
496 brne dsk_di_1
497 rjmp dsk_di_err ;
498 dsk_di_1:
499 movw x,temp
500 movw y,temp
501 ldi temp,0
502 ldi temp2,0
503 rcall dram_writew_pp ;XLT
504 adiw x,6
505 lds temp,biosdirbuf
506 lds temp2,biosdirbuf+1
507 rcall dram_writew_pp ;DIRBUF
508
509 ; get mem for DPB
510 ; -------------------------------------------------------------
511 ; DPB: | SPT |BSH|BLM|EXM| DSM | DRM |AL0|AL1| CKS | OFF |
512 ; -------------------------------------------------------------
513 ; 0 5 7 11 13
514
515 ldi temp, low (15)
516 ldi temp2,high(15)
517 rcall heap_get
518 breq dsk_di_err_p1
519 movw x,temp
520
521 ldiw z,tmpdpb
522 dsk_dicpl:
523 ld temp,z+
524 rcall dram_write_pp
525 cpi zl,low(tmpdpb + 15)
526 brne dsk_dicpl
527 sbiw x,15
528 movw temp,x
529 movw x,y
530 adiw x,10
531 rcall dram_writew_pp ;DPB
532
533 ; get mem for dir check vector
534
535 lds temp,tmpdpb+11 ;cks
536 lds temp2,tmpdpb+11+1
537 cp temp,_0
538 cpc temp2,_0
539 breq dsk_dicks0
540 rcall heap_get
541 breq dsk_di_err_p1
542 dsk_dicks0:
543 rcall dram_writew_pp ;CSV
544
545 ; get mem for alloc vector
546
547 lds temp,tmpdpb+5 ;dsm
548 lds temp2,tmpdpb+5+1
549 subi temp, low (-8)
550 sbci temp2,high(-8)
551 lsr temp2
552 ror temp
553 lsr temp2
554 ror temp
555 lsr temp2
556 ror temp ;(dsm+1+7)/8
557 rcall heap_get
558 breq dsk_di_err_p1
559 rcall dram_writew_pp ;ALV
560
561 ; success, insert DPH into drvtbl
562
563 lds xl,biosdrvtbl
564 lds xh,biosdrvtbl+1
565 lsl temp3 ;drive #
566 add xl,temp3
567 adc xh,_0
568 movw temp,y
569 rcall dram_writew_pp
570 ori temp,0xff ;return ok
571 ret
572
573 ; error, free mem
574
575 dsk_di_err_p1:
576 movw temp,y
577 rcall heap_release
578 dsk_di_err:
579 eor temp,temp ;return 0 (+ Z-flag)
580 ret
581
582
583 ; ====================================================================
584 ; Function: Does a Disk interaction
585 ; ====================================================================
586 ; Parameters
587 ; --------------------------------------------------------------------
588 ; Registers : none
589 ; Variables : [r] seeksec Sector to read
590 ; [r] seektrk Track to read
591 ; --------------------------------------------------------------------
592 ; Description:
593 ; ====================================================================
594 dskDoIt:
595 .if DISK_DEBUG
596 push temp
597 sbrc temp,READ_FUNC
598 rjmp dskdbgr
599 sbrc temp,WRITE_FUNC
600 rjmp dskdbgw
601 rjmp dskdbge
602
603 dskdbgr:
604 printnewline
605 printstring "Disk read: "
606 rjmp dskdbg1
607 dskdbgw:
608 printnewline
609 printstring "Disk write: "
610 dskdbg1:
611 lds temp,seekdsk
612 subi temp,-('A')
613 rcall uartputc
614 printstring ": track "
615 lds temp2,seektrk+1
616 lds temp,seektrk
617 rcall printhexw
618 printstring ", sector "
619 lds temp,seeksec
620 rcall printhex
621 printstring ", dma-addr "
622 lds temp2,dmaadr+1
623 lds temp,dmaadr
624 rcall printhexw
625 pop temp
626 push temp
627 sbrs temp,WRITE_FUNC
628 rjmp dskdbge
629 printstring " wrtype "
630 andi temp,3
631 rcall printhex
632 dskdbge:
633 pop temp
634 .endif
635 ;See what has to be done.
636 sbrc temp,READ_FUNC
637 rjmp dsk_read
638 sbrc temp,WRITE_FUNC
639 rjmp dsk_write
640 sbrc temp,HOME_FUNC
641 rjmp dsk_home
642 sbrc temp,BOOT_FUNC
643 rjmp dsk_boot
644
645 printstring "DISK I/O: Invalid Function code: "
646 rcall printhex
647 rjmp haltinv
648
649 dsk_boot:
650 sts ndisks,_0 ;no active partitions
651 dsk_cboot:
652 cbi flags,hostact ;host buffer inactive
653 sts unacnt,_0 ;clear unalloc count
654 ret
655
656 dsk_home:
657 sbis flags,hostwrt ;check for pending write
658 cbi flags,hostact ;clear host active flag
659 ret
660
661
662
663 ; ====================================================================
664 ; Function: Does a Disk read operation
665 ; ====================================================================
666 ; Parameters
667 ; --------------------------------------------------------------------
668 ; Registers : in: temp
669 ; Variables : [r] seekdsk Number of Disk to Read
670 ; [r] seeksec Sector to read
671 ; [r] seektrk Track to read
672 ; --------------------------------------------------------------------
673 ; Description:
674 ; ====================================================================
675 dsk_read:
676 sts erflag,_0
677 sbi flags,readop ; Set read operation flag
678
679 ;RAM disk?
680 lds xl,seekdsk
681 #if RAMDISKCNT
682 cpi xl,RAMDISKNR
683 brlt PC+2
684 rjmp rdsk_read
685 #endif
686 rcall dsk_getpartentry ; Get Paritiontableentry
687 ld temp,z ; Get Partitiontype
688
689 ; Isn't it a Disk ?
690 cpi temp,dskType_None
691 brne PC+2
692 rjmp dsk_read_err
693
694 ; It must be a FAT16-Imagefile or CP/M Partition.
695 sts unacnt,_0
696 sbi flags,rsflag ;must read data
697 ldi temp,WRUAL ;write type
698 sts wrtype,temp ;treat as unalloc
699 rjmp dsk_rwoper ;to perform the read
700
701 dsk_read_err:
702 ret
703
704 ; ====================================================================
705 ; Function: Does a Disk write operation
706 ; ====================================================================
707 ; Parameters
708 ; --------------------------------------------------------------------
709 ; Registers : in: temp Write type
710 ; Variables : [r] seekdsk Number of Disk to Read
711 ; [r] seeksec Sector to read
712 ; [r] seektrk Track to read
713 ; --------------------------------------------------------------------
714 ; Description:
715 ; ====================================================================
716 dsk_write:
717 ;write the selected sector
718 sts erflag,_0
719 cbi flags,readop ; not a read operation
720 ;RAM disk?
721 lds xl,seekdsk
722 #if RAMDISKCNT
723 cpi xl,RAMDISKNR
724 brlt PC+2
725 rjmp rdsk_write
726 #endif
727 rcall dsk_getpartentry ; Get Paritiontableentry
728 ld temp2,z ; Get Partitiontype
729
730 ; Isn't it a Disk ?
731 cpi temp2,dskType_None
732 brne PC+2
733 rjmp dsk_write_err
734
735
736 ; It must be a FAT16-Imagefile or CP/M Partition.
737
738 cbi flags,readop ;not a read operation
739
740 andi temp,WRTMSK
741 sts wrtype,temp ;save write type
742
743 cpi temp,WRUAL ;write unallocated?
744 brne dsk_chkuna ;check for unalloc
745
746 ; write to unallocated, set parameters
747 ldi temp,blksize/128 ;next unalloc recs
748 sts unacnt,temp
749 lds temp,seekdsk ;disk to seek
750 sts unadsk,temp ;unadsk = sekdsk
751 lds temp,seektrk
752 sts unatrk,temp ;unatrk = sectrk
753 lds temp,seektrk+1
754 sts unatrk+1,temp ;unatrk = sectrk
755 lds temp,seeksec
756 sts unasec,temp ;unasec = seksec
757 ;
758 dsk_chkuna:
759 ;check for write to unallocated sector
760 lds temp,unacnt ;any unalloc remain?
761 tst temp
762 breq dsk_alloc ;skip if not
763
764 ; more unallocated records remain
765 dec temp ;unacnt = unacnt-1
766 sts unacnt,temp
767 lds temp,seekdsk ;same disk?
768 lds temp2,unadsk
769 cp temp,temp2 ;seekdsk = unadsk?
770 brne dsk_alloc ;skip if not
771
772 ; disks are the same
773 lds temp,unatrk
774 lds temp2,unatrk+1
775 lds temp3,seektrk
776 lds temp4,seektrk+1
777 cp temp,temp3 ;seektrk = unatrk?
778 cpc temp2,temp4
779 brne dsk_alloc ;skip if not
780
781 ; tracks are the same
782 lds temp,seeksec ;same sector?
783 lds temp2,unasec
784 cp temp,temp2 ;seeksec = unasec?
785 brne dsk_alloc ;skip if not
786
787 ; match, move to next sector for future ref
788 inc temp2 ;unasec = unasec+1
789 sts unasec,temp2
790 cpi temp2,CPMSPT ;end of track? (count CP/M sectors)
791 brlo dsk_noovf ;skip if no overflow
792
793 ; overflow to next track
794 sts unasec,_0 ;unasec = 0
795 lds temp,unatrk
796 lds temp2,unatrk+1
797 subi temp, low(-1) ;unatrk = unatrk+1
798 sbci temp2,high(-1)
799 sts unatrk,temp
800 sts unatrk+1,temp2
801 ;
802 dsk_noovf:
803 cbi flags,rsflag ;rsflag = 0
804 rjmp dsk_rwoper ;to perform the write
805 ;
806 dsk_alloc:
807 ;not an unallocated record, requires pre-read
808 sts unacnt,_0 ;unacnt = 0
809 sbi flags,rsflag ;rsflag = 1
810 rjmp dsk_rwoper
811
812 dsk_write_err:
813 ret
814
815 ; ====================================================================
816 ; Function: Does a Disk read/write operation
817 ; ====================================================================
818 ; Parameters
819 ; --------------------------------------------------------------------
820 ; Registers : none
821 ; Variables : [r] seekdsk Number of Disk to Read
822 ; [r] seeksec Sector to read
823 ; [r] seektrk Track to read
824 ; --------------------------------------------------------------------
825 ; Description:
826 ; ====================================================================
827 dsk_rwoper:
828 ;enter here to perform the read/write
829 .if DISK_DEBUG
830 printstring ", flags: "
831 in temp,flags
832 rcall printhex
833 .endif
834 sts erflag,_0 ;no errors (yet)
835
836 ;Convert track/sector to an LBA address (in 128byte blocks)
837
838 lds xl,seeksec ;
839 ldi xh,0 ;
840 ldi yl,0 ;
841 lds temp3,seektrk ;
842 lds temp4,seektrk+1 ;
843 ldi temp,CPMSPT ;
844 mul temp3,temp ;
845 add xl,r0 ;
846 adc xh,r1 ;
847 mul temp4,temp ;
848 add xh,r0 ;yl:xh:xl := sec + trk * SectorsPerTrack
849 adc yl,r1 ;
850
851 mov temp,xl
852 andi temp,SECMSK ;mask buffer number
853 push temp ;save for later
854
855 ;Convert from CP/M LBA blocks to host LBA blocks
856 ldi temp,SECSHF
857 dsk_sh1:
858 lsr yl
859 ror xh
860 ror xl
861 dec temp
862 brne dsk_sh1
863 ;yl:xh:xl = host block to seek
864 ; active host sector?
865 in _tmp0,flags ;host active flag
866 sbi flags,hostact ;always becomes 1
867 sbrs _tmp0,hostact ;was it already?
868 rjmp dsk_filhst ;fill host if not
869
870 ; host buffer active, same as seek buffer?
871 lds temp,seekdsk
872 lds temp2,hostdsk ;same disk?
873 cp temp,temp2 ;seekdsk = hostdsk?
874 brne dsk_nomatch
875
876 ; same disk, same block?
877 lds temp,hostlba
878 lds temp2,hostlba+1
879 lds temp3,hostlba+2
880 cp xl,temp
881 cpc xh,temp2
882 cpc yl,temp3
883 breq dsk_match
884 ;
885 dsk_nomatch:
886 ;proper disk, but not correct sector
887 sbis flags,hostwrt ;host written?
888 rjmp dsk_filhst
889 push xl
890 push xh
891 push yl
892 rcall dsk_writehost ;clear host buff
893 pop yl
894 pop xh
895 pop xl
896
897 dsk_filhst:
898 ;may have to fill the host buffer
899 lds temp,seekdsk
900 sts hostdsk,temp
901 sts hostlba,xl
902 sts hostlba+1,xh
903 sts hostlba+2,yl
904
905 sbic flags,rsflag ;need to read?
906 rcall dsk_readhost ;yes, if 1
907 cbi flags,hostwrt ;no pending write
908
909 dsk_match:
910
911 ;copy data to or from buffer
912 ldiw z,hostbuf
913 ldi temp,128
914 pop temp2 ;get buffer number (which part of hostbuf)
915 mul temp2,temp
916 add zl,r0 ;offset in hostbuf
917 adc zh,r1
918
919 .if DISK_DEBUG > 2
920 push r0
921 push r1
922 printstring "; host buf adr: "
923 pop temp2
924 pop temp
925 rcall printhexw
926 .endif
927
928 lds xl,dmaadr
929 lds xh,dmaadr+1
930 ldi temp3,128 ;length of move
931 sbic flags,readop ;which way?
932 rjmp dsk_rmove ;skip if read
933
934 ; mark write operation
935 sbi flags,hostwrt ;hostwrt = 1
936 dsk_wmove:
937 mem_read
938 st z+,temp
939 adiw xl,1
940 dec temp3
941 brne dsk_wmove
942 rjmp dsk_rwmfin
943
944 dsk_rmove:
945 ld temp,z+
946 mem_write
947 adiw xl,1
948 dec temp3
949 brne dsk_rmove
950 dsk_rwmfin:
951 ; data has been moved to/from host buffer
952 lds temp,wrtype ;write type
953 cpi temp,WRDIR ;to directory?
954 breq dsk_wdir
955 ret ;no further processing
956 dsk_wdir:
957 ; clear host buffer for directory write
958 lds temp,erflag
959 tst temp ;errors?
960 breq dsk_wdir1
961 ret ;skip if so
962 dsk_wdir1:
963 rcall dsk_writehost ;clear host buff
964 cbi flags,hostwrt ;buffer written
965 ret
966
967 ; ====================================================================
968 ; Function: Does a Disk write operation
969 ; ====================================================================
970 ; Parameters
971 ; --------------------------------------------------------------------
972 ; Registers : none
973 ; Variables : [r] seekdsk Number of Disk to Read
974 ; [r] seeksec Sector to read
975 ; [r] seektrk Track to read
976 ; --------------------------------------------------------------------
977 ; Description:
978 ; ====================================================================
979 dsk_writehost:
980 lds xl,hostdsk
981 rcall dsk_getpartentry
982 ld temp,z
983
984 #if FAT16_SUPPORT
985 ; Is it a FAT16 Diskimage ?
986 cpi temp,dskType_FAT
987 brne PC+2
988 rjmp fat_writehost
989 #endif
990
991 ; Is it a CP/M Partition ?
992 cpi temp,dskType_CPM
993 brne PC+2
994 rjmp cpm_writehost
995 ; Disktype not supported -> Return
996 ret
997
998 ; ====================================================================
999 ; Function: Does a Disk read operation
1000 ; ====================================================================
1001 ; Parameters
1002 ; --------------------------------------------------------------------
1003 ; Registers : none
1004 ; Variables : [r] seekdsk Number of Disk to Read
1005 ; [r] seeksec Sector to read
1006 ; [r] seektrk Track to read
1007 ; --------------------------------------------------------------------
1008 ; Description:
1009 ; ====================================================================
1010 dsk_readhost:
1011 lds xl,hostdsk
1012 rcall dsk_getpartentry
1013 ld temp,z
1014
1015 #if FAT16_SUPPORT
1016 ; Is it a FAT16 Diskimage ?
1017 cpi temp,dskType_FAT
1018 brne PC+2
1019 rjmp fat_readhost
1020 #endif
1021
1022 ; Is it a CP/M Partition ?
1023 cpi temp,dskType_CPM
1024 brne PC+2
1025 rjmp cpm_readhost
1026 ; Disktype not supported -> Return
1027 ret
1028