Subversion Repositories Kolibri OS

Rev

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