Subversion Repositories Kolibri OS

Rev

Rev 5569 | Rev 6016 | 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: 6014 $
  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.         pop     edx
  211.         pop     eax
  212.         mov     [hd_error], 1
  213.         jmp     hd_read_error
  214. ;-----------------------------------------------------------------
  215. bd_write_cache_chain:
  216.         pusha
  217.         mov     edi, OS_BASE + 0x9A000
  218.         movzx   ecx, [cache_chain_size]
  219.         push    ecx
  220.         shl     ecx, 9-2
  221.         rep movsd
  222.         pop     ecx
  223.         mov     dl, 43h
  224.         mov     eax, [cache_chain_ptr]
  225.         mov     eax, [eax]
  226.         call    int13_call
  227.         test    eax, eax
  228.         jnz     .v86err
  229.         cmp     edx, ecx
  230.         jnz     .writeerr
  231.         popa
  232.         ret
  233. .v86err:
  234. .writeerr:
  235.         popa
  236.         mov     [hd_error], 1
  237.         jmp     hd_write_error
  238. ;-----------------------------------------------------------------
  239. int13_call:
  240. ; Because this code uses fixed addresses,
  241. ; it can not be run simultaniously by many threads.
  242. ; In current implementation it is protected by common mutex 'ide_status'
  243.         mov     word [OS_BASE + 510h], 10h          ; packet length
  244.         mov     word [OS_BASE + 512h], cx           ; number of sectors
  245.         mov     dword [OS_BASE + 514h], 9A000000h   ; buffer 9A00:0000
  246.         mov     dword [OS_BASE + 518h], eax
  247.         and     dword [OS_BASE + 51Ch], 0
  248.         push    ebx ecx esi edi
  249.         mov     ebx, int13_regs_in
  250.         mov     edi, ebx
  251.         mov     ecx, sizeof.v86_regs/4
  252.         xor     eax, eax
  253.         rep stosd
  254.         mov     byte [ebx+v86_regs.eax+1], dl
  255.         mov     eax, [hdpos]
  256.         lea     eax, [BiosDisksData+(eax-80h)*4]
  257.         mov     dl, [eax]
  258.         mov     byte [ebx+v86_regs.edx], dl
  259.         movzx   edx, byte [eax+1]
  260. ;        mov     dl, 5
  261.         test    edx, edx
  262.         jnz     .hasirq
  263.         dec     edx
  264.         jmp     @f
  265. .hasirq:
  266.         pushad
  267.         stdcall enable_irq, edx
  268.         popad
  269. @@:
  270.         mov     word [ebx+v86_regs.esi], 510h
  271.         mov     word [ebx+v86_regs.ss], 9000h
  272.         mov     word [ebx+v86_regs.esp], 0A000h
  273.         mov     word [ebx+v86_regs.eip], 500h
  274.         mov     [ebx+v86_regs.eflags], 20200h
  275.         mov     esi, [sys_v86_machine]
  276.         mov     ecx, 0x502
  277.         push    fs
  278.         call    v86_start
  279.         pop     fs
  280.         and     [bios_hdpos], 0
  281.         pop     edi esi ecx ebx
  282.         movzx   edx, byte [OS_BASE + 512h]
  283.         test    byte [int13_regs_out+v86_regs.eflags], 1
  284.         jnz     @f
  285.         mov     edx, ecx
  286. @@:
  287.         ret
  288.