Subversion Repositories Kolibri OS

Rev

Rev 9072 | Rev 9130 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 9072 Rev 9074
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2004-2021. All rights reserved. ;;
3
;; Copyright (C) KolibriOS team 2004-2021. All rights reserved. ;;
4
;; Distributed under terms of the GNU General Public License    ;;
4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
7
 
8
$Revision$
8
$Revision$
9
 
9
 
10
PCI_REG_STATUS_COMMAND = 0x0004
10
PCI_REG_STATUS_COMMAND = 0x0004
11
PCI_REG_BAR5 = 0x0024
11
PCI_REG_BAR5 = 0x0024
12
 
12
 
13
; bit_ prefix means that its index of bit
13
; bit_ prefix means that its index of bit
14
; format: bit_AHCI_STR_REG_BIT
14
; format: bit_AHCI_STR_REG_BIT
15
bit_AHCI_HBA_CAP2_BOH   = 0        ; Supports BIOS/OS Handoff
15
bit_AHCI_HBA_CAP2_BOH   = 0        ; Supports BIOS/OS Handoff
16
 
16
 
17
bit_AHCI_HBA_BOHC_BOS  = 0         ; BIOS-Owned Semaphore (BIOS owns controller)
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)
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 
19
bit_AHCI_HBA_BOHC_BB   = 4         ; BIOS Busy (polling bit while BIOS cleans up 
20
 
20
 
21
bit_AHCI_HBA_GHC_AHCI_ENABLE      = 31  ; Enable AHCI mode
21
bit_AHCI_HBA_GHC_AHCI_ENABLE      = 31  ; Enable AHCI mode
22
bit_AHCI_HBA_GHC_RESET            = 0   ; Reset HBA
22
bit_AHCI_HBA_GHC_RESET            = 0   ; Reset HBA
23
bit_AHCI_HBA_GHC_INTERRUPT_ENABLE = 1   ; Enable interrupts from the HBA 
23
bit_AHCI_HBA_GHC_INTERRUPT_ENABLE = 1   ; Enable interrupts from the HBA 
24
 
24
 
25
bit_AHCI_HBA_PxCMD_ST    = 0
25
bit_AHCI_HBA_PxCMD_ST    = 0
26
bit_AHCI_HBA_PxCMD_FRE   = 4
26
bit_AHCI_HBA_PxCMD_FRE   = 4
27
bit_AHCI_HBA_PxCMD_FR    = 14
27
bit_AHCI_HBA_PxCMD_FR    = 14
28
bit_AHCI_HBA_PxCMD_CR    = 15
28
bit_AHCI_HBA_PxCMD_CR    = 15
-
 
29
 
-
 
30
bit_AHCI_H2D_FLAG_CMD    = 7
29
 
31
 
30
AHCI_HBA_PxSSTS_DET         = 0xF
32
AHCI_HBA_PxSSTS_DET         = 0xF
31
AHCI_HBA_PORT_IPM_ACTIVE    = 1
33
AHCI_HBA_PORT_IPM_ACTIVE    = 1
32
AHCI_HBA_PxSSTS_DET_PRESENT = 3
34
AHCI_HBA_PxSSTS_DET_PRESENT = 3
33
 
35
 
34
AHCI_MAX_PORTS = 32        ;
36
AHCI_MAX_PORTS = 32        ;
35
;HBA_MEMORY_SIZE = 0x1100
37
;HBA_MEMORY_SIZE = 0x1100
36
 
38
 
37
; Frame Information Structure Types
39
; Frame Information Structure Types
38
FIS_TYPE_REG_H2D    = 0x27 ; Register FIS - host to device
40
FIS_TYPE_REG_H2D    = 0x27 ; Register FIS - host to device
39
FIS_TYPE_REG_D2H    = 0x34 ; Register FIS - device to host
41
FIS_TYPE_REG_D2H    = 0x34 ; Register FIS - device to host
40
FIS_TYPE_DMA_ACT    = 0x39 ; DMA activate FIS - device to host
42
FIS_TYPE_DMA_ACT    = 0x39 ; DMA activate FIS - device to host
41
FIS_TYPE_DMA_SETUP  = 0x41 ; DMA setup FIS - bidirectional
43
FIS_TYPE_DMA_SETUP  = 0x41 ; DMA setup FIS - bidirectional
42
FIS_TYPE_DATA       = 0x46 ; Data FIS - bidirectional
44
FIS_TYPE_DATA       = 0x46 ; Data FIS - bidirectional
43
FIS_TYPE_BIST       = 0x58 ; BIST activate FIS - bidirectional
45
FIS_TYPE_BIST       = 0x58 ; BIST activate FIS - bidirectional
44
FIS_TYPE_PIO_SETUP  = 0x5F ; PIO setup FIS - device to host
46
FIS_TYPE_PIO_SETUP  = 0x5F ; PIO setup FIS - device to host
45
FIS_TYPE_DEV_BITS   = 0xA1 ; Set device bits FIS - device to host
47
FIS_TYPE_DEV_BITS   = 0xA1 ; Set device bits FIS - device to host
46
 
48
 
47
struct AHCI_DATA
49
struct AHCI_DATA
48
        abar    dd ?       ; pointer to HBA Memory (BAR5) mapped to virtual kernelspace memory
50
        abar    dd ?       ; pointer to HBA Memory (BAR5) mapped to virtual kernelspace memory
49
        pcidev  dd ?       ; pointer to corresponding PCIDEV structure
51
        pcidev  dd ?       ; pointer to corresponding PCIDEV structure
50
ends
52
ends
51
 
53
 
52
; Generic Host Control registers
54
; Generic Host Control registers
53
struct HBA_MEM
55
struct HBA_MEM
54
        cap                   dd ?                    ; 0x00, Host capabilities
56
        cap                   dd ?                    ; 0x00, Host capabilities
55
        ghc                   dd ?                    ; 0x04, Global host control
57
        ghc                   dd ?                    ; 0x04, Global host control
56
        is                    dd ?                    ; 0x08, Interrupt status
58
        is                    dd ?                    ; 0x08, Interrupt status
57
        pi                    dd ?                    ; 0x0C, Port implemented
59
        pi                    dd ?                    ; 0x0C, Port implemented
58
        version               dd ?                    ; 0x10, Version
60
        version               dd ?                    ; 0x10, Version
59
        ccc_ctl               dd ?                    ; 0x14, Command completion coalescing control
61
        ccc_ctl               dd ?                    ; 0x14, Command completion coalescing control
60
        ccc_pts               dd ?                    ; 0x18, Command completion coalescing ports
62
        ccc_pts               dd ?                    ; 0x18, Command completion coalescing ports
61
        em_loc                dd ?                    ; 0x1C, Enclosure management location
63
        em_loc                dd ?                    ; 0x1C, Enclosure management location
62
        em_ctl                dd ?                    ; 0x20, Enclosure management control
64
        em_ctl                dd ?                    ; 0x20, Enclosure management control
63
        cap2                  dd ?                    ; 0x24, Host capabilities extended
65
        cap2                  dd ?                    ; 0x24, Host capabilities extended
64
        bohc                  dd ?                    ; 0x28, BIOS/OS handoff control and status
66
        bohc                  dd ?                    ; 0x28, BIOS/OS handoff control and status
65
        reserved              rb (0xA0-HBA_MEM.reserved)        ; 0x2C - 0x9F, Reserved
67
        reserved              rb (0xA0-HBA_MEM.reserved)        ; 0x2C - 0x9F, Reserved
66
        vendor                rb (0x100-HBA_MEM.vendor)         ; 0xA0 - 0xFF, Vendor specific 
68
        vendor                rb (0x100-HBA_MEM.vendor)         ; 0xA0 - 0xFF, Vendor specific 
67
        ports                 rb (sizeof.HBA_PORT*AHCI_MAX_PORTS) ; 0x100 - 0x10FF, Port control registers, max AHCI_MAX_PORTS
69
        ports                 rb (sizeof.HBA_PORT*AHCI_MAX_PORTS) ; 0x100 - 0x10FF, Port control registers, max AHCI_MAX_PORTS
68
ends
70
ends
69
 
71
 
70
; Port Control registers
72
; Port Control registers
71
struct HBA_PORT
73
struct HBA_PORT
72
        command_list_base_l      dd ?                 ; 0x00, command list base address, 1K-byte aligned
74
        command_list_base_l      dd ?                 ; 0x00, command list base address, 1K-byte aligned
73
        command_list_base_h      dd ?                 ; 0x04, command list base address upper 32 bits, used on 64 bit systems
75
        command_list_base_h      dd ?                 ; 0x04, command list base address upper 32 bits, used on 64 bit systems
74
        fis_base_l               dd ?                 ; 0x08, FIS base address, 256-byte aligned
76
        fis_base_l               dd ?                 ; 0x08, FIS base address, 256-byte aligned
75
        fis_base_h               dd ?                 ; 0x0C, FIS base address upper 32 bits, used on 64 bit systems
77
        fis_base_h               dd ?                 ; 0x0C, FIS base address upper 32 bits, used on 64 bit systems
76
        interrupt_status         dd ?                 ; 0x10
78
        interrupt_status         dd ?                 ; 0x10
77
        interrupt_enable         dd ?                 ; 0x14
79
        interrupt_enable         dd ?                 ; 0x14
78
        command                  dd ?                 ; 0x18, command and status
80
        command                  dd ?                 ; 0x18, command and status
79
        reserved0                dd ?                 ; 0x1C
81
        reserved0                dd ?                 ; 0x1C
80
        task_file_data           dd ?                 ; 0x20
82
        task_file_data           dd ?                 ; 0x20
81
        signature                dd ?                 ; 0x24
83
        signature                dd ?                 ; 0x24
82
        sata_status              dd ?                 ; 0x28, SATA status (SCR0:SStatus)
84
        sata_status              dd ?                 ; 0x28, SATA status (SCR0:SStatus)
83
        sata_control             dd ?                 ; 0x2C, SATA control (SCR2:SControl)
85
        sata_control             dd ?                 ; 0x2C, SATA control (SCR2:SControl)
84
        sata_error               dd ?                 ; 0x30, SATA error (SCR1:SError)
86
        sata_error               dd ?                 ; 0x30, SATA error (SCR1:SError)
85
        sata_active              dd ?                 ; 0x34, SATA active (SCR3:SActive)
87
        sata_active              dd ?                 ; 0x34, SATA active (SCR3:SActive)
86
        command_issue            dd ?                 ; 0x38
88
        command_issue            dd ?                 ; 0x38
87
        sata_notification        dd ?                 ; 0x3C, SATA notification (SCR4:SNotification)
89
        sata_notification        dd ?                 ; 0x3C, SATA notification (SCR4:SNotification)
88
        fis_based_switch_control dd ?                 ; 0x40
90
        fis_based_switch_control dd ?                 ; 0x40
89
        reserved1                rd 11                ; 0x44 - 0x6F
91
        reserved1                rd 11                ; 0x44 - 0x6F
90
        vendor                   rd 4                 ; 0x70 - 0x7F, vendor specific
92
        vendor                   rd 4                 ; 0x70 - 0x7F, vendor specific
91
ends
93
ends
92
 
94
 
93
; Command header structure
95
; Command header structure, size = 32 bytes
94
struct HBA_CMD_HDR
96
struct HBA_CMD_HDR
95
    _flags1       db ? ; 0bPWACCCCC, P - Prefetchable, W - Write (1: H2D, 0: D2H)
97
    _flags1       db ? ; 0bPWACCCCC, P - Prefetchable, W - Write (1: H2D, 0: D2H)
96
                       ; A - ATAPI, C - Command FIS length in DWORDS, 2 ~ 16
98
                       ; A - ATAPI, C - Command FIS length in DWORDS, 2 ~ 16
97
    
99
    
98
    _flags2       db ? ; 0bPPPPRCB(Re), P - Port multiplier port, R - Reserved,
100
    _flags2       db ? ; 0bPPPPRCB(Re), P - Port multiplier port, R - Reserved,
99
                       ; C - Clear busy upon R_OK, B - BIST, Re - Reset
101
                       ; C - Clear busy upon R_OK, B - BIST, Re - Reset
100
    
102
    
101
    prdtl         dw ? ; Physical region descriptor table length in entries
103
    prdtl         dw ? ; Physical region descriptor table length in entries
102
    prdbc         dd ? ; Physical region descriptor byte count transferred
104
    prdbc         dd ? ; Physical region descriptor byte count transferred
103
    ctba          dd ? ; Command table descriptor base address
105
    ctba          dd ? ; Command table descriptor base address
104
    ctbau         dd ? ; Command table descriptor base address upper 32 bits
106
    ctbau         dd ? ; Command table descriptor base address upper 32 bits
105
                  rd 4 ; Reserved
107
                  rd 4 ; Reserved
106
ends
108
ends
-
 
109
 
107
 
110
; Physical region descriptor table entry, size = 16 bytes
108
struct HBA_PRDT_ENTRY
111
struct HBA_PRDT_ENTRY
109
    dba           dd ?  ; Data base address
112
    dba           dd ?  ; Data base address
110
    dbau          dd ?  ; Data base address upper 32 bits
113
    dbau          dd ?  ; Data base address upper 32 bits
111
                  dd ?  ; Reserved
114
                  dd ?  ; Reserved
112
    _flags        dd ?  ; 0bIR..RD..D, I (1 bit) - Interrupt on completion,
115
    _flags        dd ?  ; 0bIR..RD..D, I (1 bit) - Interrupt on completion,
113
                        ; R (9 bits) - Reserved, D (22 bits) - Byte count, 4M max
116
                        ; R (9 bits) - Reserved, D (22 bits) - Byte count, 4M max
114
ends
117
ends
115
 
118
 
116
struct HBA_CMD_TBL
119
struct HBA_CMD_TBL
117
    cfis          rb 64 ; 0x00, Command FIS
120
    cfis          rb 64 ; 0x00, Command FIS
118
    acmd          rb 16 ; 0x40, ATAPI command, 12 or 16 bytes
121
    acmd          rb 16 ; 0x40, ATAPI command, 12 or 16 bytes
119
                  rb 48 ; 0x50, Reserved
122
                  rb 48 ; 0x50, Reserved
120
    prdt_entry    HBA_PRDT_ENTRY  ; 0x80, Physical region descriptor table entries, 0 ~ 65535
123
    prdt_entry    HBA_PRDT_ENTRY  ; 0x80, Physical region descriptor table entries, 0 ~ 65535
121
                        ; so, this structure is variable-length
124
                        ; so, this structure is variable-length
122
ends
125
ends
123
 
126
 
124
; Contains virtual mappings for port phys memory regions
127
; Contains virtual mappings for port phys memory regions
125
struct PORT_DATA
128
struct PORT_DATA
126
    clb           dd ? ; Command list base
129
    clb           dd ? ; Command list base
127
    fb            dd ? ; FIS base
130
    fb            dd ? ; FIS base
128
    ctba_arr      rd 32 ; ctba_arr[0] = clb[0].ctba, ... and so on.
131
    ctba_arr      rd 32 ; ctba_arr[0] = clb[0].ctba, ... and so on.
129
    port          dd ? ; address of correspoding HBA_PORT structure
132
    port          dd ? ; address of correspoding HBA_PORT structure
-
 
133
    portno        dd ? ; port index, 0..31
130
ends
134
ends
131
 
135
 
132
; Register FIS – Host to Device
136
; Register FIS – Host to Device
133
struct FIS_REG_H2D
137
struct FIS_REG_H2D
134
        fis_type      db ?       ; FIS_TYPE_REG_H2D
138
        fis_type      db ?       ; FIS_TYPE_REG_H2D
135
        _flags        db ?       ; 0bCRRRPPPP, C - 1: Command, 0: Control
139
        _flags        db ?       ; 0bCRRRPPPP, C - 1: Command, 0: Control
136
                                 ; R - Reserved, P - Port multiplier
140
                                 ; R - Reserved, P - Port multiplier
137
 
141
 
138
        command       db ?       ; Command register
142
        command       db ?       ; Command register
139
        featurel      db ?       ; Feature register, 7:0
143
        featurel      db ?       ; Feature register, 7:0
140
 
144
 
141
        lba0          db ?       ; LBA low register, 7:0
145
        lba0          db ?       ; LBA low register, 7:0
142
        lba1          db ?       ; LBA mid register, 15:8
146
        lba1          db ?       ; LBA mid register, 15:8
143
        lba2          db ?       ; LBA high register, 23:16
147
        lba2          db ?       ; LBA high register, 23:16
144
        device        db ?       ; Device register
148
        device        db ?       ; Device register
145
 
149
 
146
        lba3          db ?       ; LBA register, 31:24
150
        lba3          db ?       ; LBA register, 31:24
147
        lba4          db ?       ; LBA register, 39:32
151
        lba4          db ?       ; LBA register, 39:32
148
        lba5          db ?       ; LBA register, 47:40
152
        lba5          db ?       ; LBA register, 47:40
149
        featureh      db ?       ; Feature register, 15:8
153
        featureh      db ?       ; Feature register, 15:8
150
 
154
 
151
        countl        db ?       ; Count register, 7:0
155
        countl        db ?       ; Count register, 7:0
152
        counth        db ?       ; Count register, 15:8
156
        counth        db ?       ; Count register, 15:8
153
        icc           db ?       ; Isochronous command completion
157
        icc           db ?       ; Isochronous command completion
154
        control       db ?       ; Control register
158
        control       db ?       ; Control register
155
 
159
 
156
                      rb 4       ; Reserved
160
                      rb 4       ; Reserved
157
ends
161
ends
158
 
162
 
159
; Register FIS – Device to Host
163
; Register FIS – Device to Host
160
struct FIS_REG_D2H
164
struct FIS_REG_D2H
161
    fis_type      db ?           ; FIS_TYPE_REG_D2H
165
    fis_type      db ?           ; FIS_TYPE_REG_D2H
162
 
166
 
163
    _flags        db ?           ; 0bRIRPPPP, P - Port multiplier, R - Reserved
167
    _flags        db ?           ; 0bRIRPPPP, P - Port multiplier, R - Reserved
164
                                 ; I - Interrupt bit
168
                                 ; I - Interrupt bit
165
 
169
 
166
    status        db ?           ; Status register
170
    status        db ?           ; Status register
167
    error         db ?           ; Error register
171
    error         db ?           ; Error register
168
 
172
 
169
    lba0          db ?           ; LBA low register, 7:0
173
    lba0          db ?           ; LBA low register, 7:0
170
    lba1          db ?           ; LBA mid register, 15:8
174
    lba1          db ?           ; LBA mid register, 15:8
171
    lba2          db ?           ; LBA high register, 23:16
175
    lba2          db ?           ; LBA high register, 23:16
172
    device        db ?           ; Device register
176
    device        db ?           ; Device register
173
 
177
 
174
    lba3          db ?           ; LBA register, 31:24
178
    lba3          db ?           ; LBA register, 31:24
175
    lba4          db ?           ; LBA register, 39:32
179
    lba4          db ?           ; LBA register, 39:32
176
    lba5          db ?           ; LBA register, 47:40
180
    lba5          db ?           ; LBA register, 47:40
177
                  db ?           ; Reserved
181
                  db ?           ; Reserved
178
 
182
 
179
    countl        db ?           ; Count register, 7:0
183
    countl        db ?           ; Count register, 7:0
180
    counth        db ?           ; Count register, 15:8
184
    counth        db ?           ; Count register, 15:8
181
                  rb 2           ; Reserved
185
                  rb 2           ; Reserved
182
 
186
 
183
                  rb 4           ; Reserved
187
                  rb 4           ; Reserved
184
ends
188
ends
185
 
189
 
186
; Data FIS – Bidirectional
190
; Data FIS – Bidirectional
187
struct FIS_DATA
191
struct FIS_DATA
188
    fis_type      db ?           ; FIS_TYPE_DATA
192
    fis_type      db ?           ; FIS_TYPE_DATA
189
    _flags        db ?           ; 0bRRRRPPPP, R - Reserved, P - Port multiplier
193
    _flags        db ?           ; 0bRRRRPPPP, R - Reserved, P - Port multiplier
190
                  rb 2           ; Reserved
194
                  rb 2           ; Reserved
191
    ; DWORD 1 ~ N (?)
195
    ; DWORD 1 ~ N (?)
192
    data          rd 1           ; Payload
196
    data          rd 1           ; Payload
193
ends
197
ends
194
 
198
 
195
; PIO Setup – Device to Host
199
; PIO Setup – Device to Host
196
struct FIS_PIO_SETUP
200
struct FIS_PIO_SETUP
197
    fis_type      db ?           ; FIS_TYPE_PIO_SETUP
201
    fis_type      db ?           ; FIS_TYPE_PIO_SETUP
198
 
202
 
199
    _flags        db ?           ; 0bRIDRPPPP, P - Port multiplier, R - Reserved
203
    _flags        db ?           ; 0bRIDRPPPP, P - Port multiplier, R - Reserved
200
                                 ; I - Interrupt bit, D - Data transfer direction, 1 - device to host
204
                                 ; I - Interrupt bit, D - Data transfer direction, 1 - device to host
201
 
205
 
202
    status        db ?           ; Status register
206
    status        db ?           ; Status register
203
    error         db ?           ; Error register
207
    error         db ?           ; Error register
204
 
208
 
205
    lba0          db ?           ; LBA low register, 7:0
209
    lba0          db ?           ; LBA low register, 7:0
206
    lba1          db ?           ; LBA mid register, 15:8
210
    lba1          db ?           ; LBA mid register, 15:8
207
    lba2          db ?           ; LBA high register, 23:16
211
    lba2          db ?           ; LBA high register, 23:16
208
    device        db ?           ; Device register
212
    device        db ?           ; Device register
209
 
213
 
210
    lba3          db ?           ; LBA register, 31:24
214
    lba3          db ?           ; LBA register, 31:24
211
    lba4          db ?           ; LBA register, 39:32
215
    lba4          db ?           ; LBA register, 39:32
212
    lba5          db ?           ; LBA register, 47:40
216
    lba5          db ?           ; LBA register, 47:40
213
                  db ?           ; Reserved
217
                  db ?           ; Reserved
214
 
218
 
215
    countl        db ?           ; Count register, 7:0
219
    countl        db ?           ; Count register, 7:0
216
    counth        db ?           ; Count register, 15:8
220
    counth        db ?           ; Count register, 15:8
217
                  db ?           ; Reserved
221
                  db ?           ; Reserved
218
    e_status      db ?           ; New value of status register
222
    e_status      db ?           ; New value of status register
219
 
223
 
220
    tc            dw ?           ; Transfer count
224
    tc            dw ?           ; Transfer count
221
                  rb 2           ; Reserved
225
                  rb 2           ; Reserved
222
ends
226
ends
223
 
227
 
224
; DMA Setup – Device to Host
228
; DMA Setup – Device to Host
225
struct FIS_DMA_SETUP
229
struct FIS_DMA_SETUP
226
    fis_type      db ?           ; FIS_TYPE_DMA_SETUP
230
    fis_type      db ?           ; FIS_TYPE_DMA_SETUP
227
    _flags        db ?           ; 0bAIDRPPPP, A - Auto-activate. Specifies if DMA Activate FIS is needed,
231
    _flags        db ?           ; 0bAIDRPPPP, A - Auto-activate. Specifies if DMA Activate FIS is needed,
228
                                 ; I - Interrupt bit, D - Data transfer direction, 1 - device to host,
232
                                 ; I - Interrupt bit, D - Data transfer direction, 1 - device to host,
229
                                 ; R - Reserved, P - Port multiplier
233
                                 ; R - Reserved, P - Port multiplier
230
 
234
 
231
                  rb 2           ; Reserved
235
                  rb 2           ; Reserved
232
    DMAbufferID   dq ?           ; DMA Buffer Identifier.
236
    DMAbufferID   dq ?           ; DMA Buffer Identifier.
233
                                 ; Used to Identify DMA buffer in host memory.
237
                                 ; Used to Identify DMA buffer in host memory.
234
                                 ; SATA Spec says host specific and not in Spec.
238
                                 ; SATA Spec says host specific and not in Spec.
235
                                 ; Trying AHCI spec might work.
239
                                 ; Trying AHCI spec might work.
236
 
240
 
237
                  dd ?           ; Reserved
241
                  dd ?           ; Reserved
238
    DMAbufOffset  dd ?           ; Byte offset into buffer. First 2 bits must be 0
242
    DMAbufOffset  dd ?           ; Byte offset into buffer. First 2 bits must be 0
239
    TransferCount dd ?           ; Number of bytes to transfer. Bit 0 must be 0
243
    TransferCount dd ?           ; Number of bytes to transfer. Bit 0 must be 0
240
                  dd ?           ; Reserved
244
                  dd ?           ; Reserved
241
ends
245
ends
242
 
246
 
243
; Set device bits FIS - device to host
247
; Set device bits FIS - device to host
244
struct FIS_DEV_BITS
248
struct FIS_DEV_BITS
245
    fis_type      db ?           ; FIS_TYPE_DEV_BITS
249
    fis_type      db ?           ; FIS_TYPE_DEV_BITS
246
    _flags        db ?           ; 0bNIRRPPPP, N - Notification, I - Interrupt,
250
    _flags        db ?           ; 0bNIRRPPPP, N - Notification, I - Interrupt,
247
                                 ; R - Reserved, P - Port multiplier
251
                                 ; R - Reserved, P - Port multiplier
248
    
252
    
249
    status        db ?           ; Status register
253
    status        db ?           ; Status register
250
    error         db ?           ; Error register
254
    error         db ?           ; Error register
251
    
255
    
252
    protocol      dd ?           ; Protocol
256
    protocol      dd ?           ; Protocol
253
ends
257
ends
254
 
258
 
255
struct HBA_FIS
259
struct HBA_FIS
256
    dsfis         FIS_DMA_SETUP  ; 0x00, DMA Setup FIS
260
    dsfis         FIS_DMA_SETUP  ; 0x00, DMA Setup FIS
257
                  rb 4           ; padding
261
                  rb 4           ; padding
258
 
262
 
259
    psfis         FIS_PIO_SETUP  ; 0x20, PIO Setup FIS
263
    psfis         FIS_PIO_SETUP  ; 0x20, PIO Setup FIS
260
                  rb 12          ; padding
264
                  rb 12          ; padding
261
 
265
 
262
    rfis          FIS_REG_D2H    ; 0x40, Register - Device to Host FIS
266
    rfis          FIS_REG_D2H    ; 0x40, Register - Device to Host FIS
263
                  rb 4           ; padding
267
                  rb 4           ; padding
264
 
268
 
265
    sdbfis        FIS_DEV_BITS   ; 0x58, Set Device Bit FIS
269
    sdbfis        FIS_DEV_BITS   ; 0x58, Set Device Bit FIS
266
 
270
 
267
    ufis          rb 64          ; 0x60
271
    ufis          rb 64          ; 0x60
268
 
272
 
269
                  rb (0x100 - 0xA0) ; 0xA0, Reserved
273
                  rb (0x100 - 0xA0) ; 0xA0, Reserved
270
ends
274
ends
271
 
275
 
272
; --------------------------------------------------
276
; --------------------------------------------------
273
uglobal
277
uglobal
274
align 4
278
align 4
275
        ahci_controller AHCI_DATA
279
        ahci_controller AHCI_DATA
276
        port_data_arr   rb (sizeof.PORT_DATA*AHCI_MAX_PORTS)
280
        port_data_arr   rb (sizeof.PORT_DATA*AHCI_MAX_PORTS)
277
endg
281
endg
278
 
282
 
279
; -----------------------------------------------------------------------
283
; -----------------------------------------------------------------------
280
; detect ahci controller and initialize
284
; detect ahci controller and initialize
281
align 4
285
align 4
282
ahci_init:
286
ahci_init:
283
        mov     ecx, ahci_controller
287
        mov     ecx, ahci_controller
284
        mov     esi, pcidev_list
288
        mov     esi, pcidev_list
285
.find_ahci_ctr:
289
.find_ahci_ctr:
286
        mov     esi, [esi + PCIDEV.fd]
290
        mov     esi, [esi + PCIDEV.fd]
287
        cmp     esi, pcidev_list
291
        cmp     esi, pcidev_list
288
        jz      .ahci_ctr_not_found
292
        jz      .ahci_ctr_not_found
289
        mov     eax, [esi + PCIDEV.class]
293
        mov     eax, [esi + PCIDEV.class]
290
        ;DEBUGF  1, "K: device class = %x\n", eax
294
        ;DEBUGF  1, "K: device class = %x\n", eax
291
        shr     eax, 8 ; shift right because lowest 8 bits if ProgIf field
295
        shr     eax, 8 ; shift right because lowest 8 bits if ProgIf field
292
        cmp     eax, 0x0106 ; 0x01 - Mass Storage Controller class,  0x06 - Serial ATA Controller subclass
296
        cmp     eax, 0x0106 ; 0x01 - Mass Storage Controller class,  0x06 - Serial ATA Controller subclass
293
        jz      .ahci_ctr_found
297
        jz      .ahci_ctr_found
294
        jmp     .find_ahci_ctr
298
        jmp     .find_ahci_ctr
295
 
299
 
296
.ahci_ctr_not_found:
300
.ahci_ctr_not_found:
297
        DEBUGF  1, "K: AHCI controller not found\n"
301
        DEBUGF  1, "K: AHCI controller not found\n"
298
        ret
302
        ret
299
 
303
 
300
.ahci_ctr_found:
304
.ahci_ctr_found:
301
        mov     [ahci_controller + AHCI_DATA.pcidev], esi
305
        mov     [ahci_controller + AHCI_DATA.pcidev], esi
302
 
306
 
303
        mov     eax, [esi+PCIDEV.class]
307
        mov     eax, [esi+PCIDEV.class]
304
        movzx   ebx, byte [esi+PCIDEV.bus]
308
        movzx   ebx, byte [esi+PCIDEV.bus]
305
        movzx   ecx, byte [esi+PCIDEV.devfn]
309
        movzx   ecx, byte [esi+PCIDEV.devfn]
306
        shr     ecx, 3 ; get rid of 3 lowest bits (function code), the rest bits is device code
310
        shr     ecx, 3 ; get rid of 3 lowest bits (function code), the rest bits is device code
307
        movzx   edx, byte [esi+PCIDEV.devfn]
311
        movzx   edx, byte [esi+PCIDEV.devfn]
308
        and     edx, 00000111b ; get only 3 lowest bits (function code)
312
        and     edx, 00000111b ; get only 3 lowest bits (function code)
309
        DEBUGF  1, "K: found AHCI controller, (class, subcl, progif) = %x, bus = %x, device = %x, function = %x\n", eax, ebx, ecx, edx
313
        DEBUGF  1, "K: found AHCI controller, (class, subcl, progif) = %x, bus = %x, device = %x, function = %x\n", eax, ebx, ecx, edx
310
        
314
        
311
        ; get BAR5 value, it is physical address 
315
        ; get BAR5 value, it is physical address 
312
        movzx   ebx, [esi + PCIDEV.bus]
316
        movzx   ebx, [esi + PCIDEV.bus]
313
        movzx   ebp, [esi + PCIDEV.devfn]
317
        movzx   ebp, [esi + PCIDEV.devfn]
314
        stdcall pci_read32, ebx, ebp, PCI_REG_BAR5
318
        stdcall pci_read32, ebx, ebp, PCI_REG_BAR5
315
        DEBUGF  1, "K: AHCI controller MMIO = %x\n", eax
319
        DEBUGF  1, "K: AHCI controller MMIO = %x\n", eax
316
        mov     edi, eax
320
        mov     edi, eax
317
 
321
 
318
        ; get the size of MMIO region
322
        ; get the size of MMIO region
319
        stdcall pci_write32, ebx, ebp, PCI_REG_BAR5, 0xFFFFFFFF
323
        stdcall pci_write32, ebx, ebp, PCI_REG_BAR5, 0xFFFFFFFF
320
        stdcall pci_read32, ebx, ebp, PCI_REG_BAR5
324
        stdcall pci_read32, ebx, ebp, PCI_REG_BAR5
321
        not     eax
325
        not     eax
322
        inc     eax
326
        inc     eax
323
        DEBUGF  1, "K: AHCI: MMIO region size = 0x%x bytes\n", eax
327
        DEBUGF  1, "K: AHCI: MMIO region size = 0x%x bytes\n", eax
324
 
328
 
325
        ; Map MMIO region to virtual memory
329
        ; Map MMIO region to virtual memory
326
        stdcall map_io_mem, edi, eax, PG_SWR + PG_NOCACHE
330
        stdcall map_io_mem, edi, eax, PG_SWR + PG_NOCACHE
327
        mov     [ahci_controller + AHCI_DATA.abar], eax
331
        mov     [ahci_controller + AHCI_DATA.abar], eax
328
        DEBUGF  1, "K: AHCI controller BAR5 mapped to virtual addr %x\n", eax
332
        DEBUGF  1, "K: AHCI controller BAR5 mapped to virtual addr %x\n", eax
329
 
333
 
330
        ; Restore the original BAR5 value
334
        ; Restore the original BAR5 value
331
        stdcall pci_write32, ebx, ebp, PCI_REG_BAR5, edi
335
        stdcall pci_write32, ebx, ebp, PCI_REG_BAR5, edi
332
 
336
 
333
        ; Enable dma bus mastering, memory space access, clear the "disable interrupts" bit
337
        ; Enable dma bus mastering, memory space access, clear the "disable interrupts" bit
334
        ; Usually, it is already done before us
338
        ; Usually, it is already done before us
335
        movzx   ebx, [esi + PCIDEV.bus]
339
        movzx   ebx, [esi + PCIDEV.bus]
336
        movzx   ebp, [esi + PCIDEV.devfn]
340
        movzx   ebp, [esi + PCIDEV.devfn]
337
        stdcall pci_read32, ebx, ebp, PCI_REG_STATUS_COMMAND
341
        stdcall pci_read32, ebx, ebp, PCI_REG_STATUS_COMMAND
338
        DEBUGF  1, "K: AHCI: pci_status_command = %x\nEnabling interrupts, DMA bus mastering and memory space access\n", eax
342
        DEBUGF  1, "K: AHCI: pci_status_command = %x\nEnabling interrupts, DMA bus mastering and memory space access\n", eax
339
        or      eax, 0x06 ; pci.command |= 0x06 (dma bus mastering + memory space access)
343
        or      eax, 0x06 ; pci.command |= 0x06 (dma bus mastering + memory space access)
340
        btr     eax, 10 ; clear the "disable interrupts" bit
344
        btr     eax, 10 ; clear the "disable interrupts" bit
341
        DEBUGF  1, "K: AHCI: pci_status_command = %x\n", eax
345
        DEBUGF  1, "K: AHCI: pci_status_command = %x\n", eax
342
        stdcall pci_write32, ebx, ebp, PCI_REG_STATUS_COMMAND, eax
346
        stdcall pci_write32, ebx, ebp, PCI_REG_STATUS_COMMAND, eax
343
 
347
 
344
        ; ; Print some register values to debug board
348
        ; ; Print some register values to debug board
345
        ; mov     esi, [ahci_controller + AHCI_DATA.abar]
349
        ; mov     esi, [ahci_controller + AHCI_DATA.abar]
346
        ; DEBUGF  1, "K: AHCI: HBA.cap = %x, HBA.ghc = %x, HBA_MEM.version = %x\n", [esi + HBA_MEM.cap], [esi + HBA_MEM.ghc], [esi + HBA_MEM.version]
350
        ; DEBUGF  1, "K: AHCI: HBA.cap = %x, HBA.ghc = %x, HBA_MEM.version = %x\n", [esi + HBA_MEM.cap], [esi + HBA_MEM.ghc], [esi + HBA_MEM.version]
347
 
351
 
348
        ;-------------------------------------------------------
352
        ;-------------------------------------------------------
349
        ; Request BIOS/OS ownership handoff, if supported. (TODO check correctness)
353
        ; Request BIOS/OS ownership handoff, if supported. (TODO check correctness)
350
        mov     esi, [ahci_controller + AHCI_DATA.abar]
354
        mov     esi, [ahci_controller + AHCI_DATA.abar]
351
        ;mov     ebx, [esi + HBA_MEM.cap2]
355
        ;mov     ebx, [esi + HBA_MEM.cap2]
352
        ;DEBUGF  1, "K: AHCI: HBA_MEM.cap2 = %x\n", ebx
356
        ;DEBUGF  1, "K: AHCI: HBA_MEM.cap2 = %x\n", ebx
353
        bt      [esi + HBA_MEM.cap2], bit_AHCI_HBA_CAP2_BOH
357
        bt      [esi + HBA_MEM.cap2], bit_AHCI_HBA_CAP2_BOH
354
        jnc     .end_handoff
358
        jnc     .end_handoff
355
        DEBUGF  1, "K: AHCI: requesting AHCI ownership change...\n"
359
        DEBUGF  1, "K: AHCI: requesting AHCI ownership change...\n"
356
        bts     [esi + HBA_MEM.bohc], bit_AHCI_HBA_BOHC_OOS
360
        bts     [esi + HBA_MEM.bohc], bit_AHCI_HBA_BOHC_OOS
357
 
361
 
358
.wait_not_bos:
362
.wait_not_bos:
359
        bt      [esi + HBA_MEM.bohc], bit_AHCI_HBA_BOHC_BOS
363
        bt      [esi + HBA_MEM.bohc], bit_AHCI_HBA_BOHC_BOS
360
        jc      .wait_not_bos
364
        jc      .wait_not_bos
361
 
365
 
362
        mov     ebx, 3
366
        mov     ebx, 3
363
        call    delay_hs
367
        call    delay_hs
364
 
368
 
365
        ; if Bios Busy is still set after 30 mS, wait 2 seconds.
369
        ; if Bios Busy is still set after 30 mS, wait 2 seconds.
366
        bt      [esi + HBA_MEM.bohc], bit_AHCI_HBA_BOHC_BB
370
        bt      [esi + HBA_MEM.bohc], bit_AHCI_HBA_BOHC_BB
367
        jnc     @f
371
        jnc     @f
368
 
372
 
369
        mov     ebx, 200
373
        mov     ebx, 200
370
        call    delay_hs
374
        call    delay_hs
371
@@:
375
@@:
372
        DEBUGF  1, "K: AHCI: ownership change completed.\n"
376
        DEBUGF  1, "K: AHCI: ownership change completed.\n"
373
 
377
 
374
.end_handoff:
378
.end_handoff:
375
        ;-------------------------------------------------------
379
        ;-------------------------------------------------------
376
 
380
 
377
        ; enable the AHCI and reset it
381
        ; enable the AHCI and reset it
378
        bts     [esi + HBA_MEM.ghc], bit_AHCI_HBA_GHC_AHCI_ENABLE
382
        bts     [esi + HBA_MEM.ghc], bit_AHCI_HBA_GHC_AHCI_ENABLE
379
        bts     [esi + HBA_MEM.ghc], bit_AHCI_HBA_GHC_RESET
383
        bts     [esi + HBA_MEM.ghc], bit_AHCI_HBA_GHC_RESET
380
 
384
 
381
        ; wait for reset to complete
385
        ; wait for reset to complete
382
.wait_reset:
386
.wait_reset:
383
        bt      [esi + HBA_MEM.ghc], bit_AHCI_HBA_GHC_RESET
387
        bt      [esi + HBA_MEM.ghc], bit_AHCI_HBA_GHC_RESET
384
        jc      .wait_reset
388
        jc      .wait_reset
385
 
389
 
386
        ; enable the AHCI and interrupts
390
        ; enable the AHCI and interrupts
387
        bts     [esi + HBA_MEM.ghc], bit_AHCI_HBA_GHC_AHCI_ENABLE
391
        bts     [esi + HBA_MEM.ghc], bit_AHCI_HBA_GHC_AHCI_ENABLE
388
        bts     [esi + HBA_MEM.ghc], bit_AHCI_HBA_GHC_INTERRUPT_ENABLE
392
        bts     [esi + HBA_MEM.ghc], bit_AHCI_HBA_GHC_INTERRUPT_ENABLE
389
        mov     ebx, 2
393
        mov     ebx, 2
390
        call    delay_hs
394
        call    delay_hs
391
        
395
        
392
        DEBUGF  1, "K: AHCI: caps: %x %x, ver: %x, ghc: %x, pi: %x\n", [esi + HBA_MEM.cap], [esi + HBA_MEM.cap2], [esi + HBA_MEM.version], [esi + HBA_MEM.ghc], [esi + HBA_MEM.pi]
396
        DEBUGF  1, "K: AHCI: caps: %x %x, ver: %x, ghc: %x, pi: %x\n", [esi + HBA_MEM.cap], [esi + HBA_MEM.cap2], [esi + HBA_MEM.version], [esi + HBA_MEM.ghc], [esi + HBA_MEM.pi]
393
 
397
 
394
        ; TODO:
398
        ; TODO:
395
        ; calculate irq line
399
        ; calculate irq line
396
        ; ahciHBA->ghc |= AHCI_GHC_IE;
400
        ; ahciHBA->ghc |= AHCI_GHC_IE;
397
        ; IDT::RegisterInterruptHandler(irq, InterruptHandler);
401
        ; IDT::RegisterInterruptHandler(irq, InterruptHandler);
398
        ; ahciHBA->is = 0xffffffff;
402
        ; ahciHBA->is = 0xffffffff;
399
 
403
 
400
        xor     ebx, ebx
404
        xor     ebx, ebx
401
.detect_drives:
405
.detect_drives:
402
        cmp     ebx, AHCI_MAX_PORTS
406
        cmp     ebx, AHCI_MAX_PORTS
403
        jae     .end_detect_drives
407
        jae     .end_detect_drives
404
 
408
 
405
        ; if port with index ebx is not implemented then go to next
409
        ; if port with index ebx is not implemented then go to next
406
        mov     ecx, [esi + HBA_MEM.pi]
410
        mov     ecx, [esi + HBA_MEM.pi]
407
        bt      ecx, ebx
411
        bt      ecx, ebx
408
        jnc     .continue_detect_drives
412
        jnc     .continue_detect_drives
409
 
413
 
410
        mov     edi, ebx
414
        mov     edi, ebx
411
        shl     edi, BSF sizeof.HBA_PORT
415
        imul    edi, sizeof.HBA_PORT
412
        add     edi, HBA_MEM.ports
416
        add     edi, HBA_MEM.ports
413
        add     edi, esi
417
        add     edi, esi
414
        ; now edi - base of HBA_MEM.ports[ebx]
418
        ; now edi - base of HBA_MEM.ports[ebx]
415
 
419
 
416
        DEBUGF  1, "K: AHCI: port %d, ssts = %x\n", ebx, [edi + HBA_PORT.sata_status]
420
        DEBUGF  1, "K: AHCI: port %d, ssts = %x\n", ebx, [edi + HBA_PORT.sata_status]
417
 
421
 
418
        mov     ecx, [edi + HBA_PORT.sata_status]
422
        mov     ecx, [edi + HBA_PORT.sata_status]
419
        shr     ecx, 8
423
        shr     ecx, 8
420
        and     ecx, 0x0F
424
        and     ecx, 0x0F
421
        cmp     ecx, AHCI_HBA_PORT_IPM_ACTIVE
425
        cmp     ecx, AHCI_HBA_PORT_IPM_ACTIVE
422
        jne     .continue_detect_drives
426
        jne     .continue_detect_drives
423
 
427
 
424
        mov     ecx, [edi + HBA_PORT.sata_status]
428
        mov     ecx, [edi + HBA_PORT.sata_status]
425
        and     ecx, AHCI_HBA_PxSSTS_DET
429
        and     ecx, AHCI_HBA_PxSSTS_DET
426
        cmp     ecx, AHCI_HBA_PxSSTS_DET_PRESENT
430
        cmp     ecx, AHCI_HBA_PxSSTS_DET_PRESENT
427
        jne     .continue_detect_drives
431
        jne     .continue_detect_drives
428
 
432
 
429
        DEBUGF  1, "K: AHCI: found drive at port %d, signature = %x\n", ebx, [edi + HBA_PORT.signature]  
433
        DEBUGF  1, "K: AHCI: found drive at port %d, signature = %x\n", ebx, [edi + HBA_PORT.signature]  
430
 
434
 
431
        mov     ecx, ebx
435
        mov     ecx, ebx
432
        shl     ecx, BSF sizeof.PORT_DATA
436
        imul    ecx, sizeof.PORT_DATA
433
        add     ecx, port_data_arr
437
        add     ecx, port_data_arr
434
        stdcall ahci_port_rebase, edi, ebx, ecx
438
        stdcall ahci_port_rebase, edi, ebx, ecx
-
 
439
 
-
 
440
        stdcall ahci_port_identify, ecx
435
 
441
 
436
.continue_detect_drives:
442
.continue_detect_drives:
437
        inc     ebx
443
        inc     ebx
438
        jmp     .detect_drives
444
        jmp     .detect_drives
439
 
445
 
440
        
446
        
441
 
447
 
442
.end_detect_drives:
448
.end_detect_drives:
443
        
449
        
444
 
450
 
445
        ret
451
        ret
446
; -------------------------------------------------
452
; -------------------------------------------------
-
 
453
 
-
 
454
modelstr  rb 42
-
 
455
; Identify drive on port ; TODO check
-
 
456
; in: pdata - address of PORT_DATA structure
-
 
457
proc ahci_port_identify stdcall, pdata: dword
-
 
458
        locals
-
 
459
            cmdslot dd ?
-
 
460
            cmdheader dd ?
-
 
461
            cmdtable  dd ?
-
 
462
            buf_phys  dd ?
-
 
463
            buf_virt  dd ?
-
 
464
        endl
-
 
465
 
-
 
466
        pushad
-
 
467
        
-
 
468
        mov     esi, [pdata] ; esi - address of PORT_DATA struct of port
-
 
469
        mov     edi, [esi + PORT_DATA.port] ; edi - address of HBA_PORT struct of port
-
 
470
 
-
 
471
        mov     eax, edi
-
 
472
        call    ahci_find_cmdslot
-
 
473
 
-
 
474
        cmp     eax, -1
-
 
475
        jne      .cmdslot_found
-
 
476
 
-
 
477
        DEBUGF  1, "No free cmdslot on port %u\n", [esi + PORT_DATA.portno]
-
 
478
 
-
 
479
.cmdslot_found:
-
 
480
        mov     [cmdslot], eax
-
 
481
        DEBUGF  1, "Found free cmdslot %u on port %u\n", [cmdslot], [esi + PORT_DATA.portno]
-
 
482
 
-
 
483
        shl     eax, BSF sizeof.HBA_CMD_HDR
-
 
484
        add     eax, [esi + PORT_DATA.clb]
-
 
485
        mov     [cmdheader], eax ; address of virtual mapping of command header
-
 
486
        mov     eax, [cmdslot]
-
 
487
        mov     eax, [esi + eax*4 + PORT_DATA.ctba_arr]
-
 
488
        mov     [cmdtable], eax ; address of virtual mapping of command table of command header
-
 
489
 
-
 
490
        stdcall _memset, eax, 0, sizeof.HBA_CMD_TBL
-
 
491
 
-
 
492
        call    alloc_page
-
 
493
        mov     [buf_phys], eax
-
 
494
 
-
 
495
        stdcall map_io_mem, eax, 4096, PG_NOCACHE + PG_SWR  ; map to virt memory so we can work with it
-
 
496
        mov     [buf_virt], eax
-
 
497
 
-
 
498
        mov     eax, [cmdtable]
-
 
499
        mov     ebx, [buf_phys]
-
 
500
        mov     dword [eax + HBA_CMD_TBL.prdt_entry + HBA_PRDT_ENTRY.dba], ebx
-
 
501
        mov     dword [eax + HBA_CMD_TBL.prdt_entry + HBA_PRDT_ENTRY.dbau], 0
-
 
502
        mov     dword [eax + HBA_CMD_TBL.prdt_entry + HBA_PRDT_ENTRY._flags], 512 - 1 ; why -1 ?
-
 
503
        mov     eax, [cmdheader]
-
 
504
        mov     [eax + HBA_CMD_HDR.prdtl], 1
-
 
505
 
-
 
506
        mov     eax, [cmdtable]
-
 
507
        mov     byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.fis_type], FIS_TYPE_REG_H2D
-
 
508
        movzx   ebx, byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D._flags]
-
 
509
        bts     ebx, bit_AHCI_H2D_FLAG_CMD ; Set Command bit in H2D FIS.
-
 
510
        mov     byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D._flags], bl
-
 
511
        ; if (port->signature == AHCI_PxSIG_ATAPI) cmd_fis->command = ATA_IDENTIFY_PACKET;
-
 
512
        ; else cmd_fis->command = ATA_IDENTIFY;
-
 
513
        mov     byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.command], 0xEC ;ATA_IDENTIFY ; 
-
 
514
        mov     byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.device], 0
-
 
515
 
-
 
516
        ; TODO Wait on previous command to complete. AHCIPortWait(bd->port_num, tS + 2);
-
 
517
        mov     ebx, 20 ;;;
-
 
518
        call    delay_hs ;;;
-
 
519
 
-
 
520
        mov     eax, [cmdslot]
-
 
521
        bts     [edi + HBA_PORT.command_issue], eax ; Issue the command
-
 
522
 
-
 
523
        ; TODO AHCIPortCmdWait(bd->port_num, cmd_slot);
-
 
524
        mov     ebx, 20 ;;;
-
 
525
        call    delay_hs ;;;
-
 
526
 
-
 
527
        mov     esi, [buf_virt]
-
 
528
        add     esi, 27*2
-
 
529
        mov     edi, modelstr
-
 
530
        mov     ecx, ((46-27)+1)*2
-
 
531
        cld
-
 
532
        rep movsb
-
 
533
        mov     byte [edi], 0
-
 
534
        
-
 
535
        xor     ecx, ecx
-
 
536
.reverse1:
-
 
537
        cmp     ecx, ((46-27)+1)*2
-
 
538
        jae     .reverse1_end
-
 
539
        mov     bl, byte [modelstr + ecx]
-
 
540
        mov     dl, byte [modelstr + ecx + 1]
-
 
541
        mov     byte [modelstr + ecx], dl
-
 
542
        mov     byte [modelstr + ecx + 1], bl
-
 
543
        add     ecx, 2
-
 
544
        jmp     .reverse1
-
 
545
.reverse1_end:
-
 
546
        DEBUGF  1, "Ident data of port: model = %s\n", modelstr
-
 
547
 
-
 
548
.ret:
-
 
549
        popad
-
 
550
        ret
-
 
551
endp
447
 
552
 
448
; Start command engine
553
; Start command engine
449
; in: eax - address of HBA_PORT structure
554
; in: eax - address of HBA_PORT structure
450
ahci_start_cmd:
555
ahci_start_cmd:
451
.wait_cr: ; Wait until CR (bit15) is cleared
556
.wait_cr: ; Wait until CR (bit15) is cleared
452
        bt      [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_CR
557
        bt      [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_CR
453
        jc      .wait_cr
558
        jc      .wait_cr
454
 
559
 
455
        ; Set FRE (bit4) and ST (bit0)
560
        ; Set FRE (bit4) and ST (bit0)
456
        bts     [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_FRE
561
        bts     [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_FRE
457
        bts     [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_ST
562
        bts     [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_ST
458
        ; maybe here call ahci flush cmd ? TODO (see seakernel)
563
        ; maybe here call ahci flush cmd ? TODO (see seakernel)
459
        ret
564
        ret
460
 
565
 
461
; Stop command engine
566
; Stop command engine
462
; in: eax - address of HBA_PORT structure
567
; in: eax - address of HBA_PORT structure
463
ahci_stop_cmd:
568
ahci_stop_cmd:
464
        btr     [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_ST ; Clear ST (bit0)
569
        btr     [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_ST ; Clear ST (bit0)
465
        btr     [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_FRE ; Clear FRE (bit4)
570
        btr     [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_FRE ; Clear FRE (bit4)
466
.wait_fr_cr: ; Wait until FR (bit14), CR (bit15) are cleared
571
.wait_fr_cr: ; Wait until FR (bit14), CR (bit15) are cleared
467
        bt      [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_FR
572
        bt      [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_FR
468
        jc      .wait_fr_cr
573
        jc      .wait_fr_cr
469
        bt      [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_CR
574
        bt      [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_CR
470
        jc      .wait_fr_cr
575
        jc      .wait_fr_cr
471
 
576
 
472
        ret
577
        ret
473
 
578
 
474
; The commands may not take effect until the command
579
; The commands may not take effect until the command
475
; register is read again by software, because reasons.
580
; register is read again by software, because reasons.
476
; in: eax - address of HBA_PORT structure
581
; in: eax - address of HBA_PORT structure
477
; out: eax - command register value
582
; out: eax - command register value
478
ahci_flush_cmd:
583
ahci_flush_cmd:
479
        mov     eax, [eax + HBA_PORT.command]
584
        mov     eax, [eax + HBA_PORT.command]
480
        ret
585
        ret
481
 
586
 
482
; Send command to port
587
; Send command to port
483
; in: eax - address of HBA_PORT structure
588
; in: eax - address of HBA_PORT structure
484
;     ebx - index of command slot
589
;     ebx - index of command slot
485
ahci_send_cmd:
590
ahci_send_cmd:
486
        push    ecx
591
        push    ecx
487
        mov     [eax + HBA_PORT.interrupt_status], 0xFFFFFFFF
592
        mov     [eax + HBA_PORT.interrupt_status], 0xFFFFFFFF
488
        
593
        
489
        mov     cl, bl
594
        mov     cl, bl
490
        mov     [eax + HBA_PORT.command_issue], 1
595
        mov     [eax + HBA_PORT.command_issue], 1
491
        shl     [eax + HBA_PORT.command_issue], cl
596
        shl     [eax + HBA_PORT.command_issue], cl
492
 
597
 
493
        call    ahci_flush_cmd
598
        call    ahci_flush_cmd
494
        pop     ecx
599
        pop     ecx
495
        ret
600
        ret
496
 
601
 
497
; ---------------------------------------------------------------------------
602
; ---------------------------------------------------------------------------
498
; TODO: check correctness
603
; TODO: check correctness
499
; in: port - address of HBA_PORT structure
604
; in: port - address of HBA_PORT structure
500
;     portno - port index (0..31)
605
;     portno - port index (0..31)
501
;     pdata - address of PORT_DATA structure
606
;     pdata - address of PORT_DATA structure
502
proc ahci_port_rebase stdcall, port: dword, portno: dword, pdata: dword
607
proc ahci_port_rebase stdcall, port: dword, portno: dword, pdata: dword
503
        locals
608
        locals
504
            phys_page1  dd ?
609
            phys_page1  dd ?
505
            virt_page1  dd ?
610
            virt_page1  dd ?
506
            phys_page23 dd ?
611
            phys_page23 dd ?
507
            virt_page23 dd ?
612
            virt_page23 dd ?
508
            tmp         dd ?
613
            tmp         dd ?
509
        endl
614
        endl
510
 
615
 
511
        pushad
616
        pushad
512
 
617
 
513
        DEBUGF  1, "Rebasing port %u\n", [portno]
618
        DEBUGF  1, "Rebasing port %u\n", [portno]
514
 
619
 
515
        mov     eax, [port]
620
        mov     eax, [port]
516
        call    ahci_stop_cmd
621
        call    ahci_stop_cmd
517
 
622
 
518
        ; Command list entry size = 32
623
        ; Command list entry size = 32
519
        ; Command list entry maxim count = 32
624
        ; Command list entry maxim count = 32
520
        ; Command list maxim size = 32*32 = 1K per port
625
        ; Command list maxim size = 32*32 = 1K per port
521
        call    alloc_page
626
        call    alloc_page
522
        mov     [phys_page1], eax
627
        mov     [phys_page1], eax
523
 
628
 
524
        stdcall map_io_mem, eax, 4096, PG_NOCACHE + PG_SWR  ; map to virt memory so we can work with it
629
        stdcall map_io_mem, eax, 4096, PG_NOCACHE + PG_SWR  ; map to virt memory so we can work with it
525
        mov     [virt_page1], eax
630
        mov     [virt_page1], eax
526
 
631
 
527
        mov     esi, [port]
632
        mov     esi, [port]
528
        mov     ebx, [phys_page1]
633
        mov     ebx, [phys_page1]
529
        mov     [esi + HBA_PORT.command_list_base_l], ebx ; set the command list base
634
        mov     [esi + HBA_PORT.command_list_base_l], ebx ; set the command list base
530
        mov     [esi + HBA_PORT.command_list_base_h], 0  ; zero upper 32 bits of addr cause we are 32 bit os 
635
        mov     [esi + HBA_PORT.command_list_base_h], 0  ; zero upper 32 bits of addr cause we are 32 bit os 
531
 
636
 
532
        mov     edi, [pdata]
637
        mov     edi, [pdata]
533
        mov     ebx, [virt_page1]
638
        mov     ebx, [virt_page1]
534
        mov     [edi + PORT_DATA.clb], ebx ; set pdata->clb
639
        mov     [edi + PORT_DATA.clb], ebx ; set pdata->clb
535
 
640
 
536
        mov     eax, [port]
641
        mov     eax, [port]
537
        mov     [edi + PORT_DATA.port], eax ; set pdata->port
642
        mov     [edi + PORT_DATA.port], eax ; set pdata->port
-
 
643
        mov     eax, [portno]               ; set pdata->portno
-
 
644
        mov     [edi + PORT_DATA.portno], eax
538
 
645
 
539
        stdcall _memset, ebx, 0, 1024 ; zero out the command list
646
        stdcall _memset, ebx, 0, 1024 ; zero out the command list
540
        
647
        
541
        ; FIS entry size = 256 bytes per port
648
        ; FIS entry size = 256 bytes per port
542
        mov     eax, [phys_page1]
649
        mov     eax, [phys_page1]
543
        add     eax, 1024
650
        add     eax, 1024
544
        mov     [esi + HBA_PORT.fis_base_l], eax
651
        mov     [esi + HBA_PORT.fis_base_l], eax
545
        mov     [esi + HBA_PORT.fis_base_h], 0
652
        mov     [esi + HBA_PORT.fis_base_h], 0
546
 
653
 
547
        mov     eax, [virt_page1]
654
        mov     eax, [virt_page1]
548
        add     eax, 1024
655
        add     eax, 1024
549
        mov     [edi + PORT_DATA.fb], eax ; set pdata->fb 
656
        mov     [edi + PORT_DATA.fb], eax ; set pdata->fb 
550
        stdcall _memset, eax, 0, 256 ; zero out
657
        stdcall _memset, eax, 0, 256 ; zero out
551
        
658
        
552
        stdcall alloc_pages, 2
659
        stdcall alloc_pages, 2
553
        mov     [phys_page23], eax
660
        mov     [phys_page23], eax
554
        stdcall map_io_mem, eax, 2*4096, PG_NOCACHE + PG_SWR
661
        stdcall map_io_mem, eax, 2*4096, PG_NOCACHE + PG_SWR
555
        mov     [virt_page23], eax
662
        mov     [virt_page23], eax
556
 
663
 
557
        ; Command table size = 256*32 = 8K per port
664
        ; Command table size = 256*32 = 8K per port
558
        mov     edx, [edi + PORT_DATA.clb] ; cmdheader array base
665
        mov     edx, [edi + PORT_DATA.clb] ; cmdheader array base
559
        xor     ecx, ecx
666
        xor     ecx, ecx
560
 
667
 
561
.for1:
668
.for1:
562
        cmp     ecx, 32
669
        cmp     ecx, 32
563
        jae     .for1_end
670
        jae     .for1_end
564
 
671
 
565
        mov     ebx, ecx
672
        mov     ebx, ecx
566
        shl     ebx, BSF sizeof.HBA_CMD_HDR
673
        shl     ebx, BSF sizeof.HBA_CMD_HDR
567
        add     ebx, edx ; ebx = cmdheader[ecx]
674
        add     ebx, edx ; ebx = cmdheader[ecx]
568
 
675
 
569
        mov     [ebx + HBA_CMD_HDR.prdtl], 8 ; 8 prdt entries per command table
676
        mov     [ebx + HBA_CMD_HDR.prdtl], 8 ; 8 prdt entries per command table
570
 
677
 
571
        ; 256 bytes per command table, 64+16+48+16*8
678
        ; 256 bytes per command table, 64+16+48+16*8
572
 
679
 
573
        push    edx
680
        push    edx
574
        
681
        
575
        ; cmdheader[ecx].ctba = phys_page23 + ecx*256
682
        ; cmdheader[ecx].ctba = phys_page23 + ecx*256
576
        mov     [ebx + HBA_CMD_HDR.ctba], ecx
683
        mov     [ebx + HBA_CMD_HDR.ctba], ecx
577
        shl     [ebx + HBA_CMD_HDR.ctba], BSF 256 ; *= 256
684
        shl     [ebx + HBA_CMD_HDR.ctba], BSF 256 ; *= 256
578
        mov     eax, [ebx + HBA_CMD_HDR.ctba]
685
        mov     eax, [ebx + HBA_CMD_HDR.ctba]
579
        mov     edx, [phys_page23]
686
        mov     edx, [phys_page23]
580
        add     [ebx + HBA_CMD_HDR.ctba], edx
687
        add     [ebx + HBA_CMD_HDR.ctba], edx
581
 
688
 
582
        add     eax, [virt_page23]
689
        add     eax, [virt_page23]
583
        mov     [tmp], eax  ; tmp = virt_page23 + ecx*256
690
        mov     [tmp], eax  ; tmp = virt_page23 + ecx*256
584
        lea     eax, [ecx*4 + edi + PORT_DATA.ctba_arr] ; eax = pdata->ctba_arr[ecx]
691
        lea     eax, [ecx*4 + edi + PORT_DATA.ctba_arr] ; eax = pdata->ctba_arr[ecx]
585
        mov     edx, [tmp]
692
        mov     edx, [tmp]
586
        mov     [eax], edx  ; pdata->ctba_arr[ecx] = virt_page23 + ecx*256
693
        mov     [eax], edx  ; pdata->ctba_arr[ecx] = virt_page23 + ecx*256
587
 
694
 
588
        pop     edx
695
        pop     edx
589
 
696
 
590
        mov     [ebx + HBA_CMD_HDR.ctbau], 0
697
        mov     [ebx + HBA_CMD_HDR.ctbau], 0
591
        stdcall _memset, [eax], 0, 256 ; zero out
698
        stdcall _memset, [eax], 0, 256 ; zero out
592
 
699
 
593
        inc     ecx
700
        inc     ecx
594
        jmp     .for1
701
        jmp     .for1
595
.for1_end:
702
.for1_end:
596
        
703
        
597
        mov     eax, [port]
704
        mov     eax, [port]
598
        call    ahci_start_cmd
705
        call    ahci_start_cmd
599
 
706
 
600
        DEBUGF  1, "End rebasing port %u\n", [portno]
707
        DEBUGF  1, "End rebasing port %u\n", [portno]
601
        popad
708
        popad
602
        ret    
709
        ret    
603
endp
710
endp
604
 
711
 
605
; ----------------------------------------------------------- ; TODO check
712
; ----------------------------------------------------------- ; TODO check
606
; Find a free command list slot
713
; Find a free command list slot
607
; in: eax - address of HBA_PORT structure
714
; in: eax - address of HBA_PORT structure
608
; out: eax - if not found -1, else slot index
715
; out: eax - if not found -1, else slot index
609
ahci_find_cmdslot:
716
ahci_find_cmdslot:
610
        push    ebx ecx edx esi
717
        push    ebx ecx edx esi
611
        ; If not set in SACT and CI, the slot is free
718
        ; If not set in SACT and CI, the slot is free
612
        mov     ebx, [eax + HBA_PORT.sata_active]
719
        mov     ebx, [eax + HBA_PORT.sata_active]
613
        or      ebx, [eax + HBA_PORT.command_issue] ; ebx = slots
720
        or      ebx, [eax + HBA_PORT.command_issue] ; ebx = slots
614
 
721
 
615
        mov     esi, [ahci_controller + AHCI_DATA.abar]
722
        mov     esi, [ahci_controller + AHCI_DATA.abar]
616
        mov     edx, [esi + HBA_MEM.cap]
723
        mov     edx, [esi + HBA_MEM.cap]
617
        shr     edx, 8
724
        shr     edx, 8
618
        and     edx, 0xf
725
        and     edx, 0xf
619
        DEBUGF  1, "Number of Command Slots on each port = %u\n", edx
726
        DEBUGF  1, "Number of Command Slots on each port = %u\n", edx
620
        xor     ecx, ecx
727
        xor     ecx, ecx
621
.for1:
728
.for1:
622
        cmp     ecx, edx
729
        cmp     ecx, edx
623
        jae     .for1_end
730
        jae     .for1_end
624
 
731
 
625
        ; if ((slots&1) == 0) return i;
732
        ; if ((slots&1) == 0) return i;
626
        bt      ebx, 0
733
        bt      ebx, 0
627
        jc      .cont1
734
        jc      .cont1
628
 
735
 
629
        mov     eax, ecx
736
        mov     eax, ecx
630
        jmp     .ret
737
        jmp     .ret
631
 
738
 
632
.cont1:
739
.cont1:
633
        shr     ebx, 1
740
        shr     ebx, 1
634
        inc     ecx
741
        inc     ecx
635
        jmp     .for1
742
        jmp     .for1
636
.for1_end:
743
.for1_end:
637
        DEBUGF  1, "Cannot find free command list entry\n"
744
        DEBUGF  1, "Cannot find free command list entry\n"
638
        mov     eax, -1
745
        mov     eax, -1
639
.ret:
746
.ret:
640
        pop     esi edx ecx ebx
747
        pop     esi edx ecx ebx
641
        ret
748
        ret
642
 
749
 
643
 
750
 
644
proc _memset stdcall, dest:dword, val:byte, cnt:dword ; doesnt clobber any registers
751
proc _memset stdcall, dest:dword, val:byte, cnt:dword ; doesnt clobber any registers
645
        ;DEBUGF  DBG_INFO, "memset(%x, %u, %u)\n", [dest], [val], [cnt]
752
        ;DEBUGF  DBG_INFO, "memset(%x, %u, %u)\n", [dest], [val], [cnt]
646
        push    eax ecx edi
753
        push    eax ecx edi
647
        mov     edi, dword [dest]
754
        mov     edi, dword [dest]
648
        mov     al,  byte [val]
755
        mov     al,  byte [val]
649
        mov     ecx, dword [cnt]
756
        mov     ecx, dword [cnt]
650
        rep stosb   
757
        rep stosb   
651
        pop     edi ecx eax
758
        pop     edi ecx eax
652
        ret 
759
        ret 
653
endp
760
endp