]> cloudbase.mooo.com Git - avrcpm.git/blob - avrcpm/avr/dsk_fsys.asm
* Merged fat16-test back into trunk.
[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 = 8 ;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 ;dpb243
391 .db 0x1A,0x00 ;spt
392 .db 0x03,0x07 ;block shift, bock mask
393 .db 0x00,0xF2 ;extent mask, low(disk size -1),
394 .db 0x00,0x3F ;high(disk size -1), low(dir max)
395 .db 0x00,0xC0 ;high(dir max), alloc0
396 .db 0x00,0x10 ;alloc1, low(chk size)
397 .db 0x00,0x02 ;high(chk size), low(offset)
398 .db 0x00,0x00 ;high(offset), fill
399 ;dpb243
400 .db 0x1A,0x00 ;spt
401 .db 0x03,0x07 ;block shift, bock mask
402 .db 0x00,0xF2 ;extent mask, low(disk size -1),
403 .db 0x00,0x3F ;high(disk size -1), low(dir max)
404 .db 0x00,0xC0 ;high(dir max), alloc0
405 .db 0x00,0x10 ;alloc1, low(chk size)
406 .db 0x00,0x02 ;high(chk size), low(offset)
407 .db 0x00,0x00 ;high(offset), fill
408 ;dpb243
409 .db 0x1A,0x00 ;spt
410 .db 0x03,0x07 ;block shift, bock mask
411 .db 0x00,0xF2 ;extent mask, low(disk size -1),
412 .db 0x00,0x3F ;high(disk size -1), low(dir max)
413 .db 0x00,0xC0 ;high(dir max), alloc0
414 .db 0x00,0x10 ;alloc1, low(chk size)
415 .db 0x00,0x02 ;high(chk size), low(offset)
416 .db 0x00,0x00 ;high(offset), fill
417 ;dpb243
418 .db 0x1A,0x00 ;spt
419 .db 0x03,0x07 ;block shift, bock mask
420 .db 0x00,0xF2 ;extent mask, low(disk size -1),
421 .db 0x00,0x3F ;high(disk size -1), low(dir max)
422 .db 0x00,0xC0 ;high(dir max), alloc0
423 .db 0x00,0x10 ;alloc1, low(chk size)
424 .db 0x00,0x02 ;high(chk size), low(offset)
425 .db 0x00,0x00 ;high(offset), fill
426 #if 0
427 ;rd1016
428 .db 0x20,0x00 ;spt
429 .db 0x04,0x0F ;block shift, bock mask
430 .db 0x00,0xFB ;extent mask, low(disk size -1),
431 .db 0x01,0xBF ;high(disk size -1), low(dir max)
432 .db 0x00,0xE0 ;high(dir max), alloc0
433 .db 0x00,0x30 ;alloc1, low(chk size)
434 .db 0x00,0x02 ;high(chk size), low(offset)
435 .db 0x00,0x00 ;high(offset), fill
436 ;rd9192s
437 .db 0x20,0x00 ;spt
438 .db 0x05,0x1F ;block shift, bock mask
439 .db 0x01,0xFD ;extent mask, low(disk size -1),
440 .db 0x07,0xFF ;high(disk size -1), low(dir max)
441 .db 0x01,0xF0 ;high(dir max), alloc0
442 .db 0x00,0x80 ;alloc1, low(chk size)
443 .db 0x00,0x02 ;high(chk size), low(offset)
444 .db 0x00,0x00 ;high(offset), fill
445 #endif
446
447 ; Test
448 cpy_dpb:
449 push zh
450 push zl
451 push yh
452 push yl
453 ldiw z,dpblist*2
454 ldi temp2,16
455 mul temp,temp2
456 add zl,_tmp0
457 adc zh,_tmp1
458 ldiw y,tmpdpb
459 cpydpb_l:
460 lpm temp,z+
461 st y+,temp
462 cpi yl,low(tmpdpb + 15)
463 brne cpydpb_l
464 pop yl
465 pop yh
466 pop zl
467 pop zh
468 ret
469
470 ; ====================================================================
471 ; Function: Clear drive table
472 ; ====================================================================
473 ; Parameters
474 ; --------------------------------------------------------------------
475 ; Registers :
476 ; Variables :
477 ;
478 ; --------------------------------------------------------------------
479 ; Description:
480 ; ====================================================================
481
482 ; For now, only entries 1 - 7 are cleared.
483
484 dsk_drvtblinit:
485 ldsw x,biosdrvtbl
486 adiw x,2
487 ldi temp3,7
488 dsk_drvi_l:
489 ldi temp,0
490 ldi temp2,0
491 rcall dram_writew_pp
492 dec temp3
493 brne dsk_drvi_l
494
495 lds temp,biosenddat
496 lds temp2,biosenddat+1
497 rcall heap_init
498 clr temp
499 ret
500
501
502 ; ----------------------------------------------------------------------
503 ; Init CP/M data structures
504 ; temp = drive #
505 ;
506 ; return !0 if ok
507 ; 0 on error
508
509
510 dsk_diskinit:
511 mov temp3,temp ;save disk #
512
513
514 ; Test
515 rcall cpy_dpb
516
517
518
519
520 ; get mem for DPH
521 ; -----------------------------------------------------------------
522 ; DPH: | XLT | | | |DIRBUF | DPB | CSV | ALV |
523 ; -----------------------------------------------------------------
524 ;(offset) 0 2 4 6 8 10 12 14
525
526 ldi temp, low (16)
527 ldi temp2,high(16)
528 rcall heap_get
529 brne dsk_di_1
530 rjmp dsk_di_err ;
531 dsk_di_1:
532 movw x,temp
533 movw y,temp
534 ldi temp,0
535 ldi temp2,0
536 rcall dram_writew_pp ;XLT
537 adiw x,6
538 lds temp,biosdirbuf
539 lds temp2,biosdirbuf+1
540 rcall dram_writew_pp ;DIRBUF
541
542 ; get mem for DPB
543 ; -------------------------------------------------------------
544 ; DPB: | SPT |BSH|BLM|EXM| DSM | DRM |AL0|AL1| CKS | OFF |
545 ; -------------------------------------------------------------
546 ; 0 5 7 11 13
547
548 ldi temp, low (15)
549 ldi temp2,high(15)
550 rcall heap_get
551 breq dsk_di_err_p1
552 movw x,temp
553
554 ldiw z,tmpdpb
555 dsk_dicpl:
556 ld temp,z+
557 rcall dram_write_pp
558 cpi zl,low(tmpdpb + 15)
559 brne dsk_dicpl
560 sbiw x,15
561 movw temp,x
562 movw x,y
563 adiw x,10
564 rcall dram_writew_pp ;DPB
565
566 ; get mem for dir check vector
567
568 lds temp,tmpdpb+11 ;cks
569 lds temp2,tmpdpb+11+1
570 cp temp,_0
571 cpc temp2,_0
572 breq dsk_dicks0
573 rcall heap_get
574 breq dsk_di_err_p1
575 dsk_dicks0:
576 rcall dram_writew_pp ;CSV
577
578 ; get mem for alloc vector
579
580 lds temp,tmpdpb+5 ;dsm
581 lds temp2,tmpdpb+5+1
582 subi temp, low (-8)
583 sbci temp2,high(-8)
584 lsr temp2
585 ror temp
586 lsr temp2
587 ror temp
588 lsr temp2
589 ror temp ;(dsm+1+7)/8
590 rcall heap_get
591 breq dsk_di_err_p1
592 rcall dram_writew_pp ;ALV
593
594 ; success, insert DPH into drvtbl
595
596 lds xl,biosdrvtbl
597 lds xh,biosdrvtbl+1
598 lsl temp3 ;drive #
599 add xl,temp3
600 adc xh,_0
601 movw temp,y
602 rcall dram_writew_pp
603 ori temp,0xff ;return ok
604 ret
605
606 ; error, free mem
607
608 dsk_di_err_p1:
609 movw temp,y
610 rcall heap_release
611 dsk_di_err:
612 eor temp,temp ;return 0 (+ Z-flag)
613 ret
614
615
616 ; ====================================================================
617 ; Function: Does a Disk interaction
618 ; ====================================================================
619 ; Parameters
620 ; --------------------------------------------------------------------
621 ; Registers : none
622 ; Variables : [r] seeksec Sector to read
623 ; [r] seektrk Track to read
624 ; --------------------------------------------------------------------
625 ; Description:
626 ; ====================================================================
627 dskDoIt:
628 .if DISK_DEBUG
629 push temp
630 sbrc temp,READ_FUNC
631 rjmp dskdbgr
632 sbrc temp,WRITE_FUNC
633 rjmp dskdbgw
634 rjmp dskdbge
635
636 dskdbgr:
637 printnewline
638 printstring "Disk read: "
639 rjmp dskdbg1
640 dskdbgw:
641 printnewline
642 printstring "Disk write: "
643 dskdbg1:
644 lds temp,seekdsk
645 subi temp,-('A')
646 rcall uartputc
647 printstring ": track "
648 lds temp2,seektrk+1
649 lds temp,seektrk
650 rcall printhexw
651 printstring ", sector "
652 lds temp,seeksec
653 rcall printhex
654 printstring ", dma-addr "
655 lds temp2,dmaadr+1
656 lds temp,dmaadr
657 rcall printhexw
658 pop temp
659 push temp
660 sbrs temp,WRITE_FUNC
661 rjmp dskdbge
662 printstring " wrtype "
663 andi temp,3
664 rcall printhex
665 dskdbge:
666 pop temp
667 .endif
668 ;See what has to be done.
669 sbrc temp,READ_FUNC
670 rjmp dsk_read
671 sbrc temp,WRITE_FUNC
672 rjmp dsk_write
673 sbrc temp,HOME_FUNC
674 rjmp dsk_home
675 sbrc temp,BOOT_FUNC
676 rjmp dsk_boot
677
678 printstring "DISK I/O: Invalid Function code: "
679 rcall printhex
680 rjmp haltinv
681
682 dsk_boot:
683 sts ndisks,_0 ;no active partitions
684 dsk_cboot:
685 cbi flags,hostact ;host buffer inactive
686 sts unacnt,_0 ;clear unalloc count
687 ret
688
689 dsk_home:
690 sbis flags,hostwrt ;check for pending write
691 cbi flags,hostact ;clear host active flag
692 ret
693
694
695
696 ; ====================================================================
697 ; Function: Does a Disk read operation
698 ; ====================================================================
699 ; Parameters
700 ; --------------------------------------------------------------------
701 ; Registers : in: temp
702 ; Variables : [r] seekdsk Number of Disk to Read
703 ; [r] seeksec Sector to read
704 ; [r] seektrk Track to read
705 ; --------------------------------------------------------------------
706 ; Description:
707 ; ====================================================================
708 dsk_read:
709 sts erflag,_0
710 sbi flags,readop ; Set read operation flag
711
712 ;RAM disk?
713 lds xl,seekdsk
714 #if RAMDISKCNT
715 cpi xl,RAMDISKNR
716 brlt PC+2
717 rjmp rdsk_read
718 #endif
719 rcall dsk_getpartentry ; Get Paritiontableentry
720 ld temp,z ; Get Partitiontype
721
722 ; Isn't it a Disk ?
723 cpi temp,dskType_None
724 brne PC+2
725 rjmp dsk_read_err
726 ; It must be a FAT16-Imagefile or CP/M Partition.
727 sts unacnt,_0
728 sbi flags,rsflag ;must read data
729 ldi temp,WRUAL ;write type
730 sts wrtype,temp ;treat as unalloc
731 rjmp dsk_rwoper ;to perform the read
732
733 dsk_read_err:
734 ret
735
736 ; ====================================================================
737 ; Function: Does a Disk write operation
738 ; ====================================================================
739 ; Parameters
740 ; --------------------------------------------------------------------
741 ; Registers : in: temp Write type
742 ; Variables : [r] seekdsk Number of Disk to Read
743 ; [r] seeksec Sector to read
744 ; [r] seektrk Track to read
745 ; --------------------------------------------------------------------
746 ; Description:
747 ; ====================================================================
748 dsk_write:
749 ;write the selected sector
750 sts erflag,_0
751 cbi flags,readop ; not a read operation
752 ;RAM disk?
753 lds xl,seekdsk
754 #if RAMDISKCNT
755 cpi xl,RAMDISKNR
756 brlt PC+2
757 rjmp rdsk_write
758 #endif
759 rcall dsk_getpartentry ; Get Paritiontableentry
760 ld temp2,z ; Get Partitiontype
761
762 ; Isn't it a Disk ?
763 cpi temp2,dskType_None
764 brne PC+2
765 rjmp dsk_write_err
766
767
768 ; It must be a FAT16-Imagefile or CP/M Partition.
769
770 cbi flags,readop ;not a read operation
771
772 andi temp,WRTMSK
773 sts wrtype,temp ;save write type
774
775 cpi temp,WRUAL ;write unallocated?
776 brne dsk_chkuna ;check for unalloc
777
778 ; write to unallocated, set parameters
779 ldi temp,blksize/128 ;next unalloc recs
780 sts unacnt,temp
781 lds temp,seekdsk ;disk to seek
782 sts unadsk,temp ;unadsk = sekdsk
783 lds temp,seektrk
784 sts unatrk,temp ;unatrk = sectrk
785 lds temp,seektrk+1
786 sts unatrk+1,temp ;unatrk = sectrk
787 lds temp,seeksec
788 sts unasec,temp ;unasec = seksec
789 ;
790 dsk_chkuna:
791 ;check for write to unallocated sector
792 lds temp,unacnt ;any unalloc remain?
793 tst temp
794 breq dsk_alloc ;skip if not
795
796 ; more unallocated records remain
797 dec temp ;unacnt = unacnt-1
798 sts unacnt,temp
799 lds temp,seekdsk ;same disk?
800 lds temp2,unadsk
801 cp temp,temp2 ;seekdsk = unadsk?
802 brne dsk_alloc ;skip if not
803
804 ; disks are the same
805 lds temp,unatrk
806 lds temp2,unatrk+1
807 lds temp3,seektrk
808 lds temp4,seektrk+1
809 cp temp,temp3 ;seektrk = unatrk?
810 cpc temp2,temp4
811 brne dsk_alloc ;skip if not
812
813 ; tracks are the same
814 lds temp,seeksec ;same sector?
815 lds temp2,unasec
816 cp temp,temp2 ;seeksec = unasec?
817 brne dsk_alloc ;skip if not
818
819 ; match, move to next sector for future ref
820 inc temp2 ;unasec = unasec+1
821 sts unasec,temp2
822 cpi temp2,CPMSPT ;end of track? (count CP/M sectors)
823 brlo dsk_noovf ;skip if no overflow
824
825 ; overflow to next track
826 sts unasec,_0 ;unasec = 0
827 lds temp,unatrk
828 lds temp2,unatrk+1
829 subi temp, low(-1) ;unatrk = unatrk+1
830 sbci temp2,high(-1)
831 sts unatrk,temp
832 sts unatrk+1,temp2
833 ;
834 dsk_noovf:
835 cbi flags,rsflag ;rsflag = 0
836 rjmp dsk_rwoper ;to perform the write
837 ;
838 dsk_alloc:
839 ;not an unallocated record, requires pre-read
840 sts unacnt,_0 ;unacnt = 0
841 sbi flags,rsflag ;rsflag = 1
842 rjmp dsk_rwoper
843
844 dsk_write_err:
845 ret
846
847 ; ====================================================================
848 ; Function: Does a Disk read/write operation
849 ; ====================================================================
850 ; Parameters
851 ; --------------------------------------------------------------------
852 ; Registers : none
853 ; Variables : [r] seekdsk Number of Disk to Read
854 ; [r] seeksec Sector to read
855 ; [r] seektrk Track to read
856 ; --------------------------------------------------------------------
857 ; Description:
858 ; ====================================================================
859 dsk_rwoper:
860 ;enter here to perform the read/write
861 .if DISK_DEBUG
862 printstring ", flags: "
863 in temp,flags
864 rcall printhex
865 .endif
866 sts erflag,_0 ;no errors (yet)
867
868 ;Convert track/sector to an LBA address (in 128byte blocks)
869
870 lds xl,seeksec ;
871 ldi xh,0 ;
872 ldi yl,0 ;
873 lds temp3,seektrk ;
874 lds temp4,seektrk+1 ;
875 ldi temp,CPMSPT ;
876 mul temp3,temp ;
877 add xl,r0 ;
878 adc xh,r1 ;
879 mul temp4,temp ;
880 add xh,r0 ;yl:xh:xl := sec + trk * SectorsPerTrack
881 adc yl,r1 ;
882
883 mov temp,xl
884 andi temp,SECMSK ;mask buffer number
885 push temp ;save for later
886
887 ;Convert from CP/M LBA blocks to host LBA blocks
888 ldi temp,SECSHF
889 dsk_sh1:
890 lsr yl
891 ror xh
892 ror xl
893 dec temp
894 brne dsk_sh1
895 ;yl:xh:xl = host block to seek
896 ; active host sector?
897 in _tmp0,flags ;host active flag
898 sbi flags,hostact ;always becomes 1
899 sbrs _tmp0,hostact ;was it already?
900 rjmp dsk_filhst ;fill host if not
901
902 ; host buffer active, same as seek buffer?
903 lds temp,seekdsk
904 lds temp2,hostdsk ;same disk?
905 cp temp,temp2 ;seekdsk = hostdsk?
906 brne dsk_nomatch
907
908 ; same disk, same block?
909 lds temp,hostlba
910 lds temp2,hostlba+1
911 lds temp3,hostlba+2
912 cp xl,temp
913 cpc xh,temp2
914 cpc yl,temp3
915 breq dsk_match
916 ;
917 dsk_nomatch:
918 ;proper disk, but not correct sector
919 sbis flags,hostwrt ;host written?
920 rjmp dsk_filhst
921 push xl
922 push xh
923 push yl
924 rcall dsk_writehost ;clear host buff
925 pop yl
926 pop xh
927 pop xl
928
929 dsk_filhst:
930 ;may have to fill the host buffer
931 lds temp,seekdsk
932 sts hostdsk,temp
933 sts hostlba,xl
934 sts hostlba+1,xh
935 sts hostlba+2,yl
936
937 sbic flags,rsflag ;need to read?
938 rcall dsk_readhost ;yes, if 1
939 cbi flags,hostwrt ;no pending write
940
941 dsk_match:
942
943 ;copy data to or from buffer
944 ldiw z,hostbuf
945 ldi temp,128
946 pop temp2 ;get buffer number (which part of hostbuf)
947 mul temp2,temp
948 add zl,r0 ;offset in hostbuf
949 adc zh,r1
950
951 .if DISK_DEBUG > 2
952 push r0
953 push r1
954 printstring "; host buf adr: "
955 pop temp2
956 pop temp
957 rcall printhexw
958 .endif
959
960 lds xl,dmaadr
961 lds xh,dmaadr+1
962 ldi temp3,128 ;length of move
963 sbic flags,readop ;which way?
964 rjmp dsk_rmove ;skip if read
965
966 ; mark write operation
967 sbi flags,hostwrt ;hostwrt = 1
968 dsk_wmove:
969 mem_read
970 st z+,temp
971 adiw xl,1
972 dec temp3
973 brne dsk_wmove
974 rjmp dsk_rwmfin
975
976 dsk_rmove:
977 ld temp,z+
978 mem_write
979 adiw xl,1
980 dec temp3
981 brne dsk_rmove
982 dsk_rwmfin:
983 ; data has been moved to/from host buffer
984 lds temp,wrtype ;write type
985 cpi temp,WRDIR ;to directory?
986 breq dsk_wdir
987 ret ;no further processing
988 dsk_wdir:
989 ; clear host buffer for directory write
990 lds temp,erflag
991 tst temp ;errors?
992 breq dsk_wdir1
993 ret ;skip if so
994 dsk_wdir1:
995 rcall dsk_writehost ;clear host buff
996 cbi flags,hostwrt ;buffer written
997 ret
998
999 ; ====================================================================
1000 ; Function: Does a Disk write operation
1001 ; ====================================================================
1002 ; Parameters
1003 ; --------------------------------------------------------------------
1004 ; Registers : none
1005 ; Variables : [r] seekdsk Number of Disk to Read
1006 ; [r] seeksec Sector to read
1007 ; [r] seektrk Track to read
1008 ; --------------------------------------------------------------------
1009 ; Description:
1010 ; ====================================================================
1011 dsk_writehost:
1012 lds xl,hostdsk
1013 rcall dsk_getpartentry
1014 ld temp,z
1015
1016 #if FAT16_SUPPORT
1017 ; Is it a FAT16 Diskimage ?
1018 cpi temp,dskType_FAT
1019 brne PC+2
1020 rjmp fat_writehost
1021 #endif
1022
1023 ; Is it a CP/M Partition ?
1024 cpi temp,dskType_CPM
1025 brne PC+2
1026 rjmp cpm_writehost
1027 ; Disktype not supported -> Return
1028 ret
1029
1030 ; ====================================================================
1031 ; Function: Does a Disk read operation
1032 ; ====================================================================
1033 ; Parameters
1034 ; --------------------------------------------------------------------
1035 ; Registers : none
1036 ; Variables : [r] seekdsk Number of Disk to Read
1037 ; [r] seeksec Sector to read
1038 ; [r] seektrk Track to read
1039 ; --------------------------------------------------------------------
1040 ; Description:
1041 ; ====================================================================
1042 dsk_readhost:
1043 lds xl,hostdsk
1044 rcall dsk_getpartentry
1045 ld temp,z
1046
1047 #if FAT16_SUPPORT
1048 ; Is it a FAT16 Diskimage ?
1049 cpi temp,dskType_FAT
1050 brne PC+2
1051 rjmp fat_readhost
1052 #endif
1053
1054 ; Is it a CP/M Partition ?
1055 cpi temp,dskType_CPM
1056 brne PC+2
1057 rjmp cpm_readhost
1058 ; Disktype not supported -> Return
1059 ret
1060