Subversion Repositories Kolibri OS

Rev

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

  1. $Revision: 514 $
  2. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3. ;;                                                              ;;
  4. ;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
  5. ;; Distributed under terms of the GNU General Public License    ;;
  6. ;;                                                              ;;
  7. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  8.  
  9. ; Low-level driver for HDD access
  10. ; DMA support by Mario79
  11.  
  12. ;**************************************************************************
  13. ;
  14. ;   0x600008  - first entry in cache list
  15. ;
  16. ;            +0   - lba sector
  17. ;            +4   - state of cache sector
  18. ;                   0 = empty
  19. ;                   1 = used for read  ( same as in hd )
  20. ;                   2 = used for write ( differs from hd )
  21. ;
  22. ;      +65536 - cache entries
  23. ;
  24. ;**************************************************************************
  25.  
  26. align 4
  27. hd_read:
  28. ;-----------------------------------------------------------
  29. ; input  : eax = block to read
  30. ;          ebx = destination
  31. ;-----------------------------------------------------------
  32.         and     [hd_error], 0
  33.     push  ecx esi edi           ; scan cache
  34.  
  35.     mov   ecx,cache_max         ; entries in cache
  36.     mov   esi,HD_CACHE+8
  37.     mov   edi,1
  38.  
  39.   hdreadcache:
  40.  
  41.     cmp   dword [esi+4],0       ; empty
  42.     je    nohdcache
  43.  
  44.     cmp   [esi],eax             ; correct sector
  45.     je    yeshdcache
  46.  
  47.   nohdcache:
  48.  
  49.     add   esi,8
  50.     inc   edi
  51.     dec   ecx
  52.     jnz   hdreadcache
  53.  
  54.     call  find_empty_slot       ; ret in edi
  55.     cmp   [hd_error],0
  56.     jne   return_01
  57. ; DMA read is permitted if [allow_dma_access]=1 or 2
  58.         cmp     [allow_dma_access], 2
  59.         ja      .nodma
  60.         cmp     [dma_hdd], 1
  61.         jnz     .nodma
  62.         call    hd_read_dma
  63.         jmp     @f
  64. .nodma:
  65.         call    hd_read_pio
  66. @@:
  67.  
  68.     lea   esi,[edi*8+HD_CACHE]
  69.     mov   [esi],eax             ; sector number
  70.     mov   dword [esi+4],1       ; hd read - mark as same as in hd
  71.  
  72.   yeshdcache:
  73.  
  74.     mov   esi,edi
  75.     shl   esi,9
  76.     add   esi,HD_CACHE+65536
  77.     mov   edi,ebx
  78.     mov   ecx,512/4
  79.     cld
  80.     rep   movsd                 ; move data
  81.  return_01:
  82.     pop   edi esi ecx
  83.     ret
  84.  
  85. align 4
  86. hd_read_pio:
  87.     push  eax edx
  88.  
  89.     call  wait_for_hd_idle
  90.     cmp   [hd_error],0
  91.     jne   hd_read_error
  92.  
  93.     cli
  94.     xor   eax,eax
  95.     mov   edx,[hdbase]
  96.     inc   edx
  97.     out   dx,al   ; ATAFeatures регистр "особенностей"
  98.     inc   edx
  99.     inc   eax
  100.     out   dx,al   ; ATASectorCount счётчик секторов
  101.     inc   edx
  102.     mov   eax,[esp+4]
  103.     out   dx,al   ; ATASectorNumber регистр номера сектора
  104.     shr   eax,8
  105.     inc   edx
  106.     out   dx,al   ; ATACylinder номер цилиндра (младший байт)
  107.     shr   eax,8
  108.     inc   edx
  109.     out   dx,al   ; номер цилиндра (старший байт)
  110.     shr   eax,8
  111.     inc   edx
  112.     and   al,1+2+4+8
  113.     add   al,byte [hdid]
  114.     add   al,128+64+32
  115.     out   dx,al   ; номер головки/номер диска
  116.     inc   edx
  117.     mov   al,20h
  118.     out   dx,al   ; ATACommand регистр команд
  119.     sti
  120.  
  121.     call  wait_for_sector_buffer
  122.  
  123.     cmp   [hd_error],0
  124.     jne   hd_read_error
  125.  
  126.     cli
  127.     push  edi
  128.     shl   edi,9
  129.     add   edi,HD_CACHE+65536
  130.     mov   ecx,256
  131.     mov   edx,[hdbase]
  132.     cld
  133.     rep   insw
  134.     pop   edi
  135.     sti
  136.  
  137.     pop   edx eax
  138.     ret
  139.  
  140. disable_ide_int:
  141. ;        mov edx,[hdbase]
  142. ;        add edx,0x206
  143. ;        mov al,2
  144. ;        out dx,al
  145.         cli
  146.         ret
  147.  
  148. enable_ide_int:
  149. ;        mov edx,[hdbase]
  150. ;        add edx,0x206
  151. ;        mov al,0
  152. ;        out dx,al
  153.         sti
  154.         ret
  155.  
  156. align 4
  157. hd_write:
  158. ;-----------------------------------------------------------
  159. ; input  : eax = block
  160. ;          ebx = pointer to memory
  161. ;-----------------------------------------------------------
  162.     push  ecx esi edi
  163.  
  164.     ; check if the cache already has the sector and overwrite it
  165.  
  166.     mov   ecx,cache_max
  167.     mov   esi,HD_CACHE+8
  168.     mov   edi,1
  169.  
  170.   hdwritecache:
  171.  
  172.     cmp   dword [esi+4],0       ; if cache slot is empty
  173.     je    not_in_cache_write
  174.  
  175.     cmp   [esi],eax             ; if the slot has the sector
  176.     je    yes_in_cache_write
  177.  
  178.   not_in_cache_write:
  179.  
  180.     add   esi,8
  181.     inc   edi
  182.     dec   ecx
  183.     jnz   hdwritecache
  184.  
  185.     ; sector not found in cache
  186.     ; write the block to a new location
  187.  
  188.     call  find_empty_slot       ; ret in edi
  189.     cmp   [hd_error],0
  190.     jne   hd_write_access_denied
  191.  
  192.     lea   esi,[edi*8+HD_CACHE]
  193.     mov   [esi],eax             ; sector number
  194.  
  195.   yes_in_cache_write:
  196.  
  197.     mov   dword [esi+4],2       ; write - differs from hd
  198.  
  199.     shl   edi,9
  200.     add   edi,HD_CACHE+65536
  201.     mov   esi,ebx
  202.     mov   ecx,512/4
  203.     cld
  204.     rep   movsd                 ; move data
  205.  hd_write_access_denied:
  206.     pop   edi esi ecx
  207.     ret
  208.  
  209.  
  210. write_cache:
  211. ;-----------------------------------------------------------
  212. ; write all changed sectors to disk
  213. ;-----------------------------------------------------------
  214.     push  eax ecx edx esi edi
  215.  
  216.     ; write difference ( 2 ) from cache to hd
  217.  
  218.     mov   ecx,cache_max
  219.     mov   esi,HD_CACHE+8
  220.     mov   edi,1
  221.  
  222.   write_cache_more:
  223.  
  224.     cmp   dword [esi+4],2       ; if cache slot is not different
  225.     jne   .write_chain
  226.  
  227.     mov   dword [esi+4],1       ; same as in hd
  228.     mov   eax,[esi]             ; eax = sector to write
  229.  
  230.     cmp   eax,[PARTITION_START]
  231.     jb    danger
  232.     cmp   eax,[PARTITION_END]
  233.     ja    danger
  234.  
  235. ; DMA write is permitted only if [allow_dma_access]=1
  236.         cmp     [allow_dma_access], 2
  237.         jae     .nodma
  238.         cmp     [dma_hdd], 1
  239.         jnz     .nodma
  240. ; Объединяем запись цепочки последовательных секторов в одно обращение к диску
  241.         cmp     ecx, 1
  242.         jz      .nonext
  243.         cmp     dword [esi+8+4], 2
  244.         jnz     .nonext
  245.         push    eax
  246.         inc     eax
  247.         cmp     eax, [esi+8]
  248.         pop     eax
  249.         jnz     .nonext
  250.         cmp     [cache_chain_started], 1
  251.         jz      @f
  252.         mov     [cache_chain_started], 1
  253.         mov     [cache_chain_size], 0
  254.         mov     [cache_chain_pos], edi
  255.         mov     [cache_chain_ptr], esi
  256. @@:
  257.         inc     [cache_chain_size]
  258.         cmp     [cache_chain_size], 64
  259.         jnz     .continue
  260.         jmp     .write_chain
  261. .nonext:
  262.         call    flush_cache_chain
  263.         mov     [cache_chain_size], 1
  264.         mov     [cache_chain_ptr], esi
  265.         call    write_cache_sector
  266.         jmp     .continue
  267. .nodma:
  268.         call    cache_write_pio
  269. .write_chain:
  270.         call    flush_cache_chain
  271.  
  272. .continue:
  273.   danger:
  274.  
  275.     add   esi,8
  276.     inc   edi
  277.     dec   ecx
  278.     jnz   write_cache_more
  279.         call    flush_cache_chain
  280.  return_02:
  281.     pop   edi esi edx ecx eax
  282.     ret
  283.  
  284. flush_cache_chain:
  285.         cmp     [cache_chain_started], 0
  286.         jz      @f
  287.         call    write_cache_chain
  288.         mov     [cache_chain_started], 0
  289. @@:
  290.         ret
  291.  
  292. align 4
  293. cache_write_pio:
  294.     call  disable_ide_int
  295.  
  296.     call  wait_for_hd_idle
  297.     cmp   [hd_error],0
  298.     jne   hd_write_error
  299.  
  300. ;    cli
  301.     xor   eax,eax
  302.     mov   edx,[hdbase]
  303.     inc   edx
  304.     out   dx,al
  305.     inc   edx
  306.     inc   eax
  307.     out   dx,al
  308.     inc   edx
  309.     mov   eax,[esi]             ; eax = sector to write
  310.     out   dx,al
  311.     shr   eax,8
  312.     inc   edx
  313.     out   dx,al
  314.     shr   eax,8
  315.     inc   edx
  316.     out   dx,al
  317.     shr   eax,8
  318.     inc   edx
  319.     and   al,1+2+4+8
  320.     add   al,byte [hdid]
  321.     add   al,128+64+32
  322.     out   dx,al
  323.     inc   edx
  324.     mov   al,30h
  325.     out   dx,al
  326. ;    sti
  327.  
  328.     call  wait_for_sector_buffer
  329.  
  330.     cmp   [hd_error],0
  331.     jne   hd_write_error
  332.  
  333.     push  ecx esi
  334.  
  335. ;    cli
  336.     mov   esi,edi
  337.     shl   esi,9
  338.     add   esi,HD_CACHE+65536    ; esi = from memory position
  339.     mov   ecx,256
  340.     mov   edx,[hdbase]
  341.     cld
  342.     rep   outsw
  343. ;    sti
  344.  
  345.     call  enable_ide_int
  346.     pop   esi ecx
  347.  
  348.     ret
  349.  
  350. align 4
  351. find_empty_slot:
  352. ;-----------------------------------------------------------
  353. ; find empty or read slot, flush cache if next 10% is used by write
  354. ; output : edi = cache slot
  355. ;-----------------------------------------------------------
  356. ;    push  ecx esi
  357.  
  358.   search_again:
  359.  
  360.     mov   ecx,cache_max*10/100
  361.     mov   edi,[cache_search_start]
  362.  
  363.   search_for_empty:
  364.  
  365.     inc   edi
  366.     cmp   edi,cache_max
  367.     jbe   inside_cache
  368.     mov   edi,1
  369.  
  370.   inside_cache:
  371.  
  372.     cmp   dword [edi*8+HD_CACHE+4],2    ; get cache slot info
  373.     jb    found_slot                    ; it's empty or read
  374.     dec   ecx
  375.     jnz   search_for_empty
  376.  
  377.     call  write_cache                   ; no empty slots found, write all
  378.     cmp   [hd_error],0
  379.     jne   found_slot_access_denied
  380.  
  381.     jmp   search_again                  ; and start again
  382.  
  383.   found_slot:
  384.  
  385.     mov   [cache_search_start],edi
  386.   found_slot_access_denied:
  387.     ret
  388.  
  389. align 4
  390. clear_hd_cache:
  391.  
  392.     push  eax ecx edi
  393.     mov   edi, HD_CACHE
  394.     mov   ecx,16384
  395.     xor   eax,eax
  396.     cld
  397.     rep   stosd                 ; clear hd cache with 0
  398.     mov   [cache_search_start],eax
  399.     mov   [fat_in_cache],-1
  400.     mov   [fat_change],0
  401.     pop   edi ecx eax
  402.     ret
  403.  
  404. save_hd_wait_timeout:
  405.  
  406.     push  eax
  407.     mov   eax,[timer_ticks]
  408.     add   eax,300               ; 3 sec timeout
  409.     mov   [hd_wait_timeout],eax
  410.     pop   eax
  411.     ret
  412.  
  413. align 4
  414. check_hd_wait_timeout:
  415.  
  416.     push  eax
  417.     mov   eax,[hd_wait_timeout]
  418.     cmp   [timer_ticks], eax
  419.     jg    hd_timeout_error
  420.     pop   eax
  421.     mov   [hd_error],0
  422.     ret
  423.  
  424. ;iglobal
  425. ;  hd_timeout_str   db 'K : FS - HD timeout',0
  426. ;  hd_read_str      db 'K : FS - HD read error',0
  427. ;  hd_write_str     db 'K : FS - HD write error',0
  428. ;  hd_lba_str       db 'K : FS - HD LBA error',0
  429. ;endg
  430.  
  431. hd_timeout_error:
  432.  
  433. ;    call  clear_hd_cache
  434. ;    call  clear_application_table_status
  435. ;    mov   esi,hd_timeout_str
  436. ;    call  sys_msg_board_str
  437.     DEBUGF 1,"K : FS - HD timeout\n"
  438.  
  439.     mov   [hd_error],1
  440.     pop   eax
  441.     ret
  442.  
  443. hd_read_error:
  444.  
  445. ;    call  clear_hd_cache
  446. ;    call  clear_application_table_status
  447. ;    mov   esi,hd_read_str
  448. ;    call  sys_msg_board_str
  449.     DEBUGF 1,"K : FS - HD read error\n"
  450.     pop   edx eax
  451.     ret
  452.  
  453. hd_write_error:
  454.  
  455. ;    call  clear_hd_cache
  456. ;    call  clear_application_table_status
  457. ;     mov   esi,hd_write_str
  458. ;     call  sys_msg_board_str
  459.     DEBUGF 1,"K : FS - HD write error\n"
  460.      ret
  461.  
  462. hd_write_error_dma:
  463. ;        call    clear_hd_cache
  464. ;        call    clear_application_table_status
  465. ;        mov     esi, hd_write_str
  466. ;        call    sys_msg_board_str
  467.         DEBUGF 1,"K : FS - HD read error\n"
  468.         pop     esi
  469.         ret
  470.  
  471. hd_lba_error:
  472. ;    call  clear_hd_cache
  473. ;    call  clear_application_table_status
  474. ;    mov   esi,hd_lba_str
  475. ;    call  sys_msg_board_str
  476.      DEBUGF 1,"K : FS - HD LBA error\n"
  477.      jmp   LBA_read_ret
  478.  
  479.  
  480. align 4
  481. wait_for_hd_idle:
  482.  
  483.     push  eax edx
  484.  
  485.     call  save_hd_wait_timeout
  486.  
  487.     mov   edx,[hdbase]
  488.     add   edx,0x7
  489.  
  490.   wfhil1:
  491.  
  492.     call  check_hd_wait_timeout
  493.     cmp   [hd_error],0
  494.     jne   @f
  495.  
  496.     in    al,dx
  497.     test  al,128
  498.     jnz   wfhil1
  499.  
  500.  @@:
  501.  
  502.     pop   edx eax
  503.     ret
  504.  
  505.  
  506. align 4
  507. wait_for_sector_buffer:
  508.  
  509.     push  eax edx
  510.  
  511.     mov   edx,[hdbase]
  512.     add   edx,0x7
  513.  
  514.     call  save_hd_wait_timeout
  515.  
  516.   hdwait_sbuf:                  ; wait for sector buffer to be ready
  517.  
  518.     call  check_hd_wait_timeout
  519.     cmp   [hd_error],0
  520.     jne   @f
  521.  
  522.     in    al,dx
  523.     test  al,8
  524.     jz    hdwait_sbuf
  525.  
  526.     mov   [hd_error],0
  527.  
  528.     cmp   [hd_setup],1          ; do not mark error for setup request
  529.     je    buf_wait_ok
  530.  
  531.     test  al,1                  ; previous command ended up with an error
  532.     jz    buf_wait_ok
  533.  @@:
  534.     mov   [hd_error],1
  535.  
  536.   buf_wait_ok:
  537.  
  538.     pop   edx eax
  539.     ret
  540.  
  541. ; \begin{Mario79}
  542. align 4
  543. wait_for_sector_dma_ide0:
  544.         push    eax
  545.         push    edx
  546.         call    save_hd_wait_timeout
  547. .wait:
  548.         call    change_task
  549.         cmp     [irq14_func], hdd_irq14
  550.         jnz     .done
  551.         call    check_hd_wait_timeout
  552.         cmp     [hd_error], 0
  553.         jz      .wait
  554.         mov     [irq14_func], hdd_irq_null
  555.         mov     dx, [IDEContrRegsBaseAddr]
  556.         mov     al, 0
  557.         out     dx, al
  558. .done:
  559.         pop     edx
  560.         pop     eax
  561.         ret
  562.  
  563. align 4
  564. wait_for_sector_dma_ide1:
  565.         push    eax
  566.         push    edx
  567.         call    save_hd_wait_timeout
  568. .wait:
  569.         call    change_task
  570.         cmp     [irq15_func], hdd_irq15
  571.         jnz     .done
  572.         call    check_hd_wait_timeout
  573.         cmp     [hd_error], 0
  574.         jz      .wait
  575.         mov     [irq15_func], hdd_irq_null
  576.         mov     dx, [IDEContrRegsBaseAddr]
  577.         add     dx, 8
  578.         mov     al, 0
  579.         out     dx, al
  580. .done:
  581.         pop     edx
  582.         pop     eax
  583.         ret
  584.  
  585. iglobal
  586. align 4
  587. ; note that IDE descriptor table must be 4-byte aligned and do not cross 4K boundary
  588. IDE_descriptor_table:
  589.         dd      0x284000
  590.         dw      0x2000
  591.         dw      0x8000
  592.  
  593. dma_cur_sector  dd      not 40h
  594. irq14_func      dd      hdd_irq_null
  595. irq15_func      dd      hdd_irq_null
  596. endg
  597.  
  598. uglobal
  599. ; all uglobals are zeroed at boot
  600. dma_process     dd      0
  601. dma_slot_ptr    dd      0
  602. cache_chain_pos dd      0
  603. cache_chain_ptr dd      0
  604. cache_chain_size        db      0
  605. cache_chain_started     db      0
  606. dma_task_switched       db      0
  607. dma_hdd         db      0
  608. allow_dma_access db      0
  609. endg
  610.  
  611. align 4
  612. hdd_irq14:
  613.         pushfd
  614.         cli
  615.         pushad
  616.         mov     [irq14_func], hdd_irq_null
  617.         mov     dx, [IDEContrRegsBaseAddr]
  618.         mov     al, 0
  619.         out     dx, al
  620. ;        call    update_counters
  621. ;        mov     ebx, [dma_process]
  622. ;        cmp     [CURRENT_TASK], ebx
  623. ;        jz      .noswitch
  624. ;        mov     [dma_task_switched], 1
  625. ;        mov     edi, [dma_slot_ptr]
  626. ;        mov     eax, [CURRENT_TASK]
  627. ;        mov     [dma_process], eax
  628. ;        mov     eax, [TASK_BASE]
  629. ;        mov     [dma_slot_ptr], eax
  630. ;        mov     [CURRENT_TASK], ebx
  631. ;        mov     [TASK_BASE], edi
  632. ;        mov     byte [DONT_SWITCH], 1
  633. ;        call    do_change_task
  634. .noswitch:
  635.         popad
  636.         popfd
  637. align 4
  638. hdd_irq_null:
  639.         ret
  640.  
  641. align 4
  642. hdd_irq15:
  643.         pushfd
  644.         cli
  645.         pushad
  646.         mov     [irq15_func], hdd_irq_null
  647.         mov     dx, [IDEContrRegsBaseAddr]
  648.         add     dx, 8
  649.         mov     al, 0
  650.         out     dx, al
  651. ;        call    update_counters
  652. ;        mov     ebx, [dma_process]
  653. ;        cmp     [CURRENT_TASK], ebx
  654. ;        jz      .noswitch
  655. ;        mov     [dma_task_switched], 1
  656. ;        mov     edi, [dma_slot_ptr]
  657. ;        mov     eax, [CURRENT_TASK]
  658. ;        mov     [dma_process], eax
  659. ;        mov     eax, [TASK_BASE]
  660. ;        mov     [dma_slot_ptr], eax
  661. ;        mov     [CURRENT_TASK], ebx
  662. ;        mov     [TASK_BASE], edi
  663. ;        mov     byte [DONT_SWITCH], 1
  664. ;        call    do_change_task
  665. .noswitch:
  666.         popad
  667.         popfd
  668.         ret
  669.  
  670. align 4
  671. hd_read_dma:
  672.         push    eax
  673.         push    edx
  674.         mov     edx, [dma_cur_sector]
  675.         cmp     eax, edx
  676.         jb      .notread
  677.         add     edx, 15
  678.         cmp     [esp+4], edx
  679.         ja      .notread
  680.         mov     eax, [esp+4]
  681.         sub     eax, [dma_cur_sector]
  682.         shl     eax, 9
  683.         add     eax, OS_BASE+0x284000
  684.         push    ecx esi edi
  685.         mov     esi, eax
  686.         shl     edi, 9
  687.         add     edi, HD_CACHE+0x10000
  688.         mov     ecx, 512/4
  689.         cld
  690.         rep     movsd
  691.         pop     edi esi ecx
  692.         pop     edx
  693.         pop     eax
  694.         ret
  695. .notread:
  696.         mov     eax, IDE_descriptor_table
  697.         mov     dword [eax],  0x284000
  698.         mov     word [eax+4], 0x2000
  699.         sub     eax, OS_BASE
  700.         mov     dx, [IDEContrRegsBaseAddr]
  701.         cmp     [hdbase], 0x1F0
  702.         jz      @f
  703.         add     edx, 8
  704. @@:
  705.         push    edx
  706.         add     edx, 4
  707.         out     dx, eax
  708.         pop     edx
  709.         mov     al, 0
  710.         out     dx, al
  711.         add     edx, 2
  712.         mov     al, 6
  713.         out     dx, al
  714.         call    wait_for_hd_idle
  715.         cmp     [hd_error], 0
  716.         jnz     hd_read_error
  717.         call    disable_ide_int
  718.         xor     eax, eax
  719.         mov     edx, [hdbase]
  720.         inc     edx
  721.         out     dx, al
  722.         inc     edx
  723.         mov     eax, 10h
  724.         out     dx, al
  725.         inc     edx
  726.         mov     eax, [esp+4]
  727.         out     dx, al
  728.         shr     eax, 8
  729.         inc     edx
  730.         out     dx, al
  731.         shr     eax, 8
  732.         inc     edx
  733.         out     dx, al
  734.         shr     eax, 8
  735.         inc     edx
  736.         and     al, 0xF
  737.         add     al, byte [hdid]
  738.         add     al, 11100000b
  739.         out     dx, al
  740.         inc     edx
  741.         mov     al, 0xC8
  742.         out     dx, al
  743.         mov     dx, [IDEContrRegsBaseAddr]
  744.         cmp     [hdbase], 0x1F0
  745.         jz      @f
  746.         add     dx, 8
  747. @@:
  748.         mov     al, 9
  749.         out     dx, al
  750.         mov     eax, [CURRENT_TASK]
  751.         mov     [dma_process], eax
  752.         mov     eax, [TASK_BASE]
  753.         mov     [dma_slot_ptr], eax
  754.         cmp     [hdbase], 0x1F0
  755.         jnz     .ide1
  756.         mov     [irq14_func], hdd_irq14
  757.         jmp     @f
  758. .ide1:
  759.         mov     [irq15_func], hdd_irq15
  760. @@:
  761.         call    enable_ide_int
  762.         cmp     [hdbase], 0x1F0
  763.         jnz     .wait_ide1
  764.         call    wait_for_sector_dma_ide0
  765.         jmp     @f
  766. .wait_ide1:
  767.         call    wait_for_sector_dma_ide1
  768. @@:
  769.         cmp     [hd_error], 0
  770.         jnz     hd_read_error
  771.         pop     edx
  772.         pop     eax
  773.         mov     [dma_cur_sector], eax
  774.         jmp     hd_read_dma
  775.  
  776. align 4
  777. write_cache_chain:
  778.         push    esi
  779.         mov     eax, IDE_descriptor_table
  780.         mov     edx, [cache_chain_pos]
  781.         shl     edx, 9
  782.         add     edx, DMA_HD_MEM+0x10000
  783.         mov     [eax], edx
  784.         movzx   edx, [cache_chain_size]
  785.         shl     edx, 9
  786.         mov     [eax+4], dx
  787.         jmp     do_write_dma
  788. write_cache_sector:
  789.         push    esi
  790.         mov     eax, IDE_descriptor_table
  791.         mov     edx, edi
  792.         shl     edx, 9
  793.         add     edx, DMA_HD_MEM+0x10000
  794.         mov     [eax], edx
  795.         mov     word [eax+4], 0x200
  796. do_write_dma:
  797.         sub     eax, OS_BASE
  798.         mov     dx, [IDEContrRegsBaseAddr]
  799.         cmp     [hdbase], 0x1F0
  800.         jz      @f
  801.         add     edx, 8
  802. @@:
  803.         push    edx
  804.         add     edx, 4
  805.         out     dx, eax
  806.         pop     edx
  807.         mov     al, 0
  808.         out     dx, al
  809.         add     edx, 2
  810.         mov     al, 6
  811.         out     dx, al
  812.         call    wait_for_hd_idle
  813.         cmp     [hd_error], 0
  814.         jnz     hd_write_error_dma
  815.         call    disable_ide_int
  816.         xor     eax, eax
  817.         mov     edx, [hdbase]
  818.         inc     edx
  819.         out     dx, al
  820.         inc     edx
  821.         mov     al, [cache_chain_size]
  822.         out     dx, al
  823.         inc     edx
  824.         mov     esi, [cache_chain_ptr]
  825.         mov     eax, [esi]
  826.         out     dx, al
  827.         shr     eax, 8
  828.         inc     edx
  829.         out     dx, al
  830.         shr     eax, 8
  831.         inc     edx
  832.         out     dx, al
  833.         shr     eax, 8
  834.         inc     edx
  835.         and     al, 0xF
  836.         add     al, byte [hdid]
  837.         add     al, 11100000b
  838.         out     dx, al
  839.         inc     edx
  840.         mov     al, 0xCA
  841.         out     dx, al
  842.         mov     dx, [IDEContrRegsBaseAddr]
  843.         cmp     [hdbase], 0x1F0
  844.         jz      @f
  845.         add     dx, 8
  846. @@:
  847.         mov     al, 1
  848.         out     dx, al
  849.         mov     eax, [CURRENT_TASK]
  850.         mov     [dma_process], eax
  851.         mov     eax, [TASK_BASE]
  852.         mov     [dma_slot_ptr], eax
  853.         cmp     [hdbase], 0x1F0
  854.         jnz     .ide1
  855.         mov     [irq14_func], hdd_irq14
  856.         jmp     @f
  857. .ide1:
  858.         mov     [irq15_func], hdd_irq15
  859. @@:
  860.         call    enable_ide_int
  861.         mov     [dma_cur_sector], not 0x40
  862.         cmp     [hdbase], 0x1F0
  863.         jnz     .wait_ide1
  864.         call    wait_for_sector_dma_ide0
  865.         jmp     @f
  866. .wait_ide1:
  867.         call    wait_for_sector_dma_ide1
  868. @@:
  869.         cmp     [hd_error], 0
  870.         jnz     hd_write_error_dma
  871.         pop     esi
  872.         ret
  873.  
  874. uglobal
  875. IDEContrRegsBaseAddr    dw      ?
  876. endg
  877. ; \end{Mario79}
  878.