AHCI fixes and debugging improvements

This commit is contained in:
Ali Mashtizadeh 2014-07-03 17:36:31 -07:00
parent 568d7ee600
commit 696101f277
4 changed files with 133 additions and 10 deletions

View File

@ -18,5 +18,7 @@ typedef uint64_t uintptr_t;
typedef uint64_t size_t; typedef uint64_t size_t;
typedef int64_t ssize_t; typedef int64_t ssize_t;
typedef int64_t off_t;
#endif /* _STDINT_H_ */ #endif /* _STDINT_H_ */

View File

@ -23,6 +23,7 @@ src_amd64 = [
] ]
src_common = [ src_common = [
"kern/debug.c",
"kern/libc.c", "kern/libc.c",
"kern/palloc.c", "kern/palloc.c",
"kern/printf.c", "kern/printf.c",

View File

@ -9,6 +9,29 @@
* SATA Definitions * SATA Definitions
*/ */
typedef struct SATAIdentifyDevice
{
uint16_t _rsvd0[10]; // 0-9
uint8_t serial[20]; // 10-19 - Serial
uint16_t _rsvd1[3]; // 20-22
uint8_t firmware[8]; // 23-26 - Firmware
uint8_t model[40]; // 27-46 - Model
uint16_t _rsvd2[16]; // 47-62 X
uint16_t dmaMode; // 63 - DMA Mode
uint16_t _rsvd3[11]; // 64-74 X
uint16_t queueDepth; // 75 - Queue Depth
uint16_t sataCap; // 76 - SATA Capabilities
uint16_t ncqCap; // 77 - NCQ Capabilities
uint16_t _rsvd4[8]; // 78-85
uint16_t deviceFlags; // 86 - Device Flags (48-bit Addressing)
uint16_t deviceFlags2; // 87 - Device Flags 2 (SMART)
uint16_t udmaMode; // 88 - Ultra DMA Mode
uint16_t _rsvd5[11]; // 89-99
uint64_t lbaSectors; // 100-103 - User Addressable Logical Sectors
uint16_t _rsvd6[151]; // 104-254
uint16_t chksum; // 255 - Checksum
} SATAIdentifyDevice;
typedef struct SATAFIS_REG_H2D { typedef struct SATAFIS_REG_H2D {
uint8_t type; // 0x27 uint8_t type; // 0x27
uint8_t flag; uint8_t flag;
@ -128,7 +151,8 @@ typedef struct AHCIPort
typedef struct AHCICommandHeader typedef struct AHCICommandHeader
{ {
uint32_t descInfo; uint16_t flag;
uint16_t prdtl; // PRDT Length
uint32_t cmdStatus; uint32_t cmdStatus;
uint64_t ctba; uint64_t ctba;
uint64_t _rsvd[2]; uint64_t _rsvd[2];
@ -223,6 +247,7 @@ AHCI_Init(uint32_t bus, uint32_t slot, uint32_t func)
ASSERT(sizeof(AHCI) <= PGSIZE); ASSERT(sizeof(AHCI) <= PGSIZE);
ASSERT(sizeof(AHCICommandList) <= PGSIZE); ASSERT(sizeof(AHCICommandList) <= PGSIZE);
ASSERT(sizeof(AHCIRecvFIS) <= PGSIZE); ASSERT(sizeof(AHCIRecvFIS) <= PGSIZE);
ASSERT(sizeof(SATAIdentifyDevice) == 512);
int deviceIdx = 0; int deviceIdx = 0;
while (deviceList[deviceIdx].device != 0x0) { while (deviceList[deviceIdx].device != 0x0) {
@ -236,6 +261,26 @@ AHCI_Init(uint32_t bus, uint32_t slot, uint32_t func)
} }
} }
void
AHCI_DumpPort(AHCI *ahci, int port)
{
volatile AHCIPort *p = ahci->port[port];
kprintf("Port %d\n", port);
kprintf("CLBA: 0x%016llx\n", p->clba);
kprintf("FB: 0x%016llx\n", p->fb);
kprintf("IS: 0x%08x\n", p->is);
kprintf("IE: 0x%08x\n", p->ie);
kprintf("CMD: 0x%08x\n", p->cmd);
kprintf("TFD: 0x%08x\n", p->tfd);
kprintf("SIG: 0x%08x\n", p->sig);
kprintf("SSTS: 0x%08x\n", p->ssts);
kprintf("SCTL: 0x%08x\n", p->sctl);
kprintf("SERR: 0x%08x\n", p->serr);
kprintf("SACT: 0x%08x\n", p->sact);
kprintf("CI: 0x%08x\n", p->ci);
}
uint64_t uint64_t
AHCI_IssueCommand(AHCI *ahci, int port, SGArray *sga, void *cfis, int len) AHCI_IssueCommand(AHCI *ahci, int port, SGArray *sga, void *cfis, int len)
{ {
@ -245,7 +290,7 @@ AHCI_IssueCommand(AHCI *ahci, int port, SGArray *sga, void *cfis, int len)
volatile AHCIPort *p = ahci->port[port]; volatile AHCIPort *p = ahci->port[port];
// Copy Command FIS // Copy Command FIS
memcpy(&ct->cfis, cfis, len); memcpy((void *)&ct->cfis[0], cfis, len);
// Convert SGArray into PRDT // Convert SGArray into PRDT
int i; int i;
@ -259,7 +304,8 @@ AHCI_IssueCommand(AHCI *ahci, int port, SGArray *sga, void *cfis, int len)
// Specify cfis length and prdt entries; // Specify cfis length and prdt entries;
// XXX: support multiple commands // XXX: support multiple commands
cl->cmds[0].descInfo = (sga->len << 16) | (len / 4); cl->cmds[0].prdtl = sga->len;
cl->cmds[0].flag = len >> 2;
p->ci = 1; p->ci = 1;
} }
@ -269,7 +315,8 @@ AHCI_WaitPort(AHCI *ahci, int port)
{ {
volatile AHCIPort *p = ahci->port[port]; volatile AHCIPort *p = ahci->port[port];
while (1) { while (1) {
if (((p->tfd & AHCIPORT_TFD_BSY) == 0) && (p->ci != 0)) { uint32_t tfd = p->tfd & AHCIPORT_TFD_BSY;
if ((tfd == 0) && (p->ci == 0)) {
return; return;
} }
@ -283,7 +330,7 @@ AHCI_IdentifyPort(AHCI *ahci, int port)
volatile AHCIPort *p = ahci->port[port]; volatile AHCIPort *p = ahci->port[port];
SGArray sga; SGArray sga;
SATAFIS_REG_H2D fis; SATAFIS_REG_H2D fis;
uint8_t buf[512]; SATAIdentifyDevice ident;
kprintf("AHCI: Signature %08x\n", p->sig); kprintf("AHCI: Signature %08x\n", p->sig);
@ -291,12 +338,10 @@ AHCI_IdentifyPort(AHCI *ahci, int port)
fis.type = SATAFIS_TYPE_REG_H2D; fis.type = SATAFIS_TYPE_REG_H2D;
fis.flag = SATAFIS_REG_H2D_FLAG_COMMAND; fis.flag = SATAFIS_REG_H2D_FLAG_COMMAND;
fis.command = SATAFIS_CMD_IDENTIFY; fis.command = SATAFIS_CMD_IDENTIFY;
fis.count0 = 1;
fis.count1 = 0;
sga.len = 1; sga.len = 1;
// VA2PA // VA2PA
sga.entries[0].offset = &buf; sga.entries[0].offset = (uintptr_t)&ident;
sga.entries[0].length = 512; sga.entries[0].length = 512;
AHCI_IssueCommand(ahci, port, &sga, &fis, sizeof(fis)); AHCI_IssueCommand(ahci, port, &sga, &fis, sizeof(fis));
@ -304,6 +349,8 @@ AHCI_IdentifyPort(AHCI *ahci, int port)
AHCI_WaitPort(ahci, port); AHCI_WaitPort(ahci, port);
kprintf("AHCI: Identify Succeeded Port %d\n", port); kprintf("AHCI: Identify Succeeded Port %d\n", port);
Debug_PrintHex((const char *)&ident, 512, 0, 512);
AHCI_DumpPort(ahci, port);
return; return;
} }
@ -334,6 +381,9 @@ AHCI_ResetPort(AHCI *ahci, int port)
p->serr = 0xFFFFFFFF; p->serr = 0xFFFFFFFF;
p->serr = 0x00000000; p->serr = 0x00000000;
p->cmd |= AHCIPORT_CMD_FRE | AHCIPORT_CMD_ST | AHCIPORT_CMD_SUD |
AHCIPORT_CMD_POD | AHCIPORT_CMD_ICCACTIVE;
// Check port // Check port
uint32_t ssts = p->ssts; uint32_t ssts = p->ssts;
if ((ssts & AHCIPORT_SSTS_DETMASK) == AHCIPORT_SSTS_DETNP) { if ((ssts & AHCIPORT_SSTS_DETMASK) == AHCIPORT_SSTS_DETNP) {
@ -348,6 +398,8 @@ AHCI_ResetPort(AHCI *ahci, int port)
kprintf("AHCI: Port %d not enabled\n", port); kprintf("AHCI: Port %d not enabled\n", port);
return; return;
} }
AHCI_IdentifyPort(ahci, port);
} }
void void
@ -363,8 +415,6 @@ AHCI_Reset(AHCI *ahci)
{ {
if (ahci->port[port] != 0) { if (ahci->port[port] != 0) {
AHCI_ResetPort(ahci, port); AHCI_ResetPort(ahci, port);
// XXX: Skipme if nothing connected
AHCI_IdentifyPort(ahci, port);
} }
} }
} }

70
sys/kern/debug.c Normal file
View File

@ -0,0 +1,70 @@
/*
* Copyright (c) 2012-2014 Stanford University
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdbool.h>
#include <stdint.h>
void
Debug_PrintHex(const char *data, size_t length, off_t off, size_t limit)
{
const size_t row_size = 16;
bool stop = false;
size_t row;
for (row = 0; !stop; row++) {
size_t ix = row * row_size;
if (ix >= limit || ix >= length)
return;
kprintf("%08lx ", row * row_size);
size_t col;
for (col = 0; col < row_size; col++) {
size_t ix = row * row_size + col;
if ((limit != 0 && ix >= limit) || ix >= length) {
stop = true;
for (; col < row_size; col++) {
kprintf(" ");
}
break;
}
ix += off;
kprintf("%02X ", (unsigned char)data[ix]);
}
kprintf(" |");
for (col = 0; col < row_size; col++) {
size_t ix = row * row_size + col;
if ((limit != 0 && ix >= limit) || ix >= length) {
stop = true;
for (; col < row_size; col++) {
kprintf(" ");
}
break;
}
ix += off;
unsigned char c = (unsigned char)data[ix];
if (c >= 0x20 && c < 0x7F)
kprintf("%c", c);
else
kprintf(".");
}
kprintf("|");
kprintf("\n");
}
}