1 ; Filesystem functions for the Interaction with BIOS and Disks
3 ; Copyright (C) 2010 Frank Zoll
5 ; This file is part of avrcpm.
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.
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.
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/>.
24 ; ---------------- Defines for the Filesystem Interface -------
27 ;*****************************************************
28 ;* Disk-Manager constants *
29 ;*****************************************************
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
46 .equ SECMSK = hostblk-1 ;sector mask
47 .equ SECSHF = log2(hostblk) ;sector shift
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 ;----------------------------------------------- Start of Data Segment
60 ndisks: .byte 1 ;Number of CP/M disks
62 seekdsk: .byte 1 ;seek disk number
63 seektrk: .byte 2 ;seek track number
64 seeksec: .byte 1 ;seek sector number
66 unacnt: .byte 1 ;unalloc rec cnt
67 unadsk: .byte 1 ;last unalloc disk
68 unatrk: .byte 2 ;last unalloc track
69 unasec: .byte 1 ;last unalloc sector
71 erflag: .byte 1 ;error reporting
72 wrtype: .byte 1 ;write operation type
73 dmaadr: .byte 2 ;last dma address
75 hostbuf: .byte hostsize ;host buffer (from/to SD-card)
76 hostparttbl: .byte PARTENTRY_SIZE*MAXDISKS ;host partition table (type, start sector, sector count)
78 hostdsk: .byte 1 ;host disk number
79 hosttype: .byte 1 ;host disk type (same entry as 1 parition entry)
80 hostlba: .byte 3 ;host sector number (relative to partition start)
83 ; ------------------------------- Start of Code Segment
86 ; ====================================================================
87 ; Function: Get a Pointer to a Partitiontable entry
88 ; ====================================================================
90 ; --------------------------------------------------------------------
91 ; Registers : [w] z Pointer to the Partitionentry
92 ; [r] xl Number of Diskentry to Read
93 ; --------------------------------------------------------------------
95 ; ====================================================================
101 dsk_getpartentryloop:
103 breq dsk_getpartentryloopend
104 adiw z,PARTENTRY_SIZE
106 rjmp dsk_getpartentryloop
107 dsk_getpartentryloopend:
110 ; ====================================================================
112 ; ====================================================================
114 ; --------------------------------------------------------------------
116 ; Variables : [r] seeksec Sector to read
117 ; [r] seektrk Track to read
118 ; --------------------------------------------------------------------
120 ; ====================================================================
124 brsh dsk_dchrd ;maybe ramdisk
126 ; Check if selected disk # is less then # of disks.
134 rcall mgr_init_partitions
148 cpi temp,RAMDISKNR+RAMDISKCNT
152 ldi temp,0xff ;error return
184 ; ====================================================================
185 ; Function: Does a Disk interaction
186 ; ====================================================================
188 ; --------------------------------------------------------------------
190 ; Variables : [r] seeksec Sector to read
191 ; [r] seektrk Track to read
192 ; --------------------------------------------------------------------
194 ; ====================================================================
206 printstring "Disk read: "
210 printstring "Disk write: "
215 printstring ": track "
219 printstring ", sector "
222 printstring ", dma-addr "
230 printstring " wrtype "
236 ;See what has to be done.
246 printstring "DISK I/O: Invalid Function code: "
251 sts ndisks,_0 ;no active partitions
253 cbi flags,hostact ;host buffer inactive
254 sts unacnt,_0 ;clear unalloc count
258 sbis flags,hostwrt ;check for pending write
259 cbi flags,hostact ;clear host active flag
264 ; ====================================================================
265 ; Function: Does a Disk read operation
266 ; ====================================================================
268 ; --------------------------------------------------------------------
270 ; Variables : [r] seekdsk Number of Disk to Read
271 ; [r] seeksec Sector to read
272 ; [r] seektrk Track to read
273 ; --------------------------------------------------------------------
275 ; ====================================================================
278 sbi flags,readop ; Set read operation flag
280 rcall dsk_getpartentry ; Get Paritiontableentry
281 ld temp,z ; Get Partitiontype
284 cpi temp,dskType_None
291 ; It must be a FAT16-Imagefile or CP/M Partition.
293 sbi flags,rsflag ;must read data
294 ldi temp,WRUAL ;write type
295 sts wrtype,temp ;treat as unalloc
296 rjmp dsk_rwoper ;to perform the read
301 ; ====================================================================
302 ; Function: Does a Disk write operation
303 ; ====================================================================
305 ; --------------------------------------------------------------------
307 ; Variables : [r] seekdsk Number of Disk to Read
308 ; [r] seeksec Sector to read
309 ; [r] seektrk Track to read
310 ; --------------------------------------------------------------------
312 ; ====================================================================
314 ;write the selected sector
316 cbi flags,readop ; not a read operation
318 rcall dsk_getpartentry ; Get Paritiontableentry
319 ld temp,z ; Get Partitiontype
322 cpi temp,dskType_None
331 ; It must be a FAT16-Imagefile or CP/M Partition.
333 cbi flags,readop ;not a read operation
336 sts wrtype,temp ;save write type
338 cpi temp,WRUAL ;write unallocated?
339 brne dsk_chkuna ;check for unalloc
341 ; write to unallocated, set parameters
342 ldi temp,blksize/128 ;next unalloc recs
344 lds temp,seekdsk ;disk to seek
345 sts unadsk,temp ;unadsk = sekdsk
347 sts unatrk,temp ;unatrk = sectrk
349 sts unatrk+1,temp ;unatrk = sectrk
351 sts unasec,temp ;unasec = seksec
354 ;check for write to unallocated sector
355 lds temp,unacnt ;any unalloc remain?
357 breq dsk_alloc ;skip if not
359 ; more unallocated records remain
360 dec temp ;unacnt = unacnt-1
362 lds temp,seekdsk ;same disk?
364 cp temp,temp2 ;seekdsk = unadsk?
365 brne dsk_alloc ;skip if not
372 cp temp,temp3 ;seektrk = unatrk?
374 brne dsk_alloc ;skip if not
376 ; tracks are the same
377 lds temp,seeksec ;same sector?
379 cp temp,temp2 ;seeksec = unasec?
380 brne dsk_alloc ;skip if not
382 ; match, move to next sector for future ref
383 inc temp2 ;unasec = unasec+1
385 cpi temp2,CPMSPT ;end of track? (count CP/M sectors)
386 brlo dsk_noovf ;skip if no overflow
388 ; overflow to next track
389 sts unasec,_0 ;unasec = 0
392 subi temp, low(-1) ;unatrk = unatrk+1
398 cbi flags,rsflag ;rsflag = 0
399 rjmp dsk_rwoper ;to perform the write
402 ;not an unallocated record, requires pre-read
403 sts unacnt,_0 ;unacnt = 0
404 sbi flags,rsflag ;rsflag = 1
410 ; ====================================================================
411 ; Function: Does a Disk read/write operation
412 ; ====================================================================
414 ; --------------------------------------------------------------------
416 ; Variables : [r] seekdsk Number of Disk to Read
417 ; [r] seeksec Sector to read
418 ; [r] seektrk Track to read
419 ; --------------------------------------------------------------------
421 ; ====================================================================
423 ;enter here to perform the read/write
425 printstring ", flags: "
429 sts erflag,_0 ;no errors (yet)
431 ;Convert track/sector to an LBA address (in 128byte blocks)
437 lds temp4,seektrk+1 ;
443 add xh,r0 ;yl:xh:xl := sec + trk * SectorsPerTrack
447 andi temp,SECMSK ;mask buffer number
448 push temp ;save for later
450 ;Convert from CP/M LBA blocks to host LBA blocks
458 ;yl:xh:xl = host block to seek
459 ; active host sector?
460 in _tmp0,flags ;host active flag
461 sbi flags,hostact ;always becomes 1
462 sbrs _tmp0,hostact ;was it already?
463 rjmp dsk_filhst ;fill host if not
465 ; host buffer active, same as seek buffer?
467 lds temp2,hostdsk ;same disk?
468 cp temp,temp2 ;seekdsk = hostdsk?
471 ; same disk, same block?
481 ;proper disk, but not correct sector
482 sbis flags,hostwrt ;host written?
487 rcall dsk_writehost ;clear host buff
493 ;may have to fill the host buffer
500 sbic flags,rsflag ;need to read?
501 rcall dsk_readhost ;yes, if 1
502 cbi flags,hostwrt ;no pending write
506 ;copy data to or from buffer
509 pop temp2 ;get buffer number (which part of hostbuf)
511 add zl,r0 ;offset in hostbuf
517 printstring "; host buf adr: "
525 ldi temp3,128 ;length of move
526 sbic flags,readop ;which way?
527 rjmp dsk_rmove ;skip if read
529 ; mark write operation
530 sbi flags,hostwrt ;hostwrt = 1
546 ; data has been moved to/from host buffer
547 lds temp,wrtype ;write type
548 cpi temp,WRDIR ;to directory?
550 ret ;no further processing
552 ; clear host buffer for directory write
558 rcall dsk_writehost ;clear host buff
559 cbi flags,hostwrt ;buffer written
562 ; ====================================================================
563 ; Function: Does a Disk write operation
564 ; ====================================================================
566 ; --------------------------------------------------------------------
568 ; Variables : [r] seekdsk Number of Disk to Read
569 ; [r] seeksec Sector to read
570 ; [r] seektrk Track to read
571 ; --------------------------------------------------------------------
573 ; ====================================================================
576 rcall dsk_getpartentry
580 ; Is it a FAT16 Diskimage ?
586 ; Is it a CP/M Partition ?
590 ; Disktype not supported -> Return
593 ; ====================================================================
594 ; Function: Does a Disk read operation
595 ; ====================================================================
597 ; --------------------------------------------------------------------
599 ; Variables : [r] seekdsk Number of Disk to Read
600 ; [r] seeksec Sector to read
601 ; [r] seektrk Track to read
602 ; --------------------------------------------------------------------
604 ; ====================================================================
607 rcall dsk_getpartentry
611 ; Is it a FAT16 Diskimage ?
617 ; Is it a CP/M Partition ?
621 ; Disktype not supported -> Return