Subversion Repositories Kolibri OS

Rev

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

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