Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2021. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision$
  9.  
  10. PCI_REG_STATUS_COMMAND = 0x0004
  11. PCI_REG_BAR5 = 0x0024
  12.  
  13. ; bit_ prefix means that its index of bit
  14. ; format: bit_AHCI_STR_REG_BIT
  15. bit_AHCI_HBA_CAP2_BOH   = 0        ; Supports BIOS/OS Handoff
  16.  
  17. bit_AHCI_HBA_BOHC_BOS  = 0         ; BIOS-Owned Semaphore (BIOS owns controller)
  18. bit_AHCI_HBA_BOHC_OOS  = 1         ; OS-Owned Semaphore (OS owns controller)
  19. bit_AHCI_HBA_BOHC_BB   = 4         ; BIOS Busy (polling bit while BIOS cleans up
  20.  
  21. bit_AHCI_HBA_GHC_AHCI_ENABLE      = 31  ; Enable AHCI mode
  22. bit_AHCI_HBA_GHC_RESET            = 0   ; Reset HBA
  23. bit_AHCI_HBA_GHC_INTERRUPT_ENABLE = 1   ; Enable interrupts from the HBA
  24.  
  25. AHCI_HBA_PxSSTS_DET         = 0xF
  26. AHCI_HBA_PORT_IPM_ACTIVE    = 1
  27. AHCI_HBA_PxSSTS_DET_PRESENT = 3
  28.  
  29. AHCI_MAX_PORTS = 32        ;
  30. HBA_MEMORY_SIZE = 0x1100
  31.  
  32. struct AHCI_DATA
  33.         abar    dd ?       ; pointer to HBA Memory (BAR5) mapped to virtual kernelspace memory
  34.         pcidev  dd ?       ; pointer to corresponding PCIDEV structure
  35. ends
  36.  
  37. ; Generic Host Control registers
  38. struct HBA_MEM
  39.         capability            dd ?                    ; 0x00
  40.         global_host_control   dd ?                    ; 0x04
  41.         interrupt_status      dd ?                    ; 0x08
  42.         port_implemented      dd ?                    ; 0x0C
  43.         version               dd ?                    ; 0x10
  44.         ccc_ctl               dd ?                    ; 0x14, Command completion coalescing control
  45.         ccc_pts               dd ?                    ; 0x18, Command completion coalescing ports
  46.         em_loc                dd ?                    ; 0x1C, Enclosure management location
  47.         em_ctl                dd ?                    ; 0x20, Enclosure management control
  48.         capability2           dd ?                    ; 0x24, Host capabilities extended
  49.         bohc                  dd ?                    ; 0x28, BIOS/OS handoff control and status
  50.         reserved              rb (0xA0-0x2C)          ; 0x2C - 0x9F, Reserved
  51.         vendor                rb (0x100-0xA0)         ; 0xA0 - 0xFF, Vendor specific
  52.         ports                 rb (sizeof.HBA_PORT*AHCI_MAX_PORTS) ; 0x100 - 0x10FF, Port control registers, max AHCI_MAX_PORTS
  53. ends
  54.  
  55. ; Port Control registers
  56. struct HBA_PORT
  57.         command_list_base_l      dd ?                 ; 0x00, command list base address, 1K-byte aligned
  58.         command_list_base_h      dd ?                 ; 0x04, command list base address upper 32 bits, used on 64 bit systems
  59.         fis_base_l               dd ?                 ; 0x08, FIS base address, 256-byte aligned
  60.         fis_base_h               dd ?                 ; 0x0C, FIS base address upper 32 bits, used on 64 bit systems
  61.         interrupt_status         dd ?                 ; 0x10
  62.         interrupt_enable         dd ?                 ; 0x14
  63.         command                  dd ?                 ; 0x18, command and status
  64.         reserved0                dd ?                 ; 0x1C
  65.         task_file_data           dd ?                 ; 0x20
  66.         signature                dd ?                 ; 0x24
  67.         sata_status              dd ?                 ; 0x28, SATA status (SCR0:SStatus)
  68.         sata_control             dd ?                 ; 0x2C, SATA control (SCR2:SControl)
  69.         sata_error               dd ?                 ; 0x30, SATA error (SCR1:SError)
  70.         sata_active              dd ?                 ; 0x34, SATA active (SCR3:SActive)
  71.         command_issue            dd ?                 ; 0x38
  72.         sata_notification        dd ?                 ; 0x3C, SATA notification (SCR4:SNotification)
  73.         fis_based_switch_control dd ?                 ; 0x40
  74.         reserved1                rd 11                ; 0x44 - 0x6F
  75.         vendor                   rd 4                 ; 0x70 - 0x7F, vendor specific
  76. ends
  77.  
  78. uglobal
  79. align 4
  80.         ahci_controller AHCI_DATA
  81. endg
  82.  
  83.  
  84. ; detect ahci controller and initialize
  85. align 4
  86. init_ahci:
  87.         mov     ecx, ahci_controller
  88.         mov     esi, pcidev_list
  89. .find_ahci_ctr:
  90.         mov     esi, [esi + PCIDEV.fd]
  91.         cmp     esi, pcidev_list
  92.         jz      .ahci_ctr_not_found
  93.         mov     eax, [esi + PCIDEV.class]
  94.         ;DEBUGF  1, "K: device class = %x\n", eax
  95.         shr     eax, 8 ; shift right because lowest 8 bits if ProgIf field
  96.         cmp     eax, 0x0106 ; 0x01 - Mass Storage Controller class,  0x06 - Serial ATA Controller subclass
  97.         jz      .ahci_ctr_found
  98.         jmp     .find_ahci_ctr
  99.  
  100. .ahci_ctr_not_found:
  101.         DEBUGF  1, "K: AHCI controller not found\n"
  102.         ret
  103.  
  104. .ahci_ctr_found:
  105.         mov     [ahci_controller + AHCI_DATA.pcidev], esi
  106.  
  107.         mov     eax, [esi+PCIDEV.class]
  108.         movzx   ebx, byte [esi+PCIDEV.bus]
  109.         movzx   ecx, byte [esi+PCIDEV.devfn]
  110.         shr     ecx, 3 ; get rid of 3 lowest bits (function code), the rest bits is device code
  111.         movzx   edx, byte [esi+PCIDEV.devfn]
  112.         and     edx, 00000111b ; get only 3 lowest bits (function code)
  113.         DEBUGF  1, "K: found AHCI controller, (class, subcl, progif) = %x, bus = %x, device = %x, function = %x\n", eax, ebx, ecx, edx
  114.        
  115.         ; get BAR5 value, it is physical address
  116.         movzx   ebx, [esi + PCIDEV.bus]
  117.         movzx   ebp, [esi + PCIDEV.devfn]
  118.         stdcall pci_read32, ebx, ebp, PCI_REG_BAR5
  119.         DEBUGF  1, "K: AHCI controller MMIO = %x\n", eax
  120.         mov     edi, eax
  121.  
  122.         ; get the size of MMIO region
  123.         stdcall pci_write32, ebx, ebp, PCI_REG_BAR5, 0xFFFFFFFF
  124.         stdcall pci_read32, ebx, ebp, PCI_REG_BAR5
  125.         not     eax
  126.         inc     eax
  127.         DEBUGF  1, "K: AHCI: MMIO region size = 0x%x bytes\n", eax
  128.  
  129.         ; Map MMIO region to virtual memory
  130.         stdcall map_io_mem, edi, eax, PG_SWR + PG_NOCACHE
  131.         mov     [ahci_controller + AHCI_DATA.abar], eax
  132.         DEBUGF  1, "K: AHCI controller BAR5 mapped to virtual addr %x\n", eax
  133.  
  134.         ; Restore the original BAR5 value
  135.         stdcall pci_write32, ebx, ebp, PCI_REG_BAR5, edi
  136.  
  137.         ; Enable dma bus mastering, memory space access, clear the "disable interrupts" bit
  138.         ; Usually, it is already done before us
  139.         movzx   ebx, [esi + PCIDEV.bus]
  140.         movzx   ebp, [esi + PCIDEV.devfn]
  141.         stdcall pci_read32, ebx, ebp, PCI_REG_STATUS_COMMAND
  142.         DEBUGF  1, "K: AHCI: pci_status_command = %x\nEnabling interrupts, DMA bus mastering and memory space access\n", eax
  143.         or      eax, 0x06 ; pci.command |= 0x06 (dma bus mastering + memory space access)
  144.         btr     eax, 10 ; clear the "disable interrupts" bit
  145.         DEBUGF  1, "K: AHCI: pci_status_command = %x\n", eax
  146.         stdcall pci_write32, ebx, ebp, PCI_REG_STATUS_COMMAND, eax
  147.  
  148.         ; ; Print some register values to debug board
  149.         ; mov     esi, [ahci_controller + AHCI_DATA.abar]
  150.         ; DEBUGF  1, "K: AHCI: HBA.cap = %x, HBA.ghc = %x, HBA_MEM.version = %x\n", [esi + HBA_MEM.capability], [esi + HBA_MEM.global_host_control], [esi + HBA_MEM.version]
  151.  
  152.         ;-------------------------------------------------------
  153.         ; Request BIOS/OS ownership handoff, if supported. (TODO check correctness)
  154.         mov     esi, [ahci_controller + AHCI_DATA.abar]
  155.         ;mov     ebx, [esi + HBA_MEM.capability2]
  156.         ;DEBUGF  1, "K: AHCI: HBA_MEM.cap2 = %x\n", ebx
  157.         bt      [esi + HBA_MEM.capability2], bit_AHCI_HBA_CAP2_BOH
  158.         jnc     .end_handoff
  159.         DEBUGF  1, "K: AHCI: requesting AHCI ownership change...\n"
  160.         bts     [esi + HBA_MEM.bohc], bit_AHCI_HBA_BOHC_OOS
  161.  
  162. .wait_not_bos:
  163.         bt      [esi + HBA_MEM.bohc], bit_AHCI_HBA_BOHC_BOS
  164.         jc      .wait_not_bos
  165.  
  166.         mov     ebx, 3
  167.         call    delay_hs
  168.  
  169.         ; if Bios Busy is still set after 30 mS, wait 2 seconds.
  170.         bt      [esi + HBA_MEM.bohc], bit_AHCI_HBA_BOHC_BB
  171.         jnc     @f
  172.  
  173.         mov     ebx, 200
  174.         call    delay_hs
  175. @@:
  176.         DEBUGF  1, "K: AHCI: ownership change completed.\n"
  177.  
  178. .end_handoff:
  179.         ;-------------------------------------------------------
  180.  
  181.         ; enable the AHCI and reset it
  182.         bts     [esi + HBA_MEM.global_host_control], bit_AHCI_HBA_GHC_AHCI_ENABLE
  183.         bts     [esi + HBA_MEM.global_host_control], bit_AHCI_HBA_GHC_RESET
  184.  
  185.         ; wait for reset to complete
  186. .wait_reset:
  187.         bt      [esi + HBA_MEM.global_host_control], bit_AHCI_HBA_GHC_RESET
  188.         jc      .wait_reset
  189.  
  190.         ; enable the AHCI and interrupts
  191.         bts     [esi + HBA_MEM.global_host_control], bit_AHCI_HBA_GHC_AHCI_ENABLE
  192.         bts     [esi + HBA_MEM.global_host_control], bit_AHCI_HBA_GHC_INTERRUPT_ENABLE
  193.         mov     ebx, 2
  194.         call    delay_hs
  195.        
  196.         DEBUGF  1, "K: AHCI: caps: %x %x, ver: %x, ghc: %x, pi: %x\n", [esi + HBA_MEM.capability], [esi + HBA_MEM.capability2], [esi + HBA_MEM.version], [esi + HBA_MEM.global_host_control], [esi + HBA_MEM.port_implemented]
  197.  
  198.         ; TODO:
  199.         ; calculate irq line
  200.         ; ahciHBA->ghc |= AHCI_GHC_IE;
  201.         ; IDT::RegisterInterruptHandler(irq, InterruptHandler);
  202.         ; ahciHBA->is = 0xffffffff;
  203.  
  204.         xor     ebx, ebx
  205. .detect_drives:
  206.         cmp     ebx, AHCI_MAX_PORTS
  207.         jae     .end_detect_drives
  208.  
  209.         ; if port with index ebx is not implemented then go to next
  210.         mov     ecx, [esi + HBA_MEM.port_implemented]
  211.         bt      ecx, ebx
  212.         jnc     .continue_detect_drives
  213.  
  214.         mov     edi, ebx
  215.         shl     edi, BSF sizeof.HBA_PORT
  216.         add     edi, HBA_MEM.ports
  217.         add     edi, esi
  218.         ; now edi - base of HBA_MEM.ports[ebx]
  219.  
  220.         DEBUGF  1, "K: AHCI: port %d, ssts = %x\n", ebx, [edi + HBA_PORT.sata_status]
  221.  
  222.         mov     ecx, [edi + HBA_PORT.sata_status]
  223.         shr     ecx, 8
  224.         and     ecx, 0x0F
  225.         cmp     ecx, AHCI_HBA_PORT_IPM_ACTIVE
  226.         jne     .continue_detect_drives
  227.  
  228.         mov     ecx, [edi + HBA_PORT.sata_status]
  229.         and     ecx, AHCI_HBA_PxSSTS_DET
  230.         cmp     ecx, AHCI_HBA_PxSSTS_DET_PRESENT
  231.         jne    .continue_detect_drives
  232.  
  233.         DEBUGF 1, "K: AHCI: found drive at port %d, signature = %x\n", ebx, [edi + HBA_PORT.signature]    
  234.  
  235. .continue_detect_drives:
  236.         inc     ebx
  237.         jmp     .detect_drives
  238.  
  239.         ; TODO: why signatures of found disks are 0xFFFFFFFF ?
  240.  
  241. .end_detect_drives:
  242.        
  243.  
  244.         ret
  245.  
  246.