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