os/pci/pci.c

119 lines
3.7 KiB
C
Raw Normal View History

2019-09-08 13:01:37 -05:00
#include "pci.h"
2020-08-30 09:45:27 -05:00
#include <cpu/ports.h>
2020-07-22 19:35:23 -05:00
#include <stdint.h>
2019-09-08 13:01:37 -05:00
#include <stdio.h>
2020-07-22 19:35:23 -05:00
#include <stdlib.h>
2019-09-08 13:01:37 -05:00
pci_dev_common_info** pci_devs;
2020-07-23 11:50:23 -05:00
static size_t max_devs;
size_t pci_num_devs;
2019-09-08 13:01:37 -05:00
2020-07-23 11:50:23 -05:00
static uint32_t read_config(int bus,int device,int func,int offset) {
2019-09-08 13:01:37 -05:00
uint32_t address;
uint32_t lbus=(uint32_t)bus;
uint32_t ldev=(uint32_t)device;
uint32_t lfunc=(uint32_t)func;
address=(uint32_t)((lbus << 16)|(ldev << 11)|(lfunc<<8)|(offset&0xfc)|((uint32_t)0x80000000));
port_long_out(PCI_CONFIG_ADDRESS,address);
uint32_t data=port_long_in(PCI_CONFIG_DATA);
return data;
}
2020-07-23 11:50:23 -05:00
static void write_config(int bus,int device,int func,int offset,uint32_t data) {
2019-09-08 13:01:37 -05:00
uint32_t address;
uint32_t lbus=(uint32_t)bus;
uint32_t ldev=(uint32_t)device;
uint32_t lfunc=(uint32_t)func;
address=(uint32_t)((lbus << 16)|(ldev << 11)|(lfunc<<8)|(offset&0xfc)|((uint32_t)0x80000000));
port_long_out(PCI_CONFIG_ADDRESS,address);
port_long_out(PCI_CONFIG_DATA,data);
}
2020-07-23 11:50:23 -05:00
pci_dev_common_info* pci_get_dev_info(int bus,int device,int func) {
2019-09-08 13:01:37 -05:00
uint32_t* info=malloc(sizeof(uint32_t)*5);
info[0]=read_config(bus,device,func,0);
info[1]=read_config(bus,device,func,4);
info[2]=read_config(bus,device,func,8);
info[3]=read_config(bus,device,func,0xC);
pci_dev_common_info* pci_info=(pci_dev_common_info*)info;
return pci_info;
}
2020-08-30 17:01:50 -05:00
void pci_set_dev_info(int bus,int device,int func, pci_dev_common_info* inf) {
2019-09-08 13:01:37 -05:00
uint32_t* info=(uint32_t*)inf;
2020-08-30 17:01:50 -05:00
write_config(bus,device,func,0,info[0]);
write_config(bus,device,func,4,info[1]);
write_config(bus,device,func,8,info[2]);
write_config(bus,device,func,0xC,info[3]);
2019-09-08 13:01:37 -05:00
}
2020-08-30 17:01:50 -05:00
static void checkFunction(int bus,int device,int func, pci_dev_common_info* info);
2019-09-08 13:01:37 -05:00
2020-07-23 11:50:23 -05:00
static void checkDevice(int bus, int device) {
2019-09-08 13:01:37 -05:00
pci_dev_common_info* info=pci_get_dev_info(bus,device,0);
if(info->vend_id==0xFFFF||info->class_code==0xFF) {
return;
}
2020-08-30 17:01:50 -05:00
checkFunction(bus, device, 0, info);
2019-09-08 13:01:37 -05:00
if((info->header_type&0x80)!=0) {
2020-07-23 11:50:23 -05:00
for(int function=1;function<8;function++) {
2019-09-08 13:01:37 -05:00
pci_dev_common_info* info=pci_get_dev_info(bus,device,function);
if(info->vend_id!=0xFFFF&&info->class_code!=0xFF) {
2020-08-30 17:01:50 -05:00
checkFunction(bus,device,function,info);
2019-09-08 13:01:37 -05:00
}
}
}
}
2020-08-30 17:01:50 -05:00
static void printBAR(uint32_t bar,int num) {
2019-09-08 13:01:37 -05:00
if (bar!=0) {
if (bar&0x1) {
printf("[INFO] IO BAR%d:%x\n",num,bar&0xFFFFFFFC);
} else {
printf("[INFO] MEM BAR%d:%x\n",num,bar&0xFFFFFFF0);
}
}
}
2020-08-30 17:01:50 -05:00
static void checkFunction(int bus,int device,int func,pci_dev_common_info* info) {
2019-09-08 13:01:37 -05:00
if (pci_num_devs==max_devs) {
max_devs+=32;
pci_devs=malloc(sizeof(pci_dev_common_info)*max_devs);
}
pci_devs[pci_num_devs]=info;
if ((info->header_type&0x7f)==0) {
pci_dev_type0* dev=realloc(info,sizeof(pci_dev_type0));
uint32_t* dev_word_array=(uint32_t*)dev;
2020-08-30 17:01:50 -05:00
for (int i=0;i<16;i++) {
dev_word_array[i]=read_config(bus,device,func,i*4);
2019-09-08 13:01:37 -05:00
}
pci_devs[pci_num_devs]=(pci_dev_common_info*)dev;
}
pci_num_devs++;
}
void pci_init() {
pci_devs=malloc(sizeof(pci_dev_common_info)*32);
max_devs=32;
pci_num_devs=0;
for(uint16_t bus=0;bus<1; bus++) {
for(uint8_t device=0;device<32; device++) {
checkDevice(bus, device);
}
}
for (int i=0;i<pci_num_devs;i++) {
pci_dev_common_info* info=pci_devs[i];
printf("[INFO] Found PCI device. Class code:%x, Subclass:%x Prog IF:%x\n",info->class_code,info->subclass,info->prog_if);
printf("[INFO] Vendor ID:%x, Device ID:%x\n",info->vend_id,info->dev_id);
if ((info->header_type&0x7f)==0) {
pci_dev_type0* dev=(pci_dev_type0*)info;
2020-08-30 17:01:50 -05:00
printBAR(dev->bar0,0);
printBAR(dev->bar1,1);
printBAR(dev->bar2,2);
printBAR(dev->bar3,3);
printBAR(dev->bar4,4);
printBAR(dev->bar5,5);
2019-09-08 13:01:37 -05:00
}
}
}