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