Subversion Repositories Kolibri OS

Rev

Rev 3539 | Rev 3706 | 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: 3702 $
  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.         ; Выбрать нужный диск
  105.         mov     edx, [hdbase]
  106.         add     edx, 6   ;адрес регистра головок
  107.         mov     al, byte [hdid]
  108.         add     al, 128+64+32
  109.         out     dx, al; номер головки/номер диска
  110.        
  111.         call    wait_for_hd_idle
  112.         cmp     [hd_error], 0
  113.         jne     hd_read_error
  114.        
  115. ; ATA with 28 or 48 bit for sector number?
  116.         mov     eax, [esp+4]
  117.         cmp     eax, 0x10000000
  118.         jae     .lba48 
  119. .lba28:
  120.         cli
  121.         xor     eax, eax
  122.         mov     edx, [hdbase]
  123.         inc     edx
  124.         out     dx, al; ATAFeatures регистр "особенностей"
  125.         inc     edx
  126.         inc     eax
  127.         out     dx, al; ATASectorCount счётчик секторов
  128.         inc     edx
  129.         mov     eax, [esp+4]
  130.         out     dx, al; ATASectorNumber регистр номера сектора
  131.         shr     eax, 8
  132.         inc     edx
  133.         out     dx, al; ATACylinder номер цилиндра (младший байт)
  134.         shr     eax, 8
  135.         inc     edx
  136.         out     dx, al; номер цилиндра (старший байт)
  137.         shr     eax, 8
  138.         inc     edx
  139.         and     al, 1+2+4+8
  140.         add     al, byte [hdid]
  141.         add     al, 128+64+32
  142.         out     dx, al; номер головки/номер диска
  143.         inc     edx
  144.         mov     al, 20h
  145.         out     dx, al; ATACommand регистр команд
  146.         sti
  147.         jmp     .continue
  148. .lba48:
  149.         cli
  150.         xor     eax, eax
  151.         mov     edx, [hdbase]
  152.         inc     edx
  153.         out     dx, al ; Features Previous Reserved
  154.         out     dx, al ; Features Current Reserved
  155.         inc     edx
  156.         out     dx, al ; Sector Count Previous Sector count (15:8)
  157.         inc     eax
  158.         out     dx, al ; Sector Count Current Sector count (7:0)
  159.         inc     edx
  160.         mov     eax, [esp+4]
  161.         rol     eax,8
  162.         out     dx, al ; LBA Low Previous LBA (31:24)
  163.         xor     eax,eax ; because only 32 bit cache
  164.         inc     edx
  165.         out     dx, al ; LBA Mid Previous LBA (39:32)
  166.         inc     edx
  167.         out     dx, al ; LBA High Previous LBA (47:40)
  168.         sub     edx,2
  169.         mov     eax, [esp+4]
  170.         out     dx, al ; LBA Low Current LBA (7:0)
  171.         shr     eax, 8
  172.         inc     edx
  173.         out     dx, al ; LBA Mid Current LBA (15:8)
  174.         shr     eax, 8
  175.         inc     edx
  176.         out     dx, al ; LBA High Current LBA (23:16)
  177.         inc     edx
  178.         mov     al, byte [hdid]
  179.         add     al, 128+64+32
  180.         out     dx, al; номер головки/номер диска
  181.         inc     edx
  182.         mov     al, 24h ; READ SECTOR(S) EXT
  183.         out     dx, al; ATACommand регистр команд
  184.         sti
  185. .continue:
  186.         call    wait_for_sector_buffer
  187.  
  188.         cmp     [hd_error], 0
  189.         jne     hd_read_error
  190.  
  191.         cli
  192.         push    edi
  193.         shl     edi, 9
  194. ;    add   edi,HD_CACHE+65536
  195.         push    eax
  196.         call    calculate_cache_2
  197.         add     edi, eax
  198.         pop     eax
  199.  
  200.         mov     ecx, 256
  201.         mov     edx, [hdbase]
  202.         cld
  203.         rep insw
  204.         pop     edi
  205.         sti
  206.  
  207.         pop     edx eax
  208.         ret
  209.  
  210. disable_ide_int:
  211. ;        mov edx,[hdbase]
  212. ;        add edx,0x206
  213. ;        mov al,2
  214. ;        out dx,al
  215.         cli
  216.         ret
  217.  
  218. enable_ide_int:
  219. ;        mov edx,[hdbase]
  220. ;        add edx,0x206
  221. ;        mov al,0
  222. ;        out dx,al
  223.         sti
  224.         ret
  225.  
  226. align 4
  227. hd_write:
  228. ;-----------------------------------------------------------
  229. ; input  : eax = block
  230. ;          ebx = pointer to memory
  231. ;-----------------------------------------------------------
  232.         push    ecx esi edi
  233.  
  234.     ; check if the cache already has the sector and overwrite it
  235.  
  236. ;    mov   ecx,cache_max
  237. ;    mov   esi,HD_CACHE+8
  238.         call    calculate_cache
  239.         add     esi, 8
  240.  
  241.         mov     edi, 1
  242.  
  243.   hdwritecache:
  244.  
  245.         cmp     dword [esi+4], 0; if cache slot is empty
  246.         je      not_in_cache_write
  247.  
  248.         cmp     [esi], eax      ; if the slot has the sector
  249.         je      yes_in_cache_write
  250.  
  251.   not_in_cache_write:
  252.  
  253.         add     esi, 8
  254.         inc     edi
  255.         dec     ecx
  256.         jnz     hdwritecache
  257.  
  258.     ; sector not found in cache
  259.     ; write the block to a new location
  260.  
  261.         call    find_empty_slot ; ret in edi
  262.         cmp     [hd_error], 0
  263.         jne     hd_write_access_denied
  264.  
  265. ;    lea   esi,[edi*8+HD_CACHE]
  266. ;    push  eax
  267.         call    calculate_cache_1
  268.         lea     esi, [edi*8+esi]
  269. ;    pop   eax
  270.  
  271.         mov     [esi], eax      ; sector number
  272.  
  273.   yes_in_cache_write:
  274.  
  275.         mov     dword [esi+4], 2; write - differs from hd
  276.  
  277.         shl     edi, 9
  278. ;    add   edi,HD_CACHE+65536
  279.         push    eax
  280.         call    calculate_cache_2
  281.         add     edi, eax
  282.         pop     eax
  283.  
  284.         mov     esi, ebx
  285.         mov     ecx, 512/4
  286.         cld
  287.         rep movsd               ; move data
  288.  hd_write_access_denied:
  289.         pop     edi esi ecx
  290.         ret
  291.  
  292. align 4
  293. cache_write_pio:
  294.         cmp     dword[esi], 0x10000000
  295.         jae     .bad
  296. ;    call  disable_ide_int
  297.  
  298.         ; Выбрать нужный диск
  299.         mov     edx, [hdbase]
  300.         add     edx, 6   ;адрес регистра головок
  301.         mov     al, byte [hdid]
  302.         add     al, 128+64+32
  303.         out     dx, al; номер головки/номер диска
  304.  
  305.         call    wait_for_hd_idle
  306.         cmp     [hd_error], 0
  307.         jne     hd_write_error
  308.  
  309.         cli
  310.         xor     eax, eax
  311.         mov     edx, [hdbase]
  312.         inc     edx
  313.         out     dx, al
  314.         inc     edx
  315.         inc     eax
  316.         out     dx, al
  317.         inc     edx
  318.         mov     eax, [esi]      ; eax = sector to write
  319.         out     dx, al
  320.         shr     eax, 8
  321.         inc     edx
  322.         out     dx, al
  323.         shr     eax, 8
  324.         inc     edx
  325.         out     dx, al
  326.         shr     eax, 8
  327.         inc     edx
  328.         and     al, 1+2+4+8
  329.         add     al, byte [hdid]
  330.         add     al, 128+64+32
  331.         out     dx, al
  332.         inc     edx
  333.         mov     al, 30h
  334.         out     dx, al
  335.         sti
  336.  
  337.         call    wait_for_sector_buffer
  338.  
  339.         cmp     [hd_error], 0
  340.         jne     hd_write_error
  341.  
  342.         push    ecx esi
  343.  
  344.         cli
  345.         mov     esi, edi
  346.         shl     esi, 9
  347. ;    add   esi,HD_CACHE+65536    ; esi = from memory position
  348.         push    eax
  349.         call    calculate_cache_2
  350.         add     esi, eax
  351.         pop     eax
  352.  
  353.         mov     ecx, 256
  354.         mov     edx, [hdbase]
  355.         cld
  356.         rep outsw
  357.         sti
  358.  
  359. ;    call  enable_ide_int
  360.         pop     esi ecx
  361.  
  362.         ret
  363. .bad:
  364.         inc     [hd_error]
  365.         ret
  366.  
  367. save_hd_wait_timeout:
  368.  
  369.         push    eax
  370.         mov     eax, [timer_ticks]
  371.         add     eax, 300        ; 3 sec timeout
  372.         mov     [hd_wait_timeout], eax
  373.         pop     eax
  374.         ret
  375.  
  376. align 4
  377. check_hd_wait_timeout:
  378.  
  379.         push    eax
  380.         mov     eax, [hd_wait_timeout]
  381.         cmp     [timer_ticks], eax
  382.         jg      hd_timeout_error
  383.         pop     eax
  384.         mov     [hd_error], 0
  385.         ret
  386.  
  387. ;iglobal
  388. ;  hd_timeout_str   db 'K : FS - HD timeout',0
  389. ;  hd_read_str      db 'K : FS - HD read error',0
  390. ;  hd_write_str     db 'K : FS - HD write error',0
  391. ;  hd_lba_str       db 'K : FS - HD LBA error',0
  392. ;endg
  393.  
  394. hd_timeout_error:
  395.  
  396. ;    call  clear_hd_cache
  397. ;    call  clear_application_table_status
  398. ;    mov   esi,hd_timeout_str
  399. ;    call  sys_msg_board_str
  400.     if lang eq sp
  401.     DEBUGF 1,"K : FS - HD tiempo de espera agotado\n"
  402.     else
  403.     DEBUGF 1,"K : FS - HD timeout\n"
  404.     end if
  405.  
  406.         mov     [hd_error], 1
  407.         pop     eax
  408.         ret
  409.  
  410. hd_read_error:
  411.  
  412. ;    call  clear_hd_cache
  413. ;    call  clear_application_table_status
  414. ;    mov   esi,hd_read_str
  415. ;    call  sys_msg_board_str
  416.     if lang eq sp
  417.     DEBUGF 1,"K : FS - HD error de lectura\n"
  418.     else
  419.     DEBUGF 1,"K : FS - HD read error\n"
  420.     end if
  421.         pop     edx eax
  422.         ret
  423.  
  424. hd_write_error:
  425.  
  426. ;    call  clear_hd_cache
  427. ;    call  clear_application_table_status
  428. ;     mov   esi,hd_write_str
  429. ;     call  sys_msg_board_str
  430.     if lang eq sp
  431.     DEBUGF 1,"K : FS - HD error de escritura\n"
  432.     else
  433.     DEBUGF 1,"K : FS - HD write error\n"
  434.     end if
  435.         ret
  436.  
  437. hd_write_error_dma:
  438. ;        call    clear_hd_cache
  439. ;        call    clear_application_table_status
  440. ;        mov     esi, hd_write_str
  441. ;        call    sys_msg_board_str
  442.         if lang eq sp
  443.         DEBUGF 1,"K : FS - HD error de escritura\n"
  444.         else
  445.         DEBUGF 1,"K : FS - HD write error\n"
  446.         end if
  447.         pop     esi
  448.         ret
  449.  
  450. hd_lba_error:
  451. ;    call  clear_hd_cache
  452. ;    call  clear_application_table_status
  453. ;    mov   esi,hd_lba_str
  454. ;    call  sys_msg_board_str
  455.      if lang eq sp
  456.      DEBUGF 1,"K : FS - HD error en LBA\n"
  457.      else
  458.      DEBUGF 1,"K : FS - HD LBA error\n"
  459.      end if
  460.         jmp     LBA_read_ret
  461.  
  462.  
  463. align 4
  464. wait_for_hd_idle:
  465.  
  466.         push    eax edx
  467.  
  468.         call    save_hd_wait_timeout
  469.  
  470.         mov     edx, [hdbase]
  471.         add     edx, 0x7
  472.  
  473.   wfhil1:
  474.  
  475.         call    check_hd_wait_timeout
  476.         cmp     [hd_error], 0
  477.         jne     @f
  478.  
  479.         in      al, dx
  480.         test    al, 128
  481.         jnz     wfhil1
  482.  
  483.  @@:
  484.  
  485.         pop     edx eax
  486.         ret
  487.  
  488.  
  489. align 4
  490. wait_for_sector_buffer:
  491.  
  492.         push    eax edx
  493.  
  494.         mov     edx, [hdbase]
  495.         add     edx, 0x7
  496.  
  497.         call    save_hd_wait_timeout
  498.  
  499.   hdwait_sbuf:                  ; wait for sector buffer to be ready
  500.  
  501.         call    check_hd_wait_timeout
  502.         cmp     [hd_error], 0
  503.         jne     @f
  504.  
  505.         in      al, dx
  506.         test    al, 8
  507.         jz      hdwait_sbuf
  508.  
  509.         mov     [hd_error], 0
  510.  
  511.         cmp     [hd_setup], 1   ; do not mark error for setup request
  512.         je      buf_wait_ok
  513.  
  514.         test    al, 1           ; previous command ended up with an error
  515.         jz      buf_wait_ok
  516.  @@:
  517.         mov     [hd_error], 1
  518.  
  519.   buf_wait_ok:
  520.  
  521.         pop     edx eax
  522.         ret
  523.  
  524. ; \begin{Mario79}
  525. align 4
  526. wait_for_sector_dma_ide0:
  527.         push    eax
  528.         push    edx
  529.         call    save_hd_wait_timeout
  530. .wait:
  531.         call    change_task
  532.         cmp     [irq14_func], hdd_irq14
  533.         jnz     .done
  534.         call    check_hd_wait_timeout
  535.         cmp     [hd_error], 0
  536.         jz      .wait
  537.         mov     [irq14_func], hdd_irq_null
  538.         mov     dx, [IDEContrRegsBaseAddr]
  539.         mov     al, 0
  540.         out     dx, al
  541. .done:
  542.         pop     edx
  543.         pop     eax
  544.         ret
  545.  
  546. align 4
  547. wait_for_sector_dma_ide1:
  548.         push    eax
  549.         push    edx
  550.         call    save_hd_wait_timeout
  551. .wait:
  552.         call    change_task
  553.         cmp     [irq15_func], hdd_irq15
  554.         jnz     .done
  555.         call    check_hd_wait_timeout
  556.         cmp     [hd_error], 0
  557.         jz      .wait
  558.         mov     [irq15_func], hdd_irq_null
  559.         mov     dx, [IDEContrRegsBaseAddr]
  560.         add     dx, 8
  561.         mov     al, 0
  562.         out     dx, al
  563. .done:
  564.         pop     edx
  565.         pop     eax
  566.         ret
  567.  
  568. iglobal
  569. align 4
  570. ; note that IDE descriptor table must be 4-byte aligned and do not cross 4K boundary
  571. IDE_descriptor_table:
  572.         dd      IDE_DMA
  573.         dw      0x2000
  574.         dw      0x8000
  575.  
  576. dma_cur_sector  dd      not 40h
  577. dma_hdpos       dd      0
  578. irq14_func      dd      hdd_irq_null
  579. irq15_func      dd      hdd_irq_null
  580. endg
  581.  
  582. uglobal
  583. ; all uglobals are zeroed at boot
  584. dma_process     dd      0
  585. dma_slot_ptr    dd      0
  586. cache_chain_pos dd      0
  587. cache_chain_ptr dd      0
  588. cache_chain_size        db      0
  589. cache_chain_started     db      0
  590. dma_task_switched       db      0
  591. dma_hdd         db      0
  592. allow_dma_access db      0
  593. endg
  594.  
  595. align 4
  596. hdd_irq14:
  597.         pushfd
  598.         cli
  599.         pushad
  600.         mov     [irq14_func], hdd_irq_null
  601.         mov     dx, [IDEContrRegsBaseAddr]
  602.         mov     al, 0
  603.         out     dx, al
  604. ;        call    update_counters
  605. ;        mov     ebx, [dma_process]
  606. ;        cmp     [CURRENT_TASK], ebx
  607. ;        jz      .noswitch
  608. ;        mov     [dma_task_switched], 1
  609. ;        mov     edi, [dma_slot_ptr]
  610. ;        mov     eax, [CURRENT_TASK]
  611. ;        mov     [dma_process], eax
  612. ;        mov     eax, [TASK_BASE]
  613. ;        mov     [dma_slot_ptr], eax
  614. ;        mov     [CURRENT_TASK], ebx
  615. ;        mov     [TASK_BASE], edi
  616. ;        mov     byte [DONT_SWITCH], 1
  617. ;        call    do_change_task
  618. .noswitch:
  619.         popad
  620.         popfd
  621. align 4
  622. hdd_irq_null:
  623.         ret
  624.  
  625. align 4
  626. hdd_irq15:
  627.         pushfd
  628.         cli
  629.         pushad
  630.         mov     [irq15_func], hdd_irq_null
  631.         mov     dx, [IDEContrRegsBaseAddr]
  632.         add     dx, 8
  633.         mov     al, 0
  634.         out     dx, al
  635. ;        call    update_counters
  636. ;        mov     ebx, [dma_process]
  637. ;        cmp     [CURRENT_TASK], ebx
  638. ;        jz      .noswitch
  639. ;        mov     [dma_task_switched], 1
  640. ;        mov     edi, [dma_slot_ptr]
  641. ;        mov     eax, [CURRENT_TASK]
  642. ;        mov     [dma_process], eax
  643. ;        mov     eax, [TASK_BASE]
  644. ;        mov     [dma_slot_ptr], eax
  645. ;        mov     [CURRENT_TASK], ebx
  646. ;        mov     [TASK_BASE], edi
  647. ;        mov     byte [DONT_SWITCH], 1
  648. ;        call    do_change_task
  649. .noswitch:
  650.         popad
  651.         popfd
  652.         ret
  653.  
  654. align 4
  655. hd_read_dma:
  656. ; hd_read_dma use old ATA with 28 bit for sector number
  657.         cmp     eax, 0x10000000
  658.         jb      @f
  659.         inc     [hd_error]
  660.         ret
  661. @@:
  662.         push    eax
  663.         push    edx
  664.         mov     edx, [dma_hdpos]
  665.         cmp     edx, [hdpos]
  666.         jne     .notread
  667.         mov     edx, [dma_cur_sector]
  668.         cmp     eax, edx
  669.         jb      .notread
  670.         add     edx, 15
  671.         cmp     [esp+4], edx
  672.         ja      .notread
  673.         mov     eax, [esp+4]
  674.         sub     eax, [dma_cur_sector]
  675.         shl     eax, 9
  676.         add     eax, (OS_BASE+IDE_DMA)
  677.         push    ecx esi edi
  678.         mov     esi, eax
  679.         shl     edi, 9
  680. ;        add     edi, HD_CACHE+0x10000
  681.         push    eax
  682.         call    calculate_cache_2
  683.         add     edi, eax
  684.         pop     eax
  685.  
  686.         mov     ecx, 512/4
  687.         cld
  688.         rep movsd
  689.         pop     edi esi ecx
  690.         pop     edx
  691.         pop     eax
  692.         ret
  693. .notread:
  694.         mov     eax, IDE_descriptor_table
  695.         mov     dword [eax], IDE_DMA
  696.         mov     word [eax+4], 0x2000
  697.         sub     eax, OS_BASE
  698.         mov     dx, [IDEContrRegsBaseAddr]
  699.         cmp     [hdbase], 0x1F0
  700.         jz      @f
  701.         add     edx, 8
  702. @@:
  703.         push    edx
  704.         add     edx, 4
  705.         out     dx, eax
  706.         pop     edx
  707.         mov     al, 0
  708.         out     dx, al
  709.         add     edx, 2
  710.         mov     al, 6
  711.         out     dx, al
  712.         call    wait_for_hd_idle
  713.         cmp     [hd_error], 0
  714.         jnz     hd_read_error
  715.         call    disable_ide_int
  716.         xor     eax, eax
  717.         mov     edx, [hdbase]
  718.         inc     edx
  719.         out     dx, al
  720.         inc     edx
  721.         mov     eax, 10h
  722.         out     dx, al
  723.         inc     edx
  724.         mov     eax, [esp+4]
  725.         out     dx, al
  726.         shr     eax, 8
  727.         inc     edx
  728.         out     dx, al
  729.         shr     eax, 8
  730.         inc     edx
  731.         out     dx, al
  732.         shr     eax, 8
  733.         inc     edx
  734.         and     al, 0xF
  735.         add     al, byte [hdid]
  736.         add     al, 11100000b
  737.         out     dx, al
  738.         inc     edx
  739.         mov     al, 0xC8
  740.         out     dx, al
  741.         mov     dx, [IDEContrRegsBaseAddr]
  742.         cmp     [hdbase], 0x1F0
  743.         jz      @f
  744.         add     dx, 8
  745. @@:
  746.         mov     al, 9
  747.         out     dx, al
  748.         mov     eax, [CURRENT_TASK]
  749.         mov     [dma_process], eax
  750.         mov     eax, [TASK_BASE]
  751.         mov     [dma_slot_ptr], eax
  752.         cmp     [hdbase], 0x1F0
  753.         jnz     .ide1
  754.         mov     [irq14_func], hdd_irq14
  755.         jmp     @f
  756. .ide1:
  757.         mov     [irq15_func], hdd_irq15
  758. @@:
  759.         call    enable_ide_int
  760.         cmp     [hdbase], 0x1F0
  761.         jnz     .wait_ide1
  762.         call    wait_for_sector_dma_ide0
  763.         jmp     @f
  764. .wait_ide1:
  765.         call    wait_for_sector_dma_ide1
  766. @@:
  767.         cmp     [hd_error], 0
  768.         jnz     hd_read_error
  769.         mov     eax, [hdpos]
  770.         mov     [dma_hdpos], eax
  771.         pop     edx
  772.         pop     eax
  773.         mov     [dma_cur_sector], eax
  774.         jmp     hd_read_dma
  775.  
  776. align 4
  777. write_cache_sector:
  778.         mov     [cache_chain_size], 1
  779.         mov     [cache_chain_pos], edi
  780. write_cache_chain:
  781.         cmp     [hdpos], 0x80
  782.         jae     bd_write_cache_chain
  783.         mov     eax, [cache_chain_ptr]
  784.         cmp     dword[eax], 0x10000000
  785.         jae     .bad
  786.         push    esi
  787.         mov     eax, IDE_descriptor_table
  788.         mov     edx, eax
  789.         pusha
  790.         mov     esi, [cache_chain_pos]
  791.         shl     esi, 9
  792.         call    calculate_cache_2
  793.         add     esi, eax
  794.         mov     edi, (OS_BASE+IDE_DMA)
  795.         mov     dword [edx], IDE_DMA
  796.         movzx   ecx, [cache_chain_size]
  797.         shl     ecx, 9
  798.         mov     word [edx+4], cx
  799.         shr     ecx, 2
  800.         cld
  801.         rep movsd
  802.         popa
  803.         sub     eax, OS_BASE
  804.         mov     dx, [IDEContrRegsBaseAddr]
  805.         cmp     [hdbase], 0x1F0
  806.         jz      @f
  807.         add     edx, 8
  808. @@:
  809.         push    edx
  810.         add     edx, 4
  811.         out     dx, eax
  812.         pop     edx
  813.         mov     al, 0
  814.         out     dx, al
  815.         add     edx, 2
  816.         mov     al, 6
  817.         out     dx, al
  818.         call    wait_for_hd_idle
  819.         cmp     [hd_error], 0
  820.         jnz     hd_write_error_dma
  821.         call    disable_ide_int
  822.         xor     eax, eax
  823.         mov     edx, [hdbase]
  824.         inc     edx
  825.         out     dx, al
  826.         inc     edx
  827.         mov     al, [cache_chain_size]
  828.         out     dx, al
  829.         inc     edx
  830.         mov     esi, [cache_chain_ptr]
  831.         mov     eax, [esi]
  832.         out     dx, al
  833.         shr     eax, 8
  834.         inc     edx
  835.         out     dx, al
  836.         shr     eax, 8
  837.         inc     edx
  838.         out     dx, al
  839.         shr     eax, 8
  840.         inc     edx
  841.         and     al, 0xF
  842.         add     al, byte [hdid]
  843.         add     al, 11100000b
  844.         out     dx, al
  845.         inc     edx
  846.         mov     al, 0xCA
  847.         out     dx, al
  848.         mov     dx, [IDEContrRegsBaseAddr]
  849.         cmp     [hdbase], 0x1F0
  850.         jz      @f
  851.         add     dx, 8
  852. @@:
  853.         mov     al, 1
  854.         out     dx, al
  855.         mov     eax, [CURRENT_TASK]
  856.         mov     [dma_process], eax
  857.         mov     eax, [TASK_BASE]
  858.         mov     [dma_slot_ptr], eax
  859.         cmp     [hdbase], 0x1F0
  860.         jnz     .ide1
  861.         mov     [irq14_func], hdd_irq14
  862.         jmp     @f
  863. .ide1:
  864.         mov     [irq15_func], hdd_irq15
  865. @@:
  866.         call    enable_ide_int
  867.         mov     [dma_cur_sector], not 0x40
  868.         cmp     [hdbase], 0x1F0
  869.         jnz     .wait_ide1
  870.         call    wait_for_sector_dma_ide0
  871.         jmp     @f
  872. .wait_ide1:
  873.         call    wait_for_sector_dma_ide1
  874. @@:
  875.         cmp     [hd_error], 0
  876.         jnz     hd_write_error_dma
  877.         pop     esi
  878.         ret
  879. .bad:
  880.         inc     [hd_error]
  881.         ret
  882.  
  883. uglobal
  884. IDEContrRegsBaseAddr    dw      ?
  885. IDEContrProgrammingInterface   dw ?
  886. IDE_BAR0_val    dw ?
  887. IDE_BAR1_val    dw ?
  888. IDE_BAR2_val    dw ?
  889. IDE_BAR3_val    dw ?
  890. endg
  891. ; \end{Mario79}
  892.  
  893. ; \begin{diamond}
  894. uglobal
  895. bios_hdpos      dd      0       ; 0 is invalid value for [hdpos]
  896. bios_cur_sector dd      ?
  897. bios_read_len   dd      ?
  898. endg
  899. bd_read:
  900.         push    eax
  901.         push    edx
  902.         mov     edx, [bios_hdpos]
  903.         cmp     edx, [hdpos]
  904.         jne     .notread
  905.         mov     edx, [bios_cur_sector]
  906.         cmp     eax, edx
  907.         jb      .notread
  908.         add     edx, [bios_read_len]
  909.         dec     edx
  910.         cmp     eax, edx
  911.         ja      .notread
  912.         sub     eax, [bios_cur_sector]
  913.         shl     eax, 9
  914.         add     eax, (OS_BASE+0x9A000)
  915.         push    ecx esi edi
  916.         mov     esi, eax
  917.         shl     edi, 9
  918. ;        add     edi, HD_CACHE+0x10000
  919.         push    eax
  920.         call    calculate_cache_2
  921.         add     edi, eax
  922.         pop     eax
  923.  
  924.         mov     ecx, 512/4
  925.         cld
  926.         rep movsd
  927.         pop     edi esi ecx
  928.         pop     edx
  929.         pop     eax
  930.         ret
  931. .notread:
  932.         push    ecx
  933.         mov     dl, 42h
  934.         mov     ecx, 16
  935.         call    int13_call
  936.         pop     ecx
  937.         test    eax, eax
  938.         jnz     .v86err
  939.         test    edx, edx
  940.         jz      .readerr
  941.         mov     [bios_read_len], edx
  942.         mov     edx, [hdpos]
  943.         mov     [bios_hdpos], edx
  944.         pop     edx
  945.         pop     eax
  946.         mov     [bios_cur_sector], eax
  947.         jmp     bd_read
  948. .readerr:
  949. .v86err:
  950.         mov     [hd_error], 1
  951.         jmp     hd_read_error
  952.  
  953. bd_write_cache_chain:
  954.         pusha
  955.         mov     esi, [cache_chain_pos]
  956.         shl     esi, 9
  957.         call    calculate_cache_2
  958.         add     esi, eax
  959.         mov     edi, OS_BASE + 0x9A000
  960.         movzx   ecx, [cache_chain_size]
  961.         push    ecx
  962.         shl     ecx, 9-2
  963.         rep movsd
  964.         pop     ecx
  965.         mov     dl, 43h
  966.         mov     eax, [cache_chain_ptr]
  967.         mov     eax, [eax]
  968.         call    int13_call
  969.         test    eax, eax
  970.         jnz     .v86err
  971.         cmp     edx, ecx
  972.         jnz     .writeerr
  973.         popa
  974.         ret
  975. .v86err:
  976. .writeerr:
  977.         popa
  978.         mov     [hd_error], 1
  979.         jmp     hd_write_error
  980.  
  981. uglobal
  982. int13_regs_in   rb      sizeof.v86_regs
  983. int13_regs_out  rb      sizeof.v86_regs
  984. endg
  985.  
  986. int13_call:
  987. ; Because this code uses fixed addresses,
  988. ; it can not be run simultaniously by many threads.
  989. ; In current implementation it is protected by common mutex 'hd1_status'
  990.         mov     word [OS_BASE + 510h], 10h             ; packet length
  991.         mov     word [OS_BASE + 512h], cx              ; number of sectors
  992.         mov     dword [OS_BASE + 514h], 9A000000h      ; buffer 9A00:0000
  993.         mov     dword [OS_BASE + 518h], eax
  994.         and     dword [OS_BASE + 51Ch], 0
  995.         push    ebx ecx esi edi
  996.         mov     ebx, int13_regs_in
  997.         mov     edi, ebx
  998.         mov     ecx, sizeof.v86_regs/4
  999.         xor     eax, eax
  1000.         rep stosd
  1001.         mov     byte [ebx+v86_regs.eax+1], dl
  1002.         mov     eax, [hdpos]
  1003.         lea     eax, [BiosDisksData+(eax-80h)*4]
  1004.         mov     dl, [eax]
  1005.         mov     byte [ebx+v86_regs.edx], dl
  1006.         movzx   edx, byte [eax+1]
  1007. ;        mov     dl, 5
  1008.         test    edx, edx
  1009.         jnz     .hasirq
  1010.         dec     edx
  1011.         jmp     @f
  1012. .hasirq:
  1013.         pushad
  1014.         stdcall enable_irq, edx
  1015.         popad
  1016. @@:
  1017.         mov     word [ebx+v86_regs.esi], 510h
  1018.         mov     word [ebx+v86_regs.ss], 9000h
  1019.         mov     word [ebx+v86_regs.esp], 0A000h
  1020.         mov     word [ebx+v86_regs.eip], 500h
  1021.         mov     [ebx+v86_regs.eflags], 20200h
  1022.         mov     esi, [sys_v86_machine]
  1023.         mov     ecx, 0x502
  1024.         push    fs
  1025.         call    v86_start
  1026.         pop     fs
  1027.         and     [bios_hdpos], 0
  1028.         pop     edi esi ecx ebx
  1029.         movzx   edx, byte [OS_BASE + 512h]
  1030.         test    byte [int13_regs_out+v86_regs.eflags], 1
  1031.         jnz     @f
  1032.         mov     edx, ecx
  1033. @@:
  1034.         ret
  1035. ; \end{diamond}
  1036.  
  1037. reserve_hd1:
  1038.  
  1039.         cli
  1040.         cmp     [hd1_status], 0
  1041.         je      reserve_ok1
  1042.  
  1043.         sti
  1044.         call    change_task
  1045.         jmp     reserve_hd1
  1046.  
  1047.   reserve_ok1:
  1048.  
  1049.         push    eax
  1050.         mov     eax, [CURRENT_TASK]
  1051.         shl     eax, 5
  1052.         mov     eax, [eax+CURRENT_TASK+TASKDATA.pid]
  1053.         mov     [hd1_status], eax
  1054.         pop     eax
  1055.         sti
  1056.         ret
  1057. ;********************************************
  1058.  
  1059. uglobal
  1060. hd_in_cache db ?
  1061. endg
  1062.  
  1063. reserve_hd_channel:
  1064. ; BIOS disk accesses are protected with common mutex hd1_status
  1065. ; This must be modified when hd1_status will not be valid!
  1066.         cmp     [hdpos], 0x80
  1067.         jae     .ret
  1068.         cmp     [hdbase], 0x1F0
  1069.         jne     .IDE_Channel_2
  1070. .IDE_Channel_1:
  1071.         cli
  1072.         cmp     [IDE_Channel_1], 0
  1073.         je      .reserve_ok_1
  1074.         sti
  1075.         call    change_task
  1076.         jmp     .IDE_Channel_1
  1077. .IDE_Channel_2:
  1078.         cli
  1079.         cmp     [IDE_Channel_2], 0
  1080.         je      .reserve_ok_2
  1081.         sti
  1082.         call    change_task
  1083.         jmp     .IDE_Channel_2
  1084. .reserve_ok_1:
  1085.         mov     [IDE_Channel_1], 1
  1086.         push    eax
  1087.         mov     al, 1
  1088.         jmp     @f
  1089. .reserve_ok_2:
  1090.         mov     [IDE_Channel_2], 1
  1091.         push    eax
  1092.         mov     al, 3
  1093. @@:
  1094.         cmp     [hdid], 1
  1095.         sbb     al, -1
  1096.         mov     [hd_in_cache], al
  1097.         pop     eax
  1098.         sti
  1099. .ret:
  1100.         ret
  1101.  
  1102. free_hd_channel:
  1103. ; see comment at reserve_hd_channel
  1104.         cmp     [hdpos], 0x80
  1105.         jae     .ret
  1106.         cmp     [hdbase], 0x1F0
  1107.         jne     .IDE_Channel_2
  1108. .IDE_Channel_1:
  1109.         mov     [IDE_Channel_1], 0
  1110. .ret:
  1111.         ret
  1112. .IDE_Channel_2:
  1113.         mov     [IDE_Channel_2], 0
  1114.         ret
  1115. ;********************************************
  1116.