Last active
August 29, 2015 14:07
-
-
Save DanielO/c42819ae69a1f680039a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <errno.h> | |
#include <fcntl.h> | |
#include <limits.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <sys/types.h> | |
#include <unistd.h> | |
/* | |
* Print extended capabilities for an xHCI controller | |
* Pass the base address as the first parameter, eg.. | |
* root@foo:~ # dmesg | egrep 'xhci.* mem ' | |
* xhci0: <XHCI (generic) USB 3.0 controller> mem 0xfd4c0000-0xfd4dffff irq 18 at device 0.0 on pci3 | |
* | |
* root@foo:~ # ./xhcicap 0xfd4c0000 | |
* HCCPARAMS1 => 0x0388f283 | |
* xECP (0xfd4c0e20) => ID 2 (Supported protocol) Specific 0x0300 | |
* xECP (0xfd4c0e23) => ID 3 (Extended PM) Specific 0x4253 | |
*/ | |
#define HCCPARAMS1 0x10 | |
struct { | |
uint8_t capid; | |
char *desc; | |
} caplist[] = { | |
{ 1, "Legacy support" }, | |
{ 2, "Supported protocol" }, | |
{ 3, "Extended PM" }, | |
{ 4, "IO Virtualization" }, | |
{ 5, "Message interrupt" }, | |
{ 6, "Local memory" }, | |
{ 10, "Debug" }, | |
{ 17, "Extended message interrupt" }, | |
{ 0, NULL }, | |
}; | |
char * | |
getcapname(uint8_t id) { | |
static char tmp[16]; | |
for (int i = 0; caplist[i].desc != NULL; i++) { | |
if (id == caplist[i].capid) | |
return(caplist[i].desc); | |
} | |
snprintf(tmp, sizeof(tmp) - 1, "Reserved (%d)", id); | |
return(tmp); | |
} | |
uint32_t | |
read32(int memfd, uint32_t addr) { | |
uint32_t data; | |
if (pread(memfd, &data, sizeof(data), addr) == -1) { | |
printf("Unable to read from 0x%08x\n", addr); | |
exit(1); | |
} | |
return(data); | |
} | |
int | |
main(int argc, char **argv) { | |
int memfd; | |
uint32_t addr, hccparams1, capptr, tmp, ofs; | |
char *end; | |
if (argc != 2) { | |
printf("Bad usage\n"); | |
exit(1); | |
} | |
if ((memfd = open("/dev/mem", O_RDONLY)) == -1) { | |
printf("Can't open /dev/mem: %s\n", strerror(errno)); | |
exit(1); | |
} | |
addr = strtoll(argv[1], &end, 0); | |
if (end == argv[1]) { | |
printf("Unable to parse '%s'\n", argv[1]); | |
exit(1); | |
} | |
hccparams1 = read32(memfd, addr + HCCPARAMS1); | |
printf("HCCPARAMS1 => 0x%08x\n", hccparams1); | |
capptr = (hccparams1 >> 16) * 4; | |
while (1) { | |
uint8_t capid; | |
uint16_t capspec; | |
tmp = read32(memfd, addr + capptr); | |
capid = tmp & 0xff; | |
ofs = (tmp & 0xff00) >> 8; | |
capspec = tmp >> 16; | |
if (ofs == 0) | |
break; | |
printf("xECP (0x%08x) => ID %d (%s) Specific 0x%04x\n", addr + capptr, | |
capid, getcapname(capid), capspec); | |
capptr += ofs; | |
} | |
close(memfd); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment