Subversion Repositories Kolibri OS

Rev

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