AHCI fixes and debugging improvements
This commit is contained in:
parent
568d7ee600
commit
696101f277
@ -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_ */
|
||||||
|
|
||||||
|
@ -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",
|
||||||
|
@ -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
70
sys/kern/debug.c
Normal 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user