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