xref: /plan9-contrib/sys/src/9/pc/ahci.h (revision 58da3067adcdccaaa043d0bfde28ba83b7ced07d)
187dfdc75SDavid du Colombier /*
287dfdc75SDavid du Colombier  * advanced host controller interface (sata)
387dfdc75SDavid du Colombier  * © 2007  coraid, inc
487dfdc75SDavid du Colombier  */
587dfdc75SDavid du Colombier 
687dfdc75SDavid du Colombier /* ata errors */
787dfdc75SDavid du Colombier enum {
887dfdc75SDavid du Colombier 	Emed	= 1<<0,		/* media error */
987dfdc75SDavid du Colombier 	Enm	= 1<<1,		/* no media */
1087dfdc75SDavid du Colombier 	Eabrt	= 1<<2,		/* abort */
1187dfdc75SDavid du Colombier 	Emcr	= 1<<3,		/* media change request */
1287dfdc75SDavid du Colombier 	Eidnf	= 1<<4,		/* no user-accessible address */
1387dfdc75SDavid du Colombier 	Emc	= 1<<5,		/* media change */
1487dfdc75SDavid du Colombier 	Eunc	= 1<<6,		/* data error */
1587dfdc75SDavid du Colombier 	Ewp	= 1<<6,		/* write protect */
1687dfdc75SDavid du Colombier 	Eicrc	= 1<<7,		/* interface crc error */
1787dfdc75SDavid du Colombier 
18df13bbe8SDavid du Colombier 	Efatal	= Eidnf|Eicrc,	/* must sw reset */
1987dfdc75SDavid du Colombier };
2087dfdc75SDavid du Colombier 
2187dfdc75SDavid du Colombier /* ata status */
2287dfdc75SDavid du Colombier enum {
2387dfdc75SDavid du Colombier 	ASerr	= 1<<0,		/* error */
2487dfdc75SDavid du Colombier 	ASdrq	= 1<<3,		/* request */
2587dfdc75SDavid du Colombier 	ASdf	= 1<<5,		/* fault */
2687dfdc75SDavid du Colombier 	ASdrdy	= 1<<6,		/* ready */
2787dfdc75SDavid du Colombier 	ASbsy	= 1<<7,		/* busy */
2887dfdc75SDavid du Colombier 
2987dfdc75SDavid du Colombier 	ASobs	= 1<<1|1<<2|1<<4,
3087dfdc75SDavid du Colombier };
3187dfdc75SDavid du Colombier 
3287dfdc75SDavid du Colombier /* pci configuration */
3387dfdc75SDavid du Colombier enum {
3487dfdc75SDavid du Colombier 	Abar	= 5,
3587dfdc75SDavid du Colombier };
3687dfdc75SDavid du Colombier 
3787dfdc75SDavid du Colombier /*
3887dfdc75SDavid du Colombier  * ahci memory configuration
3987dfdc75SDavid du Colombier  *
4087dfdc75SDavid du Colombier  * 0000-0023	generic host control
4187dfdc75SDavid du Colombier  * 0024-009f	reserved
4287dfdc75SDavid du Colombier  * 00a0-00ff	vendor specific.
4387dfdc75SDavid du Colombier  * 0100-017f	port 0
4487dfdc75SDavid du Colombier  * ...
4587dfdc75SDavid du Colombier  * 1080-1100	port 31
4687dfdc75SDavid du Colombier  */
4787dfdc75SDavid du Colombier 
4887dfdc75SDavid du Colombier /* cap bits: supported features */
4987dfdc75SDavid du Colombier enum {
5087dfdc75SDavid du Colombier 	Hs64a	= 1<<31,	/* 64-bit addressing */
5187dfdc75SDavid du Colombier 	Hsncq	= 1<<30,	/* ncq */
5287dfdc75SDavid du Colombier 	Hssntf	= 1<<29,	/* snotification reg. */
5387dfdc75SDavid du Colombier 	Hsmps	= 1<<28,	/* mech pres switch */
5487dfdc75SDavid du Colombier 	Hsss	= 1<<27,	/* staggered spinup */
5587dfdc75SDavid du Colombier 	Hsalp	= 1<<26,	/* aggressive link pm */
5687dfdc75SDavid du Colombier 	Hsal	= 1<<25,	/* activity led */
5787dfdc75SDavid du Colombier 	Hsclo	= 1<<24,	/* command-list override */
58df13bbe8SDavid du Colombier 	Hiss	= 1<<20,	/* for interface speed */
5987dfdc75SDavid du Colombier //	Hsnzo	= 1<<19,
6087dfdc75SDavid du Colombier 	Hsam	= 1<<18,	/* ahci-mode only */
6187dfdc75SDavid du Colombier 	Hspm	= 1<<17,	/* port multiplier */
6287dfdc75SDavid du Colombier //	Hfbss	= 1<<16,
6387dfdc75SDavid du Colombier 	Hpmb	= 1<<15,	/* multiple-block pio */
6487dfdc75SDavid du Colombier 	Hssc	= 1<<14,	/* slumber state */
6587dfdc75SDavid du Colombier 	Hpsc	= 1<<13,	/* partial-slumber state */
6687dfdc75SDavid du Colombier 	Hncs	= 1<<8,		/* n command slots */
6787dfdc75SDavid du Colombier 	Hcccs	= 1<<7,		/* coal */
6887dfdc75SDavid du Colombier 	Hems	= 1<<6,		/* enclosure mgmt. */
69df13bbe8SDavid du Colombier 	Hsxs	= 1<<5,		/* external sata */
7087dfdc75SDavid du Colombier 	Hnp	= 1<<0,		/* n ports */
7187dfdc75SDavid du Colombier };
7287dfdc75SDavid du Colombier 
7387dfdc75SDavid du Colombier /* ghc bits */
7487dfdc75SDavid du Colombier enum {
7587dfdc75SDavid du Colombier 	Hae	= 1<<31,	/* enable ahci */
7687dfdc75SDavid du Colombier 	Hie	= 1<<1,		/* " interrupts */
7787dfdc75SDavid du Colombier 	Hhr	= 1<<0,		/* hba reset */
7887dfdc75SDavid du Colombier };
7987dfdc75SDavid du Colombier 
8087dfdc75SDavid du Colombier typedef struct {
8191b330d9SDavid du Colombier 	ulong	cap;
8291b330d9SDavid du Colombier 	ulong	ghc;
8391b330d9SDavid du Colombier 	ulong	isr;
8491b330d9SDavid du Colombier 	ulong	pi;		/* ports implemented */
8591b330d9SDavid du Colombier 	ulong	ver;
8691b330d9SDavid du Colombier 	ulong	ccc;		/* coaleasing control */
8791b330d9SDavid du Colombier 	ulong	cccports;
8891b330d9SDavid du Colombier 	ulong	emloc;
8991b330d9SDavid du Colombier 	ulong	emctl;
9087dfdc75SDavid du Colombier } Ahba;
9187dfdc75SDavid du Colombier 
9287dfdc75SDavid du Colombier enum {
9387dfdc75SDavid du Colombier 	Acpds	= 1<<31,	/* cold port detect status */
9487dfdc75SDavid du Colombier 	Atfes	= 1<<30,	/* task file error status */
9587dfdc75SDavid du Colombier 	Ahbfs	= 1<<29,	/* hba fatal */
9687dfdc75SDavid du Colombier 	Ahbds	= 1<<28,	/* hba error (parity error) */
9787dfdc75SDavid du Colombier 	Aifs	= 1<<27,	/* interface fatal  §6.1.2 */
9887dfdc75SDavid du Colombier 	Ainfs	= 1<<26,	/* interface error (recovered) */
99df13bbe8SDavid du Colombier 	Aofs	= 1<<24,	/* too many bytes from disk */
10087dfdc75SDavid du Colombier 	Aipms	= 1<<23,	/* incorrect prt mul status */
10187dfdc75SDavid du Colombier 	Aprcs	= 1<<22,	/* PhyRdy change status Pxserr.diag.n */
10287dfdc75SDavid du Colombier 	Adpms	= 1<<7,		/* mechanical presence status */
10387dfdc75SDavid du Colombier 	Apcs 	= 1<<6,		/* port connect  diag.x */
10487dfdc75SDavid du Colombier 	Adps 	= 1<<5,		/* descriptor processed */
10587dfdc75SDavid du Colombier 	Aufs 	= 1<<4,		/* unknown fis diag.f */
10687dfdc75SDavid du Colombier 	Asdbs	= 1<<3,		/* set device bits fis received w/ i bit set */
10787dfdc75SDavid du Colombier 	Adss	= 1<<2,		/* dma setup */
10887dfdc75SDavid du Colombier 	Apio	= 1<<1,		/* pio setup fis */
109df13bbe8SDavid du Colombier 	Adhrs	= 1<<0,		/* device to host register fis */
11087dfdc75SDavid du Colombier 
11187dfdc75SDavid du Colombier 	IEM	= Acpds|Atfes|Ahbds|Ahbfs|Ahbds|Aifs|Ainfs|Aprcs|Apcs|Adps|
11287dfdc75SDavid du Colombier 			Aufs|Asdbs|Adss|Adhrs,
11387dfdc75SDavid du Colombier 	Ifatal	= Atfes|Ahbfs|Ahbds|Aifs,
11487dfdc75SDavid du Colombier };
11587dfdc75SDavid du Colombier 
11687dfdc75SDavid du Colombier /* serror bits */
11787dfdc75SDavid du Colombier enum {
11887dfdc75SDavid du Colombier 	SerrX	= 1<<26,	/* exchanged */
11987dfdc75SDavid du Colombier 	SerrF	= 1<<25,	/* unknown fis */
12087dfdc75SDavid du Colombier 	SerrT	= 1<<24,	/* transition error */
12187dfdc75SDavid du Colombier 	SerrS	= 1<<23,	/* link sequence */
12287dfdc75SDavid du Colombier 	SerrH	= 1<<22,	/* handshake */
12387dfdc75SDavid du Colombier 	SerrC	= 1<<21,	/* crc */
12487dfdc75SDavid du Colombier 	SerrD	= 1<<20,	/* not used by ahci */
12587dfdc75SDavid du Colombier 	SerrB	= 1<<19,	/* 10-tp-8 decode */
12687dfdc75SDavid du Colombier 	SerrW	= 1<<18,	/* comm wake */
12787dfdc75SDavid du Colombier 	SerrI	= 1<<17,	/* phy internal */
12887dfdc75SDavid du Colombier 	SerrN	= 1<<16,	/* phyrdy change */
12987dfdc75SDavid du Colombier 
13087dfdc75SDavid du Colombier 	ErrE	= 1<<11,	/* internal */
13187dfdc75SDavid du Colombier 	ErrP	= 1<<10,	/* ata protocol violation */
13287dfdc75SDavid du Colombier 	ErrC	= 1<<9,		/* communication */
13387dfdc75SDavid du Colombier 	ErrT	= 1<<8,		/* transient */
13487dfdc75SDavid du Colombier 	ErrM	= 1<<1,		/* recoverd comm */
13587dfdc75SDavid du Colombier 	ErrI	= 1<<0,		/* recovered data integrety */
13687dfdc75SDavid du Colombier 
13787dfdc75SDavid du Colombier 	ErrAll	= ErrE|ErrP|ErrC|ErrT|ErrM|ErrI,
138df13bbe8SDavid du Colombier 	SerrAll	= SerrX|SerrF|SerrT|SerrS|SerrH|SerrC|SerrD|SerrB|SerrW|
139df13bbe8SDavid du Colombier 			SerrI|SerrN|ErrAll,
14087dfdc75SDavid du Colombier 	SerrBad	= 0x7f<<19,
14187dfdc75SDavid du Colombier };
14287dfdc75SDavid du Colombier 
14387dfdc75SDavid du Colombier /* cmd register bits */
14487dfdc75SDavid du Colombier enum {
14587dfdc75SDavid du Colombier 	Aicc	= 1<<28,	/* interface communcations control. 4 bits */
146883a8c51SDavid du Colombier 	Aasp	= 1<<27,	/* aggressive slumber & partial sleep */
147883a8c51SDavid du Colombier 	Aalpe 	= 1<<26,	/* aggressive link pm enable */
14887dfdc75SDavid du Colombier 	Adlae	= 1<<25,	/* drive led on atapi */
14987dfdc75SDavid du Colombier 	Aatapi	= 1<<24,	/* device is atapi */
15087dfdc75SDavid du Colombier 	Aesp	= 1<<21,	/* external sata port */
15187dfdc75SDavid du Colombier 	Acpd	= 1<<20,	/* cold presence detect */
15287dfdc75SDavid du Colombier 	Ampsp	= 1<<19,	/* mechanical pres. */
15387dfdc75SDavid du Colombier 	Ahpcp	= 1<<18,	/* hot plug capable */
15487dfdc75SDavid du Colombier 	Apma	= 1<<17,	/* pm attached */
15587dfdc75SDavid du Colombier 	Acps	= 1<<16,	/* cold presence state */
15687dfdc75SDavid du Colombier 	Acr	= 1<<15,	/* cmdlist running */
15787dfdc75SDavid du Colombier 	Afr	= 1<<14,	/* fis running */
15887dfdc75SDavid du Colombier 	Ampss	= 1<<13,	/* mechanical presence switch state */
15987dfdc75SDavid du Colombier 	Accs	= 1<<8,		/* current command slot 12:08 */
160df13bbe8SDavid du Colombier 	Afre	= 1<<4,		/* fis enable receive */
16187dfdc75SDavid du Colombier 	Aclo	= 1<<3,		/* command list override */
162df13bbe8SDavid du Colombier 	Apod	= 1<<2,		/* power on dev (requires cold-pres. detect) */
163df13bbe8SDavid du Colombier 	Asud	= 1<<1,		/* spin-up device;  requires ss capability */
16487dfdc75SDavid du Colombier 	Ast	= 1<<0,		/* start */
16587dfdc75SDavid du Colombier 
16687dfdc75SDavid du Colombier 	Arun	= Ast|Acr|Afre|Afr,
16787dfdc75SDavid du Colombier };
16887dfdc75SDavid du Colombier 
16987dfdc75SDavid du Colombier /* ctl register bits */
17087dfdc75SDavid du Colombier enum {
17187dfdc75SDavid du Colombier 	Aipm	= 1<<8,		/* interface power mgmt. 3=off */
17287dfdc75SDavid du Colombier 	Aspd	= 1<<4,
173df13bbe8SDavid du Colombier 	Adet	= 1<<0,		/* device detection */
17487dfdc75SDavid du Colombier };
17587dfdc75SDavid du Colombier 
17687dfdc75SDavid du Colombier #define	sstatus	scr0
17787dfdc75SDavid du Colombier #define	sctl	scr2
17887dfdc75SDavid du Colombier #define	serror	scr1
17987dfdc75SDavid du Colombier #define	sactive	scr3
18087dfdc75SDavid du Colombier 
18187dfdc75SDavid du Colombier typedef struct {
18291b330d9SDavid du Colombier 	ulong	list;		/* PxCLB must be 1kb aligned. */
18391b330d9SDavid du Colombier 	ulong	listhi;
18491b330d9SDavid du Colombier 	ulong	fis;		/* 256-byte aligned */
18591b330d9SDavid du Colombier 	ulong	fishi;
18691b330d9SDavid du Colombier 	ulong	isr;
18791b330d9SDavid du Colombier 	ulong	ie;		/* interrupt enable */
18891b330d9SDavid du Colombier 	ulong	cmd;
18991b330d9SDavid du Colombier 	ulong	res1;
19091b330d9SDavid du Colombier 	ulong	task;
19191b330d9SDavid du Colombier 	ulong	sig;
19291b330d9SDavid du Colombier 	ulong	scr0;
19391b330d9SDavid du Colombier 	ulong	scr2;
19491b330d9SDavid du Colombier 	ulong	scr1;
19591b330d9SDavid du Colombier 	ulong	scr3;
19691b330d9SDavid du Colombier 	ulong	ci;		/* command issue */
19791b330d9SDavid du Colombier 	ulong	ntf;
19887dfdc75SDavid du Colombier 	uchar	res2[8];
19991b330d9SDavid du Colombier 	ulong	vendor;
20087dfdc75SDavid du Colombier } Aport;
20187dfdc75SDavid du Colombier 
20239b91b2bSDavid du Colombier enum {
20339b91b2bSDavid du Colombier 	/*
20439b91b2bSDavid du Colombier 	 * Aport sstatus bits (actually states):
20539b91b2bSDavid du Colombier 	 * 11-8 interface power management
20639b91b2bSDavid du Colombier 	 *  7-4 current interface speed (generation #)
20739b91b2bSDavid du Colombier 	 *  3-0 device detection
20839b91b2bSDavid du Colombier 	 */
20939b91b2bSDavid du Colombier 	Intslumber	= 0x600,
21039b91b2bSDavid du Colombier 	Intpartpwr	= 0x200,
21139b91b2bSDavid du Colombier 	Intactive	= 0x100,
21239b91b2bSDavid du Colombier 	Intpm		= 0xf00,
21339b91b2bSDavid du Colombier 
21439b91b2bSDavid du Colombier 	Devphyoffline	= 4,
21539b91b2bSDavid du Colombier 	Devphycomm	= 2,		/* phy communication established */
21639b91b2bSDavid du Colombier 	Devpresent	= 1,
21739b91b2bSDavid du Colombier 	Devdet		= Devpresent | Devphycomm | Devphyoffline,
21839b91b2bSDavid du Colombier };
21939b91b2bSDavid du Colombier 
22087dfdc75SDavid du Colombier /* in host's memory; not memory mapped */
22187dfdc75SDavid du Colombier typedef struct {
22287dfdc75SDavid du Colombier 	uchar	*base;
22387dfdc75SDavid du Colombier 	uchar	*d;
22487dfdc75SDavid du Colombier 	uchar	*p;
22587dfdc75SDavid du Colombier 	uchar	*r;
22687dfdc75SDavid du Colombier 	uchar	*u;
22791b330d9SDavid du Colombier 	ulong	*devicebits;
22887dfdc75SDavid du Colombier } Afis;
22987dfdc75SDavid du Colombier 
23087dfdc75SDavid du Colombier enum {
23187dfdc75SDavid du Colombier 	Lprdtl	= 1<<16,	/* physical region descriptor table len */
23287dfdc75SDavid du Colombier 	Lpmp	= 1<<12,	/* port multiplier port */
23387dfdc75SDavid du Colombier 	Lclear	= 1<<10,	/* clear busy on R_OK */
23487dfdc75SDavid du Colombier 	Lbist	= 1<<9,
23587dfdc75SDavid du Colombier 	Lreset	= 1<<8,
23687dfdc75SDavid du Colombier 	Lpref	= 1<<7,		/* prefetchable */
23787dfdc75SDavid du Colombier 	Lwrite	= 1<<6,
23887dfdc75SDavid du Colombier 	Latapi	= 1<<5,
23987dfdc75SDavid du Colombier 	Lcfl	= 1<<0,		/* command fis length in double words */
24087dfdc75SDavid du Colombier };
24187dfdc75SDavid du Colombier 
24287dfdc75SDavid du Colombier /* in hosts memory; memory mapped */
24387dfdc75SDavid du Colombier typedef struct {
24491b330d9SDavid du Colombier 	ulong	flags;
24591b330d9SDavid du Colombier 	ulong	len;
24691b330d9SDavid du Colombier 	ulong	ctab;
24791b330d9SDavid du Colombier 	ulong	ctabhi;
24887dfdc75SDavid du Colombier 	uchar	reserved[16];
24987dfdc75SDavid du Colombier } Alist;
25087dfdc75SDavid du Colombier 
25187dfdc75SDavid du Colombier typedef struct {
25291b330d9SDavid du Colombier 	ulong	dba;
25391b330d9SDavid du Colombier 	ulong	dbahi;
25491b330d9SDavid du Colombier 	ulong	pad;
25591b330d9SDavid du Colombier 	ulong	count;
25687dfdc75SDavid du Colombier } Aprdt;
25787dfdc75SDavid du Colombier 
25887dfdc75SDavid du Colombier typedef struct {
25987dfdc75SDavid du Colombier 	uchar	cfis[0x40];
26087dfdc75SDavid du Colombier 	uchar	atapi[0x10];
26187dfdc75SDavid du Colombier 	uchar	pad[0x30];
26287dfdc75SDavid du Colombier 	Aprdt	prdt;
26387dfdc75SDavid du Colombier } Actab;
26487dfdc75SDavid du Colombier 
26587dfdc75SDavid du Colombier enum {
26687dfdc75SDavid du Colombier 	Ferror	= 1,
26787dfdc75SDavid du Colombier 	Fdone	= 2,
26887dfdc75SDavid du Colombier };
26987dfdc75SDavid du Colombier 
27087dfdc75SDavid du Colombier enum {
27187dfdc75SDavid du Colombier 	Dllba 	= 1,
27287dfdc75SDavid du Colombier 	Dsmart	= 1<<1,
27387dfdc75SDavid du Colombier 	Dpower	= 1<<2,
27487dfdc75SDavid du Colombier 	Dnop	= 1<<3,
27587dfdc75SDavid du Colombier 	Datapi	= 1<<4,
27687dfdc75SDavid du Colombier 	Datapi16= 1<<5,
27787dfdc75SDavid du Colombier };
27887dfdc75SDavid du Colombier 
27987dfdc75SDavid du Colombier typedef struct {
28087dfdc75SDavid du Colombier 	QLock;
28187dfdc75SDavid du Colombier 	Rendez;
28287dfdc75SDavid du Colombier 	uchar	flag;
28387dfdc75SDavid du Colombier 	uchar	feat;
28487dfdc75SDavid du Colombier 	uchar	smart;
28587dfdc75SDavid du Colombier 	Afis	fis;
28687dfdc75SDavid du Colombier 	Alist	*list;
28787dfdc75SDavid du Colombier 	Actab	*ctab;
28887dfdc75SDavid du Colombier } Aportm;
28987dfdc75SDavid du Colombier 
29087dfdc75SDavid du Colombier typedef struct {
29187dfdc75SDavid du Colombier 	Aport	*p;
292*58da3067SDavid du Colombier 	Aportm	*pm;
29387dfdc75SDavid du Colombier } Aportc;
294