Subversion Repositories Kolibri OS

Rev

Rev 9023 | Rev 9037 | 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_MAX_PORTS = 32        ;
  26. HBA_MEMORY_SIZE = 0x1100
  27.  
  28. struct AHCI_DATA
  29.         ;;
  30.         abar    dd ?       ; pointer to HBA Memory (BAR5) mapped to virtual kernelspace memory
  31.         pcidev  dd ?       ; pointer to corresponding PCIDEV structure
  32. ends
  33.  
  34. ; Generic Host Control registers
  35. struct HBA_MEM
  36.         capability            dd ?                    ; 0x00
  37.         global_host_control   dd ?                    ; 0x04
  38.         interrupt_status      dd ?                    ; 0x08
  39.         port_implemented      dd ?                    ; 0x0C
  40.         version               dd ?                    ; 0x10
  41.         ccc_ctl               dd ?                    ; 0x14, Command completion coalescing control
  42.         ccc_pts               dd ?                    ; 0x18, Command completion coalescing ports
  43.         em_loc                dd ?                    ; 0x1C, Enclosure management location
  44.         em_ctl                dd ?                    ; 0x20, Enclosure management control
  45.         capability2           dd ?                    ; 0x24, Host capabilities extended
  46.         bohc                  dd ?                    ; 0x28, BIOS/OS handoff control and status
  47.         reserved              rb (0xA0-0x2C)          ; 0x2C - 0x9F, Reserved
  48.         vendor                rb (0x100-0xA0)         ; 0xA0 - 0xFF, Vendor specific
  49.         ports                 rb (sizeof.HBA_PORT*AHCI_MAX_PORTS) ; 0x100 - 0x10FF, Port control registers, max AHCI_MAX_PORTS
  50. ends
  51.  
  52. ; Port Control registers
  53. struct HBA_PORT
  54.         command_list_base_l      dd ?                 ; 0x00, command list base address, 1K-byte aligned
  55.         command_list_base_h      dd ?                 ; 0x04, command list base address upper 32 bits, used on 64 bit systems
  56.         fis_base_l               dd ?                 ; 0x08, FIS base address, 256-byte aligned
  57.         fis_base_h               dd ?                 ; 0x0C, FIS base address upper 32 bits, used on 64 bit systems
  58.         interrupt_status         dd ?                 ; 0x10
  59.         interrupt_enable         dd ?                 ; 0x14
  60.         command                  dd ?                 ; 0x18, command and status
  61.         reserved0                dd ?                 ; 0x1C
  62.         task_file_data           dd ?                 ; 0x20
  63.         signature                dd ?                 ; 0x24
  64.         sata_status              dd ?                 ; 0x28, SATA status (SCR0:SStatus)
  65.         sata_control             dd ?                 ; 0x2C, SATA control (SCR2:SControl)
  66.         sata_error               dd ?                 ; 0x30, SATA error (SCR1:SError)
  67.         sata_active              dd ?                 ; 0x34, SATA active (SCR3:SActive)
  68.         command_issue            dd ?                 ; 0x38
  69.         sata_notification        dd ?                 ; 0x3C, SATA notification (SCR4:SNotification)
  70.         fis_based_switch_control dd ?                 ; 0x40
  71.         reserved1                rd 11                ; 0x44 - 0x6F
  72.         vendor                   rd 4                 ; 0x70 - 0x7F, vendor specific
  73. ends
  74.  
  75. uglobal
  76. align 4
  77.         ahci_controller AHCI_DATA
  78. endg
  79.  
  80.  
  81. ; detect ahci controller and initialize
  82. align 4
  83. init_ahci:
  84.         mov     ecx, ahci_controller
  85.         mov     esi, pcidev_list
  86. .find_ahci_ctr:
  87.         mov     esi, [esi + PCIDEV.fd]
  88.         cmp     esi, pcidev_list
  89.         jz      .ahci_ctr_not_found
  90.         mov     eax, [esi + PCIDEV.class]
  91.         ;DEBUGF  1, "K: device class = %x\n", eax
  92.         shr     eax, 8 ; shift right because lowest 8 bits if ProgIf field
  93.         cmp     eax, 0x0106 ; 0x01 - Mass Storage Controller class,  0x06 - Serial ATA Controller subclass
  94.         jz      .ahci_ctr_found
  95.         jmp     .find_ahci_ctr
  96.  
  97. .ahci_ctr_not_found:
  98.         DEBUGF  1, "K: AHCI controller not found\n"
  99.         ret
  100.  
  101. .ahci_ctr_found:
  102.         mov     [ahci_controller + AHCI_DATA.pcidev], esi
  103.  
  104.         mov     eax, [esi+PCIDEV.class]
  105.         movzx   ebx, byte [esi+PCIDEV.bus]
  106.         movzx   ecx, byte [esi+PCIDEV.devfn]
  107.         shr     ecx, 3 ; get rid of 3 lowest bits (function code), the rest bits is device code
  108.         movzx   edx, byte [esi+PCIDEV.devfn]
  109.         and     edx, 00000111b ; get only 3 lowest bits (function code)
  110.         DEBUGF  1, "K: found AHCI controller, (class, subcl, progif) = %x, bus = %x, device = %x, function = %x\n", eax, ebx, ecx, edx
  111.        
  112.         ; get BAR5 value, it is physical address
  113.         movzx   eax, [esi + PCIDEV.bus]
  114.         movzx   ebx, [esi + PCIDEV.devfn]
  115.         stdcall pci_read32, eax, ebx, PCI_REG_BAR5
  116.         DEBUGF  1, "K: AHCI controller BAR5 = %x\n", eax
  117.  
  118.         ; Map BAR5 to virtual memory
  119.         stdcall map_io_mem, eax, HBA_MEMORY_SIZE, PG_SWR + PG_NOCACHE
  120.         mov     [ahci_controller + AHCI_DATA.abar], eax
  121.         DEBUGF  1, "K: AHCI controller BAR5 mapped to virtual addr %x\n", eax
  122.  
  123.         ; Enable dma bus mastering, memory space access, clear the "disable interrupts" bit
  124.         ; Usually, it is already done before us
  125.         movzx   ebx, [esi + PCIDEV.bus]
  126.         movzx   ebp, [esi + PCIDEV.devfn]
  127.         stdcall pci_read32, ebx, ebp, PCI_REG_STATUS_COMMAND
  128.         DEBUGF  1, "K: AHCI: pci_status_command = %x\nEnabling interrupts, DMA bus mastering and memory space access\n", eax
  129.         or      eax, 0x06 ; pci.command |= 0x06 (dma bus mastering + memory space access)
  130.         btr     eax, 10 ; clear the "disable interrupts" bit
  131.         DEBUGF  1, "K: AHCI: pci_status_command = %x\n", eax
  132.         stdcall pci_write32, ebx, ebp, PCI_REG_STATUS_COMMAND, eax
  133.  
  134.         ; ; Print some register values to debug board
  135.         ; mov     esi, [ahci_controller + AHCI_DATA.abar]
  136.         ; 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]
  137.  
  138.         ;-------------------------------------------------------
  139.         ; Request BIOS/OS ownership handoff, if supported. (TODO check correctness)
  140.         mov     esi, [ahci_controller + AHCI_DATA.abar]
  141.         ;mov     ebx, [esi + HBA_MEM.capability2]
  142.         ;DEBUGF  1, "K: AHCI: HBA_MEM.cap2 = %x\n", ebx
  143.         bt      [esi + HBA_MEM.capability2], bit_AHCI_HBA_CAP2_BOH
  144.         jnc     .end_handoff
  145.         DEBUGF  1, "K: AHCI: requesting AHCI ownership change...\n"
  146.         bts     [esi + HBA_MEM.bohc], bit_AHCI_HBA_BOHC_OOS
  147.  
  148. .wait_not_bos:
  149.         bt      [esi + HBA_MEM.bohc], bit_AHCI_HBA_BOHC_BOS
  150.         jc      .wait_not_bos
  151.  
  152.         mov     ebx, 3
  153.         call    delay_hs
  154.  
  155.         ; if Bios Busy is still set after 30 mS, wait 2 seconds.
  156.         bt      [esi + HBA_MEM.bohc], bit_AHCI_HBA_BOHC_BB
  157.         jnc     @f
  158.  
  159.         mov     ebx, 200
  160.         call    delay_hs
  161. @@:
  162.         DEBUGF  1, "K: AHCI: ownership change completed.\n"
  163.  
  164. .end_handoff:
  165.         ;-------------------------------------------------------
  166.  
  167.         ; enable the AHCI and reset it
  168.         bts     [esi + HBA_MEM.global_host_control], bit_AHCI_HBA_GHC_AHCI_ENABLE
  169.         bts     [esi + HBA_MEM.global_host_control], bit_AHCI_HBA_GHC_RESET
  170.  
  171.         ; wait for reset to complete
  172. .wait_reset:
  173.         bt      [esi + HBA_MEM.global_host_control], bit_AHCI_HBA_GHC_RESET
  174.         jc      .wait_reset
  175.  
  176.         ; enable the AHCI and interrupts
  177.         bts     [esi + HBA_MEM.global_host_control], bit_AHCI_HBA_GHC_AHCI_ENABLE
  178.         bts     [esi + HBA_MEM.global_host_control], bit_AHCI_HBA_GHC_INTERRUPT_ENABLE
  179.         mov     ebx, 2
  180.         call    delay_hs
  181.        
  182.         DEBUGF  1, "K: AHCI: caps: %x %x, ver: %x, ghc: %x\n", [esi + HBA_MEM.capability], [esi + HBA_MEM.capability2], [esi + HBA_MEM.version], [esi + HBA_MEM.global_host_control]
  183.  
  184.         ret
  185.  
  186.