Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  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
  19.  
  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
  23.  
  24. maxPathLength = 1000h
  25.  
  26. include '../struct.inc'
  27.  
  28. ; TODO list:
  29. ; add support VDI image
  30.  
  31. ; Input structures:
  32. Flag:
  33.         .Ro = 1b
  34.         .Wo = 10b
  35.         .RW = 11b
  36.  
  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
  54.  
  55. struct DISKMEDIAINFO
  56.         Flags      dd ?
  57.         SectorSize dd ?
  58.         Capacity   dq ?
  59. ends
  60.  
  61.         DEBUG                   = 1
  62.         __DEBUG__               = 1
  63.         __DEBUG_LEVEL__         = 1  ; 1 = verbose, 2 = errors only
  64.  
  65. format PE DLL native 0.05
  66. entry START
  67.  
  68. section '.flat' code readable writable executable
  69.  
  70. include '../proc32.inc'
  71. include '../peimport.inc'
  72. include '../macros.inc'
  73.  
  74. include '../fdo.inc'
  75.  
  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
  80.  
  81.         mov     ecx, disk_list_lock
  82.         invoke  MutexInit
  83.  
  84.         DEBUGF  1, "VIRT_DISK: driver loaded\n"
  85.         invoke  RegService, my_service, service_proc
  86.         ret
  87. .nothing:
  88.         ret
  89. endp
  90.  
  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
  101.  
  102.         mov     ecx, [ebx + IOCTL.io_code]
  103.         test    ecx, ecx        ; check for SRV_GETVERSION
  104.         jnz     .add_disk
  105.  
  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
  112.  
  113. .add_disk:
  114.         dec     ecx     ; check for DEV_ADD_DISK
  115.         jnz     .del_disk
  116.  
  117.         cmp     [ebx + IOCTL.inp_size], sizeof.IMAGE_ADD_STRUCT
  118.         jb      .error_ret
  119.  
  120.         cmp     [ebx + IOCTL.out_size], 4
  121.         jb      .error_ret
  122.  
  123.         invoke  KernelAlloc, sizeof.DISK_DEV
  124.         test    eax, eax
  125.         jz      .error_ret
  126.  
  127.         push    eax
  128.         mov     edi, eax
  129.         mov     ecx, sizeof.DISK_DEV/4
  130.         xor     eax, eax
  131.         rep stosd
  132.         pop     eax
  133.  
  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
  139.  
  140.         mov     esi, eax ;save
  141.  
  142.         cmp     byte[esi + DISK_DEV.DiskPath], '/'
  143.         jnz     .add_disk.error
  144.  
  145.         mov     ecx, disk_list_lock
  146.         invoke  MutexLock
  147.  
  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
  153.  
  154.         ; init image
  155.         mov     eax, [esi + DISK_DEV.TypeImage]
  156.         cmp     eax, image_type.max_num
  157.         ja      .add_disk.error2
  158.  
  159.         call    dword[image_type + eax*8]  ;esi - DISK_DEV*
  160.         test    eax, eax
  161.         jnz     .add_disk.error2
  162.  
  163.         ; creating name
  164.         push    ebp
  165.         mov     ebp, esp
  166.  
  167.         mov     eax, [esi + DISK_DEV.DiskNumber]
  168.         mov     edi, esp
  169.         dec     edi
  170.         mov     byte[edi], 0
  171.         mov     ecx, 10
  172. @@:
  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
  180.  
  181.         mov     esp, edi
  182.         push    word 'vd'
  183.         sub     edi, 2
  184.  
  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
  194.  
  195.         invoke  DiskMediaChanged, eax, 1
  196.  
  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]
  204.  
  205.         mov     ecx, disk_list_lock
  206.         invoke  MutexUnlock
  207.  
  208.         xor     eax, eax
  209.         jmp     .return
  210.  
  211. .add_disk.error2:
  212.         mov     ecx, disk_list_lock
  213.         invoke  MutexUnlock
  214.  
  215. .add_disk.error:
  216.         invoke  KernelFree, esi
  217.         jmp     .error_ret
  218.  
  219.  
  220. .del_disk:
  221.         dec     ecx     ; check for DEV_DEL_DISK
  222.         jnz     .get_root_list
  223.  
  224.         cmp     [ebx + IOCTL.inp_size], 4
  225.         jb      .error_ret
  226.  
  227.         mov     ecx, [ebx + IOCTL.input]
  228.         mov     ecx, [ecx]
  229.         call    get_disk
  230.  
  231.         test    eax, eax
  232.         jz      .error_ret
  233.  
  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
  239.  
  240.         xor     eax, eax
  241.         jmp     .return
  242.  
  243. .get_root_list:
  244.         dec     ecx     ; check for DEV_DEL_DISK
  245.         jnz     .get_disk_info
  246.  
  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
  252.  
  253.         add     edx, eax
  254.         cmp     edx, [disk_count]
  255.         ja      .error_ret
  256.  
  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
  262.  
  263.         mov     edi, [ebx + IOCTL.output]
  264.         mov     eax, [disk_count]
  265.         stosd
  266.  
  267.         mov     edx, [ecx]
  268.         mov     eax, [disk_root_list]
  269. @@:
  270.         test    edx, edx
  271.         jz      @f
  272.         mov     eax, [eax]
  273.         dec     edx
  274.         jmp     @b
  275. @@:
  276.         mov     edx, [ecx + 4]
  277. @@:
  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
  287. @@:
  288.         xor     eax, eax
  289.         jmp     .return
  290.  
  291. .get_disk_info:
  292.         dec     ecx
  293.         jnz     .error_ret
  294.  
  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]
  301.  
  302.         call    get_disk
  303.         test    eax, eax
  304.         jz      .error_ret
  305.  
  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
  311.  
  312.         xor     eax, eax
  313.         jmp     .return
  314.  
  315. .error_ret:
  316.         mov     eax, ERROR_INVALID_IOCTL
  317. .return:
  318.         pop     edi esi ebx
  319.         retn    4
  320. endp
  321.  
  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
  327. @@:
  328.         mov     eax, [eax]
  329.         cmp     eax, disk_root_list
  330.         jz      .nf
  331.         cmp     eax, ecx
  332.         jnz     @b
  333.         pop     eax
  334.         ret
  335. .nf:
  336.         test    eax, eax
  337.         pop     eax
  338.         ret
  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
  347.  
  348.         mov     eax, disk_root_list
  349. @@:
  350.         mov     eax, [eax]
  351.         cmp     eax, disk_root_list
  352.         jz      .nf
  353.         cmp     ecx, [eax + DISK_DEV.DiskNumber]
  354.         jnz     @b
  355.  
  356.         push    eax
  357.         mov     ecx, disk_list_lock
  358.         invoke  MutexUnlock
  359.         pop     eax
  360.         ret
  361. .nf:
  362.         mov     ecx, disk_list_lock
  363.         invoke  MutexUnlock
  364.  
  365.         xor     eax, eax
  366.         ret
  367. endp
  368.  
  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
  374. @@:
  375.         mov     edx, [edx]
  376.         cmp     edx, disk_root_list
  377.         jz      @f
  378.         cmp     eax, [edx + DISK_DEV.DiskNumber]
  379.         jnz     @b
  380.  
  381.         inc     eax
  382.         jnz     @b
  383.  
  384.         test    edx, edx ; random :)
  385. @@:
  386.         ret
  387. endp
  388.  
  389. ;; IN: ecx - number disk
  390. ;; OUT: eax - ptr to DISK_DEV or zero
  391. ;proc    get_link_disk
  392. ;
  393. ;        push    ecx
  394. ;        mov     ecx, disk_list_lock
  395. ;        invoke  MutexLock
  396. ;        pop     ecx
  397. ;
  398. ;        xor     eax, eax
  399. ;        cmp     ecx, [disk_array.len]
  400. ;        jae     .end
  401. ;
  402. ;        mov     eax, [disk_array]
  403. ;        mov     eax, [edx + ecx*4]
  404. ;
  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
  424. ;
  425. ;        cmp     dword[ecx + eax*4], 0
  426. ;        jnz     @b
  427. ;
  428. ;        mov     [ecx + eax*4], esi
  429. ;        ret
  430. ;
  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
  456. ;
  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
  463. ;
  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
  491.  
  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
  497.  
  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
  503.  
  504.         dec     dword[disk_count]
  505.  
  506.         mov     ecx, disk_list_lock
  507.         invoke  MutexUnlock
  508.  
  509.         invoke  KernelFree, [pdata]
  510.         DEBUGF  1, "VIRT_DISK: disk deleted\n"
  511.         ret
  512. endp
  513.  
  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
  525.         ret
  526. endp
  527.  
  528. proc    raw_disk_rd stdcall pdata: dword,\
  529.                             buffer: dword,\
  530.                             startsector: qword,\
  531.                             numsectors_ptr:dword
  532.  
  533.         mov     ecx, [pdata]
  534.         test    [ecx + DISK_DEV.Flags], Flag.Ro
  535.         jz      .no_support
  536.  
  537.         pusha
  538.         lea     eax,[ecx + DISK_DEV.DiskPath]
  539.         push    eax
  540.         dec     esp
  541.         mov     byte[esp], 0
  542.         push    dword[buffer]
  543.  
  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
  558.  
  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
  569.  
  570.         add     esp, 6*4+1 ; size FS struct
  571.         test    eax, eax
  572.         popa
  573.         jz      @f
  574.         mov     eax, 1
  575.         ret
  576. @@:
  577.         xor     eax, eax
  578.         ret
  579. .no_support:
  580.         mov     eax, DISK_STATUS_GENERAL_ERROR
  581.         ret
  582. endp
  583.  
  584.  
  585. proc    raw_disk_wr stdcall pdata: dword,\
  586.                             buffer: dword,\
  587.                             startsector: qword,\
  588.                             numsectors_ptr:dword
  589.  
  590.         mov     ecx, [pdata]
  591.         test    [ecx + DISK_DEV.Flags], Flag.Wo
  592.         jz      .no_support
  593.  
  594.         pusha
  595.         lea     eax,[ecx + DISK_DEV.DiskPath]
  596.         push    eax
  597.         dec     esp
  598.         mov     byte[esp],0
  599.         push    dword[buffer]
  600.  
  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
  618.  
  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
  627.  
  628.         add     esp, 6*4+1 ; size FS struct
  629.         test    eax, eax
  630.         popa
  631.         jz      @f
  632.         mov     eax, 1
  633.         ret
  634. @@:
  635.         xor     eax, eax
  636.         ret
  637.  
  638. .no_support:
  639.         mov     eax, DISK_STATUS_GENERAL_ERROR
  640.         ret
  641. endp
  642.  
  643. disk_root_list:
  644.         dd      disk_root_list
  645.         dd      disk_root_list
  646. disk_count: dd 0
  647. disk_list_lock: MUTEX
  648.  
  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
  654.  
  655. align 4
  656. ; esi - ptr to DISK_DEV
  657. ;WARNING: raw image size >=2tb not supported.
  658.  
  659. proc    raw_image_init
  660.         sub     esp, 40 ; for file_info
  661.         mov     ecx, esp
  662.  
  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
  672.  
  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
  680.  
  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
  686.  
  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
  691.  
  692.         xor     eax, eax
  693.         ret
  694. .err:
  695.         or      eax, -1
  696.         ret
  697. endp
  698.  
  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
  710.  
  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
  719.  
  720. my_service      db      'VIRT_DISK',0
  721.  
  722. data fixups
  723. end data
  724.  
  725. include_debug_strings