Subversion Repositories Kolibri OS

Rev

Rev 9023 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
9020 rgimad 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
AHCI_BOHCf_BOS  = 0        ; BIOS-Owned Semaphore (BIOS owns controller)
14
AHCI_BOHCf_OOS  = 1        ; OS-Owned Semaphore (OS owns controller)
15
AHCI_BOHCf_BB   = 4        ; BIOS Busy (polling bit while BIOS cleans up
16
 
17
AHCI_CAP2_BOH = 0          ; number of bit in BOH which shows Supports BIOS/OS Handoff
18
 
19
HBA_MEMORY_SIZE = 0x1100
20
 
21
struct AHCI_DATA
22
        ;;
23
        abar    dd ?       ; pointer to HBA Memory (BAR5) mapped to virtual kernelspace memory
24
        pcidev  dd ?       ; pointer to corresponding PCIDEV structure
25
ends
26
 
27
; Generic Host Control registers
28
struct HBA_MEM
29
        capability            dd ?                    ; 0x00
30
        global_host_control   dd ?                    ; 0x04
31
        interrupt_status      dd ?                    ; 0x08
32
        port_implemented      dd ?                    ; 0x0C
33
        version               dd ?                    ; 0x10
34
        ccc_ctl               dd ?                    ; 0x14, Command completion coalescing control
35
        ccc_pts               dd ?                    ; 0x18, Command completion coalescing ports
36
        em_loc                dd ?                    ; 0x1C, Enclosure management location
37
        em_ctl                dd ?                    ; 0x20, Enclosure management control
38
        capability2           dd ?                    ; 0x24, Host capabilities extended
39
        bohc                  dd ?                    ; 0x28, BIOS/OS handoff control and status
40
        reserved              rb (0xA0-0x2C)          ; 0x2C - 0x9F, Reserved
41
        vendor                rb (0x100-0xA0)         ; 0xA0 - 0xFF, Vendor specific
42
        ports                 rb (sizeof.HBA_PORT*32) ; 0x100 - 0x10FF, Port control registers, max 32
43
ends
44
 
45
; Port Control registers
46
struct HBA_PORT
47
	command_list_base_l      dd ?                 ; 0x00, command list base address, 1K-byte aligned
48
	command_list_base_h      dd ?                 ; 0x04, command list base address upper 32 bits, used on 64 bit systems
49
	fis_base_l               dd ?                 ; 0x08, FIS base address, 256-byte aligned
50
	fis_base_h               dd ?                 ; 0x0C, FIS base address upper 32 bits, used on 64 bit systems
51
	interrupt_status         dd ?                 ; 0x10
52
	interrupt_enable         dd ?                 ; 0x14
53
	command                  dd ?                 ; 0x18, command and status
54
	reserved0                dd ?                 ; 0x1C
55
	task_file_data           dd ?                 ; 0x20
56
	signature                dd ?                 ; 0x24
57
	sata_status              dd ?                 ; 0x28, SATA status (SCR0:SStatus)
58
	sata_control             dd ?                 ; 0x2C, SATA control (SCR2:SControl)
59
	sata_error               dd ?                 ; 0x30, SATA error (SCR1:SError)
60
	sata_active              dd ?                 ; 0x34, SATA active (SCR3:SActive)
61
	command_issue            dd ?                 ; 0x38
62
	sata_notification        dd ?                 ; 0x3C, SATA notification (SCR4:SNotification)
63
	fis_based_switch_control dd ?                 ; 0x40
64
	reserved1                rd 11                ; 0x44 - 0x6F
65
	vendor                   rd 4                 ; 0x70 - 0x7F, vendor specific
66
ends
67
 
68
uglobal
69
align 4
70
        ahci_controller AHCI_DATA
71
endg
72
 
73
 
74
; detect ahci controller and initialize
75
align 4
76
init_ahci:
77
        mov     ecx, ahci_controller
78
        mov     esi, pcidev_list
79
.find_ahci_ctr:
80
        mov     esi, [esi + PCIDEV.fd]
81
        cmp     esi, pcidev_list
82
        jz      .ahci_ctr_not_found
83
        mov     eax, [esi + PCIDEV.class]
84
        ;DEBUGF  1, "K: device class = %x\n", eax
85
        shr     eax, 8 ; shift right because lowest 8 bits if ProgIf field
86
        cmp     eax, 0x0106 ; 0x01 - Mass Storage Controller class,  0x06 - Serial ATA Controller subclass
87
        jz      .ahci_ctr_found
88
        jmp     .find_ahci_ctr
89
 
90
.ahci_ctr_not_found:
91
        DEBUGF  1, "K: AHCI controller not found\n"
92
        ret
93
 
94
.ahci_ctr_found:
95
        mov     [ahci_controller + AHCI_DATA.pcidev], esi
96
 
97
        mov     eax, [esi+PCIDEV.class]
98
        movzx   ebx, byte [esi+PCIDEV.bus]
99
        movzx   ecx, byte [esi+PCIDEV.devfn]
100
        shr     ecx, 3 ; get rid of 3 lowest bits (function code), the rest bits is device code
101
        movzx   edx, byte [esi+PCIDEV.devfn]
102
        and     edx, 00000111b ; get only 3 lowest bits (function code)
103
        DEBUGF  1, "K: found AHCI controller, (class, subcl, progif) = %x, bus = %x, device = %x, function = %x\n", eax, ebx, ecx, edx
104
 
105
        mov     ah, [esi + PCIDEV.bus]
106
        mov     al, 2 ; read dword
107
        mov     bh, [esi + PCIDEV.devfn]
108
        mov     bl, PCI_REG_BAR5
109
        call    pci_read_reg
110
        DEBUGF  1, "K: AHCI controller BAR5 = %x\n", eax
111
 
112
        stdcall map_io_mem, eax, HBA_MEMORY_SIZE, PG_SWR + PG_NOCACHE
113
        mov     [ahci_controller + AHCI_DATA.abar], eax
114
        DEBUGF  1, "K: AHCI controller BAR5 mapped to virtual addr %x\n", eax
115
 
116
        mov     ah, [esi + PCIDEV.bus]
117
        mov     al, 2 ; read dword
118
        mov     bh, [esi + PCIDEV.devfn]
119
        mov     bl, PCI_REG_STATUS_COMMAND
120
        call    pci_read_reg
121
        DEBUGF  1, "K: AHCI: pci_status_command = %x\nEnabling interrupts, DMA bus mastering and memory space access\n", eax
122
        or      eax, 0x06 ; pci.command |= 0x06 (dma bus mastering + memory space access)
123
        btr     eax, 10 ; clear the "disable interrupts" bit
124
        DEBUGF  1, "K: AHCI: pci_status_command = %x\n", eax
125
        mov     ecx, eax
126
        mov     ah, [esi + PCIDEV.bus]
127
        mov     al, 2 ; write dword
128
        mov     bh, [esi + PCIDEV.devfn]
129
        mov     bl, PCI_REG_STATUS_COMMAND
130
        call    pci_write_reg
131
 
132
        mov     eax, [ahci_controller + AHCI_DATA.abar]
133
        mov     ebx, [eax + HBA_MEM.capability]
134
        mov     ecx, [eax + HBA_MEM.global_host_control]
135
        mov     edx, [eax + HBA_MEM.version]
136
        DEBUGF  1, "K: AHCI: HBA.cap = %x, HBA.ghc = %x, HBA_MEM.version = %x\n", ebx, ecx, edx
137
 
138
        ; //Transferring ownership from BIOS if supported.
139
	; if (Bt(&hba->caps_ext, AHCI_CAPSEXTf_BOH))
140
	; {
141
	; 	Bts(&hba->bohc, AHCI_BOHCf_OOS);
142
	; 	"AHCI: Transferring ownership from BIOS\n";
143
 
144
	; 	while (Bt(&hba->bohc, AHCI_BOHCf_BOS));
145
 
146
	; 	Sleep(25);
147
	; 	if (Bt(&hba->bohc, AHCI_BOHCf_BB)) //if Bios Busy is still set after 25 mS, wait 2 seconds.
148
	; 		Sleep(2000);
149
	; }
150
 
151
        ; Transferring ownership from BIOS if supported. (TODO check)
152
        mov     eax, [ahci_controller + AHCI_DATA.abar]
153
        mov     ebx, [eax + HBA_MEM.capability2]
154
        DEBUGF  1, "K: AHCI: HBA_MEM.cap2 = %x\n", ebx
155
        bt      dword [eax + HBA_MEM.capability2], AHCI_CAP2_BOH
156
        jnc     .end_handoff
157
        DEBUGF  1, "K: AHCI: Transferring ownership from BIOS...\n"
158
        bts     dword [eax + HBA_MEM.bohc], AHCI_BOHCf_OOS
159
 
160
.wait_not_bos:
161
        bt      dword [eax + HBA_MEM.bohc], AHCI_BOHCf_BOS
162
        jc      .wait_not_bos
163
 
164
        mov     ebx, 3
165
        call    delay_hs
166
 
167
        ; if Bios Busy is still set after 25 mS, wait 2 seconds.
168
        bt      dword [eax + HBA_MEM.bohc], AHCI_BOHCf_BB
169
        jnc     @f
170
 
171
        mov     ebx, 200
172
        call    delay_hs
173
@@:
174
        DEBUGF  1, "K: AHCI: Done.\n"
175
 
176
.end_handoff:
177
 
178
        ;; TODO: Reset controller ?
179
 
180
        ;; TODO enble AHCI ? (see https://github.com/ZenithOS/ZenithOS/blob/4ea8b133613ab95a8b53ed543d8e63525a21954e/src/Kernel/BlkDev/DiskAHCI.CC#L719)
181
 
182
        ;; TODO: find drives (see https://github.com/ZenithOS/ZenithOS/blob/4ea8b133613ab95a8b53ed543d8e63525a21954e/src/Kernel/BlkDev/DiskAHCI.CC#L742)
183
 
184
        ret
185