Subversion Repositories Kolibri OS

Rev

Rev 5577 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 4420 $
  9.  
  10. ; Disk access through BIOS
  11. iglobal
  12. align 4
  13. bd_callbacks:
  14.         dd      bd_callbacks.end - bd_callbacks     ; strucsize
  15.         dd      0   ; no close function
  16.         dd      0   ; no closemedia function
  17.         dd      bd_querymedia
  18.         dd      bd_read_interface
  19.         dd      bd_write_interface
  20.         dd      0   ; no flush function
  21.         dd      0   ; use default cache size
  22. .end:
  23. endg
  24.  
  25. uglobal
  26. bios_hdpos          dd 0
  27. bios_cur_sector     dd ?
  28. bios_read_len       dd ?
  29. cache_chain_ptr     dd ?
  30. int13_regs_in       rb sizeof.v86_regs
  31. int13_regs_out      rb sizeof.v86_regs
  32. cache_chain_size    db ?
  33. endg
  34. ;-----------------------------------------------------------------
  35. proc bd_read_interface stdcall uses edi, \
  36.         userdata, buffer, startsector:qword, numsectors
  37.         ; userdata = old [hdpos] = 80h + index in NumBiosDisks
  38.         ; buffer = pointer to buffer for data
  39.         ; startsector = 64-bit start sector
  40.         ; numsectors = pointer to number of sectors on input,
  41.         ;  must be filled with number of sectors really read
  42. locals
  43. sectors_todo    dd      ?
  44. endl
  45. ; 1. Initialize number of sectors: get number of requested sectors
  46. ; and say that no sectors were read yet.
  47.         mov     ecx, [numsectors]
  48.         mov     eax, [ecx]
  49.         mov     dword [ecx], 0
  50.         mov     [sectors_todo], eax
  51. ; 2. Acquire the global lock.
  52.         mov     ecx, ide_mutex
  53.         call    mutex_lock
  54. ; 3. Convert parameters to the form suitable for worker procedures.
  55. ; Underlying procedures do not know about 64-bit sectors.
  56. ; Worker procedures use global variables and edi for [buffer].
  57.         cmp     dword [startsector+4], 0
  58.         jnz     .fail
  59.         and     [hd_error], 0
  60.         mov     eax, [userdata]
  61.         mov     [hdpos], eax
  62.         mov     eax, dword [startsector]
  63.         mov     edi, [buffer]
  64. ; 4. Worker procedures take one sectors per time, so loop over all sectors to read.
  65. .sectors_loop:
  66.         call    bd_read
  67.         cmp     [hd_error], 0
  68.         jnz     .fail
  69.         mov     ecx, [numsectors]
  70.         inc     dword [ecx]     ; one more sector is read
  71.         dec     [sectors_todo]
  72.         jz      .done
  73.         inc     eax
  74.         jnz     .sectors_loop
  75. ; 5. Loop is done, either due to error or because everything is done.
  76. ; Release the global lock and return the corresponding status.
  77. .fail:
  78.         mov     ecx, ide_mutex
  79.         call    mutex_unlock
  80.         or      eax, -1
  81.         ret
  82. .done:
  83.         mov     ecx, ide_mutex
  84.         call    mutex_unlock
  85.         xor     eax, eax
  86.         ret
  87. endp
  88. ;-----------------------------------------------------------------
  89. proc bd_write_interface stdcall uses esi edi, \
  90.         userdata, buffer, startsector:qword, numsectors
  91.         ; userdata = old [hdpos] = 80h + index in NumBiosDisks
  92.         ; buffer = pointer to buffer with data
  93.         ; startsector = 64-bit start sector
  94.         ; numsectors = pointer to number of sectors on input,
  95.         ;  must be filled with number of sectors really written
  96. locals
  97. sectors_todo    dd      ?
  98. endl
  99. ; 1. Initialize number of sectors: get number of requested sectors
  100. ; and say that no sectors were read yet.      
  101.         mov     ecx, [numsectors]
  102.         mov     eax, [ecx]
  103.         mov     dword [ecx], 0
  104.         mov     [sectors_todo], eax
  105. ; 2. Acquire the global lock.
  106.         mov     ecx, ide_mutex
  107.         call    mutex_lock
  108. ; 3. Convert parameters to the form suitable for worker procedures.
  109. ; Underlying procedures do not know about 64-bit sectors.
  110. ; Worker procedures use global variables and esi for [buffer].
  111.         cmp     dword [startsector+4], 0
  112.         jnz     .fail
  113.         and     [hd_error], 0
  114.         mov     eax, [userdata]
  115.         mov     [hdpos], eax
  116.         mov     esi, [buffer]
  117.         lea     edi, [startsector]
  118.         mov     [cache_chain_ptr], edi
  119. ; 4. Worker procedures take max 16 sectors per time,
  120. ; loop until all sectors will be processed.
  121. .sectors_loop:
  122.         mov     ecx, 16
  123.         cmp     ecx, [sectors_todo]
  124.         jbe     @f
  125.         mov     ecx, [sectors_todo]
  126. @@:
  127.         mov     [cache_chain_size], cl
  128.         call    bd_write_cache_chain
  129.         cmp     [hd_error], 0
  130.         jnz     .fail
  131.         movzx   ecx, [cache_chain_size]
  132.         mov     eax, [numsectors]
  133.         add     [eax], ecx
  134.         sub     [sectors_todo], ecx
  135.         jz      .done
  136.         add     [edi], ecx
  137.         jc      .fail
  138.         shl     ecx, 9
  139.         add     esi, ecx
  140.         jmp     .sectors_loop
  141. ; 5. Loop is done, either due to error or because everything is done.
  142. ; Release the global lock and return the corresponding status.
  143. .fail:
  144.         mov     ecx, ide_mutex
  145.         call    mutex_unlock
  146.         or      eax, -1
  147.         ret
  148. .done:
  149.         mov     ecx, ide_mutex
  150.         call    mutex_unlock
  151.         xor     eax, eax
  152.         ret
  153. endp
  154. ;-----------------------------------------------------------------
  155. ; This is a stub.
  156. proc bd_querymedia stdcall, hd_data, mediainfo
  157.         mov     eax, [mediainfo]
  158.         mov     [eax+DISKMEDIAINFO.Flags], 0
  159.         mov     [eax+DISKMEDIAINFO.SectorSize], 512
  160.         or      dword [eax+DISKMEDIAINFO.Capacity], 0xFFFFFFFF
  161.         or      dword [eax+DISKMEDIAINFO.Capacity+4], 0xFFFFFFFF
  162.         xor     eax, eax
  163.         ret
  164. endp
  165. ;-----------------------------------------------------------------
  166. bd_read:
  167.         push    eax
  168.         push    edx
  169.         mov     edx, [bios_hdpos]
  170.         cmp     edx, [hdpos]
  171.         jne     .notread
  172.         mov     edx, [bios_cur_sector]
  173.         cmp     eax, edx
  174.         jb      .notread
  175.         add     edx, [bios_read_len]
  176.         dec     edx
  177.         cmp     eax, edx
  178.         ja      .notread
  179.         sub     eax, [bios_cur_sector]
  180.         shl     eax, 9
  181.         add     eax, (OS_BASE+0x9A000)
  182.         push    ecx esi
  183.         mov     esi, eax
  184.         mov     ecx, 512/4
  185.         cld
  186.         rep movsd
  187.         pop     esi ecx
  188.         pop     edx
  189.         pop     eax
  190.         ret
  191. .notread:
  192.         push    ecx
  193.         mov     dl, 42h
  194.         mov     ecx, 16
  195.         call    int13_call
  196.         pop     ecx
  197.         test    eax, eax
  198.         jnz     .v86err
  199.         test    edx, edx
  200.         jz      .readerr
  201.         mov     [bios_read_len], edx
  202.         mov     edx, [hdpos]
  203.         mov     [bios_hdpos], edx
  204.         pop     edx
  205.         pop     eax
  206.         mov     [bios_cur_sector], eax
  207.         jmp     bd_read
  208. .readerr:
  209. .v86err:
  210.         mov     [hd_error], 1
  211.         jmp     hd_read_error
  212. ;-----------------------------------------------------------------
  213. bd_write_cache_chain:
  214.         pusha
  215.         mov     edi, OS_BASE + 0x9A000
  216.         movzx   ecx, [cache_chain_size]
  217.         push    ecx
  218.         shl     ecx, 9-2
  219.         rep movsd
  220.         pop     ecx
  221.         mov     dl, 43h
  222.         mov     eax, [cache_chain_ptr]
  223.         mov     eax, [eax]
  224.         call    int13_call
  225.         test    eax, eax
  226.         jnz     .v86err
  227.         cmp     edx, ecx
  228.         jnz     .writeerr
  229.         popa
  230.         ret
  231. .v86err:
  232. .writeerr:
  233.         popa
  234.         mov     [hd_error], 1
  235.         jmp     hd_write_error
  236. ;-----------------------------------------------------------------
  237. int13_call:
  238. ; Because this code uses fixed addresses,
  239. ; it can not be run simultaniously by many threads.
  240. ; In current implementation it is protected by common mutex 'ide_status'
  241.         mov     word [OS_BASE + 510h], 10h          ; packet length
  242.         mov     word [OS_BASE + 512h], cx           ; number of sectors
  243.         mov     dword [OS_BASE + 514h], 9A000000h   ; buffer 9A00:0000
  244.         mov     dword [OS_BASE + 518h], eax
  245.         and     dword [OS_BASE + 51Ch], 0
  246.         push    ebx ecx esi edi
  247.         mov     ebx, int13_regs_in
  248.         mov     edi, ebx
  249.         mov     ecx, sizeof.v86_regs/4
  250.         xor     eax, eax
  251.         rep stosd
  252.         mov     byte [ebx+v86_regs.eax+1], dl
  253.         mov     eax, [hdpos]
  254.         lea     eax, [BiosDisksData+(eax-80h)*4]
  255.         mov     dl, [eax]
  256.         mov     byte [ebx+v86_regs.edx], dl
  257.         movzx   edx, byte [eax+1]
  258. ;        mov     dl, 5
  259.         test    edx, edx
  260.         jnz     .hasirq
  261.         dec     edx
  262.         jmp     @f
  263. .hasirq:
  264.         pushad
  265.         stdcall enable_irq, edx
  266.         popad
  267. @@:
  268.         mov     word [ebx+v86_regs.esi], 510h
  269.         mov     word [ebx+v86_regs.ss], 9000h
  270.         mov     word [ebx+v86_regs.esp], 0A000h
  271.         mov     word [ebx+v86_regs.eip], 500h
  272.         mov     [ebx+v86_regs.eflags], 20200h
  273.         mov     esi, [sys_v86_machine]
  274.         mov     ecx, 0x502
  275.         push    fs
  276.         call    v86_start
  277.         pop     fs
  278.         and     [bios_hdpos], 0
  279.         pop     edi esi ecx ebx
  280.         movzx   edx, byte [OS_BASE + 512h]
  281.         test    byte [int13_regs_out+v86_regs.eflags], 1
  282.         jnz     @f
  283.         mov     edx, ecx
  284. @@:
  285.         ret
  286.