Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 3742 $
  9.  
  10.  
  11. ; Low-level driver for HDD access
  12. ; DMA support by Mario79
  13. ; Access through BIOS by diamond
  14. ; LBA48 support by Mario79
  15. ;-----------------------------------------------------------------------------
  16. struct HD_DATA
  17. hdbase  dd      ?
  18. hdid    dd      ?
  19. hdpos   dd      ?
  20. ends
  21.  
  22. iglobal
  23. align 4
  24. ide_callbacks:
  25.         dd      ide_callbacks.end - ide_callbacks       ; strucsize
  26.         dd      0       ; no close function
  27.         dd      0       ; no closemedia function
  28.         dd      ide_querymedia
  29.         dd      ide_read
  30.         dd      ide_write
  31.         dd      0       ; no flush function
  32.         dd      0       ; use default cache size
  33. .end:
  34.  
  35. bd_callbacks:
  36.         dd      bd_callbacks.end - bd_callbacks         ; strucsize
  37.         dd      0       ; no close function
  38.         dd      0       ; no closemedia function
  39.         dd      bd_querymedia
  40.         dd      bd_read_interface
  41.         dd      bd_write_interface
  42.         dd      0       ; no flush function
  43.         dd      0       ; use default cache size
  44. .end:
  45.  
  46. hd0_data        HD_DATA         ?,    0, 1
  47. hd1_data        HD_DATA         ?, 0x10, 2
  48. hd2_data        HD_DATA         ?,    0, 3
  49. hd3_data        HD_DATA         ?, 0x10, 4
  50. endg
  51.  
  52. uglobal
  53. ide_mutex               MUTEX
  54. ide_channel1_mutex      MUTEX
  55. ide_channel2_mutex      MUTEX
  56. endg
  57.  
  58. proc ide_read stdcall uses edi, \
  59.         hd_data, buffer, startsector:qword, numsectors
  60.         ; hd_data = pointer to hd*_data
  61.         ; buffer = pointer to buffer for data
  62.         ; startsector = 64-bit start sector
  63.         ; numsectors = pointer to number of sectors on input,
  64.         ;  must be filled with number of sectors really read
  65. locals
  66. sectors_todo    dd      ?
  67. channel_lock    dd      ?
  68. endl
  69. ; 1. Initialize number of sectors: get number of requested sectors
  70. ; and say that no sectors were read yet.
  71.         mov     ecx, [numsectors]
  72.         mov     eax, [ecx]
  73.         mov     dword [ecx], 0
  74.         mov     [sectors_todo], eax
  75. ; 2. Acquire the global lock.
  76.         mov     ecx, ide_mutex
  77.         call    mutex_lock
  78.         mov     ecx, ide_channel2_mutex
  79.         mov     eax, [hd_data]
  80.         cmp     [eax+HD_DATA.hdbase], 0x1F0
  81.         jne     .IDE_Channel_2
  82.         mov     ecx, ide_channel1_mutex
  83. .IDE_Channel_2:
  84.         mov     [channel_lock], ecx
  85.         call    mutex_lock
  86. ; 3. Convert parameters to the form suitable for worker procedures.
  87. ; Underlying procedures do not know about 64-bit sectors.
  88. ; Worker procedures use global variables and edi for [buffer].
  89.         cmp     dword [startsector+4], 0
  90.         jnz     .fail
  91.         and     [hd_error], 0
  92.         mov     ecx, [hd_data]
  93.         mov     eax, [ecx+HD_DATA.hdbase]
  94.         mov     [hdbase], eax
  95.         mov     eax, [ecx+HD_DATA.hdid]
  96.         mov     [hdid], eax
  97.         mov     eax, [ecx+HD_DATA.hdpos]
  98.         mov     [hdpos], eax
  99.         mov     eax, dword [startsector]
  100.         mov     edi, [buffer]
  101. ; 4. Worker procedures take one sectors per time, so loop over all sectors to read.
  102. .sectors_loop:
  103. ; DMA read is permitted if [allow_dma_access]=1 or 2
  104.         cmp     [allow_dma_access], 2
  105.         ja      .nodma
  106.         cmp     [dma_hdd], 1
  107.         jnz     .nodma
  108.         call    hd_read_dma
  109.         jmp     @f
  110. .nodma:
  111.         call    hd_read_pio
  112. @@:
  113.         cmp     [hd_error], 0
  114.         jnz     .fail
  115.         mov     ecx, [numsectors]
  116.         inc     dword [ecx]     ; one more sector is read
  117.         dec     [sectors_todo]
  118.         jz      .done
  119.         inc     eax
  120.         jnz     .sectors_loop
  121. ; 5. Loop is done, either due to error or because everything is done.
  122. ; Release the global lock and return the corresponding status.
  123. .fail:
  124.         mov     ecx, [channel_lock]
  125.         call    mutex_unlock
  126.         mov     ecx, ide_mutex
  127.         call    mutex_unlock
  128.         or      eax, -1
  129.         ret
  130. .done:
  131.         mov     ecx, [channel_lock]
  132.         call    mutex_unlock
  133.         mov     ecx, ide_mutex
  134.         call    mutex_unlock
  135.         xor     eax, eax
  136.         ret
  137. endp
  138.  
  139. proc ide_write stdcall uses esi edi, \
  140.         hd_data, buffer, startsector:qword, numsectors
  141.         ; hd_data = pointer to hd*_data
  142.         ; buffer = pointer to buffer with data
  143.         ; startsector = 64-bit start sector
  144.         ; numsectors = pointer to number of sectors on input,
  145.         ;  must be filled with number of sectors really written
  146. locals
  147. sectors_todo    dd      ?
  148. channel_lock    dd      ?
  149. endl
  150. ; 1. Initialize number of sectors: get number of requested sectors
  151. ; and say that no sectors were read yet.      
  152.         mov     ecx, [numsectors]
  153.         mov     eax, [ecx]
  154.         mov     dword [ecx], 0
  155.         mov     [sectors_todo], eax
  156. ; 2. Acquire the global lock.
  157.         mov     ecx, ide_mutex
  158.         call    mutex_lock
  159.         mov     ecx, ide_channel2_mutex
  160.         mov     eax, [hd_data]
  161.         cmp     [eax+HD_DATA.hdbase], 0x1F0
  162.         jne     .IDE_Channel_2
  163.         mov     ecx, ide_channel1_mutex
  164. .IDE_Channel_2:
  165.         mov     [channel_lock], ecx
  166.         call    mutex_lock
  167. ; 3. Convert parameters to the form suitable for worker procedures.
  168. ; Underlying procedures do not know about 64-bit sectors.
  169. ; Worker procedures use global variables and esi for [buffer].
  170.         cmp     dword [startsector+4], 0
  171.         jnz     .fail
  172.         and     [hd_error], 0
  173.         mov     ecx, [hd_data]
  174.         mov     eax, [ecx+HD_DATA.hdbase]
  175.         mov     [hdbase], eax
  176.         mov     eax, [ecx+HD_DATA.hdid]
  177.         mov     [hdid], eax
  178.         mov     eax, [ecx+HD_DATA.hdpos]
  179.         mov     [hdpos], eax
  180.         mov     esi, [buffer]
  181.         lea     edi, [startsector]
  182.         mov     [cache_chain_ptr], edi
  183. ; 4. Worker procedures take max 16 sectors per time,
  184. ; loop until all sectors will be processed.
  185. .sectors_loop:
  186.         mov     ecx, 16
  187.         cmp     ecx, [sectors_todo]
  188.         jbe     @f
  189.         mov     ecx, [sectors_todo]
  190. @@:
  191.         mov     [cache_chain_size], cl
  192. ; DMA write is permitted only if [allow_dma_access]=1
  193.         cmp     [allow_dma_access], 2
  194.         jae     .nodma
  195.         cmp     [dma_hdd], 1
  196.         jnz     .nodma
  197.         call    cache_write_dma
  198.         jmp     .common
  199. .nodma:
  200.         mov     [cache_chain_size], 1
  201.         call    cache_write_pio
  202. .common:
  203.         cmp     [hd_error], 0
  204.         jnz     .fail
  205.         movzx   ecx, [cache_chain_size]
  206.         mov     eax, [numsectors]
  207.         add     [eax], ecx
  208.         sub     [sectors_todo], ecx
  209.         jz      .done
  210.         add     [edi], ecx
  211.         jc      .fail
  212.         shl     ecx, 9
  213.         add     esi, ecx
  214.         jmp     .sectors_loop
  215. ; 5. Loop is done, either due to error or because everything is done.
  216. ; Release the global lock and return the corresponding status.
  217. .fail:
  218.         mov     ecx, [channel_lock]
  219.         call    mutex_unlock
  220.         mov     ecx, ide_mutex
  221.         call    mutex_unlock
  222.         or      eax, -1
  223.         ret
  224. .done:
  225.         mov     ecx, [channel_lock]
  226.         call    mutex_unlock
  227.         mov     ecx, ide_mutex
  228.         call    mutex_unlock
  229.         xor     eax, eax
  230.         ret
  231. endp
  232.  
  233. ; This is a stub.
  234. proc ide_querymedia stdcall, hd_data, mediainfo
  235.         mov     eax, [mediainfo]
  236.         mov     [eax+DISKMEDIAINFO.Flags], 0
  237.         mov     [eax+DISKMEDIAINFO.SectorSize], 512
  238.         or      dword [eax+DISKMEDIAINFO.Capacity], 0xFFFFFFFF
  239.         or      dword [eax+DISKMEDIAINFO.Capacity+4], 0xFFFFFFFF
  240.         xor     eax, eax
  241.         ret
  242. endp
  243.  
  244. proc bd_read_interface stdcall uses edi, \
  245.         userdata, buffer, startsector:qword, numsectors
  246.         ; userdata = old [hdpos] = 80h + index in NumBiosDisks
  247.         ; buffer = pointer to buffer for data
  248.         ; startsector = 64-bit start sector
  249.         ; numsectors = pointer to number of sectors on input,
  250.         ;  must be filled with number of sectors really read
  251. locals
  252. sectors_todo    dd      ?
  253. endl
  254. ; 1. Initialize number of sectors: get number of requested sectors
  255. ; and say that no sectors were read yet.
  256.         mov     ecx, [numsectors]
  257.         mov     eax, [ecx]
  258.         mov     dword [ecx], 0
  259.         mov     [sectors_todo], eax
  260. ; 2. Acquire the global lock.
  261.         mov     ecx, ide_mutex
  262.         call    mutex_lock
  263. ; 3. Convert parameters to the form suitable for worker procedures.
  264. ; Underlying procedures do not know about 64-bit sectors.
  265. ; Worker procedures use global variables and edi for [buffer].
  266.         cmp     dword [startsector+4], 0
  267.         jnz     .fail
  268.         and     [hd_error], 0
  269.         mov     eax, [userdata]
  270.         mov     [hdpos], eax
  271.         mov     eax, dword [startsector]
  272.         mov     edi, [buffer]
  273. ; 4. Worker procedures take one sectors per time, so loop over all sectors to read.
  274. .sectors_loop:
  275.         call    bd_read
  276.         cmp     [hd_error], 0
  277.         jnz     .fail
  278.         mov     ecx, [numsectors]
  279.         inc     dword [ecx]     ; one more sector is read
  280.         dec     [sectors_todo]
  281.         jz      .done
  282.         inc     eax
  283.         jnz     .sectors_loop
  284. ; 5. Loop is done, either due to error or because everything is done.
  285. ; Release the global lock and return the corresponding status.
  286. .fail:
  287.         mov     ecx, ide_mutex
  288.         call    mutex_unlock
  289.         or      eax, -1
  290.         ret
  291. .done:
  292.         mov     ecx, ide_mutex
  293.         call    mutex_unlock
  294.         xor     eax, eax
  295.         ret
  296. endp
  297.  
  298. proc bd_write_interface stdcall uses esi edi, \
  299.         userdata, buffer, startsector:qword, numsectors
  300.         ; userdata = old [hdpos] = 80h + index in NumBiosDisks
  301.         ; buffer = pointer to buffer with data
  302.         ; startsector = 64-bit start sector
  303.         ; numsectors = pointer to number of sectors on input,
  304.         ;  must be filled with number of sectors really written
  305. locals
  306. sectors_todo    dd      ?
  307. endl
  308. ; 1. Initialize number of sectors: get number of requested sectors
  309. ; and say that no sectors were read yet.      
  310.         mov     ecx, [numsectors]
  311.         mov     eax, [ecx]
  312.         mov     dword [ecx], 0
  313.         mov     [sectors_todo], eax
  314. ; 2. Acquire the global lock.
  315.         mov     ecx, ide_mutex
  316.         call    mutex_lock
  317. ; 3. Convert parameters to the form suitable for worker procedures.
  318. ; Underlying procedures do not know about 64-bit sectors.
  319. ; Worker procedures use global variables and esi for [buffer].
  320.         cmp     dword [startsector+4], 0
  321.         jnz     .fail
  322.         and     [hd_error], 0
  323.         mov     eax, [userdata]
  324.         mov     [hdpos], eax
  325.         mov     esi, [buffer]
  326.         lea     edi, [startsector]
  327.         mov     [cache_chain_ptr], edi
  328. ; 4. Worker procedures take max 16 sectors per time,
  329. ; loop until all sectors will be processed.
  330. .sectors_loop:
  331.         mov     ecx, 16
  332.         cmp     ecx, [sectors_todo]
  333.         jbe     @f
  334.         mov     ecx, [sectors_todo]
  335. @@:
  336.         mov     [cache_chain_size], cl
  337.         call    bd_write_cache_chain
  338.         cmp     [hd_error], 0
  339.         jnz     .fail
  340.         movzx   ecx, [cache_chain_size]
  341.         mov     eax, [numsectors]
  342.         add     [eax], ecx
  343.         sub     [sectors_todo], ecx
  344.         jz      .done
  345.         add     [edi], ecx
  346.         jc      .fail
  347.         shl     ecx, 9
  348.         add     esi, ecx
  349.         jmp     .sectors_loop
  350. ; 5. Loop is done, either due to error or because everything is done.
  351. ; Release the global lock and return the corresponding status.
  352. .fail:
  353.         mov     ecx, ide_mutex
  354.         call    mutex_unlock
  355.         or      eax, -1
  356.         ret
  357. .done:
  358.         mov     ecx, ide_mutex
  359.         call    mutex_unlock
  360.         xor     eax, eax
  361.         ret
  362. endp
  363.  
  364. ; This is a stub.
  365. proc bd_querymedia stdcall, hd_data, mediainfo
  366.         mov     eax, [mediainfo]
  367.         mov     [eax+DISKMEDIAINFO.Flags], 0
  368.         mov     [eax+DISKMEDIAINFO.SectorSize], 512
  369.         or      dword [eax+DISKMEDIAINFO.Capacity], 0xFFFFFFFF
  370.         or      dword [eax+DISKMEDIAINFO.Capacity+4], 0xFFFFFFFF
  371.         xor     eax, eax
  372.         ret
  373. endp
  374.  
  375. ;-----------------------------------------------------------------------------
  376. align 4
  377. ; input: eax = sector, edi -> buffer
  378. ; output: edi = edi + 512
  379. hd_read_pio:
  380.         push    eax edx
  381.  
  382. ; Select the desired drive
  383.         mov     edx, [hdbase]
  384.         add     edx, 6   ;адрес регистра головок
  385.         mov     al, byte [hdid]
  386.         add     al, 128+64+32
  387.         out     dx, al; номер головки/номер диска
  388.        
  389.         call    wait_for_hd_idle
  390.         cmp     [hd_error], 0
  391.         jne     hd_read_error
  392.        
  393. ; ATA with 28 or 48 bit for sector number?
  394.         mov     eax, [esp+4]
  395.         cmp     eax, 0x10000000
  396.         jae     .lba48
  397. ;--------------------------------------
  398. .lba28:
  399.         pushfd
  400.         cli
  401.         xor     eax, eax
  402.         mov     edx, [hdbase]
  403.         inc     edx
  404.         out     dx, al ; ATA Features регистр "особенностей"
  405.         inc     edx
  406.         inc     eax
  407.         out     dx, al ; ATA Sector Counter счётчик секторов
  408.         inc     edx
  409.         mov     eax, [esp+4+4]
  410.         out     dx, al ; LBA Low LBA (7:0)
  411.         shr     eax, 8
  412.         inc     edx
  413.         out     dx, al ; LBA Mid LBA (15:8)
  414.         shr     eax, 8
  415.         inc     edx
  416.         out     dx, al ; LBA High LBA (23:16)
  417.         shr     eax, 8
  418.         inc     edx
  419.         and     al, 1+2+4+8 ; LBA (27:24)
  420.         add     al, byte [hdid]
  421.         add     al, 128+64+32
  422.         out     dx, al ; номер головки/номер диска
  423.         inc     edx
  424.         mov     al, 20h ; READ SECTOR(S)
  425.         out     dx, al ; ATACommand регистр команд
  426.         popfd
  427.         jmp     .continue
  428. ;--------------------------------------
  429. .lba48:
  430.         pushfd
  431.         cli
  432.         xor     eax, eax
  433.         mov     edx, [hdbase]
  434.         inc     edx
  435.         out     dx, al ; Features Previous Reserved
  436.         out     dx, al ; Features Current Reserved
  437.         inc     edx
  438.         out     dx, al ; Sector Count Previous Sector count (15:8)
  439.         inc     eax
  440.         out     dx, al ; Sector Count Current Sector count (7:0)
  441.         inc     edx
  442.         mov     eax, [esp+4+4]
  443.         rol     eax, 8
  444.         out     dx, al ; LBA Low Previous LBA (31:24)
  445.         xor     eax, eax ; because only 32 bit cache
  446.         inc     edx
  447.         out     dx, al ; LBA Mid Previous LBA (39:32)
  448.         inc     edx
  449.         out     dx, al ; LBA High Previous LBA (47:40)
  450.         sub     edx, 2
  451.         mov     eax, [esp+4+4]
  452.         out     dx, al ; LBA Low Current LBA (7:0)
  453.         shr     eax, 8
  454.         inc     edx
  455.         out     dx, al ; LBA Mid Current LBA (15:8)
  456.         shr     eax, 8
  457.         inc     edx
  458.         out     dx, al ; LBA High Current LBA (23:16)
  459.         inc     edx
  460.         mov     al, byte [hdid]
  461.         add     al, 128+64+32
  462.         out     dx, al ; номер головки/номер диска
  463.         inc     edx
  464.         mov     al, 24h ; READ SECTOR(S) EXT
  465.         out     dx, al ; ATACommand регистр команд
  466.         popfd
  467. ;--------------------------------------
  468. .continue:
  469.         call    wait_for_sector_buffer
  470.  
  471.         cmp     [hd_error], 0
  472.         jne     hd_read_error
  473.  
  474.         pushfd
  475.         cli
  476.  
  477.         mov     ecx, 256
  478.         mov     edx, [hdbase]
  479.         cld
  480.         rep insw
  481.         popfd
  482.  
  483.         pop     edx eax
  484.         ret
  485. ;-----------------------------------------------------------------------------
  486. align 4
  487. ; edi -> sector, esi -> data
  488. cache_write_pio:
  489. ; Select the desired drive
  490.         mov     edx, [hdbase]
  491.         add     edx, 6   ;адрес регистра головок
  492.         mov     al, byte [hdid]
  493.         add     al, 128+64+32
  494.         out     dx, al ; номер головки/номер диска
  495.  
  496.         call    wait_for_hd_idle
  497.         cmp     [hd_error], 0
  498.         jne     hd_write_error
  499.  
  500. ; ATA with 28 or 48 bit for sector number?
  501.         mov     eax, [edi]
  502.         cmp     eax, 0x10000000
  503.         jae     .lba48
  504. ;--------------------------------------
  505. .lba28:
  506.         pushfd
  507.         cli
  508.         xor     eax, eax
  509.         mov     edx, [hdbase]
  510.         inc     edx
  511.         out     dx, al ; ATA Features регистр "особенностей"
  512.         inc     edx
  513.         inc     eax
  514.         out     dx, al ; ATA Sector Counter счётчик секторов
  515.         inc     edx
  516.         mov     eax, [edi]      ; eax = sector to write
  517.         out     dx, al ; LBA Low LBA (7:0)
  518.         shr     eax, 8
  519.         inc     edx
  520.         out     dx, al ; LBA Mid LBA (15:8)
  521.         shr     eax, 8
  522.         inc     edx
  523.         out     dx, al ; LBA High LBA (23:16)
  524.         shr     eax, 8
  525.         inc     edx
  526.         and     al, 1+2+4+8 ; LBA (27:24)
  527.         add     al, byte [hdid]
  528.         add     al, 128+64+32
  529.         out     dx, al ; номер головки/номер диска
  530.         inc     edx
  531.         mov     al, 30h ; WRITE SECTOR(S)
  532.         out     dx, al ; ATACommand регистр команд
  533.         popfd
  534.         jmp     .continue
  535. ;--------------------------------------
  536. .lba48:
  537.         pushfd
  538.         cli
  539.         xor     eax, eax
  540.         mov     edx, [hdbase]
  541.         inc     edx
  542.         out     dx, al ; Features Previous Reserved
  543.         out     dx, al ; Features Current Reserved
  544.         inc     edx
  545.         out     dx, al ; Sector Count Previous Sector count (15:8)
  546.         inc     eax
  547.         out     dx, al ; Sector Count Current Sector count (7:0)
  548.         inc     edx
  549.         mov     eax, [edi]
  550.         rol     eax, 8
  551.         out     dx, al ; LBA Low Previous LBA (31:24)
  552.         xor     eax, eax ; because only 32 bit cache
  553.         inc     edx
  554.         out     dx, al ; LBA Mid Previous LBA (39:32)
  555.         inc     edx
  556.         out     dx, al ; LBA High Previous LBA (47:40)
  557.         sub     edx, 2
  558.         mov     eax, [edi]
  559.         out     dx, al ; LBA Low Current LBA (7:0)
  560.         shr     eax, 8
  561.         inc     edx
  562.         out     dx, al ; LBA Mid Current LBA (15:8)
  563.         shr     eax, 8
  564.         inc     edx
  565.         out     dx, al ; LBA High Current LBA (23:16)
  566.         inc     edx
  567.         mov     al, byte [hdid]
  568.         add     al, 128+64+32
  569.         out     dx, al ; номер головки/номер диска
  570.         inc     edx
  571.         mov     al, 34h ; WRITE SECTOR(S) EXT
  572.         out     dx, al ; ATACommand регистр команд
  573.         popfd
  574. ;--------------------------------------
  575. .continue:
  576.         call    wait_for_sector_buffer
  577.  
  578.         cmp     [hd_error], 0
  579.         jne     hd_write_error
  580.  
  581.         push    ecx esi
  582.  
  583.         pushfd
  584.         cli
  585.         mov     ecx, 256
  586.         mov     edx, [hdbase]
  587.         cld
  588.         rep outsw
  589.         popfd
  590.  
  591.         pop     esi ecx
  592.         ret
  593. ;-----------------------------------------------------------------------------
  594. align 4
  595. save_hd_wait_timeout:
  596.         push    eax
  597.         mov     eax, [timer_ticks]
  598.         add     eax, 300        ; 3 sec timeout
  599.         mov     [hd_wait_timeout], eax
  600.         pop     eax
  601.         ret
  602. ;-----------------------------------------------------------------------------
  603. align 4
  604. check_hd_wait_timeout:
  605.         push    eax
  606.         mov     eax, [hd_wait_timeout]
  607.         cmp     [timer_ticks], eax
  608.         jg      hd_timeout_error
  609.  
  610.         pop     eax
  611.         mov     [hd_error], 0
  612.         ret
  613. ;-----------------------------------------------------------------------------
  614. hd_timeout_error:
  615.         if lang eq sp
  616.         DEBUGF 1,"K : FS - HD tiempo de espera agotado\n"
  617.         else
  618.         DEBUGF 1,"K : FS - HD timeout\n"
  619.         end if
  620.         mov     [hd_error], 1
  621.         pop     eax
  622.         ret
  623. ;-----------------------------------------------------------------------------
  624. hd_read_error:
  625.         if lang eq sp
  626.         DEBUGF 1,"K : FS - HD error de lectura\n"
  627.         else
  628.         DEBUGF 1,"K : FS - HD read error\n"
  629.         end if
  630.         pop     edx eax
  631.         ret
  632. ;-----------------------------------------------------------------------------
  633. hd_write_error_dma:
  634.         pop     esi
  635. hd_write_error:
  636.         if lang eq sp
  637.         DEBUGF 1,"K : FS - HD error de escritura\n"
  638.         else
  639.         DEBUGF 1,"K : FS - HD write error\n"
  640.         end if
  641.         ret
  642. ;-----------------------------------------------------------------------------
  643. hd_lba_error:
  644.         if lang eq sp
  645.         DEBUGF 1,"K : FS - HD error en LBA\n"
  646.         else
  647.         DEBUGF 1,"K : FS - HD LBA error\n"
  648.         end if
  649.         jmp     LBA_read_ret
  650. ;-----------------------------------------------------------------------------
  651. align 4
  652. wait_for_hd_idle:
  653.         push    eax edx
  654.  
  655.         call    save_hd_wait_timeout
  656.  
  657.         mov     edx, [hdbase]
  658.         add     edx, 0x7
  659. ;--------------------------------------
  660. align 4
  661. wfhil1:
  662.         call    check_hd_wait_timeout
  663.         cmp     [hd_error], 0
  664.         jne     @f
  665.  
  666.         in      al, dx
  667.         test    al, 128
  668.         jnz     wfhil1
  669.  
  670. @@:
  671.         pop     edx eax
  672.         ret
  673. ;-----------------------------------------------------------------------------
  674. align 4
  675. wait_for_sector_buffer:
  676.         push    eax edx
  677.  
  678.         mov     edx, [hdbase]
  679.         add     edx, 0x7
  680.  
  681.         call    save_hd_wait_timeout
  682. ;--------------------------------------
  683. align 4
  684. hdwait_sbuf:                  ; wait for sector buffer to be ready
  685.         call    check_hd_wait_timeout
  686.         cmp     [hd_error], 0
  687.         jne     @f
  688.  
  689.         in      al, dx
  690.         test    al, 8
  691.         jz      hdwait_sbuf
  692.  
  693.         mov     [hd_error], 0
  694.  
  695.         cmp     [hd_setup], 1   ; do not mark error for setup request
  696.         je      buf_wait_ok
  697.  
  698.         test    al, 1           ; previous command ended up with an error
  699.         jz      buf_wait_ok
  700. @@:
  701.         mov     [hd_error], 1
  702.  
  703. buf_wait_ok:
  704.         pop     edx eax
  705.         ret
  706. ;-----------------------------------------------------------------------------
  707. align 4
  708. wait_for_sector_dma_ide0:
  709.         push    eax
  710.         push    edx
  711.         call    save_hd_wait_timeout
  712. ;--------------------------------------
  713. align 4
  714. .wait:
  715.         call    change_task
  716.         cmp     [irq14_func], hdd_irq14
  717.         jnz     .done
  718.         call    check_hd_wait_timeout
  719.         cmp     [hd_error], 0
  720.         jz      .wait
  721.         mov     [irq14_func], hdd_irq_null
  722.         mov     dx, [IDEContrRegsBaseAddr]
  723.         mov     al, 0
  724.         out     dx, al
  725. .done:
  726.         pop     edx
  727.         pop     eax
  728.         ret
  729. ;-----------------------------------------------------------------------------
  730. align 4
  731. wait_for_sector_dma_ide1:
  732.         push    eax
  733.         push    edx
  734.         call    save_hd_wait_timeout
  735. ;--------------------------------------
  736. align 4
  737. .wait:
  738.         call    change_task
  739.         cmp     [irq15_func], hdd_irq15
  740.         jnz     .done
  741.         call    check_hd_wait_timeout
  742.         cmp     [hd_error], 0
  743.         jz      .wait
  744.         mov     [irq15_func], hdd_irq_null
  745.         mov     dx, [IDEContrRegsBaseAddr]
  746.         add     dx, 8
  747.         mov     al, 0
  748.         out     dx, al
  749. .done:
  750.         pop     edx
  751.         pop     eax
  752.         ret
  753. ;-----------------------------------------------------------------------------
  754. iglobal
  755. align 4
  756. ; note that IDE descriptor table must be 4-byte aligned and do not cross 4K boundary
  757. IDE_descriptor_table:
  758.         dd IDE_DMA
  759.         dw 0x2000
  760.         dw 0x8000
  761.  
  762. dma_cur_sector  dd not 40h
  763. dma_hdpos       dd 0
  764. irq14_func      dd hdd_irq_null
  765. irq15_func      dd hdd_irq_null
  766. endg
  767. ;-----------------------------------------------------------------------------
  768. uglobal
  769. ; all uglobals are zeroed at boot
  770. dma_process         dd 0
  771. dma_slot_ptr        dd 0
  772. cache_chain_pos     dd 0
  773. cache_chain_ptr     dd 0
  774. cache_chain_size    db 0
  775. cache_chain_started db 0
  776. dma_task_switched   db 0
  777. dma_hdd             db 0
  778. allow_dma_access    db 0
  779. endg
  780. ;-----------------------------------------------------------------------------
  781. align 4
  782. hdd_irq14:
  783.         pushfd
  784.         cli
  785.         pushad
  786.         mov     [irq14_func], hdd_irq_null
  787.         mov     dx, [IDEContrRegsBaseAddr]
  788.         mov     al, 0
  789.         out     dx, al
  790.         popad
  791.         popfd
  792. align 4
  793. hdd_irq_null:
  794.         ret
  795. ;-----------------------------------------------------------------------------
  796. align 4
  797. hdd_irq15:
  798.         pushfd
  799.         cli
  800.         pushad
  801.         mov     [irq15_func], hdd_irq_null
  802.         mov     dx, [IDEContrRegsBaseAddr]
  803.         add     dx, 8
  804.         mov     al, 0
  805.         out     dx, al
  806.         popad
  807.         popfd
  808.         ret
  809. ;-----------------------------------------------------------------------------
  810. align 4
  811. hd_read_dma:
  812.         push    eax
  813.         push    edx
  814.         mov     edx, [dma_hdpos]
  815.         cmp     edx, [hdpos]
  816.         jne     .notread
  817.         mov     edx, [dma_cur_sector]
  818.         cmp     eax, edx
  819.         jb      .notread
  820.         add     edx, 15
  821.         cmp     [esp+4], edx
  822.         ja      .notread
  823.         mov     eax, [esp+4]
  824.         sub     eax, [dma_cur_sector]
  825.         shl     eax, 9
  826.         add     eax, (OS_BASE+IDE_DMA)
  827.         push    ecx esi
  828.         mov     esi, eax
  829.  
  830.         mov     ecx, 512/4
  831.         cld
  832.         rep movsd
  833.         pop     esi ecx
  834.         pop     edx
  835.         pop     eax
  836.         ret
  837. .notread:
  838.         mov     eax, IDE_descriptor_table
  839.         mov     dword [eax], IDE_DMA
  840.         mov     word [eax+4], 0x2000
  841.         sub     eax, OS_BASE
  842.         mov     dx, [IDEContrRegsBaseAddr]
  843.         cmp     [hdbase], 0x1F0
  844.         jz      @f
  845.         add     edx, 8
  846. @@:
  847.         push    edx
  848.         add     edx, 4
  849.         out     dx, eax
  850.         pop     edx
  851.         mov     al, 0
  852.         out     dx, al
  853.         add     edx, 2
  854.         mov     al, 6
  855.         out     dx, al
  856.  
  857. ; Select the desired drive
  858.         mov     edx, [hdbase]
  859.         add     edx, 6   ; адрес регистра головок
  860.         mov     al, byte [hdid]
  861.         add     al, 128+64+32
  862.         out     dx, al ; номер головки/номер диска
  863.  
  864.         call    wait_for_hd_idle
  865.         cmp     [hd_error], 0
  866.         jnz     hd_read_error
  867.  
  868. ; ATA with 28 or 48 bit for sector number?
  869.         mov     eax, [esp+4]
  870. ; -10h because the PreCache hits the boundary between lba28 and lba48
  871. ; 10h = 16  - size of PreCache
  872.         cmp     eax, 0x10000000-10h
  873.         jae     .lba48
  874. ;--------------------------------------
  875. .lba28:
  876.         pushfd
  877.         cli
  878.         xor     eax, eax
  879.         mov     edx, [hdbase]
  880.         inc     edx
  881.         out     dx, al ; ATA Features регистр "особенностей"
  882.         inc     edx
  883.         mov     eax, 10h ; Sector Counter = 16 ; PreCache
  884.         out     dx, al ; ATA Sector Counter счётчик секторов
  885.         inc     edx
  886.         mov     eax, [esp+4+4]
  887.         out     dx, al ; LBA Low LBA (7:0)
  888.         shr     eax, 8
  889.         inc     edx
  890.         out     dx, al ; LBA Mid LBA (15:8)
  891.         shr     eax, 8
  892.         inc     edx
  893.         out     dx, al ; LBA High LBA (23:16)
  894.         shr     eax, 8
  895.         inc     edx
  896.         and     al, 0xF ; LBA (27:24)
  897.         add     al, byte [hdid]
  898.         add     al, 11100000b
  899.         out     dx, al ; номер головки/номер диска
  900.         inc     edx
  901.         mov     al, 0xC8 ; READ DMA
  902.         out     dx, al ; ATACommand регистр команд
  903.         jmp     .continue
  904. ;--------------------------------------
  905. .lba48:
  906.         pushfd
  907.         cli
  908.         xor     eax, eax
  909.         mov     edx, [hdbase]
  910.         inc     edx
  911.         out     dx, al ; Features Previous Reserved
  912.         out     dx, al ; Features Current Reserved
  913.         inc     edx
  914.         out     dx, al ; Sector Count Previous Sector count (15:8)
  915.         mov     eax, 10h ; Sector Counter = 16 PreCache
  916.         out     dx, al ; Sector Count Current Sector count (7:0)
  917.         inc     edx
  918.         mov     eax, [esp+4+4]
  919.         rol     eax, 8
  920.         out     dx, al ; LBA Low Previous LBA (31:24)
  921.         xor     eax, eax ; because only 32 bit cache
  922.         inc     edx
  923.         out     dx, al ; LBA Mid Previous LBA (39:32)
  924.         inc     edx
  925.         out     dx, al ; LBA High Previous LBA (47:40)
  926.         sub     edx, 2
  927.         mov     eax, [esp+4+4]
  928.         out     dx, al ; LBA Low Current LBA (7:0)
  929.         shr     eax, 8
  930.         inc     edx
  931.         out     dx, al ; LBA Mid Current LBA (15:8)
  932.         shr     eax, 8
  933.         inc     edx
  934.         out     dx, al ; LBA High Current LBA (23:16)
  935.         inc     edx
  936.         mov     al, byte [hdid]
  937.         add     al, 128+64+32
  938.         out     dx, al ; номер головки/номер диска
  939.         inc     edx
  940.         mov     al, 25h ; READ DMA EXT
  941.         out     dx, al ; ATACommand регистр команд
  942. ;--------------------------------------
  943. .continue:
  944.         mov     dx, [IDEContrRegsBaseAddr]
  945.         mov     eax, [hd_address_table]
  946.         cmp     [hdbase], eax ; 0x1F0
  947.         jz      @f
  948.         add     dx, 8
  949. @@:
  950.         mov     al, 9
  951.         out     dx, al
  952.         mov     eax, [CURRENT_TASK]
  953.         mov     [dma_process], eax
  954.         mov     eax, [TASK_BASE]
  955.         mov     [dma_slot_ptr], eax
  956.         mov     eax, [hd_address_table]
  957.         cmp     [hdbase], eax ; 0x1F0
  958.         jnz     .ide1
  959.         mov     [irq14_func], hdd_irq14
  960.         jmp     @f
  961. .ide1:
  962.         mov     [irq15_func], hdd_irq15
  963. @@:
  964.         popfd
  965.         mov     eax, [hd_address_table]
  966.         cmp     [hdbase], eax ; 0x1F0
  967.         jnz     .wait_ide1
  968.         call    wait_for_sector_dma_ide0
  969.         jmp     @f
  970. .wait_ide1:
  971.         call    wait_for_sector_dma_ide1
  972. @@:
  973.         cmp     [hd_error], 0
  974.         jnz     hd_read_error
  975.         mov     eax, [hdpos]
  976.         mov     [dma_hdpos], eax
  977.         pop     edx
  978.         pop     eax
  979.         mov     [dma_cur_sector], eax
  980.         jmp     hd_read_dma
  981. ;-----------------------------------------------------------------------------
  982. cache_write_dma:
  983.         mov     eax, [cache_chain_ptr]
  984.         push    esi
  985.         mov     eax, IDE_descriptor_table
  986.         mov     edx, eax
  987.         pusha
  988.         mov     edi, (OS_BASE+IDE_DMA)
  989.         mov     dword [edx], IDE_DMA
  990.         movzx   ecx, [cache_chain_size]
  991.         shl     ecx, 9
  992.         mov     word [edx+4], cx
  993.         shr     ecx, 2
  994.         cld
  995.         rep movsd
  996.         popa
  997.         sub     eax, OS_BASE
  998.         mov     dx, [IDEContrRegsBaseAddr]
  999.         cmp     [hdbase], 0x1F0
  1000.         jz      @f
  1001.         add     edx, 8
  1002. @@:
  1003.         push    edx
  1004.         add     edx, 4
  1005.         out     dx, eax
  1006.         pop     edx
  1007.         mov     al, 0
  1008.         out     dx, al
  1009.         add     edx, 2
  1010.         mov     al, 6
  1011.         out     dx, al
  1012.  
  1013. ; Select the desired drive
  1014.         mov     edx, [hdbase]
  1015.         add     edx, 6   ; адрес регистра головок
  1016.         mov     al, byte [hdid]
  1017.         add     al, 128+64+32
  1018.         out     dx, al ; номер головки/номер диска
  1019.  
  1020.         call    wait_for_hd_idle
  1021.         cmp     [hd_error], 0
  1022.         jnz     hd_write_error_dma
  1023.  
  1024. ; ATA with 28 or 48 bit for sector number?
  1025.         mov     esi, [cache_chain_ptr]
  1026.         mov     eax, [esi]
  1027. ; -40h because the PreCache hits the boundary between lba28 and lba48
  1028. ; 40h = 64  - the maximum number of sectors to be written for one command
  1029.         cmp     eax, 0x10000000-40h
  1030.         jae     .lba48
  1031. ;--------------------------------------
  1032. .lba28:
  1033.         pushfd
  1034.         cli
  1035.         xor     eax, eax
  1036.         mov     edx, [hdbase]
  1037.         inc     edx
  1038.         out     dx, al ; ATA Features регистр "особенностей"
  1039.         inc     edx
  1040.         mov     al, [cache_chain_size] ; Sector Counter
  1041.         out     dx, al ; ATA Sector Counter счётчик секторов
  1042.         inc     edx
  1043.         mov     eax, [esi]
  1044.         out     dx, al ; LBA Low LBA (7:0)
  1045.         shr     eax, 8
  1046.         inc     edx
  1047.         out     dx, al ; LBA Mid LBA (15:8)
  1048.         shr     eax, 8
  1049.         inc     edx
  1050.         out     dx, al ; LBA High LBA (23:16)
  1051.         shr     eax, 8
  1052.         inc     edx
  1053.         and     al, 0xF ; LBA (27:24)
  1054.         add     al, byte [hdid]
  1055.         add     al, 11100000b
  1056.         out     dx, al ; номер головки/номер диска
  1057.         inc     edx
  1058.         mov     al, 0xCA ; WRITE DMA
  1059.         out     dx, al ; ATACommand регистр команд
  1060.         jmp     .continue
  1061. ;--------------------------------------
  1062. .lba48:
  1063.         pushfd
  1064.         cli
  1065.         xor     eax, eax
  1066.         mov     edx, [hdbase]
  1067.         inc     edx
  1068.         out     dx, al ; Features Previous Reserved
  1069.         out     dx, al ; Features Current Reserved
  1070.         inc     edx
  1071.         out     dx, al ; Sector Count Previous Sector count (15:8)
  1072.         mov     al, [cache_chain_size] ; Sector Counter
  1073.         out     dx, al ; Sector Count Current Sector count (7:0)
  1074.         inc     edx
  1075.         mov     eax, [esi]
  1076.         rol     eax, 8
  1077.         out     dx, al ; LBA Low Previous LBA (31:24)
  1078.         xor     eax, eax ; because only 32 bit cache
  1079.         inc     edx
  1080.         out     dx, al ; LBA Mid Previous LBA (39:32)
  1081.         inc     edx
  1082.         out     dx, al ; LBA High Previous LBA (47:40)
  1083.         sub     edx, 2
  1084.         mov     eax, [esi]
  1085.         out     dx, al ; LBA Low Current LBA (7:0)
  1086.         shr     eax, 8
  1087.         inc     edx
  1088.         out     dx, al ; LBA Mid Current LBA (15:8)
  1089.         shr     eax, 8
  1090.         inc     edx
  1091.         out     dx, al ; LBA High Current LBA (23:16)
  1092.         inc     edx
  1093.         mov     al, byte [hdid]
  1094.         add     al, 128+64+32
  1095.         out     dx, al ; номер головки/номер диска
  1096.         inc     edx
  1097.         mov     al, 35h ; WRITE DMA EXT
  1098.         out     dx, al ; ATACommand регистр команд
  1099. ;--------------------------------------
  1100. .continue:
  1101.         mov     dx, [IDEContrRegsBaseAddr]
  1102.         mov     eax, [hd_address_table]
  1103.         cmp     [hdbase], eax ; 0x1F0
  1104.         jz      @f
  1105.         add     dx, 8
  1106. @@:
  1107.         mov     al, 1
  1108.         out     dx, al
  1109.         mov     eax, [CURRENT_TASK]
  1110.         mov     [dma_process], eax
  1111.         mov     eax, [TASK_BASE]
  1112.         mov     [dma_slot_ptr], eax
  1113.         mov     eax, [hd_address_table]
  1114.         cmp     [hdbase], eax ; 0x1F0
  1115.         jnz     .ide1
  1116.         mov     [irq14_func], hdd_irq14
  1117.         jmp     @f
  1118. .ide1:
  1119.         mov     [irq15_func], hdd_irq15
  1120. @@:
  1121.         popfd
  1122.         mov     [dma_cur_sector], not 0x40
  1123.         mov     eax, [hd_address_table]
  1124.         cmp     [hdbase], eax ; 0x1F0
  1125.         jnz     .wait_ide1
  1126.         call    wait_for_sector_dma_ide0
  1127.         jmp     @f
  1128. .wait_ide1:
  1129.         call    wait_for_sector_dma_ide1
  1130. @@:
  1131.         cmp     [hd_error], 0
  1132.         jnz     hd_write_error_dma
  1133.         pop     esi
  1134.         ret
  1135. ;-----------------------------------------------------------------------------
  1136. uglobal
  1137. IDEContrRegsBaseAddr         dw ?
  1138. IDEContrProgrammingInterface dw ?
  1139. IDE_BAR0_val    dw ?
  1140. IDE_BAR1_val    dw ?
  1141. IDE_BAR2_val    dw ?
  1142. IDE_BAR3_val    dw ?
  1143. endg
  1144. ;-----------------------------------------------------------------------------
  1145. ; \begin{diamond}
  1146. uglobal
  1147. bios_hdpos      dd 0       ; 0 is invalid value for [hdpos]
  1148. bios_cur_sector dd ?
  1149. bios_read_len   dd ?
  1150. endg
  1151. ;-----------------------------------------------------------------------------
  1152. align 4
  1153. bd_read:
  1154.         push    eax
  1155.         push    edx
  1156.         mov     edx, [bios_hdpos]
  1157.         cmp     edx, [hdpos]
  1158.         jne     .notread
  1159.         mov     edx, [bios_cur_sector]
  1160.         cmp     eax, edx
  1161.         jb      .notread
  1162.         add     edx, [bios_read_len]
  1163.         dec     edx
  1164.         cmp     eax, edx
  1165.         ja      .notread
  1166.         sub     eax, [bios_cur_sector]
  1167.         shl     eax, 9
  1168.         add     eax, (OS_BASE+0x9A000)
  1169.         push    ecx esi
  1170.         mov     esi, eax
  1171.         mov     ecx, 512/4
  1172.         cld
  1173.         rep movsd
  1174.         pop     esi ecx
  1175.         pop     edx
  1176.         pop     eax
  1177.         ret
  1178. .notread:
  1179.         push    ecx
  1180.         mov     dl, 42h
  1181.         mov     ecx, 16
  1182.         call    int13_call
  1183.         pop     ecx
  1184.         test    eax, eax
  1185.         jnz     .v86err
  1186.         test    edx, edx
  1187.         jz      .readerr
  1188.         mov     [bios_read_len], edx
  1189.         mov     edx, [hdpos]
  1190.         mov     [bios_hdpos], edx
  1191.         pop     edx
  1192.         pop     eax
  1193.         mov     [bios_cur_sector], eax
  1194.         jmp     bd_read
  1195. .readerr:
  1196. .v86err:
  1197.         mov     [hd_error], 1
  1198.         jmp     hd_read_error
  1199. ;-----------------------------------------------------------------------------
  1200. align 4
  1201. bd_write_cache_chain:
  1202.         pusha
  1203.         mov     edi, OS_BASE + 0x9A000
  1204.         movzx   ecx, [cache_chain_size]
  1205.         push    ecx
  1206.         shl     ecx, 9-2
  1207.         rep movsd
  1208.         pop     ecx
  1209.         mov     dl, 43h
  1210.         mov     eax, [cache_chain_ptr]
  1211.         mov     eax, [eax]
  1212.         call    int13_call
  1213.         test    eax, eax
  1214.         jnz     .v86err
  1215.         cmp     edx, ecx
  1216.         jnz     .writeerr
  1217.         popa
  1218.         ret
  1219. .v86err:
  1220. .writeerr:
  1221.         popa
  1222.         mov     [hd_error], 1
  1223.         jmp     hd_write_error
  1224. ;-----------------------------------------------------------------------------
  1225. uglobal
  1226. int13_regs_in   rb sizeof.v86_regs
  1227. int13_regs_out  rb sizeof.v86_regs
  1228. endg
  1229. ;-----------------------------------------------------------------------------
  1230. align 4
  1231. int13_call:
  1232. ; Because this code uses fixed addresses,
  1233. ; it can not be run simultaniously by many threads.
  1234. ; In current implementation it is protected by common mutex 'ide_status'
  1235.         mov     word [OS_BASE + 510h], 10h             ; packet length
  1236.         mov     word [OS_BASE + 512h], cx              ; number of sectors
  1237.         mov     dword [OS_BASE + 514h], 9A000000h      ; buffer 9A00:0000
  1238.         mov     dword [OS_BASE + 518h], eax
  1239.         and     dword [OS_BASE + 51Ch], 0
  1240.         push    ebx ecx esi edi
  1241.         mov     ebx, int13_regs_in
  1242.         mov     edi, ebx
  1243.         mov     ecx, sizeof.v86_regs/4
  1244.         xor     eax, eax
  1245.         rep stosd
  1246.         mov     byte [ebx+v86_regs.eax+1], dl
  1247.         mov     eax, [hdpos]
  1248.         lea     eax, [BiosDisksData+(eax-80h)*4]
  1249.         mov     dl, [eax]
  1250.         mov     byte [ebx+v86_regs.edx], dl
  1251.         movzx   edx, byte [eax+1]
  1252. ;        mov     dl, 5
  1253.         test    edx, edx
  1254.         jnz     .hasirq
  1255.         dec     edx
  1256.         jmp     @f
  1257. .hasirq:
  1258.         pushad
  1259.         stdcall enable_irq, edx
  1260.         popad
  1261. @@:
  1262.         mov     word [ebx+v86_regs.esi], 510h
  1263.         mov     word [ebx+v86_regs.ss], 9000h
  1264.         mov     word [ebx+v86_regs.esp], 0A000h
  1265.         mov     word [ebx+v86_regs.eip], 500h
  1266.         mov     [ebx+v86_regs.eflags], 20200h
  1267.         mov     esi, [sys_v86_machine]
  1268.         mov     ecx, 0x502
  1269.         push    fs
  1270.         call    v86_start
  1271.         pop     fs
  1272.         and     [bios_hdpos], 0
  1273.         pop     edi esi ecx ebx
  1274.         movzx   edx, byte [OS_BASE + 512h]
  1275.         test    byte [int13_regs_out+v86_regs.eflags], 1
  1276.         jnz     @f
  1277.         mov     edx, ecx
  1278. @@:
  1279.         ret
  1280. ; \end{diamond}
  1281.