Subversion Repositories Kolibri OS

Rev

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