Subversion Repositories Kolibri OS

Rev

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