Subversion Repositories Kolibri OS

Rev

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

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