Add the 'current_kthread' helper
[akaros.git] / kern / include / ahci.h
1 /*
2  * This file is part of the UCB release of Plan 9. It is subject to the license
3  * terms in the LICENSE file found in the top-level directory of this
4  * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
5  * part of the UCB release of Plan 9, including this file, may be copied,
6  * modified, propagated, or distributed except according to the terms contained
7  * in the LICENSE file.
8  */
9
10 /*
11  * advanced host controller interface (sata)
12  * © 2007  coraid, inc
13  */
14
15 /* ata errors */
16 enum {
17         Emed = 1 << 0,  /* media error */
18         Enm = 1 << 1,   /* no media */
19         Eabrt = 1 << 2, /* abort */
20         Emcr = 1 << 3,  /* media change request */
21         Eidnf = 1 << 4, /* no user-accessible address */
22         Emc = 1 << 5,   /* media change */
23         Eunc = 1 << 6,  /* data error */
24         Ewp = 1 << 6,   /* write protect */
25         Eicrc = 1 << 7, /* interface crc error */
26
27         Efatal = Eidnf | Eicrc, /* must sw reset */
28 };
29
30 /* ata status */
31 enum {
32         ASerr = 1 << 0,  /* error */
33         ASdrq = 1 << 3,  /* request */
34         ASdf = 1 << 5,   /* fault, command specific */
35         ASdrdy = 1 << 6, /* ready, command specific */
36         ASbsy = 1 << 7,  /* busy */
37
38         ASobs = 1 << 1 | 1 << 2 | 1 << 4,
39 };
40
41 /* pci configuration */
42 enum {
43         Abar = 5,
44 };
45
46 /*
47  * ahci memory configuration
48  *
49  * 0000-0023    generic host control
50  * 0024-009f    reserved
51  * 00a0-00ff    vendor specific.
52  * 0100-017f    port 0
53  * ...
54  * 1080-1100    port 31
55  */
56
57 /* Capability bits: supported features */
58 enum {
59         Hs64a = 1 << 31,  /* 64-bit addressing */
60         Hsncq = 1 << 30,  /* ncq */
61         Hssntf = 1 << 29, /* snotification reg. */
62         Hsmps = 1 << 28,  /* mech pres switch */
63         Hsss = 1 << 27,   /* staggered spinup */
64         Hsalp = 1 << 26,  /* aggressive link pm */
65         Hsal = 1 << 25,   /* activity led */
66         Hsclo = 1 << 24,  /* command-list override */
67         Hiss = 1 << 20,   /* for interface speed */
68                           //    Hsnzo   = 1<<19,
69         Hsam = 1 << 18,   /* ahci-mode only */
70         Hspm = 1 << 17,   /* port multiplier */
71                           //    Hfbss   = 1<<16,
72         Hpmb = 1 << 15,   /* multiple-block pio */
73         Hssc = 1 << 14,   /* slumber state */
74         Hpsc = 1 << 13,   /* partial-slumber state */
75         Hncs = 1 << 8,    /* n command slots */
76         Hcccs = 1 << 7,   /* coal */
77         Hems = 1 << 6,    /* enclosure mgmt. */
78         Hsxs = 1 << 5,    /* external sata */
79         Hnp = 1 << 0,     /* n ports */
80 };
81
82 /* GHC bits */
83 enum {
84         Hae = 1 << 31, /* enable ahci */
85         Hie = 1 << 1,  /* " interrupts */
86         Hhr = 1 << 0,  /* hba reset */
87 };
88
89 #define HBA_CAP 0x00       // Host Capabilities
90 #define HBA_GHC 0x04       // Global Host Control
91 #define HBA_ISR 0x08       // Interrupt Status Register
92 #define HBA_PI  0x0C       // Ports Implemented
93 #define HBA_VS 0x10        // Version
94 #define HBA_CCC_CTL 0x14   // Command Completion Coalescing Control
95 #define HBA_CCC_PORTS 0x18 // Command Completion Coalescing Ports
96 #define HBA_EM_LOC 0x1C    // Enclosure Management Location
97 #define HBA_EM_CTL 0x20    // Enclosure Management Control
98 #define HBA_CAP2 0x24      // Host Capabilities Extended
99 #define HBA_BOHC 0x28      // BIOS/OS Hand-Off Control and Status
100
101 /* Interrupt Status bits */
102 enum {
103         Acpds = 1 << 31, /* cold port detect status */
104         Atfes = 1 << 30, /* task file error status */
105         Ahbfs = 1 << 29, /* hba fatal */
106         Ahbds = 1 << 28, /* hba error (parity error) */
107         Aifs = 1 << 27,  /* interface fatal  §6.1.2 */
108         Ainfs = 1 << 26, /* interface error (recovered) */
109         Aofs = 1 << 24,  /* too many bytes from disk */
110         Aipms = 1 << 23, /* incorrect prt mul status */
111         Aprcs = 1 << 22, /* PhyRdy change status Pxserr.diag.n */
112         Adpms = 1 << 7,  /* mechanical presence status */
113         Apcs = 1 << 6,   /* port connect  diag.x */
114         Adps = 1 << 5,   /* descriptor processed */
115         Aufs = 1 << 4,   /* unknown fis diag.f */
116         Asdbs = 1 << 3,  /* set device bits fis received w/ i bit set */
117         Adss = 1 << 2,   /* dma setup */
118         Apio = 1 << 1,   /* pio setup fis */
119         Adhrs = 1 << 0,  /* device to host register fis */
120
121         IEM = Acpds | Atfes | Ahbds | Ahbfs | Ahbds | Aifs | Ainfs | Aprcs | Apcs |
122               Adps | Aufs | Asdbs | Adss | Adhrs,
123         Ifatal = Atfes | Ahbfs | Ahbds | Aifs,
124 };
125
126 /* SError bits */
127 enum {
128         SerrX = 1 << 26, /* exchanged */
129         SerrF = 1 << 25, /* unknown fis */
130         SerrT = 1 << 24, /* transition error */
131         SerrS = 1 << 23, /* link sequence */
132         SerrH = 1 << 22, /* handshake */
133         SerrC = 1 << 21, /* crc */
134         SerrD = 1 << 20, /* not used by ahci */
135         SerrB = 1 << 19, /* 10-tp-8 decode */
136         SerrW = 1 << 18, /* comm wake */
137         SerrI = 1 << 17, /* phy internal */
138         SerrN = 1 << 16, /* phyrdy change */
139
140         ErrE = 1 << 11, /* internal */
141         ErrP = 1 << 10, /* ata protocol violation */
142         ErrC = 1 << 9,  /* communication */
143         ErrT = 1 << 8,  /* transient */
144         ErrM = 1 << 1,  /* recoverd comm */
145         ErrI = 1 << 0,  /* recovered data integrety */
146
147         ErrAll = ErrE | ErrP | ErrC | ErrT | ErrM | ErrI,
148         SerrAll = SerrX | SerrF | SerrT | SerrS | SerrH | SerrC | SerrD | SerrB |
149                   SerrW | SerrI | SerrN | ErrAll,
150         SerrBad = 0x7f << 19,
151 };
152
153 /* Command/Status register bits */
154 enum {
155         Aicc = 1 << 28,   /* interface communcations control. 4 bits */
156         Aasp = 1 << 27,   /* aggressive slumber & partial sleep */
157         Aalpe = 1 << 26,  /* aggressive link pm enable */
158         Adlae = 1 << 25,  /* drive led on atapi */
159         Aatapi = 1 << 24, /* device is atapi */
160         Aesp = 1 << 21,   /* external sata port */
161         Acpd = 1 << 20,   /* cold presence detect */
162         Ampsp = 1 << 19,  /* mechanical pres. */
163         Ahpcp = 1 << 18,  /* hot plug capable */
164         Apma = 1 << 17,   /* pm attached */
165         Acps = 1 << 16,   /* cold presence state */
166         Acr = 1 << 15,    /* cmdlist running */
167         Afr = 1 << 14,    /* fis running */
168         Ampss = 1 << 13,  /* mechanical presence switch state */
169         Accs = 1 << 8,    /* current command slot 12:08 */
170         Afre = 1 << 4,    /* fis enable receive */
171         Aclo = 1 << 3,    /* command list override */
172         Apod = 1 << 2,    /* power on dev (requires cold-pres. detect) */
173         Asud = 1 << 1,    /* spin-up device;  requires ss capability */
174         Ast = 1 << 0,     /* start */
175
176         Arun = Ast | Acr | Afre | Afr,
177 };
178
179 /* SControl register bits */
180 enum {
181         Aipm = 1 << 8, /* interface power mgmt. 3=off */
182         Aspd = 1 << 4,
183         Adis = 1 << 2, // Disable SATA interface and put Phy in offline mode
184         Adet = 1 << 0, /* device detection */
185 };
186
187 #define PORT_CLB    0x00 // Port Command List Base address
188 #define PORT_CLBU   0x04 // Port Command List Base address Upper 32-bits
189 #define PORT_FB     0x08 // Port FIS Base address
190 #define PORT_FBU    0x0C // Port FIS Base address Upper 32-bits
191 #define PORT_IS     0x10 // Port Interrupt Status
192 #define PORT_IE     0x14 // Port Interrupt Enable
193 #define PORT_CMD    0x18 // Port Command and status
194 #define PORT_RES1   0x1C // Reserved
195 #define PORT_TFD    0x20 // Port Task File Data
196 #define PORT_SIG    0x24 // Port Signature
197 #define PORT_SSTS   0x28 // Port Serial ATA Status (SCR0: SStatus)
198 #define PORT_SCTL   0x2C // Port Serial ATA Control (SCR2: SControl)
199 #define PORT_SERR   0x30 // Port Serial ATA Error (SCR1: SError)
200 #define PORT_SACT   0x34 // Port Serial ATA Active (SCR3: SActive)
201 #define PORT_CI     0x38 // Port Command Issue
202 #define PORT_SNTF   0x3C // Port Serial ATA Notification (SCR4: SNotification)
203 #define PORT_FBS    0x40 // Port FIS-Based Switching control
204 #define PORT_DEVSLP 0x44 // Port Device Sleep
205 #define PORT_RES2   0x48 // Reserved
206 #define PORT_VS     0x70 // Vendor Specific
207
208 enum {
209         /*
210      * Aport sstatus bits (actually states):
211      * 11-8 interface power management
212      *  7-4 current interface speed (generation #)
213      *  3-0 device detection
214      */
215         Intslumber = 0x600,
216         Intpartpwr = 0x200,
217         Intactive = 0x100,
218         Intpm = 0xf00,
219
220         Devphyoffline = 4,
221         Devphycomm = 2, /* phy communication established */
222         Devpresent = 1,
223         Devdet = Devpresent | Devphycomm | Devphyoffline,
224 };
225
226 /* in host's memory; not memory mapped */
227 struct afis {
228         unsigned char *base;
229         unsigned char *d;
230         unsigned char *p;
231         unsigned char *r;
232         unsigned char *u;
233         uint32_t *devicebits;
234 };
235
236 // Command header flags
237 enum {
238         Lprdtl = 1 << 16, /* physical region descriptor table len */
239         Lpmp = 1 << 12,   /* port multiplier port */
240         Lclear = 1 << 10, /* clear busy on R_OK */
241         Lbist = 1 << 9,
242         Lreset = 1 << 8,
243         Lpref = 1 << 7, /* prefetchable */
244         Lwrite = 1 << 6,
245         Latapi = 1 << 5,
246         Lcfl = 1 << 0, /* command fis length in double words */
247 };
248
249 // AHCI Command List Command Header
250 // Each header is an element in the list which is up to 32 elements long
251 #define ALIST_SIZE 0x20   // Size of the struct in memory, not for access
252 #define ALIST_FLAGS  0x00 // Flags and PRDTL (PRDT Length)
253 #define ALIST_LEN    0x04 // PRD byte count transferred
254 #define ALIST_CTAB   0x08 // Physical address of 128-bit aligned Command Table
255 #define ALIST_CTABHI 0x0C // CTAB physical address upper 32 bits
256 #define ALIST_RES    0x10 // Reserved
257
258 // AHCI Physical Region Descriptor Table Element
259 // Each of these elements is part of a table with up to 65,535 entries
260 #define APRDT_SIZE 0x10  // Size of the struct in memory, not for access
261 #define APRDT_DBA   0x00 // Data Base Address (physical)
262 #define APRDT_DBAHI 0x04 // Data Base Address upper 32 bits
263 #define APRDT_RES   0x08 // Reserved
264 #define APRDT_COUNT 0x0C // 31=Intr on Completion, 30:22=Reserved, 21:0=DBC
265
266 // AHCI Command Table
267 // Note that there is no fixed size specified - there are 1 to 65,535 PRDT's
268 // Size = ACTAB_PRDT + APRDT*N_APRDT
269 #define ACTAB_CFIS  0x00 // Command Frame Information Struct (up to 64 bytes)
270 #define ACTAB_ATAPI 0x40 // ATAPI Command (12 or 16 bytes)
271 #define ACTAB_RES   0x50 // Reserved
272 #define ACTAB_PRDT  0x80 // PRDT (up to 65,535 entries in spec, this has one)
273
274 // Portm flags (status flags?)
275 enum {
276         Ferror = 1,
277         Fdone = 2,
278 };
279
280 // Portm feature flags
281 enum {
282         Dllba = 1,
283         Dsmart = 1 << 1,
284         Dpower = 1 << 2,
285         Dnop = 1 << 3,
286         Datapi = 1 << 4,
287         Datapi16 = 1 << 5,
288 };
289
290 struct aportm {
291         qlock_t ql;
292         struct rendez Rendez;
293         unsigned char flag;
294         unsigned char feat;
295         unsigned char smart;
296         struct afis fis;
297         void *list;
298         void *ctab;
299 };
300
301 struct aportc {
302         void *p;
303         struct aportm *pm;
304 };