Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 4720 $
  9.  
  10.  
  11. ; Low-level driver for HDD access
  12. ; DMA support by Mario79
  13. ; LBA48 support by Mario79
  14. ;-----------------------------------------------------------------------------
  15. struct HD_DATA
  16. hdbase  dd      ?
  17. hdid    dd      ?
  18. hdpos   dd      ?
  19. ends
  20. ;-----------------------------------------------------------------------------
  21. iglobal
  22. align 4
  23. ide_callbacks:
  24.         dd      ide_callbacks.end - ide_callbacks       ; strucsize
  25.         dd      0       ; no close function
  26.         dd      0       ; no closemedia function
  27.         dd      ide_querymedia
  28.         dd      ide_read
  29.         dd      ide_write
  30.         dd      0       ; no flush function
  31.         dd      0       ; use default cache size
  32. .end:
  33.  
  34. hd0_data        HD_DATA         ?,    0, 1
  35. hd1_data        HD_DATA         ?, 0x10, 2
  36. hd2_data        HD_DATA         ?,    0, 3
  37. hd3_data        HD_DATA         ?, 0x10, 4
  38. hd4_data        HD_DATA         ?,    0, 5
  39. hd5_data        HD_DATA         ?, 0x10, 6
  40. hd6_data        HD_DATA         ?,    0, 7
  41. hd7_data        HD_DATA         ?, 0x10, 8
  42. hd8_data        HD_DATA         ?,    0, 9
  43. hd9_data        HD_DATA         ?, 0x10, 10
  44. hd10_data       HD_DATA         ?,    0, 11
  45. hd11_data       HD_DATA         ?, 0x10, 12
  46.  
  47. ide_mutex_table:
  48.         dd ide_channel1_mutex
  49.         dd ide_channel2_mutex
  50.         dd ide_channel3_mutex
  51.         dd ide_channel4_mutex
  52.         dd ide_channel5_mutex
  53.         dd ide_channel6_mutex
  54. endg
  55. ;-----------------------------------------------------------------------------
  56. uglobal
  57. ide_mutex               MUTEX
  58. ide_channel1_mutex      MUTEX
  59. ide_channel2_mutex      MUTEX
  60. ide_channel3_mutex      MUTEX
  61. ide_channel4_mutex      MUTEX
  62. ide_channel5_mutex      MUTEX
  63. ide_channel6_mutex      MUTEX
  64. endg
  65. ;-----------------------------------------------------------------------------
  66. proc ide_read stdcall uses edi, \
  67.         hd_data, buffer, startsector:qword, numsectors
  68.         ; hd_data = pointer to hd*_data
  69.         ; buffer = pointer to buffer for data
  70.         ; startsector = 64-bit start sector
  71.         ; numsectors = pointer to number of sectors on input,
  72.         ;  must be filled with number of sectors really read
  73. locals
  74. sectors_todo    dd      ?
  75. channel_lock    dd      ?
  76. endl
  77. ; 1. Initialize number of sectors: get number of requested sectors
  78. ; and say that no sectors were read yet.
  79.         mov     ecx, [numsectors]
  80.         mov     eax, [ecx]
  81.         mov     dword [ecx], 0
  82.         mov     [sectors_todo], eax
  83. ; 2. Acquire the global lock.
  84.         mov     ecx, ide_mutex
  85.         call    mutex_lock
  86.  
  87.         mov     ecx, [hd_data]
  88.         mov     ecx, [ecx+HD_DATA.hdpos]
  89.         dec     ecx
  90.         shr     ecx, 1
  91.         shl     ecx, 2
  92.         mov     ecx, [ecx + ide_mutex_table]
  93.         mov     [channel_lock], ecx
  94.         call    mutex_lock
  95. ; 3. Convert parameters to the form suitable for worker procedures.
  96. ; Underlying procedures do not know about 64-bit sectors.
  97. ; Worker procedures use global variables and edi for [buffer].
  98.         cmp     dword [startsector+4], 0
  99.         jnz     .fail
  100.  
  101.         and     [hd_error], 0
  102.         mov     ecx, [hd_data]
  103.         mov     eax, [ecx+HD_DATA.hdbase]
  104.         mov     [hdbase], eax
  105.         mov     eax, [ecx+HD_DATA.hdid]
  106.         mov     [hdid], eax
  107.         mov     eax, [ecx+HD_DATA.hdpos]
  108.         mov     [hdpos], eax
  109.         mov     eax, dword [startsector]
  110.         mov     edi, [buffer]
  111. ; 4. Worker procedures take one sectors per time, so loop over all sectors to read.
  112. .sectors_loop:
  113. ; DMA read is permitted if [allow_dma_access]=1 or 2
  114.         cmp     [allow_dma_access], 2
  115.         ja      .nodma
  116.  
  117.         push    eax ecx
  118.         mov     ecx, [hdpos]
  119.         dec     ecx
  120.         shr     ecx, 2
  121.         imul    ecx, sizeof.IDE_DATA
  122.         add     ecx, IDE_controller_1
  123.         mov     [IDE_controller_pointer], ecx
  124.  
  125.         mov     eax, [hdpos]
  126.         dec     eax
  127.         and     eax, 11b
  128.         shr     eax, 1
  129.         add     eax, ecx
  130.         cmp     [eax+IDE_DATA.dma_hdd_channel_1], 1
  131.         pop     ecx eax
  132.         jnz     .nodma
  133.  
  134.         call    hd_read_dma
  135.         jmp     @f
  136. ;--------------------------------------
  137. .nodma:
  138.         call    hd_read_pio
  139. ;--------------------------------------
  140. @@:
  141.         cmp     [hd_error], 0
  142.         jnz     .fail
  143.  
  144.         mov     ecx, [numsectors]
  145.         inc     dword [ecx]     ; one more sector is read
  146.         dec     [sectors_todo]
  147.         jz      .done
  148.  
  149.         inc     eax
  150.         jnz     .sectors_loop
  151. ;--------------------------------------
  152. ; 5. Loop is done, either due to error or because everything is done.
  153. ; Release the global lock and return the corresponding status.
  154. .fail:
  155.         mov     ecx, [channel_lock]
  156.         call    mutex_unlock
  157.  
  158.         mov     ecx, ide_mutex
  159.         call    mutex_unlock
  160.  
  161.         or      eax, -1
  162.         ret
  163. ;--------------------------------------
  164. .done:
  165.         mov     ecx, [channel_lock]
  166.         call    mutex_unlock
  167.  
  168.         mov     ecx, ide_mutex
  169.         call    mutex_unlock
  170.  
  171.         xor     eax, eax
  172.         ret
  173. endp
  174. ;-----------------------------------------------------------------------------
  175. proc ide_write stdcall uses esi edi, \
  176.         hd_data, buffer, startsector:qword, numsectors
  177.         ; hd_data = pointer to hd*_data
  178.         ; buffer = pointer to buffer with data
  179.         ; startsector = 64-bit start sector
  180.         ; numsectors = pointer to number of sectors on input,
  181.         ;  must be filled with number of sectors really written
  182. locals
  183. sectors_todo    dd      ?
  184. channel_lock    dd      ?
  185. endl
  186. ; 1. Initialize number of sectors: get number of requested sectors
  187. ; and say that no sectors were read yet.      
  188.         mov     ecx, [numsectors]
  189.         mov     eax, [ecx]
  190.         mov     dword [ecx], 0
  191.         mov     [sectors_todo], eax
  192. ; 2. Acquire the global lock.
  193.         mov     ecx, ide_mutex
  194.         call    mutex_lock
  195.  
  196.         mov     ecx, [hd_data]
  197.         mov     ecx, [ecx+HD_DATA.hdpos]
  198.         dec     ecx
  199.         shr     ecx, 1
  200.         shl     ecx, 2
  201.         mov     ecx, [ecx + ide_mutex_table]
  202.         mov     [channel_lock], ecx
  203.         call    mutex_lock
  204. ; 3. Convert parameters to the form suitable for worker procedures.
  205. ; Underlying procedures do not know about 64-bit sectors.
  206. ; Worker procedures use global variables and esi for [buffer].
  207.         cmp     dword [startsector+4], 0
  208.         jnz     .fail
  209.  
  210.         and     [hd_error], 0
  211.         mov     ecx, [hd_data]
  212.         mov     eax, [ecx+HD_DATA.hdbase]
  213.         mov     [hdbase], eax
  214.         mov     eax, [ecx+HD_DATA.hdid]
  215.         mov     [hdid], eax
  216.         mov     eax, [ecx+HD_DATA.hdpos]
  217.         mov     [hdpos], eax
  218.         mov     esi, [buffer]
  219.         lea     edi, [startsector]
  220.         mov     [cache_chain_ptr], edi
  221. ; 4. Worker procedures take max 16 sectors per time,
  222. ; loop until all sectors will be processed.
  223. .sectors_loop:
  224.         mov     ecx, 16
  225.         cmp     ecx, [sectors_todo]
  226.         jbe     @f
  227.  
  228.         mov     ecx, [sectors_todo]
  229. ;--------------------------------------
  230. @@:
  231.         mov     [cache_chain_size], cl
  232. ; DMA write is permitted only if [allow_dma_access]=1
  233.         cmp     [allow_dma_access], 2
  234.         jae     .nodma
  235.  
  236.         push    eax ecx
  237.         mov     ecx, [hdpos]
  238.         dec     ecx
  239.         shr     ecx, 2
  240.         imul    ecx, sizeof.IDE_DATA
  241.         add     ecx, IDE_controller_1
  242.         mov     [IDE_controller_pointer], ecx
  243.  
  244.         mov     eax, [hdpos]
  245.         dec     eax
  246.         and     eax, 11b
  247.         shr     eax, 1
  248.         add     eax, ecx
  249.         cmp     [eax+IDE_DATA.dma_hdd_channel_1], 1
  250.         pop     ecx eax
  251.         jnz     .nodma
  252.  
  253.         call    cache_write_dma
  254.         jmp     .common
  255. ;--------------------------------------
  256. .nodma:
  257.         mov     [cache_chain_size], 1
  258.         call    cache_write_pio
  259. ;--------------------------------------
  260. .common:
  261.         cmp     [hd_error], 0
  262.         jnz     .fail
  263.  
  264.         movzx   ecx, [cache_chain_size]
  265.         mov     eax, [numsectors]
  266.         add     [eax], ecx
  267.         sub     [sectors_todo], ecx
  268.         jz      .done
  269.  
  270.         add     [edi], ecx
  271.         jc      .fail
  272.  
  273.         shl     ecx, 9
  274.         add     esi, ecx
  275.         jmp     .sectors_loop
  276. ;--------------------------------------
  277. ; 5. Loop is done, either due to error or because everything is done.
  278. ; Release the global lock and return the corresponding status.
  279. .fail:
  280.         mov     ecx, [channel_lock]
  281.         call    mutex_unlock
  282.  
  283.         mov     ecx, ide_mutex
  284.         call    mutex_unlock
  285.  
  286.         or      eax, -1
  287.         ret
  288. ;--------------------------------------
  289. .done:
  290.         mov     ecx, [channel_lock]
  291.         call    mutex_unlock
  292.  
  293.         mov     ecx, ide_mutex
  294.         call    mutex_unlock
  295.  
  296.         xor     eax, eax
  297.         ret
  298. endp
  299. ;-----------------------------------------------------------------------------
  300. ; This is a stub.
  301. proc ide_querymedia stdcall, hd_data, mediainfo
  302.         mov     eax, [mediainfo]
  303.         mov     [eax+DISKMEDIAINFO.Flags], 0
  304.         mov     [eax+DISKMEDIAINFO.SectorSize], 512
  305.         or      dword [eax+DISKMEDIAINFO.Capacity], 0xFFFFFFFF
  306.         or      dword [eax+DISKMEDIAINFO.Capacity+4], 0xFFFFFFFF
  307.         xor     eax, eax
  308.         ret
  309. endp
  310. ;-----------------------------------------------------------------------------
  311. align 4
  312. ; input: eax = sector, edi -> buffer
  313. ; output: edi = edi + 512
  314. hd_read_pio:
  315.         push    eax edx
  316. ; Select the desired drive
  317.         mov     edx, [hdbase]
  318.         add     edx, 6   ;адрес регистра головок
  319.         mov     al, byte [hdid]
  320.         add     al, 128+64+32
  321.         out     dx, al; номер головки/номер диска
  322.        
  323.         call    wait_for_hd_idle
  324.  
  325.         cmp     [hd_error], 0
  326.         jne     hd_read_error
  327. ; ATA with 28 or 48 bit for sector number?
  328.         mov     eax, [esp+4]
  329.         cmp     eax, 0x10000000
  330.         jae     .lba48
  331. ;--------------------------------------
  332. .lba28:
  333.         pushfd
  334.         cli
  335.         xor     eax, eax
  336.         mov     edx, [hdbase]
  337.         inc     edx
  338.         out     dx, al ; ATA Features регистр "особенностей"
  339.         inc     edx
  340.         inc     eax
  341.         out     dx, al ; ATA Sector Counter счётчик секторов
  342.         inc     edx
  343.         mov     eax, [esp+4+4]
  344.         out     dx, al ; LBA Low LBA (7:0)
  345.         shr     eax, 8
  346.         inc     edx
  347.         out     dx, al ; LBA Mid LBA (15:8)
  348.         shr     eax, 8
  349.         inc     edx
  350.         out     dx, al ; LBA High LBA (23:16)
  351.         shr     eax, 8
  352.         inc     edx
  353.         and     al, 1+2+4+8 ; LBA (27:24)
  354.         add     al, byte [hdid]
  355.         add     al, 128+64+32
  356.         out     dx, al ; номер головки/номер диска
  357.         inc     edx
  358.         mov     al, 20h ; READ SECTOR(S)
  359.         out     dx, al ; ATACommand регистр команд
  360.         popfd
  361.         jmp     .continue
  362. ;--------------------------------------
  363. .lba48:
  364.         pushfd
  365.         cli
  366.         xor     eax, eax
  367.         mov     edx, [hdbase]
  368.         inc     edx
  369.         out     dx, al ; Features Previous Reserved
  370.         out     dx, al ; Features Current Reserved
  371.         inc     edx
  372.         out     dx, al ; Sector Count Previous Sector count (15:8)
  373.         inc     eax
  374.         out     dx, al ; Sector Count Current Sector count (7:0)
  375.         inc     edx
  376.         mov     eax, [esp+4+4]
  377.         rol     eax, 8
  378.         out     dx, al ; LBA Low Previous LBA (31:24)
  379.         xor     eax, eax ; because only 32 bit cache
  380.         inc     edx
  381.         out     dx, al ; LBA Mid Previous LBA (39:32)
  382.         inc     edx
  383.         out     dx, al ; LBA High Previous LBA (47:40)
  384.         sub     edx, 2
  385.         mov     eax, [esp+4+4]
  386.         out     dx, al ; LBA Low Current LBA (7:0)
  387.         shr     eax, 8
  388.         inc     edx
  389.         out     dx, al ; LBA Mid Current LBA (15:8)
  390.         shr     eax, 8
  391.         inc     edx
  392.         out     dx, al ; LBA High Current LBA (23:16)
  393.         inc     edx
  394.         mov     al, byte [hdid]
  395.         add     al, 128+64+32
  396.         out     dx, al ; номер головки/номер диска
  397.         inc     edx
  398.         mov     al, 24h ; READ SECTOR(S) EXT
  399.         out     dx, al ; ATACommand регистр команд
  400.         popfd
  401. ;--------------------------------------
  402. .continue:
  403.         call    wait_for_sector_buffer
  404.  
  405.         cmp     [hd_error], 0
  406.         jne     hd_read_error
  407.  
  408.         pushfd
  409.         cli
  410.         mov     ecx, 256
  411.         mov     edx, [hdbase]
  412.         cld
  413.         rep insw
  414.         popfd
  415.  
  416.         pop     edx eax
  417.         ret
  418. ;-----------------------------------------------------------------------------
  419. align 4
  420. ; edi -> sector, esi -> data
  421. cache_write_pio:
  422. ; Select the desired drive
  423.         mov     edx, [hdbase]
  424.         add     edx, 6   ;адрес регистра головок
  425.         mov     al, byte [hdid]
  426.         add     al, 128+64+32
  427.         out     dx, al ; номер головки/номер диска
  428.  
  429.         call    wait_for_hd_idle
  430.  
  431.         cmp     [hd_error], 0
  432.         jne     hd_write_error
  433.  
  434. ; ATA with 28 or 48 bit for sector number?
  435.         mov     eax, [edi]
  436.         cmp     eax, 0x10000000
  437.         jae     .lba48
  438. ;--------------------------------------
  439. .lba28:
  440.         pushfd
  441.         cli
  442.         xor     eax, eax
  443.         mov     edx, [hdbase]
  444.         inc     edx
  445.         out     dx, al ; ATA Features регистр "особенностей"
  446.         inc     edx
  447.         inc     eax
  448.         out     dx, al ; ATA Sector Counter счётчик секторов
  449.         inc     edx
  450.         mov     eax, [edi]      ; eax = sector to write
  451.         out     dx, al ; LBA Low LBA (7:0)
  452.         shr     eax, 8
  453.         inc     edx
  454.         out     dx, al ; LBA Mid LBA (15:8)
  455.         shr     eax, 8
  456.         inc     edx
  457.         out     dx, al ; LBA High LBA (23:16)
  458.         shr     eax, 8
  459.         inc     edx
  460.         and     al, 1+2+4+8 ; LBA (27:24)
  461.         add     al, byte [hdid]
  462.         add     al, 128+64+32
  463.         out     dx, al ; номер головки/номер диска
  464.         inc     edx
  465.         mov     al, 30h ; WRITE SECTOR(S)
  466.         out     dx, al ; ATACommand регистр команд
  467.         jmp     .continue
  468. ;--------------------------------------
  469. .lba48:
  470.         pushfd
  471.         cli
  472.         xor     eax, eax
  473.         mov     edx, [hdbase]
  474.         inc     edx
  475.         out     dx, al ; Features Previous Reserved
  476.         out     dx, al ; Features Current Reserved
  477.         inc     edx
  478.         out     dx, al ; Sector Count Previous Sector count (15:8)
  479.         inc     eax
  480.         out     dx, al ; Sector Count Current Sector count (7:0)
  481.         inc     edx
  482.         mov     eax, [edi]
  483.         rol     eax, 8
  484.         out     dx, al ; LBA Low Previous LBA (31:24)
  485.         xor     eax, eax ; because only 32 bit cache
  486.         inc     edx
  487.         out     dx, al ; LBA Mid Previous LBA (39:32)
  488.         inc     edx
  489.         out     dx, al ; LBA High Previous LBA (47:40)
  490.         sub     edx, 2
  491.         mov     eax, [edi]
  492.         out     dx, al ; LBA Low Current LBA (7:0)
  493.         shr     eax, 8
  494.         inc     edx
  495.         out     dx, al ; LBA Mid Current LBA (15:8)
  496.         shr     eax, 8
  497.         inc     edx
  498.         out     dx, al ; LBA High Current LBA (23:16)
  499.         inc     edx
  500.         mov     al, byte [hdid]
  501.         add     al, 128+64+32
  502.         out     dx, al ; номер головки/номер диска
  503.         inc     edx
  504.         mov     al, 34h ; WRITE SECTOR(S) EXT
  505.         out     dx, al ; ATACommand регистр команд
  506. ;--------------------------------------
  507. .continue:
  508.         popfd
  509.         call    wait_for_sector_buffer
  510.  
  511.         cmp     [hd_error], 0
  512.         jne     hd_write_error
  513.  
  514.         push    ecx esi
  515.  
  516.         pushfd
  517.         cli
  518.         mov     ecx, 256
  519.         mov     edx, [hdbase]
  520.         cld
  521.         rep outsw
  522.         popfd
  523.  
  524.         pop     esi ecx
  525.         ret
  526. ;-----------------------------------------------------------------------------
  527. align 4
  528. save_hd_wait_timeout:
  529.         push    eax
  530.         mov     eax, [timer_ticks]
  531.         add     eax, 300        ; 3 sec timeout
  532.         mov     [hd_wait_timeout], eax
  533.         pop     eax
  534.         ret
  535. ;-----------------------------------------------------------------------------
  536. align 4
  537. check_hd_wait_timeout:
  538.         push    eax
  539.         mov     eax, [hd_wait_timeout]
  540.         cmp     [timer_ticks], eax
  541.         jg      hd_timeout_error
  542.  
  543.         pop     eax
  544.         mov     [hd_error], 0
  545.         ret
  546. ;-----------------------------------------------------------------------------
  547. hd_timeout_error:
  548.         if lang eq sp
  549.         DEBUGF 1,"K : FS - HD tiempo de espera agotado\n"
  550.         else
  551.         DEBUGF 1,"K : FS - HD timeout\n"
  552.         end if
  553.         mov     [hd_error], 1
  554.         pop     eax
  555.         ret
  556. ;-----------------------------------------------------------------------------
  557. hd_read_error:
  558.         if lang eq sp
  559.         DEBUGF 1,"K : FS - HD error de lectura\n"
  560.         else
  561.         DEBUGF 1,"K : FS - HD read error\n"
  562.         end if
  563.         pop     edx eax
  564.         ret
  565. ;-----------------------------------------------------------------------------
  566. hd_write_error_dma:
  567.         pop     esi
  568. hd_write_error:
  569.         if lang eq sp
  570.         DEBUGF 1,"K : FS - HD error de escritura\n"
  571.         else
  572.         DEBUGF 1,"K : FS - HD write error\n"
  573.         end if
  574.         ret
  575. ;-----------------------------------------------------------------------------
  576. align 4
  577. wait_for_hd_idle:
  578.         push    eax edx
  579.  
  580.         call    save_hd_wait_timeout
  581.  
  582.         mov     edx, [hdbase]
  583.         add     edx, 0x7
  584. ;--------------------------------------
  585. align 4
  586. wfhil1:
  587.         call    check_hd_wait_timeout
  588.  
  589.         cmp     [hd_error], 0
  590.         jne     @f
  591.  
  592.         in      al, dx
  593.         test    al, 128
  594.         jnz     wfhil1
  595. ;--------------------------------------
  596. @@:
  597.         pop     edx eax
  598.         ret
  599. ;-----------------------------------------------------------------------------
  600. align 4
  601. wait_for_sector_buffer:
  602.         push    eax edx
  603.  
  604.         mov     edx, [hdbase]
  605.         add     edx, 0x7
  606.  
  607.         call    save_hd_wait_timeout
  608. ;--------------------------------------
  609. align 4
  610. hdwait_sbuf:                  ; wait for sector buffer to be ready
  611.         call    check_hd_wait_timeout
  612.  
  613.         cmp     [hd_error], 0
  614.         jne     @f
  615.  
  616.         in      al, dx
  617.         test    al, 8
  618.         jz      hdwait_sbuf
  619.  
  620.         mov     [hd_error], 0
  621.  
  622.         cmp     [hd_setup], 1   ; do not mark error for setup request
  623.         je      buf_wait_ok
  624.  
  625.         test    al, 1           ; previous command ended up with an error
  626.         jz      buf_wait_ok
  627. ;--------------------------------------
  628. @@:
  629.         mov     [hd_error], 1
  630. ;--------------------------------------
  631. buf_wait_ok:
  632.         pop     edx eax
  633.         ret
  634. ;-----------------------------------------------------------------------------
  635. irq14_num equ byte 14
  636. irq15_num equ byte 15
  637. ;-----------------------------------------------------------------------------
  638. align 4
  639. wait_for_sector_dma_ide0:
  640.         push    eax
  641.         push    edx
  642.         call    save_hd_wait_timeout
  643. ;--------------------------------------
  644. align 4
  645. .wait:
  646.         call    change_task
  647.  
  648.         cmp     [IDE_common_irq_param], 0
  649.         jz      .done
  650.  
  651.         call    check_hd_wait_timeout
  652.  
  653.         cmp     [hd_error], 0
  654.         jz      .wait
  655.  
  656.         mov     [IDE_common_irq_param], 0
  657. ;--------------------------------------
  658. .done:
  659.         pop     edx
  660.         pop     eax
  661.         ret
  662. ;-----------------------------------------------------------------------------
  663. align 4
  664. wait_for_sector_dma_ide1:
  665.         push    eax
  666.         push    edx
  667.         call    save_hd_wait_timeout
  668. ;--------------------------------------
  669. align 4
  670. .wait:
  671.         call    change_task
  672.  
  673.         cmp     [IDE_common_irq_param], 0
  674.         jz      .done
  675.  
  676.         call    check_hd_wait_timeout
  677.  
  678.         cmp     [hd_error], 0
  679.         jz      .wait
  680.  
  681.         mov     [IDE_common_irq_param], 0
  682. ;--------------------------------------
  683. .done:
  684.         pop     edx
  685.         pop     eax
  686.         ret
  687. ;-----------------------------------------------------------------------------
  688. iglobal
  689. align 4
  690. ; note that IDE descriptor table must be 4-byte aligned
  691. ; and do not cross 4K boundary
  692. IDE_descriptor_table:
  693.         dd IDE_DMA
  694.         dw 0x2000
  695.         dw 0x8000
  696.  
  697. dma_cur_sector  dd not 40h
  698. dma_hdpos       dd 0
  699. IDE_common_irq_param db 0
  700. endg
  701. ;-----------------------------------------------------------------------------
  702. uglobal
  703. ; all uglobals are zeroed at boot
  704. cache_chain_ptr     dd 0
  705. cache_chain_size    db 0
  706. allow_dma_access    db 0
  707. endg
  708. ;-----------------------------------------------------------------------------
  709. align 4
  710. IDE_irq_14_handler:
  711.         cmp     [IDE_common_irq_param], irq14_num
  712.         jne     .exit
  713.  
  714.         pushfd
  715.         cli
  716.         pushad
  717.         mov     [IDE_common_irq_param], 0
  718.         mov     ecx, [IDE_controller_pointer]
  719.         mov     dx, [ecx+IDE_DATA.RegsBaseAddres]
  720. ; test whether it is our interrupt?
  721.         add     edx, 2
  722.         in      al, dx
  723.         test    al, 100b
  724.         jz      @f
  725. ; clear Bus Master IDE Status register
  726. ; clear Interrupt bit
  727.         out     dx, al
  728. ; clear Bus Master IDE Command register
  729.         sub     edx, 2
  730.         xor     eax, eax
  731.         out     dx, al
  732. ; read status register and remove the interrupt request
  733.         mov     edx, [hdbase]
  734.         add     edx, 0x7
  735.         in      al, dx
  736.         popad
  737.         popfd
  738.         mov     al, 1
  739.         ret
  740. ;--------------------------------------
  741. @@:
  742.         popad
  743.         popfd
  744. ;--------------------------------------
  745. .exit:
  746.         mov     al, 0
  747.         ret
  748. ;-----------------------------------------------------------------------------
  749. align 4
  750. IDE_irq_15_handler:
  751.         cmp     [IDE_common_irq_param], irq15_num
  752.         jne     .exit
  753.  
  754.         pushfd
  755.         cli
  756.         pushad
  757.         mov     [IDE_common_irq_param], 0
  758.         mov     ecx, [IDE_controller_pointer]
  759.         mov     dx, [ecx+IDE_DATA.RegsBaseAddres]
  760.         add     dx, 8
  761. ; test whether it is our interrupt?
  762.         add     edx, 2
  763.         in      al, dx
  764.         test    al, 100b
  765.         jz      @f
  766. ; clear Bus Master IDE Status register
  767. ; clear Interrupt bit
  768.         out     dx, al
  769. ; clear Bus Master IDE Command register
  770.         sub     edx, 2
  771.         mov     al, 0
  772.         out     dx, al
  773. ; read status register and remove the interrupt request
  774.         mov     edx, [hdbase]
  775.         add     edx, 0x7
  776.         in      al, dx
  777.         popad
  778.         popfd
  779.         mov     al, 1
  780.         ret
  781. ;--------------------------------------
  782. @@:
  783.         popad
  784.         popfd
  785. ;--------------------------------------
  786. .exit:
  787.         mov     al, 0
  788.         ret
  789. ;-----------------------------------------------------------------------------
  790. align 4
  791. IDE_common_irq_handler:
  792.         cmp     [IDE_common_irq_param], 0
  793.         je      .exit
  794.  
  795.         pushfd
  796.         cli
  797.         pushad
  798.         xor     ebx, ebx
  799.         mov     ecx, [IDE_controller_pointer]
  800.         mov     dx, [ecx+IDE_DATA.RegsBaseAddres]
  801.         mov     eax, IDE_common_irq_param
  802.         cmp     [eax], irq14_num
  803.         mov     [eax], bl
  804.         je      @f
  805.  
  806.         add     dx, 8
  807. ;--------------------------------------
  808. @@:
  809. ; test whether it is our interrupt?
  810.         add     edx, 2
  811.         in      al, dx
  812.         test    al, 100b
  813.         jz      @f
  814. ; clear Bus Master IDE Status register
  815. ; clear Interrupt bit
  816.         out     dx, al
  817. ; clear Bus Master IDE Command register
  818.         sub     edx, 2
  819.         xor     eax, eax
  820.         out     dx, al
  821. ; read status register and remove the interrupt request
  822.         mov     edx, [hdbase]
  823.         add     edx, 0x7
  824.         in      al, dx
  825.         popad
  826.         popfd
  827.         mov     al, 1
  828.         ret
  829. ;--------------------------------------
  830. @@:
  831.         popad
  832.         popfd
  833. ;--------------------------------------
  834. .exit:
  835.         mov     al, 0
  836.         ret
  837. ;-----------------------------------------------------------------------------
  838. align 4
  839. hd_read_dma:
  840.         push    eax
  841.         push    edx
  842.         mov     edx, [dma_hdpos]
  843.         cmp     edx, [hdpos]
  844.         jne     .notread
  845.  
  846.         mov     edx, [dma_cur_sector]
  847.         cmp     eax, edx
  848.         jb      .notread
  849.  
  850.         add     edx, 15
  851.         cmp     [esp+4], edx
  852.         ja      .notread
  853.  
  854.         mov     eax, [esp+4]
  855.         sub     eax, [dma_cur_sector]
  856.         shl     eax, 9
  857.         add     eax, (OS_BASE+IDE_DMA)
  858.  
  859.         push    ecx esi
  860.         mov     esi, eax
  861.         mov     ecx, 512/4
  862.         cld
  863.         rep movsd
  864.         pop     esi ecx
  865.  
  866.         pop     edx
  867.         pop     eax
  868.         ret
  869. ;--------------------------------------
  870. .notread:
  871. ; set data for PRD Table
  872.         mov     eax, IDE_descriptor_table
  873.         mov     dword [eax], IDE_DMA
  874.         mov     word [eax+4], 0x2000
  875.         sub     eax, OS_BASE
  876. ; select controller Primary or Secondary
  877.         mov     ecx, [IDE_controller_pointer]
  878.         mov     dx, [ecx+IDE_DATA.RegsBaseAddres]
  879.  
  880.         push    eax
  881.         mov     eax, [hdpos]
  882.         dec     eax
  883.         test    eax, 10b
  884.         pop     eax
  885.         jz      @f
  886.  
  887.         add     edx, 8
  888. ;--------------------------------------
  889. @@:
  890.         push    edx
  891. ; Bus Master IDE PRD Table Address
  892.         add     edx, 4
  893. ; save IDE_descriptor_table
  894.         out     dx, eax
  895.         pop     edx
  896. ; clear Bus Master IDE Command register
  897.         mov     al, 0
  898.         out     dx, al
  899. ; clear Bus Master IDE Status register
  900. ; clear Error bit and Interrupt bit
  901.         add     edx, 2
  902.         mov     al, 6 ; 110b
  903.         out     dx, al
  904. ; Select the desired drive
  905.         mov     edx, [hdbase]
  906.         add     edx, 6   ; адрес регистра головок
  907.         mov     al, byte [hdid]
  908.         add     al, 128+64+32
  909.         out     dx, al ; номер головки/номер диска
  910.  
  911.         call    wait_for_hd_idle
  912.  
  913.         cmp     [hd_error], 0
  914.         jnz     hd_read_error
  915. ; ATA with 28 or 48 bit for sector number?
  916.         mov     eax, [esp+4]
  917. ; -10h because the PreCache hits the boundary between lba28 and lba48
  918. ; 10h = 16  - size of PreCache
  919.         cmp     eax, 0x10000000-10h
  920.         jae     .lba48
  921. ;--------------------------------------
  922. .lba28:
  923.         pushfd
  924.         cli
  925.         xor     eax, eax
  926.         mov     edx, [hdbase]
  927.         inc     edx
  928.         out     dx, al ; ATA Features регистр "особенностей"
  929.         inc     edx
  930.         mov     eax, 10h ; Sector Counter = 16 ; PreCache
  931.         out     dx, al ; ATA Sector Counter счётчик секторов
  932.         inc     edx
  933.         mov     eax, [esp+4+4]
  934.         out     dx, al ; LBA Low LBA (7:0)
  935.         shr     eax, 8
  936.         inc     edx
  937.         out     dx, al ; LBA Mid LBA (15:8)
  938.         shr     eax, 8
  939.         inc     edx
  940.         out     dx, al ; LBA High LBA (23:16)
  941.         shr     eax, 8
  942.         inc     edx
  943.         and     al, 0xF ; LBA (27:24)
  944.         add     al, byte [hdid]
  945.         add     al, 11100000b
  946.         out     dx, al ; номер головки/номер диска
  947.         inc     edx
  948.         mov     al, 0xC8 ; READ DMA
  949.         out     dx, al ; ATACommand регистр команд
  950.         jmp     .continue
  951. ;--------------------------------------
  952. .lba48:
  953.         pushfd
  954.         cli
  955.         xor     eax, eax
  956.         mov     edx, [hdbase]
  957.         inc     edx
  958.         out     dx, al ; Features Previous Reserved
  959.         out     dx, al ; Features Current Reserved
  960.         inc     edx
  961.         out     dx, al ; Sector Count Previous Sector count (15:8)
  962.         mov     eax, 10h ; Sector Counter = 16 PreCache
  963.         out     dx, al ; Sector Count Current Sector count (7:0)
  964.         inc     edx
  965.         mov     eax, [esp+4+4]
  966.         rol     eax, 8
  967.         out     dx, al ; LBA Low Previous LBA (31:24)
  968.         xor     eax, eax ; because only 32 bit cache
  969.         inc     edx
  970.         out     dx, al ; LBA Mid Previous LBA (39:32)
  971.         inc     edx
  972.         out     dx, al ; LBA High Previous LBA (47:40)
  973.         sub     edx, 2
  974.         mov     eax, [esp+4+4]
  975.         out     dx, al ; LBA Low Current LBA (7:0)
  976.         shr     eax, 8
  977.         inc     edx
  978.         out     dx, al ; LBA Mid Current LBA (15:8)
  979.         shr     eax, 8
  980.         inc     edx
  981.         out     dx, al ; LBA High Current LBA (23:16)
  982.         inc     edx
  983.         mov     al, byte [hdid]
  984.         add     al, 128+64+32
  985.         out     dx, al ; номер головки/номер диска
  986.         inc     edx
  987.         mov     al, 25h ; READ DMA EXT
  988.         out     dx, al ; ATACommand регистр команд
  989. ;--------------------------------------
  990. .continue:
  991. ; select controller Primary or Secondary
  992.         mov     ecx, [IDE_controller_pointer]
  993.         mov     dx, [ecx+IDE_DATA.RegsBaseAddres]
  994.  
  995.         mov     eax, [hdpos]
  996.         dec     eax
  997.         test    eax, 10b
  998.         jz      @f
  999.  
  1000.         add     dx, 8
  1001. ;--------------------------------------
  1002. @@:
  1003. ; set write to memory and Start Bus Master
  1004.         mov     al, 9
  1005.         out     dx, al
  1006.  
  1007.         mov     eax, [hdpos]
  1008.         dec     eax
  1009.         test    eax, 10b
  1010.         jnz     .ide1
  1011.  
  1012.         mov     [IDE_common_irq_param], irq14_num
  1013.         jmp     @f
  1014. ;--------------------------------------
  1015. .ide1:
  1016.         mov     [IDE_common_irq_param], irq15_num
  1017. ;--------------------------------------
  1018. @@:
  1019.         popfd
  1020. ; wait for interrupt
  1021.         mov     eax, [hdpos]
  1022.         dec     eax
  1023.         test    eax, 10b
  1024.         jnz     .wait_ide1
  1025.  
  1026.         call    wait_for_sector_dma_ide0
  1027.         jmp     @f
  1028. ;--------------------------------------
  1029. .wait_ide1:
  1030.         call    wait_for_sector_dma_ide1
  1031. ;--------------------------------------
  1032. @@:
  1033.         cmp     [hd_error], 0
  1034.         jnz     hd_read_error
  1035.  
  1036.         mov     eax, [hdpos]
  1037.         mov     [dma_hdpos], eax
  1038.         pop     edx
  1039.         pop     eax
  1040.  
  1041.         mov     [dma_cur_sector], eax
  1042.         jmp     hd_read_dma
  1043. ;-----------------------------------------------------------------------------
  1044. cache_write_dma:
  1045.         mov     eax, [cache_chain_ptr] ; for what?
  1046.         push    esi
  1047. ; set data for PRD Table
  1048.         mov     eax, IDE_descriptor_table
  1049.         mov     edx, eax
  1050.  
  1051.         pusha
  1052.         mov     edi, (OS_BASE+IDE_DMA)
  1053.         mov     dword [edx], IDE_DMA
  1054.         movzx   ecx, [cache_chain_size]
  1055.         shl     ecx, 9
  1056.         mov     word [edx+4], cx
  1057.         shr     ecx, 2
  1058.         cld
  1059.         rep movsd
  1060.         popa
  1061.  
  1062.         sub     eax, OS_BASE
  1063. ; select controller Primary or Secondary
  1064.         mov     ecx, [IDE_controller_pointer]
  1065.         mov     dx, [ecx+IDE_DATA.RegsBaseAddres]
  1066.  
  1067.         push    eax
  1068.         mov     eax, [hdpos]
  1069.         dec     eax
  1070.         test    eax, 10b
  1071.         pop     eax
  1072.         jz      @f
  1073.  
  1074.         add     edx, 8
  1075. ;--------------------------------------
  1076. @@:
  1077.         push    edx
  1078. ; Bus Master IDE PRD Table Address
  1079.         add     edx, 4
  1080. ; save IDE_descriptor_table
  1081.         out     dx, eax
  1082.         pop     edx
  1083. ; clear Bus Master IDE Command register
  1084.         mov     al, 0
  1085.         out     dx, al
  1086. ; clear Bus Master IDE Status register
  1087. ; clear Error bit and Interrupt bit
  1088.         add     edx, 2
  1089.         mov     al, 6
  1090.         out     dx, al
  1091. ; Select the desired drive
  1092.         mov     edx, [hdbase]
  1093.         add     edx, 6   ; адрес регистра головок
  1094.         mov     al, byte [hdid]
  1095.         add     al, 128+64+32
  1096.         out     dx, al ; номер головки/номер диска
  1097.  
  1098.         call    wait_for_hd_idle
  1099.  
  1100.         cmp     [hd_error], 0
  1101.         jnz     hd_write_error_dma
  1102. ; ATA with 28 or 48 bit for sector number?
  1103.         mov     esi, [cache_chain_ptr]
  1104.         mov     eax, [esi]
  1105. ; -40h because the PreCache hits the boundary between lba28 and lba48
  1106. ; 40h = 64  - the maximum number of sectors to be written for one command
  1107.         cmp     eax, 0x10000000-40h
  1108.         jae     .lba48
  1109. ;--------------------------------------
  1110. .lba28:
  1111.         pushfd
  1112.         cli
  1113.         xor     eax, eax
  1114.         mov     edx, [hdbase]
  1115.         inc     edx
  1116.         out     dx, al ; ATA Features регистр "особенностей"
  1117.         inc     edx
  1118.         mov     al, [cache_chain_size] ; Sector Counter
  1119.         out     dx, al ; ATA Sector Counter счётчик секторов
  1120.         inc     edx
  1121.         mov     eax, [esi]
  1122.         out     dx, al ; LBA Low LBA (7:0)
  1123.         shr     eax, 8
  1124.         inc     edx
  1125.         out     dx, al ; LBA Mid LBA (15:8)
  1126.         shr     eax, 8
  1127.         inc     edx
  1128.         out     dx, al ; LBA High LBA (23:16)
  1129.         shr     eax, 8
  1130.         inc     edx
  1131.         and     al, 0xF ; LBA (27:24)
  1132.         add     al, byte [hdid]
  1133.         add     al, 11100000b
  1134.         out     dx, al ; номер головки/номер диска
  1135.         inc     edx
  1136.         mov     al, 0xCA ; WRITE DMA
  1137.         out     dx, al ; ATACommand регистр команд
  1138.         jmp     .continue
  1139. ;--------------------------------------
  1140. .lba48:
  1141.         pushfd
  1142.         cli
  1143.         xor     eax, eax
  1144.         mov     edx, [hdbase]
  1145.         inc     edx
  1146.         out     dx, al ; Features Previous Reserved
  1147.         out     dx, al ; Features Current Reserved
  1148.         inc     edx
  1149.         out     dx, al ; Sector Count Previous Sector count (15:8)
  1150.         mov     al, [cache_chain_size] ; Sector Counter
  1151.         out     dx, al ; Sector Count Current Sector count (7:0)
  1152.         inc     edx
  1153.         mov     eax, [esi]
  1154.         rol     eax, 8
  1155.         out     dx, al ; LBA Low Previous LBA (31:24)
  1156.         xor     eax, eax ; because only 32 bit cache
  1157.         inc     edx
  1158.         out     dx, al ; LBA Mid Previous LBA (39:32)
  1159.         inc     edx
  1160.         out     dx, al ; LBA High Previous LBA (47:40)
  1161.         sub     edx, 2
  1162.         mov     eax, [esi]
  1163.         out     dx, al ; LBA Low Current LBA (7:0)
  1164.         shr     eax, 8
  1165.         inc     edx
  1166.         out     dx, al ; LBA Mid Current LBA (15:8)
  1167.         shr     eax, 8
  1168.         inc     edx
  1169.         out     dx, al ; LBA High Current LBA (23:16)
  1170.         inc     edx
  1171.         mov     al, byte [hdid]
  1172.         add     al, 128+64+32
  1173.         out     dx, al ; номер головки/номер диска
  1174.         inc     edx
  1175.         mov     al, 35h ; WRITE DMA EXT
  1176.         out     dx, al ; ATACommand регистр команд
  1177. ;--------------------------------------
  1178. .continue:
  1179. ; select controller Primary or Secondary
  1180.         mov     ecx, [IDE_controller_pointer]
  1181.         mov     dx, [ecx+IDE_DATA.RegsBaseAddres]
  1182.  
  1183.         mov     eax, [hdpos]
  1184.         dec     eax
  1185.         test    eax, 10b
  1186.         jz      @f
  1187.  
  1188.         add     dx, 8
  1189. ;--------------------------------------
  1190. @@:
  1191. ; set write to device and Start Bus Master
  1192.         mov     al, 1
  1193.         out     dx, al
  1194.  
  1195.         mov     eax, [hdpos]
  1196.         dec     eax
  1197.         test    eax, 10b
  1198.         jnz     .ide1
  1199.  
  1200.         mov     [IDE_common_irq_param], irq14_num
  1201.         jmp     @f
  1202. ;--------------------------------------
  1203. .ide1:
  1204.         mov     [IDE_common_irq_param], irq15_num
  1205. ;--------------------------------------
  1206. @@:
  1207.         popfd
  1208. ; wait for interrupt
  1209.         mov     [dma_cur_sector], not 0x40
  1210.  
  1211.         mov     eax, [hdpos]
  1212.         dec     eax
  1213.         test    eax, 10b
  1214.         jnz     .wait_ide1
  1215.  
  1216.         call    wait_for_sector_dma_ide0
  1217.  
  1218.         jmp     @f
  1219. ;--------------------------------------
  1220. .wait_ide1:
  1221.         call    wait_for_sector_dma_ide1
  1222. ;--------------------------------------
  1223. @@:
  1224.         cmp     [hd_error], 0
  1225.         jnz     hd_write_error_dma
  1226.         pop     esi
  1227.         ret
  1228. ;-----------------------------------------------------------------------------
  1229. proc clear_pci_ide_interrupts
  1230.         mov     esi, pcidev_list
  1231. ;--------------------------------------
  1232. align 4
  1233. .loop:
  1234.         mov     esi, [esi+PCIDEV.fd]
  1235.         cmp     esi, pcidev_list
  1236.         jz      .done
  1237.  
  1238. ;        cmp     [esi+PCIDEV.class], 0x01018F
  1239.         mov     eax, [esi+PCIDEV.class]
  1240.         shr     eax, 4
  1241.         cmp     eax, 0x01018
  1242.         jnz     .loop
  1243.  
  1244.         mov     ah, [esi+PCIDEV.bus]
  1245.         mov     al, 2
  1246.         mov     bh, [esi+PCIDEV.devfn]
  1247.         mov     bl, 0x20
  1248.         call    pci_read_reg
  1249.  
  1250.         and     eax, 0FFFCh
  1251.         mov     edx, eax
  1252.         add     edx, 2
  1253.         in      al, dx
  1254.         DEBUGF 1,'K : clear_pci_ide_interrupts: port[%x] = %x ',dx,al
  1255.         out     dx, al
  1256.         in      al, dx
  1257.         DEBUGF 1,'-> %x; ',al
  1258.         add     edx, 8
  1259.         in      al, dx
  1260.         DEBUGF 1,'port[%x] = %x ',dx,al
  1261.         out     dx, al
  1262.         in      al, dx
  1263.         DEBUGF 1,'-> %x\n',al
  1264.         jmp     .loop
  1265. ;--------------------------------------
  1266. .done:
  1267.         ret
  1268. endp
  1269. ;-----------------------------------------------------------------------------
  1270.