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