Subversion Repositories Kolibri OS

Rev

Rev 2643 | Rev 3539 | 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: 3309 $
  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.     if lang eq sp
  344.     DEBUGF 1,"K : FS - HD tiempo de espera agotado\n"
  345.     else
  346.     DEBUGF 1,"K : FS - HD timeout\n"
  347.     end if
  348.  
  349.         mov     [hd_error], 1
  350.         pop     eax
  351.         ret
  352.  
  353. hd_read_error:
  354.  
  355. ;    call  clear_hd_cache
  356. ;    call  clear_application_table_status
  357. ;    mov   esi,hd_read_str
  358. ;    call  sys_msg_board_str
  359.     if lang eq sp
  360.     DEBUGF 1,"K : FS - HD error de lectura\n"
  361.     else
  362.     DEBUGF 1,"K : FS - HD read error\n"
  363.     end if
  364.         pop     edx eax
  365.         ret
  366.  
  367. hd_write_error:
  368.  
  369. ;    call  clear_hd_cache
  370. ;    call  clear_application_table_status
  371. ;     mov   esi,hd_write_str
  372. ;     call  sys_msg_board_str
  373.     if lang eq sp
  374.     DEBUGF 1,"K : FS - HD error de escritura\n"
  375.     else
  376.     DEBUGF 1,"K : FS - HD write error\n"
  377.     end if
  378.         ret
  379.  
  380. hd_write_error_dma:
  381. ;        call    clear_hd_cache
  382. ;        call    clear_application_table_status
  383. ;        mov     esi, hd_write_str
  384. ;        call    sys_msg_board_str
  385.         if lang eq sp
  386.         DEBUGF 1,"K : FS - HD error de escritura\n"
  387.         else
  388.         DEBUGF 1,"K : FS - HD write error\n"
  389.         end if
  390.         pop     esi
  391.         ret
  392.  
  393. hd_lba_error:
  394. ;    call  clear_hd_cache
  395. ;    call  clear_application_table_status
  396. ;    mov   esi,hd_lba_str
  397. ;    call  sys_msg_board_str
  398.      if lang eq sp
  399.      DEBUGF 1,"K : FS - HD error en LBA\n"
  400.      else
  401.      DEBUGF 1,"K : FS - HD LBA error\n"
  402.      end if
  403.         jmp     LBA_read_ret
  404.  
  405.  
  406. align 4
  407. wait_for_hd_idle:
  408.  
  409.         push    eax edx
  410.  
  411.         call    save_hd_wait_timeout
  412.  
  413.         mov     edx, [hdbase]
  414.         add     edx, 0x7
  415.  
  416.   wfhil1:
  417.  
  418.         call    check_hd_wait_timeout
  419.         cmp     [hd_error], 0
  420.         jne     @f
  421.  
  422.         in      al, dx
  423.         test    al, 128
  424.         jnz     wfhil1
  425.  
  426.  @@:
  427.  
  428.         pop     edx eax
  429.         ret
  430.  
  431.  
  432. align 4
  433. wait_for_sector_buffer:
  434.  
  435.         push    eax edx
  436.  
  437.         mov     edx, [hdbase]
  438.         add     edx, 0x7
  439.  
  440.         call    save_hd_wait_timeout
  441.  
  442.   hdwait_sbuf:                  ; wait for sector buffer to be ready
  443.  
  444.         call    check_hd_wait_timeout
  445.         cmp     [hd_error], 0
  446.         jne     @f
  447.  
  448.         in      al, dx
  449.         test    al, 8
  450.         jz      hdwait_sbuf
  451.  
  452.         mov     [hd_error], 0
  453.  
  454.         cmp     [hd_setup], 1   ; do not mark error for setup request
  455.         je      buf_wait_ok
  456.  
  457.         test    al, 1           ; previous command ended up with an error
  458.         jz      buf_wait_ok
  459.  @@:
  460.         mov     [hd_error], 1
  461.  
  462.   buf_wait_ok:
  463.  
  464.         pop     edx eax
  465.         ret
  466.  
  467. ; \begin{Mario79}
  468. align 4
  469. wait_for_sector_dma_ide0:
  470.         push    eax
  471.         push    edx
  472.         call    save_hd_wait_timeout
  473. .wait:
  474.         call    change_task
  475.         cmp     [irq14_func], hdd_irq14
  476.         jnz     .done
  477.         call    check_hd_wait_timeout
  478.         cmp     [hd_error], 0
  479.         jz      .wait
  480.         mov     [irq14_func], hdd_irq_null
  481.         mov     dx, [IDEContrRegsBaseAddr]
  482.         mov     al, 0
  483.         out     dx, al
  484. .done:
  485.         pop     edx
  486.         pop     eax
  487.         ret
  488.  
  489. align 4
  490. wait_for_sector_dma_ide1:
  491.         push    eax
  492.         push    edx
  493.         call    save_hd_wait_timeout
  494. .wait:
  495.         call    change_task
  496.         cmp     [irq15_func], hdd_irq15
  497.         jnz     .done
  498.         call    check_hd_wait_timeout
  499.         cmp     [hd_error], 0
  500.         jz      .wait
  501.         mov     [irq15_func], hdd_irq_null
  502.         mov     dx, [IDEContrRegsBaseAddr]
  503.         add     dx, 8
  504.         mov     al, 0
  505.         out     dx, al
  506. .done:
  507.         pop     edx
  508.         pop     eax
  509.         ret
  510.  
  511. iglobal
  512. align 4
  513. ; note that IDE descriptor table must be 4-byte aligned and do not cross 4K boundary
  514. IDE_descriptor_table:
  515.         dd      IDE_DMA
  516.         dw      0x2000
  517.         dw      0x8000
  518.  
  519. dma_cur_sector  dd      not 40h
  520. dma_hdpos       dd      0
  521. irq14_func      dd      hdd_irq_null
  522. irq15_func      dd      hdd_irq_null
  523. endg
  524.  
  525. uglobal
  526. ; all uglobals are zeroed at boot
  527. dma_process     dd      0
  528. dma_slot_ptr    dd      0
  529. cache_chain_pos dd      0
  530. cache_chain_ptr dd      0
  531. cache_chain_size        db      0
  532. cache_chain_started     db      0
  533. dma_task_switched       db      0
  534. dma_hdd         db      0
  535. allow_dma_access db      0
  536. endg
  537.  
  538. align 4
  539. hdd_irq14:
  540.         pushfd
  541.         cli
  542.         pushad
  543.         mov     [irq14_func], hdd_irq_null
  544.         mov     dx, [IDEContrRegsBaseAddr]
  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     byte [DONT_SWITCH], 1
  560. ;        call    do_change_task
  561. .noswitch:
  562.         popad
  563.         popfd
  564. align 4
  565. hdd_irq_null:
  566.         ret
  567.  
  568. align 4
  569. hdd_irq15:
  570.         pushfd
  571.         cli
  572.         pushad
  573.         mov     [irq15_func], hdd_irq_null
  574.         mov     dx, [IDEContrRegsBaseAddr]
  575.         add     dx, 8
  576.         mov     al, 0
  577.         out     dx, al
  578. ;        call    update_counters
  579. ;        mov     ebx, [dma_process]
  580. ;        cmp     [CURRENT_TASK], ebx
  581. ;        jz      .noswitch
  582. ;        mov     [dma_task_switched], 1
  583. ;        mov     edi, [dma_slot_ptr]
  584. ;        mov     eax, [CURRENT_TASK]
  585. ;        mov     [dma_process], eax
  586. ;        mov     eax, [TASK_BASE]
  587. ;        mov     [dma_slot_ptr], eax
  588. ;        mov     [CURRENT_TASK], ebx
  589. ;        mov     [TASK_BASE], edi
  590. ;        mov     byte [DONT_SWITCH], 1
  591. ;        call    do_change_task
  592. .noswitch:
  593.         popad
  594.         popfd
  595.         ret
  596.  
  597. align 4
  598. hd_read_dma:
  599.         push    eax
  600.         push    edx
  601.         mov     edx, [dma_hdpos]
  602.         cmp     edx, [hdpos]
  603.         jne     .notread
  604.         mov     edx, [dma_cur_sector]
  605.         cmp     eax, edx
  606.         jb      .notread
  607.         add     edx, 15
  608.         cmp     [esp+4], edx
  609.         ja      .notread
  610.         mov     eax, [esp+4]
  611.         sub     eax, [dma_cur_sector]
  612.         shl     eax, 9
  613.         add     eax, (OS_BASE+IDE_DMA)
  614.         push    ecx esi edi
  615.         mov     esi, eax
  616.         shl     edi, 9
  617. ;        add     edi, HD_CACHE+0x10000
  618.         push    eax
  619.         call    calculate_cache_2
  620.         add     edi, eax
  621.         pop     eax
  622.  
  623.         mov     ecx, 512/4
  624.         cld
  625.         rep movsd
  626.         pop     edi esi ecx
  627.         pop     edx
  628.         pop     eax
  629.         ret
  630. .notread:
  631.         mov     eax, IDE_descriptor_table
  632.         mov     dword [eax], IDE_DMA
  633.         mov     word [eax+4], 0x2000
  634.         sub     eax, OS_BASE
  635.         mov     dx, [IDEContrRegsBaseAddr]
  636.         cmp     [hdbase], 0x1F0
  637.         jz      @f
  638.         add     edx, 8
  639. @@:
  640.         push    edx
  641.         add     edx, 4
  642.         out     dx, eax
  643.         pop     edx
  644.         mov     al, 0
  645.         out     dx, al
  646.         add     edx, 2
  647.         mov     al, 6
  648.         out     dx, al
  649.         call    wait_for_hd_idle
  650.         cmp     [hd_error], 0
  651.         jnz     hd_read_error
  652.         call    disable_ide_int
  653.         xor     eax, eax
  654.         mov     edx, [hdbase]
  655.         inc     edx
  656.         out     dx, al
  657.         inc     edx
  658.         mov     eax, 10h
  659.         out     dx, al
  660.         inc     edx
  661.         mov     eax, [esp+4]
  662.         out     dx, al
  663.         shr     eax, 8
  664.         inc     edx
  665.         out     dx, al
  666.         shr     eax, 8
  667.         inc     edx
  668.         out     dx, al
  669.         shr     eax, 8
  670.         inc     edx
  671.         and     al, 0xF
  672.         add     al, byte [hdid]
  673.         add     al, 11100000b
  674.         out     dx, al
  675.         inc     edx
  676.         mov     al, 0xC8
  677.         out     dx, al
  678.         mov     dx, [IDEContrRegsBaseAddr]
  679.         cmp     [hdbase], 0x1F0
  680.         jz      @f
  681.         add     dx, 8
  682. @@:
  683.         mov     al, 9
  684.         out     dx, al
  685.         mov     eax, [CURRENT_TASK]
  686.         mov     [dma_process], eax
  687.         mov     eax, [TASK_BASE]
  688.         mov     [dma_slot_ptr], eax
  689.         cmp     [hdbase], 0x1F0
  690.         jnz     .ide1
  691.         mov     [irq14_func], hdd_irq14
  692.         jmp     @f
  693. .ide1:
  694.         mov     [irq15_func], hdd_irq15
  695. @@:
  696.         call    enable_ide_int
  697.         cmp     [hdbase], 0x1F0
  698.         jnz     .wait_ide1
  699.         call    wait_for_sector_dma_ide0
  700.         jmp     @f
  701. .wait_ide1:
  702.         call    wait_for_sector_dma_ide1
  703. @@:
  704.         cmp     [hd_error], 0
  705.         jnz     hd_read_error
  706.         mov     eax, [hdpos]
  707.         mov     [dma_hdpos], eax
  708.         pop     edx
  709.         pop     eax
  710.         mov     [dma_cur_sector], eax
  711.         jmp     hd_read_dma
  712.  
  713. align 4
  714. write_cache_sector:
  715.         mov     [cache_chain_size], 1
  716.         mov     [cache_chain_pos], edi
  717. write_cache_chain:
  718.         cmp     [hdpos], 0x80
  719.         jae     bd_write_cache_chain
  720.         mov     eax, [cache_chain_ptr]
  721.         cmp     dword[eax], 0x10000000
  722.         jae     .bad
  723.         push    esi
  724.         mov     eax, IDE_descriptor_table
  725.         mov     edx, eax
  726.         pusha
  727.         mov     esi, [cache_chain_pos]
  728.         shl     esi, 9
  729.         call    calculate_cache_2
  730.         add     esi, eax
  731.         mov     edi, (OS_BASE+IDE_DMA)
  732.         mov     dword [edx], IDE_DMA
  733.         movzx   ecx, [cache_chain_size]
  734.         shl     ecx, 9
  735.         mov     word [edx+4], cx
  736.         shr     ecx, 2
  737.         cld
  738.         rep movsd
  739.         popa
  740.         sub     eax, OS_BASE
  741.         mov     dx, [IDEContrRegsBaseAddr]
  742.         cmp     [hdbase], 0x1F0
  743.         jz      @f
  744.         add     edx, 8
  745. @@:
  746.         push    edx
  747.         add     edx, 4
  748.         out     dx, eax
  749.         pop     edx
  750.         mov     al, 0
  751.         out     dx, al
  752.         add     edx, 2
  753.         mov     al, 6
  754.         out     dx, al
  755.         call    wait_for_hd_idle
  756.         cmp     [hd_error], 0
  757.         jnz     hd_write_error_dma
  758.         call    disable_ide_int
  759.         xor     eax, eax
  760.         mov     edx, [hdbase]
  761.         inc     edx
  762.         out     dx, al
  763.         inc     edx
  764.         mov     al, [cache_chain_size]
  765.         out     dx, al
  766.         inc     edx
  767.         mov     esi, [cache_chain_ptr]
  768.         mov     eax, [esi]
  769.         out     dx, al
  770.         shr     eax, 8
  771.         inc     edx
  772.         out     dx, al
  773.         shr     eax, 8
  774.         inc     edx
  775.         out     dx, al
  776.         shr     eax, 8
  777.         inc     edx
  778.         and     al, 0xF
  779.         add     al, byte [hdid]
  780.         add     al, 11100000b
  781.         out     dx, al
  782.         inc     edx
  783.         mov     al, 0xCA
  784.         out     dx, al
  785.         mov     dx, [IDEContrRegsBaseAddr]
  786.         cmp     [hdbase], 0x1F0
  787.         jz      @f
  788.         add     dx, 8
  789. @@:
  790.         mov     al, 1
  791.         out     dx, al
  792.         mov     eax, [CURRENT_TASK]
  793.         mov     [dma_process], eax
  794.         mov     eax, [TASK_BASE]
  795.         mov     [dma_slot_ptr], eax
  796.         cmp     [hdbase], 0x1F0
  797.         jnz     .ide1
  798.         mov     [irq14_func], hdd_irq14
  799.         jmp     @f
  800. .ide1:
  801.         mov     [irq15_func], hdd_irq15
  802. @@:
  803.         call    enable_ide_int
  804.         mov     [dma_cur_sector], not 0x40
  805.         cmp     [hdbase], 0x1F0
  806.         jnz     .wait_ide1
  807.         call    wait_for_sector_dma_ide0
  808.         jmp     @f
  809. .wait_ide1:
  810.         call    wait_for_sector_dma_ide1
  811. @@:
  812.         cmp     [hd_error], 0
  813.         jnz     hd_write_error_dma
  814.         pop     esi
  815.         ret
  816. .bad:
  817.         inc     [hd_error]
  818.         ret
  819.  
  820. uglobal
  821. IDEContrRegsBaseAddr    dw      ?
  822. endg
  823. ; \end{Mario79}
  824.  
  825. ; \begin{diamond}
  826. uglobal
  827. bios_hdpos      dd      0       ; 0 is invalid value for [hdpos]
  828. bios_cur_sector dd      ?
  829. bios_read_len   dd      ?
  830. endg
  831. bd_read:
  832.         push    eax
  833.         push    edx
  834.         mov     edx, [bios_hdpos]
  835.         cmp     edx, [hdpos]
  836.         jne     .notread
  837.         mov     edx, [bios_cur_sector]
  838.         cmp     eax, edx
  839.         jb      .notread
  840.         add     edx, [bios_read_len]
  841.         dec     edx
  842.         cmp     eax, edx
  843.         ja      .notread
  844.         sub     eax, [bios_cur_sector]
  845.         shl     eax, 9
  846.         add     eax, (OS_BASE+0x9A000)
  847.         push    ecx esi edi
  848.         mov     esi, eax
  849.         shl     edi, 9
  850. ;        add     edi, HD_CACHE+0x10000
  851.         push    eax
  852.         call    calculate_cache_2
  853.         add     edi, eax
  854.         pop     eax
  855.  
  856.         mov     ecx, 512/4
  857.         cld
  858.         rep movsd
  859.         pop     edi esi ecx
  860.         pop     edx
  861.         pop     eax
  862.         ret
  863. .notread:
  864.         push    ecx
  865.         mov     dl, 42h
  866.         mov     ecx, 16
  867.         call    int13_call
  868.         pop     ecx
  869.         test    eax, eax
  870.         jnz     .v86err
  871.         test    edx, edx
  872.         jz      .readerr
  873.         mov     [bios_read_len], edx
  874.         mov     edx, [hdpos]
  875.         mov     [bios_hdpos], edx
  876.         pop     edx
  877.         pop     eax
  878.         mov     [bios_cur_sector], eax
  879.         jmp     bd_read
  880. .readerr:
  881. .v86err:
  882.         mov     [hd_error], 1
  883.         jmp     hd_read_error
  884.  
  885. bd_write_cache_chain:
  886.         pusha
  887.         mov     esi, [cache_chain_pos]
  888.         shl     esi, 9
  889.         call    calculate_cache_2
  890.         add     esi, eax
  891.         mov     edi, OS_BASE + 0x9A000
  892.         movzx   ecx, [cache_chain_size]
  893.         push    ecx
  894.         shl     ecx, 9-2
  895.         rep movsd
  896.         pop     ecx
  897.         mov     dl, 43h
  898.         mov     eax, [cache_chain_ptr]
  899.         mov     eax, [eax]
  900.         call    int13_call
  901.         test    eax, eax
  902.         jnz     .v86err
  903.         cmp     edx, ecx
  904.         jnz     .writeerr
  905.         popa
  906.         ret
  907. .v86err:
  908. .writeerr:
  909.         popa
  910.         mov     [hd_error], 1
  911.         jmp     hd_write_error
  912.  
  913. uglobal
  914. int13_regs_in   rb      sizeof.v86_regs
  915. int13_regs_out  rb      sizeof.v86_regs
  916. endg
  917.  
  918. int13_call:
  919. ; Because this code uses fixed addresses,
  920. ; it can not be run simultaniously by many threads.
  921. ; In current implementation it is protected by common mutex 'hd1_status'
  922.         mov     word [OS_BASE + 510h], 10h             ; packet length
  923.         mov     word [OS_BASE + 512h], cx              ; number of sectors
  924.         mov     dword [OS_BASE + 514h], 9A000000h      ; buffer 9A00:0000
  925.         mov     dword [OS_BASE + 518h], eax
  926.         and     dword [OS_BASE + 51Ch], 0
  927.         push    ebx ecx esi edi
  928.         mov     ebx, int13_regs_in
  929.         mov     edi, ebx
  930.         mov     ecx, sizeof.v86_regs/4
  931.         xor     eax, eax
  932.         rep stosd
  933.         mov     byte [ebx+v86_regs.eax+1], dl
  934.         mov     eax, [hdpos]
  935.         lea     eax, [BiosDisksData+(eax-80h)*4]
  936.         mov     dl, [eax]
  937.         mov     byte [ebx+v86_regs.edx], dl
  938.         movzx   edx, byte [eax+1]
  939. ;        mov     dl, 5
  940.         test    edx, edx
  941.         jnz     .hasirq
  942.         dec     edx
  943.         jmp     @f
  944. .hasirq:
  945.         pushad
  946.         stdcall enable_irq, edx
  947.         popad
  948. @@:
  949.         mov     word [ebx+v86_regs.esi], 510h
  950.         mov     word [ebx+v86_regs.ss], 9000h
  951.         mov     word [ebx+v86_regs.esp], 0A000h
  952.         mov     word [ebx+v86_regs.eip], 500h
  953.         mov     [ebx+v86_regs.eflags], 20200h
  954.         mov     esi, [sys_v86_machine]
  955.         mov     ecx, 0x502
  956.         push    fs
  957.         call    v86_start
  958.         pop     fs
  959.         and     [bios_hdpos], 0
  960.         pop     edi esi ecx ebx
  961.         movzx   edx, byte [OS_BASE + 512h]
  962.         test    byte [int13_regs_out+v86_regs.eflags], 1
  963.         jnz     @f
  964.         mov     edx, ecx
  965. @@:
  966.         ret
  967. ; \end{diamond}
  968.  
  969. reserve_hd1:
  970.  
  971.         cli
  972.         cmp     [hd1_status], 0
  973.         je      reserve_ok1
  974.  
  975.         sti
  976.         call    change_task
  977.         jmp     reserve_hd1
  978.  
  979.   reserve_ok1:
  980.  
  981.         push    eax
  982.         mov     eax, [CURRENT_TASK]
  983.         shl     eax, 5
  984.         mov     eax, [eax+CURRENT_TASK+TASKDATA.pid]
  985.         mov     [hd1_status], eax
  986.         pop     eax
  987.         sti
  988.         ret
  989. ;********************************************
  990.  
  991. uglobal
  992. hd_in_cache db ?
  993. endg
  994.  
  995. reserve_hd_channel:
  996. ; BIOS disk accesses are protected with common mutex hd1_status
  997. ; This must be modified when hd1_status will not be valid!
  998.         cmp     [hdpos], 0x80
  999.         jae     .ret
  1000.         cmp     [hdbase], 0x1F0
  1001.         jne     .IDE_Channel_2
  1002. .IDE_Channel_1:
  1003.         cli
  1004.         cmp     [IDE_Channel_1], 0
  1005.         je      .reserve_ok_1
  1006.         sti
  1007.         call    change_task
  1008.         jmp     .IDE_Channel_1
  1009. .IDE_Channel_2:
  1010.         cli
  1011.         cmp     [IDE_Channel_2], 0
  1012.         je      .reserve_ok_2
  1013.         sti
  1014.         call    change_task
  1015.         jmp     .IDE_Channel_2
  1016. .reserve_ok_1:
  1017.         mov     [IDE_Channel_1], 1
  1018.         push    eax
  1019.         mov     al, 1
  1020.         jmp     @f
  1021. .reserve_ok_2:
  1022.         mov     [IDE_Channel_2], 1
  1023.         push    eax
  1024.         mov     al, 3
  1025. @@:
  1026.         cmp     [hdid], 1
  1027.         sbb     al, -1
  1028.         mov     [hd_in_cache], al
  1029.         pop     eax
  1030.         sti
  1031. .ret:
  1032.         ret
  1033.  
  1034. free_hd_channel:
  1035. ; see comment at reserve_hd_channel
  1036.         cmp     [hdpos], 0x80
  1037.         jae     .ret
  1038.         cmp     [hdbase], 0x1F0
  1039.         jne     .IDE_Channel_2
  1040. .IDE_Channel_1:
  1041.         mov     [IDE_Channel_1], 0
  1042. .ret:
  1043.         ret
  1044. .IDE_Channel_2:
  1045.         mov     [IDE_Channel_2], 0
  1046.         ret
  1047. ;********************************************
  1048.