From 696101f2773789737cf1b92ceb61d3e178a2f0f3 Mon Sep 17 00:00:00 2001 From: Ali Mashtizadeh Date: Thu, 3 Jul 2014 17:36:31 -0700 Subject: [PATCH] AHCI fixes and debugging improvements --- include/stdint.h | 2 ++ sys/SConscript | 1 + sys/dev/ahci.c | 70 +++++++++++++++++++++++++++++++++++++++++------- sys/kern/debug.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 133 insertions(+), 10 deletions(-) create mode 100644 sys/kern/debug.c diff --git a/include/stdint.h b/include/stdint.h index 824cf1b..012d8a2 100644 --- a/include/stdint.h +++ b/include/stdint.h @@ -18,5 +18,7 @@ typedef uint64_t uintptr_t; typedef uint64_t size_t; typedef int64_t ssize_t; +typedef int64_t off_t; + #endif /* _STDINT_H_ */ diff --git a/sys/SConscript b/sys/SConscript index 4b69600..3f71db2 100644 --- a/sys/SConscript +++ b/sys/SConscript @@ -23,6 +23,7 @@ src_amd64 = [ ] src_common = [ + "kern/debug.c", "kern/libc.c", "kern/palloc.c", "kern/printf.c", diff --git a/sys/dev/ahci.c b/sys/dev/ahci.c index 6207fa2..7e8b4a4 100644 --- a/sys/dev/ahci.c +++ b/sys/dev/ahci.c @@ -9,6 +9,29 @@ * 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 { uint8_t type; // 0x27 uint8_t flag; @@ -128,7 +151,8 @@ typedef struct AHCIPort typedef struct AHCICommandHeader { - uint32_t descInfo; + uint16_t flag; + uint16_t prdtl; // PRDT Length uint32_t cmdStatus; uint64_t ctba; 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(AHCICommandList) <= PGSIZE); ASSERT(sizeof(AHCIRecvFIS) <= PGSIZE); + ASSERT(sizeof(SATAIdentifyDevice) == 512); int deviceIdx = 0; 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 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]; // Copy Command FIS - memcpy(&ct->cfis, cfis, len); + memcpy((void *)&ct->cfis[0], cfis, len); // Convert SGArray into PRDT int i; @@ -259,7 +304,8 @@ AHCI_IssueCommand(AHCI *ahci, int port, SGArray *sga, void *cfis, int len) // Specify cfis length and prdt entries; // 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; } @@ -269,7 +315,8 @@ AHCI_WaitPort(AHCI *ahci, int port) { volatile AHCIPort *p = ahci->port[port]; 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; } @@ -283,7 +330,7 @@ AHCI_IdentifyPort(AHCI *ahci, int port) volatile AHCIPort *p = ahci->port[port]; SGArray sga; SATAFIS_REG_H2D fis; - uint8_t buf[512]; + SATAIdentifyDevice ident; kprintf("AHCI: Signature %08x\n", p->sig); @@ -291,12 +338,10 @@ AHCI_IdentifyPort(AHCI *ahci, int port) fis.type = SATAFIS_TYPE_REG_H2D; fis.flag = SATAFIS_REG_H2D_FLAG_COMMAND; fis.command = SATAFIS_CMD_IDENTIFY; - fis.count0 = 1; - fis.count1 = 0; sga.len = 1; // VA2PA - sga.entries[0].offset = &buf; + sga.entries[0].offset = (uintptr_t)&ident; sga.entries[0].length = 512; AHCI_IssueCommand(ahci, port, &sga, &fis, sizeof(fis)); @@ -304,6 +349,8 @@ AHCI_IdentifyPort(AHCI *ahci, int port) AHCI_WaitPort(ahci, port); kprintf("AHCI: Identify Succeeded Port %d\n", port); + Debug_PrintHex((const char *)&ident, 512, 0, 512); + AHCI_DumpPort(ahci, port); return; } @@ -334,6 +381,9 @@ AHCI_ResetPort(AHCI *ahci, int port) p->serr = 0xFFFFFFFF; p->serr = 0x00000000; + p->cmd |= AHCIPORT_CMD_FRE | AHCIPORT_CMD_ST | AHCIPORT_CMD_SUD | + AHCIPORT_CMD_POD | AHCIPORT_CMD_ICCACTIVE; + // Check port uint32_t ssts = p->ssts; 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); return; } + + AHCI_IdentifyPort(ahci, port); } void @@ -363,8 +415,6 @@ AHCI_Reset(AHCI *ahci) { if (ahci->port[port] != 0) { AHCI_ResetPort(ahci, port); - // XXX: Skipme if nothing connected - AHCI_IdentifyPort(ahci, port); } } } diff --git a/sys/kern/debug.c b/sys/kern/debug.c new file mode 100644 index 0000000..56edc9d --- /dev/null +++ b/sys/kern/debug.c @@ -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 +#include + +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"); + } +} +