Subversion Repositories Kolibri OS

Rev

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