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