Add start of a PCI driver

This commit is contained in:
pjht 2019-09-08 13:01:37 -05:00
parent 0bd3fe70cb
commit 1b1c3026ba
11 changed files with 3725 additions and 3 deletions

View File

@ -30,7 +30,7 @@ debug: os.iso kernel/kernel.elf
@$(GDB)
#gdbgui -g i386-elf-gdb --project $(CWD)
os.iso: kernel/kernel.elf init vfs devfs initrd vga_drv
os.iso: kernel/kernel.elf init vfs devfs initrd vga_drv pci
@cp kernel/kernel.elf sysroot/boot
@cd initrd; tar -f ../sysroot/boot/initrd.tar -c *
@grub-mkrescue -o $@ sysroot >/dev/null 2>/dev/null
@ -50,6 +50,9 @@ devfs: crts libc
@cd $@ && make
@cp $@/$@ initrd/$@
pci: crts libc
@cd $@ && make
@cp $@/$@ initrd/$@
vga_drv: crts libc
@cd $@ && make
@ -58,6 +61,8 @@ vga_drv: crts libc
kernel/kernel.elf: $(OBJ) $(ASM_OBJ) $(S_ASM_OBJ) sysroot/usr/lib/libc.a
@$(CC) -z max-page-size=4096 -Xlinker -n -T kernel/cpu/$(PLAT)/linker.ld -o $@ $(CFLAGS) -nostdlib $^ -lgcc
libc: sysroot/usr/lib/libc.a
sysroot/usr/lib/libc.a: $(LIBC_OBJ)
@$(AR) rcs $@ $^
@ -65,7 +70,7 @@ sysroot/usr/lib/libc.a: $(LIBC_OBJ)
@$(CC) $(CFLAGS) -c $< -o $@
%.o: %.asm
@$(NASM) $< -o $@
$(NASM) $< -o $@
%.o: %.s
@$(AS) $< -o $@

View File

@ -105,7 +105,6 @@ int main() {
yieldToPID(3);
datapos=find_loc("vga_drv",initrd);
load_task(datapos,initrd);
free(initrd);
yieldToPID(4);
mount("","devfs","/dev/");
FILE* file;
@ -115,6 +114,10 @@ int main() {
do {
file=fopen("/dev/vga","w");
} while(file==NULL);
datapos=find_loc("pci",initrd);
load_task(datapos,initrd);
free(initrd);
yieldToPID(4);
fputs("FPUTS String\n",file);
char str[3]={0,0,0};
fgets(str,2,stdin);

0
initrd_drv/Makefile Normal file
View File

13
pci/Makefile Normal file
View File

@ -0,0 +1,13 @@
C_SOURCES = $(wildcard *.c)
OBJ = $(C_SOURCES:.c=.o )
CFLAGS = -Wall -g
CC = i386-myos-gcc
pci: $(OBJ) ../libc/*
@$(CC) -o $@ $(CFLAGS) $(OBJ)
%.o: %.c
@$(CC) $(CFLAGS) -c $< -o $@
clean:
@rm -rf *.o pci

3448
pci/dump Normal file

File diff suppressed because it is too large Load Diff

13
pci/main.c Normal file
View File

@ -0,0 +1,13 @@
#include <stdio.h>
#include "pci.h"
int main() {
FILE* file;
do {
file=fopen("/dev/vga","w");
} while(file==NULL);
do {
file=fopen("/dev/vga","w");
} while(file==NULL);
yield();
pci_init();
}

BIN
pci/pci Executable file

Binary file not shown.

121
pci/pci.c Normal file
View File

@ -0,0 +1,121 @@
#include <stdint.h>
#include "ports.h"
#include "pci.h"
#include <stdlib.h>
#include <stdio.h>
pci_dev_common_info** pci_devs;
static uint32_t max_devs;
uint32_t pci_num_devs;
static uint32_t read_config(uint8_t bus,uint8_t device,uint8_t func,uint8_t offset) {
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;
}
static void write_config(uint8_t bus,uint8_t device,uint8_t func,uint8_t offset,uint32_t data) {
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);
}
pci_dev_common_info* pci_get_dev_info(uint8_t bus,uint8_t device,uint8_t func) {
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;
pci_info->bus=bus;
pci_info->device=device;
pci_info->func=func;
return pci_info;
}
void pci_set_dev_info(pci_dev_common_info* inf) {
uint32_t* info=(uint32_t*)inf;
write_config(inf->bus,inf->device,inf->func,0,info[0]);
write_config(inf->bus,inf->device,inf->func,4,info[1]);
write_config(inf->bus,inf->device,inf->func,8,info[2]);
write_config(inf->bus,inf->device,inf->func,0xC,info[3]);
}
static void checkFunction(pci_dev_common_info* info);
static void checkDevice(uint8_t bus, uint8_t device) {
pci_dev_common_info* info=pci_get_dev_info(bus,device,0);
if(info->vend_id==0xFFFF||info->class_code==0xFF) {
return;
}
checkFunction(info);
if((info->header_type&0x80)!=0) {
for(uint8_t function=1;function<8;function++) {
pci_dev_common_info* info=pci_get_dev_info(bus,device,function);
if(info->vend_id!=0xFFFF&&info->class_code!=0xFF) {
checkFunction(info);
}
}
}
}
static void printBAR(pci_dev_common_info* info,uint32_t bar,int num) {
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);
}
}
}
static void checkFunction(pci_dev_common_info* info) {
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;
for (int i=5;i<17;i++) {
dev_word_array[i]=read_config(info->bus,info->device,info->func,i*4);
}
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;
printBAR(info,dev->bar0,0);
printBAR(info,dev->bar1,1);
printBAR(info,dev->bar2,2);
printBAR(info,dev->bar3,3);
printBAR(info,dev->bar4,4);
printBAR(info,dev->bar5,5);
}
}
}

76
pci/pci.h Normal file
View File

@ -0,0 +1,76 @@
#ifndef PCI_H
#define PCI_H
#include <stdint.h>
#define PCI_CONFIG_ADDRESS 0xCF8
#define PCI_CONFIG_DATA 0xCFC
typedef struct {
uint16_t vend_id;
uint16_t dev_id;
uint16_t command;
uint16_t status;
uint8_t rev_id;
uint8_t prog_if;
uint8_t subclass;
uint8_t class_code;
uint8_t cache_line_size;
uint8_t lat_timer;
uint8_t header_type;
uint8_t bist;
uint16_t bus;
uint8_t device;
uint8_t func;
} __attribute__((packed)) pci_dev_common_info;
typedef struct {
pci_dev_common_info common;
uint32_t bar0;
uint32_t bar1;
uint32_t bar2;
uint32_t bar3;
uint32_t bar4;
uint32_t bar5;
uint32_t cis_ptr;
uint16_t sub_vend_id;
uint16_t sub_id;
uint32_t exp_rom_addr;
uint16_t cap_ptr;
uint16_t reserved1;
uint32_t reserved2;
uint8_t int_line;
uint8_t int_pin;
uint8_t min_grnt;
uint8_t max_latency;
} __attribute__((packed)) pci_dev_type0;
typedef enum {
PCI_CLASS_UNCLASSIFIED=0x0,
PCI_CLASS_STORAGE=0x1,
PCI_CLASS_NETWORK=0x2,
PCI_CLASS_DISPLAY=0x3,
PCI_CLASS_MULTIMEDIA=0x4,
PCI_CLASS_MEMORY=0x5,
PCI_CLASS_BRIDGE=0x6,
PCI_CLASS_SIMPCOM=0x7,
PCI_CLASS_BASEPERIPH=0x8,
PCI_CLASS_INPDEV=0x9,
PCI_CLASS_DOCK=0xa,
PCI_CLASS_CPU=0xb,
PCI_CLASS_SERBUS=0xc,
PCI_CLASS_WIRELESS=0xd,
PCI_CLASS_INTELLIGENT=0xe,
PCI_CLASS_SATELLITE=0xf,
PCI_CLASS_ENCRYPTION=0x10,
PCI_CLASS_SIGPROCESS=0x11,
} pci_class;
extern pci_dev_common_info** pci_devs;
extern uint32_t pci_num_devs;
pci_dev_common_info* pci_get_dev_info(uint8_t bus,uint8_t device,uint8_t func);
void pci_set_dev_info(pci_dev_common_info* inf);
void pci_init();
#endif

31
pci/ports.c Normal file
View File

@ -0,0 +1,31 @@
#include <stdint.h>
uint8_t port_byte_in(uint16_t port) {
uint8_t result;
asm("in %%dx, %%al":"=a"(result):"d"(port));
return result;
}
void port_byte_out(uint16_t port,uint8_t data) {
asm("out %%al, %%dx":: "a"(data),"d"(port));
}
uint16_t port_word_in(uint16_t port) {
uint16_t result;
asm("in %%dx, %%ax":"=a"(result):"d"(port));
return result;
}
void port_word_out(uint16_t port,uint16_t data) {
asm("out %%ax, %%dx":: "a" (data), "d" (port));
}
uint32_t port_long_in(uint16_t port) {
uint32_t result;
asm("inl %%dx, %%eax":"=a"(result):"d"(port));
return result;
}
void port_long_out(uint16_t port,uint32_t data) {
asm("outl %%eax, %%dx":: "a" (data), "d" (port));
}

12
pci/ports.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef PORTS_H
#define PORTS_H
#include <stdint.h>
uint8_t port_byte_in(uint16_t port);
void port_byte_out(uint16_t port,uint8_t data);
uint16_t port_word_in(uint16_t port);
void port_word_out(uint16_t port,uint16_t data);
uint32_t port_long_in(uint16_t port);
void port_long_out(uint16_t port,uint32_t data);
#endif