xref: /plan9/sys/src/9/pc/ahci.h (revision 58da3067adcdccaaa043d0bfde28ba83b7ced07d)
1 /*
2  * advanced host controller interface (sata)
3  * © 2007  coraid, inc
4  */
5 
6 /* ata errors */
7 enum {
8 	Emed	= 1<<0,		/* media error */
9 	Enm	= 1<<1,		/* no media */
10 	Eabrt	= 1<<2,		/* abort */
11 	Emcr	= 1<<3,		/* media change request */
12 	Eidnf	= 1<<4,		/* no user-accessible address */
13 	Emc	= 1<<5,		/* media change */
14 	Eunc	= 1<<6,		/* data error */
15 	Ewp	= 1<<6,		/* write protect */
16 	Eicrc	= 1<<7,		/* interface crc error */
17 
18 	Efatal	= Eidnf|Eicrc,	/* must sw reset */
19 };
20 
21 /* ata status */
22 enum {
23 	ASerr	= 1<<0,		/* error */
24 	ASdrq	= 1<<3,		/* request */
25 	ASdf	= 1<<5,		/* fault */
26 	ASdrdy	= 1<<6,		/* ready */
27 	ASbsy	= 1<<7,		/* busy */
28 
29 	ASobs	= 1<<1|1<<2|1<<4,
30 };
31 
32 /* pci configuration */
33 enum {
34 	Abar	= 5,
35 };
36 
37 /*
38  * ahci memory configuration
39  *
40  * 0000-0023	generic host control
41  * 0024-009f	reserved
42  * 00a0-00ff	vendor specific.
43  * 0100-017f	port 0
44  * ...
45  * 1080-1100	port 31
46  */
47 
48 /* cap bits: supported features */
49 enum {
50 	Hs64a	= 1<<31,	/* 64-bit addressing */
51 	Hsncq	= 1<<30,	/* ncq */
52 	Hssntf	= 1<<29,	/* snotification reg. */
53 	Hsmps	= 1<<28,	/* mech pres switch */
54 	Hsss	= 1<<27,	/* staggered spinup */
55 	Hsalp	= 1<<26,	/* aggressive link pm */
56 	Hsal	= 1<<25,	/* activity led */
57 	Hsclo	= 1<<24,	/* command-list override */
58 	Hiss	= 1<<20,	/* for interface speed */
59 //	Hsnzo	= 1<<19,
60 	Hsam	= 1<<18,	/* ahci-mode only */
61 	Hspm	= 1<<17,	/* port multiplier */
62 //	Hfbss	= 1<<16,
63 	Hpmb	= 1<<15,	/* multiple-block pio */
64 	Hssc	= 1<<14,	/* slumber state */
65 	Hpsc	= 1<<13,	/* partial-slumber state */
66 	Hncs	= 1<<8,		/* n command slots */
67 	Hcccs	= 1<<7,		/* coal */
68 	Hems	= 1<<6,		/* enclosure mgmt. */
69 	Hsxs	= 1<<5,		/* external sata */
70 	Hnp	= 1<<0,		/* n ports */
71 };
72 
73 /* ghc bits */
74 enum {
75 	Hae	= 1<<31,	/* enable ahci */
76 	Hie	= 1<<1,		/* " interrupts */
77 	Hhr	= 1<<0,		/* hba reset */
78 };
79 
80 typedef struct {
81 	ulong	cap;
82 	ulong	ghc;
83 	ulong	isr;
84 	ulong	pi;		/* ports implemented */
85 	ulong	ver;
86 	ulong	ccc;		/* coaleasing control */
87 	ulong	cccports;
88 	ulong	emloc;
89 	ulong	emctl;
90 } Ahba;
91 
92 enum {
93 	Acpds	= 1<<31,	/* cold port detect status */
94 	Atfes	= 1<<30,	/* task file error status */
95 	Ahbfs	= 1<<29,	/* hba fatal */
96 	Ahbds	= 1<<28,	/* hba error (parity error) */
97 	Aifs	= 1<<27,	/* interface fatal  §6.1.2 */
98 	Ainfs	= 1<<26,	/* interface error (recovered) */
99 	Aofs	= 1<<24,	/* too many bytes from disk */
100 	Aipms	= 1<<23,	/* incorrect prt mul status */
101 	Aprcs	= 1<<22,	/* PhyRdy change status Pxserr.diag.n */
102 	Adpms	= 1<<7,		/* mechanical presence status */
103 	Apcs 	= 1<<6,		/* port connect  diag.x */
104 	Adps 	= 1<<5,		/* descriptor processed */
105 	Aufs 	= 1<<4,		/* unknown fis diag.f */
106 	Asdbs	= 1<<3,		/* set device bits fis received w/ i bit set */
107 	Adss	= 1<<2,		/* dma setup */
108 	Apio	= 1<<1,		/* pio setup fis */
109 	Adhrs	= 1<<0,		/* device to host register fis */
110 
111 	IEM	= Acpds|Atfes|Ahbds|Ahbfs|Ahbds|Aifs|Ainfs|Aprcs|Apcs|Adps|
112 			Aufs|Asdbs|Adss|Adhrs,
113 	Ifatal	= Atfes|Ahbfs|Ahbds|Aifs,
114 };
115 
116 /* serror bits */
117 enum {
118 	SerrX	= 1<<26,	/* exchanged */
119 	SerrF	= 1<<25,	/* unknown fis */
120 	SerrT	= 1<<24,	/* transition error */
121 	SerrS	= 1<<23,	/* link sequence */
122 	SerrH	= 1<<22,	/* handshake */
123 	SerrC	= 1<<21,	/* crc */
124 	SerrD	= 1<<20,	/* not used by ahci */
125 	SerrB	= 1<<19,	/* 10-tp-8 decode */
126 	SerrW	= 1<<18,	/* comm wake */
127 	SerrI	= 1<<17,	/* phy internal */
128 	SerrN	= 1<<16,	/* phyrdy change */
129 
130 	ErrE	= 1<<11,	/* internal */
131 	ErrP	= 1<<10,	/* ata protocol violation */
132 	ErrC	= 1<<9,		/* communication */
133 	ErrT	= 1<<8,		/* transient */
134 	ErrM	= 1<<1,		/* recoverd comm */
135 	ErrI	= 1<<0,		/* recovered data integrety */
136 
137 	ErrAll	= ErrE|ErrP|ErrC|ErrT|ErrM|ErrI,
138 	SerrAll	= SerrX|SerrF|SerrT|SerrS|SerrH|SerrC|SerrD|SerrB|SerrW|
139 			SerrI|SerrN|ErrAll,
140 	SerrBad	= 0x7f<<19,
141 };
142 
143 /* cmd register bits */
144 enum {
145 	Aicc	= 1<<28,	/* interface communcations control. 4 bits */
146 	Aasp	= 1<<27,	/* aggressive slumber & partial sleep */
147 	Aalpe 	= 1<<26,	/* aggressive link pm enable */
148 	Adlae	= 1<<25,	/* drive led on atapi */
149 	Aatapi	= 1<<24,	/* device is atapi */
150 	Aesp	= 1<<21,	/* external sata port */
151 	Acpd	= 1<<20,	/* cold presence detect */
152 	Ampsp	= 1<<19,	/* mechanical pres. */
153 	Ahpcp	= 1<<18,	/* hot plug capable */
154 	Apma	= 1<<17,	/* pm attached */
155 	Acps	= 1<<16,	/* cold presence state */
156 	Acr	= 1<<15,	/* cmdlist running */
157 	Afr	= 1<<14,	/* fis running */
158 	Ampss	= 1<<13,	/* mechanical presence switch state */
159 	Accs	= 1<<8,		/* current command slot 12:08 */
160 	Afre	= 1<<4,		/* fis enable receive */
161 	Aclo	= 1<<3,		/* command list override */
162 	Apod	= 1<<2,		/* power on dev (requires cold-pres. detect) */
163 	Asud	= 1<<1,		/* spin-up device;  requires ss capability */
164 	Ast	= 1<<0,		/* start */
165 
166 	Arun	= Ast|Acr|Afre|Afr,
167 };
168 
169 /* ctl register bits */
170 enum {
171 	Aipm	= 1<<8,		/* interface power mgmt. 3=off */
172 	Aspd	= 1<<4,
173 	Adet	= 1<<0,		/* device detection */
174 };
175 
176 #define	sstatus	scr0
177 #define	sctl	scr2
178 #define	serror	scr1
179 #define	sactive	scr3
180 
181 typedef struct {
182 	ulong	list;		/* PxCLB must be 1kb aligned. */
183 	ulong	listhi;
184 	ulong	fis;		/* 256-byte aligned */
185 	ulong	fishi;
186 	ulong	isr;
187 	ulong	ie;		/* interrupt enable */
188 	ulong	cmd;
189 	ulong	res1;
190 	ulong	task;
191 	ulong	sig;
192 	ulong	scr0;
193 	ulong	scr2;
194 	ulong	scr1;
195 	ulong	scr3;
196 	ulong	ci;		/* command issue */
197 	ulong	ntf;
198 	uchar	res2[8];
199 	ulong	vendor;
200 } Aport;
201 
202 enum {
203 	/*
204 	 * Aport sstatus bits (actually states):
205 	 * 11-8 interface power management
206 	 *  7-4 current interface speed (generation #)
207 	 *  3-0 device detection
208 	 */
209 	Intslumber	= 0x600,
210 	Intpartpwr	= 0x200,
211 	Intactive	= 0x100,
212 	Intpm		= 0xf00,
213 
214 	Devphyoffline	= 4,
215 	Devphycomm	= 2,		/* phy communication established */
216 	Devpresent	= 1,
217 	Devdet		= Devpresent | Devphycomm | Devphyoffline,
218 };
219 
220 /* in host's memory; not memory mapped */
221 typedef struct {
222 	uchar	*base;
223 	uchar	*d;
224 	uchar	*p;
225 	uchar	*r;
226 	uchar	*u;
227 	ulong	*devicebits;
228 } Afis;
229 
230 enum {
231 	Lprdtl	= 1<<16,	/* physical region descriptor table len */
232 	Lpmp	= 1<<12,	/* port multiplier port */
233 	Lclear	= 1<<10,	/* clear busy on R_OK */
234 	Lbist	= 1<<9,
235 	Lreset	= 1<<8,
236 	Lpref	= 1<<7,		/* prefetchable */
237 	Lwrite	= 1<<6,
238 	Latapi	= 1<<5,
239 	Lcfl	= 1<<0,		/* command fis length in double words */
240 };
241 
242 /* in hosts memory; memory mapped */
243 typedef struct {
244 	ulong	flags;
245 	ulong	len;
246 	ulong	ctab;
247 	ulong	ctabhi;
248 	uchar	reserved[16];
249 } Alist;
250 
251 typedef struct {
252 	ulong	dba;
253 	ulong	dbahi;
254 	ulong	pad;
255 	ulong	count;
256 } Aprdt;
257 
258 typedef struct {
259 	uchar	cfis[0x40];
260 	uchar	atapi[0x10];
261 	uchar	pad[0x30];
262 	Aprdt	prdt;
263 } Actab;
264 
265 enum {
266 	Ferror	= 1,
267 	Fdone	= 2,
268 };
269 
270 enum {
271 	Dllba 	= 1,
272 	Dsmart	= 1<<1,
273 	Dpower	= 1<<2,
274 	Dnop	= 1<<3,
275 	Datapi	= 1<<4,
276 	Datapi16= 1<<5,
277 };
278 
279 typedef struct {
280 	QLock;
281 	Rendez;
282 	uchar	flag;
283 	uchar	feat;
284 	uchar	smart;
285 	Afis	fis;
286 	Alist	*list;
287 	Actab	*ctab;
288 } Aportm;
289 
290 typedef struct {
291 	Aport	*p;
292 	Aportm	*pm;
293 } Aportc;
294