1
2 #include <stdbool.h>
3 #include <stdint.h>
4 #include <string.h>
5
6 #include <sys/kassert.h>
7 #include <sys/kdebug.h>
8 #include <sys/kmem.h>
9 #include <sys/pci.h>
10 #include <sys/sga.h>
11
12 #include "ata.h"
13 #include "sata.h"
14
15 /*
16 * AHCI Definitions
17 */
18
19 typedef struct AHCIDevice
20 {
21 uint32_t device;
22 const char *name;
23 uint32_t flags;
24 } AHCIDevice;
25
26 static AHCIDevice deviceList[] =
27 {
28 { 0x80862922, "ICH9", 0 },
29 { 0, "", 0 },
30 };
31
32 typedef struct AHCIHostControl
33 {
34 uint32_t cap; // Host Capabilities
35 uint32_t ghc; // Global Host Control
36 uint32_t is; // Interrupt Status
37 uint32_t pi; // Ports Implemented
38 uint32_t vs; // Version
39 } AHCIHostControl;
40
41 #define AHCI_CAP_S64A 0x80000000 /* Supports 64-bit Addressing */
42 #define AHCI_CAP_SNCQ 0x40000000 /* Supports NCQ */
43
44 #define AHCI_GHC_AE 0x80000000
45 #define AHCI_GHC_IE 0x00000002
46 #define AHCI_GHC_HR 0x00000001
47
48 typedef struct AHCIPort
49 {
50 uint64_t clba; // Command List Base Address
51 uint64_t fb; // FIS Base Address
52 uint32_t is; // Interrupt Status
53 uint32_t ie; // Interrupt Enable
54 uint32_t cmd; // Command
55 uint32_t _rsvd; // *Reserved*
56 uint32_t tfd; // Task File Data
57 uint32_t sig; // Signature
58 uint32_t ssts; // SATA Status
59 uint32_t sctl; // SATA Control
60 uint32_t serr; // SATA Error
61 uint32_t sact; // SATA Active
62 uint32_t ci; // Command Issue
63 uint32_t _rsvd2; // *Reserved*
64 } AHCIPort;
65
66 #define AHCIPORT_CMD_ICCMASK 0xF0000000 /* Interface Communication Control */
67 #define AHCIPORT_CMD_ICCSLUMBER 0x60000000 /* ICC Slumber */
68 #define AHCIPORT_CMD_ICCPARTIAL 0x20000000 /* ICC Partial */
69 #define AHCIPORT_CMD_ICCACTIVE 0x10000000 /* ICC Active */
70 #define AHCIPORT_CMD_ICCIDLE 0x00000000 /* ICC Idle */
71 #define AHCIPORT_CMD_ASP 0x08000000 /* Aggressive Slumber/Partial */
72 #define AHCIPORT_CMD_ALPE 0x04000000 /* Aggressive Link PM Enable */
73 #define AHCIPORT_CMD_DLAE 0x02000000 /* Drive LED on ATAPI Enable */
74 #define AHCIPORT_CMD_ATAPI 0x01000000 /* Device is ATAPI */
75 #define AHCIPORT_CMD_CPD 0x00100000 /* Cold Presence Detection */
76 #define AHCIPORT_CMD_ISP 0x00080000 /* Interlock Switch Attached */
77 #define AHCIPORT_CMD_HPCP 0x00040000 /* Hot Plug Capable Port */
78 #define AHCIPORT_CMD_PMA 0x00020000 /* Port Multiplier Attached */
79 #define AHCIPORT_CMD_CPS 0x00010000 /* Cold Presence State */
80 #define AHCIPORT_CMD_CR 0x00008000 /* Command List Running */
81 #define AHCIPORT_CMD_FR 0x00004000 /* FIS Receive Running */
82 #define AHCIPORT_CMD_ISS 0x00002000 /* Interlock Switch State */
83 #define AHCIPORT_CMD_FRE 0x00000010 /* FIS Receive Enable */
84 #define AHCIPORT_CMD_CLO 0x00000008 /* Command List Override */
85 #define AHCIPORT_CMD_POD 0x00000004 /* Power On Device */
86 #define AHCIPORT_CMD_SUD 0x00000002 /* Spin-Up Device */
87 #define AHCIPORT_CMD_ST 0x00000001 /* Start */
88
89 #define AHCIPORT_TFD_BSY 0x00000080 /* Port Busy */
90 #define AHCIPORT_TFD_DRQ 0x00000004 /* Data Transfer Requested */
91 #define AHCIPORT_TFD_ERR 0x00000001 /* Error during Transfer */
92
93 #define AHCIPORT_SSTS_DETMASK 0x0000000F /* Device Detection (DET) Mask */
94 #define AHCIPORT_SSTS_DETNP 0x00000000 /* DET: Not Present */
95 #define AHCIPORT_SSTS_DETNOTEST 0x00000001 /* DET: Phy not established */
96 #define AHCIPORT_SSTS_DETPE 0x00000003 /* DET: Present and Established */
97 #define AHCIPORT_SSTS_DETNE 0x00000004 /* DET: Not Enabled or in BIST mode */
98
99 #define AHCI_ABAR 5
100 #define AHCI_PORT_OFFSET 0x100
101 #define AHCI_PORT_LENGTH 0x80
102 #define AHCI_MAX_PORTS 8
103 #define AHCI_MAX_CMDS 32
104
105 /*
106 * Request Structures
107 */
108
109 typedef struct AHCICommandHeader
110 {
111 uint16_t flag;
112 uint16_t prdtl; // PRDT Length
113 uint32_t cmdStatus;
114 uint64_t ctba;
115 uint64_t _rsvd[2];
116 } AHCICommandHeader;
117
118 typedef struct AHCICommandList
119 {
120 AHCICommandHeader cmds[AHCI_MAX_CMDS];
121 } AHCICommandList;
122
123 /*
124 * AHCIPRDT - Physical Region Descriptor Table
125 */
126 typedef struct AHCIPRDT
127 {
128 uint64_t dba; // Data Base Address
129 uint32_t _rsvd;
130 uint32_t descInfo; // Description Information
131 } AHCIPRDT;
132
133 /*
134 * AHCICommandTable
135 * This structure is exactly one machine page in size, we fill up the page
136 * with PRDT entries. AHCI supports up to 64K PRDT entries but on x86 we
137 * limit this to 248.
138 */
139 typedef struct AHCICommandTable
140 {
141 uint8_t cfis[64]; // Command FIS
142 uint8_t acmd[32]; // ATAPI Command
143 uint8_t _rsvd[32];
144 AHCIPRDT prdt[248]; // Physical Region Descriptor Table
145 } AHCICommandTable;
146
147 /*
148 * Response Structures
149 */
150
151 typedef struct AHCIRecvFIS
152 {
153 uint8_t dsfis[0x1c];
154 uint8_t _rsvd0[0x4];
155 uint8_t psfis[0x14];
156 uint8_t _rsvd1[0xc];
157 uint8_t rfis[0x14];
158 uint8_t _rsvd2[0x4];
159 uint8_t sdbfis[0x8];
160 uint8_t ufis[0x40];
161 uint8_t _rsvd3[0x60];
162 } AHCIRecvFIS;
163
164 /*
165 * AHCI
166 * Exceeds a single page need to use heap
167 */
168 typedef struct AHCI
169 {
170 PCIDevice dev;
171 // Device Space
172 AHCIHostControl *hc;
173 AHCIPort *port[AHCI_MAX_PORTS];
174 // Driver Memory
175 AHCICommandList *clst[AHCI_MAX_PORTS];
176 AHCICommandTable *ctbl[AHCI_MAX_PORTS][AHCI_MAX_CMDS];
177 AHCIRecvFIS *rfis[AHCI_MAX_PORTS];
178 } AHCI;
179
180 void AHCI_Configure(PCIDevice dev);
181
182 void
AHCI_Init(uint32_t bus,uint32_t slot,uint32_t func)183 AHCI_Init(uint32_t bus, uint32_t slot, uint32_t func)
184 {
185 PCIDevice dev;
186
187 dev.bus = bus;
188 dev.slot = slot;
189 dev.func = func;
190 dev.vendor = PCI_GetVendorID(&dev);
191 dev.device = PCI_GetDeviceID(&dev);
192
193 uint32_t device = dev.vendor << 16 | dev.device;
194
195 uint8_t progif = PCI_CfgRead8(&dev, PCI_OFFSET_PROGIF);
196 if (progif != 0x01)
197 {
198 kprintf("Unsupported SATA Controller PROGIF=%02x\n", progif);
199 return;
200 }
201
202 // XXX: Temporary until we have a slab allocator
203 #define PGSIZE 4096
204 ASSERT(sizeof(AHCI) <= PGSIZE);
205 ASSERT(sizeof(AHCICommandList) <= PGSIZE);
206 ASSERT(sizeof(AHCIRecvFIS) <= PGSIZE);
207 ASSERT(sizeof(ATAIdentifyDevice) == 512);
208
209 int deviceIdx = 0;
210 while (deviceList[deviceIdx].device != 0x0) {
211 if (deviceList[deviceIdx].device == device) {
212 kprintf("AHCI: Found %s\n", deviceList[deviceIdx].name);
213 // Configure and add disks
214 AHCI_Configure(dev);
215 }
216
217 deviceIdx++;
218 }
219 }
220
221 void
AHCI_Dump(AHCI * ahci)222 AHCI_Dump(AHCI *ahci)
223 {
224 volatile AHCIHostControl *hc = ahci->hc;
225
226 kprintf("CAP: 0x%08x\n", hc->cap);
227 kprintf("GHC: 0x%08x\n", hc->ghc);
228 kprintf("IS: 0x%08x\n", hc->is);
229 kprintf("PI: 0x%08x\n", hc->pi);
230 kprintf("VS: 0x%08x\n", hc->vs);
231 }
232
233 void
AHCI_DumpPort(AHCI * ahci,int port)234 AHCI_DumpPort(AHCI *ahci, int port)
235 {
236 volatile AHCIPort *p = ahci->port[port];
237
238 kprintf("Port %d\n", port);
239 kprintf("CLBA: 0x%016llx\n", p->clba);
240 kprintf("FB: 0x%016llx\n", p->fb);
241 kprintf("IS: 0x%08x\n", p->is);
242 kprintf("IE: 0x%08x\n", p->ie);
243 kprintf("CMD: 0x%08x\n", p->cmd);
244 kprintf("TFD: 0x%08x\n", p->tfd);
245 kprintf("SIG: 0x%08x\n", p->sig);
246 kprintf("SSTS: 0x%08x\n", p->ssts);
247 kprintf("SCTL: 0x%08x\n", p->sctl);
248 kprintf("SERR: 0x%08x\n", p->serr);
249 kprintf("SACT: 0x%08x\n", p->sact);
250 kprintf("CI: 0x%08x\n", p->ci);
251 }
252
253 uint64_t
AHCI_IssueCommand(AHCI * ahci,int port,SGArray * sga,void * cfis,int len)254 AHCI_IssueCommand(AHCI *ahci, int port, SGArray *sga, void *cfis, int len)
255 {
256 // XXX: support multiple commands
257 volatile AHCICommandList *cl = ahci->clst[port];
258 volatile AHCICommandTable *ct = ahci->ctbl[port][0];
259 volatile AHCIPort *p = ahci->port[port];
260
261 // Copy Command FIS
262 memcpy((void *)&ct->cfis[0], cfis, len);
263
264 // Convert SGArray into PRDT
265 int i;
266 for (i = 0; i < sga->len; i++)
267 {
268 ct->prdt[i].dba = sga->entries[i].offset;
269 ct->prdt[i].descInfo = sga->entries[i].length - 1;
270 // Must be a multiple of word size
271 ASSERT(sga->entries[i].length % 2 == 0);
272 }
273
274 // Specify cfis length and prdt entries;
275 // XXX: support multiple commands
276 cl->cmds[0].prdtl = sga->len;
277 cl->cmds[0].flag = len >> 2;
278
279 p->ci = 1;
280
281 return 0;
282 }
283
284 void
AHCI_WaitPort(AHCI * ahci,int port)285 AHCI_WaitPort(AHCI *ahci, int port)
286 {
287 volatile AHCIPort *p = ahci->port[port];
288 while (1) {
289 uint32_t tfd = p->tfd & AHCIPORT_TFD_BSY;
290 if ((tfd == 0) && (p->ci == 0)) {
291 return;
292 }
293
294 // implement timeouts
295 }
296 }
297
298 void
AHCI_IdentifyPort(AHCI * ahci,int port)299 AHCI_IdentifyPort(AHCI *ahci, int port)
300 {
301 volatile AHCIPort *p = ahci->port[port];
302 SGArray sga;
303 SATAFIS_REG_H2D fis;
304 ATAIdentifyDevice ident;
305
306 kprintf("AHCI: Signature %08x\n", p->sig);
307
308 memset(&fis, 0, sizeof(fis));
309 fis.type = SATAFIS_TYPE_REG_H2D;
310 fis.flag = SATAFIS_REG_H2D_FLAG_COMMAND;
311 fis.command = SATAFIS_CMD_IDENTIFY;
312
313 sga.len = 1;
314 // VA2PA
315 sga.entries[0].offset = (uintptr_t)&ident;
316 sga.entries[0].length = 512;
317
318 AHCI_IssueCommand(ahci, port, &sga, &fis, sizeof(fis));
319 kprintf("AHCI: Identify Issued Port %d\n", port);
320 AHCI_WaitPort(ahci, port);
321
322 kprintf("AHCI: Identify Succeeded Port %d\n", port);
323 Debug_PrintHex((const char *)&ident, 512, 0, 512);
324 AHCI_DumpPort(ahci, port);
325 uint64_t val = (uint64_t)&ident;
326 Debug_PrintHex((const char *)&val, 8, 0, 8);
327
328 return;
329 }
330
331 void
AHCI_ResetPort(AHCI * ahci,int port)332 AHCI_ResetPort(AHCI *ahci, int port)
333 {
334 volatile AHCIPort *p = ahci->port[port];
335 uint32_t cmd = p->cmd;
336 uint32_t cmd_mask = AHCIPORT_CMD_ST | AHCIPORT_CMD_CR |
337 AHCIPORT_CMD_FRE | AHCIPORT_CMD_FR;
338
339 // Wait for controller to be idle
340 if ((cmd & cmd_mask) != 0) {
341 int tries;
342 for (tries = 0; tries < 2; tries++) {
343 cmd = cmd & ~(AHCIPORT_CMD_ST | AHCIPORT_CMD_FRE);
344 p->cmd = cmd;
345 // sleep 500ms
346 cmd = p->cmd;
347 if ((cmd & cmd_mask) != 0) {
348 kprintf("AHCI: failed to reset port %d\n", port);
349 }
350 }
351 }
352
353 // Reset interrupts
354 p->is = 0xFFFFFFFF;
355 p->is = 0x00000000;
356
357 // Reset error
358 p->serr = 0xFFFFFFFF;
359 p->serr = 0x00000000;
360
361 p->cmd |= AHCIPORT_CMD_FRE | AHCIPORT_CMD_ST | AHCIPORT_CMD_SUD |
362 AHCIPORT_CMD_POD | AHCIPORT_CMD_ICCACTIVE;
363
364 // Check port
365 uint32_t ssts = p->ssts;
366 if ((ssts & AHCIPORT_SSTS_DETMASK) == AHCIPORT_SSTS_DETNP) {
367 kprintf("AHCI: Device not present on port %d\n", port);
368 return;
369 }
370 if ((ssts & AHCIPORT_SSTS_DETMASK) == AHCIPORT_SSTS_DETNOTEST) {
371 kprintf("AHCI: Phys communication not established on port %d\n", port);
372 return;
373 }
374 if ((ssts & AHCIPORT_SSTS_DETNE) == AHCIPORT_SSTS_DETNOTEST) {
375 kprintf("AHCI: Port %d not enabled\n", port);
376 return;
377 }
378
379 AHCI_IdentifyPort(ahci, port);
380 }
381
382 void
AHCI_Reset(AHCI * ahci)383 AHCI_Reset(AHCI *ahci)
384 {
385 int port;
386 volatile AHCIHostControl *hc = ahci->hc;
387
388 AHCI_Dump(ahci);
389
390 // Reset controller
391 //uint32_t caps = hc->cap;
392 //uint32_t pi = hc->pi;
393
394 hc->ghc |= AHCI_GHC_AE;
395 hc->ghc |= AHCI_GHC_HR;
396 while (1) {
397 if ((hc->ghc & AHCI_GHC_HR) == 0)
398 break;
399 }
400 hc->ghc |= AHCI_GHC_AE;
401
402 AHCI_Dump(ahci);
403
404 // Reset ports
405 for (port = 0; port < AHCI_MAX_PORTS; port++)
406 {
407 if (ahci->port[port] != 0) {
408 AHCI_ResetPort(ahci, port);
409 }
410 }
411
412 // XXX: Clear interrupts
413
414 // Enable Interrupts
415 hc->ghc = AHCI_GHC_IE;
416 }
417
418 void
AHCI_Configure(PCIDevice dev)419 AHCI_Configure(PCIDevice dev)
420 {
421 AHCI *ahci = (AHCI *)PAlloc_AllocPage();
422 volatile AHCIHostControl *hc;
423
424 PCI_Configure(&dev);
425
426 kprintf("AHCI: IRQ %d\n", dev.irq);
427
428 // MMIO
429 int bar;
430 for (bar = 0; bar < PCI_MAX_BARS; bar++) {
431 if (dev.bars[bar].size == 0)
432 continue;
433
434 kprintf("AHCI: BAR%d base=%08x size=%08x %s\n",
435 bar, dev.bars[bar].base, dev.bars[bar].size,
436 dev.bars[bar].type == PCIBAR_TYPE_IO ? "IO" : "Mem");
437 }
438
439 // Copy PCIDevice structure
440 memcpy(&ahci->dev, &dev, sizeof(dev));
441
442 // XXX: Register IRQ
443
444 // Setup
445 hc = (volatile AHCIHostControl *)(uintptr_t)dev.bars[AHCI_ABAR].base;
446 ahci->hc = (AHCIHostControl *)hc;
447
448 uint32_t caps = hc->cap;
449 uint32_t ports = hc->pi;
450 uint32_t vers = hc->vs;
451
452 kprintf("AHCI: Version %d.%d, Ports: 0x%08x\n",
453 vers >> 16, vers & 0xFFFF, ports);
454 if (ports > ((1 << AHCI_MAX_PORTS) - 1))
455 {
456 kprintf("AHCI: Currently only supports %d ports\n", AHCI_MAX_PORTS);
457 }
458
459 if (caps & AHCI_CAP_S64A) {
460 kprintf("AHCI: Supports 64-bit Addressing\n");
461 } else {
462 kprintf("AHCI: Controller does not support 64-bit addressing!\n");
463 return;
464 }
465
466 if (caps & AHCI_CAP_SNCQ)
467 kprintf("AHCI: Supports NCQ\n");
468
469 // Disable Interrupts
470 hc->ghc &= ~AHCI_GHC_IE;
471
472 // Enable AHCI Controller
473 hc->ghc |= AHCI_GHC_AE;
474
475 int p;
476 for (p = 0; p < AHCI_MAX_PORTS; p++)
477 {
478 if (ports & (1 << p))
479 {
480 ahci->port[p] = (AHCIPort *)(uintptr_t)(dev.bars[AHCI_ABAR].base +
481 AHCI_PORT_OFFSET + AHCI_PORT_LENGTH * p);
482 } else {
483 ahci->port[p] = 0;
484 }
485 }
486
487 // Allocate memory and setup pointers
488 for (p = 0; p < AHCI_MAX_PORTS; p++)
489 {
490 volatile AHCIPort *port = ahci->port[p];
491 if (port != 0) {
492 int c;
493 for (c = 0; c < AHCI_MAX_CMDS; c++)
494 {
495 ahci->ctbl[p][c] = (AHCICommandTable *)PAlloc_AllocPage();
496 memset(ahci->ctbl[p][c], 0, sizeof(AHCICommandTable));
497 // XXX: VA2PA
498 ahci->clst[p]->cmds[c].ctba = (uint64_t)ahci->ctbl[p][c];
499 }
500
501 ahci->clst[p] = (AHCICommandList *)PAlloc_AllocPage();
502 memset(ahci->clst[p], 0, sizeof(AHCICommandList));
503 // XXX: VA2PA
504 port->clba = (uint64_t)ahci->clst[p];
505
506 ahci->rfis[p] = (AHCIRecvFIS *)PAlloc_AllocPage();
507 memset(ahci->rfis[p], 0, sizeof(AHCIRecvFIS));
508 // XXX: VA2PA
509 port->fb = (uint64_t)ahci->rfis[p];
510 }
511 }
512
513 // Reset controller and ports
514 AHCI_Reset(ahci);
515 }
516
517