Subversion Repositories Kolibri OS

Rev

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

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