Subversion Repositories Kolibri OS

Rev

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