From: John Tsiombikas Date: Mon, 7 May 2018 13:15:08 +0000 (+0300) Subject: pci enumeration X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=bootcensus;a=commitdiff_plain;h=91253d061647c194cdc8c16c9ae85eccdf942139 pci enumeration --- diff --git a/src/keyb.c b/src/keyb.c index 9a34d8f..a63312e 100644 --- a/src/keyb.c +++ b/src/keyb.c @@ -15,6 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ +#include #include "keyb.h" #include "intr.h" #include "asmops.h" @@ -49,6 +50,10 @@ static unsigned char keystate[256]; void kb_init(void) { + buf_ridx = buf_widx = 0; + num_pressed = 0; + memset(keystate, 0, sizeof keystate); + interrupt(IRQ_TO_INTR(KB_IRQ), kbintr); } diff --git a/src/pci.c b/src/pci.c index b5ab9fd..c5cd65e 100644 --- a/src/pci.c +++ b/src/pci.c @@ -34,13 +34,41 @@ along with this program. If not, see . /* signature returned in edx by the PCI BIOS present function: FOURCC "PCI " */ #define PCI_SIG 0x20494350 -static uint16_t cfg_read32_acc1(int bus, int dev, int func, int reg); -static uint16_t cfg_read32_acc2(int bus, int dev, int func, int reg); +#define TYPE_MULTIFUNC 0x80 -static uint16_t (*cfg_read32)(int, int, int, int); +struct config_data { + uint16_t vendor, device; + uint16_t cmd, status; + uint8_t rev, iface, subclass, class; + uint8_t cacheline_size; + uint8_t latency_timer; + uint8_t hdr_type; + uint8_t bist; + uint32_t base_addr[6]; + uint32_t cardbus_cis; + uint16_t subsys_vendor; + uint16_t subsys; + uint32_t rom_addr; + uint32_t reserved1, reserved2; + uint8_t intr_line, intr_pin; + uint8_t min_grant, max_latency; +} __attribute__((packed)); + +static int enum_bus(int busid); +static int enum_dev(int busid, int dev); +static int read_dev_info(struct config_data *res, int bus, int dev, int func); +static void print_dev_info(struct config_data *info, int bus, int dev, int func); + +static uint32_t cfg_read32_m1(int bus, int dev, int func, int reg); +static uint32_t cfg_read32_m2(int bus, int dev, int func, int reg); +static const char *class_str(int cc); +static const char *subclass_str(int cc, int sub); + +static uint32_t (*cfg_read32)(int, int, int, int); void init_pci(void) { + int i, count = 0; struct int86regs regs; memset(®s, 0, sizeof regs); @@ -55,18 +83,87 @@ void init_pci(void) printf("PCI BIOS v%x.%x found\n", (regs.ebx & 0xff00) >> 8, regs.ebx & 0xff); if(regs.eax & 1) { - cfg_read32 = cfg_read32_acc1; + cfg_read32 = cfg_read32_m1; } else { if(!(regs.eax & 2)) { - printf("Failed to find supported PCI access mechanism\n"); + printf("Failed to find supported PCI mess mechanism\n"); return; } - printf("PCI access mechanism #1 unsupported, falling back to mechanism #2\n"); - cfg_read32 = cfg_read32_acc2; + printf("PCI mess mechanism #1 unsupported, falling back to mechanism #2\n"); + cfg_read32 = cfg_read32_m2; + } + + for(i=0; i<256; i++) { + count += enum_bus(i); + } + printf("found %d PCI devices\n", count); +} + +static int enum_bus(int busid) +{ + int i, count = 0; + + for(i=0; i<32; i++) { + count += enum_dev(busid, i); + } + + return count; +} + +static int enum_dev(int busid, int dev) +{ + int i, count; + struct config_data info; + + /* vendor id ffff is invalid */ + if((cfg_read32(busid, dev, 0, 0) & 0xffff) == 0xffff) { + return 0; + } + if(read_dev_info(&info, busid, dev, 0) == -1) { + return 0; + } + print_dev_info(&info, busid, dev, 0); + + count = 1; + + if(info.hdr_type & TYPE_MULTIFUNC) { + for(i=1; i<8; i++) { + if(read_dev_info(&info, busid, dev, i) == -1) { + continue; + } + print_dev_info(&info, busid, dev, i); + count++; + } + } + return count; +} + +static int read_dev_info(struct config_data *res, int bus, int dev, int func) +{ + int i; + uint32_t *ptr = (uint32_t*)res; + + *ptr++ = cfg_read32(bus, dev, func, 0); + if(res->vendor == 0xffff) { + return -1; + } + + for(i=1; i<16; i++) { + *ptr++ = cfg_read32(bus, dev, func, i * 4); } + return 0; +} + +static void print_dev_info(struct config_data *info, int bus, int dev, int func) +{ + printf("- (%d:%d,%d) Device %04x:%04x: ", bus, dev, func, info->vendor, info->device); + printf("\"%s\" (%d) - %s-func\n", class_str(info->class), info->class, + info->hdr_type & TYPE_MULTIFUNC ? "multi" : "single"); + printf(" subclass: \"%s\" (%d), iface: %d\n", subclass_str(info->class, info->subclass), + info->subclass, info->iface); } -static uint16_t cfg_read32_acc1(int bus, int dev, int func, int reg) +static uint32_t cfg_read32_m1(int bus, int dev, int func, int reg) { uint32_t addr = ADDR_ENABLE | ADDR_BUSID(bus) | ADDR_DEVID(dev) | ADDR_FUNC(func) | reg; @@ -75,8 +172,214 @@ static uint16_t cfg_read32_acc1(int bus, int dev, int func, int reg) return inl(CONFIG_DATA_PORT); } -static uint16_t cfg_read32_acc2(int bus, int dev, int func, int reg) +static uint32_t cfg_read32_m2(int bus, int dev, int func, int reg) { - panic("BUG: PCI access mechanism #2 not implemented yet!"); + panic("BUG: PCI mess mechanism #2 not implemented yet!"); return 0; } + +static const char *class_names[] = { + "unknown", + "mass storage controller", + "network controller", + "display controller", + "multimedia device", + "memory controller", + "bridge device", + "simple communication controller", + "base system peripheral", + "input device", + "docking station", + "processor", + "serial bus controller", + "wireless controller", + "intelligent I/O controller", + "satellite communication controller", + "encryption/decryption controller", + "data acquisition & signal processing controller" +}; + +static const char *class_mass_names[] = { + "SCSI bus controller", + "IDE controller", + "floppy disk controller", + "IPI bus controller", + "RAID controller" +}; + +static const char *class_net_names[] = { + "ethernet controller", + "token ring controller", + "FDDI controller", + "ATM controller", + "ISDN controller" +}; + +static const char *class_disp_names[] = { + "VGA-compatible controller", + "XGA controller", + "3D controller" +}; + +static const char *class_mm_names[] = { + "video device", + "audio device", + "telephony device" +}; + +static const char *class_bridge_names[] = { + "host bridge", + "ISA bridge", + "EISA bridge", + "MCA bridge", + "PCI-to-PCI bridge", + "Subtractive decode PCI-to-PCI bridge", + "PCMCIA bridge", + "NuBus bridge", + "CardBus bridge", + "RACEway bridge" +}; + +static const char *class_comm_names[] = { + "serial controller", + "parallel/IEEE1284", + "multiport serial controller", + "modem" +}; + +static const char *class_base_names[] = { + "interrupt controller", + "DMA controller", + "timer", + "RTC", + "PCI hot-plug controller" +}; + +static const char *class_input_names[] = { + "keyboard controller", + "digitizer", + "mouse controller", + "scanner controller", + "gameport controller" +}; + +static const char *class_ser_names[] = { + "firewire", + "ACCESS.bus", + "SSA", + "USB", + "Fibre Channel", + "SMBus" +}; + +static const char *class_sat_names[] = { + "TV", + "audio", + "voice", + "data" +}; + + +static const char *class_str(int cc) +{ + if(cc == 0xff) { + return "other"; + } + if(cc >= 0x12) { + return "unknown"; + } + return class_names[cc]; +} + +static const char *subclass_str(int cc, int sub) +{ + if(sub == 0x80) return "other"; + + switch(cc) { + case 0: + if(sub == 1) return "VGA-compatible device"; + return "unknown"; + + case 1: + if(sub > 4) return "unknown"; + return class_mass_names[sub]; + + case 2: + if(sub > 4) return "unknown"; + return class_net_names[sub]; + + case 3: + if(sub > 2) return "unknown"; + return class_disp_names[sub]; + + case 4: + if(sub > 2) return "unknown"; + return class_mm_names[sub]; + + case 5: + if(sub == 0) return "RAM"; + if(sub == 1) return "flash"; + return "unknown"; + + case 6: + if(sub > 8) return "unknown"; + return class_bridge_names[sub]; + + case 7: + if(sub > 3) return "unknown"; + return class_comm_names[sub]; + + case 8: + if(sub > 4) return "unknown"; + return class_base_names[sub]; + + case 9: + if(sub > 4) return "unknown"; + return class_input_names[sub]; + + case 10: + if(sub == 0) return "generic docking station"; + return "unknown"; + + case 11: + switch(sub) { + case 0: return "386"; + case 1: return "486"; + case 2: return "pentium"; + case 0x10: return "alpha"; + case 0x20: return "powerpc"; + case 0x30: return "mips"; + case 0x40: return "co-processor"; + default: + break; + } + return "unknown"; + + case 12: + if(sub > 5) return "unknown"; + return class_ser_names[sub]; + + case 13: + if(sub == 0) return "irda controller"; + if(sub == 1) return "IR controller"; + if(sub == 0x10) return "RF controller"; + return "unknonw"; + + case 15: + if(sub > 4) return "unknown"; + return class_sat_names[sub]; + + case 16: + if(sub == 0) return "network & computing crypto"; + if(sub == 1) return "entertainment crypto"; + return "unknown"; + + case 17: + if(sub == 0) return "DPIO module"; + return "unknown"; + + default: + break; + } + return "unknown"; +}