Skip to content

Instantly share code, notes, and snippets.

@DanielO
Last active August 29, 2015 14:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DanielO/c42819ae69a1f680039a to your computer and use it in GitHub Desktop.
Save DanielO/c42819ae69a1f680039a to your computer and use it in GitHub Desktop.
#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