Subversion Repositories Kolibri OS

Rev

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