xref: /haiku/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h (revision 4bd0c1066b227cec4b79883bdef697c7a27f2e90)
1 /*
2  * Copyright 2007, Marcus Overhagen. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 #ifndef _AHCI_DEFS_H
6 #define _AHCI_DEFS_H
7 
8 #include <ata_types.h>
9 #include <bus/PCI.h>
10 #include <bus/SCSI.h>
11 #include <PCI_x86.h>
12 
13 #ifdef __cplusplus
14 extern "C" {
15 #endif
16 
17 #define AHCI_DEVICE_MODULE_NAME "busses/scsi/ahci/driver_v1"
18 #define AHCI_SIM_MODULE_NAME "busses/scsi/ahci/sim/driver_v1"
19 
20 // RW1 = Write 1 to set bit (writing 0 is ignored)
21 // RWC = Write 1 to clear bit (writing 0 is ignored)
22 
23 
24 enum {
25 	CAP_S64A		= (1U << 31),	// Supports 64-bit Addressing
26 	CAP_SNCQ		= (1 << 30),	// Supports Native Command Queuing
27 	CAP_SSNTF		= (1 << 29),	// Supports SNotification Register
28 	CAP_SMPS		= (1 << 28),	// Supports Mechanical Presence Switch
29 	CAP_SSS			= (1 << 27),	// Supports Staggered Spin-up
30 	CAP_SALP		= (1 << 26),	// Supports Aggressive Link Power Management
31 	CAP_SAL			= (1 << 25),	// Supports Activity LED
32 	CAP_SCLO		= (1 << 24),	// Supports Command List Override
33 	CAP_ISS_MASK	= 0xf,			// Interface Speed Support
34 	CAP_ISS_SHIFT	= 20,
35 	CAP_SNZO		= (1 << 19),	// Supports Non-Zero DMA Offsets
36 	CAP_SAM			= (1 << 18),	// Supports AHCI mode only
37 	CAP_SPM			= (1 << 17),	// Supports Port Multiplier
38 	CAP_FBSS		= (1 << 16),	// FIS-based Switching Supported
39 	CAP_PMD			= (1 << 15),	// PIO Multiple DRQ Block
40 	CAP_SSC			= (1 << 14),	// Slumber State Capable
41 	CAP_PSC			= (1 << 13),	// Partial State Capable
42 	CAP_NCS_MASK	= 0x1f,			// Number of Command Slots
43 									// (zero-based number)
44 	CAP_NCS_SHIFT	= 8,
45 	CAP_CCCS		= (1 << 7),		// Command Completion Coalescing Supported
46 	CAP_EMS			= (1 << 6),		// Enclosure Management Supported
47 	CAP_SXS			= (1 << 5),		// Supports External SATA
48 	CAP_NP_MASK		= 0x1f,			// Number of Ports (zero-based number)
49 	CAP_NP_SHIFT	= 0,
50 };
51 
52 
53 enum {
54 	GHC_AE			= (1U << 31),	// AHCI Enable
55 	GHC_MRSM		= (1 << 2),		// MSI Revert to Single Message
56 	GHC_IE			= (1 << 1),		// Interrupt Enable
57 	GHC_HR			= (1 << 0),		// HBA Reset **RW1**
58 };
59 
60 
61 enum {
62 	INT_CPD			= (1 << 31),	// Cold Port Detect Status/Enable
63 	INT_TFE			= (1 << 30),	// Task File Error Status/Enable
64 	INT_HBF			= (1 << 29),	// Host Bus Fatal Error Status/Enable
65 	INT_HBD			= (1 << 28),	// Host Bus Data Error Status/Enable
66 	INT_IF			= (1 << 27),	// Interface Fatal Error Status/Enable
67 	INT_INF			= (1 << 26),	// Interface Non-fatal Error Status/Enable
68 	INT_OF			= (1 << 24),	// Overflow Status/Enable
69 	INT_IPM			= (1 << 23),	// Incorrect Port Multiplier Status/Enable
70 	INT_PRC			= (1 << 22),	// PhyRdy Change Status/Enable
71 	INT_DMP			= (1 << 7),		// Device Mechanical Presence Status/Enable
72 	INT_PC			= (1 << 6),		// Port Change Interrupt Status/Enable
73 	INT_DP			= (1 << 5),		// Descriptor Processed Interrupt/Enable
74 	INT_UF			= (1 << 4),		// Unknown FIS Interrupt/Enable
75 	INT_SDB			= (1 << 3),		// Set Device Bits Interrupt/Enable
76 	INT_DS			= (1 << 2),		// DMA Setup FIS Interrupt/Enable
77 	INT_PS			= (1 << 1),		// PIO Setup FIS Interrupt/Enable
78 	INT_DHR			= (1 << 0),		// Device to Host Register FIS
79 									// Interrupt/Enable
80 };
81 
82 
83 // Serial ATA Status and control
84 #define HBA_PORT_IPM_MASK		0x00000f00	// Interface Power Management
85 #define SSTS_PORT_IPM_ACTIVE	0x00000100	// active state
86 #define SSTS_PORT_IPM_PARTIAL	0x00000200	// partial state
87 #define SSTS_PORT_IPM_SLUMBER	0x00000600	// slumber power management state
88 #define SSTS_PORT_IPM_DEVSLEEP	0x00000800	// devsleep power management state
89 #define SCTL_PORT_IPM_NORES		0x00000000	// no power restrictions
90 #define SCTL_PORT_IPM_NOPART	0x00000100	// no transitions to partial
91 #define SCTL_PORT_IPM_NOSLUM	0x00000200	// no transitions to slumber
92 
93 #define HBA_PORT_SPD_MASK		0x000000f0	// Interface speed
94 
95 #define HBA_PORT_DET_MASK		0x0000000f	// Device Detection
96 #define SSTS_PORT_DET_NODEV		0x00000000	// no device detected
97 #define SSTS_PORT_DET_NOPHY		0x00000001	// device present but PHY not est.
98 #define SSTS_PORT_DET_PRESENT	0x00000003	// device present and PHY est.
99 #define SSTS_PORT_DET_OFFLINE	0x00000004	// device offline due to disabled
100 #define SCTL_PORT_DET_NOINIT	0x00000000	// no initalization request
101 #define SCTL_PORT_DET_INIT		0x00000001	// perform interface initalization
102 #define SCTL_PORT_DET_DISABLE	0x00000004	// disable phy
103 
104 // Device signatures
105 #define	SATA_SIG_ATA			0x00000101 // SATA drive
106 #define	SATA_SIG_ATAPI			0xEB140101 // ATAPI drive
107 #define	SATA_SIG_SEMB			0xC33C0101 // Enclosure management bridge
108 #define	SATA_SIG_PM				0x96690101 // Port multiplier
109 
110 typedef struct {
111 	uint32		clb;			// Command List Base Address
112 								// (alignment 1024 byte)
113 	uint32		clbu;			// Command List Base Address Upper 32-Bits
114 	uint32		fb;				// FIS Base Address (alignment 256 byte)
115 	uint32		fbu;			// FIS Base Address Upper 32-Bits
116 	uint32		is;				// Interrupt Status **RWC**
117 	uint32		ie;				// Interrupt Enable
118 	uint32		cmd;			// Command and Status
119 	uint32		res1;			// Reserved
120 	uint32		tfd;			// Task File Data
121 	uint32		sig;			// Signature
122 	uint32		ssts;			// Serial ATA Status (SCR0: SStatus)
123 	uint32		sctl;			// Serial ATA Control (SCR2: SControl)
124 	uint32		serr;			// Serial ATA Error (SCR1: SError) **RWC**
125 	uint32		sact;			// Serial ATA Active (SCR3: SActive) **RW1**
126 	uint32		ci;				// Command Issue **RW1**
127 	uint32		sntf;			// SNotification
128 	uint32		fbs;			// FIS-based Switching Control
129 	uint32		devslp;			// Device Sleep
130 	uint32		res[10];		// Reserved
131 	uint32		vendor[4];		// Vendor Specific
132 } _PACKED ahci_port;
133 
134 
135 enum {
136 	PORT_CMD_ICC_ACTIVE		= (1 << 28),	// Interface Communication control
137 	PORT_CMD_ICC_SLUMBER	= (6 << 28),	// Interface Communication control
138 	PORT_CMD_ICC_MASK		= (0xf<<28),	// Interface Communication control
139 	PORT_CMD_ATAPI	= (1 << 24),	// Device is ATAPI
140 	PORT_CMD_CR		= (1 << 15),	// Command List Running (DMA active)
141 	PORT_CMD_FR		= (1 << 14),	// FIS Receive Running
142 	PORT_CMD_FRE	= (1 << 4),		// FIS Receive Enable
143 	PORT_CMD_CLO	= (1 << 3),		// Command List Override
144 	PORT_CMD_POD	= (1 << 2),		// Power On Device
145 	PORT_CMD_SUD	= (1 << 1),		// Spin-up Device
146 	PORT_CMD_ST		= (1 << 0),		// Start DMA
147 };
148 
149 
150 enum {
151 	PORT_INT_CPD	= (1 << 31),	// Cold Presence Detect Status/Enable
152 	PORT_INT_TFE	= (1 << 30),	// Task File Error Status/Enable
153 	PORT_INT_HBF	= (1 << 29),	// Host Bus Fatal Error Status/Enable
154 	PORT_INT_HBD	= (1 << 28),	// Host Bus Data Error Status/Enable
155 	PORT_INT_IF		= (1 << 27),	// Interface Fatal Error Status/Enable
156 	PORT_INT_INF	= (1 << 26),	// Interface Non-fatal Error Status/Enable
157 	PORT_INT_OF		= (1 << 24),	// Overflow Status/Enable
158 	PORT_INT_IPM	= (1 << 23),	// Incorrect Port Multiplier Status/Enable
159 	PORT_INT_PRC	= (1 << 22),	// PhyRdy Change Status/Enable
160 	PORT_INT_DI		= (1 << 7),		// Device Interlock Status/Enable
161 	PORT_INT_PC		= (1 << 6),		// Port Change Status/Enable
162 	PORT_INT_DP		= (1 << 5),		// Descriptor Processed Interrupt
163 	PORT_INT_UF		= (1 << 4),		// Unknown FIS Interrupt
164 	PORT_INT_SDB	= (1 << 3),		// Set Device Bits FIS Interrupt
165 	PORT_INT_DS		= (1 << 2),		// DMA Setup FIS Interrupt
166 	PORT_INT_PS		= (1 << 1),		// PIO Setup FIS Interrupt
167 	PORT_INT_DHR	= (1 << 0),		// Device to Host Register FIS Interrupt
168 };
169 
170 #define PORT_INT_ERROR	(PORT_INT_TFE | PORT_INT_HBF | PORT_INT_HBD \
171 							| PORT_INT_IF | PORT_INT_INF | PORT_INT_OF \
172 							| PORT_INT_IPM | PORT_INT_PRC | PORT_INT_PC \
173 							| PORT_INT_UF)
174 
175 #define PORT_INT_MASK	(PORT_INT_ERROR | PORT_INT_DP | PORT_INT_SDB \
176 							| PORT_INT_DS | PORT_INT_PS | PORT_INT_DHR)
177 
178 enum {
179 	PORT_FBS_DWE_SHIFT		= 16,	// Device With Error
180 	PORT_FBS_DWE_MASK		= 0xf,
181 	PORT_FBS_ADO_SHIFT		= 12,	// Active Device Optimization
182 	PORT_FBS_ADO_MASK		= 0xf,
183 	PORT_FBS_DEV_SHIFT		= 8,	// Device To Issue
184 	PORT_FBS_DEV_MASK		= 0xf,
185 	PORT_FBS_SDE			= 0x04,	// Single Device Error
186 	PORT_FBS_DEC			= 0x02,	// Device Error Clear
187 	PORT_FBS_EN				= 0x01,	// Enable
188 };
189 
190 
191 enum {
192 	PORT_DEVSLP_DM_SHIFT	= 25,	// DITO Multiplier
193 	PORT_DEVSLP_DM_MASK		= 0xf,
194 	PORT_DEVSLP_DITO_SHIFT	= 15,	// Device Sleep Idle Timeout
195 	PORT_DEVSLP_DITO_MASK	= 0x3ff,
196 	PORT_DEVSLP_MDAT_SHIFT	= 10,	// Minimum Device Sleep Assertion Time
197 	PORT_DEVSLP_MDAT_MASK	= 0x1f,
198 	PORT_DEVSLP_DETO_SHIFT	= 2,	// Device Sleep Exit Timeout
199 	PORT_DEVSLP_DETO_MASK	= 0xff,
200 	PORT_DEVSLP_DSP			= 0x02,	// Device Sleep Present
201 	PORT_DEVSLP_ADSE		= 0x01,	// Aggressive Device Sleep Enable
202 };
203 
204 
205 enum {
206 	CAP2_DESO		= (1 << 5),		// DevSleep Entrance from Slumber Only
207 	CAP2_SADM		= (1 << 4),		// Supports Aggressive Device Sleep
208 									// Management
209 	CAP2_SDS		= (1 << 3),		// Supports Device Sleep
210 	CAP2_APST		= (1 << 2),		// Automatic Partial to Slumber Transitions
211 	CAP2_NVMP		= (1 << 1),		// NVMHCI Present
212 	CAP2_BOH		= (1 << 0),		// BIOS/OS Handoff
213 };
214 
215 
216 typedef struct {
217 	uint32		cap;			// Host Capabilities
218 	uint32		ghc;			// Global Host Control
219 	uint32		is;				// Interrupt Status
220 	uint32		pi;				// Ports Implemented
221 	uint32		vs;				// Version
222 	uint32		ccc_ctl;		// Command Completion Coalescing Control
223 	uint32		ccc_ports;		// Command Completion Coalsecing Ports
224 	uint32		em_loc;			// Enclosure Management Location
225 	uint32		em_ctl;			// Enclosure Management Control
226 	uint32		cap2;			// Host Capabilities Extended
227 	uint32		bohc;			// BIOS/OS Handoff Control and Status
228 	uint32		res[29];		// Reserved
229 	uint32		vendor[24];		// Vendor Specific registers
230 	ahci_port	port[32];
231 } _PACKED ahci_hba;
232 
233 
234 typedef struct {
235 	uint8		dsfis[0x1c];	// DMA Setup FIS
236 	uint8		res1[0x04];
237 	uint8		psfis[0x14];	// PIO Setup FIS
238 	uint8		res2[0x0c];
239 	uint8		rfis[0x14];		// D2H Register FIS
240 	uint8		res3[0x04];
241 	uint8		sdbfis[0x08];	// Set Device Bits FIS
242 	uint8		ufis[0x40];		// Unknown FIS
243 	uint8		res4[0x60];
244 } _PACKED fis;
245 
246 
247 typedef struct {
248 	union {
249 		struct {
250 			uint16		cfl : 5;		// command FIS length
251 			uint16		a : 1;			// ATAPI
252 			uint16		w : 1;			// Write
253 			uint16		p : 1;			// Prefetchable
254 			uint16		r : 1;			// Reset
255 			uint16		b : 1;			// Build In Self Test
256 			uint16		c : 1;			// Clear Busy upon R_OK
257 			uint16		: 1;
258 			uint16		pmp : 4;		// Port Multiplier Port
259 			uint16		prdtl;			// physical region description table
260 										// length;
261 		} _PACKED;
262 		uint32		prdtl_flags_cfl;
263 	} _PACKED;
264 	uint32		prdbc;			// PRD Byte Count
265 	uint32		ctba;			// command table desciptor base address
266 								// (alignment 128 byte)
267 	uint32		ctbau;			// command table desciptor base address upper
268 	uint8		res1[0x10];
269 } _PACKED command_list_entry;
270 
271 #define COMMAND_LIST_ENTRY_COUNT 32
272 
273 
274 // Command FIS layout - Host to Device (H2D)
275 //  0 - FIS Type (0x27)
276 //  1 - C bit (0x80)
277 //  2 - Command
278 //  3 - Features
279 //  4 - Sector Number			(LBA Low, bits 0-7)
280 //  5 - Cylinder Low			(LBA Mid, bits 8-15)
281 //  6 - Cylinder High			(LBA High, bits 16-23)
282 //  7 - Device / Head			(for 28-bit LBA commands, bits 24-27)
283 //  8 - Sector Number expanded	(LBA Low-previous, bits 24-31)
284 //  9 - Cylinder Low expanded	(LBA Mid-previous, bits 32-39)
285 // 10 - Cylinder High expanded	(LBA High-previous, bits 40-47)
286 // 11 - Features expanded
287 // 12 - Sector Count			(Sector count, bits 0-7)
288 // 13 - Sector Count expanded	(Sector count, bits 8-15)
289 // 14 - Reserved (0)
290 // 15 - Control
291 // 16 - Reserved (0)
292 // 17 - Reserved (0)
293 // 18 - Reserved (0)
294 // 19 - Reserved (0)
295 typedef struct {
296 	uint8		cfis[0x40];		// command FIS
297 	uint8		acmd[0x20];		// ATAPI command
298 	uint8		res[0x20];		// reserved
299 } _PACKED command_table;
300 
301 
302 typedef struct {
303 	uint32		dba;			// Data Base Address (2-byte aligned)
304 	uint32		dbau;			// Data Base Address Upper
305 	uint32		res;
306 	uint32		dbc;			// Bytecount (0-based, even, max 4MB)
307 	#define DBC_I	0x80000000	/* Interrupt on completition */
308 } _PACKED prd;
309 
310 #define PRD_TABLE_ENTRY_COUNT 168
311 #define PRD_MAX_DATA_LENGTH 0x400000 /* 4 MB */
312 
313 
314 typedef struct {
315 	uint16 vendor;
316 	uint16 device;
317 	const char *name;
318 	uint32 flags;
319 } device_info;
320 
321 status_t get_device_info(uint16 vendorID, uint16 deviceID, const char **name,
322 	uint32 *flags);
323 
324 
325 extern scsi_sim_interface gAHCISimInterface;
326 extern device_manager_info *gDeviceManager;
327 extern scsi_for_sim_interface *gSCSI;
328 extern pci_x86_module_info* gPCIx86Module;
329 
330 
331 #define MAX_SECTOR_LBA_28 ((1ull << 28) - 1)
332 #define MAX_SECTOR_LBA_48 ((1ull << 48) - 1)
333 
334 
335 #define LO32(val) ((uint32)(addr_t)(val))
336 #define HI32(val) ((uint32)(((uint64)(addr_t)(val)) >> 32))
337 #define ASSERT(expr) if (expr) {} else panic(#expr)
338 
339 #define PCI_VENDOR_INTEL	0x8086
340 #define PCI_VENDOR_JMICRON	0x197b
341 #define PCI_JMICRON_CONTROLLER_CONTROL_1	0x40
342 
343 #ifdef __cplusplus
344 }
345 #endif
346 
347 #ifdef __cplusplus
348 
349 template <class T>
350 int count_bits_set(T value)
351 {
352 	int count = 0;
353 	for (T mask = 1; mask; mask <<= 1)
354 		if (value & mask)
355 			count++;
356 	return count;
357 }
358 
359 inline
360 status_t
361 wait_until_set(volatile uint32 *reg, uint32 bits, bigtime_t timeout)
362 {
363 	int trys = (timeout + 9999) / 10000;
364 	while (trys--) {
365 		if (((*reg) & bits) == bits)
366 			return B_OK;
367 		snooze(10000);
368 	}
369 	return B_TIMED_OUT;
370 }
371 
372 inline
373 status_t
374 wait_until_clear(volatile uint32 *reg, uint32 bits, bigtime_t timeout)
375 {
376 	int trys = (timeout + 9999) / 10000;
377 	while (trys--) {
378 		if (((*reg) & bits) == 0)
379 			return B_OK;
380 		snooze(10000);
381 	}
382 	return B_TIMED_OUT;
383 }
384 
385 #endif	/* __cplusplus */
386 
387 #endif	/* _AHCI_DEFS_H */
388