Subversion Repositories Kolibri OS

Rev

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