Subversion Repositories Kolibri OS

Rev

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