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 |