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