Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 2643 $
  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      sizeof.v86_regs
  895. int13_regs_out  rb      sizeof.v86_regs
  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, sizeof.v86_regs/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.  
  949. reserve_hd1:
  950.  
  951.         cli
  952.         cmp     [hd1_status], 0
  953.         je      reserve_ok1
  954.  
  955.         sti
  956.         call    change_task
  957.         jmp     reserve_hd1
  958.  
  959.   reserve_ok1:
  960.  
  961.         push    eax
  962.         mov     eax, [CURRENT_TASK]
  963.         shl     eax, 5
  964.         mov     eax, [eax+CURRENT_TASK+TASKDATA.pid]
  965.         mov     [hd1_status], eax
  966.         pop     eax
  967.         sti
  968.         ret
  969. ;********************************************
  970.  
  971. uglobal
  972. hd_in_cache db ?
  973. endg
  974.  
  975. reserve_hd_channel:
  976. ; BIOS disk accesses are protected with common mutex hd1_status
  977. ; This must be modified when hd1_status will not be valid!
  978.         cmp     [hdpos], 0x80
  979.         jae     .ret
  980.         cmp     [hdbase], 0x1F0
  981.         jne     .IDE_Channel_2
  982. .IDE_Channel_1:
  983.         cli
  984.         cmp     [IDE_Channel_1], 0
  985.         je      .reserve_ok_1
  986.         sti
  987.         call    change_task
  988.         jmp     .IDE_Channel_1
  989. .IDE_Channel_2:
  990.         cli
  991.         cmp     [IDE_Channel_2], 0
  992.         je      .reserve_ok_2
  993.         sti
  994.         call    change_task
  995.         jmp     .IDE_Channel_2
  996. .reserve_ok_1:
  997.         mov     [IDE_Channel_1], 1
  998.         push    eax
  999.         mov     al, 1
  1000.         jmp     @f
  1001. .reserve_ok_2:
  1002.         mov     [IDE_Channel_2], 1
  1003.         push    eax
  1004.         mov     al, 3
  1005. @@:
  1006.         cmp     [hdid], 1
  1007.         sbb     al, -1
  1008.         mov     [hd_in_cache], al
  1009.         pop     eax
  1010.         sti
  1011. .ret:
  1012.         ret
  1013.  
  1014. free_hd_channel:
  1015. ; see comment at reserve_hd_channel
  1016.         cmp     [hdpos], 0x80
  1017.         jae     .ret
  1018.         cmp     [hdbase], 0x1F0
  1019.         jne     .IDE_Channel_2
  1020. .IDE_Channel_1:
  1021.         mov     [IDE_Channel_1], 0
  1022. .ret:
  1023.         ret
  1024. .IDE_Channel_2:
  1025.         mov     [IDE_Channel_2], 0
  1026.         ret
  1027. ;********************************************
  1028.