]> cloudbase.mooo.com Git - avrcpm.git/blob - avrcpm/avr/dsk_fsys.asm
018aebafd85f5b6b071d40bcf37451fb08bfc1e5
[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
24 ; ---------------- Defines for the Filesystem Interface -------
25
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 = 4 ;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 ;----------------------------------------------- Start of Data Segment
57
58 .dseg
59
60 ndisks: .byte 1 ;Number of CP/M disks
61
62 seekdsk: .byte 1 ;seek disk number
63 seektrk: .byte 2 ;seek track number
64 seeksec: .byte 1 ;seek sector number
65
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
70
71 erflag: .byte 1 ;error reporting
72 wrtype: .byte 1 ;write operation type
73 dmaadr: .byte 2 ;last dma address
74
75 hostbuf: .byte hostsize ;host buffer (from/to SD-card)
76 hostparttbl: .byte PARTENTRY_SIZE*MAXDISKS ;host partition table (type, start sector, sector count)
77 hostparttbltop:
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)
81
82
83 ; ------------------------------- Start of Code Segment
84 .cseg
85
86 ; ====================================================================
87 ; Function: Get a Pointer to a Partitiontable entry
88 ; ====================================================================
89 ; Parameters
90 ; --------------------------------------------------------------------
91 ; Registers : [w] z Pointer to the Partitionentry
92 ; [r] xl Number of Diskentry to Read
93 ; --------------------------------------------------------------------
94 ; Description:
95 ; ====================================================================
96 dsk_getpartentry:
97
98 ldiw z,hostparttbl
99 mov temp,xl
100
101 dsk_getpartentryloop:
102 cp temp,_0
103 breq dsk_getpartentryloopend
104 adiw z,PARTENTRY_SIZE
105 dec temp
106 rjmp dsk_getpartentryloop
107 dsk_getpartentryloopend:
108 ret
109
110 ; ====================================================================
111 ; Function:
112 ; ====================================================================
113 ; Parameters
114 ; --------------------------------------------------------------------
115 ; Registers : none
116 ; Variables : [r] seeksec Sector to read
117 ; [r] seektrk Track to read
118 ; --------------------------------------------------------------------
119 ; Description:
120 ; ====================================================================
121 dskDiskCheck:
122 lds temp2,seekdsk
123 cpi temp2,RAMDISKNR
124 brsh dsk_dchrd ;maybe ramdisk
125
126 ; Check if selected disk # is less then # of disks.
127
128 lds temp,ndisks
129 tst temp
130 brne dsk_dchpart1
131
132 ; Need to init
133
134 rcall mgr_init_partitions
135 cbr temp,0x80
136 lds temp2,seekdsk
137
138 dsk_dchpart1:
139 cp temp2,temp
140 brsh dsk_dcher
141
142 dsk_dchend:
143 ldi temp,0
144 ret
145
146 dsk_dchrd:
147 #if RAMDISKCNT
148 cpi temp,RAMDISKNR+RAMDISKCNT
149 brlo dsk_dchend
150 #endif
151 dsk_dcher:
152 ldi temp,0xff ;error return
153 ret
154
155 dskErrorRet:
156 lds temp,erflag
157 ret
158
159 dskDiskSel:
160 sts seekdsk,temp
161 ret
162
163 dskTrackSel_l:
164 sts seektrk,temp
165 sts seektrk+1,_0
166 ret
167
168 dskTrackSel_h:
169 sts seektrk+1,temp
170 ret
171
172 dskSecSel:
173 sts seeksec,temp
174 ret
175
176 dskDmal:
177 sts dmaadr,temp
178 ret
179
180 dskDmah:
181 sts dmaadr+1,temp
182 ret
183
184 ; ====================================================================
185 ; Function: Does a Disk interaction
186 ; ====================================================================
187 ; Parameters
188 ; --------------------------------------------------------------------
189 ; Registers : none
190 ; Variables : [r] seeksec Sector to read
191 ; [r] seektrk Track to read
192 ; --------------------------------------------------------------------
193 ; Description:
194 ; ====================================================================
195 dskDoIt:
196 .if DISK_DEBUG
197 push temp
198 sbrc temp,READ_FUNC
199 rjmp dskdbgr
200 sbrc temp,WRITE_FUNC
201 rjmp dskdbgw
202 rjmp dskdbge
203
204 dskdbgr:
205 printnewline
206 printstring "Disk read: "
207 rjmp dskdbg1
208 dskdbgw:
209 printnewline
210 printstring "Disk write: "
211 dskdbg1:
212 lds temp,seekdsk
213 subi temp,-('A')
214 rcall uartputc
215 printstring ": track "
216 lds temp2,seektrk+1
217 lds temp,seektrk
218 rcall printhexw
219 printstring ", sector "
220 lds temp,seeksec
221 rcall printhex
222 printstring ", dma-addr "
223 lds temp2,dmaadr+1
224 lds temp,dmaadr
225 rcall printhexw
226 pop temp
227 push temp
228 sbrs temp,WRITE_FUNC
229 rjmp dskdbge
230 printstring " wrtype "
231 andi temp,3
232 rcall printhex
233 dskdbge:
234 pop temp
235 .endif
236 ;See what has to be done.
237 sbrc temp,READ_FUNC
238 rjmp dsk_read
239 sbrc temp,WRITE_FUNC
240 rjmp dsk_write
241 sbrc temp,HOME_FUNC
242 rjmp dsk_home
243 sbrc temp,BOOT_FUNC
244 rjmp dsk_boot
245
246 printstring "DISK I/O: Invalid Function code: "
247 rcall printhex
248 rjmp haltinv
249
250 dsk_boot:
251 sts ndisks,_0 ;no active partitions
252 dsk_cboot:
253 cbi flags,hostact ;host buffer inactive
254 sts unacnt,_0 ;clear unalloc count
255 ret
256
257 dsk_home:
258 sbis flags,hostwrt ;check for pending write
259 cbi flags,hostact ;clear host active flag
260 ret
261
262
263
264 ; ====================================================================
265 ; Function: Does a Disk read operation
266 ; ====================================================================
267 ; Parameters
268 ; --------------------------------------------------------------------
269 ; Registers : none
270 ; Variables : [r] seekdsk Number of Disk to Read
271 ; [r] seeksec Sector to read
272 ; [r] seektrk Track to read
273 ; --------------------------------------------------------------------
274 ; Description:
275 ; ====================================================================
276 dsk_read:
277 sts erflag,_0
278 sbi flags,readop ; Set read operation flag
279 lds xl,seekdsk
280 rcall dsk_getpartentry ; Get Paritiontableentry
281 ld temp,z ; Get Partitiontype
282
283 ; Isn't it a Disk ?
284 cpi temp,dskType_None
285 brne PC+2
286 rjmp dsk_read_err
287 ; Is it a RamDisk ?
288 cpi temp,dskType_RAM
289 brne PC+2
290 rjmp rdsk_read
291 ; It must be a FAT16-Imagefile or CP/M Partition.
292 sts unacnt,_0
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
297
298 dsk_read_err:
299 ret
300
301 ; ====================================================================
302 ; Function: Does a Disk write operation
303 ; ====================================================================
304 ; Parameters
305 ; --------------------------------------------------------------------
306 ; Registers : none
307 ; Variables : [r] seekdsk Number of Disk to Read
308 ; [r] seeksec Sector to read
309 ; [r] seektrk Track to read
310 ; --------------------------------------------------------------------
311 ; Description:
312 ; ====================================================================
313 dsk_write:
314 ;write the selected sector
315 sts erflag,_0
316 cbi flags,readop ; not a read operation
317 lds xl,seekdsk
318 rcall dsk_getpartentry ; Get Paritiontableentry
319 ld temp,z ; Get Partitiontype
320
321 ; Isn't it a Disk ?
322 cpi temp,dskType_None
323 brne PC+2
324 rjmp dsk_write_err
325
326 ; Is it a RamDisk ?
327 cpi temp,dskType_RAM
328 brne PC+2
329 rjmp rdsk_write
330
331 ; It must be a FAT16-Imagefile or CP/M Partition.
332
333 cbi flags,readop ;not a read operation
334
335 andi temp,WRTMSK
336 sts wrtype,temp ;save write type
337
338 cpi temp,WRUAL ;write unallocated?
339 brne dsk_chkuna ;check for unalloc
340
341 ; write to unallocated, set parameters
342 ldi temp,blksize/128 ;next unalloc recs
343 sts unacnt,temp
344 lds temp,seekdsk ;disk to seek
345 sts unadsk,temp ;unadsk = sekdsk
346 lds temp,seektrk
347 sts unatrk,temp ;unatrk = sectrk
348 lds temp,seektrk+1
349 sts unatrk+1,temp ;unatrk = sectrk
350 lds temp,seeksec
351 sts unasec,temp ;unasec = seksec
352 ;
353 dsk_chkuna:
354 ;check for write to unallocated sector
355 lds temp,unacnt ;any unalloc remain?
356 tst temp
357 breq dsk_alloc ;skip if not
358
359 ; more unallocated records remain
360 dec temp ;unacnt = unacnt-1
361 sts unacnt,temp
362 lds temp,seekdsk ;same disk?
363 lds temp2,unadsk
364 cp temp,temp2 ;seekdsk = unadsk?
365 brne dsk_alloc ;skip if not
366
367 ; disks are the same
368 lds temp,unatrk
369 lds temp2,unatrk+1
370 lds temp3,seektrk
371 lds temp4,seektrk+1
372 cp temp,temp3 ;seektrk = unatrk?
373 cpc temp2,temp4
374 brne dsk_alloc ;skip if not
375
376 ; tracks are the same
377 lds temp,seeksec ;same sector?
378 lds temp2,unasec
379 cp temp,temp2 ;seeksec = unasec?
380 brne dsk_alloc ;skip if not
381
382 ; match, move to next sector for future ref
383 inc temp2 ;unasec = unasec+1
384 sts unasec,temp2
385 cpi temp2,CPMSPT ;end of track? (count CP/M sectors)
386 brlo dsk_noovf ;skip if no overflow
387
388 ; overflow to next track
389 sts unasec,_0 ;unasec = 0
390 lds temp,unatrk
391 lds temp2,unatrk+1
392 subi temp, low(-1) ;unatrk = unatrk+1
393 sbci temp2,high(-1)
394 sts unatrk,temp
395 sts unatrk+1,temp2
396 ;
397 dsk_noovf:
398 cbi flags,rsflag ;rsflag = 0
399 rjmp dsk_rwoper ;to perform the write
400 ;
401 dsk_alloc:
402 ;not an unallocated record, requires pre-read
403 sts unacnt,_0 ;unacnt = 0
404 sbi flags,rsflag ;rsflag = 1
405 rjmp dsk_rwoper
406
407 dsk_write_err:
408 ret
409
410 ; ====================================================================
411 ; Function: Does a Disk read/write operation
412 ; ====================================================================
413 ; Parameters
414 ; --------------------------------------------------------------------
415 ; Registers : none
416 ; Variables : [r] seekdsk Number of Disk to Read
417 ; [r] seeksec Sector to read
418 ; [r] seektrk Track to read
419 ; --------------------------------------------------------------------
420 ; Description:
421 ; ====================================================================
422 dsk_rwoper:
423 ;enter here to perform the read/write
424 .if DISK_DEBUG
425 printstring ", flags: "
426 in temp,flags
427 rcall printhex
428 .endif
429 sts erflag,_0 ;no errors (yet)
430
431 ;Convert track/sector to an LBA address (in 128byte blocks)
432
433 lds xl,seeksec ;
434 ldi xh,0 ;
435 ldi yl,0 ;
436 lds temp3,seektrk ;
437 lds temp4,seektrk+1 ;
438 ldi temp,CPMSPT ;
439 mul temp3,temp ;
440 add xl,r0 ;
441 adc xh,r1 ;
442 mul temp4,temp ;
443 add xh,r0 ;yl:xh:xl := sec + trk * SectorsPerTrack
444 adc yl,r1 ;
445
446 mov temp,xl
447 andi temp,SECMSK ;mask buffer number
448 push temp ;save for later
449
450 ;Convert from CP/M LBA blocks to host LBA blocks
451 ldi temp,SECSHF
452 dsk_sh1:
453 lsr yl
454 ror xh
455 ror xl
456 dec temp
457 brne dsk_sh1
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
464
465 ; host buffer active, same as seek buffer?
466 lds temp,seekdsk
467 lds temp2,hostdsk ;same disk?
468 cp temp,temp2 ;seekdsk = hostdsk?
469 brne dsk_nomatch
470
471 ; same disk, same block?
472 lds temp,hostlba
473 lds temp2,hostlba+1
474 lds temp3,hostlba+2
475 cp xl,temp
476 cpc xh,temp2
477 cpc yl,temp3
478 breq dsk_match
479 ;
480 dsk_nomatch:
481 ;proper disk, but not correct sector
482 sbis flags,hostwrt ;host written?
483 rjmp dsk_filhst
484 push xl
485 push xh
486 push yl
487 rcall dsk_writehost ;clear host buff
488 pop yl
489 pop xh
490 pop xl
491
492 dsk_filhst:
493 ;may have to fill the host buffer
494 lds temp,seekdsk
495 sts hostdsk,temp
496 sts hostlba,xl
497 sts hostlba+1,xh
498 sts hostlba+2,yl
499
500 sbic flags,rsflag ;need to read?
501 rcall dsk_readhost ;yes, if 1
502 cbi flags,hostwrt ;no pending write
503
504 dsk_match:
505
506 ;copy data to or from buffer
507 ldiw z,hostbuf
508 ldi temp,128
509 pop temp2 ;get buffer number (which part of hostbuf)
510 mul temp2,temp
511 add zl,r0 ;offset in hostbuf
512 adc zh,r1
513
514 .if DISK_DEBUG > 2
515 push r0
516 push r1
517 printstring "; host buf adr: "
518 pop temp2
519 pop temp
520 rcall printhexw
521 .endif
522
523 lds xl,dmaadr
524 lds xh,dmaadr+1
525 ldi temp3,128 ;length of move
526 sbic flags,readop ;which way?
527 rjmp dsk_rmove ;skip if read
528
529 ; mark write operation
530 sbi flags,hostwrt ;hostwrt = 1
531 dsk_wmove:
532 mem_read
533 st z+,temp
534 adiw xl,1
535 dec temp3
536 brne dsk_wmove
537 rjmp dsk_rwmfin
538
539 dsk_rmove:
540 ld temp,z+
541 mem_write
542 adiw xl,1
543 dec temp3
544 brne dsk_rmove
545 dsk_rwmfin:
546 ; data has been moved to/from host buffer
547 lds temp,wrtype ;write type
548 cpi temp,WRDIR ;to directory?
549 breq dsk_wdir
550 ret ;no further processing
551 dsk_wdir:
552 ; clear host buffer for directory write
553 lds temp,erflag
554 tst temp ;errors?
555 breq dsk_wdir1
556 ret ;skip if so
557 dsk_wdir1:
558 rcall dsk_writehost ;clear host buff
559 cbi flags,hostwrt ;buffer written
560 ret
561
562 ; ====================================================================
563 ; Function: Does a Disk write operation
564 ; ====================================================================
565 ; Parameters
566 ; --------------------------------------------------------------------
567 ; Registers : none
568 ; Variables : [r] seekdsk Number of Disk to Read
569 ; [r] seeksec Sector to read
570 ; [r] seektrk Track to read
571 ; --------------------------------------------------------------------
572 ; Description:
573 ; ====================================================================
574 dsk_writehost:
575 lds xl,hostdsk
576 rcall dsk_getpartentry
577 ld temp,z
578
579 #if FAT16_SUPPORT
580 ; Is it a FAT16 Diskimage ?
581 cpi temp,dskType_FAT
582 brne PC+2
583 rjmp fat_writehost
584 #endif
585
586 ; Is it a CP/M Partition ?
587 cpi temp,dskType_CPM
588 brne PC+2
589 rjmp cpm_writehost
590 ; Disktype not supported -> Return
591 ret
592
593 ; ====================================================================
594 ; Function: Does a Disk read operation
595 ; ====================================================================
596 ; Parameters
597 ; --------------------------------------------------------------------
598 ; Registers : none
599 ; Variables : [r] seekdsk Number of Disk to Read
600 ; [r] seeksec Sector to read
601 ; [r] seektrk Track to read
602 ; --------------------------------------------------------------------
603 ; Description:
604 ; ====================================================================
605 dsk_readhost:
606 lds xl,hostdsk
607 rcall dsk_getpartentry
608 ld temp,z
609
610 #if FAT16_SUPPORT
611 ; Is it a FAT16 Diskimage ?
612 cpi temp,dskType_FAT
613 brne PC+2
614 rjmp fat_readhost
615 #endif
616
617 ; Is it a CP/M Partition ?
618 cpi temp,dskType_CPM
619 brne PC+2
620 rjmp cpm_readhost
621 ; Disktype not supported -> Return
622 ret
623