/* * advanced host controller interface (sata) * © 2007-9 coraid, inc */ /* pci configuration */ enum { Abar = 5, }; /* * ahci memory configuration * * 0000-0023 generic host control * 0024-009f reserved * 00a0-00ff vendor specific. * 0100-017f port 0 * ... * 1080-1100 port 31 */ /* cap bits: supported features */ enum { H64a = 1<<31, /* 64-bit addressing */ Hncq = 1<<30, /* ncq */ Hsntf = 1<<29, /* snotification reg. */ Hmps = 1<<28, /* mech pres switch */ Hss = 1<<27, /* staggered spinup */ Halp = 1<<26, /* aggressive link pm */ Hal = 1<<25, /* activity led */ Hclo = 1<<24, /* command-list override */ Hiss = 1<<20, /* for interface speed */ Ham = 1<<18, /* ahci-mode only */ Hpm = 1<<17, /* port multiplier */ Hfbs = 1<<16, /* fis-based switching */ Hpmb = 1<<15, /* multiple-block pio */ Hssc = 1<<14, /* slumber state */ Hpsc = 1<<13, /* partial-slumber state */ Hncs = 1<<8, /* n command slots */ Hcccs = 1<<7, /* coal */ Hems = 1<<6, /* enclosure mgmt. */ Hxs = 1<<5, /* external sata */ Hnp = 1<<0, /* n ports */ }; /* ghc bits */ enum { Hae = 1<<31, /* enable ahci */ Hie = 1<<1, /* " interrupts */ Hhr = 1<<0, /* hba reset */ }; /* cap2 bits */ enum { Apts = 1<<2, /* automatic partial to slumber */ Nvmp = 1<<1, /* nvmhci present; nvram */ Boh = 1<<0, /* bios/os handoff supported */ }; /* bios bits */ enum { Bos = 1<<0, Oos = 1<<1, }; /* emctl bits */ enum { Pm = 1<<27, /* port multiplier support */ Alhd = 1<<26, /* activity led hardware driven */ Xonly = 1<<25, /* rx messages not supported */ Smb = 1<<24, /* single msg buffer; rx limited */ Esgpio = 1<<19, /* sgpio messages supported */ Eses2 = 1<<18, /* ses-2 supported */ Esafte = 1<<17, /* saf-te supported */ Elmt = 1<<16, /* led msg types support */ Emrst = 1<<9, /* reset all em logic */ Tmsg = 1<<8, /* transmit message */ Mr = 1<<0, /* message rx'd */ Emtype = Esgpio | Eses2 | Esafte | Elmt, }; typedef struct { ulong cap; ulong ghc; ulong isr; ulong pi; /* ports implemented */ ulong ver; ulong ccc; /* coaleasing control */ ulong cccports; ulong emloc; ulong emctl; ulong cap2; ulong bios; } Ahba; enum { Acpds = 1<<31, /* cold port detect status */ Atfes = 1<<30, /* task file error status */ Ahbfs = 1<<29, /* hba fatal */ Ahbds = 1<<28, /* hba error (parity error) */ Aifs = 1<<27, /* interface fatal §6.1.2 */ Ainfs = 1<<26, /* interface error (recovered) */ Aofs = 1<<24, /* too many bytes from disk */ Aipms = 1<<23, /* incorrect prt mul status */ Aprcs = 1<<22, /* PhyRdy change status Pxserr.diag.n */ Adpms = 1<<7, /* mechanical presence status */ Apcs = 1<<6, /* port connect diag.x */ Adps = 1<<5, /* descriptor processed */ Aufs = 1<<4, /* unknown fis diag.f */ Asdbs = 1<<3, /* set device bits fis received w/ i bit set */ Adss = 1<<2, /* dma setup */ Apio = 1<<1, /* pio setup fis */ Adhrs = 1<<0, /* device to host register fis */ IEM = Acpds|Atfes|Ahbds|Ahbfs|Ahbds|Aifs|Ainfs|Aprcs|Apcs|Adps| Aufs|Asdbs|Adss|Adhrs, Ifatal = Ahbfs|Ahbds|Aifs, }; /* serror bits */ enum { SerrX = 1<<26, /* exchanged */ SerrF = 1<<25, /* unknown fis */ SerrT = 1<<24, /* transition error */ SerrS = 1<<23, /* link sequence */ SerrH = 1<<22, /* handshake */ SerrC = 1<<21, /* crc */ SerrD = 1<<20, /* not used by ahci */ SerrB = 1<<19, /* 10-tp-8 decode */ SerrW = 1<<18, /* comm wake */ SerrI = 1<<17, /* phy internal */ SerrN = 1<<16, /* phyrdy change */ ErrE = 1<<11, /* internal */ ErrP = 1<<10, /* ata protocol violation */ ErrC = 1<<9, /* communication */ ErrT = 1<<8, /* transient */ ErrM = 1<<1, /* recoverd comm */ ErrI = 1<<0, /* recovered data integrety */ ErrAll = ErrE|ErrP|ErrC|ErrT|ErrM|ErrI, SerrAll = SerrX|SerrF|SerrT|SerrS|SerrH|SerrC|SerrD|SerrB|SerrW| SerrI|SerrN|ErrAll, SerrBad = 0x7f<<19, }; /* cmd register bits */ enum { Aicc = 1<<28, /* interface communcations control. 4 bits */ Aasp = 1<<27, /* aggressive slumber & partial sleep */ Aalpe = 1<<26, /* aggressive link pm enable */ Adlae = 1<<25, /* drive led on atapi */ Aatapi = 1<<24, /* device is atapi */ Apste = 1<<23, /* automatic slumber to partial cap */ Afbsc = 1<<22, /* fis-based switching capable */ Aesp = 1<<21, /* external sata port */ Acpd = 1<<20, /* cold presence detect */ Ampsp = 1<<19, /* mechanical pres. */ Ahpcp = 1<<18, /* hot plug capable */ Apma = 1<<17, /* pm attached */ Acps = 1<<16, /* cold presence state */ Acr = 1<<15, /* cmdlist running */ Afr = 1<<14, /* fis running */ Ampss = 1<<13, /* mechanical presence switch state */ Accs = 1<<8, /* current command slot 12:08 */ Afre = 1<<4, /* fis enable receive */ Aclo = 1<<3, /* command list override */ Apod = 1<<2, /* power on dev (requires cold-pres. detect) */ Asud = 1<<1, /* spin-up device; requires ss capability */ Ast = 1<<0, /* start */ Arun = Ast|Acr|Afre|Afr, Apwr = Apod|Asud, }; /* ctl register bits */ enum { Aipm = 1<<8, /* interface power mgmt. 3=off */ Aspd = 1<<4, Adet = 1<<0, /* device detection */ }; /* sstatus register bits */ enum{ /* sstatus det */ Smissing = 0<<0, Spresent = 1<<0, Sphylink = 3<<0, Sbist = 4<<0, Smask = 7<<0, /* sstatus speed */ Gmissing = 0<<4, Gi = 1<<4, Gii = 2<<4, Giii = 3<<4, Gmask = 7<<4, /* sstatus ipm */ Imissing = 0<<8, Iactive = 1<<8, Isleepy = 2<<8, Islumber = 6<<8, Imask = 7<<8, SImask = Smask | Imask, SSmask = Smask | Isleepy, }; #define sstatus scr0 #define sctl scr2 #define serror scr1 #define sactive scr3 #define ntf scr4 typedef struct { ulong list; /* PxCLB must be 1kb aligned */ ulong listhi; ulong fis; /* 256-byte aligned */ ulong fishi; ulong isr; ulong ie; /* interrupt enable */ ulong cmd; ulong res1; ulong task; ulong sig; ulong scr0; ulong scr2; ulong scr1; ulong scr3; ulong ci; /* command issue */ ulong scr4; ulong fbs; ulong res2[11]; ulong vendor[4]; } Aport; /* in host's memory; not memory mapped */ typedef struct { uchar *base; uchar *d; uchar *p; uchar *r; uchar *u; ulong *devicebits; } Afis; enum { Lprdtl = 1<<16, /* physical region descriptor table len */ Lpmp = 1<<12, /* port multiplier port */ Lclear = 1<<10, /* clear busy on R_OK */ Lbist = 1<<9, Lreset = 1<<8, Lpref = 1<<7, /* prefetchable */ Lwrite = 1<<6, Latapi = 1<<5, Lcfl = 1<<0, /* command fis length in double words */ }; /* in hosts memory; memory mapped */ typedef struct { ulong flags; ulong len; ulong ctab; ulong ctabhi; uchar reserved[16]; } Alist; typedef struct { ulong dba; ulong dbahi; ulong pad; ulong count; } Aprdt; typedef struct { uchar cfis[0x40]; uchar atapi[0x10]; uchar pad[0x30]; Aprdt prdt; } Actab; /* enclosure message header */ enum { Mled = 0, Msafte = 1, Mses2 = 2, Msgpio = 3, }; typedef struct { uchar dummy; uchar msize; uchar dsize; uchar type; uchar hba; /* bits 0:4 are the port */ uchar pm; uchar led[2]; } Aledmsg; enum { Aled = 1<<0, Locled = 1<<3, Errled = 1<<6, Ledoff = 0, Ledon = 1, }; typedef struct { uint encsz; ulong *enctx; ulong *encrx; } Aenc; enum { Ferror = 1, Fdone = 2, }; typedef struct { QLock; Rendez; uchar flag; Sfis; Afis fis; Alist *list; Actab *ctab; } Aportm; typedef struct { Aport *p; Aportm *m; } Aportc;