Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 5569 $
  9.  
  10. ; HDD driver
  11.  
  12. struct HD_DATA
  13. hdbase  dd      ?
  14. hdid    dd      ?
  15. hdpos   dd      ?
  16. ends
  17. ;-----------------------------------------------------------------
  18. iglobal
  19. align 4
  20. ide_callbacks:
  21.         dd      ide_callbacks.end - ide_callbacks   ; strucsize
  22.         dd      0   ; no close function
  23.         dd      0   ; no closemedia function
  24.         dd      ide_querymedia
  25.         dd      ide_read
  26.         dd      ide_write
  27.         dd      0   ; no flush function
  28.         dd      0   ; use default cache size
  29. .end:
  30.  
  31. hd0_data        HD_DATA         ?,    0, 1
  32. hd1_data        HD_DATA         ?, 0x10, 2
  33. hd2_data        HD_DATA         ?,    0, 3
  34. hd3_data        HD_DATA         ?, 0x10, 4
  35. hd4_data        HD_DATA         ?,    0, 5
  36. hd5_data        HD_DATA         ?, 0x10, 6
  37. hd6_data        HD_DATA         ?,    0, 7
  38. hd7_data        HD_DATA         ?, 0x10, 8
  39. hd8_data        HD_DATA         ?,    0, 9
  40. hd9_data        HD_DATA         ?, 0x10, 10
  41. hd10_data       HD_DATA         ?,    0, 11
  42. hd11_data       HD_DATA         ?, 0x10, 12
  43.  
  44. ide_mutex_table:
  45.         dd ide_channel1_mutex
  46.         dd ide_channel2_mutex
  47.         dd ide_channel3_mutex
  48.         dd ide_channel4_mutex
  49.         dd ide_channel5_mutex
  50.         dd ide_channel6_mutex
  51. endg
  52. ;-----------------------------------------------------------------
  53. uglobal
  54. ide_mutex               MUTEX
  55. ide_channel1_mutex      MUTEX
  56. ide_channel2_mutex      MUTEX
  57. ide_channel3_mutex      MUTEX
  58. ide_channel4_mutex      MUTEX
  59. ide_channel5_mutex      MUTEX
  60. ide_channel6_mutex      MUTEX
  61. blockSize:
  62. rb 4
  63. sector:
  64. rb 6
  65. allow_dma_access        db ?
  66. IDE_common_irq_param    db ?
  67. eventPointer            dd ?
  68. eventID                 dd ?
  69. endg
  70. ;-----------------------------------------------------------------
  71. proc ide_read stdcall uses esi edi ebx, \
  72.         hd_data, buffer, startsector:qword, numsectors
  73.         ; hd_data = pointer to hd*_data
  74.         ; buffer = pointer to buffer for data
  75.         ; startsector = 64-bit start sector
  76.         ; numsectors = pointer to number of sectors on input,
  77.         ;  must be filled with number of sectors really read
  78. locals
  79. sectors_todo    dd      ?
  80. channel_lock    dd      ?
  81. endl
  82. ; get number of requested sectors and say that no sectors were read yet
  83.         mov     ecx, [numsectors]
  84.         mov     eax, [ecx]
  85.         mov     dword [ecx], 0
  86.         mov     [sectors_todo], eax
  87. ; acquire the global lock
  88.         mov     ecx, ide_mutex
  89.         call    mutex_lock
  90.         mov     ecx, [hd_data]
  91.         mov     ecx, [ecx+HD_DATA.hdpos]
  92.         dec     ecx
  93.         shr     ecx, 1
  94.         shl     ecx, 2
  95.         mov     ecx, [ecx + ide_mutex_table]
  96.         mov     [channel_lock], ecx
  97.         call    mutex_lock
  98. ; prepare worker procedures variables
  99.         mov     ecx, [hd_data]
  100.         mov     eax, [ecx+HD_DATA.hdbase]
  101.         mov     [hdbase], eax
  102.         mov     eax, [ecx+HD_DATA.hdid]
  103.         mov     [hdid], eax
  104.         mov     eax, [ecx+HD_DATA.hdpos]
  105.         mov     [hdpos], eax
  106.         mov     eax, dword [startsector]
  107.         mov     [sector], eax
  108.         mov     ax, word [startsector+4]
  109.         mov     [sector+4], ax
  110.         mov     esi, [buffer]
  111.         mov     bl, 25h     ; READ DMA EXT
  112.         mov     ecx, [hdpos]
  113.         dec     ecx
  114.         shr     ecx, 2
  115.         imul    ecx, sizeof.IDE_DATA
  116.         add     ecx, IDE_controller_1
  117.         mov     [IDE_controller_pointer], ecx
  118.         mov     eax, [hdpos]
  119.         dec     eax
  120.         and     eax, 11b
  121.         shr     eax, 1
  122.         add     eax, ecx
  123.         cmp     [eax+IDE_DATA.dma_hdd_channel_1], 1
  124.         jz      .next
  125.         dec     bl      ; READ SECTOR(S) EXT
  126.         mov     edi, esi
  127. ; worker procedures take max 8000h sectors per time
  128. ; loop until all sectors will be processed
  129. .next:
  130.         mov     ecx, 8000h
  131.         cmp     ecx, [sectors_todo]
  132.         jbe     @f
  133.         mov     ecx, [sectors_todo]
  134. @@:
  135.         mov     [blockSize], ecx
  136.         push    ecx
  137.         call    IDE_transfer
  138.         pop     ecx
  139.         jc      .out
  140.         mov     eax, [numsectors]
  141.         add     [eax], ecx
  142.         sub     [sectors_todo], ecx
  143.         jz      .out
  144.         add     [sector], ecx
  145.         adc     word [sector+4], 0
  146.         jmp     .next
  147. ; loop is done, either due to error or because everything is done
  148. ; release the global lock and return the corresponding status
  149. .out:
  150.         sbb     eax, eax
  151.         push    eax
  152.         mov     ecx, [channel_lock]
  153.         call    mutex_unlock
  154.         mov     ecx, ide_mutex
  155.         call    mutex_unlock
  156.         pop     eax
  157.         ret
  158. endp
  159. ;-----------------------------------------------------------------
  160. proc ide_write stdcall uses esi edi ebx, \
  161.         hd_data, buffer, startsector:qword, numsectors
  162.         ; hd_data = pointer to hd*_data
  163.         ; buffer = pointer to buffer with data
  164.         ; startsector = 64-bit start sector
  165.         ; numsectors = pointer to number of sectors on input,
  166.         ;  must be filled with number of sectors really written
  167. locals
  168. sectors_todo    dd      ?
  169. channel_lock    dd      ?
  170. endl
  171. ; get number of requested sectors and say that no sectors were read yet
  172.         mov     ecx, [numsectors]
  173.         mov     eax, [ecx]
  174.         mov     dword [ecx], 0
  175.         mov     [sectors_todo], eax
  176. ; acquire the global lock
  177.         mov     ecx, ide_mutex
  178.         call    mutex_lock
  179.         mov     ecx, [hd_data]
  180.         mov     ecx, [ecx+HD_DATA.hdpos]
  181.         dec     ecx
  182.         shr     ecx, 1
  183.         shl     ecx, 2
  184.         mov     ecx, [ecx + ide_mutex_table]
  185.         mov     [channel_lock], ecx
  186.         call    mutex_lock
  187. ; prepare worker procedures variables
  188.         mov     ecx, [hd_data]
  189.         mov     eax, [ecx+HD_DATA.hdbase]
  190.         mov     [hdbase], eax
  191.         mov     eax, [ecx+HD_DATA.hdid]
  192.         mov     [hdid], eax
  193.         mov     eax, [ecx+HD_DATA.hdpos]
  194.         mov     [hdpos], eax
  195.         mov     eax, dword [startsector]
  196.         mov     [sector], eax
  197.         mov     ax, word [startsector+4]
  198.         mov     [sector+4], ax
  199.         mov     esi, [buffer]
  200.         mov     bl, 35h     ; WRITE DMA EXT
  201.         mov     ecx, [hdpos]
  202.         dec     ecx
  203.         shr     ecx, 2
  204.         imul    ecx, sizeof.IDE_DATA
  205.         add     ecx, IDE_controller_1
  206.         mov     [IDE_controller_pointer], ecx
  207.         mov     eax, [hdpos]
  208.         dec     eax
  209.         and     eax, 11b
  210.         shr     eax, 1
  211.         add     eax, ecx
  212.         cmp     [eax+IDE_DATA.dma_hdd_channel_1], 1
  213.         jz      .next
  214.         dec     bl      ; WRITE SECTOR(S) EXT
  215. ; worker procedures take max 8000h sectors per time
  216. ; loop until all sectors will be processed
  217. .next:
  218.         mov     ecx, 8000h
  219.         cmp     ecx, [sectors_todo]
  220.         jbe     @f
  221.         mov     ecx, [sectors_todo]
  222. @@:
  223.         mov     [blockSize], ecx
  224.         push    ecx
  225.         call    IDE_transfer
  226.         pop     ecx
  227.         jc      .out
  228.         mov     eax, [numsectors]
  229.         add     [eax], ecx
  230.         sub     [sectors_todo], ecx
  231.         jz      .out
  232.         add     [sector], ecx
  233.         adc     word [sector+4], 0
  234.         jmp     .next
  235. ; loop is done, either due to error or because everything is done
  236. ; release the global lock and return the corresponding status
  237. .out:
  238.         sbb     eax, eax
  239.         push    eax
  240.         mov     ecx, [channel_lock]
  241.         call    mutex_unlock
  242.         mov     ecx, ide_mutex
  243.         call    mutex_unlock
  244.         pop     eax
  245.         ret
  246. endp
  247. ;-----------------------------------------------------------------
  248. ; this is a stub
  249. proc ide_querymedia stdcall, hd_data, mediainfo
  250.         mov     eax, [mediainfo]
  251.         mov     [eax+DISKMEDIAINFO.Flags], 0
  252.         mov     [eax+DISKMEDIAINFO.SectorSize], 512
  253.         or      dword [eax+DISKMEDIAINFO.Capacity], 0xFFFFFFFF
  254.         or      dword [eax+DISKMEDIAINFO.Capacity+4], 0xFFFFFFFF
  255.         xor     eax, eax
  256.         ret
  257. endp
  258. ;-----------------------------------------------------------------
  259. ; input: esi -> buffer, bl = command, [sector], [blockSize]
  260. ; output: esi -> next block in buffer
  261. ; for pio read esi equal edi
  262. IDE_transfer:
  263.         mov     edx, [hdbase]
  264.         add     edx, 6
  265.         mov     al, byte [hdid]
  266.         add     al, 224
  267.         out     dx, al  ; select the desired drive
  268.         call    save_hd_wait_timeout
  269.         inc     edx
  270. @@:
  271.         call    check_hd_wait_timeout
  272.         jc      .hd_error
  273.         in      al, dx
  274.         test    al, 128 ; ready for command?
  275.         jnz     @b
  276.         pushfd          ; fill the ports
  277.         cli
  278.         mov     edx, [hdbase]
  279.         inc     edx
  280.         inc     edx
  281.         mov     al, [blockSize+1]
  282.         out     dx, al  ; Sector count (15:8)
  283.         inc     edx
  284.         mov     eax, [sector+3]
  285.         out     dx, al  ; LBA (31:24)
  286.         inc     edx
  287.         shr     eax, 8
  288.         out     dx, al  ; LBA (39:32)
  289.         inc     edx
  290.         shr     eax, 8
  291.         out     dx, al  ; LBA (47:40)
  292.         sub     edx, 3
  293.         mov     al, [blockSize]
  294.         out     dx, al  ; Sector count (7:0)
  295.         inc     edx
  296.         mov     eax, [sector]
  297.         out     dx, al  ; LBA (7:0)
  298.         inc     edx
  299.         shr     eax, 8
  300.         out     dx, al  ; LBA (15:8)
  301.         inc     edx
  302.         shr     eax, 8
  303.         out     dx, al  ; LBA (23:16)
  304.         inc     edx
  305.         mov     al, byte [hdid]
  306.         add     al, 224
  307.         out     dx, al
  308.         test    bl, 1
  309.         jz      .PIO
  310. ; DMA
  311.         mov     dword [esp], 0x1000
  312.         call    kernel_alloc
  313.         mov     edi, eax
  314.         push    eax
  315.         shl     dword [blockSize], 9
  316.         mov     eax, esi
  317.         add     eax, [blockSize]
  318.         push    eax
  319. ; check buffer pages physical addresses and fill the scatter-gather list
  320. ; buffer may be not aligned and may have size not divisible by page size
  321. ; [edi] = block physical address, [edi+4] = block size in bytes
  322. ; block addresses can not cross 10000h borders
  323.         mov     ecx, esi
  324.         and     ecx, 0xFFF
  325.         jz      .aligned
  326.         mov     eax, esi
  327.         call    get_pg_addr
  328.         add     eax, ecx
  329.         neg     ecx
  330.         add     ecx, 0x1000
  331.         mov     [edi], eax
  332.         cmp     ecx, [blockSize]
  333.         jnc     .end
  334.         mov     [edi+4], ecx
  335.         add     esi, 0x1000
  336.         add     edi, 8
  337.         sub     [blockSize], ecx
  338. .aligned:
  339.         mov     eax, esi
  340.         call    get_pg_addr
  341.         mov     ecx, eax
  342.         mov     [edi], eax
  343.         and     ecx, 0xFFFF
  344.         neg     ecx
  345.         add     ecx, 0x10000
  346.         cmp     [blockSize], ecx
  347.         jnc     @f
  348.         mov     ecx, [blockSize]
  349.         and     ecx, 0xF000
  350.         jz      .end
  351. @@:
  352.         push    ecx
  353. @@:
  354.         add     esi, 0x1000
  355.         add     eax, 0x1000
  356.         sub     ecx, 0x1000
  357.         jz      @f
  358.         mov     edx, eax
  359.         mov     eax, esi
  360.         call    get_pg_addr
  361.         cmp     eax, edx
  362.         jz      @b
  363. @@:
  364.         pop     edx
  365.         sub     edx, ecx
  366.         mov     [edi+4], edx
  367.         add     edi, 8
  368.         sub     [blockSize], edx
  369.         jnz     .aligned
  370.         sub     edi, 8
  371.         jmp     @f
  372. .end:
  373.         mov     ecx, [blockSize]
  374.         mov     [edi+4], ecx
  375. @@:
  376.         mov     byte [edi+7], 80h   ; list end
  377.         pop     esi
  378.         pop     edi
  379. ; select controller Primary or Secondary
  380.         mov     ecx, [IDE_controller_pointer]
  381.         mov     dx, [ecx+IDE_DATA.RegsBaseAddres]
  382.         mov     eax, [hdpos]
  383.         dec     eax
  384.         test    eax, 10b
  385.         jz      @f
  386.         add     edx, 8
  387. @@:
  388.         add     edx, 2      ; Bus Master IDE Status register
  389.         mov     al, 6
  390.         out     dx, al      ; clear Error bit and Interrupt bit
  391.  
  392.         add     edx, 2      ; Bus Master IDE PRD Table Address
  393.         mov     eax, edi
  394.         call    get_pg_addr
  395.         out     dx, eax     ; send scatter-gather list physical address
  396.  
  397.         push    edx
  398.         mov     edx, [hdbase]
  399.         add     edx, 7      ; ATACommand
  400.         mov     al, bl
  401.         out     dx, al      ; Start hard drive
  402.         pop     edx
  403.  
  404.         sub     edx, 4      ; Bus Master IDE Command register
  405.         mov     al, 1       ; set direction
  406.         cmp     bl, 35h     ; write
  407.         jz      @f
  408.         add     al, 8       ; read
  409. @@:
  410.         out     dx, al      ; Start Bus Master
  411.         mov     [IDE_common_irq_param], 14
  412.         mov     eax, [hdpos]
  413.         dec     eax
  414.         test    eax, 10b
  415.         jz      @f
  416.         inc     [IDE_common_irq_param]
  417. @@:
  418.         push    edi esi ebx
  419.         xor     ecx, ecx
  420.         xor     esi, esi
  421.         call    create_event
  422.         mov     [eventPointer], eax
  423.         mov     [eventID], edx
  424.         sti
  425.         mov     ebx, edx
  426.         mov     ecx, 300
  427.         call    wait_event_timeout
  428.         test    eax, eax
  429.         jnz     @f
  430.         mov     [IDE_common_irq_param], 0
  431.         mov     eax, [eventPointer]
  432.         mov     ebx, [eventID]
  433.         call    destroy_event
  434.         mov     [eventPointer], 0
  435. @@:
  436.         pop     ebx esi
  437.         call    kernel_free
  438.         cmp     [eventPointer], 0
  439.         jz      .hd_error
  440.         ret
  441. .PIO:
  442.         inc     edx     ; ATACommand
  443.         mov     al, bl
  444.         out     dx, al  ; Start hard drive
  445.         popfd
  446. .sectorTransfer:
  447.         call    save_hd_wait_timeout
  448.         in      al, dx
  449.         in      al, dx
  450.         in      al, dx
  451.         in      al, dx
  452. @@:
  453.         call    check_hd_wait_timeout
  454.         jc      .hd_error
  455.         in      al, dx
  456.         test    al, 8   ; ready for transfer?
  457.         jz      @b
  458.         cmp     [hd_setup], 1   ; do not mark error for setup request
  459.         jz      @f
  460.         test    al, 1   ; previous command ended up with an error
  461.         jnz     .hd_error
  462. @@:
  463.         pushfd
  464.         cli
  465.         cld
  466.         mov     ecx, 256
  467.         mov     edx, [hdbase]
  468.         cmp     bl, 34h
  469.         jz      .write
  470.         rep insw
  471.         jmp     @f
  472. .write:
  473.         rep outsw
  474. @@:
  475.         popfd
  476.         add     edx, 7
  477.         dec     dword [blockSize]
  478.         jnz     .sectorTransfer
  479.         ret
  480. .hd_error:
  481.         cmp     bl, 30h
  482.         jnc     hd_write_error
  483. ;-----------------------------------------------------------------
  484. hd_read_error:
  485.         if lang eq sp
  486.         DEBUGF 1,"K : FS - HD error de lectura\n"
  487.         else
  488.         DEBUGF 1,"K : FS - HD read error\n"
  489.         end if
  490.         stc
  491.         ret
  492. ;-----------------------------------------------------------------
  493. hd_write_error:
  494.         if lang eq sp
  495.         DEBUGF 1,"K : FS - HD error de escritura\n"
  496.         else
  497.         DEBUGF 1,"K : FS - HD write error\n"
  498.         end if
  499.         stc
  500.         ret
  501. ;-----------------------------------------------------------------
  502. save_hd_wait_timeout:
  503.         mov     eax, [timer_ticks]
  504.         add     eax, 300        ; 3 sec timeout
  505.         mov     [hd_wait_timeout], eax
  506.         ret
  507. ;-----------------------------------------------------------------
  508. check_hd_wait_timeout:
  509.         mov     eax, [timer_ticks]
  510.         cmp     [hd_wait_timeout], eax
  511.         jc      @f
  512.         ret
  513. @@:
  514.         if lang eq sp
  515.         DEBUGF 1,"K : FS - HD tiempo de espera agotado\n"
  516.         else
  517.         DEBUGF 1,"K : FS - HD timeout\n"
  518.         end if
  519.         stc
  520.         ret
  521. ;-----------------------------------------------------------------
  522. align 4
  523. IDE_irq_14_handler:
  524. IDE_irq_15_handler:
  525. IDE_common_irq_handler:
  526. ; DEBUGF  1, 'K : IDE_irq_handler %x\n', [IDE_common_irq_param]:2
  527.         cmp     [IDE_common_irq_param], 0
  528.         jz      .exit
  529.         pushfd
  530.         cli
  531.         pushad
  532.         mov     ecx, [IDE_controller_pointer]
  533.         mov     dx, [ecx+IDE_DATA.RegsBaseAddres]
  534.         cmp     [IDE_common_irq_param], 14
  535.         jz      @f
  536.         add     dx, 8
  537. @@:
  538.         add     edx, 2  ; Bus Master IDE Status register
  539.         in      al, dx
  540.         test    al, 4
  541.         jz      @f
  542.         mov     [IDE_common_irq_param], 0
  543.         out     dx, al  ; clear Interrupt bit
  544.         sub     edx, 2
  545.         xor     eax, eax
  546.         out     dx, al  ; clear Bus Master IDE Command register
  547.         mov     edx, [hdbase]
  548.         add     edx, 7
  549.         in      al, dx  ; read status register
  550.         mov     eax, [eventPointer]
  551.         mov     ebx, [eventID]
  552.         xor     edx, edx
  553.         xor     esi, esi
  554.         call    raise_event
  555.         popad
  556.         popfd
  557.         mov     al, 1   ; remove the interrupt request
  558.         ret
  559. @@:
  560.         popad
  561.         popfd
  562. .exit:
  563.         xor     eax, eax    ; not our interrupt
  564.         ret
  565. ;-----------------------------------------------------------------
  566. proc clear_pci_ide_interrupts
  567.         mov     esi, pcidev_list
  568. align 4
  569. .loop:
  570.         mov     esi, [esi+PCIDEV.fd]
  571.         cmp     esi, pcidev_list
  572.         jz      .done
  573.  
  574. ;        cmp     [esi+PCIDEV.class], 0x01018F
  575.         mov     eax, [esi+PCIDEV.class]
  576.         shr     eax, 4
  577.         cmp     eax, 0x01018
  578.         jnz     .loop
  579.  
  580.         mov     ah, [esi+PCIDEV.bus]
  581.         mov     al, 2
  582.         mov     bh, [esi+PCIDEV.devfn]
  583.         mov     bl, 0x20
  584.         call    pci_read_reg
  585.  
  586.         and     eax, 0FFFCh
  587.         mov     edx, eax
  588.         add     edx, 2
  589.         in      al, dx
  590.         DEBUGF 1,'K : clear_pci_ide_interrupts: port[%x] = %x ',dx,al
  591.         out     dx, al
  592.         in      al, dx
  593.         DEBUGF 1,'-> %x; ',al
  594.         add     edx, 8
  595.         in      al, dx
  596.         DEBUGF 1,'port[%x] = %x ',dx,al
  597.         out     dx, al
  598.         in      al, dx
  599.         DEBUGF 1,'-> %x\n',al
  600.         jmp     .loop
  601. .done:
  602.         ret
  603. endp
  604.