Subversion Repositories Kolibri OS

Rev

Rev 321 | Rev 358 | 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',13,10,0
  414.   hd_read_str      db 'K : FS - HD read error',13,10,0
  415.   hd_write_str     db 'K : FS - HD write error',13,10,0
  416.   hd_lba_str       db 'K : FS - HD LBA error',13,10,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. ;    jmp   $
  426.     mov   [hd_error],1
  427.     pop   eax
  428.     ret
  429.  
  430. hd_read_error:
  431.  
  432. ;    call  clear_hd_cache
  433. ;    call  clear_application_table_status
  434.     mov   esi,hd_read_str
  435.     call  sys_msg_board_str
  436.     pop   edx eax
  437.     ret
  438.  
  439. hd_write_error:
  440.  
  441. ;    call  clear_hd_cache
  442. ;    call  clear_application_table_status
  443.     mov   esi,hd_write_str
  444.     call  sys_msg_board_str
  445.     ret
  446.  
  447. hd_write_error_dma:
  448. ;        call    clear_hd_cache
  449. ;        call    clear_application_table_status
  450.         mov     esi, hd_write_str
  451.         call    sys_msg_board_str
  452.         pop     esi
  453.         ret
  454.  
  455. hd_lba_error:
  456. ;    call  clear_hd_cache
  457. ;    call  clear_application_table_status
  458.     mov   esi,hd_lba_str
  459.     call  sys_msg_board_str
  460.     jmp   LBA_read_ret
  461.  
  462.  
  463. align 4
  464. wait_for_hd_idle:
  465.  
  466.     push  eax edx
  467.  
  468.     call  save_hd_wait_timeout
  469.  
  470.     mov   edx,[hdbase]
  471.     add   edx,0x7
  472.  
  473.   wfhil1:
  474.  
  475.     call  check_hd_wait_timeout
  476.     cmp   [hd_error],0
  477.     jne   @f
  478.  
  479.     in    al,dx
  480.     test  al,128
  481.     jnz   wfhil1
  482.  
  483.  @@:
  484.  
  485.     pop   edx eax
  486.     ret
  487.  
  488.  
  489. align 4
  490. wait_for_sector_buffer:
  491.  
  492.     push  eax edx
  493.  
  494.     mov   edx,[hdbase]
  495.     add   edx,0x7
  496.  
  497.     call  save_hd_wait_timeout
  498.  
  499.   hdwait_sbuf:                  ; wait for sector buffer to be ready
  500.  
  501.     call  check_hd_wait_timeout
  502.     cmp   [hd_error],0
  503.     jne   @f
  504.  
  505.     in    al,dx
  506.     test  al,8
  507.     jz    hdwait_sbuf
  508.  
  509.     mov   [hd_error],0
  510.  
  511.     cmp   [hd_setup],1          ; do not mark error for setup request
  512.     je    buf_wait_ok
  513.  
  514.     test  al,1                  ; previous command ended up with an error
  515.     jz    buf_wait_ok
  516.  @@:
  517.     mov   [hd_error],1
  518.  
  519.   buf_wait_ok:
  520.  
  521.     pop   edx eax
  522.     ret
  523.  
  524. ; \begin{Mario79}
  525. align 4
  526. wait_for_sector_dma_ide0:
  527.         push    eax
  528.         push    edx
  529.         call    save_hd_wait_timeout
  530. .wait:
  531.         call    change_task
  532.         cmp     [irq14_func], hdd_irq14
  533.         jnz     .done
  534.         call    check_hd_wait_timeout
  535.         cmp     [hd_error], 0
  536.         jz      .wait
  537.         mov     [irq14_func], hdd_irq_null
  538.         mov     dx, [IDEContrRegsBaseAddr]
  539.         mov     al, 0
  540.         out     dx, al
  541. .done:
  542.         pop     edx
  543.         pop     eax
  544.         ret
  545.  
  546. align 4
  547. wait_for_sector_dma_ide1:
  548.         push    eax
  549.         push    edx
  550.         call    save_hd_wait_timeout
  551. .wait:
  552.         call    change_task
  553.         cmp     [irq15_func], hdd_irq15
  554.         jnz     .done
  555.         call    check_hd_wait_timeout
  556.         cmp     [hd_error], 0
  557.         jz      .wait
  558.         mov     [irq15_func], hdd_irq_null
  559.         mov     dx, [IDEContrRegsBaseAddr]
  560.         add     dx, 8
  561.         mov     al, 0
  562.         out     dx, al
  563. .done:
  564.         pop     edx
  565.         pop     eax
  566.         ret
  567.  
  568. iglobal
  569. align 4
  570. ; note that IDE descriptor table must be 4-byte aligned and do not cross 4K boundary
  571. IDE_descriptor_table:
  572.         dd      284000h
  573.         dw      2000h
  574.         dw      8000h
  575.  
  576. dma_cur_sector  dd      not 40h
  577. irq14_func      dd      hdd_irq_null
  578. irq15_func      dd      hdd_irq_null
  579. endg
  580.  
  581. uglobal
  582. ; all uglobals are zeroed at boot
  583. dma_process     dd      0
  584. dma_slot_ptr    dd      0
  585. cache_chain_pos dd      0
  586. cache_chain_ptr dd      0
  587. cache_chain_size        db      0
  588. cache_chain_started     db      0
  589. dma_task_switched       db      0
  590. dma_hdd         db      0
  591. allow_dma_write db      0
  592. endg
  593.  
  594. align 4
  595. hdd_irq14:
  596.         pushfd
  597.         cli
  598.         pushad
  599.         mov     [irq14_func], hdd_irq_null
  600.         mov     dx, [IDEContrRegsBaseAddr]
  601.         mov     al, 0
  602.         out     dx, al
  603.         call    update_counters
  604.         mov     ebx, [dma_process]
  605.         cmp     [0x3000], ebx
  606.         jz      .noswitch
  607.         mov     [dma_task_switched], 1
  608.         mov     edi, [dma_slot_ptr]
  609.         mov     eax, [0x3000]
  610.         mov     [dma_process], eax
  611.         mov     eax, [0x3010]
  612.         mov     [dma_slot_ptr], eax
  613.         mov     [0x3000], ebx
  614.         mov     [0x3010], edi
  615.         mov     byte [0xFFFF], 1
  616.         call    do_change_task
  617. .noswitch:
  618.         popad
  619.         popfd
  620. align 4
  621. hdd_irq_null:
  622.         ret
  623.  
  624. align 4
  625. hdd_irq15:
  626.         pushfd
  627.         cli
  628.         pushad
  629.         mov     [irq15_func], hdd_irq_null
  630.         mov     dx, [IDEContrRegsBaseAddr]
  631.         add     dx, 8
  632.         mov     al, 0
  633.         out     dx, al
  634.         call    update_counters
  635.         mov     ebx, [dma_process]
  636.         cmp     [0x3000], ebx
  637.         jz      .noswitch
  638.         mov     [dma_task_switched], 1
  639.         mov     edi, [dma_slot_ptr]
  640.         mov     eax, [0x3000]
  641.         mov     [dma_process], eax
  642.         mov     eax, [0x3010]
  643.         mov     [dma_slot_ptr], eax
  644.         mov     [0x3000], ebx
  645.         mov     [0x3010], edi
  646.         mov     byte [0xFFFF], 1
  647.         call    do_change_task
  648. .noswitch:
  649.         popad
  650.         popfd
  651.         ret
  652.  
  653. align 4
  654. hd_read_dma:
  655.         push    eax
  656.         push    edx
  657.         mov     edx, [dma_cur_sector]
  658.         cmp     eax, edx
  659.         jb      .notread
  660.         add     edx, 15
  661.         cmp     [esp+4], edx
  662.         ja      .notread
  663.         mov     eax, [esp+4]
  664.         sub     eax, [dma_cur_sector]
  665.         shl     eax, 9
  666.         add     eax, 0x284000
  667.         push    ecx esi edi
  668.         mov     esi, eax
  669.         shl     edi, 9
  670.         add     edi, 0x610000
  671.         mov     ecx, 512/4
  672.         cld
  673.         rep     movsd
  674.         pop     edi esi ecx
  675.         pop     edx
  676.         pop     eax
  677.         ret
  678. .notread:
  679.         mov     eax, IDE_descriptor_table
  680.         mov     dword [eax], 0x284000
  681.         mov     word [eax+4], 0x2000
  682.         mov     dx, [IDEContrRegsBaseAddr]
  683.         cmp     [hdbase], 0x1F0
  684.         jz      @f
  685.         add     edx, 8
  686. @@:
  687.         push    edx
  688.         add     edx, 4
  689.         out     dx, eax
  690.         pop     edx
  691.         mov     al, 0
  692.         out     dx, al
  693.         add     edx, 2
  694.         mov     al, 6
  695.         out     dx, al
  696.         call    wait_for_hd_idle
  697.         cmp     [hd_error], 0
  698.         jnz     hd_read_error
  699.         call    disable_ide_int
  700.         xor     eax, eax
  701.         mov     edx, [hdbase]
  702.         inc     edx
  703.         out     dx, al
  704.         inc     edx
  705.         mov     eax, 10h
  706.         out     dx, al
  707.         inc     edx
  708.         mov     eax, [esp+4]
  709.         out     dx, al
  710.         shr     eax, 8
  711.         inc     edx
  712.         out     dx, al
  713.         shr     eax, 8
  714.         inc     edx
  715.         out     dx, al
  716.         shr     eax, 8
  717.         inc     edx
  718.         and     al, 0xF
  719.         add     al, byte [hdid]
  720.         add     al, 11100000b
  721.         out     dx, al
  722.         inc     edx
  723.         mov     al, 0xC8
  724.         out     dx, al
  725.         mov     dx, [IDEContrRegsBaseAddr]
  726.         cmp     [hdbase], 0x1F0
  727.         jz      @f
  728.         add     dx, 8
  729. @@:
  730.         mov     al, 9
  731.         out     dx, al
  732.         mov     eax, [0x3000]
  733.         mov     [dma_process], eax
  734.         mov     eax, [0x3010]
  735.         mov     [dma_slot_ptr], eax
  736.         cmp     [hdbase], 0x1F0
  737.         jnz     .ide1
  738.         mov     [irq14_func], hdd_irq14
  739.         jmp     @f
  740. .ide1:
  741.         mov     [irq15_func], hdd_irq15
  742. @@:
  743.         call    enable_ide_int
  744.         cmp     [hdbase], 0x1F0
  745.         jnz     .wait_ide1
  746.         call    wait_for_sector_dma_ide0
  747.         jmp     @f
  748. .wait_ide1:
  749.         call    wait_for_sector_dma_ide1
  750. @@:
  751.         cmp     [hd_error], 0
  752.         jnz     hd_read_error
  753.         pop     edx
  754.         pop     eax
  755.         mov     [dma_cur_sector], eax
  756.         jmp     hd_read_dma
  757.  
  758. align 4
  759. write_cache_chain:
  760.         push    esi
  761.         mov     eax, IDE_descriptor_table
  762.         mov     edx, [cache_chain_pos]
  763.         shl     edx, 9
  764.         add     edx, 0x610000
  765.         mov     [eax], edx
  766.         movzx   edx, [cache_chain_size]
  767.         shl     edx, 9
  768.         mov     [eax+4], dx
  769.         jmp     do_write_dma
  770. write_cache_sector:
  771.         push    esi
  772.         mov     eax, IDE_descriptor_table
  773.         mov     edx, edi
  774.         shl     edx, 9
  775.         add     edx, 0x610000
  776.         mov     [eax], edx
  777.         mov     word [eax+4], 0x200
  778. do_write_dma:
  779.         mov     dx, [IDEContrRegsBaseAddr]
  780.         cmp     [hdbase], 0x1F0
  781.         jz      @f
  782.         add     edx, 8
  783. @@:
  784.         push    edx
  785.         add     edx, 4
  786.         out     dx, eax
  787.         pop     edx
  788.         mov     al, 0
  789.         out     dx, al
  790.         add     edx, 2
  791.         mov     al, 6
  792.         out     dx, al
  793.         call    wait_for_hd_idle
  794.         cmp     [hd_error], 0
  795.         jnz     hd_write_error_dma
  796.         call    disable_ide_int
  797.         xor     eax, eax
  798.         mov     edx, [hdbase]
  799.         inc     edx
  800.         out     dx, al
  801.         inc     edx
  802.         mov     al, [cache_chain_size]
  803.         out     dx, al
  804.         inc     edx
  805.         mov     esi, [cache_chain_ptr]
  806.         mov     eax, [esi]
  807.         out     dx, al
  808.         shr     eax, 8
  809.         inc     edx
  810.         out     dx, al
  811.         shr     eax, 8
  812.         inc     edx
  813.         out     dx, al
  814.         shr     eax, 8
  815.         inc     edx
  816.         and     al, 0xF
  817.         add     al, byte [hdid]
  818.         add     al, 11100000b
  819.         out     dx, al
  820.         inc     edx
  821.         mov     al, 0xCA
  822.         out     dx, al
  823.         mov     dx, [IDEContrRegsBaseAddr]
  824.         cmp     [hdbase], 0x1F0
  825.         jz      @f
  826.         add     dx, 8
  827. @@:
  828.         mov     al, 1
  829.         out     dx, al
  830.         mov     eax, [0x3000]
  831.         mov     [dma_process], eax
  832.         mov     eax, [0x3010]
  833.         mov     [dma_slot_ptr], eax
  834.         cmp     [hdbase], 0x1F0
  835.         jnz     .ide1
  836.         mov     [irq14_func], hdd_irq14
  837.         jmp     @f
  838. .ide1:
  839.         mov     [irq15_func], hdd_irq15
  840. @@:
  841.         call    enable_ide_int
  842.         mov     [dma_cur_sector], not 0x40
  843.         cmp     [hdbase], 0x1F0
  844.         jnz     .wait_ide1
  845.         call    wait_for_sector_dma_ide0
  846.         jmp     @f
  847. .wait_ide1:
  848.         call    wait_for_sector_dma_ide1
  849. @@:
  850.         cmp     [hd_error], 0
  851.         jnz     hd_write_error_dma
  852.         pop     esi
  853.         ret
  854.  
  855. uglobal
  856. IDEContrRegsBaseAddr    dw      ?
  857. endg
  858. ; \end{Mario79}
  859.