add /proc/pci, lspci
This commit is contained in:
parent
d5f6170991
commit
5a6cc6868a
131
apps/lspci.c
Normal file
131
apps/lspci.c
Normal file
@ -0,0 +1,131 @@
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* This file is part of ToaruOS and is released under the terms
|
||||
* of the NCSA / University of Illinois License - see LICENSE.md
|
||||
* Copyright (C) 2018 K. Lange
|
||||
*
|
||||
* lspci - Print information about connected PCI devices.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
struct device_class {
|
||||
char * code;
|
||||
char * name;
|
||||
} device_classes[] = {
|
||||
{"0101", "IDE interface"},
|
||||
{"0102", "Floppy disk controller"},
|
||||
{"0105", "ATA controller"},
|
||||
{"0106", "SATA controller"},
|
||||
{"0200", "Ethernet controller"},
|
||||
{"0280", "Network controller"},
|
||||
{"0300", "VGA compatible controller"},
|
||||
{"0380", "Display controller"},
|
||||
{"0401", "Multimedia audio controller"},
|
||||
{"0403", "Audio device"},
|
||||
{"0480", "Multimedia controller"},
|
||||
{"0600", "Host bridge"},
|
||||
{"0601", "ISA bridge"},
|
||||
{"0680", "Bridge"},
|
||||
{"0880", "System peripheral"},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
static void show_usage(char * argv[]) {
|
||||
fprintf(stderr,
|
||||
"lspci - show information about PCI devices\n"
|
||||
"\n"
|
||||
"usage: %s [-n]\n"
|
||||
"\n"
|
||||
" -n \033[3mshow numeric device codes\033[0m\n"
|
||||
" -? \033[3mshow this help text\033[0m\n"
|
||||
"\n", argv[0]);
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
int numeric = 0;
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "n?")) != -1) {
|
||||
switch (opt) {
|
||||
case '?':
|
||||
show_usage(argv);
|
||||
return 0;
|
||||
case 'n':
|
||||
numeric = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FILE * f = fopen("/proc/pci","r");
|
||||
if (!f) {
|
||||
fprintf(stderr, "%s: %s: %s\n", argv[0], "/proc/pci", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (!feof(f)) {
|
||||
char line[1024];
|
||||
fgets(line, 1024, f);
|
||||
if (line[0] == ' ') {
|
||||
/* Skip; don't care about this information */
|
||||
continue;
|
||||
}
|
||||
/* Read bus, etc. verbatim */
|
||||
char * device_bus = line;
|
||||
|
||||
/* Read device class */
|
||||
char * device_class = strstr(line," (");
|
||||
if (!device_class) {
|
||||
fprintf(stderr, "%s: parse error\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
*device_class = '\0';
|
||||
device_class++; /* space */
|
||||
device_class++; /* ( */
|
||||
|
||||
char * device_vendor = strstr(device_class, ", ");
|
||||
if (!device_vendor) {
|
||||
fprintf(stderr, "%s: parse error\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
*device_vendor = '\0';
|
||||
device_vendor++; /* comma */
|
||||
device_vendor++; /* space */
|
||||
|
||||
char * device_code = strstr(device_vendor, ":");
|
||||
if (!device_code) {
|
||||
fprintf(stderr, "%s: parse error\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
*device_code = '\0';
|
||||
device_code++; /* colon */
|
||||
|
||||
char * device_name = strstr(device_code, ") ");
|
||||
if (!device_name) {
|
||||
fprintf(stderr, "%s: parse error\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
*device_name = '\0';
|
||||
device_name++; /* ) */
|
||||
device_name++; /* space */
|
||||
|
||||
char * linefeed = strstr(device_name, "\n");
|
||||
if (linefeed) *linefeed = '\0';
|
||||
|
||||
if (numeric) {
|
||||
fprintf(stdout, "%s %s: %s:%s\n", device_bus, device_class, device_vendor, device_code);
|
||||
} else {
|
||||
for (struct device_class * c = device_classes; c->code; ++c) {
|
||||
if (!strcmp(device_class, c->code)) {
|
||||
device_class = c->name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* TODO: We should also look up vendor + device names ourselves and possibly remove them from the kernel */
|
||||
fprintf(stdout, "%s %s: %s\n", device_bus, device_class, device_name);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -12,6 +12,7 @@
|
||||
#include <kernel/module.h>
|
||||
#include <kernel/mod/net.h>
|
||||
#include <kernel/multiboot.h>
|
||||
#include <kernel/pci.h>
|
||||
|
||||
#define PROCFS_STANDARD_ENTRIES (sizeof(std_entries) / sizeof(struct procfs_entry))
|
||||
#define PROCFS_PROCDIR_ENTRIES (sizeof(procdir_entries) / sizeof(struct procfs_entry))
|
||||
@ -620,6 +621,67 @@ static uint32_t irq_func(fs_node_t *node, uint32_t offset, uint32_t size, uint8_
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Basically the same as the kdebug `pci` command.
|
||||
*/
|
||||
struct _pci_buf {
|
||||
size_t offset;
|
||||
char *buffer;
|
||||
};
|
||||
|
||||
static void scan_hit_list(uint32_t device, uint16_t vendorid, uint16_t deviceid, void * extra) {
|
||||
|
||||
struct _pci_buf * b = extra;
|
||||
|
||||
b->offset += sprintf(b->buffer + b->offset, "%2x:%2x.%d (%4x, %4x:%4x) %s %s\n",
|
||||
(int)pci_extract_bus(device),
|
||||
(int)pci_extract_slot(device),
|
||||
(int)pci_extract_func(device),
|
||||
(int)pci_find_type(device),
|
||||
vendorid,
|
||||
deviceid,
|
||||
pci_vendor_lookup(vendorid),
|
||||
pci_device_lookup(vendorid,deviceid));
|
||||
|
||||
b->offset += sprintf(b->buffer + b->offset, " BAR0: 0x%8x", pci_read_field(device, PCI_BAR0, 4));
|
||||
b->offset += sprintf(b->buffer + b->offset, " BAR1: 0x%8x", pci_read_field(device, PCI_BAR1, 4));
|
||||
b->offset += sprintf(b->buffer + b->offset, " BAR2: 0x%8x", pci_read_field(device, PCI_BAR2, 4));
|
||||
b->offset += sprintf(b->buffer + b->offset, " BAR3: 0x%8x", pci_read_field(device, PCI_BAR3, 4));
|
||||
b->offset += sprintf(b->buffer + b->offset, " BAR4: 0x%8x", pci_read_field(device, PCI_BAR4, 4));
|
||||
b->offset += sprintf(b->buffer + b->offset, " BAR6: 0x%8x\n", pci_read_field(device, PCI_BAR5, 4));
|
||||
|
||||
b->offset += sprintf(b->buffer + b->offset, " IRQ Line: %d", pci_read_field(device, 0x3C, 1));
|
||||
b->offset += sprintf(b->buffer + b->offset, " IRQ Pin: %d", pci_read_field(device, 0x3D, 1));
|
||||
b->offset += sprintf(b->buffer + b->offset, " Interrupt: %d", pci_get_interrupt(device));
|
||||
b->offset += sprintf(b->buffer + b->offset, " Status: 0x%4x\n", pci_read_field(device, PCI_STATUS, 2));
|
||||
}
|
||||
|
||||
static void scan_count(uint32_t device, uint16_t vendorid, uint16_t deviceid, void * extra) {
|
||||
size_t * count = extra;
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
static uint32_t pci_func(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
|
||||
size_t count = 0;
|
||||
pci_scan(&scan_count, -1, &count);
|
||||
|
||||
struct _pci_buf b = {0,NULL};
|
||||
b.buffer = malloc(count * 512);
|
||||
|
||||
pci_scan(&scan_hit_list, -1, &b);
|
||||
|
||||
size_t _bsize = b.offset;
|
||||
if (offset > _bsize) {
|
||||
free(b.buffer);
|
||||
return 0;
|
||||
}
|
||||
if (size > _bsize - offset) size = _bsize - offset;
|
||||
|
||||
memcpy(buffer, b.buffer, size);
|
||||
free(b.buffer);
|
||||
return size;
|
||||
}
|
||||
|
||||
static struct procfs_entry std_entries[] = {
|
||||
{-1, "cpuinfo", cpuinfo_func},
|
||||
{-2, "meminfo", meminfo_func},
|
||||
@ -634,6 +696,7 @@ static struct procfs_entry std_entries[] = {
|
||||
{-11,"loader", loader_func},
|
||||
{-12,"irq", irq_func},
|
||||
{-13,"pat", pat_func},
|
||||
{-14,"pci", pci_func},
|
||||
};
|
||||
|
||||
static struct dirent * readdir_procfs_root(fs_node_t *node, uint32_t index) {
|
||||
|
Loading…
Reference in New Issue
Block a user