[docs] Replace cyrillic 'с' with latin 'c' in register names
[kolibrios.git] / drivers / disk / virt_disk.asm
blob9b1358b6716e3931e8f46a9da772e91c1bb92646
1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2 ;; ;;
3 ;; Copyright (C) KolibriOS team 2023. All rights reserved. ;;
4 ;; Distributed under terms of the GNU General Public License ;;
5 ;; ;;
6 ;; Virtual disk driver for KolibriOS ;;
7 ;; ;;
8 ;; Written by Mikhail Frolov aka Doczom ;;
9 ;; ;;
10 ;; GNU GENERAL PUBLIC LICENSE ;;
11 ;; Version 2, June 1991 ;;
12 ;; ;;
13 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14 DISK_STATUS_OK = 0 ; success
15 DISK_STATUS_GENERAL_ERROR = -1; if no other code is suitable
16 DISK_STATUS_INVALID_CALL = 1 ; invalid input parameters
17 DISK_STATUS_NO_MEDIA = 2 ; no media present
18 DISK_STATUS_END_OF_MEDIA = 3 ; end of media while reading/writing data
20 ; For all IOCTLs the driver returns one of the following error codes:
21 NO_ERROR equ 0
22 ERROR_INVALID_IOCTL equ 1 ; unknown IOCTL code
24 maxPathLength = 1000h
26 include '../struct.inc'
28 ; TODO list:
29 ; add support VDI image
31 ; Input structures:
32 Flag:
33 .Ro = 1b
34 .Wo = 10b
35 .RW = 11b
37 struct DISK_DEV
38 next rd 1
39 pref rd 1
40 SectorCount rd 2
41 DiskHandle rd 1
42 DiskNumber rd 1
43 Flags rd 1 ; 1-ro 2-wo 3-rw
44 TypeImage rd 1 ; 0-raw 1-vhd 2-vdi 3-imd
45 SectorSize rd 1
46 DiskPath rb maxPathLength
47 ends
48 struct IMAGE_ADD_STRUCT
49 Flags rd 1 ; 1-ro 2-wo 3-rw
50 TypeImage rd 1 ; 0-raw 1-vhd 2-vdi 3-imd
51 SectorSize rd 1
52 DiskPath rb maxPathLength
53 ends
55 struct DISKMEDIAINFO
56 Flags dd ?
57 SectorSize dd ?
58 Capacity dq ?
59 ends
61 DEBUG = 1
62 __DEBUG__ = 1
63 __DEBUG_LEVEL__ = 1 ; 1 = verbose, 2 = errors only
65 format PE DLL native 0.05
66 entry START
68 section '.flat' code readable writable executable
70 include '../proc32.inc'
71 include '../peimport.inc'
72 include '../macros.inc'
74 include '../fdo.inc'
76 proc START c, state:dword, cmdline:dword
77 xor eax, eax ; set return value in case we will do nothing
78 cmp dword [state], 1
79 jne .nothing
81 mov ecx, disk_list_lock
82 invoke MutexInit
84 DEBUGF 1, "VIRT_DISK: driver loaded\n"
85 invoke RegService, my_service, service_proc
86 ret
87 .nothing:
88 ret
89 endp
91 ; get version
92 ; add disk
93 ; del disk
94 ; get list disks
95 ; get disk info
96 proc service_proc
97 push ebx esi edi
98 ; 2. Get parameter from the stack: [esp+16] is the first parameter,
99 ; pointer to IOCTL structure.
100 mov ebx, [esp + 16] ; edx -> IOCTL
102 mov ecx, [ebx + IOCTL.io_code]
103 test ecx, ecx ; check for SRV_GETVERSION
104 jnz .add_disk
106 cmp [ebx + IOCTL.out_size], 4
107 jb .error_ret
108 mov eax, [ebx + IOCTL.output]
109 mov dword [eax], 1 ;API_VERSION
110 xor eax, eax
111 jmp .return
113 .add_disk:
114 dec ecx ; check for DEV_ADD_DISK
115 jnz .del_disk
117 cmp [ebx + IOCTL.inp_size], sizeof.IMAGE_ADD_STRUCT
118 jb .error_ret
120 cmp [ebx + IOCTL.out_size], 4
121 jb .error_ret
123 invoke KernelAlloc, sizeof.DISK_DEV
124 test eax, eax
125 jz .error_ret
127 push eax
128 mov edi, eax
129 mov ecx, sizeof.DISK_DEV/4
130 xor eax, eax
131 rep stosd
132 pop eax
134 mov edi, eax
135 add edi, DISK_DEV.Flags
136 mov esi, [ebx + IOCTL.input]
137 mov ecx, sizeof.IMAGE_ADD_STRUCT/4
138 rep movsd
140 mov esi, eax ;save
142 cmp byte[esi + DISK_DEV.DiskPath], '/'
143 jnz .add_disk.error
145 mov ecx, disk_list_lock
146 invoke MutexLock
148 call get_free_num
149 jnz .add_disk.error2
150 mov [esi + DISK_DEV.DiskNumber], eax
151 mov ecx,[ebx + IOCTL.output]
152 mov [ecx], eax
154 ; init image
155 mov eax, [esi + DISK_DEV.TypeImage]
156 cmp eax, image_type.max_num
157 ja .add_disk.error2
159 call dword[image_type + eax*8] ;esi - DISK_DEV*
160 test eax, eax
161 jnz .add_disk.error2
163 ; creating name
164 push ebp
165 mov ebp, esp
167 mov eax, [esi + DISK_DEV.DiskNumber]
168 mov edi, esp
169 dec edi
170 mov byte[edi], 0
171 mov ecx, 10
173 xor edx, edx
174 div ecx
175 add edx,'0'
176 dec edi
177 mov byte[edi], dl
178 test eax, eax
179 jnz @b
181 mov esp, edi
182 push word 'vd'
183 sub edi, 2
185 ; add disk
186 mov eax, [esi + DISK_DEV.TypeImage]
187 invoke DiskAdd, dword[image_type + eax*8 + 4] , \
188 edi, esi, 0
189 mov [esi + DISK_DEV.DiskHandle], eax
190 mov esp, ebp
191 pop ebp
192 test eax, eax
193 jz .add_disk.error2
195 invoke DiskMediaChanged, eax, 1
197 ; add in list
198 mov dword[esi], disk_root_list
199 mov eax, [disk_root_list + 4]
200 mov [esi + 4], eax
201 mov [eax], esi
202 mov [disk_root_list + 4], esi
203 inc dword[disk_count]
205 mov ecx, disk_list_lock
206 invoke MutexUnlock
208 xor eax, eax
209 jmp .return
211 .add_disk.error2:
212 mov ecx, disk_list_lock
213 invoke MutexUnlock
215 .add_disk.error:
216 invoke KernelFree, esi
217 jmp .error_ret
220 .del_disk:
221 dec ecx ; check for DEV_DEL_DISK
222 jnz .get_root_list
224 cmp [ebx + IOCTL.inp_size], 4
225 jb .error_ret
227 mov ecx, [ebx + IOCTL.input]
228 mov ecx, [ecx]
229 call get_disk
231 test eax, eax
232 jz .error_ret
234 cmp [eax + DISK_DEV.DiskHandle], 0
235 jz .error_ret
236 mov ecx, [eax + DISK_DEV.DiskHandle]
237 mov [eax + DISK_DEV.DiskHandle], 0
238 invoke DiskDel, ecx
240 xor eax, eax
241 jmp .return
243 .get_root_list:
244 dec ecx ; check for DEV_DEL_DISK
245 jnz .get_disk_info
247 cmp [ebx + IOCTL.inp_size], 4*2 ; offset + count
248 jb .error_ret
249 mov ecx, [ebx + IOCTL.input]
250 mov edx, [ecx] ; offset
251 mov eax, [ecx + 4] ; count
253 add edx, eax
254 cmp edx, [disk_count]
255 ja .error_ret
257 xor edx, edx
258 imul eax, sizeof.DISK_DEV - 8
259 add eax, 4
260 cmp [ebx + IOCTL.out_size], eax
261 jb .error_ret
263 mov edi, [ebx + IOCTL.output]
264 mov eax, [disk_count]
265 stosd
267 mov edx, [ecx]
268 mov eax, [disk_root_list]
270 test edx, edx
271 jz @f
272 mov eax, [eax]
273 dec edx
274 jmp @b
276 mov edx, [ecx + 4]
278 test edx, edx
279 jz @f
280 mov esi, eax
281 add esi, 8
282 mov ecx, (sizeof.DISK_DEV - 8)/4
283 rep movsd
284 mov eax, [eax]
285 dec edx
286 jmp @b
288 xor eax, eax
289 jmp .return
291 .get_disk_info:
292 dec ecx
293 jnz .error_ret
295 cmp [ebx + IOCTL.inp_size], 4
296 jb .error_ret
297 cmp [ebx + IOCTL.out_size], sizeof.DISK_DEV - 8
298 jb .error_ret
299 mov ecx, [ebx + IOCTL.input]
300 mov ecx, [ecx]
302 call get_disk
303 test eax, eax
304 jz .error_ret
306 mov esi, eax
307 add esi, 4*2
308 mov edi, [ebx + IOCTL.output]
309 mov ecx, (sizeof.DISK_DEV - 8)/4
310 rep movsd
312 xor eax, eax
313 jmp .return
315 .error_ret:
316 mov eax, ERROR_INVALID_IOCTL
317 .return:
318 pop edi esi ebx
319 retn 4
320 endp
322 ; IN: ecx - ptr DISK_DEV
323 ; OUT: ZF - found zF - not found
324 proc disk_dev_check
325 push eax
326 mov eax, disk_root_list
328 mov eax, [eax]
329 cmp eax, disk_root_list
330 jz .nf
331 cmp eax, ecx
332 jnz @b
333 pop eax
335 .nf:
336 test eax, eax
337 pop eax
339 endp
340 ; IN: ecx - disk number
341 ; OUT: eax - ptr DISK_DEV
342 proc get_disk
343 push ecx
344 mov ecx, disk_list_lock
345 invoke MutexLock
346 pop ecx
348 mov eax, disk_root_list
350 mov eax, [eax]
351 cmp eax, disk_root_list
352 jz .nf
353 cmp ecx, [eax + DISK_DEV.DiskNumber]
354 jnz @b
356 push eax
357 mov ecx, disk_list_lock
358 invoke MutexUnlock
359 pop eax
361 .nf:
362 mov ecx, disk_list_lock
363 invoke MutexUnlock
365 xor eax, eax
367 endp
369 ; OUT: eax - number free disk
370 ; Zf - good zf - not found
371 proc get_free_num
372 xor eax, eax
373 mov edx, disk_root_list
375 mov edx, [edx]
376 cmp edx, disk_root_list
377 jz @f
378 cmp eax, [edx + DISK_DEV.DiskNumber]
379 jnz @b
381 inc eax
382 jnz @b
384 test edx, edx ; random :)
387 endp
389 ;; IN: ecx - number disk
390 ;; OUT: eax - ptr to DISK_DEV or zero
391 ;proc get_link_disk
393 ; push ecx
394 ; mov ecx, disk_list_lock
395 ; invoke MutexLock
396 ; pop ecx
398 ; xor eax, eax
399 ; cmp ecx, [disk_array.len]
400 ; jae .end
402 ; mov eax, [disk_array]
403 ; mov eax, [edx + ecx*4]
405 ;.end:
406 ; push eax
407 ; ; unlock disk list
408 ; mov ecx, disk_list_lock
409 ; invoke MutexUnlock
410 ; pop eax
411 ; ret
412 ;endp
413 ;; IN: esi - ptr to DISK_DEV
414 ;; OUT: eax - offset in array or -1
415 ;proc add_link_disk
416 ; ; find free item
417 ; mov ecx, [disk_array]
418 ; xor eax, eax
419 ; dec eax
420 ;@@:
421 ; inc eax
422 ; cmp eax, [disk_array.len]
423 ; jae .not_found
425 ; cmp dword[ecx + eax*4], 0
426 ; jnz @b
428 ; mov [ecx + eax*4], esi
429 ; ret
431 ;.not_found:
432 ; inc dword[disk_array.len]
433 ; ;get new memory
434 ; mov eax,[disk_array.len]
435 ; shl eax, 2 ;*4
436 ; invoke Kmalloc
437 ; test eax, eax
438 ; jz .err
439 ; ; copy data
440 ; push edi esi
441 ; mov ecx, [disk_array.len]
442 ; mov edi, eax
443 ; mov esi, [disk_array]
444 ; rep movsd
445 ; pop esi edi
446 ; ; del old array
447 ; xchg [disk_array], eax
448 ; invoke Kfree
449 ; mov eax, [disk_array.len]
450 ; ret
451 ;.err:
452 ; dec dword[disk_array.len]
453 ; mov eax, -1
454 ; ret
455 ;endp
457 ;; IN: ecx - offset in array
458 ;proc del_link_disk
459 ; mov edx, ecx
460 ; dec edx
461 ; cmp edx,[disk_array.len]
462 ; jz .last_item
464 ; mov edx,[disk_array]
465 ; mov [edx + ecx*4], 0
466 ; ret
467 ;.last_item:
468 ; dec dword[disk_array.len]
469 ; ;get new memory
470 ; mov eax,[disk_array.len]
471 ; shl eax, 2 ;*4
472 ; invoke Kmalloc
473 ; test eax, eax
474 ; jz .err
475 ; ; copy data
476 ; push edi esi
477 ; mov ecx, [disk_array.len]
478 ; mov edi, eax
479 ; mov esi, [disk_array]
480 ; rep movsd
481 ; pop esi edi
482 ; ; del old array
483 ; xchg [disk_array], eax
484 ; invoke Kfree
485 ; ret
486 ;.err:
487 ; inc dword[disk_array.len]
488 ; mov eax, -1
489 ; ret
490 ;endp
492 ; RAW IMAGE DISK FUNCTIONS
493 proc raw_disk_close stdcall, pdata
494 ; del item list
495 mov ecx, disk_list_lock
496 invoke MutexLock
498 mov ecx, [pdata]
499 mov eax, [ecx] ; eax = next
500 mov edx, [ecx + 4] ; edx = prev
501 mov [eax + 4], edx ; [next.prev] = prev
502 mov [edx], eax ; [prev.next] = next
504 dec dword[disk_count]
506 mov ecx, disk_list_lock
507 invoke MutexUnlock
509 invoke KernelFree, [pdata]
510 DEBUGF 1, "VIRT_DISK: disk deleted\n"
512 endp
514 proc disk_querymedia stdcall, pdata, mediainfo
515 mov eax, [mediainfo]
516 mov edx, [pdata]
517 mov [eax + DISKMEDIAINFO.Flags], 0
518 mov ecx, [edx + DISK_DEV.SectorSize]
519 mov [eax + DISKMEDIAINFO.SectorSize], ecx
520 mov ecx, [edx + DISK_DEV.SectorCount]
521 mov dword[eax + DISKMEDIAINFO.Capacity], ecx
522 mov ecx, [edx + DISK_DEV.SectorCount + 4]
523 mov dword[eax + DISKMEDIAINFO.Capacity + 4], ecx
524 xor eax, eax
526 endp
528 proc raw_disk_rd stdcall pdata: dword,\
529 buffer: dword,\
530 startsector: qword,\
531 numsectors_ptr:dword
533 mov ecx, [pdata]
534 test [ecx + DISK_DEV.Flags], Flag.Ro
535 jz .no_support
537 pusha
538 lea eax,[ecx + DISK_DEV.DiskPath]
539 push eax
540 dec esp
541 mov byte[esp], 0
542 push dword[buffer]
544 mov eax, [numsectors_ptr]
545 mov eax, [eax]
546 mul dword[ecx + DISK_DEV.SectorSize]
547 push eax
548 ; get offset for startsector
549 mov eax, dword[startsector]
550 xor edx, edx
551 mul dword[ecx + DISK_DEV.SectorSize]
552 push edx
553 push eax
554 mov eax, dword[startsector + 4]
555 mul dword[ecx + DISK_DEV.SectorSize]
556 add [esp + 4], eax
557 push dword 0 ;read file
559 mov ebx, esp
560 invoke FS_Service
561 push eax
562 mov ecx, [pdata]
563 mov eax, ebx
564 xor edx, edx
565 div dword[ecx + DISK_DEV.SectorSize]
566 mov edx, [numsectors_ptr]
567 mov [edx], eax
568 pop eax
570 add esp, 6*4+1 ; size FS struct
571 test eax, eax
572 popa
573 jz @f
574 mov eax, 1
577 xor eax, eax
579 .no_support:
580 mov eax, DISK_STATUS_GENERAL_ERROR
582 endp
585 proc raw_disk_wr stdcall pdata: dword,\
586 buffer: dword,\
587 startsector: qword,\
588 numsectors_ptr:dword
590 mov ecx, [pdata]
591 test [ecx + DISK_DEV.Flags], Flag.Wo
592 jz .no_support
594 pusha
595 lea eax,[ecx + DISK_DEV.DiskPath]
596 push eax
597 dec esp
598 mov byte[esp],0
599 push dword[buffer]
601 mov eax, [numsectors_ptr]
602 mov eax, [eax]
603 mul dword[ecx + DISK_DEV.SectorSize]
604 push eax
605 ; get offset for startsector
606 mov eax, dword[startsector]
607 xor edx, edx
608 mul dword[ecx + DISK_DEV.SectorSize]
609 push edx
610 push eax
611 xor edx, edx
612 mov eax, dword[startsector + 4]
613 mul dword[ecx + DISK_DEV.SectorSize]
614 add [esp + 4], eax
615 push dword 3 ; write file
616 mov ebx, esp
617 invoke FS_Service
619 push eax
620 mov ecx, [pdata]
621 mov eax, ebx
622 xor edx, edx
623 div dword[ecx + DISK_DEV.SectorSize]
624 mov edx, [numsectors_ptr]
625 mov [edx], eax
626 pop eax
628 add esp, 6*4+1 ; size FS struct
629 test eax, eax
630 popa
631 jz @f
632 mov eax, 1
635 xor eax, eax
638 .no_support:
639 mov eax, DISK_STATUS_GENERAL_ERROR
641 endp
643 disk_root_list:
644 dd disk_root_list
645 dd disk_root_list
646 disk_count: dd 0
647 disk_list_lock: MUTEX
649 image_type:
650 ; init function, table disk function
651 dd raw_image_init, raw_disk_functions
652 ; vdi
653 .max_num = ($ - image_type - 8) / 8; 8 - item size
655 align 4
656 ; esi - ptr to DISK_DEV
657 ;WARNING: raw image size >=2tb not supported.
659 proc raw_image_init
660 sub esp, 40 ; for file_info
661 mov ecx, esp
663 pusha
664 lea eax,[esi + DISK_DEV.DiskPath]
665 push eax
666 dec esp
667 mov byte[esp],0
668 push ecx
669 xor eax, eax
670 push eax eax eax
671 push dword 5
673 mov ebx, esp
674 invoke FS_Service
675 add esp, 6*4+1
676 test eax, eax
677 popa
678 lea esp,[esp + 40]
679 jnz .err
681 ; WARNING: Not working with stack, destroys the structure!
682 mov eax, [ecx + 32]
683 mov edx, [ecx + 36]
684 test eax, eax
685 jz .err
687 div dword[esi + DISK_DEV.SectorSize] ; undefined exeption
688 mov [esi + DISK_DEV.SectorCount], eax
689 mov [esi + DISK_DEV.SectorCount + 4], 0
690 ; END WARNING
692 xor eax, eax
694 .err:
695 or eax, -1
697 endp
699 align 4
700 raw_disk_functions:
701 dd .size
702 dd raw_disk_close
703 dd 0 ; no need in .closemedia
704 dd disk_querymedia
705 dd raw_disk_rd
706 dd raw_disk_wr
707 dd 0 ; no need in .flush
708 dd disk_adjust_cache_size
709 .size = $ - raw_disk_functions
711 proc disk_adjust_cache_size
712 virtual at esp+4
713 .userdata dd ?
714 .suggested_size dd ?
715 end virtual
716 xor eax, eax
717 retn 8
718 endp
720 my_service db 'VIRT_DISK',0
722 data fixups
723 end data
725 include_debug_strings